diff --git a/MAKE.bat b/MAKE.bat index 590762f..8fa272b 100644 --- a/MAKE.bat +++ b/MAKE.bat @@ -410,6 +410,51 @@ if "%1"=="back" ( exit /b ) +if "%1"=="fwk_mir" ( + rd/q/s _fwk + rd/q/s ..\_fwk + mkdir ..\_fwk + setlocal enabledelayedexpansion + xcopy /y/E "*" "..\_fwk" + move "..\_fwk" _fwk + for %%f in ("engine\split\v4k*") do ( + set "filename=%%~nf" + set "newname=fwk!filename:v4k=!%%~xf" + echo Copying and renaming "%%f" to "_fwk\engine\split\!newname!" + copy "%%f" "_fwk\engine\split\!newname!" + ) + for %%f in (_fwk\engine\split\*) do ( + set "filename=%%~nxf" + if /i not "!filename:~0,4!"=="3rd_" ( + echo Processing: %%f + tools\fwkren.exe %%f from + ) else ( + echo Skipping %%f + ) + ) + for %%f in (_fwk\demos\*.c) do ( + set "filename=%%~nxf" + echo Processing: %%f + tools\fwkren.exe %%f from + ) + for %%f in (_fwk\tools\*) do ( + set "filename=%%~nxf" + echo Processing: %%f + tools\fwkren.exe %%f from + ) + for %%f in (_fwk\tools\editor\*.c) do ( + set "filename=%%~nxf" + echo Processing: %%f + tools\fwkren.exe %%f from + ) + + tools\fwkren.exe _fwk\tools\cook.ini from + + echo All done. + endlocal + exit /b +) + rem copy demos to root folder. local changes are preserved rem echo n | copy /-y demos\*.c 1> nul 2> nul @@ -757,10 +802,10 @@ if "!v4k!"=="yes" ( rem editor if "!editor!"=="yes" ( -set edit=-DCOOK_ON_DEMAND -DUI_LESSER_SPACING -DUI_ICONS_SMALL -if "!vis!"=="yes" echo !cc! !o! editor.exe tools\editor\editor.c !edit! !import! !args! -!echo! editor && !cc! !o! editor.exe tools\editor\editor.c !edit! !import! !args! || set rc=1 +set edit=-DCOOK_ON_DEMAND !echo! editor3 && !cc! !o! editor3.exe tools\editor\editor3.c !edit! -Iengine/joint !args! || set rc=1 +set edit=-DUI_LESSER_SPACING -DUI_ICONS_SMALL !edit! +!echo! editor && !cc! !o! editor.exe tools\editor\editor.c !edit! !import! !args! || set rc=1 rem if "!cc!"=="cl" ( rem set plug_export=/LD diff --git a/bind/v4k.lua b/bind/v4k.lua index a3a29d1..c4184ed 100644 --- a/bind/v4k.lua +++ b/bind/v4k.lua @@ -1130,6 +1130,7 @@ ffi.cdef([[ //lcpp INF [0000] vec3: macro name but used as C declaration in: int gizmo(vec3 *pos, vec3 *rot, vec3 *sca); //lcpp INF [0000] vec3: macro name but used as C declaration in: int gizmo(vec3 *pos, vec3 *rot, vec3 *sca); //lcpp INF [0000] vec3: macro name but used as C declaration in: int gizmo(vec3 *pos, vec3 *rot, vec3 *sca); +//lcpp INF [0000] map: macro name but used as C declaration in:typedef struct { map base; struct { pair p; char* key; char* val; } tmp, *ptr; char** tmpval; int (*typed_cmp)(char*, char*); uint64_t (*typed_hash)(char*); } * ini_t; //lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 font_xy(); //lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 font_xy(); //lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 font_xy(); @@ -1142,7 +1143,6 @@ ffi.cdef([[ //lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 font_highlight(const char *text, const void *colors); //lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 font_highlight(const char *text, const void *colors); //lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 font_highlight(const char *text, const void *colors); -//lcpp INF [0000] map: macro name but used as C declaration in:typedef struct { map base; struct { pair p; char* key; char* val; } tmp, *ptr; char** tmpval; int (*typed_cmp)(char*, char*); uint64_t (*typed_hash)(char*); } * ini_t; //lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 input2( int vk ); //lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 input2( int vk ); //lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 input2( int vk ); @@ -1508,6 +1508,9 @@ ffi.cdef([[ //lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC void light_dir(light_t* l, vec3 dir); //lcpp INF [0000] vec3: macro name but used as C declaration in: void light_dir(light_t* l, vec3 dir); //lcpp INF [0000] vec2i: macro name but used as C declaration in:vec2i* entries; +//lcpp INF [0000] test: macro name but used as C declaration in:API int (test)(const char *file, int line, const char *expr, bool result); +//lcpp INF [0000] test: macro name but used as C declaration in:STATIC int (test)(const char *file, int line, const char *expr, bool result); +//lcpp INF [0000] test: macro name but used as C declaration in: int (test)(const char *file, int line, const char *expr, bool result); //lcpp INF [0000] vec3i: macro name but used as C declaration in:typedef vec3i guid; //lcpp INF [0000] vec3: macro name but used as C declaration in:vec3 v; //lcpp INF [0000] vec3: macro name but used as C declaration in:vec3 result; @@ -1522,9 +1525,6 @@ ffi.cdef([[ //lcpp INF [0000] vec3: macro name but used as C declaration in:API vec3 curve_eval(curve_t *c, float dt, unsigned *color); //lcpp INF [0000] vec3: macro name but used as C declaration in:STATIC vec3 curve_eval(curve_t *c, float dt, unsigned *color); //lcpp INF [0000] vec3: macro name but used as C declaration in: vec3 curve_eval(curve_t *c, float dt, unsigned *color); -//lcpp INF [0000] test: macro name but used as C declaration in:API int (test)(const char *file, int line, const char *expr, bool result); -//lcpp INF [0000] test: macro name but used as C declaration in:STATIC int (test)(const char *file, int line, const char *expr, bool result); -//lcpp INF [0000] test: macro name but used as C declaration in: int (test)(const char *file, int line, const char *expr, bool result); //lcpp INF [0000] vec2: macro name but used as C declaration in:API vec2 ui_get_dims(); //lcpp INF [0000] vec2: macro name but used as C declaration in:STATIC vec2 ui_get_dims(); //lcpp INF [0000] vec2: macro name but used as C declaration in: vec2 ui_get_dims(); @@ -2117,6 +2117,11 @@ typedef union json_t { char* s; double f; int64_t i; uintptr_t p; union json_t* void script_bind_function(const char *c_name, void *c_function); void script_call(const char *lua_function); bool script_tests(); +enum { +SCRIPT_LUA = 1, +SCRIPT_DEBUGGER = 2, +}; + void *script_init_env(unsigned flags); vec3 editor_pick(float mouse_x, float mouse_y); char* editor_path(const char *path); float* engine_getf(const char *key); @@ -2139,38 +2144,6 @@ typedef union json_t { char* s; double f; int64_t i; uintptr_t p; union json_t* char* kit_translate2( const char *id, const char *langcode_iso639_1 ); void kit_locale( const char *langcode_iso639_1 ); char* kit_translate( const char *id ); -enum FONT_FLAGS { -FONT_512 =0, -FONT_1024 =1, -FONT_2048 =2, -FONT_4096 =4, -FONT_NO_OVERSAMPLE =0, -FONT_OVERSAMPLE_X =8, -FONT_OVERSAMPLE_Y =16, -FONT_ASCII =2048, -FONT_AR =4096, -FONT_ZH =8192, -FONT_EL =16384, -FONT_EM =32768, -FONT_EU =65536, -FONT_HE =131072, -FONT_JP =262144, -FONT_KR =524288, -FONT_RU =1048576, -FONT_TH =2097152, -FONT_VI =4194304, -FONT_CJK = FONT_ZH|FONT_JP|FONT_KR, -}; - void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags); - void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags); - void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6); - void font_color(const char *color_tag, uint32_t color); - vec2 font_xy(); - void font_goto(float x, float y); - vec2 font_print(const char *text); - vec2 font_rect(const char *text); - void* font_colorize(const char *text, const char *comma_types, const char *comma_keywords); - vec2 font_highlight(const char *text, const void *colors); char** file_list( const char *pathmasks ); bool file_write( const char *file, const void *ptr, int len ); bool file_append( const char *file, const void *ptr, int len ); @@ -2218,6 +2191,38 @@ typedef struct { map base; struct { pair p; char* key; char* val; } tmp, *ptr; c ini_t ini_from_mem(const char *data); void ini_destroy(ini_t); bool ini_write(const char *filename, const char *section, const char *key, const char *value); +enum FONT_FLAGS { +FONT_512 =0, +FONT_1024 =1, +FONT_2048 =2, +FONT_4096 =4, +FONT_NO_OVERSAMPLE =0, +FONT_OVERSAMPLE_X =8, +FONT_OVERSAMPLE_Y =16, +FONT_ASCII =2048, +FONT_AR =4096, +FONT_ZH =8192, +FONT_EL =16384, +FONT_EM =32768, +FONT_EU =65536, +FONT_HE =131072, +FONT_JP =262144, +FONT_KR =524288, +FONT_RU =1048576, +FONT_TH =2097152, +FONT_VI =4194304, +FONT_CJK = FONT_ZH|FONT_JP|FONT_KR, +}; + void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags); + void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags); + void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6); + void font_color(const char *color_tag, uint32_t color); + vec2 font_xy(); + void font_goto(float x, float y); + vec2 font_print(const char *text); + vec2 font_rect(const char *text); + void* font_colorize(const char *text, const char *comma_types, const char *comma_keywords); + vec2 font_highlight(const char *text, const void *colors); int input_use( int controller_id ); float input( int vk ); vec2 input2( int vk ); @@ -2605,6 +2610,7 @@ TEXTURE_RGBA = IMAGE_RGBA, TEXTURE_FLIP = IMAGE_FLIP, TEXTURE_SRGB = 1 << 24, TEXTURE_BGR = 1 << 25, +TEXTURE_BGRA = TEXTURE_BGR, TEXTURE_ARRAY = 1 << 26, }; typedef struct texture_t { @@ -3128,6 +3134,51 @@ vec2i* entries; } quarks_db; unsigned quark_intern( quarks_db*, const char *string ); const char *quark_string( quarks_db*, unsigned key ); + void* thread( int (*thread_func)(void* user_data), void* user_data ); + void thread_destroy( void *thd ); + int argc(); + char* argv(int); + int flag(const char *commalist); + const char* option(const char *commalist, const char *defaults); + int optioni(const char *commalist, int defaults); + float optionf(const char *commalist, float defaults); + void tty_attach(); + void tty_detach(); + void tty_color(unsigned color); + void tty_reset(); + const char* app_exec(const char *command); + int app_spawn(const char *command); + int app_cores(); + int app_battery(); + const char* app_name(); + const char* app_path(); + const char* app_cache(); + const char* app_temp(); + const char* app_cmdline(); + void app_beep(); + void app_hang(); + void app_crash(); + void app_singleton(const char *guid); + bool app_open(const char *folder_file_or_url); + const char* app_loadfile(); + const char* app_savefile(); + char* callstack( int traces ); + int callstackf( FILE *fp, int traces ); + void die(const char *message); + void alert(const char *message); + void hexdump( const void *ptr, unsigned len ); + void hexdumpf( FILE *fp, const void *ptr, unsigned len, int width ); + void breakpoint(); + bool has_debugger(); + void trap_install(void); + const char *trap_name(int signal); + void trap_on_ignore(int signal); + void trap_on_quit(int signal); + void trap_on_abort(int signal); + void trap_on_debug(int signal); + int (PANIC)(const char *error, const char *file, int line); + int (PRINTF)(const char *text, const char *stack, const char *file, int line, const char *function); + int (test)(const char *file, int line, const char *expr, bool result); uint64_t date(); uint64_t date_epoch(); char* date_string(); @@ -3229,54 +3280,9 @@ int* indices; } curve_t; curve_t curve(); void curve_add(curve_t *c, vec3 p); - void curve_finish(curve_t *c, int num_points); + void curve_end(curve_t *c, int num_points); vec3 curve_eval(curve_t *c, float dt, unsigned *color); void curve_destroy(curve_t *c); - void* thread( int (*thread_func)(void* user_data), void* user_data ); - void thread_destroy( void *thd ); - int argc(); - char* argv(int); - int flag(const char *commalist); - const char* option(const char *commalist, const char *defaults); - int optioni(const char *commalist, int defaults); - float optionf(const char *commalist, float defaults); - void tty_attach(); - void tty_detach(); - void tty_color(unsigned color); - void tty_reset(); - const char* app_exec(const char *command); - int app_spawn(const char *command); - int app_cores(); - int app_battery(); - const char* app_name(); - const char* app_path(); - const char* app_cache(); - const char* app_temp(); - const char* app_cmdline(); - void app_beep(); - void app_hang(); - void app_crash(); - void app_singleton(const char *guid); - bool app_open(const char *folder_file_or_url); - const char* app_loadfile(); - const char* app_savefile(); - char* callstack( int traces ); - int callstackf( FILE *fp, int traces ); - void die(const char *message); - void alert(const char *message); - void hexdump( const void *ptr, unsigned len ); - void hexdumpf( FILE *fp, const void *ptr, unsigned len, int width ); - void breakpoint(); - bool has_debugger(); - void trap_install(void); - const char *trap_name(int signal); - void trap_on_ignore(int signal); - void trap_on_quit(int signal); - void trap_on_abort(int signal); - void trap_on_debug(int signal); - int (PANIC)(const char *error, const char *file, int line); - int (PRINTF)(const char *text, const char *stack, const char *file, int line, const char *function); - int (test)(const char *file, int line, const char *expr, bool result); enum PANEL_FLAGS { PANEL_OPEN = 1, }; @@ -3438,13 +3444,15 @@ enum CURSOR_SHAPES { CURSOR_NONE, CURSOR_HW_ARROW, CURSOR_HW_IBEAM, -CURSOR_HW_CROSS, -CURSOR_HW_HAND, CURSOR_HW_HDRAG, CURSOR_HW_VDRAG, +CURSOR_HW_HAND, +CURSOR_HW_CROSS, CURSOR_SW_AUTO, }; void window_cursor_shape(unsigned shape); + const char *window_clipboard(); + void window_setclipboard(const char *text); ]]) local _M = {} function _M.vec2(x,y) diff --git a/engine/art/fx/editorOutline.fs b/engine/art/fx/editorOutline.fs index 57a7eee..e2cf2e3 100644 --- a/engine/art/fx/editorOutline.fs +++ b/engine/art/fx/editorOutline.fs @@ -17,5 +17,8 @@ void main() { } } - FRAGCOLOR = vec4(border_color.rgb, outline * border_color.a); // mix(texel, border_color, outline * border_color.a); -} \ No newline at end of file + if( outline == 0.0 ) + discard; + + FRAGCOLOR = vec4(border_color.rgb, outline * border_color.a); +} diff --git a/engine/joint/v4k.h b/engine/joint/v4k.h index 9a4597f..fea7b09 100644 --- a/engine/joint/v4k.h +++ b/engine/joint/v4k.h @@ -15919,6 +15919,16 @@ API void script_bind_function(const char *c_name, void *c_function); API void script_call(const char *lua_function); API bool script_tests(); + +// ----------------------------------------------------------------------------- +// script framework + +enum { + SCRIPT_LUA = 1, + SCRIPT_DEBUGGER = 2, +}; + +API void *script_init_env(unsigned flags); #line 0 #line 1 "engine/split/v4k_editor.h" @@ -15968,98 +15978,6 @@ API void kit_locale( const char *langcode_iso639_1 ); // set current locale: en API char* kit_translate( const char *id ); // perform a translation, given current locale #line 0 -#line 1 "engine/split/v4k_font.h" -// ----------------------------------------------------------------------------- -// font framework -// - rlyeh, public domain - -// font size tags -#define FONT_H1 "\1" // largest -#define FONT_H2 "\2" -#define FONT_H3 "\3" -#define FONT_H4 "\4" -#define FONT_H5 "\5" -#define FONT_H6 "\6" // smallest - -// font color tags -#define FONT_COLOR1 "\x10" -#define FONT_COLOR2 "\x11" -#define FONT_COLOR3 "\x12" -#define FONT_COLOR4 "\x13" -#define FONT_COLOR5 "\x14" -#define FONT_COLOR6 "\x15" -#define FONT_COLOR7 "\x16" -#define FONT_COLOR8 "\x17" -#define FONT_COLOR9 "\x18" -#define FONT_COLOR10 "\x19" - -// font face tags -#define FONT_FACE1 "\x1a" -#define FONT_FACE2 "\x1b" -#define FONT_FACE3 "\x1c" -#define FONT_FACE4 "\x1d" -#define FONT_FACE5 "\x1e" -#define FONT_FACE6 "\x1f" - -// font align tags -#define FONT_LEFT "\\<" -#define FONT_CENTER "\\|" -#define FONT_RIGHT "\\>" -#define FONT_TOP "\\^" -#define FONT_MIDDLE "\\-" -#define FONT_BASELINE "\\_" -#define FONT_BOTTOM "\\v" - -// font flags -enum FONT_FLAGS { - // font atlas size - FONT_512 = 0x0, - FONT_1024 = 0x1, - FONT_2048 = 0x2, - FONT_4096 = 0x4, - - // font oversampling - FONT_NO_OVERSAMPLE = 0x0, - FONT_OVERSAMPLE_X = 0x08, - FONT_OVERSAMPLE_Y = 0x10, - - // unicode ranges - FONT_ASCII = 0x800, // Compatible charset - FONT_AR = 0x001000, // Arabic and Arabic-Indic digits - FONT_ZH = 0x002000, // Chinese Simplified (@todo: add ZH_FULL) - FONT_EL = 0x004000, // Greek, Coptic, modern Georgian, Svan, Mingrelian, Ancient Greek - FONT_EM = 0x008000, // Emoji - FONT_EU = 0x010000, // Eastern/western Europe, IPA, Latin ext A/B - FONT_HE = 0x020000, // Hebrew, Yiddish, Ladino, and other diaspora languages - FONT_JP = 0x040000, // Hiragana, Katakana, Punctuations, Half-width chars - FONT_KR = 0x080000, // Korean, Hangul - FONT_RU = 0x100000, // Cyrillic + ext A/B - FONT_TH = 0x200000, // Thai - FONT_VI = 0x400000, // Vietnamese - FONT_CJK = FONT_ZH|FONT_JP|FONT_KR, - - // FONT_DEFAULTS = FONT_512 | FONT_NO_OVERSAMPLE | FONT_ASCII, -}; - -// configures -API void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags); -API void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags); -API void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6); -API void font_color(const char *color_tag, uint32_t color); - -// commands -API vec2 font_xy(); -API void font_goto(float x, float y); -API vec2 font_print(const char *text); -API vec2 font_rect(const char *text); -// void font_clip(vec2 topleft, vec2 bottomright); -// void font_wrap(vec2 topleft, vec2 bottomright); - -// syntax highlighting -API void* font_colorize(const char *text, const char *comma_types, const char *comma_keywords); // comma separated tokens. expensive, please cache result. -API vec2 font_highlight(const char *text, const void *colors); -#line 0 - #line 1 "engine/split/v4k_file.h" // ----------------------------------------------------------------------------- // files, cache and virtual filesystem (registered directories and/or compressed zip archives). @@ -16160,6 +16078,98 @@ API void ini_destroy(ini_t); API bool ini_write(const char *filename, const char *section, const char *key, const char *value); #line 0 +#line 1 "engine/split/v4k_font.h" +// ----------------------------------------------------------------------------- +// font framework +// - rlyeh, public domain + +// font size tags +#define FONT_H1 "\1" // largest +#define FONT_H2 "\2" +#define FONT_H3 "\3" +#define FONT_H4 "\4" +#define FONT_H5 "\5" +#define FONT_H6 "\6" // smallest + +// font color tags +#define FONT_COLOR1 "\x10" +#define FONT_COLOR2 "\x11" +#define FONT_COLOR3 "\x12" +#define FONT_COLOR4 "\x13" +#define FONT_COLOR5 "\x14" +#define FONT_COLOR6 "\x15" +#define FONT_COLOR7 "\x16" +#define FONT_COLOR8 "\x17" +#define FONT_COLOR9 "\x18" +#define FONT_COLOR10 "\x19" + +// font face tags +#define FONT_FACE1 "\x1a" +#define FONT_FACE2 "\x1b" +#define FONT_FACE3 "\x1c" +#define FONT_FACE4 "\x1d" +#define FONT_FACE5 "\x1e" +#define FONT_FACE6 "\x1f" + +// font align tags +#define FONT_LEFT "\\<" +#define FONT_CENTER "\\|" +#define FONT_RIGHT "\\>" +#define FONT_TOP "\\^" +#define FONT_MIDDLE "\\-" +#define FONT_BASELINE "\\_" +#define FONT_BOTTOM "\\v" + +// font flags +enum FONT_FLAGS { + // font atlas size + FONT_512 = 0x0, + FONT_1024 = 0x1, + FONT_2048 = 0x2, + FONT_4096 = 0x4, + + // font oversampling + FONT_NO_OVERSAMPLE = 0x0, + FONT_OVERSAMPLE_X = 0x08, + FONT_OVERSAMPLE_Y = 0x10, + + // unicode ranges + FONT_ASCII = 0x800, // Compatible charset + FONT_AR = 0x001000, // Arabic and Arabic-Indic digits + FONT_ZH = 0x002000, // Chinese Simplified (@todo: add ZH_FULL) + FONT_EL = 0x004000, // Greek, Coptic, modern Georgian, Svan, Mingrelian, Ancient Greek + FONT_EM = 0x008000, // Emoji + FONT_EU = 0x010000, // Eastern/western Europe, IPA, Latin ext A/B + FONT_HE = 0x020000, // Hebrew, Yiddish, Ladino, and other diaspora languages + FONT_JP = 0x040000, // Hiragana, Katakana, Punctuations, Half-width chars + FONT_KR = 0x080000, // Korean, Hangul + FONT_RU = 0x100000, // Cyrillic + ext A/B + FONT_TH = 0x200000, // Thai + FONT_VI = 0x400000, // Vietnamese + FONT_CJK = FONT_ZH|FONT_JP|FONT_KR, + + // FONT_DEFAULTS = FONT_512 | FONT_NO_OVERSAMPLE | FONT_ASCII, +}; + +// configures +API void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags); +API void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags); +API void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6); +API void font_color(const char *color_tag, uint32_t color); + +// commands +API vec2 font_xy(); +API void font_goto(float x, float y); +API vec2 font_print(const char *text); +API vec2 font_rect(const char *text); +// void font_clip(vec2 topleft, vec2 bottomright); +// void font_wrap(vec2 topleft, vec2 bottomright); + +// syntax highlighting +API void* font_colorize(const char *text, const char *comma_types, const char *comma_keywords); // comma separated tokens. expensive, please cache result. +API vec2 font_highlight(const char *text, const void *colors); +#line 0 + #line 1 "engine/split/v4k_input.h" // ----------------------------------------------------------------------------- // input framework @@ -16262,7 +16272,7 @@ enum INPUT_ENUMS { KEY_PAD1,KEY_PAD2,KEY_PAD3,KEY_PAD4,KEY_PAD5,KEY_PAD6,KEY_PAD7,KEY_PAD8,KEY_PAD9,KEY_PAD0, // beware: complicated on laptops KEY_PADADD,KEY_PADSUB,KEY_PADMUL,KEY_PADDIV,KEY_PADDOT,KEY_PADENTER, // beware: complicated on laptops - MOUSE_L, MOUSE_M, MOUSE_R, + MOUSE_L, MOUSE_M, MOUSE_R, // @todo: MOUSE_CLICKS, GAMEPAD_CONNECTED, GAMEPAD_A, GAMEPAD_B, GAMEPAD_X, GAMEPAD_Y, GAMEPAD_UP, GAMEPAD_DOWN, GAMEPAD_LEFT, GAMEPAD_RIGHT, GAMEPAD_MENU, GAMEPAD_START, GAMEPAD_LB, GAMEPAD_RB, GAMEPAD_LTHUMB, GAMEPAD_RTHUMB, @@ -17125,6 +17135,7 @@ enum TEXTURE_FLAGS { // @fixme TEXTURE_SRGB = 1 << 24, TEXTURE_BGR = 1 << 25, + TEXTURE_BGRA = TEXTURE_BGR, TEXTURE_ARRAY = 1 << 26, }; @@ -17919,6 +17930,7 @@ API light_t* scene_index_light(unsigned index); API char* tempvl(const char *fmt, va_list); API char* tempva(const char *fmt, ...); #define va(...) (((&printf) || printf(__VA_ARGS__), tempva(__VA_ARGS__))) // vs2015 check trick +#define vac (const char*)va // string: allocated api (heap). FREE() after use API char* strcatf(char **s, const char *buf); @@ -18005,6 +18017,93 @@ API unsigned quark_intern( quarks_db*, const char *string ); API const char *quark_string( quarks_db*, unsigned key ); #line 0 +#line 1 "engine/split/v4k_system.h" +// ----------------------------------------------------------------------------- +// system framework utils +// - rlyeh, public domain. +// +// Note: Windows users add `/Zi` compilation flags, else add `-g` and/or `-ldl` flags +// Note: If you are linking your binary using GNU ld you need to add --export-dynamic + +API void* thread( int (*thread_func)(void* user_data), void* user_data ); +API void thread_destroy( void *thd ); + +API int argc(); +API char* argv(int); + +API int flag(const char *commalist); // --arg // app_flag? +API const char* option(const char *commalist, const char *defaults); // --arg=string or --arg string +API int optioni(const char *commalist, int defaults); // --arg=integer or --arg integer // argvi() ? +API float optionf(const char *commalist, float defaults); // --arg=float or --arg float // flagf() ? + +API void tty_attach(); +API void tty_detach(); +API void tty_color(unsigned color); +API void tty_reset(); + +API const char* app_exec(const char *command); // returns ("%15d %s", retcode, output_last_line) +API int app_spawn(const char *command); +API int app_cores(); +API int app_battery(); /// returns battery level [1..100]. also positive if charging (+), negative if discharging (-), and 0 if no battery is present. + +API const char* app_name(); +API const char* app_path(); +API const char* app_cache(); +API const char* app_temp(); +API const char* app_cmdline(); + +API void app_beep(); +API void app_hang(); +API void app_crash(); +API void app_singleton(const char *guid); +API bool app_open(const char *folder_file_or_url); + +API const char* app_loadfile(); +API const char* app_savefile(); + + +API char* callstack( int traces ); // write callstack into a temporary string. <0 traces to invert order. do not free(). +API int callstackf( FILE *fp, int traces ); // write callstack to file. <0 traces to invert order. + +API void die(const char *message); +API void alert(const char *message); +API void hexdump( const void *ptr, unsigned len ); +API void hexdumpf( FILE *fp, const void *ptr, unsigned len, int width ); +API void breakpoint(); +API bool has_debugger(); + +API void trap_install(void); +API const char *trap_name(int signal); // helper util +API void trap_on_ignore(int signal); // helper util +API void trap_on_quit(int signal); // helper util +API void trap_on_abort(int signal); // helper util +API void trap_on_debug(int signal); // helper util + +#define PANIC(...) PANIC(va(__VA_ARGS__), strrchr(__FILE__, '/')?(strrchr(__FILE__, '/')+2):__FILE__, __LINE__) // die() ? +API int (PANIC)(const char *error, const char *file, int line); + +#define PRINTF(...) PRINTF(va(__VA_ARGS__), 1[#__VA_ARGS__] == '!' ? callstack(+48) : "", strrchr(__FILE__, '/')?(strrchr(__FILE__, '/')+2):__FILE__, __LINE__, __FUNCTION__) +API int (PRINTF)(const char *text, const char *stack, const char *file, int line, const char *function); + +#define test(expr) test(strrchr(__FILE__, '/')?(strrchr(__FILE__, '/')+2):__FILE__,__LINE__,#expr,!!(expr)) +API int (test)(const char *file, int line, const char *expr, bool result); + +#if ENABLE_AUTOTESTS +#define AUTOTEST AUTORUN +#else +#define AUTOTEST static void concat(concat(concat(disabled_test_, __LINE__), _), __COUNTER__)() +#endif + +// AUTOTEST { test(1<2); } + +#if ENABLE_RETAIL +#undef PRINTF +#define PRINTF(...) 0 +#undef test +#define test(expr) 0 +#endif +#line 0 + #line 1 "engine/split/v4k_time.h" // ----------------------------------------------------------------------------- // time framework utils @@ -18159,98 +18258,11 @@ typedef struct curve_t { API curve_t curve(); API void curve_add(curve_t *c, vec3 p); -API void curve_finish(curve_t *c, int num_points); +API void curve_end(curve_t *c, int num_points); API vec3 curve_eval(curve_t *c, float dt, unsigned *color); API void curve_destroy(curve_t *c); #line 0 -#line 1 "engine/split/v4k_system.h" -// ----------------------------------------------------------------------------- -// system framework utils -// - rlyeh, public domain. -// -// Note: Windows users add `/Zi` compilation flags, else add `-g` and/or `-ldl` flags -// Note: If you are linking your binary using GNU ld you need to add --export-dynamic - -API void* thread( int (*thread_func)(void* user_data), void* user_data ); -API void thread_destroy( void *thd ); - -API int argc(); -API char* argv(int); - -API int flag(const char *commalist); // --arg // app_flag? -API const char* option(const char *commalist, const char *defaults); // --arg=string or --arg string -API int optioni(const char *commalist, int defaults); // --arg=integer or --arg integer // argvi() ? -API float optionf(const char *commalist, float defaults); // --arg=float or --arg float // flagf() ? - -API void tty_attach(); -API void tty_detach(); -API void tty_color(unsigned color); -API void tty_reset(); - -API const char* app_exec(const char *command); // returns ("%15d %s", retcode, output_last_line) -API int app_spawn(const char *command); -API int app_cores(); -API int app_battery(); /// returns battery level [1..100]. also positive if charging (+), negative if discharging (-), and 0 if no battery is present. - -API const char* app_name(); -API const char* app_path(); -API const char* app_cache(); -API const char* app_temp(); -API const char* app_cmdline(); - -API void app_beep(); -API void app_hang(); -API void app_crash(); -API void app_singleton(const char *guid); -API bool app_open(const char *folder_file_or_url); - -API const char* app_loadfile(); -API const char* app_savefile(); - - -API char* callstack( int traces ); // write callstack into a temporary string. <0 traces to invert order. do not free(). -API int callstackf( FILE *fp, int traces ); // write callstack to file. <0 traces to invert order. - -API void die(const char *message); -API void alert(const char *message); -API void hexdump( const void *ptr, unsigned len ); -API void hexdumpf( FILE *fp, const void *ptr, unsigned len, int width ); -API void breakpoint(); -API bool has_debugger(); - -API void trap_install(void); -API const char *trap_name(int signal); // helper util -API void trap_on_ignore(int signal); // helper util -API void trap_on_quit(int signal); // helper util -API void trap_on_abort(int signal); // helper util -API void trap_on_debug(int signal); // helper util - -#define PANIC(...) PANIC(va(__VA_ARGS__), strrchr(__FILE__, '/')?(strrchr(__FILE__, '/')+2):__FILE__, __LINE__) // die() ? -API int (PANIC)(const char *error, const char *file, int line); - -#define PRINTF(...) PRINTF(va(__VA_ARGS__), 1[#__VA_ARGS__] == '!' ? callstack(+48) : "", strrchr(__FILE__, '/')?(strrchr(__FILE__, '/')+2):__FILE__, __LINE__, __FUNCTION__) -API int (PRINTF)(const char *text, const char *stack, const char *file, int line, const char *function); - -#define test(expr) test(strrchr(__FILE__, '/')?(strrchr(__FILE__, '/')+2):__FILE__,__LINE__,#expr,!!(expr)) -API int (test)(const char *file, int line, const char *expr, bool result); - -#if ENABLE_AUTOTESTS -#define AUTOTEST AUTORUN -#else -#define AUTOTEST static void concat(concat(concat(disabled_test_, __LINE__), _), __COUNTER__)() -#endif - -// AUTOTEST { test(1<2); } - -#if ENABLE_RETAIL -#undef PRINTF -#define PRINTF(...) 0 -#undef test -#define test(expr) 0 -#endif -#line 0 - #line 1 "engine/split/v4k_ui.h" // ----------------------------------------------------------------------------- // immediate ui framework @@ -18474,14 +18486,17 @@ enum CURSOR_SHAPES { CURSOR_NONE, CURSOR_HW_ARROW, // default CURSOR_HW_IBEAM, // i-beam text cursor - CURSOR_HW_CROSS, // crosshair - CURSOR_HW_HAND, // hand, clickable CURSOR_HW_HDRAG, // horizontal drag/resize CURSOR_HW_VDRAG, // vertical drag/resize + CURSOR_HW_HAND, // hand, clickable + CURSOR_HW_CROSS, // crosshair CURSOR_SW_AUTO, // software cursor, ui driven. note: this is the only icon that may be recorded or snapshotted }; API void window_cursor_shape(unsigned shape); + +API const char *window_clipboard(); +API void window_setclipboard(const char *text); #line 0 // ---- @@ -18498,7 +18513,7 @@ API void window_cursor_shape(unsigned shape); #include #define gladLoadGL(func) (glewExperimental = true, glewInit() == GLEW_OK) #else - #if is(win32) /*&& is(tcc)*/ // && WITH_DLL + #if is(win32) /*&& is(tcc)*/ // && ENABLE_DLL #ifdef GLAD_API_CALL #undef GLAD_API_CALL #endif @@ -32466,6 +32481,7 @@ int gladLoadGL( GLADloadfunc load) { #define JO_MPEG_COMPONENTS 3 // jo_mpeg #define JSON5_C // json5 #define LUA_IMPL // lua544 +#define LUA_USE_POPEN 1 // for lite editor #define MINIAUDIO_IMPLEMENTATION // miniaudio #define MA_NO_FLAC // miniaudio #define NK_GLFW_GL3_IMPLEMENTATION // nuklear @@ -32494,7 +32510,7 @@ int gladLoadGL( GLADloadfunc load) { #define BQ_WEBSOCKET_IMPLEMENTATION // websocket #define XML_C // xml #ifdef __APPLE__ -#define MA_NO_RUNTIME_LINKING // miniaudio +#define MA_NO_RUNTIME_LINKING // miniaudio osx #define _GLFW_COCOA // glfw osx #elif defined _WIN32 #define _GLFW_WIN32 // glfw win32 @@ -32543,7 +32559,6 @@ errno_t fopen_s( ); #endif - //--- #line 1 "engine/split/3rd_glfw3.h" #ifndef __EMSCRIPTEN__ @@ -75043,14 +75058,14 @@ static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, float k00,k11; float l00,l11; - k00 = z[-0] - z[-8]; - k11 = z[-1] - z[-9]; + k00 = z[-0] - z[ -8]; + k11 = z[-1] - z[ -9]; l00 = z[-2] - z[-10]; l11 = z[-3] - z[-11]; - z[-0] = z[-0] + z[-8]; - z[-1] = z[-1] + z[-9]; - z[ -2] = z[ -2] + z[-10]; - z[ -3] = z[ -3] + z[-11]; + z[ -0] = z[-0] + z[ -8]; + z[ -1] = z[-1] + z[ -9]; + z[ -2] = z[-2] + z[-10]; + z[ -3] = z[-3] + z[-11]; z[ -8] = k00; z[ -9] = k11; z[-10] = (l00+l11) * A2; @@ -76110,7 +76125,7 @@ static int start_decoder(vorb *f) f->comment_list = NULL; if (f->comment_list_length > 0) { - f->comment_list = (char**)setup_malloc(f, sizeof(char*) * (f->comment_list_length)); + f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length)); if (f->comment_list == NULL) return error(f, VORBIS_outofmem); } @@ -201401,7 +201416,7 @@ STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int #if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) { - return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); } #endif @@ -201418,8 +201433,8 @@ static FILE *stbi__fopen(char const *filename, char const *mode) return 0; #if defined(_MSC_VER) && _MSC_VER >= 1400 - if (0 != _wfopen_s(&f, wFilename, wMode)) - f = 0; + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; #else f = _wfopen(wFilename, wMode); #endif @@ -203509,8 +203524,8 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j) m = stbi__get_marker(j); } else { if (!stbi__process_marker(j, m)) return 1; - m = stbi__get_marker(j); - } + m = stbi__get_marker(j); + } } if (j->progressive) stbi__jpeg_finish(j); @@ -205403,7 +205418,7 @@ static int stbi__png_is16(stbi__context *s) stbi__png p; p.s = s; if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) - return 0; + return 0; if (p.depth != 16) { stbi__rewind(p.s); return 0; @@ -205647,7 +205662,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn // ensures the number computed in the second half of the test can't overflow. if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { - return stbi__errpuc("bad offset", "Corrupt BMP"); + return stbi__errpuc("bad offset", "Corrupt BMP"); } else { stbi__skip(s, info.offset - bytes_read_so_far); } @@ -207412,7 +207427,7 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) info.all_a = 255; p = stbi__bmp_parse_header(s, &info); if (p == NULL) { - stbi__rewind( s ); + stbi__rewind( s ); return 0; } if (x) *x = s->img_x; @@ -207605,7 +207620,7 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req if (ri->bits_per_channel == 16) { out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); } else { - out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); } if (out == NULL) return out; // stbi__convert_format frees input on failure } @@ -208555,11 +208570,11 @@ static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, c { if (comp != 4) { // write RGB bitmap - int pad = (-x*3) & 3; - return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, - "11 4 22 4" "4 44 22 444444", - 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header - 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header } else { // RGBA bitmaps need a v4 header // use BI_BITFIELDS mode with 32bpp and alpha mask @@ -235069,6 +235084,7 @@ nk_selectable_text(struct nk_context *ctx, const char *str, int len, state = nk_widget(&bounds, ctx); if (!state) return 0; in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; + return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds, str, len, align, value, &style->selectable, in, style->font); } @@ -254604,8 +254620,12 @@ struct dir { // --- -#if !defined(S_ISDIR) -# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#ifndef S_ISDIR +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #endif int dir_yield(dir *d, const char *pathfile, char *name, int namelen) { @@ -296042,12 +296062,12 @@ Compiling ---------- Simple TLS client: -`$ gcc tlshello.c -o tlshello -ltomcrypt -ltommath -DLTM_DESC` +`$ gcc tlshello.c -o tlshello -ltomcrypt -ltommath -DLTM_DESC` For debuging tls connections, the DEBUG flag must be set (-DDEBUG). Simple TLS server: -`$ gcc tlsserverhello.c -o tlsserverhello -ltomcrypt -ltommath -DLTM_DESC` +`$ gcc tlsserverhello.c -o tlsserverhello -ltomcrypt -ltommath -DLTM_DESC` The entire library is a single c file that you just include in your source. @@ -296068,7 +296088,7 @@ TLSe supports KTLS on linux kernel 4.13 or higher. KTLS is a TLS implementation Usage ---------- -You just +You just `#include "tlse.c"` in your code. Everything is a single file. @@ -296479,7 +296499,7 @@ int tls_make_ktls(struct TLSContext *context, int socket); int tls_unmake_ktls(struct TLSContext *context, int socket); /* Creates a new DTLS random cookie secret to be used in HelloVerifyRequest (server-side). - It is recommended to call this function from time to time, to protect against some + It is recommended to call this function from time to time, to protect against some DoS attacks. */ void dtls_reset_cookie_secret(); @@ -296573,17 +296593,17 @@ int tls_remote_error(struct TLSContext *context); /******************************************************************************** Copyright (c) 2016-2023, Eduard Suica All rights reserved. - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -297398,7 +297418,7 @@ int chacha20_poly1305_aead(struct chacha_ctx *ctx, unsigned char *pt, unsigned unsigned int counter = 1; chacha_ivsetup_96bitnonce(ctx, NULL, (unsigned char *)&counter); chacha_encrypt_bytes(ctx, pt, out, len); - + poly1305_context aead_ctx; _private_tls_poly1305_init(&aead_ctx, poly_key); _private_tls_poly1305_update(&aead_ctx, aad, aad_len); @@ -297418,7 +297438,7 @@ int chacha20_poly1305_aead(struct chacha_ctx *ctx, unsigned char *pt, unsigned _private_tls_poly1305_update(&aead_ctx, trail, 16); _private_tls_poly1305_finish(&aead_ctx, out + len); - + return len + POLY1305_TAGLEN; } #endif @@ -297790,19 +297810,19 @@ struct TLSContext { unsigned char cipher_spec_set; TLSCipher crypto; TLSHash *handshake_hash; - + unsigned char *message_buffer; unsigned int message_buffer_len; uint64_t remote_sequence_number; uint64_t local_sequence_number; - + unsigned char connection_status; unsigned char critical_error; unsigned char error_code; - + unsigned char *tls_buffer; unsigned int tls_buffer_len; - + unsigned char *application_buffer; unsigned int application_buffer_len; unsigned char is_child; @@ -297962,10 +297982,10 @@ void _private_b64_decodeblock(unsigned char in[4], unsigned char out[3]) { int _private_b64_decode(const char *in_buffer, int in_buffer_size, unsigned char *out_buffer) { unsigned char in[4], out[3], v; int i, len; - + const char *ptr = in_buffer; char *out_ptr = (char *)out_buffer; - + while (ptr <= in_buffer + in_buffer_size) { for (len = 0, i = 0; i < 4 && (ptr <= in_buffer + in_buffer_size); i++) { v = 0; @@ -298033,26 +298053,26 @@ int _private_tls_dh_shared_secret(DHKey *private_key, DHKey *public_key, unsigne void *tmp; unsigned long x; int err; - + if ((!private_key) || (!public_key) || (!out) || (!outlen)) return TLS_GENERIC_ERROR; - + /* compute y^x mod p */ if ((err = mp_init(&tmp)) != CRYPT_OK) return err; - + if ((err = mp_exptmod(public_key->y, private_key->x, private_key->p, tmp)) != CRYPT_OK) { mp_clear(tmp); return err; } - + x = (unsigned long)mp_unsigned_bin_size(tmp); if (*outlen < x) { err = CRYPT_BUFFER_OVERFLOW; mp_clear(tmp); return err; } - + if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { mp_clear(tmp); return err; @@ -298068,10 +298088,10 @@ unsigned char *_private_tls_decrypt_dhe(struct TLSContext *context, const unsign DEBUG_PRINT("No private DHE key set\n"); return NULL; } - + unsigned long out_size = len; void *Yc = NULL; - + if (mp_init(&Yc)) { DEBUG_PRINT("ERROR CREATING Yc\n"); return NULL; @@ -298085,7 +298105,7 @@ unsigned char *_private_tls_decrypt_dhe(struct TLSContext *context, const unsign unsigned char *out = (unsigned char *)TLS_MALLOC(len); DHKey client_key; memset(&client_key, 0, sizeof(DHKey)); - + client_key.p = context->dhe->p; client_key.g = context->dhe->g; client_key.y = Yc; @@ -298114,15 +298134,15 @@ unsigned char *_private_tls_decrypt_ecc_dhe(struct TLSContext *context, const un DEBUG_PRINT("No private ECC DHE key set\n"); return NULL; } - + const struct ECCCurveParameters *curve; if (context->curve) curve = context->curve; else curve = default_curve; - + ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&curve->dp; - + ecc_key client_key; memset(&client_key, 0, sizeof(client_key)); if (ecc_ansi_x963_import_ex(buffer, len, &client_key, dp)) { @@ -298131,7 +298151,7 @@ unsigned char *_private_tls_decrypt_ecc_dhe(struct TLSContext *context, const un } unsigned char *out = (unsigned char *)TLS_MALLOC(len); unsigned long out_size = len; - + int err = ecc_shared_secret(context->ecc_dhe, &client_key, out, &out_size); ecc_free(&client_key); if (clear_key) @@ -298158,7 +298178,7 @@ unsigned char *_private_tls_decrypt_rsa(struct TLSContext *context, const unsign rsa_key key; int err; err = rsa_import(context->private_key->der_bytes, context->private_key->der_len, &key); - + if (err) { DEBUG_PRINT("Error importing RSA key (code: %i)\n", err); return NULL; @@ -298192,7 +298212,7 @@ unsigned char *_private_tls_encrypt_rsa(struct TLSContext *context, const unsign rsa_key key; int err; err = rsa_import(context->certificates[0]->der_bytes, context->certificates[0]->der_len, &key); - + if (err) { DEBUG_PRINT("Error importing RSA certificate (code: %i)\n", err); return NULL; @@ -298216,28 +298236,28 @@ int _private_rsa_verify_hash_md5sha1(const unsigned char *sig, unsigned long sig unsigned long modulus_bitlen, modulus_bytelen, x; int err; unsigned char *tmpbuf = NULL; - + if ((hash == NULL) || (sig == NULL) || (stat == NULL) || (key == NULL) || (!siglen) || (!hashlen)) return TLS_GENERIC_ERROR; - + *stat = 0; - + modulus_bitlen = mp_count_bits((key->N)); - + modulus_bytelen = mp_unsigned_bin_size((key->N)); if (modulus_bytelen != siglen) return TLS_GENERIC_ERROR; - + tmpbuf = (unsigned char *)TLS_MALLOC(siglen); if (!tmpbuf) return TLS_GENERIC_ERROR; - + x = siglen; if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) { TLS_FREE(tmpbuf); return err; } - + if (x != siglen) { TLS_FREE(tmpbuf); return CRYPT_INVALID_PACKET; @@ -298248,7 +298268,7 @@ int _private_rsa_verify_hash_md5sha1(const unsigned char *sig, unsigned long sig TLS_FREE(tmpbuf); return TLS_GENERIC_ERROR; } - + int decoded = 0; err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &out_len, &decoded); if (decoded) { @@ -298257,7 +298277,7 @@ int _private_rsa_verify_hash_md5sha1(const unsigned char *sig, unsigned long sig *stat = 1; } } - + TLS_FREE(tmpbuf); TLS_FREE(out); return err; @@ -298268,7 +298288,7 @@ int _private_tls_verify_rsa(struct TLSContext *context, unsigned int hash_type, tls_init(); rsa_key key; int err; - + if (context->is_server) { if ((!len) || (!context->client_certificates) || (!context->client_certificates_count) || (!context->client_certificates[0]) || (!context->client_certificates[0]->der_bytes) || (!context->client_certificates[0]->der_len)) { @@ -298396,12 +298416,12 @@ int _private_tls_verify_rsa(struct TLSContext *context, unsigned int hash_type, int _private_rsa_sign_hash_md5sha1(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; - + if ((in == NULL) || (out == NULL) || (outlen == NULL) || (key == NULL)) return TLS_GENERIC_ERROR; - + modulus_bitlen = mp_count_bits((key->N)); - + modulus_bytelen = mp_unsigned_bin_size((key->N)); if (modulus_bytelen > *outlen) { *outlen = modulus_bytelen; @@ -298411,7 +298431,7 @@ int _private_rsa_sign_hash_md5sha1(const unsigned char *in, unsigned long inlen, err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x); if (err != CRYPT_OK) return err; - + return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key); } #endif @@ -298425,7 +298445,7 @@ int _private_tls_sign_rsa(struct TLSContext *context, unsigned int hash_type, co rsa_key key; int err; err = rsa_import(context->private_key->der_bytes, context->private_key->der_len, &key); - + if (err) { DEBUG_PRINT("Error importing RSA certificate (code: %i)\n", err); return TLS_GENERIC_ERROR; @@ -298534,7 +298554,7 @@ int _private_tls_sign_rsa(struct TLSContext *context, unsigned int hash_type, co rsa_free(&key); if (err) return 0; - + return 1; } @@ -298542,11 +298562,11 @@ int _private_tls_sign_rsa(struct TLSContext *context, unsigned int hash_type, co static int _private_tls_is_point(ecc_key *key) { void *prime, *b, *t1, *t2; int err; - + if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL)) != CRYPT_OK) { return err; } - + /* load prime and b */ if ((err = mp_read_radix(prime, TLS_TOMCRYPT_PRIVATE_DP(key)->prime, 16)) != CRYPT_OK) { goto error; @@ -298554,12 +298574,12 @@ static int _private_tls_is_point(ecc_key *key) { if ((err = mp_read_radix(b, TLS_TOMCRYPT_PRIVATE_DP(key)->B, 16)) != CRYPT_OK) { goto error; } - + /* compute y^2 */ if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; } - + /* compute x^3 */ if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; @@ -298570,12 +298590,12 @@ static int _private_tls_is_point(ecc_key *key) { if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; } - + /* compute y^2 - x^3 */ if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; } - + /* compute y^2 - x^3 + 3x */ if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; @@ -298599,14 +298619,14 @@ static int _private_tls_is_point(ecc_key *key) { goto error; } } - + /* compare to b */ if (mp_cmp(t1, b) != LTC_MP_EQ) { err = CRYPT_INVALID_PACKET; } else { err = CRYPT_OK; } - + error: mp_clear_multi(prime, b, t1, t2, NULL); return err; @@ -298614,15 +298634,15 @@ error: int _private_tls_ecc_import_key(const unsigned char *private_key, int private_len, const unsigned char *public_key, int public_len, ecc_key *key, const ltc_ecc_set_type *dp) { int err; - + if ((!key) || (!ltc_mp.name)) return CRYPT_MEM; - + key->type = PK_PRIVATE; - + if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) return CRYPT_MEM; - + if ((public_len) && (!public_key[0])) { public_key++; public_len--; @@ -298631,33 +298651,33 @@ int _private_tls_ecc_import_key(const unsigned char *private_key, int private_le mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)public_key + 1 + ((public_len - 1) >> 1), (public_len - 1) >> 1)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)private_key, private_len)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + TLS_TOMCRYPT_PRIVATE_SET_INDEX(key, -1); TLS_TOMCRYPT_PRIVATE_DP(key) = dp; - + /* set z */ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + /* is it a point on the curve? */ if ((err = _private_tls_is_point(key)) != CRYPT_OK) { DEBUG_PRINT("KEY IS NOT ON CURVE\n"); mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + /* we're good */ return CRYPT_OK; } @@ -298668,9 +298688,9 @@ int _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, DEBUG_PRINT("No private ECDSA key set\n"); return TLS_GENERIC_ERROR; } - + const struct ECCCurveParameters *curve = NULL; - + switch (context->ec_private_key->ec_algorithm) { case 19: curve = &secp192r1; @@ -298696,16 +298716,16 @@ int _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, default: DEBUG_PRINT("UNSUPPORTED CURVE\n"); } - + if (!curve) return TLS_GENERIC_ERROR; - + tls_init(); ecc_key key; int err; - + ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&curve->dp; - + // broken ... fix this err = _private_tls_ecc_import_key(context->ec_private_key->priv, context->ec_private_key->priv_len, context->ec_private_key->pk, context->ec_private_key->pk_len, &key, dp); if (err) { @@ -298784,7 +298804,7 @@ int _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, hash_len = 36; break; } - + if (err) { DEBUG_PRINT("Unsupported hash type: %i\n", hash_type); return TLS_GENERIC_ERROR; @@ -298797,22 +298817,22 @@ int _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, ecc_free(&key); if (err) return 0; - + return 1; } #if defined(TLS_CLIENT_ECDSA) || defined(WITH_TLS_13) int _private_tls_ecc_import_pk(const unsigned char *public_key, int public_len, ecc_key *key, const ltc_ecc_set_type *dp) { int err; - + if ((!key) || (!ltc_mp.name)) return CRYPT_MEM; - + key->type = PK_PUBLIC; - + if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) return CRYPT_MEM; - + if ((public_len) && (!public_key[0])) { public_key++; public_len--; @@ -298821,29 +298841,29 @@ int _private_tls_ecc_import_pk(const unsigned char *public_key, int public_len, mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)public_key + 1 + ((public_len - 1) >> 1), (public_len - 1) >> 1)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - - + + TLS_TOMCRYPT_PRIVATE_SET_INDEX(key, -1); TLS_TOMCRYPT_PRIVATE_DP(key) = dp; - + /* set z */ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + /* is it a point on the curve? */ if ((err = _private_tls_is_point(key)) != CRYPT_OK) { DEBUG_PRINT("KEY IS NOT ON CURVE\n"); mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + /* we're good */ return CRYPT_OK; } @@ -298985,10 +299005,10 @@ void _private_tls_sleep(unsigned int microseconds) { Sleep(microseconds/1000); #else struct timespec ts; - + ts.tv_sec = (unsigned int) (microseconds / 1000000); ts.tv_nsec = (unsigned int) (microseconds % 1000000) * 1000ul; - + nanosleep(&ts, NULL); #endif } @@ -299007,10 +299027,10 @@ void _private_tls_prf_helper(int hash_idx, unsigned long dlen, unsigned char *ou unsigned char digest_out1[TLS_MAX_HASH_LEN]; unsigned int i; hmac_state hmac; - + hmac_init(&hmac, hash_idx, secret, secret_len); hmac_process(&hmac, label, label_len); - + hmac_process(&hmac, seed, seed_len); if ((seed_b) && (seed_b_len)) hmac_process(&hmac, seed_b, seed_b_len); @@ -299024,19 +299044,19 @@ void _private_tls_prf_helper(int hash_idx, unsigned long dlen, unsigned char *ou if ((seed_b) && (seed_b_len)) hmac_process(&hmac, seed_b, seed_b_len); hmac_done(&hmac, digest_out1, &dlen); - + unsigned int copylen = outlen; if (copylen > dlen) copylen = dlen; - + for (i = 0; i < copylen; i++) { output[idx++] ^= digest_out1[i]; outlen--; } - + if (!outlen) break; - + hmac_init(&hmac, hash_idx, secret, secret_len); hmac_process(&hmac, digest_out0, dlen); hmac_done(&hmac, digest_out0, &dlen); @@ -299106,18 +299126,18 @@ void _private_tls_hkdf_expand(unsigned int mac_length, unsigned char *output, un i2++; hmac_process(&hmac, &i2, 1); hmac_done(&hmac, digest_out, &dlen); - + unsigned int copylen = outlen; if (copylen > dlen) copylen = (unsigned int)dlen; - + for (i = 0; i < copylen; i++) { output[idx++] = digest_out[i]; outlen--; } - + if (!outlen) - break; + break; } } @@ -299141,7 +299161,7 @@ void _private_tls_prf(struct TLSContext *context, int md5_hash_idx = find_hash("md5"); int sha1_hash_idx = find_hash("sha1"); int half_secret = (secret_len + 1) / 2; - + memset(output, 0, outlen); _private_tls_prf_helper(md5_hash_idx, 16, output, outlen, secret, half_secret, label, label_len, seed, seed_len, seed_b, seed_b_len); _private_tls_prf_helper(sha1_hash_idx, 20, output, outlen, secret + (secret_len - half_secret), secret_len - half_secret, label, label_len, seed, seed_len, seed_b, seed_b_len); @@ -299159,10 +299179,10 @@ void _private_tls_prf(struct TLSContext *context, hash_idx = find_hash("sha256"); unsigned int i; hmac_state hmac; - + hmac_init(&hmac, hash_idx, secret, secret_len); hmac_process(&hmac, label, label_len); - + hmac_process(&hmac, seed, seed_len); if ((seed_b) && (seed_b_len)) hmac_process(&hmac, seed_b, seed_b_len); @@ -299176,19 +299196,19 @@ void _private_tls_prf(struct TLSContext *context, if ((seed_b) && (seed_b_len)) hmac_process(&hmac, seed_b, seed_b_len); hmac_done(&hmac, digest_out1, &dlen); - + unsigned int copylen = outlen; if (copylen > dlen) copylen = (unsigned int)dlen; - + for (i = 0; i < copylen; i++) { output[idx++] = digest_out1[i]; outlen--; } - + if (!outlen) break; - + hmac_init(&hmac, hash_idx, secret, secret_len); hmac_process(&hmac, digest_out0, dlen); hmac_done(&hmac, digest_out0, &dlen); @@ -299309,8 +299329,8 @@ int _private_tls13_key(struct TLSContext *context, int handshake) { unsigned int mac_length = _private_tls_mac_length(context); if ((!context->premaster_key) || (!context->premaster_key_len)) - return 0; - + return 0; + if ((!key_length) || (!mac_length)) { DEBUG_PRINT("KEY EXPANSION FAILED, KEY LENGTH: %i, MAC LENGTH: %i\n", key_length, mac_length); return 0; @@ -299415,7 +299435,7 @@ int _private_tls13_key(struct TLSContext *context, int handshake) { DEBUG_DUMP_HEX_LABEL("CLIENT IV", clientiv, iv_length) DEBUG_DUMP_HEX_LABEL("SERVER KEY", serverkey, key_length) DEBUG_DUMP_HEX_LABEL("SERVER IV", serveriv, iv_length) - + TLS_FREE(context->finished_key); TLS_FREE(context->remote_finished_key); if (handshake) { @@ -299488,7 +299508,7 @@ int _private_tls13_key(struct TLSContext *context, int handshake) { } context->local_sequence_number = 0; context->remote_sequence_number = 0; - + // extract client_mac_key(mac_key_length) // extract server_mac_key(mac_key_length) // extract client_key(enc_key_length) @@ -299505,13 +299525,13 @@ int _private_tls_expand_key(struct TLSContext *context) { if ((context->version == TLS_V13) || (context->version == DTLS_V13)) return 0; #endif - + if ((!context->master_key) || (!context->master_key_len)) return 0; - + int key_length = _private_tls_key_length(context); int mac_length = _private_tls_mac_length(context); - + if ((!key_length) || (!mac_length)) { DEBUG_PRINT("KEY EXPANSION FAILED, KEY LENGTH: %i, MAC LENGTH: %i\n", key_length, mac_length); return 0; @@ -299526,13 +299546,13 @@ int _private_tls_expand_key(struct TLSContext *context) { _private_tls_prf(context, key, sizeof(key), context->master_key, context->master_key_len, (unsigned char *)"key expansion", 13, context->local_random, TLS_SERVER_RANDOM_SIZE, context->remote_random, TLS_CLIENT_RANDOM_SIZE); else _private_tls_prf(context, key, sizeof(key), context->master_key, context->master_key_len, (unsigned char *)"key expansion", 13, context->remote_random, TLS_SERVER_RANDOM_SIZE, context->local_random, TLS_CLIENT_RANDOM_SIZE); - + DEBUG_DUMP_HEX_LABEL("LOCAL RANDOM ", context->local_random, TLS_SERVER_RANDOM_SIZE); DEBUG_DUMP_HEX_LABEL("REMOTE RANDOM", context->remote_random, TLS_CLIENT_RANDOM_SIZE); DEBUG_PRINT("\n=========== EXPANSION ===========\n"); DEBUG_DUMP_HEX(key, TLS_MAX_KEY_EXPANSION_SIZE); DEBUG_PRINT("\n"); - + int pos = 0; #ifdef TLS_WITH_CHACHA20_POLY1305 if (is_aead == 2) { @@ -299554,7 +299574,7 @@ int _private_tls_expand_key(struct TLSContext *context) { pos += mac_length; } } - + clientkey = &key[pos]; pos += key_length; serverkey = &key[pos]; @@ -299570,7 +299590,7 @@ int _private_tls_expand_key(struct TLSContext *context) { DEBUG_DUMP_HEX_LABEL("SERVER KEY", serverkey, key_length) DEBUG_DUMP_HEX_LABEL("SERVER IV", serveriv, iv_length) DEBUG_DUMP_HEX_LABEL("SERVER MAC KEY", context->is_server ? context->crypto.ctx_local_mac.local_mac : context->crypto.ctx_remote_mac.remote_mac, mac_length) - + if (context->is_server) { #ifdef TLS_WITH_CHACHA20_POLY1305 if (is_aead == 2) { @@ -299598,7 +299618,7 @@ int _private_tls_expand_key(struct TLSContext *context) { if (_private_tls_crypto_create(context, key_length, clientkey, clientiv, serverkey, serveriv)) return 0; } - + if (context->exportable) { TLS_FREE(context->exportable_keys); context->exportable_keys = (unsigned char *)TLS_MALLOC(key_length * 2); @@ -299613,7 +299633,7 @@ int _private_tls_expand_key(struct TLSContext *context) { context->exportable_size = key_length * 2; } } - + // extract client_mac_key(mac_key_length) // extract server_mac_key(mac_key_length) // extract client_key(enc_key_length) @@ -299692,14 +299712,14 @@ unsigned char *tls_pem_decode(const unsigned char *data_in, unsigned int input_l for (i = 0; i < input_length; i++) { if ((data_in[i] == '\n') || (data_in[i] == '\r')) continue; - + if (data_in[i] != '-') { // read entire line while ((i < input_length) && (data_in[i] != '\n')) i++; continue; } - + if (data_in[i] == '-') { unsigned int end_idx = i; //read until end of line @@ -299730,7 +299750,7 @@ int _is_oid(const unsigned char *oid, const unsigned char *compare_to, int compa while ((oid[i]) && (i < compare_to_len)) { if (oid[i] != compare_to[i]) return 0; - + i++; } return 1; @@ -299743,7 +299763,7 @@ int _is_oid2(const unsigned char *oid, const unsigned char *compare_to, int comp while (i < compare_to_len) { if (oid[i] != compare_to[i]) return 0; - + i++; } return 1; @@ -299760,17 +299780,17 @@ int tls_certificate_valid_subject_name(const unsigned char *cert_subject, const // no subjects ... if (((!cert_subject) || (!cert_subject[0])) && ((!subject) || (!subject[0]))) return 0; - + if ((!subject) || (!subject[0])) return bad_certificate; - + if ((!cert_subject) || (!cert_subject[0])) return bad_certificate; - + // exact match if (!strcmp((const char *)cert_subject, subject)) return 0; - + const char *wildcard = strchr((const char *)cert_subject, '*'); if (wildcard) { // 6.4.3 (1) The client SHOULD NOT attempt to match a presented identifier in @@ -299801,7 +299821,7 @@ int tls_certificate_valid_subject_name(const unsigned char *cert_subject, const return 0; } } - + return bad_certificate; } @@ -300026,7 +300046,7 @@ char *tls_certificate_to_string(struct TLSCertificate *cert, char *buffer, int l default: res += snprintf(buffer + res, len - res, "not supported):\n"); } - + for (i = 0; i < cert->sign_len; i++) res += snprintf(buffer + res, len - res, "%02x", (int)cert->sign_key[i]); } @@ -300106,32 +300126,32 @@ void tls_certificate_set_algorithm(struct TLSContext *context, unsigned int *alg } if (len != 9) return; - + if (_is_oid(val, TLS_RSA_SIGN_SHA256_OID, 9)) { *algorithm = TLS_RSA_SIGN_SHA256; return; } - + if (_is_oid(val, TLS_RSA_SIGN_RSA_OID, 9)) { *algorithm = TLS_RSA_SIGN_RSA; return; } - + if (_is_oid(val, TLS_RSA_SIGN_SHA1_OID, 9)) { *algorithm = TLS_RSA_SIGN_SHA1; return; } - + if (_is_oid(val, TLS_RSA_SIGN_SHA512_OID, 9)) { *algorithm = TLS_RSA_SIGN_SHA512; return; } - + if (_is_oid(val, TLS_RSA_SIGN_SHA384_OID, 9)) { *algorithm = TLS_RSA_SIGN_SHA384; return; } - + if (_is_oid(val, TLS_RSA_SIGN_MD5_OID, 9)) { *algorithm = TLS_RSA_SIGN_MD5; return; @@ -300268,14 +300288,14 @@ int _private_tls_crypto_create(struct TLSContext *context, int key_length, unsig if (is_aead) { int res1 = gcm_init(&context->crypto.ctx_local.aes_gcm_local, cipherID, localkey, key_length); int res2 = gcm_init(&context->crypto.ctx_remote.aes_gcm_remote, cipherID, remotekey, key_length); - + if ((res1) || (res2)) return TLS_GENERIC_ERROR; context->crypto.created = 2; } else { int res1 = cbc_start(cipherID, localiv, localkey, key_length, 0, &context->crypto.ctx_local.aes_local); int res2 = cbc_start(cipherID, remoteiv, remotekey, key_length, 0, &context->crypto.ctx_remote.aes_remote); - + if ((res1) || (res2)) return TLS_GENERIC_ERROR; context->crypto.created = 1; @@ -300294,7 +300314,7 @@ int _private_tls_crypto_encrypt(struct TLSContext *context, unsigned char *buf, int _private_tls_crypto_decrypt(struct TLSContext *context, unsigned char *buf, unsigned char *pt, unsigned int len) { if (context->crypto.created == 1) return cbc_decrypt(buf, pt, len, &context->crypto.ctx_remote.aes_remote); - + memset(pt, 0, len); return TLS_GENERIC_ERROR; } @@ -300316,7 +300336,7 @@ void _private_tls_crypto_done(struct TLSContext *context) { } void tls_packet_update(struct TLSPacket *packet) { - if ((packet) && (!packet->broken)) { + if ((packet) && (!packet->broken)) { int footer_size = 0; #ifdef WITH_TLS_13 if ((packet->context) && ((packet->context->version == TLS_V13) || (packet->context->version == DTLS_V13)) && (packet->context->cipher_spec_set) && (packet->context->crypto.created)) { @@ -300364,7 +300384,7 @@ void tls_packet_update(struct TLSPacket *packet) { unsigned int length = 0; unsigned char padding = 0; unsigned int pt_length = packet->len - header_size; - + if (packet->context->crypto.created == 1) { mac_size = _private_tls_mac_length(packet->context); #ifdef TLS_LEGACY_SUPPORT @@ -300412,10 +300432,10 @@ void tls_packet_update(struct TLSPacket *packet) { } else _private_tls_hmac_message(1, packet->context, packet->buf, packet->len, NULL, 0, buf + buf_pos, mac_size, 0); buf_pos += mac_size; - + memset(buf + buf_pos, padding - 1, padding); buf_pos += padding; - + //DEBUG_DUMP_HEX_LABEL("PT BUFFER", buf, length); _private_tls_crypto_encrypt(packet->context, buf, ct + header_size, length); TLS_FREE(packet->buf); @@ -300510,10 +300530,10 @@ void tls_packet_update(struct TLSPacket *packet) { gcm_reset(&packet->context->crypto.ctx_local.aes_gcm_local); gcm_add_iv(&packet->context->crypto.ctx_local.aes_gcm_local, iv, 12); - gcm_add_aad(&packet->context->crypto.ctx_local.aes_gcm_local, aad, aad_size); + gcm_add_aad(&packet->context->crypto.ctx_local.aes_gcm_local, aad, aad_size); gcm_process(&packet->context->crypto.ctx_local.aes_gcm_local, packet->buf + header_size, pt_length, ct + ct_pos, GCM_ENCRYPT); ct_pos += pt_length; - + unsigned long taglen = TLS_GCM_TAG_LEN; gcm_done(&packet->context->crypto.ctx_local.aes_gcm_local, ct + ct_pos, &taglen); ct_pos += taglen; @@ -300554,12 +300574,12 @@ void tls_packet_update(struct TLSPacket *packet) { int tls_packet_append(struct TLSPacket *packet, const unsigned char *buf, unsigned int len) { if ((!packet) || (packet->broken)) return -1; - + if (!len) return 0; - + unsigned int new_len = packet->len + len; - + if (new_len > packet->size) { packet->size = (new_len / TLS_BLOB_INCREMENT + 1) * TLS_BLOB_INCREMENT; packet->buf = (unsigned char *)TLS_REALLOC(packet->buf, packet->size); @@ -300596,7 +300616,7 @@ int tls_packet_uint24(struct TLSPacket *packet, unsigned int i) { buf[1] = i / 0x100; i %= 0x100; buf[2] = i; - + return tls_packet_append(packet, buf, 3); } @@ -300655,7 +300675,7 @@ void _private_tls_destroy_hash(struct TLSContext *context) { void _private_tls_create_hash(struct TLSContext *context) { if (!context) return; - + TLSHash *hash = _private_tls_ensure_hash(context); if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) { int hash_size = _private_tls_mac_length(context); @@ -300746,11 +300766,11 @@ int _private_tls_change_hash_type(struct TLSContext *context) { int _private_tls_done_hash(struct TLSContext *context, unsigned char *hout) { if (!context) return 0; - + TLSHash *hash = _private_tls_ensure_hash(context); if (!hash->created) return 0; - + int hash_size = 0; if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) { unsigned char temp[TLS_MAX_SHA_SIZE]; @@ -300804,11 +300824,11 @@ int _private_tls_get_hash_idx(struct TLSContext *context) { int _private_tls_get_hash(struct TLSContext *context, unsigned char *hout) { if (!context) return 0; - + TLSHash *hash = _private_tls_ensure_hash(context); if (!hash->created) return 0; - + int hash_size = 0; if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) { hash_size = _private_tls_mac_length(context); @@ -300827,15 +300847,15 @@ int _private_tls_get_hash(struct TLSContext *context, unsigned char *hout) { #ifdef TLS_LEGACY_SUPPORT // TLS_V11 hash_state prec; - + memcpy(&prec, &hash->hash32, sizeof(hash_state)); md5_done(&hash->hash32, hout); memcpy(&hash->hash32, &prec, sizeof(hash_state)); - + memcpy(&prec, &hash->hash2, sizeof(hash_state)); sha1_done(&hash->hash2, hout + 16); memcpy(&hash->hash2, &prec, sizeof(hash_state)); - + hash_size = TLS_V11_HASH_SIZE; #endif } @@ -300848,7 +300868,7 @@ int _private_tls_write_packet(struct TLSPacket *packet) { struct TLSContext *context = packet->context; if (!context) return -1; - + if (context->tls_buffer) { int len = context->tls_buffer_len + packet->len; context->tls_buffer = (unsigned char *)TLS_REALLOC(context->tls_buffer, len); @@ -300876,7 +300896,7 @@ int _private_tls_write_app_data(struct TLSContext *context, const unsigned char return -1; if ((!buf) || (!buf_len)) return 0; - + int len = context->application_buffer_len + buf_len; context->application_buffer = (unsigned char *)TLS_REALLOC(context->application_buffer, len); if (!context->application_buffer) { @@ -300965,7 +300985,7 @@ int tls_established(struct TLSContext *context) { if (context) { if (context->critical_error) return -1; - + if (context->connection_status == 0xFF) return 1; @@ -300992,7 +301012,7 @@ int tls_read(struct TLSContext *context, unsigned char *buf, unsigned int size) if ((context->application_buffer) && (context->application_buffer_len)) { if (context->application_buffer_len < size) size = context->application_buffer_len; - + memcpy(buf, context->application_buffer, size); if (context->application_buffer_len == size) { TLS_FREE(context->application_buffer); @@ -301032,7 +301052,7 @@ const struct ECCCurveParameters *tls_set_curve(struct TLSContext *context, const struct TLSContext *tls_accept(struct TLSContext *context) { if ((!context) || (!context->is_server)) return NULL; - + struct TLSContext *child = (struct TLSContext *)TLS_MALLOC(sizeof(struct TLSContext)); if (child) { memset(child, 0, sizeof(struct TLSContext)); @@ -301093,13 +301113,13 @@ void _private_tls_ecc_dhe_create(struct TLSContext *context) { int tls_set_default_dhe_pg(struct TLSContext *context, const char *p_hex_str, const char *g_hex_str) { if ((!context) || (context->is_child) || (!context->is_server) || (!p_hex_str) || (!g_hex_str)) return 0; - + TLS_FREE(context->default_dhe_p); TLS_FREE(context->default_dhe_g); - + context->default_dhe_p = NULL; context->default_dhe_g = NULL; - + size_t p_len = strlen(p_hex_str); size_t g_len = strlen(g_hex_str); if ((p_len <= 0) || (g_len <= 0)) @@ -301110,10 +301130,10 @@ int tls_set_default_dhe_pg(struct TLSContext *context, const char *p_hex_str, co context->default_dhe_g = (char *)TLS_MALLOC(g_len + 1); if (!context->default_dhe_g) return 0; - + memcpy(context->default_dhe_p, p_hex_str, p_len); context->default_dhe_p[p_len] = 0; - + memcpy(context->default_dhe_g, g_hex_str, g_len); context->default_dhe_g[g_len] = 0; return 1; @@ -301613,10 +301633,10 @@ const char *tls_cipher_name(struct TLSContext *context) { #ifdef TLS_FORWARD_SECRECY int _private_tls_dh_export_Y(unsigned char *Ybuf, unsigned long *Ylen, DHKey *key) { unsigned long len; - + if ((Ybuf == NULL) || (Ylen == NULL) || (key == NULL)) return TLS_GENERIC_ERROR; - + len = mp_unsigned_bin_size(key->y); if (len > *Ylen) return TLS_GENERIC_ERROR; @@ -301628,37 +301648,37 @@ int _private_tls_dh_export_Y(unsigned char *Ybuf, unsigned long *Ylen, DHKey *ke int _private_tls_dh_export_pqY(unsigned char *pbuf, unsigned long *plen, unsigned char *gbuf, unsigned long *glen, unsigned char *Ybuf, unsigned long *Ylen, DHKey *key) { unsigned long len; int err; - + if ((pbuf == NULL) || (plen == NULL) || (gbuf == NULL) || (glen == NULL) || (Ybuf == NULL) || (Ylen == NULL) || (key == NULL)) return TLS_GENERIC_ERROR; - + len = mp_unsigned_bin_size(key->y); if (len > *Ylen) return TLS_GENERIC_ERROR; - + if ((err = mp_to_unsigned_bin(key->y, Ybuf)) != CRYPT_OK) return err; - + *Ylen = len; - + len = mp_unsigned_bin_size(key->p); if (len > *plen) return TLS_GENERIC_ERROR; - + if ((err = mp_to_unsigned_bin(key->p, pbuf)) != CRYPT_OK) return err; - + *plen = len; - + len = mp_unsigned_bin_size(key->g); if (len > *glen) return TLS_GENERIC_ERROR; - + if ((err = mp_to_unsigned_bin(key->g, gbuf)) != CRYPT_OK) return err; - + *glen = len; - + return 0; } @@ -301675,32 +301695,32 @@ int _private_tls_dh_make_key(int keysize, DHKey *key, const char *pbuf, const ch int err; if (!key) return TLS_GENERIC_ERROR; - + static prng_state prng; int wprng = find_prng("sprng"); if ((err = prng_is_valid(wprng)) != CRYPT_OK) return err; - + buf = (unsigned char *)TLS_MALLOC(keysize); if (!buf) return TLS_NO_MEMORY; - + if (rng_make_prng(keysize, wprng, &prng, NULL) != CRYPT_OK) { TLS_FREE(buf); return TLS_GENERIC_ERROR; } - + if (prng_descriptor[wprng].read(buf, keysize, &prng) != (unsigned long)keysize) { TLS_FREE(buf); return TLS_GENERIC_ERROR; } - + if ((err = mp_init_multi(&key->g, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) { TLS_FREE(buf); - + return TLS_GENERIC_ERROR; } - + if (gbuf_len <= 0) { if ((err = mp_read_radix(key->g, gbuf, 16)) != CRYPT_OK) { TLS_FREE(buf); @@ -301714,7 +301734,7 @@ int _private_tls_dh_make_key(int keysize, DHKey *key, const char *pbuf, const ch return TLS_GENERIC_ERROR; } } - + if (pbuf_len <= 0) { if ((err = mp_read_radix(key->p, pbuf, 16)) != CRYPT_OK) { TLS_FREE(buf); @@ -301728,19 +301748,19 @@ int _private_tls_dh_make_key(int keysize, DHKey *key, const char *pbuf, const ch return TLS_GENERIC_ERROR; } } - + if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) { TLS_FREE(buf); _private_tls_dh_clear_key(key); return TLS_GENERIC_ERROR; } - + if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { TLS_FREE(buf); _private_tls_dh_clear_key(key); return TLS_GENERIC_ERROR; } - + TLS_FREE(buf); return 0; } @@ -301773,7 +301793,7 @@ struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) { DEBUG_PRINT("CANNOT BUILD CLIENT KEY EXCHANGE MESSAGE FOR SERVERS\n"); return NULL; } - + struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 0); tls_packet_uint8(packet, 0x10); #ifdef TLS_FORWARD_SECRECY @@ -301786,7 +301806,7 @@ struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) { unsigned long dh_p_len = sizeof(dh_p); unsigned long dh_g_len = sizeof(dh_g); unsigned long dh_Ys_len = sizeof(dh_Ys); - + if (_private_tls_dh_export_pqY(dh_p, &dh_p_len, dh_g, &dh_g_len, dh_Ys, &dh_Ys_len, context->dhe)) { DEBUG_PRINT("ERROR EXPORTING DHE KEY %p\n", context->dhe); TLS_FREE(packet); @@ -301804,7 +301824,7 @@ struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) { if (context->ecc_dhe) { unsigned char out[TLS_MAX_RSA_KEY]; unsigned long out_len = TLS_MAX_RSA_KEY; - + if (ecc_ansi_x963_export(context->ecc_dhe, out, &out_len)) { DEBUG_PRINT("Error exporting ECC key\n"); TLS_FREE(packet); @@ -301818,7 +301838,7 @@ struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) { } tls_packet_uint8(packet, out_len); tls_packet_append(packet, out, out_len); - } + } #ifdef TLS_CURVE25519 else if ((context->curve == &x25519) && (context->client_secret)) { @@ -301861,7 +301881,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int DEBUG_PRINT("CANNOT BUILD SERVER KEY EXCHANGE MESSAGE FOR CLIENTS\n"); return NULL; } - + struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 0); tls_packet_uint8(packet, 0x0C); unsigned char dummy[3]; @@ -301873,7 +301893,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int if (method == KEA_dhe_rsa) { tls_init(); _private_tls_dhe_create(context); - + const char *default_dhe_p = context->default_dhe_p; const char *default_dhe_g = context->default_dhe_g; int key_size; @@ -301891,31 +301911,31 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int context->dhe = NULL; return NULL; } - + unsigned char dh_Ys[0xFFF]; unsigned char dh_p[0xFFF]; unsigned char dh_g[0xFFF]; unsigned long dh_p_len = sizeof(dh_p); unsigned long dh_g_len = sizeof(dh_g); unsigned long dh_Ys_len = sizeof(dh_Ys); - + if (_private_tls_dh_export_pqY(dh_p, &dh_p_len, dh_g, &dh_g_len, dh_Ys, &dh_Ys_len, context->dhe)) { DEBUG_PRINT("ERROR EXPORTING DHE KEY\n"); TLS_FREE(packet); return NULL; } - + DEBUG_PRINT("LEN: %lu (%lu, %lu)\n", dh_Ys_len, dh_p_len, dh_g_len); DEBUG_DUMP_HEX_LABEL("DHE PK", dh_Ys, dh_Ys_len); DEBUG_DUMP_HEX_LABEL("DHE P", dh_p, dh_p_len); DEBUG_DUMP_HEX_LABEL("DHE G", dh_g, dh_g_len); - + tls_packet_uint16(packet, dh_p_len); tls_packet_append(packet, dh_p, dh_p_len); - + tls_packet_uint16(packet, dh_g_len); tls_packet_append(packet, dh_g, dh_g_len); - + tls_packet_uint16(packet, dh_Ys_len); tls_packet_append(packet, dh_Ys, dh_Ys_len); //dh_p @@ -301930,9 +301950,9 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int tls_packet_uint16(packet, context->curve->iana); tls_init(); _private_tls_ecc_dhe_create(context); - + ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&context->curve->dp; - + if (ecc_make_key_ex(NULL, find_prng("sprng"), context->ecc_dhe, dp)) { TLS_FREE(context->ecc_dhe); context->ecc_dhe = NULL; @@ -301956,7 +301976,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int DEBUG_PRINT("Unsupported ephemeral method: %i\n", method); return NULL; } - + // signature unsigned int params_len = packet->len - start_len; unsigned int message_len = params_len + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE; @@ -301964,7 +301984,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int if (message) { unsigned char out[TLS_MAX_RSA_KEY]; unsigned long out_len = TLS_MAX_RSA_KEY; - + int hash_algorithm; if ((context->version != TLS_V13) && (context->version != DTLS_V13) && (context->version != TLS_V12) && (context->version != DTLS_V12)) { hash_algorithm = _md5_sha1; @@ -301973,7 +301993,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int hash_algorithm = sha256; else hash_algorithm = sha1; - + #ifdef TLS_ECDSA_SUPPORTED if (tls_is_ecdsa(context)) { if ((context->version == TLS_V13) || (context->version == DTLS_V13) || (context->version == TLS_V12) || (context->version == DTLS_V12)) @@ -301987,7 +302007,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int tls_packet_uint8(packet, rsa_sign); } } - + memcpy(message, context->remote_random, TLS_CLIENT_RANDOM_SIZE); memcpy(message + TLS_CLIENT_RANDOM_SIZE, context->local_random, TLS_SERVER_RANDOM_SIZE); memcpy(message + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE, packet->buf + start_len, params_len); @@ -302181,7 +302201,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad // fallback ... this should never happen if (!context->cipher) context->cipher = TLS_DHE_RSA_WITH_AES_128_CBC_SHA; - + tls_packet_uint16(packet, context->cipher); // no compression tls_packet_uint8(packet, 0); @@ -302191,7 +302211,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad #ifdef WITH_TLS_13 if ((context->version == TLS_V13) || (context->version == DTLS_V13)) { tls_packet_uint16(packet, extension_len); - } else + } else #endif { tls_packet_uint16(packet, 5 + extension_len); @@ -302369,7 +302389,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad int sni_len = 0; if (context->sni) sni_len = strlen(context->sni); - + #ifdef TLS_CLIENT_ECDHE extension_len += 12; #endif @@ -302386,7 +302406,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad } #endif tls_packet_uint16(packet, extension_len); - + if (sni_len) { // sni extension tls_packet_uint16(packet, 0x00); @@ -302498,9 +302518,9 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad tls_packet_uint16(packet, shared_key_short + 6); tls_packet_uint16(packet, shared_key_short + 4); - _private_tls_ecc_dhe_create(context); + _private_tls_ecc_dhe_create(context); ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&secp256r1.dp; - + if (ecc_make_key_ex(NULL, find_prng("sprng"), context->ecc_dhe, dp)) { TLS_FREE(context->ecc_dhe); context->ecc_dhe = NULL; @@ -302541,7 +302561,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad } } #endif - + if ((!packet->broken) && (packet->buf)) { int remaining = packet->len - start_len; int payload_pos = 6; @@ -302565,7 +302585,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad struct TLSPacket *tls_certificate_request(struct TLSContext *context) { if ((!context) || (!context->is_server)) return NULL; - + unsigned short packet_version = context->version; struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, packet_version, 0); if (packet) { @@ -302676,7 +302696,7 @@ int _private_dtls_build_cookie(struct TLSContext *context) { struct TLSPacket *tls_build_verify_request(struct TLSContext *context) { if ((!context->is_server) || (!context->dtls)) return NULL; - + if ((!context->dtls_cookie) || (!context->dtls_cookie_len)) { if (!_private_dtls_build_cookie(context)) return NULL; @@ -302923,7 +302943,7 @@ int _private_tls_parse_key_share(struct TLSContext *context, const unsigned char } out2 = (unsigned char *)TLS_MALLOC(key_size); out_size = key_size; - + int err = ecc_shared_secret(context->ecc_dhe, &client_key, out2, &out_size); ecc_free(&client_key); @@ -302982,7 +303002,7 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu DEBUG_PRINT("UNEXPECTED HELLO MESSAGE\n"); return TLS_UNEXPECTED_MESSAGE; } - + int res = 0; int downgraded = 0; int hello_min_size = context->dtls ? TLS_CLIENT_HELLO_MINSIZE + 8 : TLS_CLIENT_HELLO_MINSIZE; @@ -302998,11 +303018,11 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu res += 8; } CHECK_SIZE(bytes_to_follow, buf_len - res, TLS_NEED_MORE_DATA) - + CHECK_SIZE(2, buf_len - res, TLS_NEED_MORE_DATA) unsigned short version = ntohs(*(unsigned short *)&buf[res]); unsigned short cipher = 0; - + res += 2; VERSION_SUPPORTED(version, TLS_NOT_SAFE) DEBUG_PRINT("VERSION REQUIRED BY REMOTE %x, VERSION NOW %x\n", (int)version, (int)context->version); @@ -303027,7 +303047,7 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu #endif memcpy(context->remote_random, &buf[res], TLS_CLIENT_RANDOM_SIZE); res += TLS_CLIENT_RANDOM_SIZE; - + unsigned char session_len = buf[res++]; CHECK_SIZE(session_len, buf_len - res, TLS_NEED_MORE_DATA) if ((session_len) && (session_len <= TLS_MAX_SESSION_ID)) { @@ -303081,11 +303101,11 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu cipher_buffer = &buf[res]; res += cipher_len; - + CHECK_SIZE(1, buf_len - res, TLS_NEED_MORE_DATA) unsigned char compression_list_size = buf[res++]; CHECK_SIZE(compression_list_size, buf_len - res, TLS_NEED_MORE_DATA) - + // no compression support res += compression_list_size; } else { @@ -303108,15 +303128,15 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu return TLS_COMPRESSION_NOT_SUPPORTED; } } - + if (res > 0) { if (context->is_server) *write_packets = 2; if (context->connection_status != 4) context->connection_status = 1; } - - + + if (res > 2) res += 2; #ifdef WITH_TLS_13 @@ -303344,7 +303364,7 @@ int tls_parse_certificate(struct TLSContext *context, const unsigned char *buf, int res = 0; CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA) unsigned int size_of_all_certificates = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; - + if (size_of_all_certificates <= 4) return 3 + size_of_all_certificates; res += 3; @@ -303366,7 +303386,7 @@ int tls_parse_certificate(struct TLSContext *context, const unsigned char *buf, CHECK_SIZE(size_of_all_certificates, buf_len - res, TLS_NEED_MORE_DATA); int size = size_of_all_certificates; - + int idx = 0; int valid_certificate = 0; while (size > 0) { @@ -303391,7 +303411,7 @@ int tls_parse_certificate(struct TLSContext *context, const unsigned char *buf, break; } remaining -= certificate_size2; - + struct TLSCertificate *cert = asn1_parse(context, &buf[res2], certificate_size2, is_client); if (cert) { if (certificate_size2) { @@ -303476,7 +303496,7 @@ int _private_tls_parse_random(struct TLSContext *context, const unsigned char *b size = ntohs(*(unsigned short *)buf); res += 2; } - + CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA) unsigned int out_len = 0; unsigned char *random = NULL; @@ -303492,7 +303512,7 @@ int _private_tls_parse_random(struct TLSContext *context, const unsigned char *b default: random = _private_tls_decrypt_rsa(context, &buf[res], size, &out_len); } - + if ((random) && (out_len > 2)) { DEBUG_DUMP_HEX_LABEL("PRE MASTER KEY", random, out_len); TLS_FREE(context->premaster_key); @@ -303513,7 +303533,7 @@ int _private_tls_build_random(struct TLSPacket *packet) { int bytes = 48; if (!tls_random(rand_bytes, bytes)) return TLS_GENERIC_ERROR; - + // max supported version if (packet->context->is_server) *(unsigned short *)rand_bytes = htons(packet->context->version); @@ -303523,18 +303543,18 @@ int _private_tls_build_random(struct TLSPacket *packet) { else *(unsigned short *)rand_bytes = htons(TLS_V12); //DEBUG_DUMP_HEX_LABEL("PREMASTER KEY", rand_bytes, bytes); - + TLS_FREE(packet->context->premaster_key); packet->context->premaster_key = (unsigned char *)TLS_MALLOC(bytes); if (!packet->context->premaster_key) return TLS_NO_MEMORY; - + packet->context->premaster_key_len = bytes; memcpy(packet->context->premaster_key, rand_bytes, packet->context->premaster_key_len); - + unsigned int out_len; unsigned char *random = _private_tls_encrypt_rsa(packet->context, packet->context->premaster_key, packet->context->premaster_key_len, &out_len); - + _private_tls_compute_key(packet->context, bytes); if ((random) && (out_len > 2)) { tls_packet_uint24(packet, out_len + 2); @@ -303547,7 +303567,7 @@ int _private_tls_build_random(struct TLSPacket *packet) { TLS_FREE(random); if (res) return res; - + return out_len + 2; } @@ -303586,10 +303606,10 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha } const unsigned char *packet_ref = buf + res; CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA); - + if (!size) return res; - + unsigned char has_ds_params = 0; unsigned int key_size = 0; #ifdef TLS_FORWARD_SECRECY @@ -303662,14 +303682,14 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha return TLS_BROKEN_PACKET; res += dh_res; DEBUG_PRINT("\n"); - + DEBUG_PRINT(" dh_q: "); dh_res = _private_tls_parse_dh(&buf[res], buf_len - res, &dh_g, &dh_g_len); if (dh_res <= 0) return TLS_BROKEN_PACKET; res += dh_res; DEBUG_PRINT("\n"); - + DEBUG_PRINT(" dh_Ys: "); dh_res = _private_tls_parse_dh(&buf[res], buf_len - res, &dh_Ys, &dh_Ys_len); if (dh_res <= 0) @@ -303693,7 +303713,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha // check signature unsigned int message_len = packet_size + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE; unsigned char *message = (unsigned char *)TLS_MALLOC(message_len); - if (message) { + if (message) { memcpy(message, context->local_random, TLS_CLIENT_RANDOM_SIZE); memcpy(message + TLS_CLIENT_RANDOM_SIZE, context->remote_random, TLS_SERVER_RANDOM_SIZE); memcpy(message + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE, packet_ref, packet_size); @@ -303704,7 +303724,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha TLS_FREE(message); return TLS_BROKEN_PACKET; } - } else + } else #endif { if (_private_tls_verify_rsa(context, hash_algorithm, signature, sign_size, message, message_len) != 1) { @@ -303715,7 +303735,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha } TLS_FREE(message); } - + if (buf_len - res) { DEBUG_PRINT("EXTRA %i BYTES AT THE END OF MESSAGE\n", buf_len - res); DEBUG_DUMP_HEX(&buf[res], buf_len - res); @@ -303735,7 +303755,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha context->dhe = NULL; return TLS_GENERIC_ERROR; } - + unsigned int dh_key_size = 0; unsigned char *key = _private_tls_decrypt_dhe(context, dh_Ys, dh_Ys_len, &dh_key_size, 0); DEBUG_DUMP_HEX_LABEL("DH COMMON SECRET", key, dh_key_size); @@ -303759,7 +303779,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha DEBUG_PRINT("ERROR IN TLS_MALLOC"); return TLS_GENERIC_ERROR; } - + tls_random(context->client_secret, 32); context->client_secret[0] &= 248; @@ -303778,7 +303798,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha { tls_init(); _private_tls_ecc_dhe_create(context); - + ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&curve->dp; if (ecc_make_key_ex(NULL, find_prng("sprng"), context->ecc_dhe, dp)) { TLS_FREE(context->ecc_dhe); @@ -303786,10 +303806,10 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha DEBUG_PRINT("Error generating ECC key\n"); return TLS_GENERIC_ERROR; } - + TLS_FREE(context->premaster_key); context->premaster_key_len = 0; - + unsigned int out_len = 0; context->premaster_key = _private_tls_decrypt_ecc_dhe(context, pk_key, key_size, &out_len, 0); if (context->premaster_key) @@ -303809,7 +303829,7 @@ int tls_parse_client_key_exchange(struct TLSContext *context, const unsigned cha int res = 0; int dh_res = 0; CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA) - + unsigned int size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; res += 3; if (context->dtls) { @@ -303823,14 +303843,14 @@ int tls_parse_client_key_exchange(struct TLSContext *context, const unsigned cha if (!size) return res; - + dh_res = _private_tls_parse_random(context, &buf[res], size); if (dh_res <= 0) { DEBUG_PRINT("broken key\n"); return TLS_BROKEN_PACKET; } DEBUG_PRINT("\n"); - + res += size; context->connection_status = 2; return res; @@ -303839,7 +303859,7 @@ int tls_parse_client_key_exchange(struct TLSContext *context, const unsigned cha int tls_parse_server_hello_done(struct TLSContext *context, const unsigned char *buf, int buf_len) { int res = 0; CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA) - + unsigned int size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; res += 3; if (context->dtls) { @@ -303848,9 +303868,9 @@ int tls_parse_server_hello_done(struct TLSContext *context, const unsigned char return dtls_check; res += 8; } - + CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA); - + res += size; return res; } @@ -303860,11 +303880,11 @@ int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int DEBUG_PRINT("UNEXPECTED FINISHED MESSAGE\n"); return TLS_UNEXPECTED_MESSAGE; } - + int res = 0; *write_packets = 0; CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA) - + unsigned int size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; res += 3; if (context->dtls) { @@ -303873,14 +303893,14 @@ int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int return dtls_check; res += 8; } - + if (size < TLS_MIN_FINISHED_OPAQUE_LEN) { DEBUG_PRINT("Invalid finished pachet size: %i\n", size); return TLS_BROKEN_PACKET; } - + CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA); - + unsigned char hash[TLS_MAX_SHA_SIZE]; unsigned int hash_len = _private_tls_get_hash(context, hash); @@ -303926,13 +303946,13 @@ int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int DEBUG_PRINT("Error in TLS_MALLOC (%i bytes)\n", (int)size); return TLS_NO_MEMORY; } - + // server verifies client's message if (context->is_server) _private_tls_prf(context, out, size, context->master_key, context->master_key_len, (unsigned char *)"client finished", 15, hash, hash_len, NULL, 0); else _private_tls_prf(context, out, size, context->master_key, context->master_key_len, (unsigned char *)"server finished", 15, hash, hash_len, NULL, 0); - + if (memcmp(out, &buf[res], size)) { TLS_FREE(out); DEBUG_PRINT("Finished validation error (sequence number, local: %i, remote: %i)\n", (int)context->local_sequence_number, (int)context->remote_sequence_number); @@ -303974,7 +303994,7 @@ int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int int tls_parse_verify_tls13(struct TLSContext *context, const unsigned char *buf, int buf_len) { CHECK_SIZE(7, buf_len, TLS_NEED_MORE_DATA) unsigned int size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; - + if (size < 2) return buf_len; @@ -304047,7 +304067,7 @@ int tls_parse_verify(struct TLSContext *context, const unsigned char *buf, int b CHECK_SIZE(size, bytes_to_follow - 4, TLS_BAD_CERTIFICATE) DEBUG_PRINT("ALGORITHM %i/%i (%i)\n", hash, algorithm, (int)size); DEBUG_DUMP_HEX_LABEL("VERIFY", &buf[7], bytes_to_follow - 7); - + res = _private_tls_verify_rsa(context, hash, &buf[7], size, context->cached_handshake, context->cached_handshake_len); } else { #ifdef TLS_LEGACY_SUPPORT @@ -304280,12 +304300,12 @@ int tls_parse_payload(struct TLSContext *context, const unsigned char *buf, int } if ((type != 0x00) && (update_hash)) _private_tls_update_hash(context, buf, payload_size + 1); - + if (certificate_verify_alert != no_error) { _private_tls_write_packet(tls_build_alert(context, 1, certificate_verify_alert)); context->critical_error = 1; } - + if (payload_res < 0) { switch (payload_res) { case TLS_UNEXPECTED_MESSAGE: @@ -304333,7 +304353,7 @@ int tls_parse_payload(struct TLSContext *context, const unsigned char *buf, int } if (certificate_verify_alert != no_error) payload_res = TLS_BAD_CERTIFICATE; - + // except renegotiation switch (write_packets) { case 1: @@ -304461,7 +304481,7 @@ unsigned int _private_tls_hmac_message(unsigned char local, struct TLSContext *c hash_idx = find_hash("sha384"); else hash_idx = find_hash("sha256"); - + if (hmac_init(&hash, hash_idx, local ? context->crypto.ctx_local_mac.local_mac : context->crypto.ctx_remote_mac.remote_mac, mac_size)) return 0; @@ -304476,7 +304496,7 @@ unsigned int _private_tls_hmac_message(unsigned char local, struct TLSContext *c if (hmac_process(&hash, (unsigned char *)&squence_number, sizeof(uint64_t))) return 0; - + if (hmac_process(&hash, buf, buf_len)) return 0; if ((buf2) && (buf_len2)) { @@ -304486,7 +304506,7 @@ unsigned int _private_tls_hmac_message(unsigned char local, struct TLSContext *c unsigned long ref_outlen = outlen; if (hmac_done(&hash, out, &ref_outlen)) return 0; - + return (unsigned int)ref_outlen; } @@ -304496,9 +304516,9 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le res = 13; int header_size = res; int payload_res = 0; - + CHECK_SIZE(res, buf_len, TLS_NEED_MORE_DATA) - + unsigned char type = *buf; int buf_pos = 1; @@ -304593,7 +304613,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le } DEBUG_DUMP_HEX_LABEL("aad", aad, aad_size); DEBUG_DUMP_HEX_LABEL("aad iv", iv, 12); - + int res0 = gcm_add_iv(&context->crypto.ctx_remote.aes_gcm_remote, iv, 12); int res1 = gcm_add_aad(&context->crypto.ctx_remote.aes_gcm_remote, aad, aad_size); memset(pt, 0, length); @@ -304684,7 +304704,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le rem = pt_length % 16; if (rem) _private_tls_poly1305_update(&ctx, zeropad, 16 - rem); - + _private_tls_U32TO8(&trail[0], aad_size == 5 ? 5 : 13); *(int *)&trail[4] = 0; _private_tls_U32TO8(&trail[8], pt_length); @@ -304717,7 +304737,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le } unsigned char padding_byte = pt[length - 1]; unsigned char padding = padding_byte + 1; - + // poodle check int padding_index = length - padding; if (padding_index > 0) { @@ -304733,11 +304753,11 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le } } } - + unsigned int decrypted_length = length; if (padding < decrypted_length) decrypted_length -= padding; - + DEBUG_DUMP_HEX_LABEL("decrypted", pt, decrypted_length); ptr = pt; #ifdef TLS_LEGACY_SUPPORT @@ -304752,7 +304772,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le } #endif length = decrypted_length; - + unsigned int mac_size = _private_tls_mac_length(context); if ((length < mac_size) || (!mac_size)) { TLS_FREE(pt); @@ -304761,9 +304781,9 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le _private_tls_write_packet(tls_build_alert(context, 1, decrypt_error)); return TLS_BROKEN_PACKET; } - + length -= mac_size; - + const unsigned char *message_hmac = &ptr[length]; unsigned char hmac_out[TLS_MAX_MAC_SIZE]; unsigned char temp_buf[5]; @@ -304861,22 +304881,22 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le return TLS_NOT_UNDERSTOOD; } TLS_FREE(pt); - + if (payload_res < 0) return payload_res; - + if (res > 0) return header_size + length; - + return res; } unsigned int asn1_get_len(const unsigned char *buffer, int buf_len, unsigned int *octets) { *octets = 0; - + if (buf_len < 1) return 0; - + unsigned char size = buffer[0]; int i; if (size & 0x80) { @@ -304891,7 +304911,7 @@ unsigned int asn1_get_len(const unsigned char *buffer, int buf_len, unsigned int return 0; unsigned int long_size = 0; unsigned int coef = 1; - + for (i = ref_octets; i > 0; i--) { long_size += buffer[i] * coef; coef *= 0x100; @@ -304956,7 +304976,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(16); if (!hash) return NULL; - + err = md5_init(&state); if (!err) { err = md5_process(&state, message, message_len); @@ -304969,7 +304989,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(20); if (!hash) return NULL; - + err = sha1_init(&state); if (!err) { err = sha1_process(&state, message, message_len); @@ -304983,7 +305003,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(32); if (!hash) return NULL; - + err = sha256_init(&state); if (!err) { err = sha256_process(&state, message, message_len); @@ -304996,7 +305016,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(48); if (!hash) return NULL; - + err = sha384_init(&state); if (!err) { err = sha384_process(&state, message, message_len); @@ -305009,7 +305029,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(64); if (!hash) return NULL; - + err = sha512_init(&state); if (!err) { err = sha512_process(&state, message, message_len); @@ -305032,7 +305052,7 @@ int tls_certificate_verify_signature(struct TLSCertificate *cert, struct TLSCert int hash_len = _private_tls_hash_len(cert->algorithm); if (hash_len <= 0) return 0; - + int hash_index = -1; switch (cert->algorithm) { case TLS_RSA_SIGN_MD5: @@ -305081,7 +305101,7 @@ int tls_certificate_verify_signature(struct TLSCertificate *cert, struct TLSCert return ecc_stat; } #endif - + rsa_key key; int err = rsa_import(parent->der_bytes, parent->der_len, &key); if (err) { @@ -305109,14 +305129,14 @@ int tls_certificate_verify_signature(struct TLSCertificate *cert, struct TLSCert int tls_certificate_chain_is_valid(struct TLSCertificate **certificates, int len) { if ((!certificates) || (!len)) return bad_certificate; - + int i; len--; - + // expired certificate or not yet valid ? if (tls_certificate_is_valid(certificates[0])) return bad_certificate; - + // check for (i = 0; i < len; i++) { // certificate in chain is expired ? @@ -305199,7 +305219,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, for (i1 = 1; i1 < level; i1++) DEBUG_PRINT(" "); #endif - + if ((length) && (constructed)) { switch (type) { case 0x03: @@ -305263,7 +305283,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, if (_is_field(fields, pk_id)) { if (has_key) *has_key = 1; - + if (idx == 1) tls_certificate_set_key(cert, &buffer[pos], length); else @@ -305308,7 +305328,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, case 0x03: if (_is_field(fields, pk_id)) { if (has_key) - *has_key = 1; + *has_key = 1; } // bitstream DEBUG_PRINT("BITSTREAM(%i): ", length); @@ -305370,7 +305390,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, } if (_is_field(fields, algorithm_id)) tls_certificate_set_algorithm(context, &cert->algorithm, &buffer[pos], length); - + DEBUG_PRINT("OBJECT IDENTIFIER(%i): ", length); DEBUG_DUMP_HEX(&buffer[pos], length); DEBUG_PRINT("\n"); @@ -305395,7 +305415,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, DEBUG_PRINT("UTC TIME: ["); DEBUG_DUMP(&buffer[pos], length); DEBUG_PRINT("]\n"); - + if (_is_field(fields, validity_id)) { if (idx == 1) tls_certificate_set_copy_date(&cert->not_before, &buffer[pos], length); @@ -305505,7 +305525,7 @@ struct TLSCertificate *asn1_parse(struct TLSContext *context, const unsigned cha int tls_load_certificates(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size) { if (!context) return TLS_GENERIC_ERROR; - + unsigned int len; int idx = 0; do { @@ -305514,7 +305534,7 @@ int tls_load_certificates(struct TLSContext *context, const unsigned char *pem_b break; struct TLSCertificate *cert = asn1_parse(context, data, len, 0); if (cert) { - if ((cert->version == 2) + if ((cert->version == 2) #ifdef TLS_X509_V1_SUPPORT || (cert->version == 0) #endif @@ -305553,7 +305573,7 @@ int tls_load_certificates(struct TLSContext *context, const unsigned char *pem_b int tls_load_private_key(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size) { if (!context) return TLS_GENERIC_ERROR; - + unsigned int len; int idx = 0; do { @@ -305844,7 +305864,7 @@ struct TLSPacket *tls_build_finished(struct TLSContext *context) { unsigned char out[TLS_MIN_FINISHED_OPAQUE_LEN]; #endif unsigned int hash_len; - + // server verifies client's message if (context->is_server) { #ifdef WITH_TLS_13 @@ -305959,7 +305979,7 @@ struct TLSPacket *tls_build_message(struct TLSContext *context, const unsigned c int tls_client_connect(struct TLSContext *context) { if ((context->is_server) || (context->critical_error)) return TLS_UNEXPECTED_MESSAGE; - + return _private_tls_write_packet(tls_build_hello(context, 0)); } @@ -306030,7 +306050,7 @@ int tls_consume_stream(struct TLSContext *context, const unsigned char *buf, int unsigned int index = 0; unsigned int tls_buffer_len = context->message_buffer_len; int err_flag = 0; - + int tls_header_size; int tls_size_offset; @@ -306123,7 +306143,7 @@ int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsign DEBUG_PRINT("CANNOT EXPORT CONTEXT %i\n", (int)context->connection_status); return 0; } - + struct TLSPacket *packet = tls_create_packet(NULL, TLS_SERIALIZED_OBJECT, context->version, 0); // export buffer version tls_packet_uint8(packet, 0x01); @@ -306133,7 +306153,7 @@ int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsign tls_packet_uint8(packet, 2); else tls_packet_uint8(packet, context->is_server); - + if (context->crypto.created == 2) { // aead #ifdef WITH_TLS_13 @@ -306160,20 +306180,20 @@ int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsign } else { unsigned char iv[TLS_AES_IV_LENGTH]; unsigned long len = TLS_AES_IV_LENGTH; - + memset(iv, 0, TLS_AES_IV_LENGTH); cbc_getiv(iv, &len, &context->crypto.ctx_local.aes_local); tls_packet_uint8(packet, TLS_AES_IV_LENGTH); tls_packet_append(packet, iv, len); - + memset(iv, 0, TLS_AES_IV_LENGTH); cbc_getiv(iv, &len, &context->crypto.ctx_remote.aes_remote); tls_packet_append(packet, iv, TLS_AES_IV_LENGTH); } - + tls_packet_uint8(packet, context->exportable_size); tls_packet_append(packet, context->exportable_keys, context->exportable_size); - + if (context->crypto.created == 2) { tls_packet_uint8(packet, 0); #ifdef TLS_WITH_CHACHA20_POLY1305 @@ -306195,25 +306215,25 @@ int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsign tls_packet_append(packet, context->crypto.ctx_local_mac.local_mac, mac_length); tls_packet_append(packet, context->crypto.ctx_remote_mac.remote_mac, mac_length); } - + if (small_version) { tls_packet_uint16(packet, 0); } else { tls_packet_uint16(packet, context->master_key_len); tls_packet_append(packet, context->master_key, context->master_key_len); } - + uint64_t sequence_number = htonll(context->local_sequence_number); tls_packet_append(packet, (unsigned char *)&sequence_number, sizeof(uint64_t)); sequence_number = htonll(context->remote_sequence_number); tls_packet_append(packet, (unsigned char *)&sequence_number, sizeof(uint64_t)); - + tls_packet_uint32(packet, context->tls_buffer_len); tls_packet_append(packet, context->tls_buffer, context->tls_buffer_len); - + tls_packet_uint32(packet, context->message_buffer_len); tls_packet_append(packet, context->message_buffer, context->message_buffer_len); - + tls_packet_uint32(packet, context->application_buffer_len); tls_packet_append(packet, context->application_buffer, context->application_buffer_len); tls_packet_uint8(packet, context->dtls); @@ -306259,7 +306279,7 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int context->is_child = 1; } else context->is_server = server; - + unsigned char local_iv[TLS_AES_IV_LENGTH]; unsigned char remote_iv[TLS_AES_IV_LENGTH]; unsigned char iv_len = buffer[10]; @@ -306268,14 +306288,14 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int tls_destroy_context(context); return NULL; } - + // get the initialization vectors int buf_pos = 11; memcpy(local_iv, &buffer[buf_pos], iv_len); buf_pos += iv_len; memcpy(remote_iv, &buffer[buf_pos], iv_len); buf_pos += iv_len; - + unsigned char key_lengths = buffer[buf_pos++]; TLS_IMPORT_CHECK_SIZE(buf_pos, key_lengths, buf_len) memcpy(temp, &buffer[buf_pos], key_lengths); @@ -306329,19 +306349,19 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int } } memset(temp, 0, sizeof(temp)); - + unsigned char mac_length = buffer[buf_pos++]; if (mac_length > TLS_MAX_MAC_SIZE) { DEBUG_PRINT("INVALID MAC SIZE\n"); tls_destroy_context(context); return NULL; } - + if (mac_length) { TLS_IMPORT_CHECK_SIZE(buf_pos, mac_length, buf_len) memcpy(context->crypto.ctx_local_mac.local_mac, &buffer[buf_pos], mac_length); buf_pos += mac_length; - + TLS_IMPORT_CHECK_SIZE(buf_pos, mac_length, buf_len) memcpy(context->crypto.ctx_remote_mac.remote_mac, &buffer[buf_pos], mac_length); buf_pos += mac_length; @@ -306365,7 +306385,7 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int buf_pos += CHACHA_BLOCKLEN; } #endif - + TLS_IMPORT_CHECK_SIZE(buf_pos, 2, buf_len) unsigned short master_key_len = ntohs(*(unsigned short *)(buffer + buf_pos)); buf_pos += 2; @@ -306378,14 +306398,14 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int } buf_pos += master_key_len; } - + TLS_IMPORT_CHECK_SIZE(buf_pos, 16, buf_len) - + context->local_sequence_number = ntohll(*(uint64_t *)&buffer[buf_pos]); buf_pos += 8; context->remote_sequence_number = ntohll(*(uint64_t *)&buffer[buf_pos]); buf_pos += 8; - + TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len) unsigned int tls_buffer_len = ntohl(*(unsigned int *)&buffer[buf_pos]); buf_pos += 4; @@ -306398,7 +306418,7 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int } buf_pos += tls_buffer_len; } - + TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len) unsigned int message_buffer_len = ntohl(*(unsigned int *)&buffer[buf_pos]); buf_pos += 4; @@ -306411,7 +306431,7 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int } buf_pos += message_buffer_len; } - + TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len) unsigned int application_buffer_len = ntohl(*(unsigned int *)&buffer[buf_pos]); buf_pos += 4; @@ -306447,7 +306467,7 @@ int tls_is_broken(struct TLSContext *context) { int tls_request_client_certificate(struct TLSContext *context) { if ((!context) || (!context->is_server)) return 0; - + context->request_client_certificate = 1; return 1; } @@ -306455,7 +306475,7 @@ int tls_request_client_certificate(struct TLSContext *context) { int tls_client_verified(struct TLSContext *context) { if ((!context) || (context->critical_error)) return 0; - + return (context->client_verified == 1); } @@ -306487,17 +306507,17 @@ int tls_sni_set(struct TLSContext *context, const char *sni) { int tls_load_root_certificates(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size) { if (!context) return TLS_GENERIC_ERROR; - + unsigned int len; int idx = 0; - + do { unsigned char *data = tls_pem_decode(pem_buffer, pem_size, idx++, &len); if ((!data) || (!len)) break; struct TLSCertificate *cert = asn1_parse(NULL, data, len, 0); if (cert) { - if ((cert->version == 2) + if ((cert->version == 2) #ifdef TLS_X509_V1_SUPPORT || (cert->version == 0) #endif @@ -306529,7 +306549,7 @@ int tls_load_root_certificates(struct TLSContext *context, const unsigned char * int tls_default_verify(struct TLSContext *context, struct TLSCertificate **certificate_chain, int len) { int i; int err; - + if (certificate_chain) { for (i = 0; i < len; i++) { struct TLSCertificate *certificate = certificate_chain[i]; @@ -306543,18 +306563,18 @@ int tls_default_verify(struct TLSContext *context, struct TLSCertificate **certi err = tls_certificate_chain_is_valid(certificate_chain, len); if (err) return err; - + // check certificate subject if ((!context->is_server) && (context->sni) && (len > 0) && (certificate_chain)) { err = tls_certificate_valid_subject(certificate_chain[0], context->sni); if (err) return err; } - + err = tls_certificate_chain_is_valid_root(context, certificate_chain, len); if (err) return err; - + DEBUG_PRINT("Certificate OK\n"); return no_error; } @@ -306803,7 +306823,7 @@ int SSL_CTX_use_PrivateKey_file(struct TLSContext *context, const char *filename int size = _private_tls_read_from_file(filename, buf, sizeof(buf)); if (size > 0) return tls_load_private_key(context, buf, size); - + return size; } @@ -306879,14 +306899,14 @@ void *SSL_userdata(struct TLSContext *context) { SSLUserData *ssl_data = (SSLUserData *)context->user_data; if (!ssl_data) return NULL; - + return ssl_data->user_data; } int SSL_CTX_root_ca(struct TLSContext *context, const char *pem_filename) { if (!context) return TLS_GENERIC_ERROR; - + int count = TLS_GENERIC_ERROR; FILE *f = fopen(pem_filename, "rb"); if (f) { @@ -306987,7 +307007,7 @@ int SSL_connect(struct TLSContext *context) { res = _tls_ssl_private_send_pending(ssl_data->fd, context); if (res < 0) return res; - + int read_size; unsigned char client_message[0xFFFF]; @@ -307011,7 +307031,7 @@ int SSL_shutdown(struct TLSContext *context) { SSLUserData *ssl_data = (SSLUserData *)context->user_data; if ((!ssl_data) || (ssl_data->fd < 0)) return TLS_GENERIC_ERROR; - + tls_close_notify(context); return 0; } @@ -307022,7 +307042,7 @@ int SSL_write(struct TLSContext *context, const void *buf, unsigned int len) { SSLUserData *ssl_data = (SSLUserData *)context->user_data; if ((!ssl_data) || (ssl_data->fd < 0)) return TLS_GENERIC_ERROR; - + int written_size = tls_write(context, (const unsigned char *)buf, len); if (written_size > 0) { int res = _tls_ssl_private_send_pending(ssl_data->fd, context); @@ -307035,7 +307055,7 @@ int SSL_write(struct TLSContext *context, const void *buf, unsigned int len) { int SSL_read(struct TLSContext *context, void *buf, unsigned int len) { if (!context) return TLS_GENERIC_ERROR; - + if (context->application_buffer_len) return tls_read(context, (unsigned char *)buf, len); @@ -307044,7 +307064,7 @@ int SSL_read(struct TLSContext *context, void *buf, unsigned int len) { return TLS_GENERIC_ERROR; if (tls_established(context) != 1) return TLS_GENERIC_ERROR; - + unsigned char client_message[0xFFFF]; // accept int read_size; @@ -307057,7 +307077,7 @@ int SSL_read(struct TLSContext *context, void *buf, unsigned int len) { } if ((read_size <= 0) && (!context->application_buffer_len)) return read_size; - + return tls_read(context, (unsigned char *)buf, len); } @@ -331879,6 +331899,15 @@ API void ProgressiveMesh(int vert_n, int vert_stride, const float *v, int tri_n, */ #line 0 #define expr expr2 // 3rd_lua.h +#define EVAL_EXTEND_CONSTANTS \ + for( int vk = input_enum(id), *once = &vk; once; once = 0) \ + if( vk >= 0 ) push(ev, vk); +#define EVAL_EXTEND_FUNCTIONS \ + /**/ if(!strcmp(id, "input") && nargs ==1) push(ev, input(pop(ev))); \ + else if(!strcmp(id, "down") && nargs ==1) push(ev, input_down(pop(ev))); \ + else if(!strcmp(id, "held") && nargs ==1) push(ev, input_held(pop(ev))); \ + else if(!strcmp(id, "up") && nargs ==1) push(ev, input_up(pop(ev))); \ + else if(!strcmp(id, "idle") && nargs ==1) push(ev, input_idle(pop(ev))); #line 1 "engine/split/3rd_eval.h" /* A mathematical expression evaluator. * It uses a recursive descent parser internally. @@ -332389,19 +332418,1499 @@ int main() { } #endif #line 0 -// #define SQLITE_OMIT_LOAD_EXTENSION -// #define SQLITE_CORE 1 -// #define SQLITE_DEBUG 1 -// #define Token SQToken -// #define Table SQTable -// #define rehash sqlite3__rehash -// #undef NB -//{{FILE/*:*/3rd_sqlite3.c}} -// #undef Token -// #undef Table -// #undef rehash -// #undef NB -// #undef threadid +#line 1 "engine/split/3rd_luadebugger.h" +/* + Copyright (c) 2023 Scott Lembcke and Howling Moon Software + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#include +#include +#include +#include + +//#include +//#include + +static const char DEBUGGER_SRC[] = { +/*000000*/ 0x2d,0x2d,0x5b,0x5b,0x0d,0x0a,0x09,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74, +/*000010*/ 0x20,0x28,0x63,0x29,0x20,0x32,0x30,0x32,0x33,0x20,0x53,0x63,0x6f,0x74,0x74,0x20, +/*000020*/ 0x4c,0x65,0x6d,0x62,0x63,0x6b,0x65,0x20,0x61,0x6e,0x64,0x20,0x48,0x6f,0x77,0x6c, +/*000030*/ 0x69,0x6e,0x67,0x20,0x4d,0x6f,0x6f,0x6e,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72, +/*000040*/ 0x65,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x50,0x65,0x72,0x6d,0x69,0x73,0x73,0x69,0x6f, +/*000050*/ 0x6e,0x20,0x69,0x73,0x20,0x68,0x65,0x72,0x65,0x62,0x79,0x20,0x67,0x72,0x61,0x6e, +/*000060*/ 0x74,0x65,0x64,0x2c,0x20,0x66,0x72,0x65,0x65,0x20,0x6f,0x66,0x20,0x63,0x68,0x61, +/*000070*/ 0x72,0x67,0x65,0x2c,0x20,0x74,0x6f,0x20,0x61,0x6e,0x79,0x20,0x70,0x65,0x72,0x73, +/*000080*/ 0x6f,0x6e,0x20,0x6f,0x62,0x74,0x61,0x69,0x6e,0x69,0x6e,0x67,0x20,0x61,0x20,0x63, +/*000090*/ 0x6f,0x70,0x79,0x0d,0x0a,0x09,0x6f,0x66,0x20,0x74,0x68,0x69,0x73,0x20,0x73,0x6f, +/*0000a0*/ 0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x61,0x6e,0x64,0x20,0x61,0x73,0x73,0x6f,0x63, +/*0000b0*/ 0x69,0x61,0x74,0x65,0x64,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x61,0x74, +/*0000c0*/ 0x69,0x6f,0x6e,0x20,0x66,0x69,0x6c,0x65,0x73,0x20,0x28,0x74,0x68,0x65,0x20,0x22, +/*0000d0*/ 0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x22,0x29,0x2c,0x20,0x74,0x6f,0x20,0x64, +/*0000e0*/ 0x65,0x61,0x6c,0x0d,0x0a,0x09,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x53,0x6f,0x66, +/*0000f0*/ 0x74,0x77,0x61,0x72,0x65,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x72,0x65, +/*000100*/ 0x73,0x74,0x72,0x69,0x63,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x69,0x6e,0x63,0x6c,0x75, +/*000110*/ 0x64,0x69,0x6e,0x67,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x6c,0x69,0x6d, +/*000120*/ 0x69,0x74,0x61,0x74,0x69,0x6f,0x6e,0x20,0x74,0x68,0x65,0x20,0x72,0x69,0x67,0x68, +/*000130*/ 0x74,0x73,0x0d,0x0a,0x09,0x74,0x6f,0x20,0x75,0x73,0x65,0x2c,0x20,0x63,0x6f,0x70, +/*000140*/ 0x79,0x2c,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x2c,0x20,0x6d,0x65,0x72,0x67,0x65, +/*000150*/ 0x2c,0x20,0x70,0x75,0x62,0x6c,0x69,0x73,0x68,0x2c,0x20,0x64,0x69,0x73,0x74,0x72, +/*000160*/ 0x69,0x62,0x75,0x74,0x65,0x2c,0x20,0x73,0x75,0x62,0x6c,0x69,0x63,0x65,0x6e,0x73, +/*000170*/ 0x65,0x2c,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x73,0x65,0x6c,0x6c,0x0d,0x0a, +/*000180*/ 0x09,0x63,0x6f,0x70,0x69,0x65,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x53, +/*000190*/ 0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x2c,0x20,0x61,0x6e,0x64,0x20,0x74,0x6f,0x20, +/*0001a0*/ 0x70,0x65,0x72,0x6d,0x69,0x74,0x20,0x70,0x65,0x72,0x73,0x6f,0x6e,0x73,0x20,0x74, +/*0001b0*/ 0x6f,0x20,0x77,0x68,0x6f,0x6d,0x20,0x74,0x68,0x65,0x20,0x53,0x6f,0x66,0x74,0x77, +/*0001c0*/ 0x61,0x72,0x65,0x20,0x69,0x73,0x0d,0x0a,0x09,0x66,0x75,0x72,0x6e,0x69,0x73,0x68, +/*0001d0*/ 0x65,0x64,0x20,0x74,0x6f,0x20,0x64,0x6f,0x20,0x73,0x6f,0x2c,0x20,0x73,0x75,0x62, +/*0001e0*/ 0x6a,0x65,0x63,0x74,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x66,0x6f,0x6c,0x6c, +/*0001f0*/ 0x6f,0x77,0x69,0x6e,0x67,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x73, +/*000200*/ 0x3a,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x54,0x68,0x65,0x20,0x61,0x62,0x6f,0x76,0x65, +/*000210*/ 0x20,0x63,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x6e,0x6f,0x74,0x69,0x63, +/*000220*/ 0x65,0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x65,0x72,0x6d,0x69, +/*000230*/ 0x73,0x73,0x69,0x6f,0x6e,0x20,0x6e,0x6f,0x74,0x69,0x63,0x65,0x20,0x73,0x68,0x61, +/*000240*/ 0x6c,0x6c,0x20,0x62,0x65,0x20,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x64,0x20,0x69, +/*000250*/ 0x6e,0x0d,0x0a,0x09,0x61,0x6c,0x6c,0x20,0x63,0x6f,0x70,0x69,0x65,0x73,0x20,0x6f, +/*000260*/ 0x72,0x20,0x73,0x75,0x62,0x73,0x74,0x61,0x6e,0x74,0x69,0x61,0x6c,0x20,0x70,0x6f, +/*000270*/ 0x72,0x74,0x69,0x6f,0x6e,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x53,0x6f, +/*000280*/ 0x66,0x74,0x77,0x61,0x72,0x65,0x2e,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x54,0x48,0x45, +/*000290*/ 0x20,0x53,0x4f,0x46,0x54,0x57,0x41,0x52,0x45,0x20,0x49,0x53,0x20,0x50,0x52,0x4f, +/*0002a0*/ 0x56,0x49,0x44,0x45,0x44,0x20,0x22,0x41,0x53,0x20,0x49,0x53,0x22,0x2c,0x20,0x57, +/*0002b0*/ 0x49,0x54,0x48,0x4f,0x55,0x54,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x59,0x20, +/*0002c0*/ 0x4f,0x46,0x20,0x41,0x4e,0x59,0x20,0x4b,0x49,0x4e,0x44,0x2c,0x20,0x45,0x58,0x50, +/*0002d0*/ 0x52,0x45,0x53,0x53,0x20,0x4f,0x52,0x0d,0x0a,0x09,0x49,0x4d,0x50,0x4c,0x49,0x45, +/*0002e0*/ 0x44,0x2c,0x20,0x49,0x4e,0x43,0x4c,0x55,0x44,0x49,0x4e,0x47,0x20,0x42,0x55,0x54, +/*0002f0*/ 0x20,0x4e,0x4f,0x54,0x20,0x4c,0x49,0x4d,0x49,0x54,0x45,0x44,0x20,0x54,0x4f,0x20, +/*000300*/ 0x54,0x48,0x45,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x49,0x45,0x53,0x20,0x4f, +/*000310*/ 0x46,0x20,0x4d,0x45,0x52,0x43,0x48,0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54, +/*000320*/ 0x59,0x2c,0x0d,0x0a,0x09,0x46,0x49,0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52, +/*000330*/ 0x20,0x41,0x20,0x50,0x41,0x52,0x54,0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55, +/*000340*/ 0x52,0x50,0x4f,0x53,0x45,0x20,0x41,0x4e,0x44,0x20,0x4e,0x4f,0x4e,0x49,0x4e,0x46, +/*000350*/ 0x52,0x49,0x4e,0x47,0x45,0x4d,0x45,0x4e,0x54,0x2e,0x20,0x49,0x4e,0x20,0x4e,0x4f, +/*000360*/ 0x20,0x45,0x56,0x45,0x4e,0x54,0x20,0x53,0x48,0x41,0x4c,0x4c,0x20,0x54,0x48,0x45, +/*000370*/ 0x0d,0x0a,0x09,0x41,0x55,0x54,0x48,0x4f,0x52,0x53,0x20,0x4f,0x52,0x20,0x43,0x4f, +/*000380*/ 0x50,0x59,0x52,0x49,0x47,0x48,0x54,0x20,0x48,0x4f,0x4c,0x44,0x45,0x52,0x53,0x20, +/*000390*/ 0x42,0x45,0x20,0x4c,0x49,0x41,0x42,0x4c,0x45,0x20,0x46,0x4f,0x52,0x20,0x41,0x4e, +/*0003a0*/ 0x59,0x20,0x43,0x4c,0x41,0x49,0x4d,0x2c,0x20,0x44,0x41,0x4d,0x41,0x47,0x45,0x53, +/*0003b0*/ 0x20,0x4f,0x52,0x20,0x4f,0x54,0x48,0x45,0x52,0x0d,0x0a,0x09,0x4c,0x49,0x41,0x42, +/*0003c0*/ 0x49,0x4c,0x49,0x54,0x59,0x2c,0x20,0x57,0x48,0x45,0x54,0x48,0x45,0x52,0x20,0x49, +/*0003d0*/ 0x4e,0x20,0x41,0x4e,0x20,0x41,0x43,0x54,0x49,0x4f,0x4e,0x20,0x4f,0x46,0x20,0x43, +/*0003e0*/ 0x4f,0x4e,0x54,0x52,0x41,0x43,0x54,0x2c,0x20,0x54,0x4f,0x52,0x54,0x20,0x4f,0x52, +/*0003f0*/ 0x20,0x4f,0x54,0x48,0x45,0x52,0x57,0x49,0x53,0x45,0x2c,0x20,0x41,0x52,0x49,0x53, +/*000400*/ 0x49,0x4e,0x47,0x20,0x46,0x52,0x4f,0x4d,0x2c,0x0d,0x0a,0x09,0x4f,0x55,0x54,0x20, +/*000410*/ 0x4f,0x46,0x20,0x4f,0x52,0x20,0x49,0x4e,0x20,0x43,0x4f,0x4e,0x4e,0x45,0x43,0x54, +/*000420*/ 0x49,0x4f,0x4e,0x20,0x57,0x49,0x54,0x48,0x20,0x54,0x48,0x45,0x20,0x53,0x4f,0x46, +/*000430*/ 0x54,0x57,0x41,0x52,0x45,0x20,0x4f,0x52,0x20,0x54,0x48,0x45,0x20,0x55,0x53,0x45, +/*000440*/ 0x20,0x4f,0x52,0x20,0x4f,0x54,0x48,0x45,0x52,0x20,0x44,0x45,0x41,0x4c,0x49,0x4e, +/*000450*/ 0x47,0x53,0x20,0x49,0x4e,0x20,0x54,0x48,0x45,0x0d,0x0a,0x09,0x53,0x4f,0x46,0x54, +/*000460*/ 0x57,0x41,0x52,0x45,0x2e,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x54,0x4f,0x44,0x4f,0x3a, +/*000470*/ 0x0d,0x0a,0x09,0x2a,0x20,0x50,0x72,0x69,0x6e,0x74,0x20,0x73,0x68,0x6f,0x72,0x74, +/*000480*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x61,0x72,0x67,0x75,0x6d,0x65, +/*000490*/ 0x6e,0x74,0x73,0x20,0x61,0x73,0x20,0x70,0x61,0x72,0x74,0x20,0x6f,0x66,0x20,0x73, +/*0004a0*/ 0x74,0x61,0x63,0x6b,0x20,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x0d,0x0a, +/*0004b0*/ 0x09,0x2a,0x20,0x50,0x72,0x6f,0x70,0x65,0x72,0x6c,0x79,0x20,0x68,0x61,0x6e,0x64, +/*0004c0*/ 0x6c,0x65,0x20,0x62,0x65,0x69,0x6e,0x67,0x20,0x72,0x65,0x65,0x6e,0x74,0x72,0x61, +/*0004d0*/ 0x6e,0x74,0x20,0x64,0x75,0x65,0x20,0x74,0x6f,0x20,0x63,0x6f,0x72,0x6f,0x75,0x74, +/*0004e0*/ 0x69,0x6e,0x65,0x73,0x2e,0x0d,0x0a,0x5d,0x5d,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63, +/*0004f0*/ 0x61,0x6c,0x20,0x64,0x62,0x67,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x55,0x73,0x65, +/*000500*/ 0x20,0x41,0x4e,0x53,0x49,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x63,0x6f,0x64,0x65, +/*000510*/ 0x73,0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6f,0x6d,0x70,0x74,0x20, +/*000520*/ 0x62,0x79,0x20,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x2e,0x0d,0x0a,0x6c,0x6f,0x63, +/*000530*/ 0x61,0x6c,0x20,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x47,0x52,0x41,0x59,0x20,0x3d,0x20, +/*000540*/ 0x22,0x22,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*000550*/ 0x52,0x45,0x44,0x20,0x3d,0x20,0x22,0x22,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*000560*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x20,0x3d,0x20,0x22,0x22,0x0d, +/*000570*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*000580*/ 0x4c,0x4f,0x57,0x20,0x3d,0x20,0x22,0x22,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*000590*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x20,0x3d,0x20,0x22,0x22, +/*0005a0*/ 0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41, +/*0005b0*/ 0x52,0x45,0x54,0x20,0x3d,0x20,0x22,0x20,0x3d,0x3e,0x20,0x22,0x0d,0x0a,0x0d,0x0a, +/*0005c0*/ 0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x70, +/*0005d0*/ 0x72,0x65,0x74,0x74,0x79,0x28,0x6f,0x62,0x6a,0x2c,0x20,0x6d,0x61,0x78,0x5f,0x64, +/*0005e0*/ 0x65,0x70,0x74,0x68,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20,0x6d,0x61,0x78,0x5f,0x64, +/*0005f0*/ 0x65,0x70,0x74,0x68,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x74,0x68,0x65,0x6e, +/*000600*/ 0x20,0x6d,0x61,0x78,0x5f,0x64,0x65,0x70,0x74,0x68,0x20,0x3d,0x20,0x64,0x62,0x67, +/*000610*/ 0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x5f,0x64,0x65,0x70,0x74,0x68,0x20,0x65,0x6e, +/*000620*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x75,0x72,0x6e, +/*000630*/ 0x73,0x20,0x74,0x72,0x75,0x65,0x20,0x69,0x66,0x20,0x61,0x20,0x74,0x61,0x62,0x6c, +/*000640*/ 0x65,0x20,0x68,0x61,0x73,0x20,0x61,0x20,0x5f,0x5f,0x74,0x6f,0x73,0x74,0x72,0x69, +/*000650*/ 0x6e,0x67,0x20,0x6d,0x65,0x74,0x61,0x6d,0x65,0x74,0x68,0x6f,0x64,0x2e,0x0d,0x0a, +/*000660*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*000670*/ 0x63,0x6f,0x65,0x72,0x63,0x65,0x61,0x62,0x6c,0x65,0x28,0x74,0x62,0x6c,0x29,0x0d, +/*000680*/ 0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6d,0x65,0x74,0x61,0x20,0x3d,0x20, +/*000690*/ 0x67,0x65,0x74,0x6d,0x65,0x74,0x61,0x74,0x61,0x62,0x6c,0x65,0x28,0x74,0x62,0x6c, +/*0006a0*/ 0x29,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x6d,0x65,0x74, +/*0006b0*/ 0x61,0x20,0x61,0x6e,0x64,0x20,0x6d,0x65,0x74,0x61,0x2e,0x5f,0x5f,0x74,0x6f,0x73, +/*0006c0*/ 0x74,0x72,0x69,0x6e,0x67,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d, +/*0006d0*/ 0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e, +/*0006e0*/ 0x20,0x72,0x65,0x63,0x75,0x72,0x73,0x65,0x28,0x6f,0x62,0x6a,0x2c,0x20,0x64,0x65, +/*0006f0*/ 0x70,0x74,0x68,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x74,0x79,0x70,0x65,0x28, +/*000700*/ 0x6f,0x62,0x6a,0x29,0x20,0x3d,0x3d,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22, +/*000710*/ 0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d,0x20,0x44,0x75,0x6d, +/*000720*/ 0x70,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x73,0x6f,0x20, +/*000730*/ 0x74,0x68,0x61,0x74,0x20,0x65,0x73,0x63,0x61,0x70,0x65,0x20,0x73,0x65,0x71,0x75, +/*000740*/ 0x65,0x6e,0x63,0x65,0x73,0x20,0x61,0x72,0x65,0x20,0x70,0x72,0x69,0x6e,0x74,0x65, +/*000750*/ 0x64,0x2e,0x0d,0x0a,0x09,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74, +/*000760*/ 0x72,0x69,0x6e,0x67,0x2e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x28,0x22,0x25,0x71,0x22, +/*000770*/ 0x2c,0x20,0x6f,0x62,0x6a,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6c,0x73,0x65,0x69,0x66, +/*000780*/ 0x20,0x74,0x79,0x70,0x65,0x28,0x6f,0x62,0x6a,0x29,0x20,0x3d,0x3d,0x20,0x22,0x74, +/*000790*/ 0x61,0x62,0x6c,0x65,0x22,0x20,0x61,0x6e,0x64,0x20,0x64,0x65,0x70,0x74,0x68,0x20, +/*0007a0*/ 0x3c,0x20,0x6d,0x61,0x78,0x5f,0x64,0x65,0x70,0x74,0x68,0x20,0x61,0x6e,0x64,0x20, +/*0007b0*/ 0x6e,0x6f,0x74,0x20,0x63,0x6f,0x65,0x72,0x63,0x65,0x61,0x62,0x6c,0x65,0x28,0x6f, +/*0007c0*/ 0x62,0x6a,0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63, +/*0007d0*/ 0x61,0x6c,0x20,0x73,0x74,0x72,0x20,0x3d,0x20,0x22,0x7b,0x22,0x0d,0x0a,0x09,0x09, +/*0007e0*/ 0x09,0x0d,0x0a,0x09,0x09,0x09,0x66,0x6f,0x72,0x20,0x6b,0x2c,0x20,0x76,0x20,0x69, +/*0007f0*/ 0x6e,0x20,0x70,0x61,0x69,0x72,0x73,0x28,0x6f,0x62,0x6a,0x29,0x20,0x64,0x6f,0x0d, +/*000800*/ 0x0a,0x09,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x70,0x61,0x69,0x72,0x20, +/*000810*/ 0x3d,0x20,0x70,0x72,0x65,0x74,0x74,0x79,0x28,0x6b,0x2c,0x20,0x30,0x29,0x2e,0x2e, +/*000820*/ 0x22,0x20,0x3d,0x20,0x22,0x2e,0x2e,0x72,0x65,0x63,0x75,0x72,0x73,0x65,0x28,0x76, +/*000830*/ 0x2c,0x20,0x64,0x65,0x70,0x74,0x68,0x20,0x2b,0x20,0x31,0x29,0x0d,0x0a,0x09,0x09, +/*000840*/ 0x09,0x09,0x73,0x74,0x72,0x20,0x3d,0x20,0x73,0x74,0x72,0x2e,0x2e,0x28,0x73,0x74, +/*000850*/ 0x72,0x20,0x3d,0x3d,0x20,0x22,0x7b,0x22,0x20,0x61,0x6e,0x64,0x20,0x70,0x61,0x69, +/*000860*/ 0x72,0x20,0x6f,0x72,0x20,0x22,0x2c,0x20,0x22,0x2e,0x2e,0x70,0x61,0x69,0x72,0x29, +/*000870*/ 0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x0d,0x0a,0x09, +/*000880*/ 0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x72,0x2e,0x2e,0x22,0x7d, +/*000890*/ 0x22,0x0d,0x0a,0x09,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d, +/*0008a0*/ 0x20,0x74,0x6f,0x73,0x74,0x72,0x69,0x6e,0x67,0x28,0x29,0x20,0x63,0x61,0x6e,0x20, +/*0008b0*/ 0x66,0x61,0x69,0x6c,0x20,0x69,0x66,0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x69,0x73, +/*0008c0*/ 0x20,0x61,0x6e,0x20,0x65,0x72,0x72,0x6f,0x72,0x20,0x69,0x6e,0x20,0x61,0x20,0x5f, +/*0008d0*/ 0x5f,0x74,0x6f,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x6d,0x65,0x74,0x61,0x6d,0x65, +/*0008e0*/ 0x74,0x68,0x6f,0x64,0x2e,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*0008f0*/ 0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x2c,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d, +/*000900*/ 0x20,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28, +/*000910*/ 0x29,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x6f,0x73,0x74,0x72,0x69,0x6e, +/*000920*/ 0x67,0x28,0x6f,0x62,0x6a,0x29,0x20,0x65,0x6e,0x64,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*000930*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x20, +/*000940*/ 0x61,0x6e,0x64,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x6f,0x72,0x20,0x22,0x3c,0x21, +/*000950*/ 0x21,0x65,0x72,0x72,0x6f,0x72,0x20,0x69,0x6e,0x20,0x5f,0x5f,0x74,0x6f,0x73,0x74, +/*000960*/ 0x72,0x69,0x6e,0x67,0x20,0x6d,0x65,0x74,0x61,0x6d,0x65,0x74,0x68,0x6f,0x64,0x21, +/*000970*/ 0x21,0x3e,0x22,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6e, +/*000980*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x72,0x65, +/*000990*/ 0x63,0x75,0x72,0x73,0x65,0x28,0x6f,0x62,0x6a,0x2c,0x20,0x30,0x29,0x0d,0x0a,0x65, +/*0009a0*/ 0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x54,0x68,0x65,0x20,0x73,0x74,0x61, +/*0009b0*/ 0x63,0x6b,0x20,0x6c,0x65,0x76,0x65,0x6c,0x20,0x74,0x68,0x61,0x74,0x20,0x63,0x6d, +/*0009c0*/ 0x64,0x5f,0x2a,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x20,0x75,0x73, +/*0009d0*/ 0x65,0x20,0x74,0x6f,0x20,0x61,0x63,0x63,0x65,0x73,0x73,0x20,0x6c,0x6f,0x63,0x61, +/*0009e0*/ 0x6c,0x73,0x20,0x6f,0x72,0x20,0x69,0x6e,0x66,0x6f,0x0d,0x0a,0x2d,0x2d,0x20,0x54, +/*0009f0*/ 0x68,0x65,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x75,0x72,0x65,0x20,0x6f,0x66,0x20, +/*000a00*/ 0x74,0x68,0x65,0x20,0x63,0x6f,0x64,0x65,0x20,0x76,0x65,0x72,0x79,0x20,0x63,0x61, +/*000a10*/ 0x72,0x65,0x66,0x75,0x6c,0x6c,0x79,0x20,0x65,0x6e,0x73,0x75,0x72,0x65,0x73,0x20, +/*000a20*/ 0x74,0x68,0x69,0x73,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x43,0x4d,0x44, +/*000a30*/ 0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x20,0x3d,0x20,0x36, +/*000a40*/ 0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20, +/*000a50*/ 0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x6f,0x70,0x20,0x6f,0x66,0x20,0x74,0x68, +/*000a60*/ 0x65,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x6f,0x75,0x74,0x73,0x69,0x64,0x65,0x20, +/*000a70*/ 0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x2e, +/*000a80*/ 0x0d,0x0a,0x2d,0x2d,0x20,0x41,0x64,0x6a,0x75,0x73,0x74,0x65,0x64,0x20,0x62,0x79, +/*000a90*/ 0x20,0x73,0x6f,0x6d,0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x20,0x65, +/*000aa0*/ 0x6e,0x74,0x72,0x79,0x70,0x6f,0x69,0x6e,0x74,0x73,0x2e,0x0d,0x0a,0x6c,0x6f,0x63, +/*000ab0*/ 0x61,0x6c,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x20,0x3d,0x20,0x30, +/*000ac0*/ 0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x54,0x68,0x65,0x20,0x63,0x75,0x72,0x72,0x65, +/*000ad0*/ 0x6e,0x74,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x66,0x72,0x61,0x6d,0x65,0x20,0x69, +/*000ae0*/ 0x6e,0x64,0x65,0x78,0x2e,0x0d,0x0a,0x2d,0x2d,0x20,0x43,0x68,0x61,0x6e,0x67,0x65, +/*000af0*/ 0x64,0x20,0x75,0x73,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x75,0x70,0x2f,0x64, +/*000b00*/ 0x6f,0x77,0x6e,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x73,0x0d,0x0a,0x6c,0x6f, +/*000b10*/ 0x63,0x61,0x6c,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63, +/*000b20*/ 0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x30,0x0d,0x0a,0x0d,0x0a, +/*000b30*/ 0x2d,0x2d,0x20,0x4c,0x75,0x61,0x4a,0x49,0x54,0x20,0x68,0x61,0x73,0x20,0x61,0x6e, +/*000b40*/ 0x20,0x6f,0x66,0x66,0x20,0x62,0x79,0x20,0x6f,0x6e,0x65,0x20,0x62,0x75,0x67,0x20, +/*000b50*/ 0x77,0x68,0x65,0x6e,0x20,0x73,0x65,0x74,0x74,0x69,0x6e,0x67,0x20,0x6c,0x6f,0x63, +/*000b60*/ 0x61,0x6c,0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x73,0x2e,0x0d,0x0a,0x6c, +/*000b70*/ 0x6f,0x63,0x61,0x6c,0x20,0x4c,0x55,0x41,0x5f,0x4a,0x49,0x54,0x5f,0x53,0x45,0x54, +/*000b80*/ 0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x57,0x4f,0x52,0x4b,0x41,0x52,0x4f,0x55,0x4e,0x44, +/*000b90*/ 0x20,0x3d,0x20,0x30,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x44,0x65,0x66,0x61,0x75, +/*000ba0*/ 0x6c,0x74,0x20,0x64,0x62,0x67,0x2e,0x72,0x65,0x61,0x64,0x20,0x66,0x75,0x6e,0x63, +/*000bb0*/ 0x74,0x69,0x6f,0x6e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63, +/*000bc0*/ 0x74,0x69,0x6f,0x6e,0x20,0x64,0x62,0x67,0x5f,0x72,0x65,0x61,0x64,0x28,0x70,0x72, +/*000bd0*/ 0x6f,0x6d,0x70,0x74,0x29,0x0d,0x0a,0x09,0x64,0x62,0x67,0x2e,0x77,0x72,0x69,0x74, +/*000be0*/ 0x65,0x28,0x70,0x72,0x6f,0x6d,0x70,0x74,0x29,0x0d,0x0a,0x09,0x69,0x6f,0x2e,0x66, +/*000bf0*/ 0x6c,0x75,0x73,0x68,0x28,0x29,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*000c00*/ 0x69,0x6f,0x2e,0x72,0x65,0x61,0x64,0x28,0x29,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a, +/*000c10*/ 0x0d,0x0a,0x2d,0x2d,0x20,0x44,0x65,0x66,0x61,0x75,0x6c,0x74,0x20,0x64,0x62,0x67, +/*000c20*/ 0x2e,0x77,0x72,0x69,0x74,0x65,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x0d, +/*000c30*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*000c40*/ 0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x74,0x72,0x29,0x0d,0x0a, +/*000c50*/ 0x09,0x69,0x6f,0x2e,0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x74,0x72,0x29,0x0d,0x0a, +/*000c60*/ 0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e, +/*000c70*/ 0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c, +/*000c80*/ 0x6e,0x28,0x73,0x74,0x72,0x2c,0x20,0x2e,0x2e,0x2e,0x29,0x0d,0x0a,0x09,0x69,0x66, +/*000c90*/ 0x20,0x73,0x65,0x6c,0x65,0x63,0x74,0x28,0x22,0x23,0x22,0x2c,0x20,0x2e,0x2e,0x2e, +/*000ca0*/ 0x29,0x20,0x3d,0x3d,0x20,0x30,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x64, +/*000cb0*/ 0x62,0x67,0x2e,0x77,0x72,0x69,0x74,0x65,0x28,0x28,0x73,0x74,0x72,0x20,0x6f,0x72, +/*000cc0*/ 0x20,0x22,0x3c,0x4e,0x55,0x4c,0x4c,0x3e,0x22,0x29,0x2e,0x2e,0x22,0x5c,0x6e,0x22, +/*000cd0*/ 0x29,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x2e, +/*000ce0*/ 0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x66,0x6f,0x72, +/*000cf0*/ 0x6d,0x61,0x74,0x28,0x73,0x74,0x72,0x2e,0x2e,0x22,0x5c,0x6e,0x22,0x2c,0x20,0x2e, +/*000d00*/ 0x2e,0x2e,0x29,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*000d10*/ 0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f, +/*000d20*/ 0x6e,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x6c,0x6f,0x63,0x28,0x66,0x69,0x6c, +/*000d30*/ 0x65,0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*000d40*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x66,0x69,0x6c,0x65, +/*000d50*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22, +/*000d60*/ 0x3a,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57, +/*000d70*/ 0x2e,0x2e,0x6c,0x69,0x6e,0x65,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*000d80*/ 0x53,0x45,0x54,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66, +/*000d90*/ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x73, +/*000da0*/ 0x74,0x61,0x63,0x6b,0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66,0x6f,0x28, +/*000db0*/ 0x69,0x6e,0x66,0x6f,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x69, +/*000dc0*/ 0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x73,0x6f, +/*000dd0*/ 0x75,0x72,0x63,0x65,0x3a,0x6d,0x61,0x74,0x63,0x68,0x28,0x22,0x40,0x28,0x2e,0x2a, +/*000de0*/ 0x29,0x22,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x6f,0x75,0x72, +/*000df0*/ 0x63,0x65,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20,0x61,0x6e, +/*000e00*/ 0x64,0x20,0x64,0x62,0x67,0x2e,0x73,0x68,0x6f,0x72,0x74,0x65,0x6e,0x5f,0x70,0x61, +/*000e10*/ 0x74,0x68,0x28,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x29,0x20,0x6f,0x72,0x20, +/*000e20*/ 0x69,0x6e,0x66,0x6f,0x2e,0x73,0x68,0x6f,0x72,0x74,0x5f,0x73,0x72,0x63,0x0d,0x0a, +/*000e30*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6e,0x61,0x6d,0x65,0x77,0x68,0x61,0x74,0x20, +/*000e40*/ 0x3d,0x20,0x28,0x69,0x6e,0x66,0x6f,0x2e,0x6e,0x61,0x6d,0x65,0x77,0x68,0x61,0x74, +/*000e50*/ 0x20,0x3d,0x3d,0x20,0x22,0x22,0x20,0x61,0x6e,0x64,0x20,0x22,0x63,0x68,0x75,0x6e, +/*000e60*/ 0x6b,0x20,0x61,0x74,0x22,0x20,0x6f,0x72,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x6e,0x61, +/*000e70*/ 0x6d,0x65,0x77,0x68,0x61,0x74,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*000e80*/ 0x6e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x28,0x69,0x6e,0x66,0x6f,0x2e,0x6e,0x61,0x6d, +/*000e90*/ 0x65,0x20,0x61,0x6e,0x64,0x20,0x22,0x27,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*000ea0*/ 0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x69,0x6e,0x66,0x6f,0x2e,0x6e,0x61,0x6d,0x65, +/*000eb0*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22, +/*000ec0*/ 0x27,0x22,0x20,0x6f,0x72,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x6c,0x6f,0x63, +/*000ed0*/ 0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x6c,0x69, +/*000ee0*/ 0x6e,0x65,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x29,0x29,0x0d,0x0a,0x09,0x72,0x65, +/*000ef0*/ 0x74,0x75,0x72,0x6e,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x6c,0x6f,0x63,0x28, +/*000f00*/ 0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72, +/*000f10*/ 0x72,0x65,0x6e,0x74,0x6c,0x69,0x6e,0x65,0x29,0x2e,0x2e,0x22,0x20,0x69,0x6e,0x20, +/*000f20*/ 0x22,0x2e,0x2e,0x6e,0x61,0x6d,0x65,0x77,0x68,0x61,0x74,0x2e,0x2e,0x22,0x20,0x22, +/*000f30*/ 0x2e,0x2e,0x6e,0x61,0x6d,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c, +/*000f40*/ 0x6f,0x63,0x61,0x6c,0x20,0x72,0x65,0x70,0x6c,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20, +/*000f50*/ 0x52,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x20,0x66,0x6f,0x72, +/*000f60*/ 0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x66,0x72,0x61,0x6d,0x65,0x73,0x20,0x77,0x69, +/*000f70*/ 0x74,0x68,0x6f,0x75,0x74,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x0d,0x0a,0x2d, +/*000f80*/ 0x2d,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x73, +/*000f90*/ 0x20,0x43,0x20,0x66,0x72,0x61,0x6d,0x65,0x73,0x2c,0x20,0x4c,0x75,0x61,0x20,0x62, +/*000fa0*/ 0x79,0x74,0x65,0x63,0x6f,0x64,0x65,0x2c,0x20,0x61,0x6e,0x64,0x20,0x60,0x6c,0x6f, +/*000fb0*/ 0x61,0x64,0x73,0x74,0x72,0x69,0x6e,0x67,0x60,0x20,0x66,0x75,0x6e,0x63,0x74,0x69, +/*000fc0*/ 0x6f,0x6e,0x73,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74, +/*000fd0*/ 0x69,0x6f,0x6e,0x20,0x66,0x72,0x61,0x6d,0x65,0x5f,0x68,0x61,0x73,0x5f,0x6c,0x69, +/*000fe0*/ 0x6e,0x65,0x28,0x69,0x6e,0x66,0x6f,0x29,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*000ff0*/ 0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x6c,0x69,0x6e,0x65, +/*001000*/ 0x20,0x3e,0x3d,0x20,0x30,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63, +/*001010*/ 0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x68,0x6f,0x6f,0x6b, +/*001020*/ 0x5f,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x72,0x65,0x70,0x6c,0x5f,0x74,0x68, +/*001030*/ 0x72,0x65,0x73,0x68,0x6f,0x6c,0x64,0x29,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72, +/*001040*/ 0x6e,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x6f,0x66,0x66,0x73,0x65, +/*001050*/ 0x74,0x2c,0x20,0x72,0x65,0x61,0x73,0x6f,0x6e,0x29,0x0d,0x0a,0x09,0x09,0x72,0x65, +/*001060*/ 0x74,0x75,0x72,0x6e,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x65,0x76, +/*001070*/ 0x65,0x6e,0x74,0x2c,0x20,0x5f,0x29,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d,0x20,0x53, +/*001080*/ 0x6b,0x69,0x70,0x20,0x65,0x76,0x65,0x6e,0x74,0x73,0x20,0x74,0x68,0x61,0x74,0x20, +/*001090*/ 0x64,0x6f,0x6e,0x27,0x74,0x20,0x68,0x61,0x76,0x65,0x20,0x6c,0x69,0x6e,0x65,0x20, +/*0010a0*/ 0x69,0x6e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,0x09,0x09, +/*0010b0*/ 0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x66,0x72,0x61,0x6d,0x65,0x5f,0x68,0x61, +/*0010c0*/ 0x73,0x5f,0x6c,0x69,0x6e,0x65,0x28,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74, +/*0010d0*/ 0x69,0x6e,0x66,0x6f,0x28,0x32,0x29,0x29,0x20,0x74,0x68,0x65,0x6e,0x20,0x72,0x65, +/*0010e0*/ 0x74,0x75,0x72,0x6e,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x0d,0x0a,0x09, +/*0010f0*/ 0x09,0x09,0x2d,0x2d,0x20,0x54,0x61,0x69,0x6c,0x20,0x63,0x61,0x6c,0x6c,0x73,0x20, +/*001100*/ 0x61,0x72,0x65,0x20,0x73,0x70,0x65,0x63,0x69,0x66,0x69,0x63,0x61,0x6c,0x6c,0x79, +/*001110*/ 0x20,0x69,0x67,0x6e,0x6f,0x72,0x65,0x64,0x20,0x73,0x69,0x6e,0x63,0x65,0x20,0x74, +/*001120*/ 0x68,0x65,0x79,0x20,0x61,0x6c,0x73,0x6f,0x20,0x77,0x69,0x6c,0x6c,0x20,0x68,0x61, +/*001130*/ 0x76,0x65,0x20,0x74,0x61,0x69,0x6c,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x73,0x20, +/*001140*/ 0x74,0x6f,0x20,0x62,0x61,0x6c,0x61,0x6e,0x63,0x65,0x20,0x6f,0x75,0x74,0x2e,0x0d, +/*001150*/ 0x0a,0x09,0x09,0x09,0x69,0x66,0x20,0x65,0x76,0x65,0x6e,0x74,0x20,0x3d,0x3d,0x20, +/*001160*/ 0x22,0x63,0x61,0x6c,0x6c,0x22,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09, +/*001170*/ 0x09,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x6f,0x66,0x66,0x73,0x65,0x74, +/*001180*/ 0x20,0x2b,0x20,0x31,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6c,0x73,0x65,0x69,0x66,0x20, +/*001190*/ 0x65,0x76,0x65,0x6e,0x74,0x20,0x3d,0x3d,0x20,0x22,0x72,0x65,0x74,0x75,0x72,0x6e, +/*0011a0*/ 0x22,0x20,0x61,0x6e,0x64,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3e,0x20,0x72, +/*0011b0*/ 0x65,0x70,0x6c,0x5f,0x74,0x68,0x72,0x65,0x73,0x68,0x6f,0x6c,0x64,0x20,0x74,0x68, +/*0011c0*/ 0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x09,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d, +/*0011d0*/ 0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2d,0x20,0x31,0x0d,0x0a,0x09,0x09,0x09, +/*0011e0*/ 0x65,0x6c,0x73,0x65,0x69,0x66,0x20,0x65,0x76,0x65,0x6e,0x74,0x20,0x3d,0x3d,0x20, +/*0011f0*/ 0x22,0x6c,0x69,0x6e,0x65,0x22,0x20,0x61,0x6e,0x64,0x20,0x6f,0x66,0x66,0x73,0x65, +/*001200*/ 0x74,0x20,0x3c,0x3d,0x20,0x72,0x65,0x70,0x6c,0x5f,0x74,0x68,0x72,0x65,0x73,0x68, +/*001210*/ 0x6f,0x6c,0x64,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x09,0x72,0x65, +/*001220*/ 0x70,0x6c,0x28,0x72,0x65,0x61,0x73,0x6f,0x6e,0x29,0x0d,0x0a,0x09,0x09,0x09,0x65, +/*001230*/ 0x6e,0x64,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d, +/*001240*/ 0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x68,0x6f, +/*001250*/ 0x6f,0x6b,0x5f,0x73,0x74,0x65,0x70,0x20,0x3d,0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x66, +/*001260*/ 0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x31,0x29,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c, +/*001270*/ 0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x6e,0x65,0x78,0x74,0x20,0x3d,0x20,0x68,0x6f,0x6f, +/*001280*/ 0x6b,0x5f,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x30,0x29,0x0d,0x0a,0x6c,0x6f, +/*001290*/ 0x63,0x61,0x6c,0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x66,0x69,0x6e,0x69,0x73,0x68,0x20, +/*0012a0*/ 0x3d,0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x2d, +/*0012b0*/ 0x31,0x29,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x43,0x72,0x65,0x61,0x74,0x65,0x20, +/*0012c0*/ 0x61,0x20,0x74,0x61,0x62,0x6c,0x65,0x20,0x6f,0x66,0x20,0x61,0x6c,0x6c,0x20,0x74, +/*0012d0*/ 0x68,0x65,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x6c,0x79,0x20,0x61,0x63,0x63,0x65,0x73, +/*0012e0*/ 0x73,0x69,0x62,0x6c,0x65,0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x73,0x2e, +/*0012f0*/ 0x0d,0x0a,0x2d,0x2d,0x20,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x20,0x61,0x72,0x65, +/*001300*/ 0x20,0x6e,0x6f,0x74,0x20,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x64,0x20,0x77,0x68, +/*001310*/ 0x65,0x6e,0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x6c, +/*001320*/ 0x6f,0x63,0x61,0x6c,0x73,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x2c,0x20,0x62, +/*001330*/ 0x75,0x74,0x20,0x61,0x72,0x65,0x20,0x77,0x68,0x65,0x6e,0x20,0x72,0x75,0x6e,0x6e, +/*001340*/ 0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x69,0x6e,0x74,0x20,0x63,0x6f, +/*001350*/ 0x6d,0x6d,0x61,0x6e,0x64,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75, +/*001360*/ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x62,0x69,0x6e, +/*001370*/ 0x64,0x69,0x6e,0x67,0x73,0x28,0x6f,0x66,0x66,0x73,0x65,0x74,0x2c,0x20,0x69,0x6e, +/*001380*/ 0x63,0x6c,0x75,0x64,0x65,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x29,0x0d,0x0a, +/*001390*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6c,0x65,0x76,0x65,0x6c,0x20,0x3d,0x20,0x6f, +/*0013a0*/ 0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e, +/*0013b0*/ 0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x43, +/*0013c0*/ 0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x0d,0x0a, +/*0013d0*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x20,0x3d,0x20,0x64,0x65, +/*0013e0*/ 0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x6c,0x65,0x76,0x65, +/*0013f0*/ 0x6c,0x29,0x2e,0x66,0x75,0x6e,0x63,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*001400*/ 0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x20,0x3d,0x20,0x7b,0x7d,0x0d,0x0a,0x09, +/*001410*/ 0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x72,0x69,0x65,0x76,0x65,0x20,0x74, +/*001420*/ 0x68,0x65,0x20,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x73,0x0d,0x0a,0x09,0x64,0x6f, +/*001430*/ 0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20,0x3d,0x20,0x31,0x3b,0x20,0x77,0x68, +/*001440*/ 0x69,0x6c,0x65,0x20,0x74,0x72,0x75,0x65,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x6c, +/*001450*/ 0x6f,0x63,0x61,0x6c,0x20,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x76,0x61,0x6c,0x75,0x65, +/*001460*/ 0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x75,0x70,0x76,0x61, +/*001470*/ 0x6c,0x75,0x65,0x28,0x66,0x75,0x6e,0x63,0x2c,0x20,0x69,0x29,0x0d,0x0a,0x09,0x09, +/*001480*/ 0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x6e,0x61,0x6d,0x65,0x20,0x74,0x68,0x65,0x6e, +/*001490*/ 0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x62,0x69, +/*0014a0*/ 0x6e,0x64,0x69,0x6e,0x67,0x73,0x5b,0x6e,0x61,0x6d,0x65,0x5d,0x20,0x3d,0x20,0x76, +/*0014b0*/ 0x61,0x6c,0x75,0x65,0x0d,0x0a,0x09,0x09,0x69,0x20,0x3d,0x20,0x69,0x20,0x2b,0x20, +/*0014c0*/ 0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a, +/*0014d0*/ 0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x72,0x69,0x65,0x76,0x65,0x20,0x74,0x68,0x65, +/*0014e0*/ 0x20,0x6c,0x6f,0x63,0x61,0x6c,0x73,0x20,0x28,0x6f,0x76,0x65,0x72,0x77,0x72,0x69, +/*0014f0*/ 0x74,0x69,0x6e,0x67,0x20,0x61,0x6e,0x79,0x20,0x75,0x70,0x76,0x61,0x6c,0x75,0x65, +/*001500*/ 0x73,0x29,0x0d,0x0a,0x09,0x64,0x6f,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20, +/*001510*/ 0x3d,0x20,0x31,0x3b,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x74,0x72,0x75,0x65,0x20, +/*001520*/ 0x64,0x6f,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6e,0x61,0x6d,0x65, +/*001530*/ 0x2c,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e, +/*001540*/ 0x67,0x65,0x74,0x6c,0x6f,0x63,0x61,0x6c,0x28,0x6c,0x65,0x76,0x65,0x6c,0x2c,0x20, +/*001550*/ 0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x6e,0x61,0x6d, +/*001560*/ 0x65,0x20,0x74,0x68,0x65,0x6e,0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65,0x6e,0x64, +/*001570*/ 0x0d,0x0a,0x09,0x09,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x5b,0x6e,0x61,0x6d, +/*001580*/ 0x65,0x5d,0x20,0x3d,0x20,0x76,0x61,0x6c,0x75,0x65,0x0d,0x0a,0x09,0x09,0x69,0x20, +/*001590*/ 0x3d,0x20,0x69,0x20,0x2b,0x20,0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x20,0x65,0x6e, +/*0015a0*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x72,0x69,0x65, +/*0015b0*/ 0x76,0x65,0x20,0x74,0x68,0x65,0x20,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x20,0x28, +/*0015c0*/ 0x77,0x6f,0x72,0x6b,0x73,0x20,0x69,0x6e,0x20,0x4c,0x75,0x61,0x20,0x35,0x2e,0x32, +/*0015d0*/ 0x20,0x61,0x6e,0x64,0x20,0x4c,0x75,0x61,0x4a,0x49,0x54,0x29,0x0d,0x0a,0x09,0x6c, +/*0015e0*/ 0x6f,0x63,0x61,0x6c,0x20,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x20,0x3d,0x20,0x7b, +/*0015f0*/ 0x7d,0x0d,0x0a,0x09,0x64,0x6f,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20,0x3d, +/*001600*/ 0x20,0x31,0x3b,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x74,0x72,0x75,0x65,0x20,0x64, +/*001610*/ 0x6f,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6e,0x61,0x6d,0x65,0x2c, +/*001620*/ 0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67, +/*001630*/ 0x65,0x74,0x6c,0x6f,0x63,0x61,0x6c,0x28,0x6c,0x65,0x76,0x65,0x6c,0x2c,0x20,0x2d, +/*001640*/ 0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x6e,0x61,0x6d, +/*001650*/ 0x65,0x20,0x74,0x68,0x65,0x6e,0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65,0x6e,0x64, +/*001660*/ 0x0d,0x0a,0x09,0x09,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x5b,0x69,0x5d,0x20,0x3d, +/*001670*/ 0x20,0x76,0x61,0x6c,0x75,0x65,0x0d,0x0a,0x09,0x09,0x69,0x20,0x3d,0x20,0x69,0x20, +/*001680*/ 0x2b,0x20,0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09, +/*001690*/ 0x69,0x66,0x20,0x23,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x20,0x3e,0x20,0x30,0x20, +/*0016a0*/ 0x74,0x68,0x65,0x6e,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x5b,0x22,0x2e, +/*0016b0*/ 0x2e,0x2e,0x22,0x5d,0x20,0x3d,0x20,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x20,0x65, +/*0016c0*/ 0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66,0x20,0x69,0x6e,0x63,0x6c,0x75, +/*0016d0*/ 0x64,0x65,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x20,0x74,0x68,0x65,0x6e,0x0d, +/*0016e0*/ 0x0a,0x09,0x09,0x2d,0x2d,0x20,0x49,0x6e,0x20,0x4c,0x75,0x61,0x20,0x35,0x2e,0x32, +/*0016f0*/ 0x2c,0x20,0x79,0x6f,0x75,0x20,0x68,0x61,0x76,0x65,0x20,0x74,0x6f,0x20,0x67,0x65, +/*001700*/ 0x74,0x20,0x74,0x68,0x65,0x20,0x65,0x6e,0x76,0x69,0x72,0x6f,0x6e,0x6d,0x65,0x6e, +/*001710*/ 0x74,0x20,0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x72,0x6f,0x6d,0x20,0x74,0x68,0x65, +/*001720*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x27,0x73,0x20,0x6c,0x6f,0x63,0x61, +/*001730*/ 0x6c,0x73,0x2e,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x76, +/*001740*/ 0x20,0x3d,0x20,0x28,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x20,0x3c,0x3d,0x20, +/*001750*/ 0x22,0x4c,0x75,0x61,0x20,0x35,0x2e,0x31,0x22,0x20,0x61,0x6e,0x64,0x20,0x67,0x65, +/*001760*/ 0x74,0x66,0x65,0x6e,0x76,0x28,0x66,0x75,0x6e,0x63,0x29,0x20,0x6f,0x72,0x20,0x62, +/*001770*/ 0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x2e,0x5f,0x45,0x4e,0x56,0x29,0x0d,0x0a,0x09, +/*001780*/ 0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x65,0x74,0x6d,0x65,0x74,0x61,0x74, +/*001790*/ 0x61,0x62,0x6c,0x65,0x28,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x2c,0x20,0x7b, +/*0017a0*/ 0x5f,0x5f,0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x20,0x65,0x6e,0x76,0x20,0x6f,0x72, +/*0017b0*/ 0x20,0x5f,0x47,0x7d,0x29,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09, +/*0017c0*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x0d, +/*0017d0*/ 0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d, +/*0017e0*/ 0x20,0x55,0x73,0x65,0x64,0x20,0x61,0x73,0x20,0x61,0x20,0x5f,0x5f,0x6e,0x65,0x77, +/*0017f0*/ 0x69,0x6e,0x64,0x65,0x78,0x20,0x6d,0x65,0x74,0x61,0x6d,0x65,0x74,0x68,0x6f,0x64, +/*001800*/ 0x20,0x74,0x6f,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x20,0x76,0x61,0x72,0x69,0x61, +/*001810*/ 0x62,0x6c,0x65,0x73,0x20,0x69,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x65,0x76,0x61,0x6c, +/*001820*/ 0x28,0x29,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74, +/*001830*/ 0x69,0x6f,0x6e,0x20,0x6d,0x75,0x74,0x61,0x74,0x65,0x5f,0x62,0x69,0x6e,0x64,0x69, +/*001840*/ 0x6e,0x67,0x73,0x28,0x5f,0x2c,0x20,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x76,0x61,0x6c, +/*001850*/ 0x75,0x65,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x46,0x55,0x4e,0x43, +/*001860*/ 0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x20,0x3d,0x20, +/*001870*/ 0x33,0x20,0x2d,0x2d,0x20,0x53,0x74,0x61,0x63,0x6b,0x20,0x64,0x65,0x70,0x74,0x68, +/*001880*/ 0x20,0x6f,0x66,0x20,0x74,0x68,0x69,0x73,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f, +/*001890*/ 0x6e,0x2e,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6c,0x65,0x76,0x65,0x6c, +/*0018a0*/ 0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74, +/*0018b0*/ 0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x46,0x55,0x4e,0x43,0x5f,0x53, +/*0018c0*/ 0x54,0x41,0x43,0x4b,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x20,0x2b,0x20,0x43,0x4d, +/*0018d0*/ 0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x0d,0x0a,0x09, +/*0018e0*/ 0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x53,0x65,0x74,0x20,0x61,0x20,0x6c,0x6f,0x63,0x61, +/*0018f0*/ 0x6c,0x2e,0x0d,0x0a,0x09,0x64,0x6f,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20, +/*001900*/ 0x3d,0x20,0x31,0x3b,0x20,0x72,0x65,0x70,0x65,0x61,0x74,0x0d,0x0a,0x09,0x09,0x6c, +/*001910*/ 0x6f,0x63,0x61,0x6c,0x20,0x76,0x61,0x72,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67, +/*001920*/ 0x2e,0x67,0x65,0x74,0x6c,0x6f,0x63,0x61,0x6c,0x28,0x6c,0x65,0x76,0x65,0x6c,0x2c, +/*001930*/ 0x20,0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x61,0x6d,0x65,0x20,0x3d, +/*001940*/ 0x3d,0x20,0x76,0x61,0x72,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x64, +/*001950*/ 0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52, +/*001960*/ 0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67, +/*001970*/ 0x65,0x72,0x2e,0x6c,0x75,0x61,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43, +/*001980*/ 0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x53,0x65,0x74,0x20,0x6c,0x6f,0x63,0x61,0x6c, +/*001990*/ 0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c, +/*0019a0*/ 0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x6e,0x61,0x6d,0x65,0x2e,0x2e,0x43, +/*0019b0*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*0019c0*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x73,0x65,0x74, +/*0019d0*/ 0x6c,0x6f,0x63,0x61,0x6c,0x28,0x6c,0x65,0x76,0x65,0x6c,0x20,0x2b,0x20,0x4c,0x55, +/*0019e0*/ 0x41,0x5f,0x4a,0x49,0x54,0x5f,0x53,0x45,0x54,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x57, +/*0019f0*/ 0x4f,0x52,0x4b,0x41,0x52,0x4f,0x55,0x4e,0x44,0x2c,0x20,0x69,0x2c,0x20,0x76,0x61, +/*001a00*/ 0x6c,0x75,0x65,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x69, +/*001a10*/ 0x20,0x3d,0x20,0x69,0x20,0x2b,0x20,0x31,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c, +/*001a20*/ 0x20,0x76,0x61,0x72,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x65,0x6e,0x64,0x0d, +/*001a30*/ 0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x53,0x65,0x74,0x20,0x61,0x6e,0x20,0x75, +/*001a40*/ 0x70,0x76,0x61,0x6c,0x75,0x65,0x2e,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*001a50*/ 0x66,0x75,0x6e,0x63,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74, +/*001a60*/ 0x69,0x6e,0x66,0x6f,0x28,0x6c,0x65,0x76,0x65,0x6c,0x29,0x2e,0x66,0x75,0x6e,0x63, +/*001a70*/ 0x0d,0x0a,0x09,0x64,0x6f,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20,0x3d,0x20, +/*001a80*/ 0x31,0x3b,0x20,0x72,0x65,0x70,0x65,0x61,0x74,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63, +/*001a90*/ 0x61,0x6c,0x20,0x76,0x61,0x72,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67, +/*001aa0*/ 0x65,0x74,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x28,0x66,0x75,0x6e,0x63,0x2c,0x20, +/*001ab0*/ 0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d, +/*001ac0*/ 0x20,0x76,0x61,0x72,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x64,0x62, +/*001ad0*/ 0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*001ae0*/ 0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67,0x65, +/*001af0*/ 0x72,0x2e,0x6c,0x75,0x61,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41, +/*001b00*/ 0x52,0x45,0x54,0x2e,0x2e,0x22,0x53,0x65,0x74,0x20,0x75,0x70,0x76,0x61,0x6c,0x75, +/*001b10*/ 0x65,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e, +/*001b20*/ 0x2e,0x6e,0x61,0x6d,0x65,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53, +/*001b30*/ 0x45,0x54,0x29,0x0d,0x0a,0x09,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64, +/*001b40*/ 0x65,0x62,0x75,0x67,0x2e,0x73,0x65,0x74,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x28, +/*001b50*/ 0x66,0x75,0x6e,0x63,0x2c,0x20,0x69,0x2c,0x20,0x76,0x61,0x6c,0x75,0x65,0x29,0x0d, +/*001b60*/ 0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x69,0x20,0x3d,0x20,0x69,0x20, +/*001b70*/ 0x2b,0x20,0x31,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c,0x20,0x76,0x61,0x72,0x20, +/*001b80*/ 0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09, +/*001b90*/ 0x2d,0x2d,0x20,0x53,0x65,0x74,0x20,0x61,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x2e, +/*001ba0*/ 0x0d,0x0a,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*001bb0*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65, +/*001bc0*/ 0x62,0x75,0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x22,0x2e,0x2e,0x47,0x52,0x45, +/*001bd0*/ 0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x53,0x65,0x74,0x20,0x67, +/*001be0*/ 0x6c,0x6f,0x62,0x61,0x6c,0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x20,0x22, +/*001bf0*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x6e,0x61, +/*001c00*/ 0x6d,0x65,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x29, +/*001c10*/ 0x0d,0x0a,0x09,0x5f,0x47,0x5b,0x6e,0x61,0x6d,0x65,0x5d,0x20,0x3d,0x20,0x76,0x61, +/*001c20*/ 0x6c,0x75,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x43, +/*001c30*/ 0x6f,0x6d,0x70,0x69,0x6c,0x65,0x20,0x61,0x6e,0x20,0x65,0x78,0x70,0x72,0x65,0x73, +/*001c40*/ 0x73,0x69,0x6f,0x6e,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x65,0x20,0x67,0x69, +/*001c50*/ 0x76,0x65,0x6e,0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x20,0x62,0x69,0x6e, +/*001c60*/ 0x64,0x69,0x6e,0x67,0x73,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75, +/*001c70*/ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x5f,0x63, +/*001c80*/ 0x68,0x75,0x6e,0x6b,0x28,0x62,0x6c,0x6f,0x63,0x6b,0x2c,0x20,0x65,0x6e,0x76,0x29, +/*001c90*/ 0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20, +/*001ca0*/ 0x3d,0x20,0x22,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x20, +/*001cb0*/ 0x52,0x45,0x50,0x4c,0x22,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x68, +/*001cc0*/ 0x75,0x6e,0x6b,0x20,0x3d,0x20,0x6e,0x69,0x6c,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69, +/*001cd0*/ 0x66,0x20,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x20,0x3c,0x3d,0x20,0x22,0x4c, +/*001ce0*/ 0x75,0x61,0x20,0x35,0x2e,0x31,0x22,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09, +/*001cf0*/ 0x63,0x68,0x75,0x6e,0x6b,0x20,0x3d,0x20,0x6c,0x6f,0x61,0x64,0x73,0x74,0x72,0x69, +/*001d00*/ 0x6e,0x67,0x28,0x62,0x6c,0x6f,0x63,0x6b,0x2c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65, +/*001d10*/ 0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x74,0x68, +/*001d20*/ 0x65,0x6e,0x20,0x73,0x65,0x74,0x66,0x65,0x6e,0x76,0x28,0x63,0x68,0x75,0x6e,0x6b, +/*001d30*/ 0x2c,0x20,0x65,0x6e,0x76,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6c,0x73, +/*001d40*/ 0x65,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x54,0x68,0x65,0x20,0x4c,0x75,0x61,0x20, +/*001d50*/ 0x35,0x2e,0x32,0x20,0x77,0x61,0x79,0x20,0x69,0x73,0x20,0x61,0x20,0x62,0x69,0x74, +/*001d60*/ 0x20,0x63,0x6c,0x65,0x61,0x6e,0x65,0x72,0x0d,0x0a,0x09,0x09,0x63,0x68,0x75,0x6e, +/*001d70*/ 0x6b,0x20,0x3d,0x20,0x6c,0x6f,0x61,0x64,0x28,0x62,0x6c,0x6f,0x63,0x6b,0x2c,0x20, +/*001d80*/ 0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x22,0x74,0x22,0x2c,0x20,0x65,0x6e,0x76, +/*001d90*/ 0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66,0x20, +/*001da0*/ 0x6e,0x6f,0x74,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x74,0x68,0x65,0x6e,0x20,0x64, +/*001db0*/ 0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52, +/*001dc0*/ 0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x72,0x72,0x6f,0x72,0x3a,0x20,0x43,0x6f, +/*001dd0*/ 0x75,0x6c,0x64,0x20,0x6e,0x6f,0x74,0x20,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x20, +/*001de0*/ 0x62,0x6c,0x6f,0x63,0x6b,0x3a,0x5c,0x6e,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*001df0*/ 0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x62,0x6c,0x6f,0x63,0x6b,0x29,0x20,0x65, +/*001e00*/ 0x6e,0x64,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x63,0x68,0x75,0x6e, +/*001e10*/ 0x6b,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*001e20*/ 0x53,0x4f,0x55,0x52,0x43,0x45,0x5f,0x43,0x41,0x43,0x48,0x45,0x20,0x3d,0x20,0x7b, +/*001e30*/ 0x7d,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74, +/*001e40*/ 0x69,0x6f,0x6e,0x20,0x77,0x68,0x65,0x72,0x65,0x28,0x69,0x6e,0x66,0x6f,0x2c,0x20, +/*001e50*/ 0x63,0x6f,0x6e,0x74,0x65,0x78,0x74,0x5f,0x6c,0x69,0x6e,0x65,0x73,0x29,0x0d,0x0a, +/*001e60*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x3d,0x20, +/*001e70*/ 0x53,0x4f,0x55,0x52,0x43,0x45,0x5f,0x43,0x41,0x43,0x48,0x45,0x5b,0x69,0x6e,0x66, +/*001e80*/ 0x6f,0x2e,0x73,0x6f,0x75,0x72,0x63,0x65,0x5d,0x0d,0x0a,0x09,0x69,0x66,0x20,0x6e, +/*001e90*/ 0x6f,0x74,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a, +/*001ea0*/ 0x09,0x09,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x3d,0x20,0x7b,0x7d,0x0d,0x0a,0x09, +/*001eb0*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20, +/*001ec0*/ 0x3d,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x73,0x6f,0x75,0x72,0x63,0x65,0x3a,0x6d,0x61, +/*001ed0*/ 0x74,0x63,0x68,0x28,0x22,0x40,0x28,0x2e,0x2a,0x29,0x22,0x29,0x0d,0x0a,0x09,0x09, +/*001ee0*/ 0x69,0x66,0x20,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20,0x74,0x68,0x65,0x6e, +/*001ef0*/ 0x0d,0x0a,0x09,0x09,0x09,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66,0x75,0x6e,0x63,0x74, +/*001f00*/ 0x69,0x6f,0x6e,0x28,0x29,0x20,0x66,0x6f,0x72,0x20,0x6c,0x69,0x6e,0x65,0x20,0x69, +/*001f10*/ 0x6e,0x20,0x69,0x6f,0x2e,0x6c,0x69,0x6e,0x65,0x73,0x28,0x66,0x69,0x6c,0x65,0x6e, +/*001f20*/ 0x61,0x6d,0x65,0x29,0x20,0x64,0x6f,0x20,0x74,0x61,0x62,0x6c,0x65,0x2e,0x69,0x6e, +/*001f30*/ 0x73,0x65,0x72,0x74,0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x6c,0x69,0x6e, +/*001f40*/ 0x65,0x29,0x20,0x65,0x6e,0x64,0x20,0x65,0x6e,0x64,0x29,0x0d,0x0a,0x09,0x09,0x65, +/*001f50*/ 0x6c,0x73,0x65,0x69,0x66,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x73,0x6f,0x75,0x72,0x63, +/*001f60*/ 0x65,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x66,0x6f,0x72,0x20,0x6c, +/*001f70*/ 0x69,0x6e,0x65,0x20,0x69,0x6e,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x73,0x6f,0x75,0x72, +/*001f80*/ 0x63,0x65,0x3a,0x67,0x6d,0x61,0x74,0x63,0x68,0x28,0x22,0x28,0x2e,0x2d,0x29,0x5c, +/*001f90*/ 0x6e,0x22,0x29,0x20,0x64,0x6f,0x20,0x74,0x61,0x62,0x6c,0x65,0x2e,0x69,0x6e,0x73, +/*001fa0*/ 0x65,0x72,0x74,0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x6c,0x69,0x6e,0x65, +/*001fb0*/ 0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09, +/*001fc0*/ 0x53,0x4f,0x55,0x52,0x43,0x45,0x5f,0x43,0x41,0x43,0x48,0x45,0x5b,0x69,0x6e,0x66, +/*001fd0*/ 0x6f,0x2e,0x73,0x6f,0x75,0x72,0x63,0x65,0x5d,0x20,0x3d,0x20,0x73,0x6f,0x75,0x72, +/*001fe0*/ 0x63,0x65,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66, +/*001ff0*/ 0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x61,0x6e,0x64,0x20,0x73,0x6f,0x75,0x72, +/*002000*/ 0x63,0x65,0x5b,0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x6c, +/*002010*/ 0x69,0x6e,0x65,0x5d,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x66,0x6f,0x72, +/*002020*/ 0x20,0x69,0x20,0x3d,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72,0x72,0x65,0x6e, +/*002030*/ 0x74,0x6c,0x69,0x6e,0x65,0x20,0x2d,0x20,0x63,0x6f,0x6e,0x74,0x65,0x78,0x74,0x5f, +/*002040*/ 0x6c,0x69,0x6e,0x65,0x73,0x2c,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72,0x72, +/*002050*/ 0x65,0x6e,0x74,0x6c,0x69,0x6e,0x65,0x20,0x2b,0x20,0x63,0x6f,0x6e,0x74,0x65,0x78, +/*002060*/ 0x74,0x5f,0x6c,0x69,0x6e,0x65,0x73,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x09,0x6c, +/*002070*/ 0x6f,0x63,0x61,0x6c,0x20,0x74,0x61,0x62,0x5f,0x6f,0x72,0x5f,0x63,0x61,0x72,0x65, +/*002080*/ 0x74,0x20,0x3d,0x20,0x28,0x69,0x20,0x3d,0x3d,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x63, +/*002090*/ 0x75,0x72,0x72,0x65,0x6e,0x74,0x6c,0x69,0x6e,0x65,0x20,0x61,0x6e,0x64,0x20,0x20, +/*0020a0*/ 0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x20,0x6f,0x72,0x20,0x22, +/*0020b0*/ 0x20,0x20,0x20,0x20,0x22,0x29,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*0020c0*/ 0x20,0x6c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x5b,0x69, +/*0020d0*/ 0x5d,0x0d,0x0a,0x09,0x09,0x09,0x69,0x66,0x20,0x6c,0x69,0x6e,0x65,0x20,0x74,0x68, +/*0020e0*/ 0x65,0x6e,0x20,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*0020f0*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x47,0x52,0x41,0x59,0x2e,0x2e,0x22,0x25,0x20,0x34,0x64, +/*002100*/ 0x22,0x2e,0x2e,0x74,0x61,0x62,0x5f,0x6f,0x72,0x5f,0x63,0x61,0x72,0x65,0x74,0x2e, +/*002110*/ 0x2e,0x22,0x25,0x73,0x22,0x2c,0x20,0x69,0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x20, +/*002120*/ 0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6c,0x73, +/*002130*/ 0x65,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e, +/*002140*/ 0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x72,0x72, +/*002150*/ 0x6f,0x72,0x3a,0x20,0x53,0x6f,0x75,0x72,0x63,0x65,0x20,0x6e,0x6f,0x74,0x20,0x61, +/*002160*/ 0x76,0x61,0x69,0x6c,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x22,0x2e,0x2e, +/*002170*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x69,0x6e,0x66,0x6f, +/*002180*/ 0x2e,0x73,0x68,0x6f,0x72,0x74,0x5f,0x73,0x72,0x63,0x29,0x3b,0x0d,0x0a,0x09,0x65, +/*002190*/ 0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66, +/*0021a0*/ 0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20, +/*0021b0*/ 0x57,0x65,0x65,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x64,0x69,0x66,0x66, +/*0021c0*/ 0x65,0x72,0x65,0x6e,0x63,0x65,0x73,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75, +/*0021d0*/ 0x6e,0x70,0x61,0x63,0x6b,0x20,0x3d,0x20,0x75,0x6e,0x70,0x61,0x63,0x6b,0x20,0x6f, +/*0021e0*/ 0x72,0x20,0x74,0x61,0x62,0x6c,0x65,0x2e,0x75,0x6e,0x70,0x61,0x63,0x6b,0x0d,0x0a, +/*0021f0*/ 0x6c,0x6f,0x63,0x61,0x6c,0x20,0x70,0x61,0x63,0x6b,0x20,0x3d,0x20,0x66,0x75,0x6e, +/*002200*/ 0x63,0x74,0x69,0x6f,0x6e,0x28,0x2e,0x2e,0x2e,0x29,0x20,0x72,0x65,0x74,0x75,0x72, +/*002210*/ 0x6e,0x20,0x7b,0x6e,0x20,0x3d,0x20,0x73,0x65,0x6c,0x65,0x63,0x74,0x28,0x22,0x23, +/*002220*/ 0x22,0x2c,0x20,0x2e,0x2e,0x2e,0x29,0x2c,0x20,0x2e,0x2e,0x2e,0x7d,0x20,0x65,0x6e, +/*002230*/ 0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74, +/*002240*/ 0x69,0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x73,0x74,0x65,0x70,0x28,0x29,0x0d,0x0a, +/*002250*/ 0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f, +/*002260*/ 0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f, +/*002270*/ 0x70,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x2c, +/*002280*/ 0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x73,0x74,0x65,0x70,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*002290*/ 0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f, +/*0022a0*/ 0x6e,0x20,0x63,0x6d,0x64,0x5f,0x6e,0x65,0x78,0x74,0x28,0x29,0x0d,0x0a,0x09,0x73, +/*0022b0*/ 0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66, +/*0022c0*/ 0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x0d, +/*0022d0*/ 0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x2c,0x20,0x68, +/*0022e0*/ 0x6f,0x6f,0x6b,0x5f,0x6e,0x65,0x78,0x74,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d, +/*0022f0*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*002300*/ 0x63,0x6d,0x64,0x5f,0x66,0x69,0x6e,0x69,0x73,0x68,0x28,0x29,0x0d,0x0a,0x09,0x6c, +/*002310*/ 0x6f,0x63,0x61,0x6c,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74, +/*002320*/ 0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x20,0x2d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f, +/*002330*/ 0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x0d,0x0a, +/*002340*/ 0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f, +/*002350*/ 0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f, +/*002360*/ 0x70,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x2c, +/*002370*/ 0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3c,0x20,0x30,0x20,0x61,0x6e,0x64,0x20, +/*002380*/ 0x68,0x6f,0x6f,0x6b,0x5f,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x6f,0x66,0x66, +/*002390*/ 0x73,0x65,0x74,0x20,0x2d,0x20,0x31,0x29,0x20,0x6f,0x72,0x20,0x68,0x6f,0x6f,0x6b, +/*0023a0*/ 0x5f,0x66,0x69,0x6e,0x69,0x73,0x68,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a, +/*0023b0*/ 0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63, +/*0023c0*/ 0x6d,0x64,0x5f,0x70,0x72,0x69,0x6e,0x74,0x28,0x65,0x78,0x70,0x72,0x29,0x0d,0x0a, +/*0023d0*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x76,0x20,0x3d,0x20,0x6c,0x6f,0x63, +/*0023e0*/ 0x61,0x6c,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x28,0x31,0x2c,0x20,0x74, +/*0023f0*/ 0x72,0x75,0x65,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x68,0x75, +/*002400*/ 0x6e,0x6b,0x20,0x3d,0x20,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x5f,0x63,0x68,0x75, +/*002410*/ 0x6e,0x6b,0x28,0x22,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x22,0x2e,0x2e,0x65,0x78, +/*002420*/ 0x70,0x72,0x2c,0x20,0x65,0x6e,0x76,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20,0x63,0x68, +/*002430*/ 0x75,0x6e,0x6b,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x74,0x68,0x65,0x6e,0x20, +/*002440*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x20,0x65,0x6e,0x64, +/*002450*/ 0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x43,0x61,0x6c,0x6c,0x20,0x74,0x68, +/*002460*/ 0x65,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x61,0x6e,0x64,0x20,0x63,0x6f,0x6c,0x6c, +/*002470*/ 0x65,0x63,0x74,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x2e, +/*002480*/ 0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73, +/*002490*/ 0x20,0x3d,0x20,0x70,0x61,0x63,0x6b,0x28,0x70,0x63,0x61,0x6c,0x6c,0x28,0x63,0x68, +/*0024a0*/ 0x75,0x6e,0x6b,0x2c,0x20,0x75,0x6e,0x70,0x61,0x63,0x6b,0x28,0x72,0x61,0x77,0x67, +/*0024b0*/ 0x65,0x74,0x28,0x65,0x6e,0x76,0x2c,0x20,0x22,0x2e,0x2e,0x2e,0x22,0x29,0x20,0x6f, +/*0024c0*/ 0x72,0x20,0x7b,0x7d,0x29,0x29,0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20, +/*0024d0*/ 0x54,0x68,0x65,0x20,0x66,0x69,0x72,0x73,0x74,0x20,0x72,0x65,0x73,0x75,0x6c,0x74, +/*0024e0*/ 0x20,0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x70,0x63,0x61,0x6c,0x6c,0x20,0x65,0x72, +/*0024f0*/ 0x72,0x6f,0x72,0x2e,0x0d,0x0a,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x72,0x65, +/*002500*/ 0x73,0x75,0x6c,0x74,0x73,0x5b,0x31,0x5d,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09, +/*002510*/ 0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c, +/*002520*/ 0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x72,0x72,0x6f,0x72,0x3a,0x22, +/*002530*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22, +/*002540*/ 0x20,0x22,0x2e,0x2e,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x5b,0x32,0x5d,0x29,0x0d, +/*002550*/ 0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*002560*/ 0x6f,0x75,0x74,0x70,0x75,0x74,0x20,0x3d,0x20,0x22,0x22,0x0d,0x0a,0x09,0x09,0x66, +/*002570*/ 0x6f,0x72,0x20,0x69,0x20,0x3d,0x20,0x32,0x2c,0x20,0x72,0x65,0x73,0x75,0x6c,0x74, +/*002580*/ 0x73,0x2e,0x6e,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x09,0x6f,0x75,0x74,0x70,0x75, +/*002590*/ 0x74,0x20,0x3d,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x2e,0x28,0x69,0x20,0x7e, +/*0025a0*/ 0x3d,0x20,0x32,0x20,0x61,0x6e,0x64,0x20,0x22,0x2c,0x20,0x22,0x20,0x6f,0x72,0x20, +/*0025b0*/ 0x22,0x22,0x29,0x2e,0x2e,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x28, +/*0025c0*/ 0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x5b,0x69,0x5d,0x29,0x0d,0x0a,0x09,0x09,0x65, +/*0025d0*/ 0x6e,0x64,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6f,0x75,0x74, +/*0025e0*/ 0x70,0x75,0x74,0x20,0x3d,0x3d,0x20,0x22,0x22,0x20,0x74,0x68,0x65,0x6e,0x20,0x6f, +/*0025f0*/ 0x75,0x74,0x70,0x75,0x74,0x20,0x3d,0x20,0x22,0x3c,0x6e,0x6f,0x20,0x72,0x65,0x73, +/*002600*/ 0x75,0x6c,0x74,0x3e,0x22,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67, +/*002610*/ 0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42, +/*002620*/ 0x4c,0x55,0x45,0x2e,0x2e,0x65,0x78,0x70,0x72,0x2e,0x2e,0x20,0x47,0x52,0x45,0x45, +/*002630*/ 0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x6f,0x75,0x74,0x70,0x75,0x74,0x29, +/*002640*/ 0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75, +/*002650*/ 0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d, +/*002660*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*002670*/ 0x63,0x6d,0x64,0x5f,0x65,0x76,0x61,0x6c,0x28,0x63,0x6f,0x64,0x65,0x29,0x0d,0x0a, +/*002680*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x76,0x20,0x3d,0x20,0x6c,0x6f,0x63, +/*002690*/ 0x61,0x6c,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x28,0x31,0x2c,0x20,0x74, +/*0026a0*/ 0x72,0x75,0x65,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6d,0x75,0x74, +/*0026b0*/ 0x61,0x62,0x6c,0x65,0x5f,0x65,0x6e,0x76,0x20,0x3d,0x20,0x73,0x65,0x74,0x6d,0x65, +/*0026c0*/ 0x74,0x61,0x74,0x61,0x62,0x6c,0x65,0x28,0x7b,0x7d,0x2c,0x20,0x7b,0x0d,0x0a,0x09, +/*0026d0*/ 0x09,0x5f,0x5f,0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x20,0x65,0x6e,0x76,0x2c,0x0d, +/*0026e0*/ 0x0a,0x09,0x09,0x5f,0x5f,0x6e,0x65,0x77,0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x20, +/*0026f0*/ 0x6d,0x75,0x74,0x61,0x74,0x65,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x2c, +/*002700*/ 0x0d,0x0a,0x09,0x7d,0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*002710*/ 0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x3d,0x20,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65, +/*002720*/ 0x5f,0x63,0x68,0x75,0x6e,0x6b,0x28,0x63,0x6f,0x64,0x65,0x2c,0x20,0x6d,0x75,0x74, +/*002730*/ 0x61,0x62,0x6c,0x65,0x5f,0x65,0x6e,0x76,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20,0x63, +/*002740*/ 0x68,0x75,0x6e,0x6b,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x74,0x68,0x65,0x6e, +/*002750*/ 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x20,0x65,0x6e, +/*002760*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x43,0x61,0x6c,0x6c,0x20,0x74, +/*002770*/ 0x68,0x65,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x61,0x6e,0x64,0x20,0x63,0x6f,0x6c, +/*002780*/ 0x6c,0x65,0x63,0x74,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73, +/*002790*/ 0x2e,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x75,0x63,0x63,0x65,0x73, +/*0027a0*/ 0x73,0x2c,0x20,0x65,0x72,0x72,0x20,0x3d,0x20,0x70,0x63,0x61,0x6c,0x6c,0x28,0x63, +/*0027b0*/ 0x68,0x75,0x6e,0x6b,0x2c,0x20,0x75,0x6e,0x70,0x61,0x63,0x6b,0x28,0x72,0x61,0x77, +/*0027c0*/ 0x67,0x65,0x74,0x28,0x65,0x6e,0x76,0x2c,0x20,0x22,0x2e,0x2e,0x2e,0x22,0x29,0x20, +/*0027d0*/ 0x6f,0x72,0x20,0x7b,0x7d,0x29,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74, +/*0027e0*/ 0x20,0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09, +/*0027f0*/ 0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c, +/*002800*/ 0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x72,0x72,0x6f,0x72,0x3a,0x22, +/*002810*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22, +/*002820*/ 0x20,0x22,0x2e,0x2e,0x74,0x6f,0x73,0x74,0x72,0x69,0x6e,0x67,0x28,0x65,0x72,0x72, +/*002830*/ 0x29,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65, +/*002840*/ 0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*002850*/ 0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f, +/*002860*/ 0x6e,0x20,0x63,0x6d,0x64,0x5f,0x64,0x6f,0x77,0x6e,0x28,0x29,0x0d,0x0a,0x09,0x6c, +/*002870*/ 0x6f,0x63,0x61,0x6c,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74, +/*002880*/ 0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73, +/*002890*/ 0x65,0x74,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x6e,0x66,0x6f,0x0d, +/*0028a0*/ 0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x70,0x65,0x61,0x74,0x20,0x2d,0x2d,0x20,0x46, +/*0028b0*/ 0x69,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x6e,0x65,0x78,0x74,0x20,0x66,0x72,0x61, +/*0028c0*/ 0x6d,0x65,0x20,0x77,0x69,0x74,0x68,0x20,0x61,0x20,0x66,0x69,0x6c,0x65,0x2e,0x0d, +/*0028d0*/ 0x0a,0x09,0x09,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x6f,0x66,0x66,0x73, +/*0028e0*/ 0x65,0x74,0x20,0x2b,0x20,0x31,0x0d,0x0a,0x09,0x09,0x69,0x6e,0x66,0x6f,0x20,0x3d, +/*0028f0*/ 0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x6f, +/*002900*/ 0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43, +/*002910*/ 0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x29,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c, +/*002920*/ 0x20,0x6e,0x6f,0x74,0x20,0x69,0x6e,0x66,0x6f,0x20,0x6f,0x72,0x20,0x66,0x72,0x61, +/*002930*/ 0x6d,0x65,0x5f,0x68,0x61,0x73,0x5f,0x6c,0x69,0x6e,0x65,0x28,0x69,0x6e,0x66,0x6f, +/*002940*/ 0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66,0x20,0x69,0x6e,0x66,0x6f,0x20,0x74, +/*002950*/ 0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73, +/*002960*/ 0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x6f,0x66, +/*002970*/ 0x66,0x73,0x65,0x74,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74, +/*002980*/ 0x65,0x6c,0x6e,0x28,0x22,0x49,0x6e,0x73,0x70,0x65,0x63,0x74,0x69,0x6e,0x67,0x20, +/*002990*/ 0x66,0x72,0x61,0x6d,0x65,0x3a,0x20,0x22,0x2e,0x2e,0x66,0x6f,0x72,0x6d,0x61,0x74, +/*0029a0*/ 0x5f,0x73,0x74,0x61,0x63,0x6b,0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66, +/*0029b0*/ 0x6f,0x28,0x69,0x6e,0x66,0x6f,0x29,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x74, +/*0029c0*/ 0x6f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x28,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f, +/*0029d0*/ 0x5f,0x77,0x68,0x65,0x72,0x65,0x29,0x20,0x74,0x68,0x65,0x6e,0x20,0x77,0x68,0x65, +/*0029e0*/ 0x72,0x65,0x28,0x69,0x6e,0x66,0x6f,0x2c,0x20,0x64,0x62,0x67,0x2e,0x61,0x75,0x74, +/*0029f0*/ 0x6f,0x5f,0x77,0x68,0x65,0x72,0x65,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65, +/*002a00*/ 0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65, +/*002a10*/ 0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63, +/*002a20*/ 0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74, +/*002a30*/ 0x20,0x2b,0x20,0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56, +/*002a40*/ 0x45,0x4c,0x29,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65, +/*002a50*/ 0x6c,0x6e,0x28,0x22,0x41,0x6c,0x72,0x65,0x61,0x64,0x79,0x20,0x61,0x74,0x20,0x74, +/*002a60*/ 0x68,0x65,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x20,0x6f,0x66,0x20,0x74,0x68,0x65, +/*002a70*/ 0x20,0x73,0x74,0x61,0x63,0x6b,0x2e,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d, +/*002a80*/ 0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73, +/*002a90*/ 0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*002aa0*/ 0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x75,0x70,0x28, +/*002ab0*/ 0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6f,0x66,0x66,0x73,0x65,0x74, +/*002ac0*/ 0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74, +/*002ad0*/ 0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*002ae0*/ 0x69,0x6e,0x66,0x6f,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x70,0x65,0x61,0x74, +/*002af0*/ 0x20,0x2d,0x2d,0x20,0x46,0x69,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x6e,0x65,0x78, +/*002b00*/ 0x74,0x20,0x66,0x72,0x61,0x6d,0x65,0x20,0x77,0x69,0x74,0x68,0x20,0x61,0x20,0x66, +/*002b10*/ 0x69,0x6c,0x65,0x2e,0x0d,0x0a,0x09,0x09,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d, +/*002b20*/ 0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2d,0x20,0x31,0x0d,0x0a,0x09,0x09,0x69, +/*002b30*/ 0x66,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3c,0x20,0x73,0x74,0x61,0x63,0x6b, +/*002b40*/ 0x5f,0x74,0x6f,0x70,0x20,0x74,0x68,0x65,0x6e,0x20,0x69,0x6e,0x66,0x6f,0x20,0x3d, +/*002b50*/ 0x20,0x6e,0x69,0x6c,0x3b,0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65,0x6e,0x64,0x0d, +/*002b60*/ 0x0a,0x09,0x09,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e, +/*002b70*/ 0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b, +/*002b80*/ 0x20,0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c, +/*002b90*/ 0x29,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c,0x20,0x66,0x72,0x61,0x6d,0x65,0x5f, +/*002ba0*/ 0x68,0x61,0x73,0x5f,0x6c,0x69,0x6e,0x65,0x28,0x69,0x6e,0x66,0x6f,0x29,0x0d,0x0a, +/*002bb0*/ 0x09,0x0d,0x0a,0x09,0x69,0x66,0x20,0x69,0x6e,0x66,0x6f,0x20,0x74,0x68,0x65,0x6e, +/*002bc0*/ 0x0d,0x0a,0x09,0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63, +/*002bd0*/ 0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x6f,0x66,0x66,0x73,0x65, +/*002be0*/ 0x74,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e, +/*002bf0*/ 0x28,0x22,0x49,0x6e,0x73,0x70,0x65,0x63,0x74,0x69,0x6e,0x67,0x20,0x66,0x72,0x61, +/*002c00*/ 0x6d,0x65,0x3a,0x20,0x22,0x2e,0x2e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x73,0x74, +/*002c10*/ 0x61,0x63,0x6b,0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66,0x6f,0x28,0x69, +/*002c20*/ 0x6e,0x66,0x6f,0x29,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x74,0x6f,0x6e,0x75, +/*002c30*/ 0x6d,0x62,0x65,0x72,0x28,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77,0x68, +/*002c40*/ 0x65,0x72,0x65,0x29,0x20,0x74,0x68,0x65,0x6e,0x20,0x77,0x68,0x65,0x72,0x65,0x28, +/*002c50*/ 0x69,0x6e,0x66,0x6f,0x2c,0x20,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77, +/*002c60*/ 0x68,0x65,0x72,0x65,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65, +/*002c70*/ 0x0d,0x0a,0x09,0x09,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67, +/*002c80*/ 0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69, +/*002c90*/ 0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20, +/*002ca0*/ 0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x29, +/*002cb0*/ 0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28, +/*002cc0*/ 0x22,0x41,0x6c,0x72,0x65,0x61,0x64,0x79,0x20,0x61,0x74,0x20,0x74,0x68,0x65,0x20, +/*002cd0*/ 0x74,0x6f,0x70,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x63,0x6b, +/*002ce0*/ 0x2e,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72, +/*002cf0*/ 0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64, +/*002d00*/ 0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69, +/*002d10*/ 0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x77,0x68,0x65,0x72,0x65,0x28,0x63,0x6f,0x6e, +/*002d20*/ 0x74,0x65,0x78,0x74,0x5f,0x6c,0x69,0x6e,0x65,0x73,0x29,0x0d,0x0a,0x09,0x6c,0x6f, +/*002d30*/ 0x63,0x61,0x6c,0x20,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67, +/*002d40*/ 0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69, +/*002d50*/ 0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20, +/*002d60*/ 0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x29, +/*002d70*/ 0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x69,0x6e,0x66,0x6f,0x20, +/*002d80*/ 0x61,0x6e,0x64,0x20,0x77,0x68,0x65,0x72,0x65,0x28,0x69,0x6e,0x66,0x6f,0x2c,0x20, +/*002d90*/ 0x74,0x6f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x28,0x63,0x6f,0x6e,0x74,0x65,0x78,0x74, +/*002da0*/ 0x5f,0x6c,0x69,0x6e,0x65,0x73,0x29,0x20,0x6f,0x72,0x20,0x35,0x29,0x29,0x0d,0x0a, +/*002db0*/ 0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e, +/*002dc0*/ 0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x74,0x72,0x61,0x63,0x65,0x28, +/*002dd0*/ 0x29,0x0d,0x0a,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28, +/*002de0*/ 0x22,0x49,0x6e,0x73,0x70,0x65,0x63,0x74,0x69,0x6e,0x67,0x20,0x66,0x72,0x61,0x6d, +/*002df0*/ 0x65,0x20,0x25,0x64,0x22,0x2c,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73, +/*002e00*/ 0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2d,0x20,0x73,0x74, +/*002e10*/ 0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*002e20*/ 0x20,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x74,0x72, +/*002e30*/ 0x75,0x65,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69, +/*002e40*/ 0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69, +/*002e50*/ 0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x20,0x2b,0x20, +/*002e60*/ 0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x20, +/*002e70*/ 0x2b,0x20,0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x69, +/*002e80*/ 0x6e,0x66,0x6f,0x20,0x74,0x68,0x65,0x6e,0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65, +/*002e90*/ 0x6e,0x64,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*002ea0*/ 0x69,0x73,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x5f,0x66,0x72,0x61,0x6d,0x65, +/*002eb0*/ 0x20,0x3d,0x20,0x28,0x69,0x20,0x2b,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f, +/*002ec0*/ 0x70,0x20,0x3d,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65, +/*002ed0*/ 0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x29,0x0d,0x0a,0x09,0x09,0x6c,0x6f, +/*002ee0*/ 0x63,0x61,0x6c,0x20,0x74,0x61,0x62,0x5f,0x6f,0x72,0x5f,0x63,0x61,0x72,0x65,0x74, +/*002ef0*/ 0x20,0x3d,0x20,0x28,0x69,0x73,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x5f,0x66, +/*002f00*/ 0x72,0x61,0x6d,0x65,0x20,0x61,0x6e,0x64,0x20,0x20,0x47,0x52,0x45,0x45,0x4e,0x5f, +/*002f10*/ 0x43,0x41,0x52,0x45,0x54,0x20,0x6f,0x72,0x20,0x22,0x20,0x20,0x20,0x20,0x22,0x29, +/*002f20*/ 0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28, +/*002f30*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x47,0x52,0x41,0x59,0x2e,0x2e,0x22,0x25,0x20,0x34, +/*002f40*/ 0x64,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e, +/*002f50*/ 0x2e,0x74,0x61,0x62,0x5f,0x6f,0x72,0x5f,0x63,0x61,0x72,0x65,0x74,0x2e,0x2e,0x22, +/*002f60*/ 0x25,0x73,0x22,0x2c,0x20,0x69,0x2c,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x73, +/*002f70*/ 0x74,0x61,0x63,0x6b,0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66,0x6f,0x28, +/*002f80*/ 0x69,0x6e,0x66,0x6f,0x29,0x29,0x0d,0x0a,0x09,0x09,0x69,0x20,0x3d,0x20,0x69,0x20, +/*002f90*/ 0x2b,0x20,0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72, +/*002fa0*/ 0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64, +/*002fb0*/ 0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69, +/*002fc0*/ 0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x73,0x28,0x29,0x0d, +/*002fd0*/ 0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73, +/*002fe0*/ 0x20,0x3d,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67, +/*002ff0*/ 0x73,0x28,0x31,0x2c,0x20,0x66,0x61,0x6c,0x73,0x65,0x29,0x0d,0x0a,0x09,0x0d,0x0a, +/*003000*/ 0x09,0x2d,0x2d,0x20,0x47,0x65,0x74,0x20,0x61,0x6c,0x6c,0x20,0x74,0x68,0x65,0x20, +/*003010*/ 0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67, +/*003020*/ 0x20,0x6e,0x61,0x6d,0x65,0x73,0x20,0x61,0x6e,0x64,0x20,0x73,0x6f,0x72,0x74,0x20, +/*003030*/ 0x74,0x68,0x65,0x6d,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6b,0x65,0x79, +/*003040*/ 0x73,0x20,0x3d,0x20,0x7b,0x7d,0x0d,0x0a,0x09,0x66,0x6f,0x72,0x20,0x6b,0x2c,0x20, +/*003050*/ 0x5f,0x20,0x69,0x6e,0x20,0x70,0x61,0x69,0x72,0x73,0x28,0x62,0x69,0x6e,0x64,0x69, +/*003060*/ 0x6e,0x67,0x73,0x29,0x20,0x64,0x6f,0x20,0x74,0x61,0x62,0x6c,0x65,0x2e,0x69,0x6e, +/*003070*/ 0x73,0x65,0x72,0x74,0x28,0x6b,0x65,0x79,0x73,0x2c,0x20,0x6b,0x29,0x20,0x65,0x6e, +/*003080*/ 0x64,0x0d,0x0a,0x09,0x74,0x61,0x62,0x6c,0x65,0x2e,0x73,0x6f,0x72,0x74,0x28,0x6b, +/*003090*/ 0x65,0x79,0x73,0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x66,0x6f,0x72,0x20,0x5f,0x2c, +/*0030a0*/ 0x20,0x6b,0x20,0x69,0x6e,0x20,0x69,0x70,0x61,0x69,0x72,0x73,0x28,0x6b,0x65,0x79, +/*0030b0*/ 0x73,0x29,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x76, +/*0030c0*/ 0x20,0x3d,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x5b,0x6b,0x5d,0x0d,0x0a, +/*0030d0*/ 0x09,0x09,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x53,0x6b,0x69,0x70,0x20,0x74,0x68, +/*0030e0*/ 0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x20,0x6f,0x62,0x6a,0x65,0x63, +/*0030f0*/ 0x74,0x20,0x69,0x74,0x73,0x65,0x6c,0x66,0x2c,0x20,0x22,0x28,0x2a,0x69,0x6e,0x74, +/*003100*/ 0x65,0x72,0x6e,0x61,0x6c,0x29,0x22,0x20,0x76,0x61,0x6c,0x75,0x65,0x73,0x2c,0x20, +/*003110*/ 0x61,0x6e,0x64,0x20,0x4c,0x75,0x61,0x20,0x35,0x2e,0x32,0x27,0x73,0x20,0x5f,0x45, +/*003120*/ 0x4e,0x56,0x20,0x6f,0x62,0x6a,0x65,0x63,0x74,0x2e,0x0d,0x0a,0x09,0x09,0x69,0x66, +/*003130*/ 0x20,0x6e,0x6f,0x74,0x20,0x72,0x61,0x77,0x65,0x71,0x75,0x61,0x6c,0x28,0x76,0x2c, +/*003140*/ 0x20,0x64,0x62,0x67,0x29,0x20,0x61,0x6e,0x64,0x20,0x6b,0x20,0x7e,0x3d,0x20,0x22, +/*003150*/ 0x5f,0x45,0x4e,0x56,0x22,0x20,0x61,0x6e,0x64,0x20,0x6e,0x6f,0x74,0x20,0x6b,0x3a, +/*003160*/ 0x6d,0x61,0x74,0x63,0x68,0x28,0x22,0x25,0x28,0x2e,0x2a,0x25,0x29,0x22,0x29,0x20, +/*003170*/ 0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69, +/*003180*/ 0x74,0x65,0x6c,0x6e,0x28,0x22,0x20,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*003190*/ 0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x6b,0x2e,0x2e,0x20,0x47,0x52,0x45,0x45,0x4e, +/*0031a0*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74, +/*0031b0*/ 0x74,0x79,0x28,0x76,0x29,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09, +/*0031c0*/ 0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*0031d0*/ 0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f, +/*0031e0*/ 0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6d,0x64, +/*0031f0*/ 0x5f,0x68,0x65,0x6c,0x70,0x28,0x29,0x0d,0x0a,0x09,0x64,0x62,0x67,0x2e,0x77,0x72, +/*003200*/ 0x69,0x74,0x65,0x28,0x22,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*003210*/ 0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x3c,0x72,0x65,0x74,0x75, +/*003220*/ 0x72,0x6e,0x3e,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45, +/*003230*/ 0x54,0x2e,0x2e,0x22,0x72,0x65,0x2d,0x72,0x75,0x6e,0x20,0x6c,0x61,0x73,0x74,0x20, +/*003240*/ 0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e, +/*003250*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x63, +/*003260*/ 0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e, +/*003270*/ 0x2e,0x22,0x28,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x29,0x22,0x2e,0x2e,0x47,0x52, +/*003280*/ 0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x63,0x6f,0x6e,0x74, +/*003290*/ 0x69,0x6e,0x75,0x65,0x20,0x65,0x78,0x65,0x63,0x75,0x74,0x69,0x6f,0x6e,0x5c,0x6e, +/*0032a0*/ 0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55, +/*0032b0*/ 0x45,0x2e,0x2e,0x22,0x20,0x20,0x73,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*0032c0*/ 0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x74,0x65,0x70,0x29,0x22,0x2e, +/*0032d0*/ 0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x73, +/*0032e0*/ 0x74,0x65,0x70,0x20,0x66,0x6f,0x72,0x77,0x61,0x72,0x64,0x20,0x62,0x79,0x20,0x6f, +/*0032f0*/ 0x6e,0x65,0x20,0x6c,0x69,0x6e,0x65,0x20,0x28,0x69,0x6e,0x74,0x6f,0x20,0x66,0x75, +/*003300*/ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x29,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e, +/*003310*/ 0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20, +/*003320*/ 0x6e,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57, +/*003330*/ 0x2e,0x2e,0x22,0x28,0x65,0x78,0x74,0x29,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e, +/*003340*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x73,0x74,0x65,0x70,0x20,0x66,0x6f, +/*003350*/ 0x72,0x77,0x61,0x72,0x64,0x20,0x62,0x79,0x20,0x6f,0x6e,0x65,0x20,0x6c,0x69,0x6e, +/*003360*/ 0x65,0x20,0x28,0x73,0x6b,0x69,0x70,0x70,0x69,0x6e,0x67,0x20,0x6f,0x76,0x65,0x72, +/*003370*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x29,0x5c,0x6e,0x22,0x0d,0x0a, +/*003380*/ 0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e, +/*003390*/ 0x22,0x20,0x20,0x66,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*0033a0*/ 0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x69,0x6e,0x69,0x73,0x68,0x29,0x22,0x2e,0x2e, +/*0033b0*/ 0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x73,0x74, +/*0033c0*/ 0x65,0x70,0x20,0x66,0x6f,0x72,0x77,0x61,0x72,0x64,0x20,0x75,0x6e,0x74,0x69,0x6c, +/*0033d0*/ 0x20,0x65,0x78,0x69,0x74,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72, +/*0033e0*/ 0x72,0x65,0x6e,0x74,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x5c,0x6e,0x22, +/*0033f0*/ 0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45, +/*003400*/ 0x2e,0x2e,0x22,0x20,0x20,0x75,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59, +/*003410*/ 0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x70,0x29,0x22,0x2e,0x2e,0x47,0x52, +/*003420*/ 0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x6d,0x6f,0x76,0x65, +/*003430*/ 0x20,0x75,0x70,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x62,0x79, +/*003440*/ 0x20,0x6f,0x6e,0x65,0x20,0x66,0x72,0x61,0x6d,0x65,0x5c,0x6e,0x22,0x0d,0x0a,0x09, +/*003450*/ 0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22, +/*003460*/ 0x20,0x20,0x64,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c, +/*003470*/ 0x4f,0x57,0x2e,0x2e,0x22,0x28,0x6f,0x77,0x6e,0x29,0x22,0x2e,0x2e,0x47,0x52,0x45, +/*003480*/ 0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x6d,0x6f,0x76,0x65,0x20, +/*003490*/ 0x64,0x6f,0x77,0x6e,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x62, +/*0034a0*/ 0x79,0x20,0x6f,0x6e,0x65,0x20,0x66,0x72,0x61,0x6d,0x65,0x5c,0x6e,0x22,0x0d,0x0a, +/*0034b0*/ 0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e, +/*0034c0*/ 0x22,0x20,0x20,0x77,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*0034d0*/ 0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x68,0x65,0x72,0x65,0x29,0x20,0x22,0x2e,0x2e, +/*0034e0*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x5b,0x6c,0x69, +/*0034f0*/ 0x6e,0x65,0x20,0x63,0x6f,0x75,0x6e,0x74,0x5d,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45, +/*003500*/ 0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x70,0x72,0x69,0x6e,0x74,0x20, +/*003510*/ 0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x63,0x6f,0x64,0x65,0x20,0x61,0x72,0x6f,0x75, +/*003520*/ 0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x20,0x6c, +/*003530*/ 0x69,0x6e,0x65,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*003540*/ 0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x65,0x22,0x2e,0x2e,0x43, +/*003550*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x76, +/*003560*/ 0x61,0x6c,0x29,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55, +/*003570*/ 0x45,0x2e,0x2e,0x22,0x5b,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x5d,0x22, +/*003580*/ 0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22, +/*003590*/ 0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x74, +/*0035a0*/ 0x65,0x6d,0x65,0x6e,0x74,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f, +/*0035b0*/ 0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x70,0x22,0x2e, +/*0035c0*/ 0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22, +/*0035d0*/ 0x28,0x72,0x69,0x6e,0x74,0x29,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*0035e0*/ 0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x5b,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69, +/*0035f0*/ 0x6f,0x6e,0x5d,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45, +/*003600*/ 0x54,0x2e,0x2e,0x22,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x20,0x74,0x68,0x65,0x20, +/*003610*/ 0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x20,0x61,0x6e,0x64,0x20,0x70, +/*003620*/ 0x72,0x69,0x6e,0x74,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x5c, +/*003630*/ 0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c, +/*003640*/ 0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x74,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*003650*/ 0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x72,0x61,0x63,0x65,0x29, +/*003660*/ 0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e, +/*003670*/ 0x22,0x70,0x72,0x69,0x6e,0x74,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x63,0x6b, +/*003680*/ 0x20,0x74,0x72,0x61,0x63,0x65,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43, +/*003690*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x6c,0x22, +/*0036a0*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e, +/*0036b0*/ 0x22,0x28,0x6f,0x63,0x61,0x6c,0x73,0x29,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e, +/*0036c0*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x70,0x72,0x69,0x6e,0x74,0x20,0x74, +/*0036d0*/ 0x68,0x65,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x61,0x72,0x67,0x75, +/*0036e0*/ 0x6d,0x65,0x6e,0x74,0x73,0x2c,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x73,0x20,0x61,0x6e, +/*0036f0*/ 0x64,0x20,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x73,0x2e,0x5c,0x6e,0x22,0x0d,0x0a, +/*003700*/ 0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e, +/*003710*/ 0x22,0x20,0x20,0x68,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*003720*/ 0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x65,0x6c,0x70,0x29,0x22,0x2e,0x2e,0x47,0x52, +/*003730*/ 0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x70,0x72,0x69,0x6e, +/*003740*/ 0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x5c,0x6e, +/*003750*/ 0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55, +/*003760*/ 0x45,0x2e,0x2e,0x22,0x20,0x20,0x71,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*003770*/ 0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x75,0x69,0x74,0x29,0x22,0x2e, +/*003780*/ 0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x68, +/*003790*/ 0x61,0x6c,0x74,0x20,0x65,0x78,0x65,0x63,0x75,0x74,0x69,0x6f,0x6e,0x5c,0x6e,0x22, +/*0037a0*/ 0x0d,0x0a,0x09,0x29,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61, +/*0037b0*/ 0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61, +/*0037c0*/ 0x6c,0x20,0x6c,0x61,0x73,0x74,0x5f,0x63,0x6d,0x64,0x20,0x3d,0x20,0x66,0x61,0x6c, +/*0037d0*/ 0x73,0x65,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x6f,0x6d,0x6d, +/*0037e0*/ 0x61,0x6e,0x64,0x73,0x20,0x3d,0x20,0x7b,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x63,0x24, +/*0037f0*/ 0x22,0x5d,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x20, +/*003800*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x20,0x65,0x6e,0x64,0x2c, +/*003810*/ 0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x73,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64, +/*003820*/ 0x5f,0x73,0x74,0x65,0x70,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x6e,0x24,0x22,0x5d, +/*003830*/ 0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x6e,0x65,0x78,0x74,0x2c,0x0d,0x0a,0x09,0x5b, +/*003840*/ 0x22,0x5e,0x66,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x66,0x69,0x6e, +/*003850*/ 0x69,0x73,0x68,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x70,0x25,0x73,0x2b,0x28,0x2e, +/*003860*/ 0x2a,0x29,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x70,0x72,0x69,0x6e, +/*003870*/ 0x74,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x65,0x25,0x73,0x2b,0x28,0x2e,0x2a,0x29, +/*003880*/ 0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x65,0x76,0x61,0x6c,0x2c,0x0d, +/*003890*/ 0x0a,0x09,0x5b,0x22,0x5e,0x75,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f, +/*0038a0*/ 0x75,0x70,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x64,0x24,0x22,0x5d,0x20,0x3d,0x20, +/*0038b0*/ 0x63,0x6d,0x64,0x5f,0x64,0x6f,0x77,0x6e,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x77, +/*0038c0*/ 0x25,0x73,0x2a,0x28,0x25,0x64,0x2a,0x29,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d, +/*0038d0*/ 0x64,0x5f,0x77,0x68,0x65,0x72,0x65,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x74,0x24, +/*0038e0*/ 0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x74,0x72,0x61,0x63,0x65,0x2c,0x0d, +/*0038f0*/ 0x0a,0x09,0x5b,0x22,0x5e,0x6c,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f, +/*003900*/ 0x6c,0x6f,0x63,0x61,0x6c,0x73,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x68,0x24,0x22, +/*003910*/ 0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x68,0x65,0x6c,0x70,0x2c,0x0d,0x0a,0x09, +/*003920*/ 0x5b,0x22,0x5e,0x71,0x24,0x22,0x5d,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69, +/*003930*/ 0x6f,0x6e,0x28,0x29,0x20,0x64,0x62,0x67,0x2e,0x65,0x78,0x69,0x74,0x28,0x30,0x29, +/*003940*/ 0x3b,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x20,0x65,0x6e, +/*003950*/ 0x64,0x2c,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66, +/*003960*/ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6d,0x61,0x74,0x63,0x68,0x5f,0x63,0x6f, +/*003970*/ 0x6d,0x6d,0x61,0x6e,0x64,0x28,0x6c,0x69,0x6e,0x65,0x29,0x0d,0x0a,0x09,0x66,0x6f, +/*003980*/ 0x72,0x20,0x70,0x61,0x74,0x2c,0x20,0x66,0x75,0x6e,0x63,0x20,0x69,0x6e,0x20,0x70, +/*003990*/ 0x61,0x69,0x72,0x73,0x28,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x73,0x29,0x20,0x64, +/*0039a0*/ 0x6f,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x75,0x72,0x6e,0x20,0x74, +/*0039b0*/ 0x68,0x65,0x20,0x6d,0x61,0x74,0x63,0x68,0x69,0x6e,0x67,0x20,0x63,0x6f,0x6d,0x6d, +/*0039c0*/ 0x61,0x6e,0x64,0x20,0x61,0x6e,0x64,0x20,0x63,0x61,0x70,0x74,0x75,0x72,0x65,0x20, +/*0039d0*/ 0x61,0x72,0x67,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20, +/*0039e0*/ 0x6c,0x69,0x6e,0x65,0x3a,0x66,0x69,0x6e,0x64,0x28,0x70,0x61,0x74,0x29,0x20,0x74, +/*0039f0*/ 0x68,0x65,0x6e,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x75,0x6e,0x63,0x2c, +/*003a00*/ 0x20,0x6c,0x69,0x6e,0x65,0x3a,0x6d,0x61,0x74,0x63,0x68,0x28,0x70,0x61,0x74,0x29, +/*003a10*/ 0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*003a20*/ 0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x52,0x75,0x6e,0x20,0x61,0x20,0x63,0x6f,0x6d,0x6d, +/*003a30*/ 0x61,0x6e,0x64,0x20,0x6c,0x69,0x6e,0x65,0x0d,0x0a,0x2d,0x2d,0x20,0x52,0x65,0x74, +/*003a40*/ 0x75,0x72,0x6e,0x73,0x20,0x74,0x72,0x75,0x65,0x20,0x69,0x66,0x20,0x74,0x68,0x65, +/*003a50*/ 0x20,0x52,0x45,0x50,0x4c,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x65,0x78,0x69, +/*003a60*/ 0x74,0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x6f,0x6b,0x20,0x66, +/*003a70*/ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x0d, +/*003a80*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*003a90*/ 0x72,0x75,0x6e,0x5f,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x28,0x6c,0x69,0x6e,0x65, +/*003aa0*/ 0x29,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x47,0x44,0x42,0x2f,0x4c,0x4c,0x44,0x42,0x20, +/*003ab0*/ 0x65,0x78,0x69,0x74,0x20,0x6f,0x6e,0x20,0x63,0x74,0x72,0x6c,0x2d,0x64,0x0d,0x0a, +/*003ac0*/ 0x09,0x69,0x66,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20, +/*003ad0*/ 0x74,0x68,0x65,0x6e,0x20,0x64,0x62,0x67,0x2e,0x65,0x78,0x69,0x74,0x28,0x31,0x29, +/*003ae0*/ 0x3b,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x20,0x65,0x6e, +/*003af0*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x52,0x65,0x2d,0x65,0x78,0x65, +/*003b00*/ 0x63,0x75,0x74,0x65,0x20,0x74,0x68,0x65,0x20,0x6c,0x61,0x73,0x74,0x20,0x63,0x6f, +/*003b10*/ 0x6d,0x6d,0x61,0x6e,0x64,0x20,0x69,0x66,0x20,0x79,0x6f,0x75,0x20,0x70,0x72,0x65, +/*003b20*/ 0x73,0x73,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x2e,0x0d,0x0a,0x09,0x69,0x66,0x20, +/*003b30*/ 0x6c,0x69,0x6e,0x65,0x20,0x3d,0x3d,0x20,0x22,0x22,0x20,0x74,0x68,0x65,0x6e,0x20, +/*003b40*/ 0x6c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x6c,0x61,0x73,0x74,0x5f,0x63,0x6d,0x64,0x20, +/*003b50*/ 0x6f,0x72,0x20,0x22,0x68,0x22,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09, +/*003b60*/ 0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x2c,0x20,0x63, +/*003b70*/ 0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x5f,0x61,0x72,0x67,0x20,0x3d,0x20,0x6d,0x61,0x74, +/*003b80*/ 0x63,0x68,0x5f,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x28,0x6c,0x69,0x6e,0x65,0x29, +/*003b90*/ 0x0d,0x0a,0x09,0x69,0x66,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x74,0x68, +/*003ba0*/ 0x65,0x6e,0x0d,0x0a,0x09,0x09,0x6c,0x61,0x73,0x74,0x5f,0x63,0x6d,0x64,0x20,0x3d, +/*003bb0*/ 0x20,0x6c,0x69,0x6e,0x65,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x75,0x6e,0x70,0x61, +/*003bc0*/ 0x63,0x6b,0x28,0x7b,0x2e,0x2e,0x2e,0x7d,0x29,0x20,0x70,0x72,0x65,0x76,0x65,0x6e, +/*003bd0*/ 0x74,0x73,0x20,0x74,0x61,0x69,0x6c,0x20,0x63,0x61,0x6c,0x6c,0x20,0x65,0x6c,0x69, +/*003be0*/ 0x6d,0x69,0x6e,0x61,0x74,0x69,0x6f,0x6e,0x20,0x73,0x6f,0x20,0x74,0x68,0x65,0x20, +/*003bf0*/ 0x73,0x74,0x61,0x63,0x6b,0x20,0x66,0x72,0x61,0x6d,0x65,0x20,0x69,0x6e,0x64,0x69, +/*003c00*/ 0x63,0x65,0x73,0x20,0x61,0x72,0x65,0x20,0x70,0x72,0x65,0x64,0x69,0x63,0x74,0x61, +/*003c10*/ 0x62,0x6c,0x65,0x2e,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x75, +/*003c20*/ 0x6e,0x70,0x61,0x63,0x6b,0x28,0x7b,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x28,0x63, +/*003c30*/ 0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x5f,0x61,0x72,0x67,0x29,0x7d,0x29,0x0d,0x0a,0x09, +/*003c40*/ 0x65,0x6c,0x73,0x65,0x69,0x66,0x20,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f, +/*003c50*/ 0x65,0x76,0x61,0x6c,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74, +/*003c60*/ 0x75,0x72,0x6e,0x20,0x75,0x6e,0x70,0x61,0x63,0x6b,0x28,0x7b,0x63,0x6d,0x64,0x5f, +/*003c70*/ 0x65,0x76,0x61,0x6c,0x28,0x6c,0x69,0x6e,0x65,0x29,0x7d,0x29,0x0d,0x0a,0x09,0x65, +/*003c80*/ 0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65, +/*003c90*/ 0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45, +/*003ca0*/ 0x72,0x72,0x6f,0x72,0x3a,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*003cb0*/ 0x53,0x45,0x54,0x2e,0x2e,0x22,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x27, +/*003cc0*/ 0x25,0x73,0x27,0x20,0x6e,0x6f,0x74,0x20,0x72,0x65,0x63,0x6f,0x67,0x6e,0x69,0x7a, +/*003cd0*/ 0x65,0x64,0x2e,0x5c,0x6e,0x54,0x79,0x70,0x65,0x20,0x27,0x68,0x27,0x20,0x61,0x6e, +/*003ce0*/ 0x64,0x20,0x70,0x72,0x65,0x73,0x73,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66, +/*003cf0*/ 0x6f,0x72,0x20,0x61,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x6c,0x69,0x73, +/*003d00*/ 0x74,0x2e,0x22,0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x0d,0x0a,0x09,0x09,0x72,0x65, +/*003d10*/ 0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x65,0x6e,0x64, +/*003d20*/ 0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x72,0x65,0x70,0x6c,0x20,0x3d,0x20, +/*003d30*/ 0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x72,0x65,0x61,0x73,0x6f,0x6e,0x29, +/*003d40*/ 0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x53,0x6b,0x69,0x70,0x20,0x66,0x72,0x61,0x6d,0x65, +/*003d50*/ 0x73,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x73,0x6f,0x75,0x72,0x63,0x65, +/*003d60*/ 0x20,0x69,0x6e,0x66,0x6f,0x2e,0x0d,0x0a,0x09,0x77,0x68,0x69,0x6c,0x65,0x20,0x6e, +/*003d70*/ 0x6f,0x74,0x20,0x66,0x72,0x61,0x6d,0x65,0x5f,0x68,0x61,0x73,0x5f,0x6c,0x69,0x6e, +/*003d80*/ 0x65,0x28,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28, +/*003d90*/ 0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66, +/*003da0*/ 0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b, +/*003db0*/ 0x5f,0x4c,0x45,0x56,0x45,0x4c,0x20,0x2d,0x20,0x33,0x29,0x29,0x20,0x64,0x6f,0x0d, +/*003dc0*/ 0x0a,0x09,0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74, +/*003dd0*/ 0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f, +/*003de0*/ 0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b, +/*003df0*/ 0x20,0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x6c,0x6f, +/*003e00*/ 0x63,0x61,0x6c,0x20,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67, +/*003e10*/ 0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69, +/*003e20*/ 0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20, +/*003e30*/ 0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x20, +/*003e40*/ 0x2d,0x20,0x33,0x29,0x0d,0x0a,0x09,0x72,0x65,0x61,0x73,0x6f,0x6e,0x20,0x3d,0x20, +/*003e50*/ 0x72,0x65,0x61,0x73,0x6f,0x6e,0x20,0x61,0x6e,0x64,0x20,0x28,0x43,0x4f,0x4c,0x4f, +/*003e60*/ 0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x62,0x72,0x65,0x61,0x6b, +/*003e70*/ 0x20,0x76,0x69,0x61,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*003e80*/ 0x44,0x2e,0x2e,0x72,0x65,0x61,0x73,0x6f,0x6e,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e, +/*003e90*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x29,0x20,0x6f,0x72,0x20,0x22,0x22,0x0d,0x0a,0x09, +/*003ea0*/ 0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x72,0x65,0x61,0x73, +/*003eb0*/ 0x6f,0x6e,0x2e,0x2e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x73,0x74,0x61,0x63,0x6b, +/*003ec0*/ 0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66,0x6f,0x28,0x69,0x6e,0x66,0x6f, +/*003ed0*/ 0x29,0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66,0x20,0x74,0x6f,0x6e,0x75,0x6d, +/*003ee0*/ 0x62,0x65,0x72,0x28,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77,0x68,0x65, +/*003ef0*/ 0x72,0x65,0x29,0x20,0x74,0x68,0x65,0x6e,0x20,0x77,0x68,0x65,0x72,0x65,0x28,0x69, +/*003f00*/ 0x6e,0x66,0x6f,0x2c,0x20,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77,0x68, +/*003f10*/ 0x65,0x72,0x65,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65, +/*003f20*/ 0x70,0x65,0x61,0x74,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x75, +/*003f30*/ 0x63,0x63,0x65,0x73,0x73,0x2c,0x20,0x64,0x6f,0x6e,0x65,0x2c,0x20,0x68,0x6f,0x6f, +/*003f40*/ 0x6b,0x20,0x3d,0x20,0x70,0x63,0x61,0x6c,0x6c,0x28,0x72,0x75,0x6e,0x5f,0x63,0x6f, +/*003f50*/ 0x6d,0x6d,0x61,0x6e,0x64,0x2c,0x20,0x64,0x62,0x67,0x2e,0x72,0x65,0x61,0x64,0x28, +/*003f60*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75, +/*003f70*/ 0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x3e,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c, +/*003f80*/ 0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x29,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66, +/*003f90*/ 0x20,0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09, +/*003fa0*/ 0x09,0x09,0x64,0x65,0x62,0x75,0x67,0x2e,0x73,0x65,0x74,0x68,0x6f,0x6f,0x6b,0x28, +/*003fb0*/ 0x68,0x6f,0x6f,0x6b,0x20,0x61,0x6e,0x64,0x20,0x68,0x6f,0x6f,0x6b,0x28,0x30,0x29, +/*003fc0*/ 0x2c,0x20,0x22,0x63,0x72,0x6c,0x22,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6c,0x73,0x65, +/*003fd0*/ 0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6d,0x65,0x73,0x73,0x61, +/*003fe0*/ 0x67,0x65,0x20,0x3d,0x20,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e, +/*003ff0*/ 0x22,0x49,0x4e,0x54,0x45,0x52,0x4e,0x41,0x4c,0x20,0x44,0x45,0x42,0x55,0x47,0x47, +/*004000*/ 0x45,0x52,0x2e,0x4c,0x55,0x41,0x20,0x45,0x52,0x52,0x4f,0x52,0x2e,0x20,0x41,0x42, +/*004010*/ 0x4f,0x52,0x54,0x49,0x4e,0x47,0x5c,0x6e,0x3a,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*004020*/ 0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x20,0x22,0x2e,0x2e,0x64,0x6f, +/*004030*/ 0x6e,0x65,0x0d,0x0a,0x09,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65, +/*004040*/ 0x6c,0x6e,0x28,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*004050*/ 0x65,0x72,0x72,0x6f,0x72,0x28,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a, +/*004060*/ 0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c,0x20,0x64,0x6f, +/*004070*/ 0x6e,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x4d,0x61, +/*004080*/ 0x6b,0x65,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x20, +/*004090*/ 0x6f,0x62,0x6a,0x65,0x63,0x74,0x20,0x63,0x61,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x20, +/*0040a0*/ 0x6c,0x69,0x6b,0x65,0x20,0x61,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x2e, +/*0040b0*/ 0x0d,0x0a,0x64,0x62,0x67,0x20,0x3d,0x20,0x73,0x65,0x74,0x6d,0x65,0x74,0x61,0x74, +/*0040c0*/ 0x61,0x62,0x6c,0x65,0x28,0x7b,0x7d,0x2c,0x20,0x7b,0x0d,0x0a,0x09,0x5f,0x5f,0x63, +/*0040d0*/ 0x61,0x6c,0x6c,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x5f, +/*0040e0*/ 0x2c,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x74,0x6f,0x70, +/*0040f0*/ 0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x2c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x29, +/*004100*/ 0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e, +/*004110*/ 0x20,0x74,0x68,0x65,0x6e,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x65,0x6e,0x64, +/*004120*/ 0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x74,0x6f,0x70,0x5f,0x6f,0x66,0x66,0x73, +/*004130*/ 0x65,0x74,0x20,0x3d,0x20,0x28,0x74,0x6f,0x70,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74, +/*004140*/ 0x20,0x6f,0x72,0x20,0x30,0x29,0x0d,0x0a,0x09,0x09,0x73,0x74,0x61,0x63,0x6b,0x5f, +/*004150*/ 0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d, +/*004160*/ 0x20,0x74,0x6f,0x70,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x0d,0x0a,0x09,0x09,0x73, +/*004170*/ 0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x20,0x3d,0x20,0x74,0x6f,0x70,0x5f,0x6f, +/*004180*/ 0x66,0x66,0x73,0x65,0x74,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x64,0x65,0x62, +/*004190*/ 0x75,0x67,0x2e,0x73,0x65,0x74,0x68,0x6f,0x6f,0x6b,0x28,0x68,0x6f,0x6f,0x6b,0x5f, +/*0041a0*/ 0x6e,0x65,0x78,0x74,0x28,0x31,0x2c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x6f, +/*0041b0*/ 0x72,0x20,0x22,0x64,0x62,0x67,0x28,0x29,0x22,0x29,0x2c,0x20,0x22,0x63,0x72,0x6c, +/*0041c0*/ 0x22,0x29,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x0d,0x0a,0x09,0x65, +/*0041d0*/ 0x6e,0x64,0x2c,0x0d,0x0a,0x7d,0x29,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x45,0x78, +/*0041e0*/ 0x70,0x6f,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65, +/*0041f0*/ 0x72,0x27,0x73,0x20,0x49,0x4f,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73, +/*004200*/ 0x2e,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x72,0x65,0x61,0x64,0x20,0x3d,0x20,0x64,0x62, +/*004210*/ 0x67,0x5f,0x72,0x65,0x61,0x64,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x77,0x72,0x69,0x74, +/*004220*/ 0x65,0x20,0x3d,0x20,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x0d,0x0a,0x64, +/*004230*/ 0x62,0x67,0x2e,0x73,0x68,0x6f,0x72,0x74,0x65,0x6e,0x5f,0x70,0x61,0x74,0x68,0x20, +/*004240*/ 0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x70,0x61,0x74,0x68, +/*004250*/ 0x29,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x70,0x61,0x74,0x68,0x20,0x65,0x6e, +/*004260*/ 0x64,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x65,0x78,0x69,0x74,0x20,0x3d,0x20,0x66,0x75, +/*004270*/ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x65,0x72,0x72,0x29,0x20,0x6f,0x73,0x2e,0x65, +/*004280*/ 0x78,0x69,0x74,0x28,0x65,0x72,0x72,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a, +/*004290*/ 0x64,0x62,0x67,0x2e,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x20,0x3d,0x20,0x64,0x62, +/*0042a0*/ 0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x0d,0x0a,0x0d,0x0a,0x64,0x62,0x67, +/*0042b0*/ 0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x5f,0x64,0x65,0x70,0x74,0x68,0x20,0x3d,0x20, +/*0042c0*/ 0x33,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x20,0x3d,0x20, +/*0042d0*/ 0x70,0x72,0x65,0x74,0x74,0x79,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x70,0x70,0x20,0x3d, +/*0042e0*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x76,0x61,0x6c,0x75,0x65,0x2c, +/*0042f0*/ 0x20,0x64,0x65,0x70,0x74,0x68,0x29,0x20,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74, +/*004300*/ 0x65,0x6c,0x6e,0x28,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x28,0x76, +/*004310*/ 0x61,0x6c,0x75,0x65,0x2c,0x20,0x64,0x65,0x70,0x74,0x68,0x29,0x29,0x20,0x65,0x6e, +/*004320*/ 0x64,0x0d,0x0a,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77,0x68, +/*004330*/ 0x65,0x72,0x65,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x64,0x62,0x67, +/*004340*/ 0x2e,0x61,0x75,0x74,0x6f,0x5f,0x65,0x76,0x61,0x6c,0x20,0x3d,0x20,0x66,0x61,0x6c, +/*004350*/ 0x73,0x65,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6c,0x75,0x61,0x5f, +/*004360*/ 0x65,0x72,0x72,0x6f,0x72,0x2c,0x20,0x6c,0x75,0x61,0x5f,0x61,0x73,0x73,0x65,0x72, +/*004370*/ 0x74,0x20,0x3d,0x20,0x65,0x72,0x72,0x6f,0x72,0x2c,0x20,0x61,0x73,0x73,0x65,0x72, +/*004380*/ 0x74,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x57,0x6f,0x72,0x6b,0x73,0x20,0x6c,0x69, +/*004390*/ 0x6b,0x65,0x20,0x65,0x72,0x72,0x6f,0x72,0x28,0x29,0x2c,0x20,0x62,0x75,0x74,0x20, +/*0043a0*/ 0x69,0x6e,0x76,0x6f,0x6b,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75, +/*0043b0*/ 0x67,0x67,0x65,0x72,0x2e,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*0043c0*/ 0x64,0x62,0x67,0x2e,0x65,0x72,0x72,0x6f,0x72,0x28,0x65,0x72,0x72,0x2c,0x20,0x6c, +/*0043d0*/ 0x65,0x76,0x65,0x6c,0x29,0x0d,0x0a,0x09,0x6c,0x65,0x76,0x65,0x6c,0x20,0x3d,0x20, +/*0043e0*/ 0x6c,0x65,0x76,0x65,0x6c,0x20,0x6f,0x72,0x20,0x31,0x0d,0x0a,0x09,0x64,0x62,0x67, +/*0043f0*/ 0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52, +/*004400*/ 0x45,0x44,0x2e,0x2e,0x22,0x45,0x52,0x52,0x4f,0x52,0x3a,0x20,0x22,0x2e,0x2e,0x43, +/*004410*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x64,0x62,0x67,0x2e, +/*004420*/ 0x70,0x72,0x65,0x74,0x74,0x79,0x28,0x65,0x72,0x72,0x29,0x29,0x0d,0x0a,0x09,0x64, +/*004430*/ 0x62,0x67,0x28,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x6c,0x65,0x76,0x65,0x6c,0x2c, +/*004440*/ 0x20,0x22,0x64,0x62,0x67,0x2e,0x65,0x72,0x72,0x6f,0x72,0x28,0x29,0x22,0x29,0x0d, +/*004450*/ 0x0a,0x09,0x0d,0x0a,0x09,0x6c,0x75,0x61,0x5f,0x65,0x72,0x72,0x6f,0x72,0x28,0x65, +/*004460*/ 0x72,0x72,0x2c,0x20,0x6c,0x65,0x76,0x65,0x6c,0x29,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*004470*/ 0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x57,0x6f,0x72,0x6b,0x73,0x20,0x6c,0x69,0x6b,0x65, +/*004480*/ 0x20,0x61,0x73,0x73,0x65,0x72,0x74,0x28,0x29,0x2c,0x20,0x62,0x75,0x74,0x20,0x69, +/*004490*/ 0x6e,0x76,0x6f,0x6b,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75,0x67, +/*0044a0*/ 0x67,0x65,0x72,0x20,0x6f,0x6e,0x20,0x61,0x20,0x66,0x61,0x69,0x6c,0x75,0x72,0x65, +/*0044b0*/ 0x2e,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x62,0x67,0x2e, +/*0044c0*/ 0x61,0x73,0x73,0x65,0x72,0x74,0x28,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e, +/*0044d0*/ 0x2c,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20, +/*0044e0*/ 0x6e,0x6f,0x74,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x20,0x74,0x68, +/*0044f0*/ 0x65,0x6e,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c, +/*004500*/ 0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x52, +/*004510*/ 0x52,0x4f,0x52,0x3a,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53, +/*004520*/ 0x45,0x54,0x2e,0x2e,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a,0x09,0x09, +/*004530*/ 0x64,0x62,0x67,0x28,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x31,0x2c,0x20,0x22,0x64, +/*004540*/ 0x62,0x67,0x2e,0x61,0x73,0x73,0x65,0x72,0x74,0x28,0x29,0x22,0x29,0x0d,0x0a,0x09, +/*004550*/ 0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*004560*/ 0x6c,0x75,0x61,0x5f,0x61,0x73,0x73,0x65,0x72,0x74,0x28,0x63,0x6f,0x6e,0x64,0x69, +/*004570*/ 0x74,0x69,0x6f,0x6e,0x2c,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a, +/*004580*/ 0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x57,0x6f,0x72,0x6b,0x73,0x20, +/*004590*/ 0x6c,0x69,0x6b,0x65,0x20,0x70,0x63,0x61,0x6c,0x6c,0x28,0x29,0x2c,0x20,0x62,0x75, +/*0045a0*/ 0x74,0x20,0x69,0x6e,0x76,0x6f,0x6b,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x64,0x65, +/*0045b0*/ 0x62,0x75,0x67,0x67,0x65,0x72,0x20,0x6f,0x6e,0x20,0x61,0x6e,0x20,0x65,0x72,0x72, +/*0045c0*/ 0x6f,0x72,0x2e,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x62, +/*0045d0*/ 0x67,0x2e,0x63,0x61,0x6c,0x6c,0x28,0x66,0x2c,0x20,0x2e,0x2e,0x2e,0x29,0x0d,0x0a, +/*0045e0*/ 0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x78,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66, +/*0045f0*/ 0x2c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x65,0x72,0x72,0x29,0x0d, +/*004600*/ 0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*004610*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x52,0x52,0x4f,0x52, +/*004620*/ 0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54, +/*004630*/ 0x2e,0x2e,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x28,0x65,0x72,0x72, +/*004640*/ 0x29,0x29,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x28,0x66,0x61,0x6c,0x73,0x65,0x2c, +/*004650*/ 0x20,0x31,0x2c,0x20,0x22,0x64,0x62,0x67,0x2e,0x63,0x61,0x6c,0x6c,0x28,0x29,0x22, +/*004660*/ 0x29,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*004670*/ 0x65,0x72,0x72,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x2c,0x20,0x2e,0x2e,0x2e,0x29,0x0d, +/*004680*/ 0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x45,0x72,0x72,0x6f,0x72, +/*004690*/ 0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x20,0x68,0x61,0x6e,0x64,0x6c,0x65,0x72, +/*0046a0*/ 0x20,0x74,0x68,0x61,0x74,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x75,0x73,0x65, +/*0046b0*/ 0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x6c,0x75,0x61,0x5f,0x70,0x63,0x61,0x6c,0x6c, +/*0046c0*/ 0x28,0x29,0x2e,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x62, +/*0046d0*/ 0x67,0x2e,0x6d,0x73,0x67,0x68,0x28,0x2e,0x2e,0x2e,0x29,0x0d,0x0a,0x09,0x69,0x66, +/*0046e0*/ 0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x32, +/*0046f0*/ 0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72, +/*004700*/ 0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e, +/*004710*/ 0x2e,0x22,0x45,0x52,0x52,0x4f,0x52,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*004720*/ 0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x64,0x62,0x67,0x2e,0x70,0x72,0x65, +/*004730*/ 0x74,0x74,0x79,0x28,0x2e,0x2e,0x2e,0x29,0x29,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67, +/*004740*/ 0x28,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x31,0x2c,0x20,0x22,0x64,0x62,0x67,0x2e, +/*004750*/ 0x6d,0x73,0x67,0x68,0x28,0x29,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d, +/*004760*/ 0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*004770*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67, +/*004780*/ 0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*004790*/ 0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x45,0x72,0x72,0x6f,0x72,0x20, +/*0047a0*/ 0x64,0x69,0x64,0x20,0x6e,0x6f,0x74,0x20,0x6f,0x63,0x63,0x75,0x72,0x20,0x69,0x6e, +/*0047b0*/ 0x20,0x4c,0x75,0x61,0x20,0x63,0x6f,0x64,0x65,0x2e,0x20,0x45,0x78,0x65,0x63,0x75, +/*0047c0*/ 0x74,0x69,0x6f,0x6e,0x20,0x77,0x69,0x6c,0x6c,0x20,0x63,0x6f,0x6e,0x74,0x69,0x6e, +/*0047d0*/ 0x75,0x65,0x20,0x61,0x66,0x74,0x65,0x72,0x20,0x64,0x62,0x67,0x5f,0x70,0x63,0x61, +/*0047e0*/ 0x6c,0x6c,0x28,0x29,0x2e,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09, +/*0047f0*/ 0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x2e,0x2e,0x2e,0x0d,0x0a,0x65, +/*004800*/ 0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x41,0x73,0x73,0x75,0x6d,0x65,0x20, +/*004810*/ 0x73,0x74,0x64,0x69,0x6e,0x2f,0x6f,0x75,0x74,0x20,0x61,0x72,0x65,0x20,0x54,0x54, +/*004820*/ 0x59,0x73,0x20,0x75,0x6e,0x6c,0x65,0x73,0x73,0x20,0x77,0x65,0x20,0x63,0x61,0x6e, +/*004830*/ 0x20,0x75,0x73,0x65,0x20,0x4c,0x75,0x61,0x4a,0x49,0x54,0x27,0x73,0x20,0x46,0x46, +/*004840*/ 0x49,0x20,0x74,0x6f,0x20,0x70,0x72,0x6f,0x70,0x65,0x72,0x6c,0x79,0x20,0x63,0x68, +/*004850*/ 0x65,0x63,0x6b,0x20,0x74,0x68,0x65,0x6d,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c, +/*004860*/ 0x20,0x73,0x74,0x64,0x69,0x6e,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x3d,0x20, +/*004870*/ 0x74,0x72,0x75,0x65,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x74,0x64,0x6f, +/*004880*/ 0x75,0x74,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x3d,0x20,0x74,0x72,0x75,0x65, +/*004890*/ 0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e, +/*0048a0*/ 0x61,0x6c,0x6c,0x79,0x20,0x65,0x6e,0x61,0x62,0x6c,0x65,0x20,0x74,0x68,0x65,0x20, +/*0048b0*/ 0x4c,0x75,0x61,0x4a,0x49,0x54,0x20,0x46,0x46,0x49,0x2e,0x0d,0x0a,0x6c,0x6f,0x63, +/*0048c0*/ 0x61,0x6c,0x20,0x66,0x66,0x69,0x20,0x3d,0x20,0x28,0x6a,0x69,0x74,0x20,0x61,0x6e, +/*0048d0*/ 0x64,0x20,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x28,0x22,0x66,0x66,0x69,0x22,0x29, +/*0048e0*/ 0x29,0x0d,0x0a,0x69,0x66,0x20,0x66,0x66,0x69,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a, +/*0048f0*/ 0x09,0x66,0x66,0x69,0x2e,0x63,0x64,0x65,0x66,0x5b,0x5b,0x0d,0x0a,0x09,0x09,0x69, +/*004900*/ 0x6e,0x74,0x20,0x69,0x73,0x61,0x74,0x74,0x79,0x28,0x69,0x6e,0x74,0x29,0x3b,0x20, +/*004910*/ 0x2f,0x2f,0x20,0x55,0x6e,0x69,0x78,0x0d,0x0a,0x09,0x09,0x69,0x6e,0x74,0x20,0x5f, +/*004920*/ 0x69,0x73,0x61,0x74,0x74,0x79,0x28,0x69,0x6e,0x74,0x29,0x3b,0x20,0x2f,0x2f,0x20, +/*004930*/ 0x57,0x69,0x6e,0x64,0x6f,0x77,0x73,0x0d,0x0a,0x09,0x09,0x76,0x6f,0x69,0x64,0x20, +/*004940*/ 0x66,0x72,0x65,0x65,0x28,0x76,0x6f,0x69,0x64,0x20,0x2a,0x70,0x74,0x72,0x29,0x3b, +/*004950*/ 0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x63,0x68,0x61,0x72,0x20,0x2a,0x72,0x65, +/*004960*/ 0x61,0x64,0x6c,0x69,0x6e,0x65,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x63,0x68,0x61, +/*004970*/ 0x72,0x20,0x2a,0x29,0x3b,0x0d,0x0a,0x09,0x09,0x69,0x6e,0x74,0x20,0x61,0x64,0x64, +/*004980*/ 0x5f,0x68,0x69,0x73,0x74,0x6f,0x72,0x79,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x63, +/*004990*/ 0x68,0x61,0x72,0x20,0x2a,0x29,0x3b,0x0d,0x0a,0x09,0x5d,0x5d,0x0d,0x0a,0x09,0x0d, +/*0049a0*/ 0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e, +/*0049b0*/ 0x20,0x67,0x65,0x74,0x5f,0x66,0x75,0x6e,0x63,0x5f,0x6f,0x72,0x5f,0x6e,0x69,0x6c, +/*0049c0*/ 0x28,0x73,0x79,0x6d,0x29,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73, +/*0049d0*/ 0x75,0x63,0x63,0x65,0x73,0x73,0x2c,0x20,0x66,0x75,0x6e,0x63,0x20,0x3d,0x20,0x70, +/*0049e0*/ 0x63,0x61,0x6c,0x6c,0x28,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x20, +/*0049f0*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x66,0x69,0x2e,0x43,0x5b,0x73,0x79,0x6d, +/*004a00*/ 0x5d,0x20,0x65,0x6e,0x64,0x29,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e, +/*004a10*/ 0x20,0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x20,0x61,0x6e,0x64,0x20,0x66,0x75,0x6e, +/*004a20*/ 0x63,0x20,0x6f,0x72,0x20,0x6e,0x69,0x6c,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a, +/*004a30*/ 0x09,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x73,0x61,0x74,0x74,0x79, +/*004a40*/ 0x20,0x3d,0x20,0x67,0x65,0x74,0x5f,0x66,0x75,0x6e,0x63,0x5f,0x6f,0x72,0x5f,0x6e, +/*004a50*/ 0x69,0x6c,0x28,0x22,0x69,0x73,0x61,0x74,0x74,0x79,0x22,0x29,0x20,0x6f,0x72,0x20, +/*004a60*/ 0x67,0x65,0x74,0x5f,0x66,0x75,0x6e,0x63,0x5f,0x6f,0x72,0x5f,0x6e,0x69,0x6c,0x28, +/*004a70*/ 0x22,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x22,0x29,0x20,0x6f,0x72,0x20,0x28,0x66, +/*004a80*/ 0x66,0x69,0x2e,0x6c,0x6f,0x61,0x64,0x28,0x22,0x75,0x63,0x72,0x74,0x62,0x61,0x73, +/*004a90*/ 0x65,0x22,0x29,0x29,0x5b,0x22,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x22,0x5d,0x0d, +/*004aa0*/ 0x0a,0x09,0x73,0x74,0x64,0x69,0x6e,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x3d, +/*004ab0*/ 0x20,0x69,0x73,0x61,0x74,0x74,0x79,0x28,0x30,0x29,0x0d,0x0a,0x09,0x73,0x74,0x64, +/*004ac0*/ 0x6f,0x75,0x74,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x3d,0x20,0x69,0x73,0x61, +/*004ad0*/ 0x74,0x74,0x79,0x28,0x31,0x29,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d, +/*004ae0*/ 0x2d,0x20,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x6c,0x79,0x20, +/*004af0*/ 0x65,0x6e,0x61,0x62,0x6c,0x65,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x73,0x75,0x70, +/*004b00*/ 0x70,0x6f,0x72,0x74,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x6f,0x6c, +/*004b10*/ 0x6f,0x72,0x5f,0x6d,0x61,0x79,0x62,0x65,0x5f,0x73,0x75,0x70,0x70,0x6f,0x72,0x74, +/*004b20*/ 0x65,0x64,0x20,0x3d,0x20,0x28,0x73,0x74,0x64,0x6f,0x75,0x74,0x5f,0x69,0x73,0x61, +/*004b30*/ 0x74,0x74,0x79,0x20,0x61,0x6e,0x64,0x20,0x6f,0x73,0x2e,0x67,0x65,0x74,0x65,0x6e, +/*004b40*/ 0x76,0x28,0x22,0x54,0x45,0x52,0x4d,0x22,0x29,0x20,0x61,0x6e,0x64,0x20,0x6f,0x73, +/*004b50*/ 0x2e,0x67,0x65,0x74,0x65,0x6e,0x76,0x28,0x22,0x54,0x45,0x52,0x4d,0x22,0x29,0x20, +/*004b60*/ 0x7e,0x3d,0x20,0x22,0x64,0x75,0x6d,0x62,0x22,0x29,0x0d,0x0a,0x69,0x66,0x20,0x63, +/*004b70*/ 0x6f,0x6c,0x6f,0x72,0x5f,0x6d,0x61,0x79,0x62,0x65,0x5f,0x73,0x75,0x70,0x70,0x6f, +/*004b80*/ 0x72,0x74,0x65,0x64,0x20,0x61,0x6e,0x64,0x20,0x6e,0x6f,0x74,0x20,0x6f,0x73,0x2e, +/*004b90*/ 0x67,0x65,0x74,0x65,0x6e,0x76,0x28,0x22,0x44,0x42,0x47,0x5f,0x4e,0x4f,0x43,0x4f, +/*004ba0*/ 0x4c,0x4f,0x52,0x22,0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x43,0x4f,0x4c, +/*004bb0*/ 0x4f,0x52,0x5f,0x47,0x52,0x41,0x59,0x20,0x3d,0x20,0x73,0x74,0x72,0x69,0x6e,0x67, +/*004bc0*/ 0x2e,0x63,0x68,0x61,0x72,0x28,0x32,0x37,0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b,0x39, +/*004bd0*/ 0x30,0x6d,0x22,0x0d,0x0a,0x09,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x20, +/*004be0*/ 0x3d,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x63,0x68,0x61,0x72,0x28,0x32,0x37, +/*004bf0*/ 0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b,0x39,0x31,0x6d,0x22,0x0d,0x0a,0x09,0x43,0x4f, +/*004c00*/ 0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x20,0x3d,0x20,0x73,0x74,0x72,0x69,0x6e, +/*004c10*/ 0x67,0x2e,0x63,0x68,0x61,0x72,0x28,0x32,0x37,0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b, +/*004c20*/ 0x39,0x34,0x6d,0x22,0x0d,0x0a,0x09,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*004c30*/ 0x4c,0x4f,0x57,0x20,0x3d,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x63,0x68,0x61, +/*004c40*/ 0x72,0x28,0x32,0x37,0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b,0x33,0x33,0x6d,0x22,0x0d, +/*004c50*/ 0x0a,0x09,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x20,0x3d,0x20, +/*004c60*/ 0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x63,0x68,0x61,0x72,0x28,0x32,0x37,0x29,0x20, +/*004c70*/ 0x2e,0x2e,0x20,0x22,0x5b,0x30,0x6d,0x22,0x0d,0x0a,0x09,0x47,0x52,0x45,0x45,0x4e, +/*004c80*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x20,0x3d,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e, +/*004c90*/ 0x63,0x68,0x61,0x72,0x28,0x32,0x37,0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b,0x39,0x32, +/*004ca0*/ 0x6d,0x20,0x3d,0x3e,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*004cb0*/ 0x53,0x45,0x54,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x69,0x66,0x20,0x73, +/*004cc0*/ 0x74,0x64,0x69,0x6e,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x61,0x6e,0x64,0x20, +/*004cd0*/ 0x6e,0x6f,0x74,0x20,0x6f,0x73,0x2e,0x67,0x65,0x74,0x65,0x6e,0x76,0x28,0x22,0x44, +/*004ce0*/ 0x42,0x47,0x5f,0x4e,0x4f,0x52,0x45,0x41,0x44,0x4c,0x49,0x4e,0x45,0x22,0x29,0x20, +/*004cf0*/ 0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66,0x75,0x6e, +/*004d00*/ 0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*004d10*/ 0x20,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x20,0x3d,0x20,0x72,0x65,0x71, +/*004d20*/ 0x75,0x69,0x72,0x65,0x20,0x27,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x27, +/*004d30*/ 0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x4c,0x6f,0x61,0x64,0x20, +/*004d40*/ 0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x68,0x69,0x73,0x74,0x6f,0x72,0x79,0x20, +/*004d50*/ 0x66,0x72,0x6f,0x6d,0x20,0x7e,0x2f,0x2e,0x6c,0x75,0x61,0x5f,0x68,0x69,0x73,0x74, +/*004d60*/ 0x6f,0x72,0x79,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x68,0x69,0x73, +/*004d70*/ 0x74,0x5f,0x70,0x61,0x74,0x68,0x20,0x3d,0x20,0x6f,0x73,0x2e,0x67,0x65,0x74,0x65, +/*004d80*/ 0x6e,0x76,0x28,0x27,0x48,0x4f,0x4d,0x45,0x27,0x29,0x20,0x2e,0x2e,0x20,0x27,0x2f, +/*004d90*/ 0x2e,0x6c,0x75,0x61,0x5f,0x68,0x69,0x73,0x74,0x6f,0x72,0x79,0x27,0x0d,0x0a,0x09, +/*004da0*/ 0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x68,0x69,0x73,0x74,0x6f, +/*004db0*/ 0x72,0x79,0x6c,0x6f,0x61,0x64,0x28,0x68,0x69,0x73,0x74,0x5f,0x70,0x61,0x74,0x68, +/*004dc0*/ 0x29,0x0d,0x0a,0x09,0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x68, +/*004dd0*/ 0x69,0x73,0x74,0x6f,0x72,0x79,0x73,0x65,0x74,0x6d,0x61,0x78,0x6c,0x65,0x6e,0x28, +/*004de0*/ 0x35,0x30,0x29,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*004df0*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x61,0x75,0x74,0x6f,0x63,0x6f, +/*004e00*/ 0x6d,0x70,0x6c,0x65,0x74,0x65,0x28,0x65,0x6e,0x76,0x2c,0x20,0x69,0x6e,0x70,0x75, +/*004e10*/ 0x74,0x2c,0x20,0x6d,0x61,0x74,0x63,0x68,0x65,0x73,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*004e20*/ 0x66,0x6f,0x72,0x20,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x5f,0x20,0x69,0x6e,0x20,0x70, +/*004e30*/ 0x61,0x69,0x72,0x73,0x28,0x65,0x6e,0x76,0x29,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09, +/*004e40*/ 0x09,0x09,0x69,0x66,0x20,0x6e,0x61,0x6d,0x65,0x3a,0x6d,0x61,0x74,0x63,0x68,0x28, +/*004e50*/ 0x27,0x5e,0x27,0x20,0x2e,0x2e,0x20,0x69,0x6e,0x70,0x75,0x74,0x20,0x2e,0x2e,0x20, +/*004e60*/ 0x27,0x2e,0x2a,0x27,0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x09, +/*004e70*/ 0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x61,0x64,0x64,0x63,0x6f, +/*004e80*/ 0x6d,0x70,0x6c,0x65,0x74,0x69,0x6f,0x6e,0x28,0x6d,0x61,0x74,0x63,0x68,0x65,0x73, +/*004e90*/ 0x2c,0x20,0x6e,0x61,0x6d,0x65,0x29,0x0d,0x0a,0x09,0x09,0x09,0x09,0x65,0x6e,0x64, +/*004ea0*/ 0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d, +/*004eb0*/ 0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x41,0x75,0x74,0x6f,0x2d,0x63, +/*004ec0*/ 0x6f,0x6d,0x70,0x6c,0x65,0x74,0x69,0x6f,0x6e,0x20,0x66,0x6f,0x72,0x20,0x6c,0x6f, +/*004ed0*/ 0x63,0x61,0x6c,0x73,0x20,0x61,0x6e,0x64,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x73, +/*004ee0*/ 0x0d,0x0a,0x09,0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x73,0x65, +/*004ef0*/ 0x74,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x74,0x69,0x6f,0x6e,0x28,0x66,0x75,0x6e,0x63, +/*004f00*/ 0x74,0x69,0x6f,0x6e,0x28,0x6d,0x61,0x74,0x63,0x68,0x65,0x73,0x2c,0x20,0x69,0x6e, +/*004f10*/ 0x70,0x75,0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d,0x20,0x46,0x69,0x72,0x73, +/*004f20*/ 0x74,0x2c,0x20,0x63,0x68,0x65,0x63,0x6b,0x20,0x74,0x68,0x65,0x20,0x6c,0x6f,0x63, +/*004f30*/ 0x61,0x6c,0x73,0x20,0x61,0x6e,0x64,0x20,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x73, +/*004f40*/ 0x2e,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x76,0x20, +/*004f50*/ 0x3d,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73, +/*004f60*/ 0x28,0x31,0x2c,0x20,0x74,0x72,0x75,0x65,0x29,0x0d,0x0a,0x09,0x09,0x09,0x61,0x75, +/*004f70*/ 0x74,0x6f,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x74,0x65,0x28,0x65,0x6e,0x76,0x2c,0x20, +/*004f80*/ 0x69,0x6e,0x70,0x75,0x74,0x2c,0x20,0x6d,0x61,0x74,0x63,0x68,0x65,0x73,0x29,0x0d, +/*004f90*/ 0x0a,0x09,0x09,0x09,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d,0x20,0x54,0x68,0x65,0x6e, +/*004fa0*/ 0x2c,0x20,0x63,0x68,0x65,0x63,0x6b,0x20,0x74,0x68,0x65,0x20,0x69,0x6d,0x70,0x6c, +/*004fb0*/ 0x69,0x63,0x69,0x74,0x20,0x65,0x6e,0x76,0x69,0x72,0x6f,0x6e,0x6d,0x65,0x6e,0x74, +/*004fc0*/ 0x2e,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x76,0x20,0x3d,0x20,0x67,0x65,0x74,0x6d, +/*004fd0*/ 0x65,0x74,0x61,0x74,0x61,0x62,0x6c,0x65,0x28,0x65,0x6e,0x76,0x29,0x2e,0x5f,0x5f, +/*004fe0*/ 0x69,0x6e,0x64,0x65,0x78,0x0d,0x0a,0x09,0x09,0x09,0x61,0x75,0x74,0x6f,0x63,0x6f, +/*004ff0*/ 0x6d,0x70,0x6c,0x65,0x74,0x65,0x28,0x65,0x6e,0x76,0x2c,0x20,0x69,0x6e,0x70,0x75, +/*005000*/ 0x74,0x2c,0x20,0x6d,0x61,0x74,0x63,0x68,0x65,0x73,0x29,0x0d,0x0a,0x09,0x09,0x65, +/*005010*/ 0x6e,0x64,0x29,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x2e,0x72, +/*005020*/ 0x65,0x61,0x64,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x70, +/*005030*/ 0x72,0x6f,0x6d,0x70,0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*005040*/ 0x20,0x73,0x74,0x72,0x20,0x3d,0x20,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65, +/*005050*/ 0x2e,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x28,0x70,0x72,0x6f,0x6d,0x70, +/*005060*/ 0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x69,0x66,0x20,0x73,0x74,0x72,0x20,0x61,0x6e, +/*005070*/ 0x64,0x20,0x6e,0x6f,0x74,0x20,0x73,0x74,0x72,0x3a,0x6d,0x61,0x74,0x63,0x68,0x20, +/*005080*/ 0x22,0x5e,0x25,0x73,0x2a,0x24,0x22,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09, +/*005090*/ 0x09,0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x68,0x69,0x73,0x74, +/*0050a0*/ 0x6f,0x72,0x79,0x61,0x64,0x64,0x28,0x73,0x74,0x72,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*0050b0*/ 0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x68,0x69,0x73,0x74,0x6f, +/*0050c0*/ 0x72,0x79,0x73,0x61,0x76,0x65,0x28,0x68,0x69,0x73,0x74,0x5f,0x70,0x61,0x74,0x68, +/*0050d0*/ 0x29,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x72,0x65, +/*0050e0*/ 0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x72,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d, +/*0050f0*/ 0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*005100*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65, +/*005110*/ 0x62,0x75,0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43, +/*005120*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x4c,0x69,0x6e, +/*005130*/ 0x65,0x6e,0x6f,0x69,0x73,0x65,0x20,0x73,0x75,0x70,0x70,0x6f,0x72,0x74,0x20,0x65, +/*005140*/ 0x6e,0x61,0x62,0x6c,0x65,0x64,0x2e,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x29, +/*005150*/ 0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69, +/*005160*/ 0x6f,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x65,0x6e,0x61,0x62,0x6c,0x65,0x20,0x4c,0x75, +/*005170*/ 0x61,0x4a,0x49,0x54,0x20,0x72,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x20,0x73,0x75, +/*005180*/ 0x70,0x70,0x6f,0x72,0x74,0x2e,0x0d,0x0a,0x09,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66, +/*005190*/ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20, +/*0051a0*/ 0x64,0x62,0x67,0x2e,0x72,0x65,0x61,0x64,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20, +/*0051b0*/ 0x61,0x6e,0x64,0x20,0x66,0x66,0x69,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09, +/*0051c0*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x72,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x20, +/*0051d0*/ 0x3d,0x20,0x66,0x66,0x69,0x2e,0x6c,0x6f,0x61,0x64,0x28,0x22,0x72,0x65,0x61,0x64, +/*0051e0*/ 0x6c,0x69,0x6e,0x65,0x22,0x29,0x0d,0x0a,0x09,0x09,0x09,0x64,0x62,0x67,0x2e,0x72, +/*0051f0*/ 0x65,0x61,0x64,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x70, +/*005200*/ 0x72,0x6f,0x6d,0x70,0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61, +/*005210*/ 0x6c,0x20,0x63,0x73,0x74,0x72,0x20,0x3d,0x20,0x72,0x65,0x61,0x64,0x6c,0x69,0x6e, +/*005220*/ 0x65,0x2e,0x72,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x28,0x70,0x72,0x6f,0x6d,0x70, +/*005230*/ 0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x09,0x69,0x66,0x20,0x63,0x73,0x74,0x72,0x20, +/*005240*/ 0x7e,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09, +/*005250*/ 0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x74,0x72,0x20,0x3d,0x20,0x66,0x66, +/*005260*/ 0x69,0x2e,0x73,0x74,0x72,0x69,0x6e,0x67,0x28,0x63,0x73,0x74,0x72,0x29,0x0d,0x0a, +/*005270*/ 0x09,0x09,0x09,0x09,0x09,0x69,0x66,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x6d, +/*005280*/ 0x61,0x74,0x63,0x68,0x28,0x73,0x74,0x72,0x2c,0x20,0x22,0x5b,0x5e,0x25,0x73,0x5d, +/*005290*/ 0x2b,0x22,0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x09,0x09,0x09, +/*0052a0*/ 0x72,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x2e,0x61,0x64,0x64,0x5f,0x68,0x69,0x73, +/*0052b0*/ 0x74,0x6f,0x72,0x79,0x28,0x63,0x73,0x74,0x72,0x29,0x0d,0x0a,0x09,0x09,0x09,0x09, +/*0052c0*/ 0x09,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x09,0x09,0x09,0x09,0x09,0x66,0x66,0x69, +/*0052d0*/ 0x2e,0x43,0x2e,0x66,0x72,0x65,0x65,0x28,0x63,0x73,0x74,0x72,0x29,0x0d,0x0a,0x09, +/*0052e0*/ 0x09,0x09,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x72,0x0d,0x0a, +/*0052f0*/ 0x09,0x09,0x09,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x09,0x09,0x09,0x72, +/*005300*/ 0x65,0x74,0x75,0x72,0x6e,0x20,0x6e,0x69,0x6c,0x0d,0x0a,0x09,0x09,0x09,0x09,0x65, +/*005310*/ 0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x64, +/*005320*/ 0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52, +/*005330*/ 0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67, +/*005340*/ 0x65,0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*005350*/ 0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x52,0x65,0x61,0x64,0x6c,0x69,0x6e, +/*005360*/ 0x65,0x20,0x73,0x75,0x70,0x70,0x6f,0x72,0x74,0x20,0x65,0x6e,0x61,0x62,0x6c,0x65, +/*005370*/ 0x64,0x2e,0x22,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6e, +/*005380*/ 0x64,0x29,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x44,0x65, +/*005390*/ 0x74,0x65,0x63,0x74,0x20,0x4c,0x75,0x61,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e, +/*0053a0*/ 0x2e,0x0d,0x0a,0x69,0x66,0x20,0x6a,0x69,0x74,0x20,0x74,0x68,0x65,0x6e,0x20,0x2d, +/*0053b0*/ 0x2d,0x20,0x4c,0x75,0x61,0x4a,0x49,0x54,0x0d,0x0a,0x09,0x4c,0x55,0x41,0x5f,0x4a, +/*0053c0*/ 0x49,0x54,0x5f,0x53,0x45,0x54,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x57,0x4f,0x52,0x4b, +/*0053d0*/ 0x41,0x52,0x4f,0x55,0x4e,0x44,0x20,0x3d,0x20,0x2d,0x31,0x0d,0x0a,0x09,0x64,0x62, +/*0053e0*/ 0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*0053f0*/ 0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67,0x65, +/*005400*/ 0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*005410*/ 0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x4c,0x6f,0x61,0x64,0x65,0x64,0x20,0x66, +/*005420*/ 0x6f,0x72,0x20,0x22,0x2e,0x2e,0x6a,0x69,0x74,0x2e,0x76,0x65,0x72,0x73,0x69,0x6f, +/*005430*/ 0x6e,0x29,0x0d,0x0a,0x65,0x6c,0x73,0x65,0x69,0x66,0x20,0x22,0x4c,0x75,0x61,0x20, +/*005440*/ 0x35,0x2e,0x31,0x22,0x20,0x3c,0x3d,0x20,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e, +/*005450*/ 0x20,0x61,0x6e,0x64,0x20,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x20,0x3c,0x3d, +/*005460*/ 0x20,0x22,0x4c,0x75,0x61,0x20,0x35,0x2e,0x34,0x22,0x20,0x74,0x68,0x65,0x6e,0x0d, +/*005470*/ 0x0a,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f, +/*005480*/ 0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62, +/*005490*/ 0x75,0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f, +/*0054a0*/ 0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x4c,0x6f,0x61,0x64, +/*0054b0*/ 0x65,0x64,0x20,0x66,0x6f,0x72,0x20,0x22,0x2e,0x2e,0x5f,0x56,0x45,0x52,0x53,0x49, +/*0054c0*/ 0x4f,0x4e,0x29,0x0d,0x0a,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x64,0x62,0x67,0x5f, +/*0054d0*/ 0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45, +/*0054e0*/ 0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x2e, +/*0054f0*/ 0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*005500*/ 0x53,0x45,0x54,0x2e,0x2e,0x22,0x4e,0x6f,0x74,0x20,0x74,0x65,0x73,0x74,0x65,0x64, +/*005510*/ 0x20,0x61,0x67,0x61,0x69,0x6e,0x73,0x74,0x20,0x22,0x2e,0x2e,0x5f,0x56,0x45,0x52, +/*005520*/ 0x53,0x49,0x4f,0x4e,0x29,0x0d,0x0a,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74, +/*005530*/ 0x65,0x6c,0x6e,0x28,0x22,0x50,0x6c,0x65,0x61,0x73,0x65,0x20,0x73,0x65,0x6e,0x64, +/*005540*/ 0x20,0x6d,0x65,0x20,0x66,0x65,0x65,0x64,0x62,0x61,0x63,0x6b,0x21,0x22,0x29,0x0d, +/*005550*/ 0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64, +/*005560*/ 0x62,0x67,0x0d,0x0a +}; + +const unsigned DEBUGGER_SRC_LEN = (unsigned)sizeof(DEBUGGER_SRC); + + +int luaopen_debugger(lua_State *lua){ + if( + luaL_loadbufferx(lua, DEBUGGER_SRC, DEBUGGER_SRC_LEN, "", NULL) || + lua_pcall(lua, 0, LUA_MULTRET, 0) + ) lua_error(lua); + + // Or you could load it from disk: + // if(luaL_dofile(lua, "debugger.lua")) lua_error(lua); + + return 1; +} + +static const char *MODULE_NAME = "DEBUGGER_LUA_MODULE"; +static const char *MSGH = "DEBUGGER_LUA_MSGH"; + +void dbg_setup(lua_State *lua, const char *name, const char *globalName, lua_CFunction readFunc, lua_CFunction writeFunc){ + // Check that the module name was not already defined. + lua_getfield(lua, LUA_REGISTRYINDEX, MODULE_NAME); + assert(lua_isnil(lua, -1) || strcmp(name, luaL_checkstring(lua, -1))); + lua_pop(lua, 1); + + // Push the module name into the registry. + lua_pushstring(lua, name); + lua_setfield(lua, LUA_REGISTRYINDEX, MODULE_NAME); + + // Preload the module + luaL_requiref(lua, name, luaopen_debugger, false); + + // Insert the msgh function into the registry. + lua_getfield(lua, -1, "msgh"); + lua_setfield(lua, LUA_REGISTRYINDEX, MSGH); + + if(readFunc){ + lua_pushcfunction(lua, readFunc); + lua_setfield(lua, -2, "read"); + } + + if(writeFunc){ + lua_pushcfunction(lua, writeFunc); + lua_setfield(lua, -2, "write"); + } + + if(globalName){ + lua_setglobal(lua, globalName); + } else { + lua_pop(lua, 1); + } +} + +void dbg_setup_default(lua_State *lua){ + dbg_setup(lua, "debugger", "dbg", NULL, NULL); +} + +int dbg_pcall(lua_State *lua, int nargs, int nresults, int msgh){ + // Call regular lua_pcall() if a message handler is provided. + if(msgh) return lua_pcall(lua, nargs, nresults, msgh); + + // Grab the msgh function out of the registry. + lua_getfield(lua, LUA_REGISTRYINDEX, MSGH); + if(lua_isnil(lua, -1)){ + luaL_error(lua, "Tried to call dbg_call() before calling dbg_setup()."); + } + + // Move the error handler just below the function. + msgh = lua_gettop(lua) - (1 + nargs); + lua_insert(lua, msgh); + + // Call the function. + int err = lua_pcall(lua, nargs, nresults, msgh); + + // Remove the debug handler. + lua_remove(lua, msgh); + + return err; +} +#line 0 +//#define SQLITE_OMIT_LOAD_EXTENSION +//#define SQLITE_CORE 1 +//#define SQLITE_DEBUG 1 +//#define Token SQToken +//#define Table SQTable +//#define rehash sqlite3__rehash +//#undef NB +//{ {FILE:3rd_sqlite3.c}} +//#undef Token +//#undef Table +//#undef rehash +//#undef NB +//#undef threadid #endif // V4K_3RD /* game framework. * - rlyeh, public domain @@ -332503,18 +334012,6 @@ int main() { #include "v4k" #endif -#define do_threadlock(mutexptr) \ - for( int init_ = !!(mutexptr) || (thread_mutex_init( (mutexptr) = CALLOC(1, sizeof(thread_mutex_t)) ), 1); init_; init_ = 0) \ - for( int lock_ = (thread_mutex_lock( mutexptr ), 1); lock_; lock_ = (thread_mutex_unlock( mutexptr ), 0) ) - -API void *ui_handle(); -#define ui_push_hspace(px) \ - (int xx = px; xx; xx = 0) \ - for(struct nk_context *ctx = (struct nk_context*)ui_handle(); ctx; ctx = 0 ) \ - for(struct nk_panel *layout = ui_ctx->current->layout; layout; ) \ - for( xx = (layout->at_x += px, layout->bounds.w -= px, 0); layout; layout->at_x -= px, layout->bounds.w += px, layout = 0 ) - - //----------------------------------------------------------------------------- // C files @@ -332933,7 +334430,7 @@ char* tempvl(const char *fmt, va_list vl) { static __thread char buf[STACK_ALLOC]; #else int heap = 1; - static __thread int STACK_ALLOC = 128*1024; + static __thread int STACK_ALLOC = 512*1024; static __thread char *buf = 0; if(!buf) buf = REALLOC(0, STACK_ALLOC); // @leak #endif static __thread int cur = 0; //printf("string stack %d/%d\n", cur, STACK_ALLOC); @@ -335963,7 +337460,7 @@ int ui_browse(const char **output, bool *inlined) { // if(ui_ctx->current) bounds = nk_window_get_bounds(ui_ctx), P(bounds); // if(ui_ctx->current) bounds = nk_window_get_content_region(ui_ctx), P(bounds); // if(ui_ctx->current) nk_layout_peek(&bounds, ui_ctx), P(bounds); - // // if(ui_ctx->current) nk_layout_widget_space(&bounds, ui_ctx, ui_ctx->current, nk_false), P(bounds); // note: cant be used within a panel + // if(ui_ctx->current) nk_layout_widget_space(&bounds, ui_ctx, ui_ctx->current, nk_false), P(bounds); // note: cant be used within a panel // #undef P // panel @@ -339351,29 +340848,36 @@ bool data_tests() { #line 1 "engine/split/v4k_extend.c" // dll ------------------------------------------------------------------------ +/* deprecated #if is(win32) # include -# define dlopen(name,mode) (void*)( (name) ? LoadLibraryA(name) : GetModuleHandle(NULL)) -# define dlsym(handle,symbol) GetProcAddress((HMODULE)handle, symbol ) +# define dlopen(name,flags) (void*)( (name) ? LoadLibraryA(name) : GetModuleHandleA(NULL)) +# define dlsym(handle,symbol) GetProcAddress((HMODULE)(handle), symbol ) # define dlclose(handle) 0 #else # include +# define dlopen(name,flags) (void*)( (name) ? dlopen(name, flags) : NULL ) +# define dlsym(handle,symbol) dlsym( (handle) ? (handle) : ifdef(osx,RTLD_SELF,NULL), symbol ) #endif - -void* dll(const char *filename, const char *symbol) { -/* - char *buf, *base = file_name(filename); - if( file_exists(buf = va("%s", base)) || - file_exists(buf = va("%s.dll", base)) || - file_exists(buf = va("%s.so", base)) || - file_exists(buf = va("lib%s.so", base)) || - file_exists(buf = va("%s.dylib", base)) ) { - filename = buf; - } */ - void *dll = dlopen(filename, RTLD_NOW | RTLD_LOCAL); - dll = dll ? dlsym(dll, symbol) : 0; - return dll; + +void* dll(const char *fname, const char *symbol) { + if( fname && !file_exist(fname) ) { + char *buf, *path = file_path(fname), *base = file_base(fname); + if( file_exist(buf = va("%s%s.dll", path, base)) || + file_exist(buf = va("%s%s.so", path, base)) || + file_exist(buf = va("%slib%s.so", path, base)) || + file_exist(buf = va("%s%s.dylib", path, base)) ) { + fname = (const char *)buf; + } else { + return NULL; + } + } +#if is(win32) + return (void*)GetProcAddress(fname ? LoadLibraryA(fname) : GetModuleHandleA(NULL), symbol); +#else + return dlsym(fname ? dlopen(fname, RTLD_NOW|RTLD_LOCAL) : ifdef(osx, RTLD_SELF, NULL), symbol); +#endif } #if 0 // demo: cl demo.c /LD && REM dll @@ -339561,6 +341065,75 @@ bool script_tests() { } #undef XMACRO + +// script v2 ------------------------------------------------------------------ + +#define luaL_dostringsafe(L, str) \ + luaL_dostring(L, \ + "xpcall(function()\n" \ + str \ + "end, function(err)\n" \ + " print('Error: ' .. tostring(err))\n" \ + " print(debug.traceback(nil, 2))\n" \ + " if core and core.on_error then\n" \ + " pcall(core.on_error, err)\n" \ + " end\n" \ + " os.exit(1)\n" \ + "end)" \ + ); + +static int f_vfs_read(lua_State *L) { + char *file = file_normalize(luaL_checkstring(L, 1)); + if( strbegi(file, app_path()) ) file += strlen(app_path()); + strswap(file+1, ".", "/"); + strswap(file+1, "/lua", ".lua"); + int len; char *data = vfs_load(file, &len); + if( len ) { + data = memcpy(MALLOC(len+1), data, len), data[len] = 0; + //tty_color(data ? GREEN : RED); + //printf("%s (%s)\n%s", file, data ? "ok" : "failed", data); + //tty_color(0); + } + return lua_pushstring(L, data), 1; // "\n\tcannot find `%s` within mounted zipfiles", file), 1; +} + +// add our zip loader at the end of package.loaders +void lua_add_ziploader(lua_State* L) { + lua_pushcfunction( L, f_vfs_read ); + lua_setglobal( L, "vfs_read" ); + + luaL_dostringsafe(L, +// "package.path = [[;;<>;]]\n" // .. package.path\n" + "package.searchers[#package.searchers + 1] = function(libraryname)\n" + " for pattern in string.gmatch( package.path, '[^;]+' ) do\n" + " local proper_path = string.gsub(pattern, '?', libraryname)\n" + " local f = vfs_read(proper_path)\n" + " if f ~= nil then\n" + " return load(f, proper_path)\n" + " end\n" + " end\n" + " return nil\n" + "end\n" + ); +} + +void *script_init_env(unsigned flags) { + if( flags & SCRIPT_LUA ) { + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + + if( flags & SCRIPT_DEBUGGER ) { + // Register debuggers/inspectors + // luaL_dostringsafe(L, "I = require('inspect').inspect\n"); + dbg_setup_default(L); + } + + lua_add_ziploader(L); + return L; + } + + return 0; +} #line 0 #line 1 "engine/split/v4k_file.c" @@ -339727,7 +341300,7 @@ char *file_id(const char *pathfile) { char *ext = strchr(base, '.'); if (ext) ext[0] = '\0'; // remove all extensions #else // extensionless for audio/images only (materials: diffuse.tga and diffuse.png will match) char *ext = strrchr(base, '.'); //if (ext) ext[0] = '\0'; // remove all extensions - if(ext) if( strstr(".jpg.png.bmp.tga"".", ext) || strstr(".ogg.mp3.wav.mod.xm.flac"".", ext) || strstr(".mp4.ogv.avi.mkv.wmv.mpg.mpeg"".", ext) ) { + if(ext) if( strstr(".jpg.png.bmp.tga.hdr"".", ext) || strstr(".ogg.mp3.wav.mod.xm.flac"".", ext) || strstr(".mp4.ogv.avi.mkv.wmv.mpg.mpeg"".", ext) ) { ext = strchr(base, '.'); ext[0] = '\0'; //strcpy(ext, "_xxx"); } @@ -354711,646 +356284,6 @@ void scene_render(int flags) { } #line 0 -#line 1 "engine/split/v4k_time.c" -// ---------------------------------------------------------------------------- -// time - -#if 0 -uint64_t time_gpu() { - GLint64 t = 123456789; - glGetInteger64v(GL_TIMESTAMP, &t); - return (uint64_t)t; -} -#endif -uint64_t date() { - time_t epoch = time(0); - struct tm *ti = localtime(&epoch); - return atoi64(va("%04d%02d%02d%02d%02d%02d",ti->tm_year+1900,ti->tm_mon+1,ti->tm_mday,ti->tm_hour,ti->tm_min,ti->tm_sec)); -} -char *date_string() { - time_t epoch = time(0); - struct tm *ti = localtime(&epoch); - return va("%04d-%02d-%02d %02d:%02d:%02d",ti->tm_year+1900,ti->tm_mon+1,ti->tm_mday,ti->tm_hour,ti->tm_min,ti->tm_sec); -} -uint64_t date_epoch() { - time_t epoch = time(0); - return epoch; -} -#if 0 -double time_ss() { - return glfwGetTime(); -} -double time_ms() { - return glfwGetTime() * 1000.0; -} -uint64_t time_us() { - return (uint64_t)(glfwGetTime() * 1000000.0); // @fixme: use a high resolution timer instead, or time_gpu below -} -uint64_t sleep_us(uint64_t us) { // @fixme: use a high resolution sleeper instead - return sleep_ms( us / 1000.0 ); -} -double sleep_ms(double ms) { - double now = time_ms(); - if( ms <= 0 ) { -#if is(win32) - Sleep(0); // yield -#else - usleep(0); -#endif - } else { -#if is(win32) - Sleep(ms); -#else - usleep(ms * 1000); -#endif - } - return time_ms() - now; -} -double sleep_ss(double ss) { - return sleep_ms( ss * 1000 ) / 1000.0; -} -#endif - -// high-perf functions - -#define TIMER_E3 1000ULL -#define TIMER_E6 1000000ULL -#define TIMER_E9 1000000000ULL - -#ifdef CLOCK_MONOTONIC_RAW -#define TIME_MONOTONIC CLOCK_MONOTONIC_RAW -#elif defined CLOCK_MONOTONIC -#define TIME_MONOTONIC CLOCK_MONOTONIC -#else -// #define TIME_MONOTONIC CLOCK_REALTIME // untested -#endif - -static uint64_t nanotimer(uint64_t *out_freq) { - if( out_freq ) { -#if is(win32) - LARGE_INTEGER li; - QueryPerformanceFrequency(&li); - *out_freq = li.QuadPart; -//#elif is(ANDROID) -// *out_freq = CLOCKS_PER_SEC; -#elif defined TIME_MONOTONIC - *out_freq = TIMER_E9; -#else - *out_freq = TIMER_E6; -#endif - } -#if is(win32) - LARGE_INTEGER li; - QueryPerformanceCounter(&li); - return (uint64_t)li.QuadPart; -//#elif is(ANDROID) -// return (uint64_t)clock(); -#elif defined TIME_MONOTONIC - struct timespec ts; - clock_gettime(TIME_MONOTONIC, &ts); - return (TIMER_E9 * (uint64_t)ts.tv_sec) + ts.tv_nsec; -#else - struct timeval tv; - gettimeofday(&tv, NULL); - return (TIMER_E6 * (uint64_t)tv.tv_sec) + tv.tv_usec; -#endif -} - -uint64_t time_ns() { - static uint64_t epoch = 0; - static uint64_t freq = 0; - if( !freq ) { - epoch = nanotimer(&freq); - } - - uint64_t a = nanotimer(NULL) - epoch; - uint64_t b = TIMER_E9; - uint64_t c = freq; - - // Computes (a*b)/c without overflow, as long as both (a*b) and the overall result fit into 64-bits. - // [ref] https://github.com/rust-lang/rust/blob/3809bbf47c8557bd149b3e52ceb47434ca8378d5/src/libstd/sys_common/mod.rs#L124 - uint64_t q = a / c; - uint64_t r = a % c; - return q * b + r * b / c; -} -uint64_t time_us() { - return time_ns() / TIMER_E3; -} -uint64_t time_ms() { - return time_ns() / TIMER_E6; -} -double time_ss() { - return time_ns() / 1e9; // TIMER_E9; -} -double time_mm() { - return time_ss() / 60; -} -double time_hh() { - return time_mm() / 60; -} - -void sleep_ns( double ns ) { -#if is(win32) - if( ns >= 100 ) { - LARGE_INTEGER li; // Windows sleep in 100ns units - HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL); - li.QuadPart = (LONGLONG)(__int64)(-ns/100); // Negative for relative time - SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE); - WaitForSingleObject(timer, INFINITE); - CloseHandle(timer); -#else - if( ns > 0 ) { - struct timespec wait = {0}; - wait.tv_sec = ns / 1e9; - wait.tv_nsec = ns - wait.tv_sec * 1e9; - nanosleep(&wait, NULL); -#endif - } else { -#if is(win32) - Sleep(0); // yield, Sleep(0), SwitchToThread -#else - usleep(0); -#endif - } -} -void sleep_us( double us ) { - sleep_ns(us * 1e3); -} -void sleep_ms( double ms ) { - sleep_ns(ms * 1e6); -} -void sleep_ss( double ss ) { - sleep_ns(ss * 1e9); -} - -// ---------------------------------------------------------------------------- -// timer - -struct timer_internal_t { - unsigned ms; - unsigned (*callback)(unsigned interval, void *arg); - void *arg; - thread_ptr_t thd; -}; - -static int timer_func(void *arg) { - struct timer_internal_t *p = (struct timer_internal_t*)arg; - - sleep_ms( p->ms ); - - for( ;; ) { - unsigned then = time_ms(); - - p->ms = p->callback(p->ms, p->arg); - if( !p->ms ) break; - - unsigned now = time_ms(); - unsigned lapse = now - then; - int diff = p->ms - lapse; - sleep_ms( diff <= 0 ? 0 : diff ); - } - - thread_exit(0); - return 0; -} - -static __thread array(struct timer_internal_t *) timers; - -unsigned timer(unsigned ms, unsigned (*callback)(unsigned ms, void *arg), void *arg) { - struct timer_internal_t *p = MALLOC( sizeof(struct timer_internal_t) ); - p->ms = ms; - p->callback = callback; - p->arg = arg; - p->thd = thread_init( timer_func, p, "", 0 ); - - array_push(timers, p); - return array_count(timers); -} -void timer_destroy(unsigned i) { - if( i-- ) { - thread_join(timers[i]->thd); - thread_term(timers[i]->thd); - FREE(timers[i]); - timers[i] = 0; - } -} - -// ---------------------------------------------------------------------------- -// guid - -//typedef vec3i guid; - -guid guid_create() { - static __thread unsigned counter = 0; - static uint64_t appid = 0; do_once appid = hash_str(app_name()); - - union conv { - struct { - unsigned timestamp : 32; - unsigned threadid : 16; // inverted order in LE - unsigned appid : 16; // - unsigned counter : 32; - }; - vec3i v3; - } c; - c.timestamp = date_epoch() - 0x65000000; - c.appid = (unsigned)appid; - c.threadid = (unsigned)(uintptr_t)thread_current_thread_id(); - c.counter = ++counter; - - return c.v3; -} - -// ---------------------------------------------------------------------------- -// ease - -float ease_nop(float t) { return 0; } -float ease_linear(float t) { return t; } - -float ease_out_sine(float t) { return sinf(t*(C_PI*0.5f)); } -float ease_out_quad(float t) { return -(t*(t-2)); } -float ease_out_cubic(float t) { float f=t-1; return f*f*f+1; } -float ease_out_quart(float t) { float f=t-1; return f*f*f*(1-t)+1; } -float ease_out_quint(float t) { float f=(t-1); return f*f*f*f*f+1; } -float ease_out_expo(float t) { return (t >= 1) ? t : 1-powf(2,-10*t); } -float ease_out_circ(float t) { return sqrtf((2-t)*t); } -float ease_out_back(float t) { float f=1-t; return 1-(f*f*f-f*sinf(f*C_PI)); } -float ease_out_elastic(float t) { return sinf(-13*(C_PI*0.5f)*(t+1))*powf(2,-10*t)+1; } -float ease_out_bounce(float t) { return (t < 4.f/11) ? (121.f*t*t)/16 : (t < 8.f/11) ? (363.f/40*t*t)-(99.f/10*t)+17.f/5 : (t < 9.f/10) ? (4356.f/361*t*t)-(35442.f/1805*t)+16061.f/1805 : (54.f/5*t*t)-(513.f/25*t)+268.f/25; } - -float ease_in_sine(float t) { return 1+sinf((t-1)*(C_PI*0.5f)); } -float ease_in_quad(float t) { return t*t; } -float ease_in_cubic(float t) { return t*t*t; } -float ease_in_quart(float t) { return t*t*t*t; } -float ease_in_quint(float t) { return t*t*t*t*t; } -float ease_in_expo(float t) { return (t <= 0) ? t : powf(2,10*(t-1)); } -float ease_in_circ(float t) { return 1-sqrtf(1-(t*t)); } -float ease_in_back(float t) { return t*t*t-t*sinf(t*C_PI); } -float ease_in_elastic(float t) { return sinf(13*(C_PI*0.5f)*t)*powf(2,10*(t-1)); } -float ease_in_bounce(float t) { return 1-ease_out_bounce(1-t); } - -float ease_inout_sine(float t) { return 0.5f*(1-cosf(t*C_PI)); } -float ease_inout_quad(float t) { return (t < 0.5f) ? 2*t*t : (-2*t*t)+(4*t)-1; } -float ease_inout_cubic(float t) { float f; return (t < 0.5f) ? 4*t*t*t : (f=(2*t)-2,0.5f*f*f*f+1); } -float ease_inout_quart(float t) { float f; return (t < 0.5f) ? 8*t*t*t*t : (f=(t-1),-8*f*f*f*f+1); } -float ease_inout_quint(float t) { float f; return (t < 0.5f) ? 16*t*t*t*t*t : (f=((2*t)-2),0.5f*f*f*f*f*f+1); } -float ease_inout_expo(float t) { return (t <= 0 || t >= 1) ? t : t < 0.5f ? 0.5f*powf(2,(20*t)-10) : -0.5f*powf(2,(-20*t)+10)+1; } -float ease_inout_circ(float t) { return t < 0.5f ? 0.5f*(1-sqrtf(1-4*(t*t))) : 0.5f*(sqrtf(-((2*t)-3)*((2*t)-1))+1); } -float ease_inout_back(float t) { float f; return t < 0.5f ? (f=2*t,0.5f*(f*f*f-f*sinf(f*C_PI))) : (f=(1-(2*t-1)),0.5f*(1-(f*f*f-f*sinf(f*C_PI)))+0.5f); } -float ease_inout_elastic(float t) { return t < 0.5f ? 0.5f*sinf(13*(C_PI*0.5f)*(2*t))*powf(2,10*((2*t)-1)) : 0.5f*(sinf(-13*(C_PI*0.5f)*((2*t-1)+1))*powf(2,-10*(2*t-1))+2); } -float ease_inout_bounce(float t) { return t < 0.5f ? 0.5f*ease_in_bounce(t*2) : 0.5f*ease_out_bounce(t*2-1)+0.5f; } - -float ease_inout_perlin(float t) { float t3=t*t*t,t4=t3*t,t5=t4*t; return 6*t5-15*t4+10*t3; } - -float ease(float t01, unsigned mode) { - typedef float (*easing)(float); - easing modes[] = { - ease_out_sine, - ease_out_quad, - ease_out_cubic, - ease_out_quart, - ease_out_quint, - ease_out_expo, - ease_out_circ, - ease_out_back, - ease_out_elastic, - ease_out_bounce, - - ease_in_sine, - ease_in_quad, - ease_in_cubic, - ease_in_quart, - ease_in_quint, - ease_in_expo, - ease_in_circ, - ease_in_back, - ease_in_elastic, - ease_in_bounce, - - ease_inout_sine, - ease_inout_quad, - ease_inout_cubic, - ease_inout_quart, - ease_inout_quint, - ease_inout_expo, - ease_inout_circ, - ease_inout_back, - ease_inout_elastic, - ease_inout_bounce, - - ease_nop, - ease_linear, - ease_inout_perlin, - }; - return modes[clampi(mode, 0, countof(modes))](clampf(t01,0,1)); -} - -float ease_pong(float t, unsigned fn) { return 1 - ease(t, fn); } -float ease_ping_pong(float t, unsigned fn1, unsigned fn2) { return t < 0.5 ? ease(t*2,fn1) : ease(1-(t-0.5)*2,fn2); } -float ease_pong_ping(float t, unsigned fn1, unsigned fn2) { return 1 - ease_ping_pong(t,fn1,fn2); } - - -const char **ease_enums() { - static const char *list[] = { - "ease_out_sine", - "ease_out_quad", - "ease_out_cubic", - "ease_out_quart", - "ease_out_quint", - "ease_out_expo", - "ease_out_circ", - "ease_out_back", - "ease_out_elastic", - "ease_out_bounce", - - "ease_in_sine", - "ease_in_quad", - "ease_in_cubic", - "ease_in_quart", - "ease_in_quint", - "ease_in_expo", - "ease_in_circ", - "ease_in_back", - "ease_in_elastic", - "ease_in_bounce", - - "ease_inout_sine", - "ease_inout_quad", - "ease_inout_cubic", - "ease_inout_quart", - "ease_inout_quint", - "ease_inout_expo", - "ease_inout_circ", - "ease_inout_back", - "ease_inout_elastic", - "ease_inout_bounce", - - "ease_nop", - "ease_linear", - "ease_inout_perlin", - - 0 - }; - return list; -} - -const char *ease_enum(unsigned mode) { - return mode[ ease_enums() ]; -} - -/*AUTORUN { - ENUM(EASE_LINEAR|EASE_OUT); - ENUM(EASE_SINE|EASE_OUT); - ENUM(EASE_QUAD|EASE_OUT); - ENUM(EASE_CUBIC|EASE_OUT); - ENUM(EASE_QUART|EASE_OUT); - ENUM(EASE_QUINT|EASE_OUT); - ENUM(EASE_EXPO|EASE_OUT); - ENUM(EASE_CIRC|EASE_OUT); - ENUM(EASE_BACK|EASE_OUT); - ENUM(EASE_ELASTIC|EASE_OUT); - ENUM(EASE_BOUNCE|EASE_OUT); - - ENUM(EASE_SINE|EASE_IN); - ENUM(EASE_QUAD|EASE_IN); - ENUM(EASE_CUBIC|EASE_IN); - ENUM(EASE_QUART|EASE_IN); - ENUM(EASE_QUINT|EASE_IN); - ENUM(EASE_EXPO|EASE_IN); - ENUM(EASE_CIRC|EASE_IN); - ENUM(EASE_BACK|EASE_IN); - ENUM(EASE_ELASTIC|EASE_IN); - ENUM(EASE_BOUNCE|EASE_IN); - - ENUM(EASE_SINE|EASE_INOUT); - ENUM(EASE_QUAD|EASE_INOUT); - ENUM(EASE_CUBIC|EASE_INOUT); - ENUM(EASE_QUART|EASE_INOUT); - ENUM(EASE_QUINT|EASE_INOUT); - ENUM(EASE_EXPO|EASE_INOUT); - ENUM(EASE_CIRC|EASE_INOUT); - ENUM(EASE_BACK|EASE_INOUT); - ENUM(EASE_ELASTIC|EASE_INOUT); - ENUM(EASE_BOUNCE|EASE_INOUT); - - ENUM(EASE_NOP); - ENUM(EASE_LINEAR); - ENUM(EASE_INOUT_PERLIN); -};*/ - -// ---------------------------------------------------------------------------- -// tween - -tween_t tween() { - tween_t tw = {0}; - return tw; -} - -float tween_update(tween_t *tw, float dt) { - if( !array_count(tw->keyframes) ) return 0.0f; - - for( int i = 0, end = array_count(tw->keyframes) - 1; i < end; ++i ) { - tween_keyframe_t *kf1 = &tw->keyframes[i]; - tween_keyframe_t *kf2 = &tw->keyframes[i + 1]; - if (tw->time >= kf1->t && tw->time <= kf2->t) { - float localT = (tw->time - kf1->t) / (kf2->t - kf1->t); - float easedT = ease(localT, kf1->ease); - tw->result = mix3(kf1->v, kf2->v, easedT); - break; - } - } - - float done = (tw->time / tw->duration); - tw->time += dt; - return clampf(done, 0.0f, 1.0f); -} - -void tween_reset(tween_t *tw) { - tw->time = 0.0f; -} - -void tween_destroy(tween_t *tw) { - tween_t tw_ = {0}; - array_free(tw->keyframes); - *tw = tw_; -} - -static INLINE -int tween_comp_keyframes(const void *a, const void *b) { - float t1 = ((const tween_keyframe_t*)a)->t; - float t2 = ((const tween_keyframe_t*)b)->t; - return (t1 > t2) - (t1 < t2); -} - -void tween_setkey(tween_t *tw, float t, vec3 v, unsigned mode) { - tween_keyframe_t keyframe = { t, v, mode }; - array_push(tw->keyframes, keyframe); - array_sort(tw->keyframes, tween_comp_keyframes); - tw->duration = array_back(tw->keyframes)->t; -} - -void tween_delkey(tween_t *tw, float t) { // @todo: untested - for( int i = 0, end = array_count(tw->keyframes); i < end; i++ ) { - if( tw->keyframes[i].t == t ) { - array_erase_slow(tw->keyframes, i); - tw->duration = array_back(tw->keyframes)->t; - return; - } - } -} - -// ---------------------------------------------------------------------------- -// curve - -curve_t curve() { - curve_t c = {0}; - return c; -} - -static INLINE -vec3 catmull( vec3 p0, vec3 p1, vec3 p2, vec3 p3, float t ) { - float t2 = t*t; - float t3 = t*t*t; - - vec3 c; - c.x = 0.5 * ((2 * p1.x) + (-p0.x + p2.x) * t + (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 + (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3); - c.y = 0.5 * ((2 * p1.y) + (-p0.y + p2.y) * t + (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 + (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3); - c.z = 0.5 * ((2 * p1.z) + (-p0.z + p2.z) * t + (2 * p0.z - 5 * p1.z + 4 * p2.z - p3.z) * t2 + (-p0.z + 3 * p1.z - 3 * p2.z + p3.z) * t3); - return c; -} - -void curve_add(curve_t *c, vec3 p) { - array_push(c->points, p); -} - -void curve_finish( curve_t *c, int k ) { - assert( k > 0 ); - - array_free(c->lengths); - array_free(c->samples); - array_free(c->indices); - array_free(c->colors); - - // refit points[N] to samples[K] - int N = array_count(c->points); - if( k < N ) { - // truncate: expected k-points lesser or equal than existing N points - for( int i = 0; i <= k; ++i ) { - float s = (float)i / k; - int t = s * (N-1); - array_push(c->samples, c->points[t]); - - float p = fmod(i, N-1) / (N-1); // [0..1) - int is_control_point = p <= 0 || p >= 1; - array_push(c->colors, is_control_point ? ORANGE: BLUE); - } - - } else { - // interpolate: expected k-points greater than existing N-points - --N; - int upper = N - (k%N); - int lower = (k%N); - if(upper < lower) - k += upper; - else - k -= lower; - - int points_per_segment = (k / N); - ++N; - - int looped = len3sq(sub3(c->points[0], *array_back(c->points))) < 0.1; - - for( int i = 0; i <= k; ++i ) { - int point = i % points_per_segment; - float p = point / (float)points_per_segment; // [0..1) - int t = i / points_per_segment; - - // linear - vec3 l = mix3(c->points[t], c->points[t+(i!=k)], p); - - // printf("%d) %d>%d %f\n", i, t, t+(i!=k), p); - ASSERT(p <= 1); - - // catmull - int p0 = t - 1; - int p1 = t + 0; - int p2 = t + 1; - int p3 = t + 2; - if( looped ) - { - int M = N-1; - if(p0<0) p0+=M; else if(p0>=M) p0-=M; - if(p1<0) p1+=M; else if(p1>=M) p1-=M; - if(p2<0) p2+=M; else if(p2>=M) p2-=M; - if(p3<0) p3+=M; else if(p3>=M) p3-=M; - } - else - { - int M = N-1; - if(p0<0) p0=0; else if(p0>=M) p0=M; - if(p1<0) p1=0; else if(p1>=M) p1=M; - if(p2<0) p2=0; else if(p2>=M) p2=M; - if(p3<0) p3=0; else if(p3>=M) p3=M; - } - vec3 m = catmull(c->points[p0],c->points[p1],c->points[p2],c->points[p3],p); - l = m; - - array_push(c->samples, l); - - int is_control_point = p <= 0 || p >= 1; - array_push(c->colors, is_control_point ? ORANGE: BLUE); - } - } - - array_push(c->lengths, 0 ); - for( int i = 1; i <= k; ++i ) { - // approximate curve length at every sample point - array_push(c->lengths, len3(sub3(c->samples[i], c->samples[i-1])) + c->lengths[i-1] ); - } - // normalize lengths to be between 0 and 1 - float maxv = c->lengths[k]; - for( int i = 1; i <= k; ++i ) c->lengths[i] /= maxv; - - array_push(c->indices, 0 ); - for( int i = 0/*1*/; i indices) + 1; j lengths[j] lengths[j] > 0.01) - array_push(c->indices, j ); - } -} - -vec3 curve_eval(curve_t *c, float dt, unsigned *color) { - unsigned nil; if(!color) color = &nil; - dt = clampf(dt, 0.0f, 1.0f); - int l = (int)(array_count(c->indices) - 1); - int p = (int)(dt * l); - int t = c->indices[p]; - - t %= (array_count(c->indices)-1); - vec3 pos = mix3(c->samples[t], c->samples[t+1], dt * l - p); - *color = c->colors[t]; - - return pos; -} - -void curve_destroy(curve_t *c) { - array_free(c->lengths); - array_free(c->colors); - array_free(c->samples); - array_free(c->points); - array_free(c->indices); -} -#line 0 - #line 1 "engine/split/v4k_system.c" #if (is(tcc) && is(linux)) || (is(gcc) && !is(mingw)) // || is(clang) int __argc; char **__argv; @@ -356279,6 +357212,646 @@ int (test)(const char *file, int line, const char *expr, bool result) { } #line 0 +#line 1 "engine/split/v4k_time.c" +// ---------------------------------------------------------------------------- +// time + +#if 0 +uint64_t time_gpu() { + GLint64 t = 123456789; + glGetInteger64v(GL_TIMESTAMP, &t); + return (uint64_t)t; +} +#endif +uint64_t date() { + time_t epoch = time(0); + struct tm *ti = localtime(&epoch); + return atoi64(va("%04d%02d%02d%02d%02d%02d",ti->tm_year+1900,ti->tm_mon+1,ti->tm_mday,ti->tm_hour,ti->tm_min,ti->tm_sec)); +} +char *date_string() { + time_t epoch = time(0); + struct tm *ti = localtime(&epoch); + return va("%04d-%02d-%02d %02d:%02d:%02d",ti->tm_year+1900,ti->tm_mon+1,ti->tm_mday,ti->tm_hour,ti->tm_min,ti->tm_sec); +} +uint64_t date_epoch() { + time_t epoch = time(0); + return epoch; +} +#if 0 +double time_ss() { + return glfwGetTime(); +} +double time_ms() { + return glfwGetTime() * 1000.0; +} +uint64_t time_us() { + return (uint64_t)(glfwGetTime() * 1000000.0); // @fixme: use a high resolution timer instead, or time_gpu below +} +uint64_t sleep_us(uint64_t us) { // @fixme: use a high resolution sleeper instead + return sleep_ms( us / 1000.0 ); +} +double sleep_ms(double ms) { + double now = time_ms(); + if( ms <= 0 ) { +#if is(win32) + Sleep(0); // yield +#else + usleep(0); +#endif + } else { +#if is(win32) + Sleep(ms); +#else + usleep(ms * 1000); +#endif + } + return time_ms() - now; +} +double sleep_ss(double ss) { + return sleep_ms( ss * 1000 ) / 1000.0; +} +#endif + +// high-perf functions + +#define TIMER_E3 1000ULL +#define TIMER_E6 1000000ULL +#define TIMER_E9 1000000000ULL + +#ifdef CLOCK_MONOTONIC_RAW +#define TIME_MONOTONIC CLOCK_MONOTONIC_RAW +#elif defined CLOCK_MONOTONIC +#define TIME_MONOTONIC CLOCK_MONOTONIC +#else +// #define TIME_MONOTONIC CLOCK_REALTIME // untested +#endif + +static uint64_t nanotimer(uint64_t *out_freq) { + if( out_freq ) { +#if is(win32) + LARGE_INTEGER li; + QueryPerformanceFrequency(&li); + *out_freq = li.QuadPart; +//#elif is(ANDROID) +// *out_freq = CLOCKS_PER_SEC; +#elif defined TIME_MONOTONIC + *out_freq = TIMER_E9; +#else + *out_freq = TIMER_E6; +#endif + } +#if is(win32) + LARGE_INTEGER li; + QueryPerformanceCounter(&li); + return (uint64_t)li.QuadPart; +//#elif is(ANDROID) +// return (uint64_t)clock(); +#elif defined TIME_MONOTONIC + struct timespec ts; + clock_gettime(TIME_MONOTONIC, &ts); + return (TIMER_E9 * (uint64_t)ts.tv_sec) + ts.tv_nsec; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return (TIMER_E6 * (uint64_t)tv.tv_sec) + tv.tv_usec; +#endif +} + +uint64_t time_ns() { + static uint64_t epoch = 0; + static uint64_t freq = 0; + if( !freq ) { + epoch = nanotimer(&freq); + } + + uint64_t a = nanotimer(NULL) - epoch; + uint64_t b = TIMER_E9; + uint64_t c = freq; + + // Computes (a*b)/c without overflow, as long as both (a*b) and the overall result fit into 64-bits. + // [ref] https://github.com/rust-lang/rust/blob/3809bbf47c8557bd149b3e52ceb47434ca8378d5/src/libstd/sys_common/mod.rs#L124 + uint64_t q = a / c; + uint64_t r = a % c; + return q * b + r * b / c; +} +uint64_t time_us() { + return time_ns() / TIMER_E3; +} +uint64_t time_ms() { + return time_ns() / TIMER_E6; +} +double time_ss() { + return time_ns() / 1e9; // TIMER_E9; +} +double time_mm() { + return time_ss() / 60; +} +double time_hh() { + return time_mm() / 60; +} + +void sleep_ns( double ns ) { +#if is(win32) + if( ns >= 100 ) { + LARGE_INTEGER li; // Windows sleep in 100ns units + HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL); + li.QuadPart = (LONGLONG)(__int64)(-ns/100); // Negative for relative time + SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE); + WaitForSingleObject(timer, INFINITE); + CloseHandle(timer); +#else + if( ns > 0 ) { + struct timespec wait = {0}; + wait.tv_sec = ns / 1e9; + wait.tv_nsec = ns - wait.tv_sec * 1e9; + nanosleep(&wait, NULL); +#endif + } else { +#if is(win32) + Sleep(0); // yield, Sleep(0), SwitchToThread +#else + usleep(0); +#endif + } +} +void sleep_us( double us ) { + sleep_ns(us * 1e3); +} +void sleep_ms( double ms ) { + sleep_ns(ms * 1e6); +} +void sleep_ss( double ss ) { + sleep_ns(ss * 1e9); +} + +// ---------------------------------------------------------------------------- +// timer + +struct timer_internal_t { + unsigned ms; + unsigned (*callback)(unsigned interval, void *arg); + void *arg; + thread_ptr_t thd; +}; + +static int timer_func(void *arg) { + struct timer_internal_t *p = (struct timer_internal_t*)arg; + + sleep_ms( p->ms ); + + for( ;; ) { + unsigned then = time_ms(); + + p->ms = p->callback(p->ms, p->arg); + if( !p->ms ) break; + + unsigned now = time_ms(); + unsigned lapse = now - then; + int diff = p->ms - lapse; + sleep_ms( diff <= 0 ? 0 : diff ); + } + + thread_exit(0); + return 0; +} + +static __thread array(struct timer_internal_t *) timers; + +unsigned timer(unsigned ms, unsigned (*callback)(unsigned ms, void *arg), void *arg) { + struct timer_internal_t *p = MALLOC( sizeof(struct timer_internal_t) ); + p->ms = ms; + p->callback = callback; + p->arg = arg; + p->thd = thread_init( timer_func, p, "", 0 ); + + array_push(timers, p); + return array_count(timers); +} +void timer_destroy(unsigned i) { + if( i-- ) { + thread_join(timers[i]->thd); + thread_term(timers[i]->thd); + FREE(timers[i]); + timers[i] = 0; + } +} + +// ---------------------------------------------------------------------------- +// guid + +//typedef vec3i guid; + +guid guid_create() { + static __thread unsigned counter = 0; + static uint64_t appid = 0; do_once appid = hash_str(app_name()); + + union conv { + struct { + unsigned timestamp : 32; + unsigned threadid : 16; // inverted order in LE + unsigned appid : 16; // + unsigned counter : 32; + }; + vec3i v3; + } c; + c.timestamp = date_epoch() - 0x65000000; + c.appid = (unsigned)appid; + c.threadid = (unsigned)(uintptr_t)thread_current_thread_id(); + c.counter = ++counter; + + return c.v3; +} + +// ---------------------------------------------------------------------------- +// ease + +float ease_nop(float t) { return 0; } +float ease_linear(float t) { return t; } + +float ease_out_sine(float t) { return sinf(t*(C_PI*0.5f)); } +float ease_out_quad(float t) { return -(t*(t-2)); } +float ease_out_cubic(float t) { float f=t-1; return f*f*f+1; } +float ease_out_quart(float t) { float f=t-1; return f*f*f*(1-t)+1; } +float ease_out_quint(float t) { float f=(t-1); return f*f*f*f*f+1; } +float ease_out_expo(float t) { return (t >= 1) ? t : 1-powf(2,-10*t); } +float ease_out_circ(float t) { return sqrtf((2-t)*t); } +float ease_out_back(float t) { float f=1-t; return 1-(f*f*f-f*sinf(f*C_PI)); } +float ease_out_elastic(float t) { return sinf(-13*(C_PI*0.5f)*(t+1))*powf(2,-10*t)+1; } +float ease_out_bounce(float t) { return (t < 4.f/11) ? (121.f*t*t)/16 : (t < 8.f/11) ? (363.f/40*t*t)-(99.f/10*t)+17.f/5 : (t < 9.f/10) ? (4356.f/361*t*t)-(35442.f/1805*t)+16061.f/1805 : (54.f/5*t*t)-(513.f/25*t)+268.f/25; } + +float ease_in_sine(float t) { return 1+sinf((t-1)*(C_PI*0.5f)); } +float ease_in_quad(float t) { return t*t; } +float ease_in_cubic(float t) { return t*t*t; } +float ease_in_quart(float t) { return t*t*t*t; } +float ease_in_quint(float t) { return t*t*t*t*t; } +float ease_in_expo(float t) { return (t <= 0) ? t : powf(2,10*(t-1)); } +float ease_in_circ(float t) { return 1-sqrtf(1-(t*t)); } +float ease_in_back(float t) { return t*t*t-t*sinf(t*C_PI); } +float ease_in_elastic(float t) { return sinf(13*(C_PI*0.5f)*t)*powf(2,10*(t-1)); } +float ease_in_bounce(float t) { return 1-ease_out_bounce(1-t); } + +float ease_inout_sine(float t) { return 0.5f*(1-cosf(t*C_PI)); } +float ease_inout_quad(float t) { return (t < 0.5f) ? 2*t*t : (-2*t*t)+(4*t)-1; } +float ease_inout_cubic(float t) { float f; return (t < 0.5f) ? 4*t*t*t : (f=(2*t)-2,0.5f*f*f*f+1); } +float ease_inout_quart(float t) { float f; return (t < 0.5f) ? 8*t*t*t*t : (f=(t-1),-8*f*f*f*f+1); } +float ease_inout_quint(float t) { float f; return (t < 0.5f) ? 16*t*t*t*t*t : (f=((2*t)-2),0.5f*f*f*f*f*f+1); } +float ease_inout_expo(float t) { return (t <= 0 || t >= 1) ? t : t < 0.5f ? 0.5f*powf(2,(20*t)-10) : -0.5f*powf(2,(-20*t)+10)+1; } +float ease_inout_circ(float t) { return t < 0.5f ? 0.5f*(1-sqrtf(1-4*(t*t))) : 0.5f*(sqrtf(-((2*t)-3)*((2*t)-1))+1); } +float ease_inout_back(float t) { float f; return t < 0.5f ? (f=2*t,0.5f*(f*f*f-f*sinf(f*C_PI))) : (f=(1-(2*t-1)),0.5f*(1-(f*f*f-f*sinf(f*C_PI)))+0.5f); } +float ease_inout_elastic(float t) { return t < 0.5f ? 0.5f*sinf(13*(C_PI*0.5f)*(2*t))*powf(2,10*((2*t)-1)) : 0.5f*(sinf(-13*(C_PI*0.5f)*((2*t-1)+1))*powf(2,-10*(2*t-1))+2); } +float ease_inout_bounce(float t) { return t < 0.5f ? 0.5f*ease_in_bounce(t*2) : 0.5f*ease_out_bounce(t*2-1)+0.5f; } + +float ease_inout_perlin(float t) { float t3=t*t*t,t4=t3*t,t5=t4*t; return 6*t5-15*t4+10*t3; } + +float ease(float t01, unsigned mode) { + typedef float (*easing)(float); + easing modes[] = { + ease_out_sine, + ease_out_quad, + ease_out_cubic, + ease_out_quart, + ease_out_quint, + ease_out_expo, + ease_out_circ, + ease_out_back, + ease_out_elastic, + ease_out_bounce, + + ease_in_sine, + ease_in_quad, + ease_in_cubic, + ease_in_quart, + ease_in_quint, + ease_in_expo, + ease_in_circ, + ease_in_back, + ease_in_elastic, + ease_in_bounce, + + ease_inout_sine, + ease_inout_quad, + ease_inout_cubic, + ease_inout_quart, + ease_inout_quint, + ease_inout_expo, + ease_inout_circ, + ease_inout_back, + ease_inout_elastic, + ease_inout_bounce, + + ease_nop, + ease_linear, + ease_inout_perlin, + }; + return modes[clampi(mode, 0, countof(modes))](clampf(t01,0,1)); +} + +float ease_pong(float t, unsigned fn) { return 1 - ease(t, fn); } +float ease_ping_pong(float t, unsigned fn1, unsigned fn2) { return t < 0.5 ? ease(t*2,fn1) : ease(1-(t-0.5)*2,fn2); } +float ease_pong_ping(float t, unsigned fn1, unsigned fn2) { return 1 - ease_ping_pong(t,fn1,fn2); } + + +const char **ease_enums() { + static const char *list[] = { + "ease_out_sine", + "ease_out_quad", + "ease_out_cubic", + "ease_out_quart", + "ease_out_quint", + "ease_out_expo", + "ease_out_circ", + "ease_out_back", + "ease_out_elastic", + "ease_out_bounce", + + "ease_in_sine", + "ease_in_quad", + "ease_in_cubic", + "ease_in_quart", + "ease_in_quint", + "ease_in_expo", + "ease_in_circ", + "ease_in_back", + "ease_in_elastic", + "ease_in_bounce", + + "ease_inout_sine", + "ease_inout_quad", + "ease_inout_cubic", + "ease_inout_quart", + "ease_inout_quint", + "ease_inout_expo", + "ease_inout_circ", + "ease_inout_back", + "ease_inout_elastic", + "ease_inout_bounce", + + "ease_nop", + "ease_linear", + "ease_inout_perlin", + + 0 + }; + return list; +} + +const char *ease_enum(unsigned mode) { + return mode[ ease_enums() ]; +} + +/*AUTORUN { + ENUM(EASE_LINEAR|EASE_OUT); + ENUM(EASE_SINE|EASE_OUT); + ENUM(EASE_QUAD|EASE_OUT); + ENUM(EASE_CUBIC|EASE_OUT); + ENUM(EASE_QUART|EASE_OUT); + ENUM(EASE_QUINT|EASE_OUT); + ENUM(EASE_EXPO|EASE_OUT); + ENUM(EASE_CIRC|EASE_OUT); + ENUM(EASE_BACK|EASE_OUT); + ENUM(EASE_ELASTIC|EASE_OUT); + ENUM(EASE_BOUNCE|EASE_OUT); + + ENUM(EASE_SINE|EASE_IN); + ENUM(EASE_QUAD|EASE_IN); + ENUM(EASE_CUBIC|EASE_IN); + ENUM(EASE_QUART|EASE_IN); + ENUM(EASE_QUINT|EASE_IN); + ENUM(EASE_EXPO|EASE_IN); + ENUM(EASE_CIRC|EASE_IN); + ENUM(EASE_BACK|EASE_IN); + ENUM(EASE_ELASTIC|EASE_IN); + ENUM(EASE_BOUNCE|EASE_IN); + + ENUM(EASE_SINE|EASE_INOUT); + ENUM(EASE_QUAD|EASE_INOUT); + ENUM(EASE_CUBIC|EASE_INOUT); + ENUM(EASE_QUART|EASE_INOUT); + ENUM(EASE_QUINT|EASE_INOUT); + ENUM(EASE_EXPO|EASE_INOUT); + ENUM(EASE_CIRC|EASE_INOUT); + ENUM(EASE_BACK|EASE_INOUT); + ENUM(EASE_ELASTIC|EASE_INOUT); + ENUM(EASE_BOUNCE|EASE_INOUT); + + ENUM(EASE_NOP); + ENUM(EASE_LINEAR); + ENUM(EASE_INOUT_PERLIN); +};*/ + +// ---------------------------------------------------------------------------- +// tween + +tween_t tween() { + tween_t tw = {0}; + return tw; +} + +float tween_update(tween_t *tw, float dt) { + if( !array_count(tw->keyframes) ) return 0.0f; + + for( int i = 0, end = array_count(tw->keyframes) - 1; i < end; ++i ) { + tween_keyframe_t *kf1 = &tw->keyframes[i]; + tween_keyframe_t *kf2 = &tw->keyframes[i + 1]; + if (tw->time >= kf1->t && tw->time <= kf2->t) { + float localT = (tw->time - kf1->t) / (kf2->t - kf1->t); + float easedT = ease(localT, kf1->ease); + tw->result = mix3(kf1->v, kf2->v, easedT); + break; + } + } + + float done = (tw->time / tw->duration); + tw->time += dt; + return clampf(done, 0.0f, 1.0f); +} + +void tween_reset(tween_t *tw) { + tw->time = 0.0f; +} + +void tween_destroy(tween_t *tw) { + tween_t tw_ = {0}; + array_free(tw->keyframes); + *tw = tw_; +} + +static INLINE +int tween_comp_keyframes(const void *a, const void *b) { + float t1 = ((const tween_keyframe_t*)a)->t; + float t2 = ((const tween_keyframe_t*)b)->t; + return (t1 > t2) - (t1 < t2); +} + +void tween_setkey(tween_t *tw, float t, vec3 v, unsigned mode) { + tween_keyframe_t keyframe = { t, v, mode }; + array_push(tw->keyframes, keyframe); + array_sort(tw->keyframes, tween_comp_keyframes); + tw->duration = array_back(tw->keyframes)->t; +} + +void tween_delkey(tween_t *tw, float t) { // @todo: untested + for( int i = 0, end = array_count(tw->keyframes); i < end; i++ ) { + if( tw->keyframes[i].t == t ) { + array_erase_slow(tw->keyframes, i); + tw->duration = array_back(tw->keyframes)->t; + return; + } + } +} + +// ---------------------------------------------------------------------------- +// curve + +curve_t curve() { + curve_t c = {0}; + return c; +} + +static INLINE +vec3 catmull( vec3 p0, vec3 p1, vec3 p2, vec3 p3, float t ) { + float t2 = t*t; + float t3 = t*t*t; + + vec3 c; + c.x = 0.5 * ((2 * p1.x) + (-p0.x + p2.x) * t + (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 + (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3); + c.y = 0.5 * ((2 * p1.y) + (-p0.y + p2.y) * t + (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 + (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3); + c.z = 0.5 * ((2 * p1.z) + (-p0.z + p2.z) * t + (2 * p0.z - 5 * p1.z + 4 * p2.z - p3.z) * t2 + (-p0.z + 3 * p1.z - 3 * p2.z + p3.z) * t3); + return c; +} + +void curve_add(curve_t *c, vec3 p) { + array_push(c->points, p); +} + +void curve_end( curve_t *c, int k ) { + ASSERT( k > 0 ); + + array_free(c->lengths); + array_free(c->samples); + array_free(c->indices); + array_free(c->colors); + + // refit points[N] to samples[K] + int N = array_count(c->points); + if( k < N ) { + // truncate: expected k-points lesser or equal than existing N points + for( int i = 0; i <= k; ++i ) { + float s = (float)i / k; + int t = s * (N-1); + array_push(c->samples, c->points[t]); + + float p = fmod(i, N-1) / (N-1); // [0..1) + int is_control_point = p <= 0 || p >= 1; + array_push(c->colors, is_control_point ? ORANGE: BLUE); + } + + } else { + // interpolate: expected k-points greater than existing N-points + --N; + int upper = N - (k%N); + int lower = (k%N); + if(upper < lower) + k += upper; + else + k -= lower; + + int points_per_segment = (k / N); + ++N; + + int looped = len3sq(sub3(c->points[0], *array_back(c->points))) < 0.1; + + for( int i = 0; i <= k; ++i ) { + int point = i % points_per_segment; + float p = point / (float)points_per_segment; // [0..1) + int t = i / points_per_segment; + + // linear + vec3 l = mix3(c->points[t], c->points[t+(i!=k)], p); + + // printf("%d) %d>%d %f\n", i, t, t+(i!=k), p); + ASSERT(p <= 1); + + // catmull + int p0 = t - 1; + int p1 = t + 0; + int p2 = t + 1; + int p3 = t + 2; + if( looped ) + { + int M = N-1; + if(p0<0) p0+=M; else if(p0>=M) p0-=M; + if(p1<0) p1+=M; else if(p1>=M) p1-=M; + if(p2<0) p2+=M; else if(p2>=M) p2-=M; + if(p3<0) p3+=M; else if(p3>=M) p3-=M; + } + else + { + int M = N-1; + if(p0<0) p0=0; else if(p0>=M) p0=M; + if(p1<0) p1=0; else if(p1>=M) p1=M; + if(p2<0) p2=0; else if(p2>=M) p2=M; + if(p3<0) p3=0; else if(p3>=M) p3=M; + } + vec3 m = catmull(c->points[p0],c->points[p1],c->points[p2],c->points[p3],p); + l = m; + + array_push(c->samples, l); + + int is_control_point = p <= 0 || p >= 1; + array_push(c->colors, is_control_point ? ORANGE: BLUE); + } + } + + array_push(c->lengths, 0 ); + for( int i = 1; i <= k; ++i ) { + // approximate curve length at every sample point + array_push(c->lengths, len3(sub3(c->samples[i], c->samples[i-1])) + c->lengths[i-1] ); + } + // normalize lengths to be between 0 and 1 + float maxv = c->lengths[k]; + for( int i = 1; i <= k; ++i ) c->lengths[i] /= maxv; + + array_push(c->indices, 0 ); + for( int i = 0/*1*/; i indices) + 1; j lengths[j] lengths[j] > 0.01) + array_push(c->indices, j ); + } +} + +vec3 curve_eval(curve_t *c, float dt, unsigned *color) { + unsigned nil; if(!color) color = &nil; + dt = clampf(dt, 0.0f, 1.0f); + int l = (int)(array_count(c->indices) - 1); + int p = (int)(dt * l); + int t = c->indices[p]; + + t %= (array_count(c->indices)-1); + vec3 pos = mix3(c->samples[t], c->samples[t+1], dt * l - p); + *color = c->colors[t]; + + return pos; +} + +void curve_destroy(curve_t *c) { + array_free(c->lengths); + array_free(c->colors); + array_free(c->samples); + array_free(c->points); + array_free(c->indices); +} +#line 0 + #line 1 "engine/split/v4k_profile.c" #if ENABLE_PROFILER profiler_t profiler; @@ -357544,10 +359117,10 @@ void window_cursor_shape(unsigned mode) { 0, GLFW_ARROW_CURSOR, GLFW_IBEAM_CURSOR, - GLFW_CROSSHAIR_CURSOR, - GLFW_HAND_CURSOR, GLFW_HRESIZE_CURSOR, GLFW_VRESIZE_CURSOR, + GLFW_HAND_CURSOR, + GLFW_CROSSHAIR_CURSOR, }; do_once { static unsigned pixels[16 * 16] = { 0x01000000 }; // ABGR(le) glfw3 note: A(0x00) means 0xFF for some reason @@ -357640,7 +359213,20 @@ int window_has_maximize() { return ifdef(ems, 0, glfwGetWindowAttrib(window, GLFW_MAXIMIZED) == GLFW_TRUE); } +const char *window_clipboard() { + return glfwGetClipboardString(window); +} +void window_setclipboard(const char *text) { + glfwSetClipboardString(window, text); +} +static +double window_scale() { // ok? @testme + float xscale, yscale; + GLFWmonitor *monitor = glfwGetPrimaryMonitor(); + glfwGetMonitorContentScale(monitor, &xscale, &yscale); + return maxi(xscale, yscale); +} #line 0 #line 1 "engine/split/v4k_obj.c" @@ -358995,7 +360581,7 @@ int pathfind_astar(int width, int height, const unsigned* map, vec2i src, vec2i #error ASTAR_POS_INDEX(p) should specify macro to map position to index #endif - #ifndef ASTAR_MAX_INDEX + #ifndef ASTAR_MAX_INDEX #error ASTAR_MAX_INDEX should specify max count of indices the position can map to #endif @@ -359086,7 +360672,7 @@ int pathfind_astar(int width, int height, const unsigned* map, vec2i src, vec2i i = p; \ p = (i - 1) / 2; \ } \ - } while (0) + } while (0) #define ASTAR_HEAP_POP() \ do { \ @@ -359277,7 +360863,7 @@ int pathfind_astar(int width, int height, const unsigned* map, vec2i src, vec2i // [ ] CompareKeys(keyVar1, operator < <= > >= == !=, keyVar2) // [ ] SetTags(names=blank,cooldownTime=inf,bIsCooldownAdditive=false) // [ ] HasTags(names=blank,bAllRequired=true) -// [ ] PushToStack(keyVar,itemObj): creates a new stack if one doesn’t exist, and stores it in the passed variable name, and then pushes ‘item’ object onto it. +// [ ] PushToStack(keyVar,itemObj): creates a new stack if one doesnt exist, and stores it in the passed variable name, and then pushes item object onto it. // [ ] PopFromStack(keyVar,itemVar): pop pops an item off the stack, and stores it in the itemVar variable, failing if the stack is already empty. // [ ] IsEmptyStack(keyVar): checks if the stack passed is empty and returns success if it is, and failure if its not. // [ ] Communication Node: This is a type of action node that allows an AI agent to communicate with other agents or entities in the game world. The node takes an input specifying the message to be communicated and the recipient(s) of the message (wildmask,l/p/f/g prefixes). The node then sends the message to the designated recipient(s) and returns success when the communication is completed. This node can be useful for implementing behaviors that require the AI agent to coordinate with other agents or to convey information to the player. It could use a radius argument to specify the maximum allowed distance for the recipients. diff --git a/engine/split/3rd_archive.h b/engine/split/3rd_archive.h index 73b74c4..5488b31 100644 --- a/engine/split/3rd_archive.h +++ b/engine/split/3rd_archive.h @@ -1491,8 +1491,12 @@ struct dir { // --- -#if !defined(S_ISDIR) -# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#ifndef S_ISDIR +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #endif int dir_yield(dir *d, const char *pathfile, char *name, int namelen) { diff --git a/engine/split/3rd_https.h b/engine/split/3rd_https.h index 6f9fb35..3a0b574 100644 --- a/engine/split/3rd_https.h +++ b/engine/split/3rd_https.h @@ -35042,12 +35042,12 @@ Compiling ---------- Simple TLS client: -`$ gcc tlshello.c -o tlshello -ltomcrypt -ltommath -DLTM_DESC` +`$ gcc tlshello.c -o tlshello -ltomcrypt -ltommath -DLTM_DESC` For debuging tls connections, the DEBUG flag must be set (-DDEBUG). Simple TLS server: -`$ gcc tlsserverhello.c -o tlsserverhello -ltomcrypt -ltommath -DLTM_DESC` +`$ gcc tlsserverhello.c -o tlsserverhello -ltomcrypt -ltommath -DLTM_DESC` The entire library is a single c file that you just include in your source. @@ -35068,7 +35068,7 @@ TLSe supports KTLS on linux kernel 4.13 or higher. KTLS is a TLS implementation Usage ---------- -You just +You just `#include "tlse.c"` in your code. Everything is a single file. @@ -35479,7 +35479,7 @@ int tls_make_ktls(struct TLSContext *context, int socket); int tls_unmake_ktls(struct TLSContext *context, int socket); /* Creates a new DTLS random cookie secret to be used in HelloVerifyRequest (server-side). - It is recommended to call this function from time to time, to protect against some + It is recommended to call this function from time to time, to protect against some DoS attacks. */ void dtls_reset_cookie_secret(); @@ -35573,17 +35573,17 @@ int tls_remote_error(struct TLSContext *context); /******************************************************************************** Copyright (c) 2016-2023, Eduard Suica All rights reserved. - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -36398,7 +36398,7 @@ int chacha20_poly1305_aead(struct chacha_ctx *ctx, unsigned char *pt, unsigned unsigned int counter = 1; chacha_ivsetup_96bitnonce(ctx, NULL, (unsigned char *)&counter); chacha_encrypt_bytes(ctx, pt, out, len); - + poly1305_context aead_ctx; _private_tls_poly1305_init(&aead_ctx, poly_key); _private_tls_poly1305_update(&aead_ctx, aad, aad_len); @@ -36418,7 +36418,7 @@ int chacha20_poly1305_aead(struct chacha_ctx *ctx, unsigned char *pt, unsigned _private_tls_poly1305_update(&aead_ctx, trail, 16); _private_tls_poly1305_finish(&aead_ctx, out + len); - + return len + POLY1305_TAGLEN; } #endif @@ -36790,19 +36790,19 @@ struct TLSContext { unsigned char cipher_spec_set; TLSCipher crypto; TLSHash *handshake_hash; - + unsigned char *message_buffer; unsigned int message_buffer_len; uint64_t remote_sequence_number; uint64_t local_sequence_number; - + unsigned char connection_status; unsigned char critical_error; unsigned char error_code; - + unsigned char *tls_buffer; unsigned int tls_buffer_len; - + unsigned char *application_buffer; unsigned int application_buffer_len; unsigned char is_child; @@ -36962,10 +36962,10 @@ void _private_b64_decodeblock(unsigned char in[4], unsigned char out[3]) { int _private_b64_decode(const char *in_buffer, int in_buffer_size, unsigned char *out_buffer) { unsigned char in[4], out[3], v; int i, len; - + const char *ptr = in_buffer; char *out_ptr = (char *)out_buffer; - + while (ptr <= in_buffer + in_buffer_size) { for (len = 0, i = 0; i < 4 && (ptr <= in_buffer + in_buffer_size); i++) { v = 0; @@ -37033,26 +37033,26 @@ int _private_tls_dh_shared_secret(DHKey *private_key, DHKey *public_key, unsigne void *tmp; unsigned long x; int err; - + if ((!private_key) || (!public_key) || (!out) || (!outlen)) return TLS_GENERIC_ERROR; - + /* compute y^x mod p */ if ((err = mp_init(&tmp)) != CRYPT_OK) return err; - + if ((err = mp_exptmod(public_key->y, private_key->x, private_key->p, tmp)) != CRYPT_OK) { mp_clear(tmp); return err; } - + x = (unsigned long)mp_unsigned_bin_size(tmp); if (*outlen < x) { err = CRYPT_BUFFER_OVERFLOW; mp_clear(tmp); return err; } - + if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { mp_clear(tmp); return err; @@ -37068,10 +37068,10 @@ unsigned char *_private_tls_decrypt_dhe(struct TLSContext *context, const unsign DEBUG_PRINT("No private DHE key set\n"); return NULL; } - + unsigned long out_size = len; void *Yc = NULL; - + if (mp_init(&Yc)) { DEBUG_PRINT("ERROR CREATING Yc\n"); return NULL; @@ -37085,7 +37085,7 @@ unsigned char *_private_tls_decrypt_dhe(struct TLSContext *context, const unsign unsigned char *out = (unsigned char *)TLS_MALLOC(len); DHKey client_key; memset(&client_key, 0, sizeof(DHKey)); - + client_key.p = context->dhe->p; client_key.g = context->dhe->g; client_key.y = Yc; @@ -37114,15 +37114,15 @@ unsigned char *_private_tls_decrypt_ecc_dhe(struct TLSContext *context, const un DEBUG_PRINT("No private ECC DHE key set\n"); return NULL; } - + const struct ECCCurveParameters *curve; if (context->curve) curve = context->curve; else curve = default_curve; - + ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&curve->dp; - + ecc_key client_key; memset(&client_key, 0, sizeof(client_key)); if (ecc_ansi_x963_import_ex(buffer, len, &client_key, dp)) { @@ -37131,7 +37131,7 @@ unsigned char *_private_tls_decrypt_ecc_dhe(struct TLSContext *context, const un } unsigned char *out = (unsigned char *)TLS_MALLOC(len); unsigned long out_size = len; - + int err = ecc_shared_secret(context->ecc_dhe, &client_key, out, &out_size); ecc_free(&client_key); if (clear_key) @@ -37158,7 +37158,7 @@ unsigned char *_private_tls_decrypt_rsa(struct TLSContext *context, const unsign rsa_key key; int err; err = rsa_import(context->private_key->der_bytes, context->private_key->der_len, &key); - + if (err) { DEBUG_PRINT("Error importing RSA key (code: %i)\n", err); return NULL; @@ -37192,7 +37192,7 @@ unsigned char *_private_tls_encrypt_rsa(struct TLSContext *context, const unsign rsa_key key; int err; err = rsa_import(context->certificates[0]->der_bytes, context->certificates[0]->der_len, &key); - + if (err) { DEBUG_PRINT("Error importing RSA certificate (code: %i)\n", err); return NULL; @@ -37216,28 +37216,28 @@ int _private_rsa_verify_hash_md5sha1(const unsigned char *sig, unsigned long sig unsigned long modulus_bitlen, modulus_bytelen, x; int err; unsigned char *tmpbuf = NULL; - + if ((hash == NULL) || (sig == NULL) || (stat == NULL) || (key == NULL) || (!siglen) || (!hashlen)) return TLS_GENERIC_ERROR; - + *stat = 0; - + modulus_bitlen = mp_count_bits((key->N)); - + modulus_bytelen = mp_unsigned_bin_size((key->N)); if (modulus_bytelen != siglen) return TLS_GENERIC_ERROR; - + tmpbuf = (unsigned char *)TLS_MALLOC(siglen); if (!tmpbuf) return TLS_GENERIC_ERROR; - + x = siglen; if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) { TLS_FREE(tmpbuf); return err; } - + if (x != siglen) { TLS_FREE(tmpbuf); return CRYPT_INVALID_PACKET; @@ -37248,7 +37248,7 @@ int _private_rsa_verify_hash_md5sha1(const unsigned char *sig, unsigned long sig TLS_FREE(tmpbuf); return TLS_GENERIC_ERROR; } - + int decoded = 0; err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &out_len, &decoded); if (decoded) { @@ -37257,7 +37257,7 @@ int _private_rsa_verify_hash_md5sha1(const unsigned char *sig, unsigned long sig *stat = 1; } } - + TLS_FREE(tmpbuf); TLS_FREE(out); return err; @@ -37268,7 +37268,7 @@ int _private_tls_verify_rsa(struct TLSContext *context, unsigned int hash_type, tls_init(); rsa_key key; int err; - + if (context->is_server) { if ((!len) || (!context->client_certificates) || (!context->client_certificates_count) || (!context->client_certificates[0]) || (!context->client_certificates[0]->der_bytes) || (!context->client_certificates[0]->der_len)) { @@ -37396,12 +37396,12 @@ int _private_tls_verify_rsa(struct TLSContext *context, unsigned int hash_type, int _private_rsa_sign_hash_md5sha1(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; - + if ((in == NULL) || (out == NULL) || (outlen == NULL) || (key == NULL)) return TLS_GENERIC_ERROR; - + modulus_bitlen = mp_count_bits((key->N)); - + modulus_bytelen = mp_unsigned_bin_size((key->N)); if (modulus_bytelen > *outlen) { *outlen = modulus_bytelen; @@ -37411,7 +37411,7 @@ int _private_rsa_sign_hash_md5sha1(const unsigned char *in, unsigned long inlen, err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x); if (err != CRYPT_OK) return err; - + return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key); } #endif @@ -37425,7 +37425,7 @@ int _private_tls_sign_rsa(struct TLSContext *context, unsigned int hash_type, co rsa_key key; int err; err = rsa_import(context->private_key->der_bytes, context->private_key->der_len, &key); - + if (err) { DEBUG_PRINT("Error importing RSA certificate (code: %i)\n", err); return TLS_GENERIC_ERROR; @@ -37534,7 +37534,7 @@ int _private_tls_sign_rsa(struct TLSContext *context, unsigned int hash_type, co rsa_free(&key); if (err) return 0; - + return 1; } @@ -37542,11 +37542,11 @@ int _private_tls_sign_rsa(struct TLSContext *context, unsigned int hash_type, co static int _private_tls_is_point(ecc_key *key) { void *prime, *b, *t1, *t2; int err; - + if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL)) != CRYPT_OK) { return err; } - + /* load prime and b */ if ((err = mp_read_radix(prime, TLS_TOMCRYPT_PRIVATE_DP(key)->prime, 16)) != CRYPT_OK) { goto error; @@ -37554,12 +37554,12 @@ static int _private_tls_is_point(ecc_key *key) { if ((err = mp_read_radix(b, TLS_TOMCRYPT_PRIVATE_DP(key)->B, 16)) != CRYPT_OK) { goto error; } - + /* compute y^2 */ if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; } - + /* compute x^3 */ if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; @@ -37570,12 +37570,12 @@ static int _private_tls_is_point(ecc_key *key) { if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; } - + /* compute y^2 - x^3 */ if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; } - + /* compute y^2 - x^3 + 3x */ if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; @@ -37599,14 +37599,14 @@ static int _private_tls_is_point(ecc_key *key) { goto error; } } - + /* compare to b */ if (mp_cmp(t1, b) != LTC_MP_EQ) { err = CRYPT_INVALID_PACKET; } else { err = CRYPT_OK; } - + error: mp_clear_multi(prime, b, t1, t2, NULL); return err; @@ -37614,15 +37614,15 @@ error: int _private_tls_ecc_import_key(const unsigned char *private_key, int private_len, const unsigned char *public_key, int public_len, ecc_key *key, const ltc_ecc_set_type *dp) { int err; - + if ((!key) || (!ltc_mp.name)) return CRYPT_MEM; - + key->type = PK_PRIVATE; - + if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) return CRYPT_MEM; - + if ((public_len) && (!public_key[0])) { public_key++; public_len--; @@ -37631,33 +37631,33 @@ int _private_tls_ecc_import_key(const unsigned char *private_key, int private_le mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)public_key + 1 + ((public_len - 1) >> 1), (public_len - 1) >> 1)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)private_key, private_len)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + TLS_TOMCRYPT_PRIVATE_SET_INDEX(key, -1); TLS_TOMCRYPT_PRIVATE_DP(key) = dp; - + /* set z */ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + /* is it a point on the curve? */ if ((err = _private_tls_is_point(key)) != CRYPT_OK) { DEBUG_PRINT("KEY IS NOT ON CURVE\n"); mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + /* we're good */ return CRYPT_OK; } @@ -37668,9 +37668,9 @@ int _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, DEBUG_PRINT("No private ECDSA key set\n"); return TLS_GENERIC_ERROR; } - + const struct ECCCurveParameters *curve = NULL; - + switch (context->ec_private_key->ec_algorithm) { case 19: curve = &secp192r1; @@ -37696,16 +37696,16 @@ int _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, default: DEBUG_PRINT("UNSUPPORTED CURVE\n"); } - + if (!curve) return TLS_GENERIC_ERROR; - + tls_init(); ecc_key key; int err; - + ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&curve->dp; - + // broken ... fix this err = _private_tls_ecc_import_key(context->ec_private_key->priv, context->ec_private_key->priv_len, context->ec_private_key->pk, context->ec_private_key->pk_len, &key, dp); if (err) { @@ -37784,7 +37784,7 @@ int _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, hash_len = 36; break; } - + if (err) { DEBUG_PRINT("Unsupported hash type: %i\n", hash_type); return TLS_GENERIC_ERROR; @@ -37797,22 +37797,22 @@ int _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, ecc_free(&key); if (err) return 0; - + return 1; } #if defined(TLS_CLIENT_ECDSA) || defined(WITH_TLS_13) int _private_tls_ecc_import_pk(const unsigned char *public_key, int public_len, ecc_key *key, const ltc_ecc_set_type *dp) { int err; - + if ((!key) || (!ltc_mp.name)) return CRYPT_MEM; - + key->type = PK_PUBLIC; - + if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) return CRYPT_MEM; - + if ((public_len) && (!public_key[0])) { public_key++; public_len--; @@ -37821,29 +37821,29 @@ int _private_tls_ecc_import_pk(const unsigned char *public_key, int public_len, mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)public_key + 1 + ((public_len - 1) >> 1), (public_len - 1) >> 1)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - - + + TLS_TOMCRYPT_PRIVATE_SET_INDEX(key, -1); TLS_TOMCRYPT_PRIVATE_DP(key) = dp; - + /* set z */ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + /* is it a point on the curve? */ if ((err = _private_tls_is_point(key)) != CRYPT_OK) { DEBUG_PRINT("KEY IS NOT ON CURVE\n"); mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + /* we're good */ return CRYPT_OK; } @@ -37985,10 +37985,10 @@ void _private_tls_sleep(unsigned int microseconds) { Sleep(microseconds/1000); #else struct timespec ts; - + ts.tv_sec = (unsigned int) (microseconds / 1000000); ts.tv_nsec = (unsigned int) (microseconds % 1000000) * 1000ul; - + nanosleep(&ts, NULL); #endif } @@ -38007,10 +38007,10 @@ void _private_tls_prf_helper(int hash_idx, unsigned long dlen, unsigned char *ou unsigned char digest_out1[TLS_MAX_HASH_LEN]; unsigned int i; hmac_state hmac; - + hmac_init(&hmac, hash_idx, secret, secret_len); hmac_process(&hmac, label, label_len); - + hmac_process(&hmac, seed, seed_len); if ((seed_b) && (seed_b_len)) hmac_process(&hmac, seed_b, seed_b_len); @@ -38024,19 +38024,19 @@ void _private_tls_prf_helper(int hash_idx, unsigned long dlen, unsigned char *ou if ((seed_b) && (seed_b_len)) hmac_process(&hmac, seed_b, seed_b_len); hmac_done(&hmac, digest_out1, &dlen); - + unsigned int copylen = outlen; if (copylen > dlen) copylen = dlen; - + for (i = 0; i < copylen; i++) { output[idx++] ^= digest_out1[i]; outlen--; } - + if (!outlen) break; - + hmac_init(&hmac, hash_idx, secret, secret_len); hmac_process(&hmac, digest_out0, dlen); hmac_done(&hmac, digest_out0, &dlen); @@ -38106,18 +38106,18 @@ void _private_tls_hkdf_expand(unsigned int mac_length, unsigned char *output, un i2++; hmac_process(&hmac, &i2, 1); hmac_done(&hmac, digest_out, &dlen); - + unsigned int copylen = outlen; if (copylen > dlen) copylen = (unsigned int)dlen; - + for (i = 0; i < copylen; i++) { output[idx++] = digest_out[i]; outlen--; } - + if (!outlen) - break; + break; } } @@ -38141,7 +38141,7 @@ void _private_tls_prf(struct TLSContext *context, int md5_hash_idx = find_hash("md5"); int sha1_hash_idx = find_hash("sha1"); int half_secret = (secret_len + 1) / 2; - + memset(output, 0, outlen); _private_tls_prf_helper(md5_hash_idx, 16, output, outlen, secret, half_secret, label, label_len, seed, seed_len, seed_b, seed_b_len); _private_tls_prf_helper(sha1_hash_idx, 20, output, outlen, secret + (secret_len - half_secret), secret_len - half_secret, label, label_len, seed, seed_len, seed_b, seed_b_len); @@ -38159,10 +38159,10 @@ void _private_tls_prf(struct TLSContext *context, hash_idx = find_hash("sha256"); unsigned int i; hmac_state hmac; - + hmac_init(&hmac, hash_idx, secret, secret_len); hmac_process(&hmac, label, label_len); - + hmac_process(&hmac, seed, seed_len); if ((seed_b) && (seed_b_len)) hmac_process(&hmac, seed_b, seed_b_len); @@ -38176,19 +38176,19 @@ void _private_tls_prf(struct TLSContext *context, if ((seed_b) && (seed_b_len)) hmac_process(&hmac, seed_b, seed_b_len); hmac_done(&hmac, digest_out1, &dlen); - + unsigned int copylen = outlen; if (copylen > dlen) copylen = (unsigned int)dlen; - + for (i = 0; i < copylen; i++) { output[idx++] = digest_out1[i]; outlen--; } - + if (!outlen) break; - + hmac_init(&hmac, hash_idx, secret, secret_len); hmac_process(&hmac, digest_out0, dlen); hmac_done(&hmac, digest_out0, &dlen); @@ -38309,8 +38309,8 @@ int _private_tls13_key(struct TLSContext *context, int handshake) { unsigned int mac_length = _private_tls_mac_length(context); if ((!context->premaster_key) || (!context->premaster_key_len)) - return 0; - + return 0; + if ((!key_length) || (!mac_length)) { DEBUG_PRINT("KEY EXPANSION FAILED, KEY LENGTH: %i, MAC LENGTH: %i\n", key_length, mac_length); return 0; @@ -38415,7 +38415,7 @@ int _private_tls13_key(struct TLSContext *context, int handshake) { DEBUG_DUMP_HEX_LABEL("CLIENT IV", clientiv, iv_length) DEBUG_DUMP_HEX_LABEL("SERVER KEY", serverkey, key_length) DEBUG_DUMP_HEX_LABEL("SERVER IV", serveriv, iv_length) - + TLS_FREE(context->finished_key); TLS_FREE(context->remote_finished_key); if (handshake) { @@ -38488,7 +38488,7 @@ int _private_tls13_key(struct TLSContext *context, int handshake) { } context->local_sequence_number = 0; context->remote_sequence_number = 0; - + // extract client_mac_key(mac_key_length) // extract server_mac_key(mac_key_length) // extract client_key(enc_key_length) @@ -38505,13 +38505,13 @@ int _private_tls_expand_key(struct TLSContext *context) { if ((context->version == TLS_V13) || (context->version == DTLS_V13)) return 0; #endif - + if ((!context->master_key) || (!context->master_key_len)) return 0; - + int key_length = _private_tls_key_length(context); int mac_length = _private_tls_mac_length(context); - + if ((!key_length) || (!mac_length)) { DEBUG_PRINT("KEY EXPANSION FAILED, KEY LENGTH: %i, MAC LENGTH: %i\n", key_length, mac_length); return 0; @@ -38526,13 +38526,13 @@ int _private_tls_expand_key(struct TLSContext *context) { _private_tls_prf(context, key, sizeof(key), context->master_key, context->master_key_len, (unsigned char *)"key expansion", 13, context->local_random, TLS_SERVER_RANDOM_SIZE, context->remote_random, TLS_CLIENT_RANDOM_SIZE); else _private_tls_prf(context, key, sizeof(key), context->master_key, context->master_key_len, (unsigned char *)"key expansion", 13, context->remote_random, TLS_SERVER_RANDOM_SIZE, context->local_random, TLS_CLIENT_RANDOM_SIZE); - + DEBUG_DUMP_HEX_LABEL("LOCAL RANDOM ", context->local_random, TLS_SERVER_RANDOM_SIZE); DEBUG_DUMP_HEX_LABEL("REMOTE RANDOM", context->remote_random, TLS_CLIENT_RANDOM_SIZE); DEBUG_PRINT("\n=========== EXPANSION ===========\n"); DEBUG_DUMP_HEX(key, TLS_MAX_KEY_EXPANSION_SIZE); DEBUG_PRINT("\n"); - + int pos = 0; #ifdef TLS_WITH_CHACHA20_POLY1305 if (is_aead == 2) { @@ -38554,7 +38554,7 @@ int _private_tls_expand_key(struct TLSContext *context) { pos += mac_length; } } - + clientkey = &key[pos]; pos += key_length; serverkey = &key[pos]; @@ -38570,7 +38570,7 @@ int _private_tls_expand_key(struct TLSContext *context) { DEBUG_DUMP_HEX_LABEL("SERVER KEY", serverkey, key_length) DEBUG_DUMP_HEX_LABEL("SERVER IV", serveriv, iv_length) DEBUG_DUMP_HEX_LABEL("SERVER MAC KEY", context->is_server ? context->crypto.ctx_local_mac.local_mac : context->crypto.ctx_remote_mac.remote_mac, mac_length) - + if (context->is_server) { #ifdef TLS_WITH_CHACHA20_POLY1305 if (is_aead == 2) { @@ -38598,7 +38598,7 @@ int _private_tls_expand_key(struct TLSContext *context) { if (_private_tls_crypto_create(context, key_length, clientkey, clientiv, serverkey, serveriv)) return 0; } - + if (context->exportable) { TLS_FREE(context->exportable_keys); context->exportable_keys = (unsigned char *)TLS_MALLOC(key_length * 2); @@ -38613,7 +38613,7 @@ int _private_tls_expand_key(struct TLSContext *context) { context->exportable_size = key_length * 2; } } - + // extract client_mac_key(mac_key_length) // extract server_mac_key(mac_key_length) // extract client_key(enc_key_length) @@ -38692,14 +38692,14 @@ unsigned char *tls_pem_decode(const unsigned char *data_in, unsigned int input_l for (i = 0; i < input_length; i++) { if ((data_in[i] == '\n') || (data_in[i] == '\r')) continue; - + if (data_in[i] != '-') { // read entire line while ((i < input_length) && (data_in[i] != '\n')) i++; continue; } - + if (data_in[i] == '-') { unsigned int end_idx = i; //read until end of line @@ -38730,7 +38730,7 @@ int _is_oid(const unsigned char *oid, const unsigned char *compare_to, int compa while ((oid[i]) && (i < compare_to_len)) { if (oid[i] != compare_to[i]) return 0; - + i++; } return 1; @@ -38743,7 +38743,7 @@ int _is_oid2(const unsigned char *oid, const unsigned char *compare_to, int comp while (i < compare_to_len) { if (oid[i] != compare_to[i]) return 0; - + i++; } return 1; @@ -38760,17 +38760,17 @@ int tls_certificate_valid_subject_name(const unsigned char *cert_subject, const // no subjects ... if (((!cert_subject) || (!cert_subject[0])) && ((!subject) || (!subject[0]))) return 0; - + if ((!subject) || (!subject[0])) return bad_certificate; - + if ((!cert_subject) || (!cert_subject[0])) return bad_certificate; - + // exact match if (!strcmp((const char *)cert_subject, subject)) return 0; - + const char *wildcard = strchr((const char *)cert_subject, '*'); if (wildcard) { // 6.4.3 (1) The client SHOULD NOT attempt to match a presented identifier in @@ -38801,7 +38801,7 @@ int tls_certificate_valid_subject_name(const unsigned char *cert_subject, const return 0; } } - + return bad_certificate; } @@ -39026,7 +39026,7 @@ char *tls_certificate_to_string(struct TLSCertificate *cert, char *buffer, int l default: res += snprintf(buffer + res, len - res, "not supported):\n"); } - + for (i = 0; i < cert->sign_len; i++) res += snprintf(buffer + res, len - res, "%02x", (int)cert->sign_key[i]); } @@ -39106,32 +39106,32 @@ void tls_certificate_set_algorithm(struct TLSContext *context, unsigned int *alg } if (len != 9) return; - + if (_is_oid(val, TLS_RSA_SIGN_SHA256_OID, 9)) { *algorithm = TLS_RSA_SIGN_SHA256; return; } - + if (_is_oid(val, TLS_RSA_SIGN_RSA_OID, 9)) { *algorithm = TLS_RSA_SIGN_RSA; return; } - + if (_is_oid(val, TLS_RSA_SIGN_SHA1_OID, 9)) { *algorithm = TLS_RSA_SIGN_SHA1; return; } - + if (_is_oid(val, TLS_RSA_SIGN_SHA512_OID, 9)) { *algorithm = TLS_RSA_SIGN_SHA512; return; } - + if (_is_oid(val, TLS_RSA_SIGN_SHA384_OID, 9)) { *algorithm = TLS_RSA_SIGN_SHA384; return; } - + if (_is_oid(val, TLS_RSA_SIGN_MD5_OID, 9)) { *algorithm = TLS_RSA_SIGN_MD5; return; @@ -39268,14 +39268,14 @@ int _private_tls_crypto_create(struct TLSContext *context, int key_length, unsig if (is_aead) { int res1 = gcm_init(&context->crypto.ctx_local.aes_gcm_local, cipherID, localkey, key_length); int res2 = gcm_init(&context->crypto.ctx_remote.aes_gcm_remote, cipherID, remotekey, key_length); - + if ((res1) || (res2)) return TLS_GENERIC_ERROR; context->crypto.created = 2; } else { int res1 = cbc_start(cipherID, localiv, localkey, key_length, 0, &context->crypto.ctx_local.aes_local); int res2 = cbc_start(cipherID, remoteiv, remotekey, key_length, 0, &context->crypto.ctx_remote.aes_remote); - + if ((res1) || (res2)) return TLS_GENERIC_ERROR; context->crypto.created = 1; @@ -39294,7 +39294,7 @@ int _private_tls_crypto_encrypt(struct TLSContext *context, unsigned char *buf, int _private_tls_crypto_decrypt(struct TLSContext *context, unsigned char *buf, unsigned char *pt, unsigned int len) { if (context->crypto.created == 1) return cbc_decrypt(buf, pt, len, &context->crypto.ctx_remote.aes_remote); - + memset(pt, 0, len); return TLS_GENERIC_ERROR; } @@ -39316,7 +39316,7 @@ void _private_tls_crypto_done(struct TLSContext *context) { } void tls_packet_update(struct TLSPacket *packet) { - if ((packet) && (!packet->broken)) { + if ((packet) && (!packet->broken)) { int footer_size = 0; #ifdef WITH_TLS_13 if ((packet->context) && ((packet->context->version == TLS_V13) || (packet->context->version == DTLS_V13)) && (packet->context->cipher_spec_set) && (packet->context->crypto.created)) { @@ -39364,7 +39364,7 @@ void tls_packet_update(struct TLSPacket *packet) { unsigned int length = 0; unsigned char padding = 0; unsigned int pt_length = packet->len - header_size; - + if (packet->context->crypto.created == 1) { mac_size = _private_tls_mac_length(packet->context); #ifdef TLS_LEGACY_SUPPORT @@ -39412,10 +39412,10 @@ void tls_packet_update(struct TLSPacket *packet) { } else _private_tls_hmac_message(1, packet->context, packet->buf, packet->len, NULL, 0, buf + buf_pos, mac_size, 0); buf_pos += mac_size; - + memset(buf + buf_pos, padding - 1, padding); buf_pos += padding; - + //DEBUG_DUMP_HEX_LABEL("PT BUFFER", buf, length); _private_tls_crypto_encrypt(packet->context, buf, ct + header_size, length); TLS_FREE(packet->buf); @@ -39510,10 +39510,10 @@ void tls_packet_update(struct TLSPacket *packet) { gcm_reset(&packet->context->crypto.ctx_local.aes_gcm_local); gcm_add_iv(&packet->context->crypto.ctx_local.aes_gcm_local, iv, 12); - gcm_add_aad(&packet->context->crypto.ctx_local.aes_gcm_local, aad, aad_size); + gcm_add_aad(&packet->context->crypto.ctx_local.aes_gcm_local, aad, aad_size); gcm_process(&packet->context->crypto.ctx_local.aes_gcm_local, packet->buf + header_size, pt_length, ct + ct_pos, GCM_ENCRYPT); ct_pos += pt_length; - + unsigned long taglen = TLS_GCM_TAG_LEN; gcm_done(&packet->context->crypto.ctx_local.aes_gcm_local, ct + ct_pos, &taglen); ct_pos += taglen; @@ -39554,12 +39554,12 @@ void tls_packet_update(struct TLSPacket *packet) { int tls_packet_append(struct TLSPacket *packet, const unsigned char *buf, unsigned int len) { if ((!packet) || (packet->broken)) return -1; - + if (!len) return 0; - + unsigned int new_len = packet->len + len; - + if (new_len > packet->size) { packet->size = (new_len / TLS_BLOB_INCREMENT + 1) * TLS_BLOB_INCREMENT; packet->buf = (unsigned char *)TLS_REALLOC(packet->buf, packet->size); @@ -39596,7 +39596,7 @@ int tls_packet_uint24(struct TLSPacket *packet, unsigned int i) { buf[1] = i / 0x100; i %= 0x100; buf[2] = i; - + return tls_packet_append(packet, buf, 3); } @@ -39655,7 +39655,7 @@ void _private_tls_destroy_hash(struct TLSContext *context) { void _private_tls_create_hash(struct TLSContext *context) { if (!context) return; - + TLSHash *hash = _private_tls_ensure_hash(context); if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) { int hash_size = _private_tls_mac_length(context); @@ -39746,11 +39746,11 @@ int _private_tls_change_hash_type(struct TLSContext *context) { int _private_tls_done_hash(struct TLSContext *context, unsigned char *hout) { if (!context) return 0; - + TLSHash *hash = _private_tls_ensure_hash(context); if (!hash->created) return 0; - + int hash_size = 0; if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) { unsigned char temp[TLS_MAX_SHA_SIZE]; @@ -39804,11 +39804,11 @@ int _private_tls_get_hash_idx(struct TLSContext *context) { int _private_tls_get_hash(struct TLSContext *context, unsigned char *hout) { if (!context) return 0; - + TLSHash *hash = _private_tls_ensure_hash(context); if (!hash->created) return 0; - + int hash_size = 0; if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) { hash_size = _private_tls_mac_length(context); @@ -39827,15 +39827,15 @@ int _private_tls_get_hash(struct TLSContext *context, unsigned char *hout) { #ifdef TLS_LEGACY_SUPPORT // TLS_V11 hash_state prec; - + memcpy(&prec, &hash->hash32, sizeof(hash_state)); md5_done(&hash->hash32, hout); memcpy(&hash->hash32, &prec, sizeof(hash_state)); - + memcpy(&prec, &hash->hash2, sizeof(hash_state)); sha1_done(&hash->hash2, hout + 16); memcpy(&hash->hash2, &prec, sizeof(hash_state)); - + hash_size = TLS_V11_HASH_SIZE; #endif } @@ -39848,7 +39848,7 @@ int _private_tls_write_packet(struct TLSPacket *packet) { struct TLSContext *context = packet->context; if (!context) return -1; - + if (context->tls_buffer) { int len = context->tls_buffer_len + packet->len; context->tls_buffer = (unsigned char *)TLS_REALLOC(context->tls_buffer, len); @@ -39876,7 +39876,7 @@ int _private_tls_write_app_data(struct TLSContext *context, const unsigned char return -1; if ((!buf) || (!buf_len)) return 0; - + int len = context->application_buffer_len + buf_len; context->application_buffer = (unsigned char *)TLS_REALLOC(context->application_buffer, len); if (!context->application_buffer) { @@ -39965,7 +39965,7 @@ int tls_established(struct TLSContext *context) { if (context) { if (context->critical_error) return -1; - + if (context->connection_status == 0xFF) return 1; @@ -39992,7 +39992,7 @@ int tls_read(struct TLSContext *context, unsigned char *buf, unsigned int size) if ((context->application_buffer) && (context->application_buffer_len)) { if (context->application_buffer_len < size) size = context->application_buffer_len; - + memcpy(buf, context->application_buffer, size); if (context->application_buffer_len == size) { TLS_FREE(context->application_buffer); @@ -40032,7 +40032,7 @@ const struct ECCCurveParameters *tls_set_curve(struct TLSContext *context, const struct TLSContext *tls_accept(struct TLSContext *context) { if ((!context) || (!context->is_server)) return NULL; - + struct TLSContext *child = (struct TLSContext *)TLS_MALLOC(sizeof(struct TLSContext)); if (child) { memset(child, 0, sizeof(struct TLSContext)); @@ -40093,13 +40093,13 @@ void _private_tls_ecc_dhe_create(struct TLSContext *context) { int tls_set_default_dhe_pg(struct TLSContext *context, const char *p_hex_str, const char *g_hex_str) { if ((!context) || (context->is_child) || (!context->is_server) || (!p_hex_str) || (!g_hex_str)) return 0; - + TLS_FREE(context->default_dhe_p); TLS_FREE(context->default_dhe_g); - + context->default_dhe_p = NULL; context->default_dhe_g = NULL; - + size_t p_len = strlen(p_hex_str); size_t g_len = strlen(g_hex_str); if ((p_len <= 0) || (g_len <= 0)) @@ -40110,10 +40110,10 @@ int tls_set_default_dhe_pg(struct TLSContext *context, const char *p_hex_str, co context->default_dhe_g = (char *)TLS_MALLOC(g_len + 1); if (!context->default_dhe_g) return 0; - + memcpy(context->default_dhe_p, p_hex_str, p_len); context->default_dhe_p[p_len] = 0; - + memcpy(context->default_dhe_g, g_hex_str, g_len); context->default_dhe_g[g_len] = 0; return 1; @@ -40613,10 +40613,10 @@ const char *tls_cipher_name(struct TLSContext *context) { #ifdef TLS_FORWARD_SECRECY int _private_tls_dh_export_Y(unsigned char *Ybuf, unsigned long *Ylen, DHKey *key) { unsigned long len; - + if ((Ybuf == NULL) || (Ylen == NULL) || (key == NULL)) return TLS_GENERIC_ERROR; - + len = mp_unsigned_bin_size(key->y); if (len > *Ylen) return TLS_GENERIC_ERROR; @@ -40628,37 +40628,37 @@ int _private_tls_dh_export_Y(unsigned char *Ybuf, unsigned long *Ylen, DHKey *ke int _private_tls_dh_export_pqY(unsigned char *pbuf, unsigned long *plen, unsigned char *gbuf, unsigned long *glen, unsigned char *Ybuf, unsigned long *Ylen, DHKey *key) { unsigned long len; int err; - + if ((pbuf == NULL) || (plen == NULL) || (gbuf == NULL) || (glen == NULL) || (Ybuf == NULL) || (Ylen == NULL) || (key == NULL)) return TLS_GENERIC_ERROR; - + len = mp_unsigned_bin_size(key->y); if (len > *Ylen) return TLS_GENERIC_ERROR; - + if ((err = mp_to_unsigned_bin(key->y, Ybuf)) != CRYPT_OK) return err; - + *Ylen = len; - + len = mp_unsigned_bin_size(key->p); if (len > *plen) return TLS_GENERIC_ERROR; - + if ((err = mp_to_unsigned_bin(key->p, pbuf)) != CRYPT_OK) return err; - + *plen = len; - + len = mp_unsigned_bin_size(key->g); if (len > *glen) return TLS_GENERIC_ERROR; - + if ((err = mp_to_unsigned_bin(key->g, gbuf)) != CRYPT_OK) return err; - + *glen = len; - + return 0; } @@ -40675,32 +40675,32 @@ int _private_tls_dh_make_key(int keysize, DHKey *key, const char *pbuf, const ch int err; if (!key) return TLS_GENERIC_ERROR; - + static prng_state prng; int wprng = find_prng("sprng"); if ((err = prng_is_valid(wprng)) != CRYPT_OK) return err; - + buf = (unsigned char *)TLS_MALLOC(keysize); if (!buf) return TLS_NO_MEMORY; - + if (rng_make_prng(keysize, wprng, &prng, NULL) != CRYPT_OK) { TLS_FREE(buf); return TLS_GENERIC_ERROR; } - + if (prng_descriptor[wprng].read(buf, keysize, &prng) != (unsigned long)keysize) { TLS_FREE(buf); return TLS_GENERIC_ERROR; } - + if ((err = mp_init_multi(&key->g, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) { TLS_FREE(buf); - + return TLS_GENERIC_ERROR; } - + if (gbuf_len <= 0) { if ((err = mp_read_radix(key->g, gbuf, 16)) != CRYPT_OK) { TLS_FREE(buf); @@ -40714,7 +40714,7 @@ int _private_tls_dh_make_key(int keysize, DHKey *key, const char *pbuf, const ch return TLS_GENERIC_ERROR; } } - + if (pbuf_len <= 0) { if ((err = mp_read_radix(key->p, pbuf, 16)) != CRYPT_OK) { TLS_FREE(buf); @@ -40728,19 +40728,19 @@ int _private_tls_dh_make_key(int keysize, DHKey *key, const char *pbuf, const ch return TLS_GENERIC_ERROR; } } - + if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) { TLS_FREE(buf); _private_tls_dh_clear_key(key); return TLS_GENERIC_ERROR; } - + if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { TLS_FREE(buf); _private_tls_dh_clear_key(key); return TLS_GENERIC_ERROR; } - + TLS_FREE(buf); return 0; } @@ -40773,7 +40773,7 @@ struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) { DEBUG_PRINT("CANNOT BUILD CLIENT KEY EXCHANGE MESSAGE FOR SERVERS\n"); return NULL; } - + struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 0); tls_packet_uint8(packet, 0x10); #ifdef TLS_FORWARD_SECRECY @@ -40786,7 +40786,7 @@ struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) { unsigned long dh_p_len = sizeof(dh_p); unsigned long dh_g_len = sizeof(dh_g); unsigned long dh_Ys_len = sizeof(dh_Ys); - + if (_private_tls_dh_export_pqY(dh_p, &dh_p_len, dh_g, &dh_g_len, dh_Ys, &dh_Ys_len, context->dhe)) { DEBUG_PRINT("ERROR EXPORTING DHE KEY %p\n", context->dhe); TLS_FREE(packet); @@ -40804,7 +40804,7 @@ struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) { if (context->ecc_dhe) { unsigned char out[TLS_MAX_RSA_KEY]; unsigned long out_len = TLS_MAX_RSA_KEY; - + if (ecc_ansi_x963_export(context->ecc_dhe, out, &out_len)) { DEBUG_PRINT("Error exporting ECC key\n"); TLS_FREE(packet); @@ -40818,7 +40818,7 @@ struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) { } tls_packet_uint8(packet, out_len); tls_packet_append(packet, out, out_len); - } + } #ifdef TLS_CURVE25519 else if ((context->curve == &x25519) && (context->client_secret)) { @@ -40861,7 +40861,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int DEBUG_PRINT("CANNOT BUILD SERVER KEY EXCHANGE MESSAGE FOR CLIENTS\n"); return NULL; } - + struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 0); tls_packet_uint8(packet, 0x0C); unsigned char dummy[3]; @@ -40873,7 +40873,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int if (method == KEA_dhe_rsa) { tls_init(); _private_tls_dhe_create(context); - + const char *default_dhe_p = context->default_dhe_p; const char *default_dhe_g = context->default_dhe_g; int key_size; @@ -40891,31 +40891,31 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int context->dhe = NULL; return NULL; } - + unsigned char dh_Ys[0xFFF]; unsigned char dh_p[0xFFF]; unsigned char dh_g[0xFFF]; unsigned long dh_p_len = sizeof(dh_p); unsigned long dh_g_len = sizeof(dh_g); unsigned long dh_Ys_len = sizeof(dh_Ys); - + if (_private_tls_dh_export_pqY(dh_p, &dh_p_len, dh_g, &dh_g_len, dh_Ys, &dh_Ys_len, context->dhe)) { DEBUG_PRINT("ERROR EXPORTING DHE KEY\n"); TLS_FREE(packet); return NULL; } - + DEBUG_PRINT("LEN: %lu (%lu, %lu)\n", dh_Ys_len, dh_p_len, dh_g_len); DEBUG_DUMP_HEX_LABEL("DHE PK", dh_Ys, dh_Ys_len); DEBUG_DUMP_HEX_LABEL("DHE P", dh_p, dh_p_len); DEBUG_DUMP_HEX_LABEL("DHE G", dh_g, dh_g_len); - + tls_packet_uint16(packet, dh_p_len); tls_packet_append(packet, dh_p, dh_p_len); - + tls_packet_uint16(packet, dh_g_len); tls_packet_append(packet, dh_g, dh_g_len); - + tls_packet_uint16(packet, dh_Ys_len); tls_packet_append(packet, dh_Ys, dh_Ys_len); //dh_p @@ -40930,9 +40930,9 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int tls_packet_uint16(packet, context->curve->iana); tls_init(); _private_tls_ecc_dhe_create(context); - + ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&context->curve->dp; - + if (ecc_make_key_ex(NULL, find_prng("sprng"), context->ecc_dhe, dp)) { TLS_FREE(context->ecc_dhe); context->ecc_dhe = NULL; @@ -40956,7 +40956,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int DEBUG_PRINT("Unsupported ephemeral method: %i\n", method); return NULL; } - + // signature unsigned int params_len = packet->len - start_len; unsigned int message_len = params_len + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE; @@ -40964,7 +40964,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int if (message) { unsigned char out[TLS_MAX_RSA_KEY]; unsigned long out_len = TLS_MAX_RSA_KEY; - + int hash_algorithm; if ((context->version != TLS_V13) && (context->version != DTLS_V13) && (context->version != TLS_V12) && (context->version != DTLS_V12)) { hash_algorithm = _md5_sha1; @@ -40973,7 +40973,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int hash_algorithm = sha256; else hash_algorithm = sha1; - + #ifdef TLS_ECDSA_SUPPORTED if (tls_is_ecdsa(context)) { if ((context->version == TLS_V13) || (context->version == DTLS_V13) || (context->version == TLS_V12) || (context->version == DTLS_V12)) @@ -40987,7 +40987,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int tls_packet_uint8(packet, rsa_sign); } } - + memcpy(message, context->remote_random, TLS_CLIENT_RANDOM_SIZE); memcpy(message + TLS_CLIENT_RANDOM_SIZE, context->local_random, TLS_SERVER_RANDOM_SIZE); memcpy(message + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE, packet->buf + start_len, params_len); @@ -41181,7 +41181,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad // fallback ... this should never happen if (!context->cipher) context->cipher = TLS_DHE_RSA_WITH_AES_128_CBC_SHA; - + tls_packet_uint16(packet, context->cipher); // no compression tls_packet_uint8(packet, 0); @@ -41191,7 +41191,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad #ifdef WITH_TLS_13 if ((context->version == TLS_V13) || (context->version == DTLS_V13)) { tls_packet_uint16(packet, extension_len); - } else + } else #endif { tls_packet_uint16(packet, 5 + extension_len); @@ -41369,7 +41369,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad int sni_len = 0; if (context->sni) sni_len = strlen(context->sni); - + #ifdef TLS_CLIENT_ECDHE extension_len += 12; #endif @@ -41386,7 +41386,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad } #endif tls_packet_uint16(packet, extension_len); - + if (sni_len) { // sni extension tls_packet_uint16(packet, 0x00); @@ -41498,9 +41498,9 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad tls_packet_uint16(packet, shared_key_short + 6); tls_packet_uint16(packet, shared_key_short + 4); - _private_tls_ecc_dhe_create(context); + _private_tls_ecc_dhe_create(context); ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&secp256r1.dp; - + if (ecc_make_key_ex(NULL, find_prng("sprng"), context->ecc_dhe, dp)) { TLS_FREE(context->ecc_dhe); context->ecc_dhe = NULL; @@ -41541,7 +41541,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad } } #endif - + if ((!packet->broken) && (packet->buf)) { int remaining = packet->len - start_len; int payload_pos = 6; @@ -41565,7 +41565,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad struct TLSPacket *tls_certificate_request(struct TLSContext *context) { if ((!context) || (!context->is_server)) return NULL; - + unsigned short packet_version = context->version; struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, packet_version, 0); if (packet) { @@ -41676,7 +41676,7 @@ int _private_dtls_build_cookie(struct TLSContext *context) { struct TLSPacket *tls_build_verify_request(struct TLSContext *context) { if ((!context->is_server) || (!context->dtls)) return NULL; - + if ((!context->dtls_cookie) || (!context->dtls_cookie_len)) { if (!_private_dtls_build_cookie(context)) return NULL; @@ -41923,7 +41923,7 @@ int _private_tls_parse_key_share(struct TLSContext *context, const unsigned char } out2 = (unsigned char *)TLS_MALLOC(key_size); out_size = key_size; - + int err = ecc_shared_secret(context->ecc_dhe, &client_key, out2, &out_size); ecc_free(&client_key); @@ -41982,7 +41982,7 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu DEBUG_PRINT("UNEXPECTED HELLO MESSAGE\n"); return TLS_UNEXPECTED_MESSAGE; } - + int res = 0; int downgraded = 0; int hello_min_size = context->dtls ? TLS_CLIENT_HELLO_MINSIZE + 8 : TLS_CLIENT_HELLO_MINSIZE; @@ -41998,11 +41998,11 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu res += 8; } CHECK_SIZE(bytes_to_follow, buf_len - res, TLS_NEED_MORE_DATA) - + CHECK_SIZE(2, buf_len - res, TLS_NEED_MORE_DATA) unsigned short version = ntohs(*(unsigned short *)&buf[res]); unsigned short cipher = 0; - + res += 2; VERSION_SUPPORTED(version, TLS_NOT_SAFE) DEBUG_PRINT("VERSION REQUIRED BY REMOTE %x, VERSION NOW %x\n", (int)version, (int)context->version); @@ -42027,7 +42027,7 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu #endif memcpy(context->remote_random, &buf[res], TLS_CLIENT_RANDOM_SIZE); res += TLS_CLIENT_RANDOM_SIZE; - + unsigned char session_len = buf[res++]; CHECK_SIZE(session_len, buf_len - res, TLS_NEED_MORE_DATA) if ((session_len) && (session_len <= TLS_MAX_SESSION_ID)) { @@ -42081,11 +42081,11 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu cipher_buffer = &buf[res]; res += cipher_len; - + CHECK_SIZE(1, buf_len - res, TLS_NEED_MORE_DATA) unsigned char compression_list_size = buf[res++]; CHECK_SIZE(compression_list_size, buf_len - res, TLS_NEED_MORE_DATA) - + // no compression support res += compression_list_size; } else { @@ -42108,15 +42108,15 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu return TLS_COMPRESSION_NOT_SUPPORTED; } } - + if (res > 0) { if (context->is_server) *write_packets = 2; if (context->connection_status != 4) context->connection_status = 1; } - - + + if (res > 2) res += 2; #ifdef WITH_TLS_13 @@ -42344,7 +42344,7 @@ int tls_parse_certificate(struct TLSContext *context, const unsigned char *buf, int res = 0; CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA) unsigned int size_of_all_certificates = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; - + if (size_of_all_certificates <= 4) return 3 + size_of_all_certificates; res += 3; @@ -42366,7 +42366,7 @@ int tls_parse_certificate(struct TLSContext *context, const unsigned char *buf, CHECK_SIZE(size_of_all_certificates, buf_len - res, TLS_NEED_MORE_DATA); int size = size_of_all_certificates; - + int idx = 0; int valid_certificate = 0; while (size > 0) { @@ -42391,7 +42391,7 @@ int tls_parse_certificate(struct TLSContext *context, const unsigned char *buf, break; } remaining -= certificate_size2; - + struct TLSCertificate *cert = asn1_parse(context, &buf[res2], certificate_size2, is_client); if (cert) { if (certificate_size2) { @@ -42476,7 +42476,7 @@ int _private_tls_parse_random(struct TLSContext *context, const unsigned char *b size = ntohs(*(unsigned short *)buf); res += 2; } - + CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA) unsigned int out_len = 0; unsigned char *random = NULL; @@ -42492,7 +42492,7 @@ int _private_tls_parse_random(struct TLSContext *context, const unsigned char *b default: random = _private_tls_decrypt_rsa(context, &buf[res], size, &out_len); } - + if ((random) && (out_len > 2)) { DEBUG_DUMP_HEX_LABEL("PRE MASTER KEY", random, out_len); TLS_FREE(context->premaster_key); @@ -42513,7 +42513,7 @@ int _private_tls_build_random(struct TLSPacket *packet) { int bytes = 48; if (!tls_random(rand_bytes, bytes)) return TLS_GENERIC_ERROR; - + // max supported version if (packet->context->is_server) *(unsigned short *)rand_bytes = htons(packet->context->version); @@ -42523,18 +42523,18 @@ int _private_tls_build_random(struct TLSPacket *packet) { else *(unsigned short *)rand_bytes = htons(TLS_V12); //DEBUG_DUMP_HEX_LABEL("PREMASTER KEY", rand_bytes, bytes); - + TLS_FREE(packet->context->premaster_key); packet->context->premaster_key = (unsigned char *)TLS_MALLOC(bytes); if (!packet->context->premaster_key) return TLS_NO_MEMORY; - + packet->context->premaster_key_len = bytes; memcpy(packet->context->premaster_key, rand_bytes, packet->context->premaster_key_len); - + unsigned int out_len; unsigned char *random = _private_tls_encrypt_rsa(packet->context, packet->context->premaster_key, packet->context->premaster_key_len, &out_len); - + _private_tls_compute_key(packet->context, bytes); if ((random) && (out_len > 2)) { tls_packet_uint24(packet, out_len + 2); @@ -42547,7 +42547,7 @@ int _private_tls_build_random(struct TLSPacket *packet) { TLS_FREE(random); if (res) return res; - + return out_len + 2; } @@ -42586,10 +42586,10 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha } const unsigned char *packet_ref = buf + res; CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA); - + if (!size) return res; - + unsigned char has_ds_params = 0; unsigned int key_size = 0; #ifdef TLS_FORWARD_SECRECY @@ -42662,14 +42662,14 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha return TLS_BROKEN_PACKET; res += dh_res; DEBUG_PRINT("\n"); - + DEBUG_PRINT(" dh_q: "); dh_res = _private_tls_parse_dh(&buf[res], buf_len - res, &dh_g, &dh_g_len); if (dh_res <= 0) return TLS_BROKEN_PACKET; res += dh_res; DEBUG_PRINT("\n"); - + DEBUG_PRINT(" dh_Ys: "); dh_res = _private_tls_parse_dh(&buf[res], buf_len - res, &dh_Ys, &dh_Ys_len); if (dh_res <= 0) @@ -42693,7 +42693,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha // check signature unsigned int message_len = packet_size + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE; unsigned char *message = (unsigned char *)TLS_MALLOC(message_len); - if (message) { + if (message) { memcpy(message, context->local_random, TLS_CLIENT_RANDOM_SIZE); memcpy(message + TLS_CLIENT_RANDOM_SIZE, context->remote_random, TLS_SERVER_RANDOM_SIZE); memcpy(message + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE, packet_ref, packet_size); @@ -42704,7 +42704,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha TLS_FREE(message); return TLS_BROKEN_PACKET; } - } else + } else #endif { if (_private_tls_verify_rsa(context, hash_algorithm, signature, sign_size, message, message_len) != 1) { @@ -42715,7 +42715,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha } TLS_FREE(message); } - + if (buf_len - res) { DEBUG_PRINT("EXTRA %i BYTES AT THE END OF MESSAGE\n", buf_len - res); DEBUG_DUMP_HEX(&buf[res], buf_len - res); @@ -42735,7 +42735,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha context->dhe = NULL; return TLS_GENERIC_ERROR; } - + unsigned int dh_key_size = 0; unsigned char *key = _private_tls_decrypt_dhe(context, dh_Ys, dh_Ys_len, &dh_key_size, 0); DEBUG_DUMP_HEX_LABEL("DH COMMON SECRET", key, dh_key_size); @@ -42759,7 +42759,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha DEBUG_PRINT("ERROR IN TLS_MALLOC"); return TLS_GENERIC_ERROR; } - + tls_random(context->client_secret, 32); context->client_secret[0] &= 248; @@ -42778,7 +42778,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha { tls_init(); _private_tls_ecc_dhe_create(context); - + ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&curve->dp; if (ecc_make_key_ex(NULL, find_prng("sprng"), context->ecc_dhe, dp)) { TLS_FREE(context->ecc_dhe); @@ -42786,10 +42786,10 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha DEBUG_PRINT("Error generating ECC key\n"); return TLS_GENERIC_ERROR; } - + TLS_FREE(context->premaster_key); context->premaster_key_len = 0; - + unsigned int out_len = 0; context->premaster_key = _private_tls_decrypt_ecc_dhe(context, pk_key, key_size, &out_len, 0); if (context->premaster_key) @@ -42809,7 +42809,7 @@ int tls_parse_client_key_exchange(struct TLSContext *context, const unsigned cha int res = 0; int dh_res = 0; CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA) - + unsigned int size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; res += 3; if (context->dtls) { @@ -42823,14 +42823,14 @@ int tls_parse_client_key_exchange(struct TLSContext *context, const unsigned cha if (!size) return res; - + dh_res = _private_tls_parse_random(context, &buf[res], size); if (dh_res <= 0) { DEBUG_PRINT("broken key\n"); return TLS_BROKEN_PACKET; } DEBUG_PRINT("\n"); - + res += size; context->connection_status = 2; return res; @@ -42839,7 +42839,7 @@ int tls_parse_client_key_exchange(struct TLSContext *context, const unsigned cha int tls_parse_server_hello_done(struct TLSContext *context, const unsigned char *buf, int buf_len) { int res = 0; CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA) - + unsigned int size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; res += 3; if (context->dtls) { @@ -42848,9 +42848,9 @@ int tls_parse_server_hello_done(struct TLSContext *context, const unsigned char return dtls_check; res += 8; } - + CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA); - + res += size; return res; } @@ -42860,11 +42860,11 @@ int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int DEBUG_PRINT("UNEXPECTED FINISHED MESSAGE\n"); return TLS_UNEXPECTED_MESSAGE; } - + int res = 0; *write_packets = 0; CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA) - + unsigned int size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; res += 3; if (context->dtls) { @@ -42873,14 +42873,14 @@ int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int return dtls_check; res += 8; } - + if (size < TLS_MIN_FINISHED_OPAQUE_LEN) { DEBUG_PRINT("Invalid finished pachet size: %i\n", size); return TLS_BROKEN_PACKET; } - + CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA); - + unsigned char hash[TLS_MAX_SHA_SIZE]; unsigned int hash_len = _private_tls_get_hash(context, hash); @@ -42926,13 +42926,13 @@ int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int DEBUG_PRINT("Error in TLS_MALLOC (%i bytes)\n", (int)size); return TLS_NO_MEMORY; } - + // server verifies client's message if (context->is_server) _private_tls_prf(context, out, size, context->master_key, context->master_key_len, (unsigned char *)"client finished", 15, hash, hash_len, NULL, 0); else _private_tls_prf(context, out, size, context->master_key, context->master_key_len, (unsigned char *)"server finished", 15, hash, hash_len, NULL, 0); - + if (memcmp(out, &buf[res], size)) { TLS_FREE(out); DEBUG_PRINT("Finished validation error (sequence number, local: %i, remote: %i)\n", (int)context->local_sequence_number, (int)context->remote_sequence_number); @@ -42974,7 +42974,7 @@ int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int int tls_parse_verify_tls13(struct TLSContext *context, const unsigned char *buf, int buf_len) { CHECK_SIZE(7, buf_len, TLS_NEED_MORE_DATA) unsigned int size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; - + if (size < 2) return buf_len; @@ -43047,7 +43047,7 @@ int tls_parse_verify(struct TLSContext *context, const unsigned char *buf, int b CHECK_SIZE(size, bytes_to_follow - 4, TLS_BAD_CERTIFICATE) DEBUG_PRINT("ALGORITHM %i/%i (%i)\n", hash, algorithm, (int)size); DEBUG_DUMP_HEX_LABEL("VERIFY", &buf[7], bytes_to_follow - 7); - + res = _private_tls_verify_rsa(context, hash, &buf[7], size, context->cached_handshake, context->cached_handshake_len); } else { #ifdef TLS_LEGACY_SUPPORT @@ -43280,12 +43280,12 @@ int tls_parse_payload(struct TLSContext *context, const unsigned char *buf, int } if ((type != 0x00) && (update_hash)) _private_tls_update_hash(context, buf, payload_size + 1); - + if (certificate_verify_alert != no_error) { _private_tls_write_packet(tls_build_alert(context, 1, certificate_verify_alert)); context->critical_error = 1; } - + if (payload_res < 0) { switch (payload_res) { case TLS_UNEXPECTED_MESSAGE: @@ -43333,7 +43333,7 @@ int tls_parse_payload(struct TLSContext *context, const unsigned char *buf, int } if (certificate_verify_alert != no_error) payload_res = TLS_BAD_CERTIFICATE; - + // except renegotiation switch (write_packets) { case 1: @@ -43461,7 +43461,7 @@ unsigned int _private_tls_hmac_message(unsigned char local, struct TLSContext *c hash_idx = find_hash("sha384"); else hash_idx = find_hash("sha256"); - + if (hmac_init(&hash, hash_idx, local ? context->crypto.ctx_local_mac.local_mac : context->crypto.ctx_remote_mac.remote_mac, mac_size)) return 0; @@ -43476,7 +43476,7 @@ unsigned int _private_tls_hmac_message(unsigned char local, struct TLSContext *c if (hmac_process(&hash, (unsigned char *)&squence_number, sizeof(uint64_t))) return 0; - + if (hmac_process(&hash, buf, buf_len)) return 0; if ((buf2) && (buf_len2)) { @@ -43486,7 +43486,7 @@ unsigned int _private_tls_hmac_message(unsigned char local, struct TLSContext *c unsigned long ref_outlen = outlen; if (hmac_done(&hash, out, &ref_outlen)) return 0; - + return (unsigned int)ref_outlen; } @@ -43496,9 +43496,9 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le res = 13; int header_size = res; int payload_res = 0; - + CHECK_SIZE(res, buf_len, TLS_NEED_MORE_DATA) - + unsigned char type = *buf; int buf_pos = 1; @@ -43593,7 +43593,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le } DEBUG_DUMP_HEX_LABEL("aad", aad, aad_size); DEBUG_DUMP_HEX_LABEL("aad iv", iv, 12); - + int res0 = gcm_add_iv(&context->crypto.ctx_remote.aes_gcm_remote, iv, 12); int res1 = gcm_add_aad(&context->crypto.ctx_remote.aes_gcm_remote, aad, aad_size); memset(pt, 0, length); @@ -43684,7 +43684,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le rem = pt_length % 16; if (rem) _private_tls_poly1305_update(&ctx, zeropad, 16 - rem); - + _private_tls_U32TO8(&trail[0], aad_size == 5 ? 5 : 13); *(int *)&trail[4] = 0; _private_tls_U32TO8(&trail[8], pt_length); @@ -43717,7 +43717,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le } unsigned char padding_byte = pt[length - 1]; unsigned char padding = padding_byte + 1; - + // poodle check int padding_index = length - padding; if (padding_index > 0) { @@ -43733,11 +43733,11 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le } } } - + unsigned int decrypted_length = length; if (padding < decrypted_length) decrypted_length -= padding; - + DEBUG_DUMP_HEX_LABEL("decrypted", pt, decrypted_length); ptr = pt; #ifdef TLS_LEGACY_SUPPORT @@ -43752,7 +43752,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le } #endif length = decrypted_length; - + unsigned int mac_size = _private_tls_mac_length(context); if ((length < mac_size) || (!mac_size)) { TLS_FREE(pt); @@ -43761,9 +43761,9 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le _private_tls_write_packet(tls_build_alert(context, 1, decrypt_error)); return TLS_BROKEN_PACKET; } - + length -= mac_size; - + const unsigned char *message_hmac = &ptr[length]; unsigned char hmac_out[TLS_MAX_MAC_SIZE]; unsigned char temp_buf[5]; @@ -43861,22 +43861,22 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le return TLS_NOT_UNDERSTOOD; } TLS_FREE(pt); - + if (payload_res < 0) return payload_res; - + if (res > 0) return header_size + length; - + return res; } unsigned int asn1_get_len(const unsigned char *buffer, int buf_len, unsigned int *octets) { *octets = 0; - + if (buf_len < 1) return 0; - + unsigned char size = buffer[0]; int i; if (size & 0x80) { @@ -43891,7 +43891,7 @@ unsigned int asn1_get_len(const unsigned char *buffer, int buf_len, unsigned int return 0; unsigned int long_size = 0; unsigned int coef = 1; - + for (i = ref_octets; i > 0; i--) { long_size += buffer[i] * coef; coef *= 0x100; @@ -43956,7 +43956,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(16); if (!hash) return NULL; - + err = md5_init(&state); if (!err) { err = md5_process(&state, message, message_len); @@ -43969,7 +43969,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(20); if (!hash) return NULL; - + err = sha1_init(&state); if (!err) { err = sha1_process(&state, message, message_len); @@ -43983,7 +43983,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(32); if (!hash) return NULL; - + err = sha256_init(&state); if (!err) { err = sha256_process(&state, message, message_len); @@ -43996,7 +43996,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(48); if (!hash) return NULL; - + err = sha384_init(&state); if (!err) { err = sha384_process(&state, message, message_len); @@ -44009,7 +44009,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(64); if (!hash) return NULL; - + err = sha512_init(&state); if (!err) { err = sha512_process(&state, message, message_len); @@ -44032,7 +44032,7 @@ int tls_certificate_verify_signature(struct TLSCertificate *cert, struct TLSCert int hash_len = _private_tls_hash_len(cert->algorithm); if (hash_len <= 0) return 0; - + int hash_index = -1; switch (cert->algorithm) { case TLS_RSA_SIGN_MD5: @@ -44081,7 +44081,7 @@ int tls_certificate_verify_signature(struct TLSCertificate *cert, struct TLSCert return ecc_stat; } #endif - + rsa_key key; int err = rsa_import(parent->der_bytes, parent->der_len, &key); if (err) { @@ -44109,14 +44109,14 @@ int tls_certificate_verify_signature(struct TLSCertificate *cert, struct TLSCert int tls_certificate_chain_is_valid(struct TLSCertificate **certificates, int len) { if ((!certificates) || (!len)) return bad_certificate; - + int i; len--; - + // expired certificate or not yet valid ? if (tls_certificate_is_valid(certificates[0])) return bad_certificate; - + // check for (i = 0; i < len; i++) { // certificate in chain is expired ? @@ -44199,7 +44199,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, for (i1 = 1; i1 < level; i1++) DEBUG_PRINT(" "); #endif - + if ((length) && (constructed)) { switch (type) { case 0x03: @@ -44263,7 +44263,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, if (_is_field(fields, pk_id)) { if (has_key) *has_key = 1; - + if (idx == 1) tls_certificate_set_key(cert, &buffer[pos], length); else @@ -44308,7 +44308,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, case 0x03: if (_is_field(fields, pk_id)) { if (has_key) - *has_key = 1; + *has_key = 1; } // bitstream DEBUG_PRINT("BITSTREAM(%i): ", length); @@ -44370,7 +44370,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, } if (_is_field(fields, algorithm_id)) tls_certificate_set_algorithm(context, &cert->algorithm, &buffer[pos], length); - + DEBUG_PRINT("OBJECT IDENTIFIER(%i): ", length); DEBUG_DUMP_HEX(&buffer[pos], length); DEBUG_PRINT("\n"); @@ -44395,7 +44395,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, DEBUG_PRINT("UTC TIME: ["); DEBUG_DUMP(&buffer[pos], length); DEBUG_PRINT("]\n"); - + if (_is_field(fields, validity_id)) { if (idx == 1) tls_certificate_set_copy_date(&cert->not_before, &buffer[pos], length); @@ -44505,7 +44505,7 @@ struct TLSCertificate *asn1_parse(struct TLSContext *context, const unsigned cha int tls_load_certificates(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size) { if (!context) return TLS_GENERIC_ERROR; - + unsigned int len; int idx = 0; do { @@ -44514,7 +44514,7 @@ int tls_load_certificates(struct TLSContext *context, const unsigned char *pem_b break; struct TLSCertificate *cert = asn1_parse(context, data, len, 0); if (cert) { - if ((cert->version == 2) + if ((cert->version == 2) #ifdef TLS_X509_V1_SUPPORT || (cert->version == 0) #endif @@ -44553,7 +44553,7 @@ int tls_load_certificates(struct TLSContext *context, const unsigned char *pem_b int tls_load_private_key(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size) { if (!context) return TLS_GENERIC_ERROR; - + unsigned int len; int idx = 0; do { @@ -44844,7 +44844,7 @@ struct TLSPacket *tls_build_finished(struct TLSContext *context) { unsigned char out[TLS_MIN_FINISHED_OPAQUE_LEN]; #endif unsigned int hash_len; - + // server verifies client's message if (context->is_server) { #ifdef WITH_TLS_13 @@ -44959,7 +44959,7 @@ struct TLSPacket *tls_build_message(struct TLSContext *context, const unsigned c int tls_client_connect(struct TLSContext *context) { if ((context->is_server) || (context->critical_error)) return TLS_UNEXPECTED_MESSAGE; - + return _private_tls_write_packet(tls_build_hello(context, 0)); } @@ -45030,7 +45030,7 @@ int tls_consume_stream(struct TLSContext *context, const unsigned char *buf, int unsigned int index = 0; unsigned int tls_buffer_len = context->message_buffer_len; int err_flag = 0; - + int tls_header_size; int tls_size_offset; @@ -45123,7 +45123,7 @@ int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsign DEBUG_PRINT("CANNOT EXPORT CONTEXT %i\n", (int)context->connection_status); return 0; } - + struct TLSPacket *packet = tls_create_packet(NULL, TLS_SERIALIZED_OBJECT, context->version, 0); // export buffer version tls_packet_uint8(packet, 0x01); @@ -45133,7 +45133,7 @@ int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsign tls_packet_uint8(packet, 2); else tls_packet_uint8(packet, context->is_server); - + if (context->crypto.created == 2) { // aead #ifdef WITH_TLS_13 @@ -45160,20 +45160,20 @@ int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsign } else { unsigned char iv[TLS_AES_IV_LENGTH]; unsigned long len = TLS_AES_IV_LENGTH; - + memset(iv, 0, TLS_AES_IV_LENGTH); cbc_getiv(iv, &len, &context->crypto.ctx_local.aes_local); tls_packet_uint8(packet, TLS_AES_IV_LENGTH); tls_packet_append(packet, iv, len); - + memset(iv, 0, TLS_AES_IV_LENGTH); cbc_getiv(iv, &len, &context->crypto.ctx_remote.aes_remote); tls_packet_append(packet, iv, TLS_AES_IV_LENGTH); } - + tls_packet_uint8(packet, context->exportable_size); tls_packet_append(packet, context->exportable_keys, context->exportable_size); - + if (context->crypto.created == 2) { tls_packet_uint8(packet, 0); #ifdef TLS_WITH_CHACHA20_POLY1305 @@ -45195,25 +45195,25 @@ int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsign tls_packet_append(packet, context->crypto.ctx_local_mac.local_mac, mac_length); tls_packet_append(packet, context->crypto.ctx_remote_mac.remote_mac, mac_length); } - + if (small_version) { tls_packet_uint16(packet, 0); } else { tls_packet_uint16(packet, context->master_key_len); tls_packet_append(packet, context->master_key, context->master_key_len); } - + uint64_t sequence_number = htonll(context->local_sequence_number); tls_packet_append(packet, (unsigned char *)&sequence_number, sizeof(uint64_t)); sequence_number = htonll(context->remote_sequence_number); tls_packet_append(packet, (unsigned char *)&sequence_number, sizeof(uint64_t)); - + tls_packet_uint32(packet, context->tls_buffer_len); tls_packet_append(packet, context->tls_buffer, context->tls_buffer_len); - + tls_packet_uint32(packet, context->message_buffer_len); tls_packet_append(packet, context->message_buffer, context->message_buffer_len); - + tls_packet_uint32(packet, context->application_buffer_len); tls_packet_append(packet, context->application_buffer, context->application_buffer_len); tls_packet_uint8(packet, context->dtls); @@ -45259,7 +45259,7 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int context->is_child = 1; } else context->is_server = server; - + unsigned char local_iv[TLS_AES_IV_LENGTH]; unsigned char remote_iv[TLS_AES_IV_LENGTH]; unsigned char iv_len = buffer[10]; @@ -45268,14 +45268,14 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int tls_destroy_context(context); return NULL; } - + // get the initialization vectors int buf_pos = 11; memcpy(local_iv, &buffer[buf_pos], iv_len); buf_pos += iv_len; memcpy(remote_iv, &buffer[buf_pos], iv_len); buf_pos += iv_len; - + unsigned char key_lengths = buffer[buf_pos++]; TLS_IMPORT_CHECK_SIZE(buf_pos, key_lengths, buf_len) memcpy(temp, &buffer[buf_pos], key_lengths); @@ -45329,19 +45329,19 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int } } memset(temp, 0, sizeof(temp)); - + unsigned char mac_length = buffer[buf_pos++]; if (mac_length > TLS_MAX_MAC_SIZE) { DEBUG_PRINT("INVALID MAC SIZE\n"); tls_destroy_context(context); return NULL; } - + if (mac_length) { TLS_IMPORT_CHECK_SIZE(buf_pos, mac_length, buf_len) memcpy(context->crypto.ctx_local_mac.local_mac, &buffer[buf_pos], mac_length); buf_pos += mac_length; - + TLS_IMPORT_CHECK_SIZE(buf_pos, mac_length, buf_len) memcpy(context->crypto.ctx_remote_mac.remote_mac, &buffer[buf_pos], mac_length); buf_pos += mac_length; @@ -45365,7 +45365,7 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int buf_pos += CHACHA_BLOCKLEN; } #endif - + TLS_IMPORT_CHECK_SIZE(buf_pos, 2, buf_len) unsigned short master_key_len = ntohs(*(unsigned short *)(buffer + buf_pos)); buf_pos += 2; @@ -45378,14 +45378,14 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int } buf_pos += master_key_len; } - + TLS_IMPORT_CHECK_SIZE(buf_pos, 16, buf_len) - + context->local_sequence_number = ntohll(*(uint64_t *)&buffer[buf_pos]); buf_pos += 8; context->remote_sequence_number = ntohll(*(uint64_t *)&buffer[buf_pos]); buf_pos += 8; - + TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len) unsigned int tls_buffer_len = ntohl(*(unsigned int *)&buffer[buf_pos]); buf_pos += 4; @@ -45398,7 +45398,7 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int } buf_pos += tls_buffer_len; } - + TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len) unsigned int message_buffer_len = ntohl(*(unsigned int *)&buffer[buf_pos]); buf_pos += 4; @@ -45411,7 +45411,7 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int } buf_pos += message_buffer_len; } - + TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len) unsigned int application_buffer_len = ntohl(*(unsigned int *)&buffer[buf_pos]); buf_pos += 4; @@ -45447,7 +45447,7 @@ int tls_is_broken(struct TLSContext *context) { int tls_request_client_certificate(struct TLSContext *context) { if ((!context) || (!context->is_server)) return 0; - + context->request_client_certificate = 1; return 1; } @@ -45455,7 +45455,7 @@ int tls_request_client_certificate(struct TLSContext *context) { int tls_client_verified(struct TLSContext *context) { if ((!context) || (context->critical_error)) return 0; - + return (context->client_verified == 1); } @@ -45487,17 +45487,17 @@ int tls_sni_set(struct TLSContext *context, const char *sni) { int tls_load_root_certificates(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size) { if (!context) return TLS_GENERIC_ERROR; - + unsigned int len; int idx = 0; - + do { unsigned char *data = tls_pem_decode(pem_buffer, pem_size, idx++, &len); if ((!data) || (!len)) break; struct TLSCertificate *cert = asn1_parse(NULL, data, len, 0); if (cert) { - if ((cert->version == 2) + if ((cert->version == 2) #ifdef TLS_X509_V1_SUPPORT || (cert->version == 0) #endif @@ -45529,7 +45529,7 @@ int tls_load_root_certificates(struct TLSContext *context, const unsigned char * int tls_default_verify(struct TLSContext *context, struct TLSCertificate **certificate_chain, int len) { int i; int err; - + if (certificate_chain) { for (i = 0; i < len; i++) { struct TLSCertificate *certificate = certificate_chain[i]; @@ -45543,18 +45543,18 @@ int tls_default_verify(struct TLSContext *context, struct TLSCertificate **certi err = tls_certificate_chain_is_valid(certificate_chain, len); if (err) return err; - + // check certificate subject if ((!context->is_server) && (context->sni) && (len > 0) && (certificate_chain)) { err = tls_certificate_valid_subject(certificate_chain[0], context->sni); if (err) return err; } - + err = tls_certificate_chain_is_valid_root(context, certificate_chain, len); if (err) return err; - + DEBUG_PRINT("Certificate OK\n"); return no_error; } @@ -45803,7 +45803,7 @@ int SSL_CTX_use_PrivateKey_file(struct TLSContext *context, const char *filename int size = _private_tls_read_from_file(filename, buf, sizeof(buf)); if (size > 0) return tls_load_private_key(context, buf, size); - + return size; } @@ -45879,14 +45879,14 @@ void *SSL_userdata(struct TLSContext *context) { SSLUserData *ssl_data = (SSLUserData *)context->user_data; if (!ssl_data) return NULL; - + return ssl_data->user_data; } int SSL_CTX_root_ca(struct TLSContext *context, const char *pem_filename) { if (!context) return TLS_GENERIC_ERROR; - + int count = TLS_GENERIC_ERROR; FILE *f = fopen(pem_filename, "rb"); if (f) { @@ -45987,7 +45987,7 @@ int SSL_connect(struct TLSContext *context) { res = _tls_ssl_private_send_pending(ssl_data->fd, context); if (res < 0) return res; - + int read_size; unsigned char client_message[0xFFFF]; @@ -46011,7 +46011,7 @@ int SSL_shutdown(struct TLSContext *context) { SSLUserData *ssl_data = (SSLUserData *)context->user_data; if ((!ssl_data) || (ssl_data->fd < 0)) return TLS_GENERIC_ERROR; - + tls_close_notify(context); return 0; } @@ -46022,7 +46022,7 @@ int SSL_write(struct TLSContext *context, const void *buf, unsigned int len) { SSLUserData *ssl_data = (SSLUserData *)context->user_data; if ((!ssl_data) || (ssl_data->fd < 0)) return TLS_GENERIC_ERROR; - + int written_size = tls_write(context, (const unsigned char *)buf, len); if (written_size > 0) { int res = _tls_ssl_private_send_pending(ssl_data->fd, context); @@ -46035,7 +46035,7 @@ int SSL_write(struct TLSContext *context, const void *buf, unsigned int len) { int SSL_read(struct TLSContext *context, void *buf, unsigned int len) { if (!context) return TLS_GENERIC_ERROR; - + if (context->application_buffer_len) return tls_read(context, (unsigned char *)buf, len); @@ -46044,7 +46044,7 @@ int SSL_read(struct TLSContext *context, void *buf, unsigned int len) { return TLS_GENERIC_ERROR; if (tls_established(context) != 1) return TLS_GENERIC_ERROR; - + unsigned char client_message[0xFFFF]; // accept int read_size; @@ -46057,7 +46057,7 @@ int SSL_read(struct TLSContext *context, void *buf, unsigned int len) { } if ((read_size <= 0) && (!context->application_buffer_len)) return read_size; - + return tls_read(context, (unsigned char *)buf, len); } diff --git a/engine/split/3rd_luadebugger.h b/engine/split/3rd_luadebugger.h new file mode 100644 index 0000000..d6c0eec --- /dev/null +++ b/engine/split/3rd_luadebugger.h @@ -0,0 +1,1478 @@ +/* + Copyright (c) 2023 Scott Lembcke and Howling Moon Software + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#include +#include +#include +#include + +//#include +//#include + +static const char DEBUGGER_SRC[] = { +/*000000*/ 0x2d,0x2d,0x5b,0x5b,0x0d,0x0a,0x09,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74, +/*000010*/ 0x20,0x28,0x63,0x29,0x20,0x32,0x30,0x32,0x33,0x20,0x53,0x63,0x6f,0x74,0x74,0x20, +/*000020*/ 0x4c,0x65,0x6d,0x62,0x63,0x6b,0x65,0x20,0x61,0x6e,0x64,0x20,0x48,0x6f,0x77,0x6c, +/*000030*/ 0x69,0x6e,0x67,0x20,0x4d,0x6f,0x6f,0x6e,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72, +/*000040*/ 0x65,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x50,0x65,0x72,0x6d,0x69,0x73,0x73,0x69,0x6f, +/*000050*/ 0x6e,0x20,0x69,0x73,0x20,0x68,0x65,0x72,0x65,0x62,0x79,0x20,0x67,0x72,0x61,0x6e, +/*000060*/ 0x74,0x65,0x64,0x2c,0x20,0x66,0x72,0x65,0x65,0x20,0x6f,0x66,0x20,0x63,0x68,0x61, +/*000070*/ 0x72,0x67,0x65,0x2c,0x20,0x74,0x6f,0x20,0x61,0x6e,0x79,0x20,0x70,0x65,0x72,0x73, +/*000080*/ 0x6f,0x6e,0x20,0x6f,0x62,0x74,0x61,0x69,0x6e,0x69,0x6e,0x67,0x20,0x61,0x20,0x63, +/*000090*/ 0x6f,0x70,0x79,0x0d,0x0a,0x09,0x6f,0x66,0x20,0x74,0x68,0x69,0x73,0x20,0x73,0x6f, +/*0000a0*/ 0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x61,0x6e,0x64,0x20,0x61,0x73,0x73,0x6f,0x63, +/*0000b0*/ 0x69,0x61,0x74,0x65,0x64,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x61,0x74, +/*0000c0*/ 0x69,0x6f,0x6e,0x20,0x66,0x69,0x6c,0x65,0x73,0x20,0x28,0x74,0x68,0x65,0x20,0x22, +/*0000d0*/ 0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x22,0x29,0x2c,0x20,0x74,0x6f,0x20,0x64, +/*0000e0*/ 0x65,0x61,0x6c,0x0d,0x0a,0x09,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x53,0x6f,0x66, +/*0000f0*/ 0x74,0x77,0x61,0x72,0x65,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x72,0x65, +/*000100*/ 0x73,0x74,0x72,0x69,0x63,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x69,0x6e,0x63,0x6c,0x75, +/*000110*/ 0x64,0x69,0x6e,0x67,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x6c,0x69,0x6d, +/*000120*/ 0x69,0x74,0x61,0x74,0x69,0x6f,0x6e,0x20,0x74,0x68,0x65,0x20,0x72,0x69,0x67,0x68, +/*000130*/ 0x74,0x73,0x0d,0x0a,0x09,0x74,0x6f,0x20,0x75,0x73,0x65,0x2c,0x20,0x63,0x6f,0x70, +/*000140*/ 0x79,0x2c,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x2c,0x20,0x6d,0x65,0x72,0x67,0x65, +/*000150*/ 0x2c,0x20,0x70,0x75,0x62,0x6c,0x69,0x73,0x68,0x2c,0x20,0x64,0x69,0x73,0x74,0x72, +/*000160*/ 0x69,0x62,0x75,0x74,0x65,0x2c,0x20,0x73,0x75,0x62,0x6c,0x69,0x63,0x65,0x6e,0x73, +/*000170*/ 0x65,0x2c,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x73,0x65,0x6c,0x6c,0x0d,0x0a, +/*000180*/ 0x09,0x63,0x6f,0x70,0x69,0x65,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x53, +/*000190*/ 0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x2c,0x20,0x61,0x6e,0x64,0x20,0x74,0x6f,0x20, +/*0001a0*/ 0x70,0x65,0x72,0x6d,0x69,0x74,0x20,0x70,0x65,0x72,0x73,0x6f,0x6e,0x73,0x20,0x74, +/*0001b0*/ 0x6f,0x20,0x77,0x68,0x6f,0x6d,0x20,0x74,0x68,0x65,0x20,0x53,0x6f,0x66,0x74,0x77, +/*0001c0*/ 0x61,0x72,0x65,0x20,0x69,0x73,0x0d,0x0a,0x09,0x66,0x75,0x72,0x6e,0x69,0x73,0x68, +/*0001d0*/ 0x65,0x64,0x20,0x74,0x6f,0x20,0x64,0x6f,0x20,0x73,0x6f,0x2c,0x20,0x73,0x75,0x62, +/*0001e0*/ 0x6a,0x65,0x63,0x74,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x66,0x6f,0x6c,0x6c, +/*0001f0*/ 0x6f,0x77,0x69,0x6e,0x67,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x73, +/*000200*/ 0x3a,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x54,0x68,0x65,0x20,0x61,0x62,0x6f,0x76,0x65, +/*000210*/ 0x20,0x63,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x6e,0x6f,0x74,0x69,0x63, +/*000220*/ 0x65,0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x65,0x72,0x6d,0x69, +/*000230*/ 0x73,0x73,0x69,0x6f,0x6e,0x20,0x6e,0x6f,0x74,0x69,0x63,0x65,0x20,0x73,0x68,0x61, +/*000240*/ 0x6c,0x6c,0x20,0x62,0x65,0x20,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x64,0x20,0x69, +/*000250*/ 0x6e,0x0d,0x0a,0x09,0x61,0x6c,0x6c,0x20,0x63,0x6f,0x70,0x69,0x65,0x73,0x20,0x6f, +/*000260*/ 0x72,0x20,0x73,0x75,0x62,0x73,0x74,0x61,0x6e,0x74,0x69,0x61,0x6c,0x20,0x70,0x6f, +/*000270*/ 0x72,0x74,0x69,0x6f,0x6e,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x53,0x6f, +/*000280*/ 0x66,0x74,0x77,0x61,0x72,0x65,0x2e,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x54,0x48,0x45, +/*000290*/ 0x20,0x53,0x4f,0x46,0x54,0x57,0x41,0x52,0x45,0x20,0x49,0x53,0x20,0x50,0x52,0x4f, +/*0002a0*/ 0x56,0x49,0x44,0x45,0x44,0x20,0x22,0x41,0x53,0x20,0x49,0x53,0x22,0x2c,0x20,0x57, +/*0002b0*/ 0x49,0x54,0x48,0x4f,0x55,0x54,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x59,0x20, +/*0002c0*/ 0x4f,0x46,0x20,0x41,0x4e,0x59,0x20,0x4b,0x49,0x4e,0x44,0x2c,0x20,0x45,0x58,0x50, +/*0002d0*/ 0x52,0x45,0x53,0x53,0x20,0x4f,0x52,0x0d,0x0a,0x09,0x49,0x4d,0x50,0x4c,0x49,0x45, +/*0002e0*/ 0x44,0x2c,0x20,0x49,0x4e,0x43,0x4c,0x55,0x44,0x49,0x4e,0x47,0x20,0x42,0x55,0x54, +/*0002f0*/ 0x20,0x4e,0x4f,0x54,0x20,0x4c,0x49,0x4d,0x49,0x54,0x45,0x44,0x20,0x54,0x4f,0x20, +/*000300*/ 0x54,0x48,0x45,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x49,0x45,0x53,0x20,0x4f, +/*000310*/ 0x46,0x20,0x4d,0x45,0x52,0x43,0x48,0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54, +/*000320*/ 0x59,0x2c,0x0d,0x0a,0x09,0x46,0x49,0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52, +/*000330*/ 0x20,0x41,0x20,0x50,0x41,0x52,0x54,0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55, +/*000340*/ 0x52,0x50,0x4f,0x53,0x45,0x20,0x41,0x4e,0x44,0x20,0x4e,0x4f,0x4e,0x49,0x4e,0x46, +/*000350*/ 0x52,0x49,0x4e,0x47,0x45,0x4d,0x45,0x4e,0x54,0x2e,0x20,0x49,0x4e,0x20,0x4e,0x4f, +/*000360*/ 0x20,0x45,0x56,0x45,0x4e,0x54,0x20,0x53,0x48,0x41,0x4c,0x4c,0x20,0x54,0x48,0x45, +/*000370*/ 0x0d,0x0a,0x09,0x41,0x55,0x54,0x48,0x4f,0x52,0x53,0x20,0x4f,0x52,0x20,0x43,0x4f, +/*000380*/ 0x50,0x59,0x52,0x49,0x47,0x48,0x54,0x20,0x48,0x4f,0x4c,0x44,0x45,0x52,0x53,0x20, +/*000390*/ 0x42,0x45,0x20,0x4c,0x49,0x41,0x42,0x4c,0x45,0x20,0x46,0x4f,0x52,0x20,0x41,0x4e, +/*0003a0*/ 0x59,0x20,0x43,0x4c,0x41,0x49,0x4d,0x2c,0x20,0x44,0x41,0x4d,0x41,0x47,0x45,0x53, +/*0003b0*/ 0x20,0x4f,0x52,0x20,0x4f,0x54,0x48,0x45,0x52,0x0d,0x0a,0x09,0x4c,0x49,0x41,0x42, +/*0003c0*/ 0x49,0x4c,0x49,0x54,0x59,0x2c,0x20,0x57,0x48,0x45,0x54,0x48,0x45,0x52,0x20,0x49, +/*0003d0*/ 0x4e,0x20,0x41,0x4e,0x20,0x41,0x43,0x54,0x49,0x4f,0x4e,0x20,0x4f,0x46,0x20,0x43, +/*0003e0*/ 0x4f,0x4e,0x54,0x52,0x41,0x43,0x54,0x2c,0x20,0x54,0x4f,0x52,0x54,0x20,0x4f,0x52, +/*0003f0*/ 0x20,0x4f,0x54,0x48,0x45,0x52,0x57,0x49,0x53,0x45,0x2c,0x20,0x41,0x52,0x49,0x53, +/*000400*/ 0x49,0x4e,0x47,0x20,0x46,0x52,0x4f,0x4d,0x2c,0x0d,0x0a,0x09,0x4f,0x55,0x54,0x20, +/*000410*/ 0x4f,0x46,0x20,0x4f,0x52,0x20,0x49,0x4e,0x20,0x43,0x4f,0x4e,0x4e,0x45,0x43,0x54, +/*000420*/ 0x49,0x4f,0x4e,0x20,0x57,0x49,0x54,0x48,0x20,0x54,0x48,0x45,0x20,0x53,0x4f,0x46, +/*000430*/ 0x54,0x57,0x41,0x52,0x45,0x20,0x4f,0x52,0x20,0x54,0x48,0x45,0x20,0x55,0x53,0x45, +/*000440*/ 0x20,0x4f,0x52,0x20,0x4f,0x54,0x48,0x45,0x52,0x20,0x44,0x45,0x41,0x4c,0x49,0x4e, +/*000450*/ 0x47,0x53,0x20,0x49,0x4e,0x20,0x54,0x48,0x45,0x0d,0x0a,0x09,0x53,0x4f,0x46,0x54, +/*000460*/ 0x57,0x41,0x52,0x45,0x2e,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x54,0x4f,0x44,0x4f,0x3a, +/*000470*/ 0x0d,0x0a,0x09,0x2a,0x20,0x50,0x72,0x69,0x6e,0x74,0x20,0x73,0x68,0x6f,0x72,0x74, +/*000480*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x61,0x72,0x67,0x75,0x6d,0x65, +/*000490*/ 0x6e,0x74,0x73,0x20,0x61,0x73,0x20,0x70,0x61,0x72,0x74,0x20,0x6f,0x66,0x20,0x73, +/*0004a0*/ 0x74,0x61,0x63,0x6b,0x20,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x0d,0x0a, +/*0004b0*/ 0x09,0x2a,0x20,0x50,0x72,0x6f,0x70,0x65,0x72,0x6c,0x79,0x20,0x68,0x61,0x6e,0x64, +/*0004c0*/ 0x6c,0x65,0x20,0x62,0x65,0x69,0x6e,0x67,0x20,0x72,0x65,0x65,0x6e,0x74,0x72,0x61, +/*0004d0*/ 0x6e,0x74,0x20,0x64,0x75,0x65,0x20,0x74,0x6f,0x20,0x63,0x6f,0x72,0x6f,0x75,0x74, +/*0004e0*/ 0x69,0x6e,0x65,0x73,0x2e,0x0d,0x0a,0x5d,0x5d,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63, +/*0004f0*/ 0x61,0x6c,0x20,0x64,0x62,0x67,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x55,0x73,0x65, +/*000500*/ 0x20,0x41,0x4e,0x53,0x49,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x63,0x6f,0x64,0x65, +/*000510*/ 0x73,0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6f,0x6d,0x70,0x74,0x20, +/*000520*/ 0x62,0x79,0x20,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x2e,0x0d,0x0a,0x6c,0x6f,0x63, +/*000530*/ 0x61,0x6c,0x20,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x47,0x52,0x41,0x59,0x20,0x3d,0x20, +/*000540*/ 0x22,0x22,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*000550*/ 0x52,0x45,0x44,0x20,0x3d,0x20,0x22,0x22,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*000560*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x20,0x3d,0x20,0x22,0x22,0x0d, +/*000570*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*000580*/ 0x4c,0x4f,0x57,0x20,0x3d,0x20,0x22,0x22,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*000590*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x20,0x3d,0x20,0x22,0x22, +/*0005a0*/ 0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41, +/*0005b0*/ 0x52,0x45,0x54,0x20,0x3d,0x20,0x22,0x20,0x3d,0x3e,0x20,0x22,0x0d,0x0a,0x0d,0x0a, +/*0005c0*/ 0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x70, +/*0005d0*/ 0x72,0x65,0x74,0x74,0x79,0x28,0x6f,0x62,0x6a,0x2c,0x20,0x6d,0x61,0x78,0x5f,0x64, +/*0005e0*/ 0x65,0x70,0x74,0x68,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20,0x6d,0x61,0x78,0x5f,0x64, +/*0005f0*/ 0x65,0x70,0x74,0x68,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x74,0x68,0x65,0x6e, +/*000600*/ 0x20,0x6d,0x61,0x78,0x5f,0x64,0x65,0x70,0x74,0x68,0x20,0x3d,0x20,0x64,0x62,0x67, +/*000610*/ 0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x5f,0x64,0x65,0x70,0x74,0x68,0x20,0x65,0x6e, +/*000620*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x75,0x72,0x6e, +/*000630*/ 0x73,0x20,0x74,0x72,0x75,0x65,0x20,0x69,0x66,0x20,0x61,0x20,0x74,0x61,0x62,0x6c, +/*000640*/ 0x65,0x20,0x68,0x61,0x73,0x20,0x61,0x20,0x5f,0x5f,0x74,0x6f,0x73,0x74,0x72,0x69, +/*000650*/ 0x6e,0x67,0x20,0x6d,0x65,0x74,0x61,0x6d,0x65,0x74,0x68,0x6f,0x64,0x2e,0x0d,0x0a, +/*000660*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*000670*/ 0x63,0x6f,0x65,0x72,0x63,0x65,0x61,0x62,0x6c,0x65,0x28,0x74,0x62,0x6c,0x29,0x0d, +/*000680*/ 0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6d,0x65,0x74,0x61,0x20,0x3d,0x20, +/*000690*/ 0x67,0x65,0x74,0x6d,0x65,0x74,0x61,0x74,0x61,0x62,0x6c,0x65,0x28,0x74,0x62,0x6c, +/*0006a0*/ 0x29,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x6d,0x65,0x74, +/*0006b0*/ 0x61,0x20,0x61,0x6e,0x64,0x20,0x6d,0x65,0x74,0x61,0x2e,0x5f,0x5f,0x74,0x6f,0x73, +/*0006c0*/ 0x74,0x72,0x69,0x6e,0x67,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d, +/*0006d0*/ 0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e, +/*0006e0*/ 0x20,0x72,0x65,0x63,0x75,0x72,0x73,0x65,0x28,0x6f,0x62,0x6a,0x2c,0x20,0x64,0x65, +/*0006f0*/ 0x70,0x74,0x68,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x74,0x79,0x70,0x65,0x28, +/*000700*/ 0x6f,0x62,0x6a,0x29,0x20,0x3d,0x3d,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22, +/*000710*/ 0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d,0x20,0x44,0x75,0x6d, +/*000720*/ 0x70,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x73,0x6f,0x20, +/*000730*/ 0x74,0x68,0x61,0x74,0x20,0x65,0x73,0x63,0x61,0x70,0x65,0x20,0x73,0x65,0x71,0x75, +/*000740*/ 0x65,0x6e,0x63,0x65,0x73,0x20,0x61,0x72,0x65,0x20,0x70,0x72,0x69,0x6e,0x74,0x65, +/*000750*/ 0x64,0x2e,0x0d,0x0a,0x09,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74, +/*000760*/ 0x72,0x69,0x6e,0x67,0x2e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x28,0x22,0x25,0x71,0x22, +/*000770*/ 0x2c,0x20,0x6f,0x62,0x6a,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6c,0x73,0x65,0x69,0x66, +/*000780*/ 0x20,0x74,0x79,0x70,0x65,0x28,0x6f,0x62,0x6a,0x29,0x20,0x3d,0x3d,0x20,0x22,0x74, +/*000790*/ 0x61,0x62,0x6c,0x65,0x22,0x20,0x61,0x6e,0x64,0x20,0x64,0x65,0x70,0x74,0x68,0x20, +/*0007a0*/ 0x3c,0x20,0x6d,0x61,0x78,0x5f,0x64,0x65,0x70,0x74,0x68,0x20,0x61,0x6e,0x64,0x20, +/*0007b0*/ 0x6e,0x6f,0x74,0x20,0x63,0x6f,0x65,0x72,0x63,0x65,0x61,0x62,0x6c,0x65,0x28,0x6f, +/*0007c0*/ 0x62,0x6a,0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63, +/*0007d0*/ 0x61,0x6c,0x20,0x73,0x74,0x72,0x20,0x3d,0x20,0x22,0x7b,0x22,0x0d,0x0a,0x09,0x09, +/*0007e0*/ 0x09,0x0d,0x0a,0x09,0x09,0x09,0x66,0x6f,0x72,0x20,0x6b,0x2c,0x20,0x76,0x20,0x69, +/*0007f0*/ 0x6e,0x20,0x70,0x61,0x69,0x72,0x73,0x28,0x6f,0x62,0x6a,0x29,0x20,0x64,0x6f,0x0d, +/*000800*/ 0x0a,0x09,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x70,0x61,0x69,0x72,0x20, +/*000810*/ 0x3d,0x20,0x70,0x72,0x65,0x74,0x74,0x79,0x28,0x6b,0x2c,0x20,0x30,0x29,0x2e,0x2e, +/*000820*/ 0x22,0x20,0x3d,0x20,0x22,0x2e,0x2e,0x72,0x65,0x63,0x75,0x72,0x73,0x65,0x28,0x76, +/*000830*/ 0x2c,0x20,0x64,0x65,0x70,0x74,0x68,0x20,0x2b,0x20,0x31,0x29,0x0d,0x0a,0x09,0x09, +/*000840*/ 0x09,0x09,0x73,0x74,0x72,0x20,0x3d,0x20,0x73,0x74,0x72,0x2e,0x2e,0x28,0x73,0x74, +/*000850*/ 0x72,0x20,0x3d,0x3d,0x20,0x22,0x7b,0x22,0x20,0x61,0x6e,0x64,0x20,0x70,0x61,0x69, +/*000860*/ 0x72,0x20,0x6f,0x72,0x20,0x22,0x2c,0x20,0x22,0x2e,0x2e,0x70,0x61,0x69,0x72,0x29, +/*000870*/ 0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x0d,0x0a,0x09, +/*000880*/ 0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x72,0x2e,0x2e,0x22,0x7d, +/*000890*/ 0x22,0x0d,0x0a,0x09,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d, +/*0008a0*/ 0x20,0x74,0x6f,0x73,0x74,0x72,0x69,0x6e,0x67,0x28,0x29,0x20,0x63,0x61,0x6e,0x20, +/*0008b0*/ 0x66,0x61,0x69,0x6c,0x20,0x69,0x66,0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x69,0x73, +/*0008c0*/ 0x20,0x61,0x6e,0x20,0x65,0x72,0x72,0x6f,0x72,0x20,0x69,0x6e,0x20,0x61,0x20,0x5f, +/*0008d0*/ 0x5f,0x74,0x6f,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x6d,0x65,0x74,0x61,0x6d,0x65, +/*0008e0*/ 0x74,0x68,0x6f,0x64,0x2e,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*0008f0*/ 0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x2c,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d, +/*000900*/ 0x20,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28, +/*000910*/ 0x29,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x6f,0x73,0x74,0x72,0x69,0x6e, +/*000920*/ 0x67,0x28,0x6f,0x62,0x6a,0x29,0x20,0x65,0x6e,0x64,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*000930*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x20, +/*000940*/ 0x61,0x6e,0x64,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x6f,0x72,0x20,0x22,0x3c,0x21, +/*000950*/ 0x21,0x65,0x72,0x72,0x6f,0x72,0x20,0x69,0x6e,0x20,0x5f,0x5f,0x74,0x6f,0x73,0x74, +/*000960*/ 0x72,0x69,0x6e,0x67,0x20,0x6d,0x65,0x74,0x61,0x6d,0x65,0x74,0x68,0x6f,0x64,0x21, +/*000970*/ 0x21,0x3e,0x22,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6e, +/*000980*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x72,0x65, +/*000990*/ 0x63,0x75,0x72,0x73,0x65,0x28,0x6f,0x62,0x6a,0x2c,0x20,0x30,0x29,0x0d,0x0a,0x65, +/*0009a0*/ 0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x54,0x68,0x65,0x20,0x73,0x74,0x61, +/*0009b0*/ 0x63,0x6b,0x20,0x6c,0x65,0x76,0x65,0x6c,0x20,0x74,0x68,0x61,0x74,0x20,0x63,0x6d, +/*0009c0*/ 0x64,0x5f,0x2a,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x20,0x75,0x73, +/*0009d0*/ 0x65,0x20,0x74,0x6f,0x20,0x61,0x63,0x63,0x65,0x73,0x73,0x20,0x6c,0x6f,0x63,0x61, +/*0009e0*/ 0x6c,0x73,0x20,0x6f,0x72,0x20,0x69,0x6e,0x66,0x6f,0x0d,0x0a,0x2d,0x2d,0x20,0x54, +/*0009f0*/ 0x68,0x65,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x75,0x72,0x65,0x20,0x6f,0x66,0x20, +/*000a00*/ 0x74,0x68,0x65,0x20,0x63,0x6f,0x64,0x65,0x20,0x76,0x65,0x72,0x79,0x20,0x63,0x61, +/*000a10*/ 0x72,0x65,0x66,0x75,0x6c,0x6c,0x79,0x20,0x65,0x6e,0x73,0x75,0x72,0x65,0x73,0x20, +/*000a20*/ 0x74,0x68,0x69,0x73,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x43,0x4d,0x44, +/*000a30*/ 0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x20,0x3d,0x20,0x36, +/*000a40*/ 0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20, +/*000a50*/ 0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x6f,0x70,0x20,0x6f,0x66,0x20,0x74,0x68, +/*000a60*/ 0x65,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x6f,0x75,0x74,0x73,0x69,0x64,0x65,0x20, +/*000a70*/ 0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x2e, +/*000a80*/ 0x0d,0x0a,0x2d,0x2d,0x20,0x41,0x64,0x6a,0x75,0x73,0x74,0x65,0x64,0x20,0x62,0x79, +/*000a90*/ 0x20,0x73,0x6f,0x6d,0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x20,0x65, +/*000aa0*/ 0x6e,0x74,0x72,0x79,0x70,0x6f,0x69,0x6e,0x74,0x73,0x2e,0x0d,0x0a,0x6c,0x6f,0x63, +/*000ab0*/ 0x61,0x6c,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x20,0x3d,0x20,0x30, +/*000ac0*/ 0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x54,0x68,0x65,0x20,0x63,0x75,0x72,0x72,0x65, +/*000ad0*/ 0x6e,0x74,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x66,0x72,0x61,0x6d,0x65,0x20,0x69, +/*000ae0*/ 0x6e,0x64,0x65,0x78,0x2e,0x0d,0x0a,0x2d,0x2d,0x20,0x43,0x68,0x61,0x6e,0x67,0x65, +/*000af0*/ 0x64,0x20,0x75,0x73,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x75,0x70,0x2f,0x64, +/*000b00*/ 0x6f,0x77,0x6e,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x73,0x0d,0x0a,0x6c,0x6f, +/*000b10*/ 0x63,0x61,0x6c,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63, +/*000b20*/ 0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x30,0x0d,0x0a,0x0d,0x0a, +/*000b30*/ 0x2d,0x2d,0x20,0x4c,0x75,0x61,0x4a,0x49,0x54,0x20,0x68,0x61,0x73,0x20,0x61,0x6e, +/*000b40*/ 0x20,0x6f,0x66,0x66,0x20,0x62,0x79,0x20,0x6f,0x6e,0x65,0x20,0x62,0x75,0x67,0x20, +/*000b50*/ 0x77,0x68,0x65,0x6e,0x20,0x73,0x65,0x74,0x74,0x69,0x6e,0x67,0x20,0x6c,0x6f,0x63, +/*000b60*/ 0x61,0x6c,0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x73,0x2e,0x0d,0x0a,0x6c, +/*000b70*/ 0x6f,0x63,0x61,0x6c,0x20,0x4c,0x55,0x41,0x5f,0x4a,0x49,0x54,0x5f,0x53,0x45,0x54, +/*000b80*/ 0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x57,0x4f,0x52,0x4b,0x41,0x52,0x4f,0x55,0x4e,0x44, +/*000b90*/ 0x20,0x3d,0x20,0x30,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x44,0x65,0x66,0x61,0x75, +/*000ba0*/ 0x6c,0x74,0x20,0x64,0x62,0x67,0x2e,0x72,0x65,0x61,0x64,0x20,0x66,0x75,0x6e,0x63, +/*000bb0*/ 0x74,0x69,0x6f,0x6e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63, +/*000bc0*/ 0x74,0x69,0x6f,0x6e,0x20,0x64,0x62,0x67,0x5f,0x72,0x65,0x61,0x64,0x28,0x70,0x72, +/*000bd0*/ 0x6f,0x6d,0x70,0x74,0x29,0x0d,0x0a,0x09,0x64,0x62,0x67,0x2e,0x77,0x72,0x69,0x74, +/*000be0*/ 0x65,0x28,0x70,0x72,0x6f,0x6d,0x70,0x74,0x29,0x0d,0x0a,0x09,0x69,0x6f,0x2e,0x66, +/*000bf0*/ 0x6c,0x75,0x73,0x68,0x28,0x29,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*000c00*/ 0x69,0x6f,0x2e,0x72,0x65,0x61,0x64,0x28,0x29,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a, +/*000c10*/ 0x0d,0x0a,0x2d,0x2d,0x20,0x44,0x65,0x66,0x61,0x75,0x6c,0x74,0x20,0x64,0x62,0x67, +/*000c20*/ 0x2e,0x77,0x72,0x69,0x74,0x65,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x0d, +/*000c30*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*000c40*/ 0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x74,0x72,0x29,0x0d,0x0a, +/*000c50*/ 0x09,0x69,0x6f,0x2e,0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x74,0x72,0x29,0x0d,0x0a, +/*000c60*/ 0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e, +/*000c70*/ 0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c, +/*000c80*/ 0x6e,0x28,0x73,0x74,0x72,0x2c,0x20,0x2e,0x2e,0x2e,0x29,0x0d,0x0a,0x09,0x69,0x66, +/*000c90*/ 0x20,0x73,0x65,0x6c,0x65,0x63,0x74,0x28,0x22,0x23,0x22,0x2c,0x20,0x2e,0x2e,0x2e, +/*000ca0*/ 0x29,0x20,0x3d,0x3d,0x20,0x30,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x64, +/*000cb0*/ 0x62,0x67,0x2e,0x77,0x72,0x69,0x74,0x65,0x28,0x28,0x73,0x74,0x72,0x20,0x6f,0x72, +/*000cc0*/ 0x20,0x22,0x3c,0x4e,0x55,0x4c,0x4c,0x3e,0x22,0x29,0x2e,0x2e,0x22,0x5c,0x6e,0x22, +/*000cd0*/ 0x29,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x2e, +/*000ce0*/ 0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x66,0x6f,0x72, +/*000cf0*/ 0x6d,0x61,0x74,0x28,0x73,0x74,0x72,0x2e,0x2e,0x22,0x5c,0x6e,0x22,0x2c,0x20,0x2e, +/*000d00*/ 0x2e,0x2e,0x29,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*000d10*/ 0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f, +/*000d20*/ 0x6e,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x6c,0x6f,0x63,0x28,0x66,0x69,0x6c, +/*000d30*/ 0x65,0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*000d40*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x66,0x69,0x6c,0x65, +/*000d50*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22, +/*000d60*/ 0x3a,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57, +/*000d70*/ 0x2e,0x2e,0x6c,0x69,0x6e,0x65,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*000d80*/ 0x53,0x45,0x54,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66, +/*000d90*/ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x73, +/*000da0*/ 0x74,0x61,0x63,0x6b,0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66,0x6f,0x28, +/*000db0*/ 0x69,0x6e,0x66,0x6f,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x69, +/*000dc0*/ 0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x73,0x6f, +/*000dd0*/ 0x75,0x72,0x63,0x65,0x3a,0x6d,0x61,0x74,0x63,0x68,0x28,0x22,0x40,0x28,0x2e,0x2a, +/*000de0*/ 0x29,0x22,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x6f,0x75,0x72, +/*000df0*/ 0x63,0x65,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20,0x61,0x6e, +/*000e00*/ 0x64,0x20,0x64,0x62,0x67,0x2e,0x73,0x68,0x6f,0x72,0x74,0x65,0x6e,0x5f,0x70,0x61, +/*000e10*/ 0x74,0x68,0x28,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x29,0x20,0x6f,0x72,0x20, +/*000e20*/ 0x69,0x6e,0x66,0x6f,0x2e,0x73,0x68,0x6f,0x72,0x74,0x5f,0x73,0x72,0x63,0x0d,0x0a, +/*000e30*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6e,0x61,0x6d,0x65,0x77,0x68,0x61,0x74,0x20, +/*000e40*/ 0x3d,0x20,0x28,0x69,0x6e,0x66,0x6f,0x2e,0x6e,0x61,0x6d,0x65,0x77,0x68,0x61,0x74, +/*000e50*/ 0x20,0x3d,0x3d,0x20,0x22,0x22,0x20,0x61,0x6e,0x64,0x20,0x22,0x63,0x68,0x75,0x6e, +/*000e60*/ 0x6b,0x20,0x61,0x74,0x22,0x20,0x6f,0x72,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x6e,0x61, +/*000e70*/ 0x6d,0x65,0x77,0x68,0x61,0x74,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*000e80*/ 0x6e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x28,0x69,0x6e,0x66,0x6f,0x2e,0x6e,0x61,0x6d, +/*000e90*/ 0x65,0x20,0x61,0x6e,0x64,0x20,0x22,0x27,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*000ea0*/ 0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x69,0x6e,0x66,0x6f,0x2e,0x6e,0x61,0x6d,0x65, +/*000eb0*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22, +/*000ec0*/ 0x27,0x22,0x20,0x6f,0x72,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x6c,0x6f,0x63, +/*000ed0*/ 0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x6c,0x69, +/*000ee0*/ 0x6e,0x65,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x29,0x29,0x0d,0x0a,0x09,0x72,0x65, +/*000ef0*/ 0x74,0x75,0x72,0x6e,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x6c,0x6f,0x63,0x28, +/*000f00*/ 0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72, +/*000f10*/ 0x72,0x65,0x6e,0x74,0x6c,0x69,0x6e,0x65,0x29,0x2e,0x2e,0x22,0x20,0x69,0x6e,0x20, +/*000f20*/ 0x22,0x2e,0x2e,0x6e,0x61,0x6d,0x65,0x77,0x68,0x61,0x74,0x2e,0x2e,0x22,0x20,0x22, +/*000f30*/ 0x2e,0x2e,0x6e,0x61,0x6d,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c, +/*000f40*/ 0x6f,0x63,0x61,0x6c,0x20,0x72,0x65,0x70,0x6c,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20, +/*000f50*/ 0x52,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x20,0x66,0x6f,0x72, +/*000f60*/ 0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x66,0x72,0x61,0x6d,0x65,0x73,0x20,0x77,0x69, +/*000f70*/ 0x74,0x68,0x6f,0x75,0x74,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x0d,0x0a,0x2d, +/*000f80*/ 0x2d,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x73, +/*000f90*/ 0x20,0x43,0x20,0x66,0x72,0x61,0x6d,0x65,0x73,0x2c,0x20,0x4c,0x75,0x61,0x20,0x62, +/*000fa0*/ 0x79,0x74,0x65,0x63,0x6f,0x64,0x65,0x2c,0x20,0x61,0x6e,0x64,0x20,0x60,0x6c,0x6f, +/*000fb0*/ 0x61,0x64,0x73,0x74,0x72,0x69,0x6e,0x67,0x60,0x20,0x66,0x75,0x6e,0x63,0x74,0x69, +/*000fc0*/ 0x6f,0x6e,0x73,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74, +/*000fd0*/ 0x69,0x6f,0x6e,0x20,0x66,0x72,0x61,0x6d,0x65,0x5f,0x68,0x61,0x73,0x5f,0x6c,0x69, +/*000fe0*/ 0x6e,0x65,0x28,0x69,0x6e,0x66,0x6f,0x29,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*000ff0*/ 0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x6c,0x69,0x6e,0x65, +/*001000*/ 0x20,0x3e,0x3d,0x20,0x30,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63, +/*001010*/ 0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x68,0x6f,0x6f,0x6b, +/*001020*/ 0x5f,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x72,0x65,0x70,0x6c,0x5f,0x74,0x68, +/*001030*/ 0x72,0x65,0x73,0x68,0x6f,0x6c,0x64,0x29,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72, +/*001040*/ 0x6e,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x6f,0x66,0x66,0x73,0x65, +/*001050*/ 0x74,0x2c,0x20,0x72,0x65,0x61,0x73,0x6f,0x6e,0x29,0x0d,0x0a,0x09,0x09,0x72,0x65, +/*001060*/ 0x74,0x75,0x72,0x6e,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x65,0x76, +/*001070*/ 0x65,0x6e,0x74,0x2c,0x20,0x5f,0x29,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d,0x20,0x53, +/*001080*/ 0x6b,0x69,0x70,0x20,0x65,0x76,0x65,0x6e,0x74,0x73,0x20,0x74,0x68,0x61,0x74,0x20, +/*001090*/ 0x64,0x6f,0x6e,0x27,0x74,0x20,0x68,0x61,0x76,0x65,0x20,0x6c,0x69,0x6e,0x65,0x20, +/*0010a0*/ 0x69,0x6e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,0x09,0x09, +/*0010b0*/ 0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x66,0x72,0x61,0x6d,0x65,0x5f,0x68,0x61, +/*0010c0*/ 0x73,0x5f,0x6c,0x69,0x6e,0x65,0x28,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74, +/*0010d0*/ 0x69,0x6e,0x66,0x6f,0x28,0x32,0x29,0x29,0x20,0x74,0x68,0x65,0x6e,0x20,0x72,0x65, +/*0010e0*/ 0x74,0x75,0x72,0x6e,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x0d,0x0a,0x09, +/*0010f0*/ 0x09,0x09,0x2d,0x2d,0x20,0x54,0x61,0x69,0x6c,0x20,0x63,0x61,0x6c,0x6c,0x73,0x20, +/*001100*/ 0x61,0x72,0x65,0x20,0x73,0x70,0x65,0x63,0x69,0x66,0x69,0x63,0x61,0x6c,0x6c,0x79, +/*001110*/ 0x20,0x69,0x67,0x6e,0x6f,0x72,0x65,0x64,0x20,0x73,0x69,0x6e,0x63,0x65,0x20,0x74, +/*001120*/ 0x68,0x65,0x79,0x20,0x61,0x6c,0x73,0x6f,0x20,0x77,0x69,0x6c,0x6c,0x20,0x68,0x61, +/*001130*/ 0x76,0x65,0x20,0x74,0x61,0x69,0x6c,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x73,0x20, +/*001140*/ 0x74,0x6f,0x20,0x62,0x61,0x6c,0x61,0x6e,0x63,0x65,0x20,0x6f,0x75,0x74,0x2e,0x0d, +/*001150*/ 0x0a,0x09,0x09,0x09,0x69,0x66,0x20,0x65,0x76,0x65,0x6e,0x74,0x20,0x3d,0x3d,0x20, +/*001160*/ 0x22,0x63,0x61,0x6c,0x6c,0x22,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09, +/*001170*/ 0x09,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x6f,0x66,0x66,0x73,0x65,0x74, +/*001180*/ 0x20,0x2b,0x20,0x31,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6c,0x73,0x65,0x69,0x66,0x20, +/*001190*/ 0x65,0x76,0x65,0x6e,0x74,0x20,0x3d,0x3d,0x20,0x22,0x72,0x65,0x74,0x75,0x72,0x6e, +/*0011a0*/ 0x22,0x20,0x61,0x6e,0x64,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3e,0x20,0x72, +/*0011b0*/ 0x65,0x70,0x6c,0x5f,0x74,0x68,0x72,0x65,0x73,0x68,0x6f,0x6c,0x64,0x20,0x74,0x68, +/*0011c0*/ 0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x09,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d, +/*0011d0*/ 0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2d,0x20,0x31,0x0d,0x0a,0x09,0x09,0x09, +/*0011e0*/ 0x65,0x6c,0x73,0x65,0x69,0x66,0x20,0x65,0x76,0x65,0x6e,0x74,0x20,0x3d,0x3d,0x20, +/*0011f0*/ 0x22,0x6c,0x69,0x6e,0x65,0x22,0x20,0x61,0x6e,0x64,0x20,0x6f,0x66,0x66,0x73,0x65, +/*001200*/ 0x74,0x20,0x3c,0x3d,0x20,0x72,0x65,0x70,0x6c,0x5f,0x74,0x68,0x72,0x65,0x73,0x68, +/*001210*/ 0x6f,0x6c,0x64,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x09,0x72,0x65, +/*001220*/ 0x70,0x6c,0x28,0x72,0x65,0x61,0x73,0x6f,0x6e,0x29,0x0d,0x0a,0x09,0x09,0x09,0x65, +/*001230*/ 0x6e,0x64,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d, +/*001240*/ 0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x68,0x6f, +/*001250*/ 0x6f,0x6b,0x5f,0x73,0x74,0x65,0x70,0x20,0x3d,0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x66, +/*001260*/ 0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x31,0x29,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c, +/*001270*/ 0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x6e,0x65,0x78,0x74,0x20,0x3d,0x20,0x68,0x6f,0x6f, +/*001280*/ 0x6b,0x5f,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x30,0x29,0x0d,0x0a,0x6c,0x6f, +/*001290*/ 0x63,0x61,0x6c,0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x66,0x69,0x6e,0x69,0x73,0x68,0x20, +/*0012a0*/ 0x3d,0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x2d, +/*0012b0*/ 0x31,0x29,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x43,0x72,0x65,0x61,0x74,0x65,0x20, +/*0012c0*/ 0x61,0x20,0x74,0x61,0x62,0x6c,0x65,0x20,0x6f,0x66,0x20,0x61,0x6c,0x6c,0x20,0x74, +/*0012d0*/ 0x68,0x65,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x6c,0x79,0x20,0x61,0x63,0x63,0x65,0x73, +/*0012e0*/ 0x73,0x69,0x62,0x6c,0x65,0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x73,0x2e, +/*0012f0*/ 0x0d,0x0a,0x2d,0x2d,0x20,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x20,0x61,0x72,0x65, +/*001300*/ 0x20,0x6e,0x6f,0x74,0x20,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x64,0x20,0x77,0x68, +/*001310*/ 0x65,0x6e,0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x6c, +/*001320*/ 0x6f,0x63,0x61,0x6c,0x73,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x2c,0x20,0x62, +/*001330*/ 0x75,0x74,0x20,0x61,0x72,0x65,0x20,0x77,0x68,0x65,0x6e,0x20,0x72,0x75,0x6e,0x6e, +/*001340*/ 0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x69,0x6e,0x74,0x20,0x63,0x6f, +/*001350*/ 0x6d,0x6d,0x61,0x6e,0x64,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75, +/*001360*/ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x62,0x69,0x6e, +/*001370*/ 0x64,0x69,0x6e,0x67,0x73,0x28,0x6f,0x66,0x66,0x73,0x65,0x74,0x2c,0x20,0x69,0x6e, +/*001380*/ 0x63,0x6c,0x75,0x64,0x65,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x29,0x0d,0x0a, +/*001390*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6c,0x65,0x76,0x65,0x6c,0x20,0x3d,0x20,0x6f, +/*0013a0*/ 0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e, +/*0013b0*/ 0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x43, +/*0013c0*/ 0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x0d,0x0a, +/*0013d0*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x20,0x3d,0x20,0x64,0x65, +/*0013e0*/ 0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x6c,0x65,0x76,0x65, +/*0013f0*/ 0x6c,0x29,0x2e,0x66,0x75,0x6e,0x63,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*001400*/ 0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x20,0x3d,0x20,0x7b,0x7d,0x0d,0x0a,0x09, +/*001410*/ 0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x72,0x69,0x65,0x76,0x65,0x20,0x74, +/*001420*/ 0x68,0x65,0x20,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x73,0x0d,0x0a,0x09,0x64,0x6f, +/*001430*/ 0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20,0x3d,0x20,0x31,0x3b,0x20,0x77,0x68, +/*001440*/ 0x69,0x6c,0x65,0x20,0x74,0x72,0x75,0x65,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x6c, +/*001450*/ 0x6f,0x63,0x61,0x6c,0x20,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x76,0x61,0x6c,0x75,0x65, +/*001460*/ 0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x75,0x70,0x76,0x61, +/*001470*/ 0x6c,0x75,0x65,0x28,0x66,0x75,0x6e,0x63,0x2c,0x20,0x69,0x29,0x0d,0x0a,0x09,0x09, +/*001480*/ 0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x6e,0x61,0x6d,0x65,0x20,0x74,0x68,0x65,0x6e, +/*001490*/ 0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x62,0x69, +/*0014a0*/ 0x6e,0x64,0x69,0x6e,0x67,0x73,0x5b,0x6e,0x61,0x6d,0x65,0x5d,0x20,0x3d,0x20,0x76, +/*0014b0*/ 0x61,0x6c,0x75,0x65,0x0d,0x0a,0x09,0x09,0x69,0x20,0x3d,0x20,0x69,0x20,0x2b,0x20, +/*0014c0*/ 0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a, +/*0014d0*/ 0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x72,0x69,0x65,0x76,0x65,0x20,0x74,0x68,0x65, +/*0014e0*/ 0x20,0x6c,0x6f,0x63,0x61,0x6c,0x73,0x20,0x28,0x6f,0x76,0x65,0x72,0x77,0x72,0x69, +/*0014f0*/ 0x74,0x69,0x6e,0x67,0x20,0x61,0x6e,0x79,0x20,0x75,0x70,0x76,0x61,0x6c,0x75,0x65, +/*001500*/ 0x73,0x29,0x0d,0x0a,0x09,0x64,0x6f,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20, +/*001510*/ 0x3d,0x20,0x31,0x3b,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x74,0x72,0x75,0x65,0x20, +/*001520*/ 0x64,0x6f,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6e,0x61,0x6d,0x65, +/*001530*/ 0x2c,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e, +/*001540*/ 0x67,0x65,0x74,0x6c,0x6f,0x63,0x61,0x6c,0x28,0x6c,0x65,0x76,0x65,0x6c,0x2c,0x20, +/*001550*/ 0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x6e,0x61,0x6d, +/*001560*/ 0x65,0x20,0x74,0x68,0x65,0x6e,0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65,0x6e,0x64, +/*001570*/ 0x0d,0x0a,0x09,0x09,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x5b,0x6e,0x61,0x6d, +/*001580*/ 0x65,0x5d,0x20,0x3d,0x20,0x76,0x61,0x6c,0x75,0x65,0x0d,0x0a,0x09,0x09,0x69,0x20, +/*001590*/ 0x3d,0x20,0x69,0x20,0x2b,0x20,0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x20,0x65,0x6e, +/*0015a0*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x72,0x69,0x65, +/*0015b0*/ 0x76,0x65,0x20,0x74,0x68,0x65,0x20,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x20,0x28, +/*0015c0*/ 0x77,0x6f,0x72,0x6b,0x73,0x20,0x69,0x6e,0x20,0x4c,0x75,0x61,0x20,0x35,0x2e,0x32, +/*0015d0*/ 0x20,0x61,0x6e,0x64,0x20,0x4c,0x75,0x61,0x4a,0x49,0x54,0x29,0x0d,0x0a,0x09,0x6c, +/*0015e0*/ 0x6f,0x63,0x61,0x6c,0x20,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x20,0x3d,0x20,0x7b, +/*0015f0*/ 0x7d,0x0d,0x0a,0x09,0x64,0x6f,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20,0x3d, +/*001600*/ 0x20,0x31,0x3b,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x74,0x72,0x75,0x65,0x20,0x64, +/*001610*/ 0x6f,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6e,0x61,0x6d,0x65,0x2c, +/*001620*/ 0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67, +/*001630*/ 0x65,0x74,0x6c,0x6f,0x63,0x61,0x6c,0x28,0x6c,0x65,0x76,0x65,0x6c,0x2c,0x20,0x2d, +/*001640*/ 0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x6e,0x61,0x6d, +/*001650*/ 0x65,0x20,0x74,0x68,0x65,0x6e,0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65,0x6e,0x64, +/*001660*/ 0x0d,0x0a,0x09,0x09,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x5b,0x69,0x5d,0x20,0x3d, +/*001670*/ 0x20,0x76,0x61,0x6c,0x75,0x65,0x0d,0x0a,0x09,0x09,0x69,0x20,0x3d,0x20,0x69,0x20, +/*001680*/ 0x2b,0x20,0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09, +/*001690*/ 0x69,0x66,0x20,0x23,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x20,0x3e,0x20,0x30,0x20, +/*0016a0*/ 0x74,0x68,0x65,0x6e,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x5b,0x22,0x2e, +/*0016b0*/ 0x2e,0x2e,0x22,0x5d,0x20,0x3d,0x20,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x20,0x65, +/*0016c0*/ 0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66,0x20,0x69,0x6e,0x63,0x6c,0x75, +/*0016d0*/ 0x64,0x65,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x20,0x74,0x68,0x65,0x6e,0x0d, +/*0016e0*/ 0x0a,0x09,0x09,0x2d,0x2d,0x20,0x49,0x6e,0x20,0x4c,0x75,0x61,0x20,0x35,0x2e,0x32, +/*0016f0*/ 0x2c,0x20,0x79,0x6f,0x75,0x20,0x68,0x61,0x76,0x65,0x20,0x74,0x6f,0x20,0x67,0x65, +/*001700*/ 0x74,0x20,0x74,0x68,0x65,0x20,0x65,0x6e,0x76,0x69,0x72,0x6f,0x6e,0x6d,0x65,0x6e, +/*001710*/ 0x74,0x20,0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x72,0x6f,0x6d,0x20,0x74,0x68,0x65, +/*001720*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x27,0x73,0x20,0x6c,0x6f,0x63,0x61, +/*001730*/ 0x6c,0x73,0x2e,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x76, +/*001740*/ 0x20,0x3d,0x20,0x28,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x20,0x3c,0x3d,0x20, +/*001750*/ 0x22,0x4c,0x75,0x61,0x20,0x35,0x2e,0x31,0x22,0x20,0x61,0x6e,0x64,0x20,0x67,0x65, +/*001760*/ 0x74,0x66,0x65,0x6e,0x76,0x28,0x66,0x75,0x6e,0x63,0x29,0x20,0x6f,0x72,0x20,0x62, +/*001770*/ 0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x2e,0x5f,0x45,0x4e,0x56,0x29,0x0d,0x0a,0x09, +/*001780*/ 0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x65,0x74,0x6d,0x65,0x74,0x61,0x74, +/*001790*/ 0x61,0x62,0x6c,0x65,0x28,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x2c,0x20,0x7b, +/*0017a0*/ 0x5f,0x5f,0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x20,0x65,0x6e,0x76,0x20,0x6f,0x72, +/*0017b0*/ 0x20,0x5f,0x47,0x7d,0x29,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09, +/*0017c0*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x0d, +/*0017d0*/ 0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d, +/*0017e0*/ 0x20,0x55,0x73,0x65,0x64,0x20,0x61,0x73,0x20,0x61,0x20,0x5f,0x5f,0x6e,0x65,0x77, +/*0017f0*/ 0x69,0x6e,0x64,0x65,0x78,0x20,0x6d,0x65,0x74,0x61,0x6d,0x65,0x74,0x68,0x6f,0x64, +/*001800*/ 0x20,0x74,0x6f,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x20,0x76,0x61,0x72,0x69,0x61, +/*001810*/ 0x62,0x6c,0x65,0x73,0x20,0x69,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x65,0x76,0x61,0x6c, +/*001820*/ 0x28,0x29,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74, +/*001830*/ 0x69,0x6f,0x6e,0x20,0x6d,0x75,0x74,0x61,0x74,0x65,0x5f,0x62,0x69,0x6e,0x64,0x69, +/*001840*/ 0x6e,0x67,0x73,0x28,0x5f,0x2c,0x20,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x76,0x61,0x6c, +/*001850*/ 0x75,0x65,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x46,0x55,0x4e,0x43, +/*001860*/ 0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x20,0x3d,0x20, +/*001870*/ 0x33,0x20,0x2d,0x2d,0x20,0x53,0x74,0x61,0x63,0x6b,0x20,0x64,0x65,0x70,0x74,0x68, +/*001880*/ 0x20,0x6f,0x66,0x20,0x74,0x68,0x69,0x73,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f, +/*001890*/ 0x6e,0x2e,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6c,0x65,0x76,0x65,0x6c, +/*0018a0*/ 0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74, +/*0018b0*/ 0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x46,0x55,0x4e,0x43,0x5f,0x53, +/*0018c0*/ 0x54,0x41,0x43,0x4b,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x20,0x2b,0x20,0x43,0x4d, +/*0018d0*/ 0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x0d,0x0a,0x09, +/*0018e0*/ 0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x53,0x65,0x74,0x20,0x61,0x20,0x6c,0x6f,0x63,0x61, +/*0018f0*/ 0x6c,0x2e,0x0d,0x0a,0x09,0x64,0x6f,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20, +/*001900*/ 0x3d,0x20,0x31,0x3b,0x20,0x72,0x65,0x70,0x65,0x61,0x74,0x0d,0x0a,0x09,0x09,0x6c, +/*001910*/ 0x6f,0x63,0x61,0x6c,0x20,0x76,0x61,0x72,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67, +/*001920*/ 0x2e,0x67,0x65,0x74,0x6c,0x6f,0x63,0x61,0x6c,0x28,0x6c,0x65,0x76,0x65,0x6c,0x2c, +/*001930*/ 0x20,0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x61,0x6d,0x65,0x20,0x3d, +/*001940*/ 0x3d,0x20,0x76,0x61,0x72,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x64, +/*001950*/ 0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52, +/*001960*/ 0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67, +/*001970*/ 0x65,0x72,0x2e,0x6c,0x75,0x61,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43, +/*001980*/ 0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x53,0x65,0x74,0x20,0x6c,0x6f,0x63,0x61,0x6c, +/*001990*/ 0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c, +/*0019a0*/ 0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x6e,0x61,0x6d,0x65,0x2e,0x2e,0x43, +/*0019b0*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*0019c0*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x73,0x65,0x74, +/*0019d0*/ 0x6c,0x6f,0x63,0x61,0x6c,0x28,0x6c,0x65,0x76,0x65,0x6c,0x20,0x2b,0x20,0x4c,0x55, +/*0019e0*/ 0x41,0x5f,0x4a,0x49,0x54,0x5f,0x53,0x45,0x54,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x57, +/*0019f0*/ 0x4f,0x52,0x4b,0x41,0x52,0x4f,0x55,0x4e,0x44,0x2c,0x20,0x69,0x2c,0x20,0x76,0x61, +/*001a00*/ 0x6c,0x75,0x65,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x69, +/*001a10*/ 0x20,0x3d,0x20,0x69,0x20,0x2b,0x20,0x31,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c, +/*001a20*/ 0x20,0x76,0x61,0x72,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x65,0x6e,0x64,0x0d, +/*001a30*/ 0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x53,0x65,0x74,0x20,0x61,0x6e,0x20,0x75, +/*001a40*/ 0x70,0x76,0x61,0x6c,0x75,0x65,0x2e,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*001a50*/ 0x66,0x75,0x6e,0x63,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74, +/*001a60*/ 0x69,0x6e,0x66,0x6f,0x28,0x6c,0x65,0x76,0x65,0x6c,0x29,0x2e,0x66,0x75,0x6e,0x63, +/*001a70*/ 0x0d,0x0a,0x09,0x64,0x6f,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20,0x3d,0x20, +/*001a80*/ 0x31,0x3b,0x20,0x72,0x65,0x70,0x65,0x61,0x74,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63, +/*001a90*/ 0x61,0x6c,0x20,0x76,0x61,0x72,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67, +/*001aa0*/ 0x65,0x74,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x28,0x66,0x75,0x6e,0x63,0x2c,0x20, +/*001ab0*/ 0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d, +/*001ac0*/ 0x20,0x76,0x61,0x72,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x64,0x62, +/*001ad0*/ 0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*001ae0*/ 0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67,0x65, +/*001af0*/ 0x72,0x2e,0x6c,0x75,0x61,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41, +/*001b00*/ 0x52,0x45,0x54,0x2e,0x2e,0x22,0x53,0x65,0x74,0x20,0x75,0x70,0x76,0x61,0x6c,0x75, +/*001b10*/ 0x65,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e, +/*001b20*/ 0x2e,0x6e,0x61,0x6d,0x65,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53, +/*001b30*/ 0x45,0x54,0x29,0x0d,0x0a,0x09,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64, +/*001b40*/ 0x65,0x62,0x75,0x67,0x2e,0x73,0x65,0x74,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x28, +/*001b50*/ 0x66,0x75,0x6e,0x63,0x2c,0x20,0x69,0x2c,0x20,0x76,0x61,0x6c,0x75,0x65,0x29,0x0d, +/*001b60*/ 0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x69,0x20,0x3d,0x20,0x69,0x20, +/*001b70*/ 0x2b,0x20,0x31,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c,0x20,0x76,0x61,0x72,0x20, +/*001b80*/ 0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09, +/*001b90*/ 0x2d,0x2d,0x20,0x53,0x65,0x74,0x20,0x61,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x2e, +/*001ba0*/ 0x0d,0x0a,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*001bb0*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65, +/*001bc0*/ 0x62,0x75,0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x22,0x2e,0x2e,0x47,0x52,0x45, +/*001bd0*/ 0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x53,0x65,0x74,0x20,0x67, +/*001be0*/ 0x6c,0x6f,0x62,0x61,0x6c,0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x20,0x22, +/*001bf0*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x6e,0x61, +/*001c00*/ 0x6d,0x65,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x29, +/*001c10*/ 0x0d,0x0a,0x09,0x5f,0x47,0x5b,0x6e,0x61,0x6d,0x65,0x5d,0x20,0x3d,0x20,0x76,0x61, +/*001c20*/ 0x6c,0x75,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x43, +/*001c30*/ 0x6f,0x6d,0x70,0x69,0x6c,0x65,0x20,0x61,0x6e,0x20,0x65,0x78,0x70,0x72,0x65,0x73, +/*001c40*/ 0x73,0x69,0x6f,0x6e,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x65,0x20,0x67,0x69, +/*001c50*/ 0x76,0x65,0x6e,0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x20,0x62,0x69,0x6e, +/*001c60*/ 0x64,0x69,0x6e,0x67,0x73,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75, +/*001c70*/ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x5f,0x63, +/*001c80*/ 0x68,0x75,0x6e,0x6b,0x28,0x62,0x6c,0x6f,0x63,0x6b,0x2c,0x20,0x65,0x6e,0x76,0x29, +/*001c90*/ 0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20, +/*001ca0*/ 0x3d,0x20,0x22,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x20, +/*001cb0*/ 0x52,0x45,0x50,0x4c,0x22,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x68, +/*001cc0*/ 0x75,0x6e,0x6b,0x20,0x3d,0x20,0x6e,0x69,0x6c,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69, +/*001cd0*/ 0x66,0x20,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x20,0x3c,0x3d,0x20,0x22,0x4c, +/*001ce0*/ 0x75,0x61,0x20,0x35,0x2e,0x31,0x22,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09, +/*001cf0*/ 0x63,0x68,0x75,0x6e,0x6b,0x20,0x3d,0x20,0x6c,0x6f,0x61,0x64,0x73,0x74,0x72,0x69, +/*001d00*/ 0x6e,0x67,0x28,0x62,0x6c,0x6f,0x63,0x6b,0x2c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65, +/*001d10*/ 0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x74,0x68, +/*001d20*/ 0x65,0x6e,0x20,0x73,0x65,0x74,0x66,0x65,0x6e,0x76,0x28,0x63,0x68,0x75,0x6e,0x6b, +/*001d30*/ 0x2c,0x20,0x65,0x6e,0x76,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6c,0x73, +/*001d40*/ 0x65,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x54,0x68,0x65,0x20,0x4c,0x75,0x61,0x20, +/*001d50*/ 0x35,0x2e,0x32,0x20,0x77,0x61,0x79,0x20,0x69,0x73,0x20,0x61,0x20,0x62,0x69,0x74, +/*001d60*/ 0x20,0x63,0x6c,0x65,0x61,0x6e,0x65,0x72,0x0d,0x0a,0x09,0x09,0x63,0x68,0x75,0x6e, +/*001d70*/ 0x6b,0x20,0x3d,0x20,0x6c,0x6f,0x61,0x64,0x28,0x62,0x6c,0x6f,0x63,0x6b,0x2c,0x20, +/*001d80*/ 0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x22,0x74,0x22,0x2c,0x20,0x65,0x6e,0x76, +/*001d90*/ 0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66,0x20, +/*001da0*/ 0x6e,0x6f,0x74,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x74,0x68,0x65,0x6e,0x20,0x64, +/*001db0*/ 0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52, +/*001dc0*/ 0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x72,0x72,0x6f,0x72,0x3a,0x20,0x43,0x6f, +/*001dd0*/ 0x75,0x6c,0x64,0x20,0x6e,0x6f,0x74,0x20,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x20, +/*001de0*/ 0x62,0x6c,0x6f,0x63,0x6b,0x3a,0x5c,0x6e,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*001df0*/ 0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x62,0x6c,0x6f,0x63,0x6b,0x29,0x20,0x65, +/*001e00*/ 0x6e,0x64,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x63,0x68,0x75,0x6e, +/*001e10*/ 0x6b,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*001e20*/ 0x53,0x4f,0x55,0x52,0x43,0x45,0x5f,0x43,0x41,0x43,0x48,0x45,0x20,0x3d,0x20,0x7b, +/*001e30*/ 0x7d,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74, +/*001e40*/ 0x69,0x6f,0x6e,0x20,0x77,0x68,0x65,0x72,0x65,0x28,0x69,0x6e,0x66,0x6f,0x2c,0x20, +/*001e50*/ 0x63,0x6f,0x6e,0x74,0x65,0x78,0x74,0x5f,0x6c,0x69,0x6e,0x65,0x73,0x29,0x0d,0x0a, +/*001e60*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x3d,0x20, +/*001e70*/ 0x53,0x4f,0x55,0x52,0x43,0x45,0x5f,0x43,0x41,0x43,0x48,0x45,0x5b,0x69,0x6e,0x66, +/*001e80*/ 0x6f,0x2e,0x73,0x6f,0x75,0x72,0x63,0x65,0x5d,0x0d,0x0a,0x09,0x69,0x66,0x20,0x6e, +/*001e90*/ 0x6f,0x74,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a, +/*001ea0*/ 0x09,0x09,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x3d,0x20,0x7b,0x7d,0x0d,0x0a,0x09, +/*001eb0*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20, +/*001ec0*/ 0x3d,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x73,0x6f,0x75,0x72,0x63,0x65,0x3a,0x6d,0x61, +/*001ed0*/ 0x74,0x63,0x68,0x28,0x22,0x40,0x28,0x2e,0x2a,0x29,0x22,0x29,0x0d,0x0a,0x09,0x09, +/*001ee0*/ 0x69,0x66,0x20,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20,0x74,0x68,0x65,0x6e, +/*001ef0*/ 0x0d,0x0a,0x09,0x09,0x09,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66,0x75,0x6e,0x63,0x74, +/*001f00*/ 0x69,0x6f,0x6e,0x28,0x29,0x20,0x66,0x6f,0x72,0x20,0x6c,0x69,0x6e,0x65,0x20,0x69, +/*001f10*/ 0x6e,0x20,0x69,0x6f,0x2e,0x6c,0x69,0x6e,0x65,0x73,0x28,0x66,0x69,0x6c,0x65,0x6e, +/*001f20*/ 0x61,0x6d,0x65,0x29,0x20,0x64,0x6f,0x20,0x74,0x61,0x62,0x6c,0x65,0x2e,0x69,0x6e, +/*001f30*/ 0x73,0x65,0x72,0x74,0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x6c,0x69,0x6e, +/*001f40*/ 0x65,0x29,0x20,0x65,0x6e,0x64,0x20,0x65,0x6e,0x64,0x29,0x0d,0x0a,0x09,0x09,0x65, +/*001f50*/ 0x6c,0x73,0x65,0x69,0x66,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x73,0x6f,0x75,0x72,0x63, +/*001f60*/ 0x65,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x66,0x6f,0x72,0x20,0x6c, +/*001f70*/ 0x69,0x6e,0x65,0x20,0x69,0x6e,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x73,0x6f,0x75,0x72, +/*001f80*/ 0x63,0x65,0x3a,0x67,0x6d,0x61,0x74,0x63,0x68,0x28,0x22,0x28,0x2e,0x2d,0x29,0x5c, +/*001f90*/ 0x6e,0x22,0x29,0x20,0x64,0x6f,0x20,0x74,0x61,0x62,0x6c,0x65,0x2e,0x69,0x6e,0x73, +/*001fa0*/ 0x65,0x72,0x74,0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x6c,0x69,0x6e,0x65, +/*001fb0*/ 0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09, +/*001fc0*/ 0x53,0x4f,0x55,0x52,0x43,0x45,0x5f,0x43,0x41,0x43,0x48,0x45,0x5b,0x69,0x6e,0x66, +/*001fd0*/ 0x6f,0x2e,0x73,0x6f,0x75,0x72,0x63,0x65,0x5d,0x20,0x3d,0x20,0x73,0x6f,0x75,0x72, +/*001fe0*/ 0x63,0x65,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66, +/*001ff0*/ 0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x61,0x6e,0x64,0x20,0x73,0x6f,0x75,0x72, +/*002000*/ 0x63,0x65,0x5b,0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x6c, +/*002010*/ 0x69,0x6e,0x65,0x5d,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x66,0x6f,0x72, +/*002020*/ 0x20,0x69,0x20,0x3d,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72,0x72,0x65,0x6e, +/*002030*/ 0x74,0x6c,0x69,0x6e,0x65,0x20,0x2d,0x20,0x63,0x6f,0x6e,0x74,0x65,0x78,0x74,0x5f, +/*002040*/ 0x6c,0x69,0x6e,0x65,0x73,0x2c,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72,0x72, +/*002050*/ 0x65,0x6e,0x74,0x6c,0x69,0x6e,0x65,0x20,0x2b,0x20,0x63,0x6f,0x6e,0x74,0x65,0x78, +/*002060*/ 0x74,0x5f,0x6c,0x69,0x6e,0x65,0x73,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x09,0x6c, +/*002070*/ 0x6f,0x63,0x61,0x6c,0x20,0x74,0x61,0x62,0x5f,0x6f,0x72,0x5f,0x63,0x61,0x72,0x65, +/*002080*/ 0x74,0x20,0x3d,0x20,0x28,0x69,0x20,0x3d,0x3d,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x63, +/*002090*/ 0x75,0x72,0x72,0x65,0x6e,0x74,0x6c,0x69,0x6e,0x65,0x20,0x61,0x6e,0x64,0x20,0x20, +/*0020a0*/ 0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x20,0x6f,0x72,0x20,0x22, +/*0020b0*/ 0x20,0x20,0x20,0x20,0x22,0x29,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*0020c0*/ 0x20,0x6c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x5b,0x69, +/*0020d0*/ 0x5d,0x0d,0x0a,0x09,0x09,0x09,0x69,0x66,0x20,0x6c,0x69,0x6e,0x65,0x20,0x74,0x68, +/*0020e0*/ 0x65,0x6e,0x20,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*0020f0*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x47,0x52,0x41,0x59,0x2e,0x2e,0x22,0x25,0x20,0x34,0x64, +/*002100*/ 0x22,0x2e,0x2e,0x74,0x61,0x62,0x5f,0x6f,0x72,0x5f,0x63,0x61,0x72,0x65,0x74,0x2e, +/*002110*/ 0x2e,0x22,0x25,0x73,0x22,0x2c,0x20,0x69,0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x20, +/*002120*/ 0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6c,0x73, +/*002130*/ 0x65,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e, +/*002140*/ 0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x72,0x72, +/*002150*/ 0x6f,0x72,0x3a,0x20,0x53,0x6f,0x75,0x72,0x63,0x65,0x20,0x6e,0x6f,0x74,0x20,0x61, +/*002160*/ 0x76,0x61,0x69,0x6c,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x22,0x2e,0x2e, +/*002170*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x69,0x6e,0x66,0x6f, +/*002180*/ 0x2e,0x73,0x68,0x6f,0x72,0x74,0x5f,0x73,0x72,0x63,0x29,0x3b,0x0d,0x0a,0x09,0x65, +/*002190*/ 0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66, +/*0021a0*/ 0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20, +/*0021b0*/ 0x57,0x65,0x65,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x64,0x69,0x66,0x66, +/*0021c0*/ 0x65,0x72,0x65,0x6e,0x63,0x65,0x73,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75, +/*0021d0*/ 0x6e,0x70,0x61,0x63,0x6b,0x20,0x3d,0x20,0x75,0x6e,0x70,0x61,0x63,0x6b,0x20,0x6f, +/*0021e0*/ 0x72,0x20,0x74,0x61,0x62,0x6c,0x65,0x2e,0x75,0x6e,0x70,0x61,0x63,0x6b,0x0d,0x0a, +/*0021f0*/ 0x6c,0x6f,0x63,0x61,0x6c,0x20,0x70,0x61,0x63,0x6b,0x20,0x3d,0x20,0x66,0x75,0x6e, +/*002200*/ 0x63,0x74,0x69,0x6f,0x6e,0x28,0x2e,0x2e,0x2e,0x29,0x20,0x72,0x65,0x74,0x75,0x72, +/*002210*/ 0x6e,0x20,0x7b,0x6e,0x20,0x3d,0x20,0x73,0x65,0x6c,0x65,0x63,0x74,0x28,0x22,0x23, +/*002220*/ 0x22,0x2c,0x20,0x2e,0x2e,0x2e,0x29,0x2c,0x20,0x2e,0x2e,0x2e,0x7d,0x20,0x65,0x6e, +/*002230*/ 0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74, +/*002240*/ 0x69,0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x73,0x74,0x65,0x70,0x28,0x29,0x0d,0x0a, +/*002250*/ 0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f, +/*002260*/ 0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f, +/*002270*/ 0x70,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x2c, +/*002280*/ 0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x73,0x74,0x65,0x70,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*002290*/ 0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f, +/*0022a0*/ 0x6e,0x20,0x63,0x6d,0x64,0x5f,0x6e,0x65,0x78,0x74,0x28,0x29,0x0d,0x0a,0x09,0x73, +/*0022b0*/ 0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66, +/*0022c0*/ 0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x0d, +/*0022d0*/ 0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x2c,0x20,0x68, +/*0022e0*/ 0x6f,0x6f,0x6b,0x5f,0x6e,0x65,0x78,0x74,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d, +/*0022f0*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*002300*/ 0x63,0x6d,0x64,0x5f,0x66,0x69,0x6e,0x69,0x73,0x68,0x28,0x29,0x0d,0x0a,0x09,0x6c, +/*002310*/ 0x6f,0x63,0x61,0x6c,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74, +/*002320*/ 0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x20,0x2d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f, +/*002330*/ 0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x0d,0x0a, +/*002340*/ 0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f, +/*002350*/ 0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f, +/*002360*/ 0x70,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x2c, +/*002370*/ 0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3c,0x20,0x30,0x20,0x61,0x6e,0x64,0x20, +/*002380*/ 0x68,0x6f,0x6f,0x6b,0x5f,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x6f,0x66,0x66, +/*002390*/ 0x73,0x65,0x74,0x20,0x2d,0x20,0x31,0x29,0x20,0x6f,0x72,0x20,0x68,0x6f,0x6f,0x6b, +/*0023a0*/ 0x5f,0x66,0x69,0x6e,0x69,0x73,0x68,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a, +/*0023b0*/ 0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63, +/*0023c0*/ 0x6d,0x64,0x5f,0x70,0x72,0x69,0x6e,0x74,0x28,0x65,0x78,0x70,0x72,0x29,0x0d,0x0a, +/*0023d0*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x76,0x20,0x3d,0x20,0x6c,0x6f,0x63, +/*0023e0*/ 0x61,0x6c,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x28,0x31,0x2c,0x20,0x74, +/*0023f0*/ 0x72,0x75,0x65,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x68,0x75, +/*002400*/ 0x6e,0x6b,0x20,0x3d,0x20,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x5f,0x63,0x68,0x75, +/*002410*/ 0x6e,0x6b,0x28,0x22,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x22,0x2e,0x2e,0x65,0x78, +/*002420*/ 0x70,0x72,0x2c,0x20,0x65,0x6e,0x76,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20,0x63,0x68, +/*002430*/ 0x75,0x6e,0x6b,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x74,0x68,0x65,0x6e,0x20, +/*002440*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x20,0x65,0x6e,0x64, +/*002450*/ 0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x43,0x61,0x6c,0x6c,0x20,0x74,0x68, +/*002460*/ 0x65,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x61,0x6e,0x64,0x20,0x63,0x6f,0x6c,0x6c, +/*002470*/ 0x65,0x63,0x74,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x2e, +/*002480*/ 0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73, +/*002490*/ 0x20,0x3d,0x20,0x70,0x61,0x63,0x6b,0x28,0x70,0x63,0x61,0x6c,0x6c,0x28,0x63,0x68, +/*0024a0*/ 0x75,0x6e,0x6b,0x2c,0x20,0x75,0x6e,0x70,0x61,0x63,0x6b,0x28,0x72,0x61,0x77,0x67, +/*0024b0*/ 0x65,0x74,0x28,0x65,0x6e,0x76,0x2c,0x20,0x22,0x2e,0x2e,0x2e,0x22,0x29,0x20,0x6f, +/*0024c0*/ 0x72,0x20,0x7b,0x7d,0x29,0x29,0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20, +/*0024d0*/ 0x54,0x68,0x65,0x20,0x66,0x69,0x72,0x73,0x74,0x20,0x72,0x65,0x73,0x75,0x6c,0x74, +/*0024e0*/ 0x20,0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x70,0x63,0x61,0x6c,0x6c,0x20,0x65,0x72, +/*0024f0*/ 0x72,0x6f,0x72,0x2e,0x0d,0x0a,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x72,0x65, +/*002500*/ 0x73,0x75,0x6c,0x74,0x73,0x5b,0x31,0x5d,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09, +/*002510*/ 0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c, +/*002520*/ 0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x72,0x72,0x6f,0x72,0x3a,0x22, +/*002530*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22, +/*002540*/ 0x20,0x22,0x2e,0x2e,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x5b,0x32,0x5d,0x29,0x0d, +/*002550*/ 0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*002560*/ 0x6f,0x75,0x74,0x70,0x75,0x74,0x20,0x3d,0x20,0x22,0x22,0x0d,0x0a,0x09,0x09,0x66, +/*002570*/ 0x6f,0x72,0x20,0x69,0x20,0x3d,0x20,0x32,0x2c,0x20,0x72,0x65,0x73,0x75,0x6c,0x74, +/*002580*/ 0x73,0x2e,0x6e,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x09,0x6f,0x75,0x74,0x70,0x75, +/*002590*/ 0x74,0x20,0x3d,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x2e,0x28,0x69,0x20,0x7e, +/*0025a0*/ 0x3d,0x20,0x32,0x20,0x61,0x6e,0x64,0x20,0x22,0x2c,0x20,0x22,0x20,0x6f,0x72,0x20, +/*0025b0*/ 0x22,0x22,0x29,0x2e,0x2e,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x28, +/*0025c0*/ 0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x5b,0x69,0x5d,0x29,0x0d,0x0a,0x09,0x09,0x65, +/*0025d0*/ 0x6e,0x64,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6f,0x75,0x74, +/*0025e0*/ 0x70,0x75,0x74,0x20,0x3d,0x3d,0x20,0x22,0x22,0x20,0x74,0x68,0x65,0x6e,0x20,0x6f, +/*0025f0*/ 0x75,0x74,0x70,0x75,0x74,0x20,0x3d,0x20,0x22,0x3c,0x6e,0x6f,0x20,0x72,0x65,0x73, +/*002600*/ 0x75,0x6c,0x74,0x3e,0x22,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67, +/*002610*/ 0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42, +/*002620*/ 0x4c,0x55,0x45,0x2e,0x2e,0x65,0x78,0x70,0x72,0x2e,0x2e,0x20,0x47,0x52,0x45,0x45, +/*002630*/ 0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x6f,0x75,0x74,0x70,0x75,0x74,0x29, +/*002640*/ 0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75, +/*002650*/ 0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d, +/*002660*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*002670*/ 0x63,0x6d,0x64,0x5f,0x65,0x76,0x61,0x6c,0x28,0x63,0x6f,0x64,0x65,0x29,0x0d,0x0a, +/*002680*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x76,0x20,0x3d,0x20,0x6c,0x6f,0x63, +/*002690*/ 0x61,0x6c,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x28,0x31,0x2c,0x20,0x74, +/*0026a0*/ 0x72,0x75,0x65,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6d,0x75,0x74, +/*0026b0*/ 0x61,0x62,0x6c,0x65,0x5f,0x65,0x6e,0x76,0x20,0x3d,0x20,0x73,0x65,0x74,0x6d,0x65, +/*0026c0*/ 0x74,0x61,0x74,0x61,0x62,0x6c,0x65,0x28,0x7b,0x7d,0x2c,0x20,0x7b,0x0d,0x0a,0x09, +/*0026d0*/ 0x09,0x5f,0x5f,0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x20,0x65,0x6e,0x76,0x2c,0x0d, +/*0026e0*/ 0x0a,0x09,0x09,0x5f,0x5f,0x6e,0x65,0x77,0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x20, +/*0026f0*/ 0x6d,0x75,0x74,0x61,0x74,0x65,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x2c, +/*002700*/ 0x0d,0x0a,0x09,0x7d,0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*002710*/ 0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x3d,0x20,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65, +/*002720*/ 0x5f,0x63,0x68,0x75,0x6e,0x6b,0x28,0x63,0x6f,0x64,0x65,0x2c,0x20,0x6d,0x75,0x74, +/*002730*/ 0x61,0x62,0x6c,0x65,0x5f,0x65,0x6e,0x76,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20,0x63, +/*002740*/ 0x68,0x75,0x6e,0x6b,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x74,0x68,0x65,0x6e, +/*002750*/ 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x20,0x65,0x6e, +/*002760*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x43,0x61,0x6c,0x6c,0x20,0x74, +/*002770*/ 0x68,0x65,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x61,0x6e,0x64,0x20,0x63,0x6f,0x6c, +/*002780*/ 0x6c,0x65,0x63,0x74,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73, +/*002790*/ 0x2e,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x75,0x63,0x63,0x65,0x73, +/*0027a0*/ 0x73,0x2c,0x20,0x65,0x72,0x72,0x20,0x3d,0x20,0x70,0x63,0x61,0x6c,0x6c,0x28,0x63, +/*0027b0*/ 0x68,0x75,0x6e,0x6b,0x2c,0x20,0x75,0x6e,0x70,0x61,0x63,0x6b,0x28,0x72,0x61,0x77, +/*0027c0*/ 0x67,0x65,0x74,0x28,0x65,0x6e,0x76,0x2c,0x20,0x22,0x2e,0x2e,0x2e,0x22,0x29,0x20, +/*0027d0*/ 0x6f,0x72,0x20,0x7b,0x7d,0x29,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74, +/*0027e0*/ 0x20,0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09, +/*0027f0*/ 0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c, +/*002800*/ 0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x72,0x72,0x6f,0x72,0x3a,0x22, +/*002810*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22, +/*002820*/ 0x20,0x22,0x2e,0x2e,0x74,0x6f,0x73,0x74,0x72,0x69,0x6e,0x67,0x28,0x65,0x72,0x72, +/*002830*/ 0x29,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65, +/*002840*/ 0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*002850*/ 0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f, +/*002860*/ 0x6e,0x20,0x63,0x6d,0x64,0x5f,0x64,0x6f,0x77,0x6e,0x28,0x29,0x0d,0x0a,0x09,0x6c, +/*002870*/ 0x6f,0x63,0x61,0x6c,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74, +/*002880*/ 0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73, +/*002890*/ 0x65,0x74,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x6e,0x66,0x6f,0x0d, +/*0028a0*/ 0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x70,0x65,0x61,0x74,0x20,0x2d,0x2d,0x20,0x46, +/*0028b0*/ 0x69,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x6e,0x65,0x78,0x74,0x20,0x66,0x72,0x61, +/*0028c0*/ 0x6d,0x65,0x20,0x77,0x69,0x74,0x68,0x20,0x61,0x20,0x66,0x69,0x6c,0x65,0x2e,0x0d, +/*0028d0*/ 0x0a,0x09,0x09,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x6f,0x66,0x66,0x73, +/*0028e0*/ 0x65,0x74,0x20,0x2b,0x20,0x31,0x0d,0x0a,0x09,0x09,0x69,0x6e,0x66,0x6f,0x20,0x3d, +/*0028f0*/ 0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x6f, +/*002900*/ 0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43, +/*002910*/ 0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x29,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c, +/*002920*/ 0x20,0x6e,0x6f,0x74,0x20,0x69,0x6e,0x66,0x6f,0x20,0x6f,0x72,0x20,0x66,0x72,0x61, +/*002930*/ 0x6d,0x65,0x5f,0x68,0x61,0x73,0x5f,0x6c,0x69,0x6e,0x65,0x28,0x69,0x6e,0x66,0x6f, +/*002940*/ 0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66,0x20,0x69,0x6e,0x66,0x6f,0x20,0x74, +/*002950*/ 0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73, +/*002960*/ 0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x6f,0x66, +/*002970*/ 0x66,0x73,0x65,0x74,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74, +/*002980*/ 0x65,0x6c,0x6e,0x28,0x22,0x49,0x6e,0x73,0x70,0x65,0x63,0x74,0x69,0x6e,0x67,0x20, +/*002990*/ 0x66,0x72,0x61,0x6d,0x65,0x3a,0x20,0x22,0x2e,0x2e,0x66,0x6f,0x72,0x6d,0x61,0x74, +/*0029a0*/ 0x5f,0x73,0x74,0x61,0x63,0x6b,0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66, +/*0029b0*/ 0x6f,0x28,0x69,0x6e,0x66,0x6f,0x29,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x74, +/*0029c0*/ 0x6f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x28,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f, +/*0029d0*/ 0x5f,0x77,0x68,0x65,0x72,0x65,0x29,0x20,0x74,0x68,0x65,0x6e,0x20,0x77,0x68,0x65, +/*0029e0*/ 0x72,0x65,0x28,0x69,0x6e,0x66,0x6f,0x2c,0x20,0x64,0x62,0x67,0x2e,0x61,0x75,0x74, +/*0029f0*/ 0x6f,0x5f,0x77,0x68,0x65,0x72,0x65,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65, +/*002a00*/ 0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65, +/*002a10*/ 0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63, +/*002a20*/ 0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74, +/*002a30*/ 0x20,0x2b,0x20,0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56, +/*002a40*/ 0x45,0x4c,0x29,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65, +/*002a50*/ 0x6c,0x6e,0x28,0x22,0x41,0x6c,0x72,0x65,0x61,0x64,0x79,0x20,0x61,0x74,0x20,0x74, +/*002a60*/ 0x68,0x65,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x20,0x6f,0x66,0x20,0x74,0x68,0x65, +/*002a70*/ 0x20,0x73,0x74,0x61,0x63,0x6b,0x2e,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d, +/*002a80*/ 0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73, +/*002a90*/ 0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*002aa0*/ 0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x75,0x70,0x28, +/*002ab0*/ 0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6f,0x66,0x66,0x73,0x65,0x74, +/*002ac0*/ 0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74, +/*002ad0*/ 0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*002ae0*/ 0x69,0x6e,0x66,0x6f,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x70,0x65,0x61,0x74, +/*002af0*/ 0x20,0x2d,0x2d,0x20,0x46,0x69,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x6e,0x65,0x78, +/*002b00*/ 0x74,0x20,0x66,0x72,0x61,0x6d,0x65,0x20,0x77,0x69,0x74,0x68,0x20,0x61,0x20,0x66, +/*002b10*/ 0x69,0x6c,0x65,0x2e,0x0d,0x0a,0x09,0x09,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d, +/*002b20*/ 0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2d,0x20,0x31,0x0d,0x0a,0x09,0x09,0x69, +/*002b30*/ 0x66,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3c,0x20,0x73,0x74,0x61,0x63,0x6b, +/*002b40*/ 0x5f,0x74,0x6f,0x70,0x20,0x74,0x68,0x65,0x6e,0x20,0x69,0x6e,0x66,0x6f,0x20,0x3d, +/*002b50*/ 0x20,0x6e,0x69,0x6c,0x3b,0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65,0x6e,0x64,0x0d, +/*002b60*/ 0x0a,0x09,0x09,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e, +/*002b70*/ 0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b, +/*002b80*/ 0x20,0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c, +/*002b90*/ 0x29,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c,0x20,0x66,0x72,0x61,0x6d,0x65,0x5f, +/*002ba0*/ 0x68,0x61,0x73,0x5f,0x6c,0x69,0x6e,0x65,0x28,0x69,0x6e,0x66,0x6f,0x29,0x0d,0x0a, +/*002bb0*/ 0x09,0x0d,0x0a,0x09,0x69,0x66,0x20,0x69,0x6e,0x66,0x6f,0x20,0x74,0x68,0x65,0x6e, +/*002bc0*/ 0x0d,0x0a,0x09,0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63, +/*002bd0*/ 0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x6f,0x66,0x66,0x73,0x65, +/*002be0*/ 0x74,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e, +/*002bf0*/ 0x28,0x22,0x49,0x6e,0x73,0x70,0x65,0x63,0x74,0x69,0x6e,0x67,0x20,0x66,0x72,0x61, +/*002c00*/ 0x6d,0x65,0x3a,0x20,0x22,0x2e,0x2e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x73,0x74, +/*002c10*/ 0x61,0x63,0x6b,0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66,0x6f,0x28,0x69, +/*002c20*/ 0x6e,0x66,0x6f,0x29,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x74,0x6f,0x6e,0x75, +/*002c30*/ 0x6d,0x62,0x65,0x72,0x28,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77,0x68, +/*002c40*/ 0x65,0x72,0x65,0x29,0x20,0x74,0x68,0x65,0x6e,0x20,0x77,0x68,0x65,0x72,0x65,0x28, +/*002c50*/ 0x69,0x6e,0x66,0x6f,0x2c,0x20,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77, +/*002c60*/ 0x68,0x65,0x72,0x65,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65, +/*002c70*/ 0x0d,0x0a,0x09,0x09,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67, +/*002c80*/ 0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69, +/*002c90*/ 0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20, +/*002ca0*/ 0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x29, +/*002cb0*/ 0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28, +/*002cc0*/ 0x22,0x41,0x6c,0x72,0x65,0x61,0x64,0x79,0x20,0x61,0x74,0x20,0x74,0x68,0x65,0x20, +/*002cd0*/ 0x74,0x6f,0x70,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x63,0x6b, +/*002ce0*/ 0x2e,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72, +/*002cf0*/ 0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64, +/*002d00*/ 0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69, +/*002d10*/ 0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x77,0x68,0x65,0x72,0x65,0x28,0x63,0x6f,0x6e, +/*002d20*/ 0x74,0x65,0x78,0x74,0x5f,0x6c,0x69,0x6e,0x65,0x73,0x29,0x0d,0x0a,0x09,0x6c,0x6f, +/*002d30*/ 0x63,0x61,0x6c,0x20,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67, +/*002d40*/ 0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69, +/*002d50*/ 0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20, +/*002d60*/ 0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x29, +/*002d70*/ 0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x69,0x6e,0x66,0x6f,0x20, +/*002d80*/ 0x61,0x6e,0x64,0x20,0x77,0x68,0x65,0x72,0x65,0x28,0x69,0x6e,0x66,0x6f,0x2c,0x20, +/*002d90*/ 0x74,0x6f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x28,0x63,0x6f,0x6e,0x74,0x65,0x78,0x74, +/*002da0*/ 0x5f,0x6c,0x69,0x6e,0x65,0x73,0x29,0x20,0x6f,0x72,0x20,0x35,0x29,0x29,0x0d,0x0a, +/*002db0*/ 0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e, +/*002dc0*/ 0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x74,0x72,0x61,0x63,0x65,0x28, +/*002dd0*/ 0x29,0x0d,0x0a,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28, +/*002de0*/ 0x22,0x49,0x6e,0x73,0x70,0x65,0x63,0x74,0x69,0x6e,0x67,0x20,0x66,0x72,0x61,0x6d, +/*002df0*/ 0x65,0x20,0x25,0x64,0x22,0x2c,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73, +/*002e00*/ 0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2d,0x20,0x73,0x74, +/*002e10*/ 0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*002e20*/ 0x20,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x74,0x72, +/*002e30*/ 0x75,0x65,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69, +/*002e40*/ 0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69, +/*002e50*/ 0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x20,0x2b,0x20, +/*002e60*/ 0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x20, +/*002e70*/ 0x2b,0x20,0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x69, +/*002e80*/ 0x6e,0x66,0x6f,0x20,0x74,0x68,0x65,0x6e,0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65, +/*002e90*/ 0x6e,0x64,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*002ea0*/ 0x69,0x73,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x5f,0x66,0x72,0x61,0x6d,0x65, +/*002eb0*/ 0x20,0x3d,0x20,0x28,0x69,0x20,0x2b,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f, +/*002ec0*/ 0x70,0x20,0x3d,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65, +/*002ed0*/ 0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x29,0x0d,0x0a,0x09,0x09,0x6c,0x6f, +/*002ee0*/ 0x63,0x61,0x6c,0x20,0x74,0x61,0x62,0x5f,0x6f,0x72,0x5f,0x63,0x61,0x72,0x65,0x74, +/*002ef0*/ 0x20,0x3d,0x20,0x28,0x69,0x73,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x5f,0x66, +/*002f00*/ 0x72,0x61,0x6d,0x65,0x20,0x61,0x6e,0x64,0x20,0x20,0x47,0x52,0x45,0x45,0x4e,0x5f, +/*002f10*/ 0x43,0x41,0x52,0x45,0x54,0x20,0x6f,0x72,0x20,0x22,0x20,0x20,0x20,0x20,0x22,0x29, +/*002f20*/ 0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28, +/*002f30*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x47,0x52,0x41,0x59,0x2e,0x2e,0x22,0x25,0x20,0x34, +/*002f40*/ 0x64,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e, +/*002f50*/ 0x2e,0x74,0x61,0x62,0x5f,0x6f,0x72,0x5f,0x63,0x61,0x72,0x65,0x74,0x2e,0x2e,0x22, +/*002f60*/ 0x25,0x73,0x22,0x2c,0x20,0x69,0x2c,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x73, +/*002f70*/ 0x74,0x61,0x63,0x6b,0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66,0x6f,0x28, +/*002f80*/ 0x69,0x6e,0x66,0x6f,0x29,0x29,0x0d,0x0a,0x09,0x09,0x69,0x20,0x3d,0x20,0x69,0x20, +/*002f90*/ 0x2b,0x20,0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72, +/*002fa0*/ 0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64, +/*002fb0*/ 0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69, +/*002fc0*/ 0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x73,0x28,0x29,0x0d, +/*002fd0*/ 0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73, +/*002fe0*/ 0x20,0x3d,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67, +/*002ff0*/ 0x73,0x28,0x31,0x2c,0x20,0x66,0x61,0x6c,0x73,0x65,0x29,0x0d,0x0a,0x09,0x0d,0x0a, +/*003000*/ 0x09,0x2d,0x2d,0x20,0x47,0x65,0x74,0x20,0x61,0x6c,0x6c,0x20,0x74,0x68,0x65,0x20, +/*003010*/ 0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67, +/*003020*/ 0x20,0x6e,0x61,0x6d,0x65,0x73,0x20,0x61,0x6e,0x64,0x20,0x73,0x6f,0x72,0x74,0x20, +/*003030*/ 0x74,0x68,0x65,0x6d,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6b,0x65,0x79, +/*003040*/ 0x73,0x20,0x3d,0x20,0x7b,0x7d,0x0d,0x0a,0x09,0x66,0x6f,0x72,0x20,0x6b,0x2c,0x20, +/*003050*/ 0x5f,0x20,0x69,0x6e,0x20,0x70,0x61,0x69,0x72,0x73,0x28,0x62,0x69,0x6e,0x64,0x69, +/*003060*/ 0x6e,0x67,0x73,0x29,0x20,0x64,0x6f,0x20,0x74,0x61,0x62,0x6c,0x65,0x2e,0x69,0x6e, +/*003070*/ 0x73,0x65,0x72,0x74,0x28,0x6b,0x65,0x79,0x73,0x2c,0x20,0x6b,0x29,0x20,0x65,0x6e, +/*003080*/ 0x64,0x0d,0x0a,0x09,0x74,0x61,0x62,0x6c,0x65,0x2e,0x73,0x6f,0x72,0x74,0x28,0x6b, +/*003090*/ 0x65,0x79,0x73,0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x66,0x6f,0x72,0x20,0x5f,0x2c, +/*0030a0*/ 0x20,0x6b,0x20,0x69,0x6e,0x20,0x69,0x70,0x61,0x69,0x72,0x73,0x28,0x6b,0x65,0x79, +/*0030b0*/ 0x73,0x29,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x76, +/*0030c0*/ 0x20,0x3d,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x5b,0x6b,0x5d,0x0d,0x0a, +/*0030d0*/ 0x09,0x09,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x53,0x6b,0x69,0x70,0x20,0x74,0x68, +/*0030e0*/ 0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x20,0x6f,0x62,0x6a,0x65,0x63, +/*0030f0*/ 0x74,0x20,0x69,0x74,0x73,0x65,0x6c,0x66,0x2c,0x20,0x22,0x28,0x2a,0x69,0x6e,0x74, +/*003100*/ 0x65,0x72,0x6e,0x61,0x6c,0x29,0x22,0x20,0x76,0x61,0x6c,0x75,0x65,0x73,0x2c,0x20, +/*003110*/ 0x61,0x6e,0x64,0x20,0x4c,0x75,0x61,0x20,0x35,0x2e,0x32,0x27,0x73,0x20,0x5f,0x45, +/*003120*/ 0x4e,0x56,0x20,0x6f,0x62,0x6a,0x65,0x63,0x74,0x2e,0x0d,0x0a,0x09,0x09,0x69,0x66, +/*003130*/ 0x20,0x6e,0x6f,0x74,0x20,0x72,0x61,0x77,0x65,0x71,0x75,0x61,0x6c,0x28,0x76,0x2c, +/*003140*/ 0x20,0x64,0x62,0x67,0x29,0x20,0x61,0x6e,0x64,0x20,0x6b,0x20,0x7e,0x3d,0x20,0x22, +/*003150*/ 0x5f,0x45,0x4e,0x56,0x22,0x20,0x61,0x6e,0x64,0x20,0x6e,0x6f,0x74,0x20,0x6b,0x3a, +/*003160*/ 0x6d,0x61,0x74,0x63,0x68,0x28,0x22,0x25,0x28,0x2e,0x2a,0x25,0x29,0x22,0x29,0x20, +/*003170*/ 0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69, +/*003180*/ 0x74,0x65,0x6c,0x6e,0x28,0x22,0x20,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*003190*/ 0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x6b,0x2e,0x2e,0x20,0x47,0x52,0x45,0x45,0x4e, +/*0031a0*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74, +/*0031b0*/ 0x74,0x79,0x28,0x76,0x29,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09, +/*0031c0*/ 0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*0031d0*/ 0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f, +/*0031e0*/ 0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6d,0x64, +/*0031f0*/ 0x5f,0x68,0x65,0x6c,0x70,0x28,0x29,0x0d,0x0a,0x09,0x64,0x62,0x67,0x2e,0x77,0x72, +/*003200*/ 0x69,0x74,0x65,0x28,0x22,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*003210*/ 0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x3c,0x72,0x65,0x74,0x75, +/*003220*/ 0x72,0x6e,0x3e,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45, +/*003230*/ 0x54,0x2e,0x2e,0x22,0x72,0x65,0x2d,0x72,0x75,0x6e,0x20,0x6c,0x61,0x73,0x74,0x20, +/*003240*/ 0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e, +/*003250*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x63, +/*003260*/ 0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e, +/*003270*/ 0x2e,0x22,0x28,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x29,0x22,0x2e,0x2e,0x47,0x52, +/*003280*/ 0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x63,0x6f,0x6e,0x74, +/*003290*/ 0x69,0x6e,0x75,0x65,0x20,0x65,0x78,0x65,0x63,0x75,0x74,0x69,0x6f,0x6e,0x5c,0x6e, +/*0032a0*/ 0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55, +/*0032b0*/ 0x45,0x2e,0x2e,0x22,0x20,0x20,0x73,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*0032c0*/ 0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x74,0x65,0x70,0x29,0x22,0x2e, +/*0032d0*/ 0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x73, +/*0032e0*/ 0x74,0x65,0x70,0x20,0x66,0x6f,0x72,0x77,0x61,0x72,0x64,0x20,0x62,0x79,0x20,0x6f, +/*0032f0*/ 0x6e,0x65,0x20,0x6c,0x69,0x6e,0x65,0x20,0x28,0x69,0x6e,0x74,0x6f,0x20,0x66,0x75, +/*003300*/ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x29,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e, +/*003310*/ 0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20, +/*003320*/ 0x6e,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57, +/*003330*/ 0x2e,0x2e,0x22,0x28,0x65,0x78,0x74,0x29,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e, +/*003340*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x73,0x74,0x65,0x70,0x20,0x66,0x6f, +/*003350*/ 0x72,0x77,0x61,0x72,0x64,0x20,0x62,0x79,0x20,0x6f,0x6e,0x65,0x20,0x6c,0x69,0x6e, +/*003360*/ 0x65,0x20,0x28,0x73,0x6b,0x69,0x70,0x70,0x69,0x6e,0x67,0x20,0x6f,0x76,0x65,0x72, +/*003370*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x29,0x5c,0x6e,0x22,0x0d,0x0a, +/*003380*/ 0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e, +/*003390*/ 0x22,0x20,0x20,0x66,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*0033a0*/ 0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x69,0x6e,0x69,0x73,0x68,0x29,0x22,0x2e,0x2e, +/*0033b0*/ 0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x73,0x74, +/*0033c0*/ 0x65,0x70,0x20,0x66,0x6f,0x72,0x77,0x61,0x72,0x64,0x20,0x75,0x6e,0x74,0x69,0x6c, +/*0033d0*/ 0x20,0x65,0x78,0x69,0x74,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72, +/*0033e0*/ 0x72,0x65,0x6e,0x74,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x5c,0x6e,0x22, +/*0033f0*/ 0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45, +/*003400*/ 0x2e,0x2e,0x22,0x20,0x20,0x75,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59, +/*003410*/ 0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x70,0x29,0x22,0x2e,0x2e,0x47,0x52, +/*003420*/ 0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x6d,0x6f,0x76,0x65, +/*003430*/ 0x20,0x75,0x70,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x62,0x79, +/*003440*/ 0x20,0x6f,0x6e,0x65,0x20,0x66,0x72,0x61,0x6d,0x65,0x5c,0x6e,0x22,0x0d,0x0a,0x09, +/*003450*/ 0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22, +/*003460*/ 0x20,0x20,0x64,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c, +/*003470*/ 0x4f,0x57,0x2e,0x2e,0x22,0x28,0x6f,0x77,0x6e,0x29,0x22,0x2e,0x2e,0x47,0x52,0x45, +/*003480*/ 0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x6d,0x6f,0x76,0x65,0x20, +/*003490*/ 0x64,0x6f,0x77,0x6e,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x62, +/*0034a0*/ 0x79,0x20,0x6f,0x6e,0x65,0x20,0x66,0x72,0x61,0x6d,0x65,0x5c,0x6e,0x22,0x0d,0x0a, +/*0034b0*/ 0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e, +/*0034c0*/ 0x22,0x20,0x20,0x77,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*0034d0*/ 0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x68,0x65,0x72,0x65,0x29,0x20,0x22,0x2e,0x2e, +/*0034e0*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x5b,0x6c,0x69, +/*0034f0*/ 0x6e,0x65,0x20,0x63,0x6f,0x75,0x6e,0x74,0x5d,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45, +/*003500*/ 0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x70,0x72,0x69,0x6e,0x74,0x20, +/*003510*/ 0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x63,0x6f,0x64,0x65,0x20,0x61,0x72,0x6f,0x75, +/*003520*/ 0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x20,0x6c, +/*003530*/ 0x69,0x6e,0x65,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*003540*/ 0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x65,0x22,0x2e,0x2e,0x43, +/*003550*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x76, +/*003560*/ 0x61,0x6c,0x29,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55, +/*003570*/ 0x45,0x2e,0x2e,0x22,0x5b,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x5d,0x22, +/*003580*/ 0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22, +/*003590*/ 0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x74, +/*0035a0*/ 0x65,0x6d,0x65,0x6e,0x74,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f, +/*0035b0*/ 0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x70,0x22,0x2e, +/*0035c0*/ 0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22, +/*0035d0*/ 0x28,0x72,0x69,0x6e,0x74,0x29,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*0035e0*/ 0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x5b,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69, +/*0035f0*/ 0x6f,0x6e,0x5d,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45, +/*003600*/ 0x54,0x2e,0x2e,0x22,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x20,0x74,0x68,0x65,0x20, +/*003610*/ 0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x20,0x61,0x6e,0x64,0x20,0x70, +/*003620*/ 0x72,0x69,0x6e,0x74,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x5c, +/*003630*/ 0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c, +/*003640*/ 0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x74,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*003650*/ 0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x72,0x61,0x63,0x65,0x29, +/*003660*/ 0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e, +/*003670*/ 0x22,0x70,0x72,0x69,0x6e,0x74,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x63,0x6b, +/*003680*/ 0x20,0x74,0x72,0x61,0x63,0x65,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43, +/*003690*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x6c,0x22, +/*0036a0*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e, +/*0036b0*/ 0x22,0x28,0x6f,0x63,0x61,0x6c,0x73,0x29,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e, +/*0036c0*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x70,0x72,0x69,0x6e,0x74,0x20,0x74, +/*0036d0*/ 0x68,0x65,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x61,0x72,0x67,0x75, +/*0036e0*/ 0x6d,0x65,0x6e,0x74,0x73,0x2c,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x73,0x20,0x61,0x6e, +/*0036f0*/ 0x64,0x20,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x73,0x2e,0x5c,0x6e,0x22,0x0d,0x0a, +/*003700*/ 0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e, +/*003710*/ 0x22,0x20,0x20,0x68,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*003720*/ 0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x65,0x6c,0x70,0x29,0x22,0x2e,0x2e,0x47,0x52, +/*003730*/ 0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x70,0x72,0x69,0x6e, +/*003740*/ 0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x5c,0x6e, +/*003750*/ 0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55, +/*003760*/ 0x45,0x2e,0x2e,0x22,0x20,0x20,0x71,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*003770*/ 0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x75,0x69,0x74,0x29,0x22,0x2e, +/*003780*/ 0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x68, +/*003790*/ 0x61,0x6c,0x74,0x20,0x65,0x78,0x65,0x63,0x75,0x74,0x69,0x6f,0x6e,0x5c,0x6e,0x22, +/*0037a0*/ 0x0d,0x0a,0x09,0x29,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61, +/*0037b0*/ 0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61, +/*0037c0*/ 0x6c,0x20,0x6c,0x61,0x73,0x74,0x5f,0x63,0x6d,0x64,0x20,0x3d,0x20,0x66,0x61,0x6c, +/*0037d0*/ 0x73,0x65,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x6f,0x6d,0x6d, +/*0037e0*/ 0x61,0x6e,0x64,0x73,0x20,0x3d,0x20,0x7b,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x63,0x24, +/*0037f0*/ 0x22,0x5d,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x20, +/*003800*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x20,0x65,0x6e,0x64,0x2c, +/*003810*/ 0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x73,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64, +/*003820*/ 0x5f,0x73,0x74,0x65,0x70,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x6e,0x24,0x22,0x5d, +/*003830*/ 0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x6e,0x65,0x78,0x74,0x2c,0x0d,0x0a,0x09,0x5b, +/*003840*/ 0x22,0x5e,0x66,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x66,0x69,0x6e, +/*003850*/ 0x69,0x73,0x68,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x70,0x25,0x73,0x2b,0x28,0x2e, +/*003860*/ 0x2a,0x29,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x70,0x72,0x69,0x6e, +/*003870*/ 0x74,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x65,0x25,0x73,0x2b,0x28,0x2e,0x2a,0x29, +/*003880*/ 0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x65,0x76,0x61,0x6c,0x2c,0x0d, +/*003890*/ 0x0a,0x09,0x5b,0x22,0x5e,0x75,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f, +/*0038a0*/ 0x75,0x70,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x64,0x24,0x22,0x5d,0x20,0x3d,0x20, +/*0038b0*/ 0x63,0x6d,0x64,0x5f,0x64,0x6f,0x77,0x6e,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x77, +/*0038c0*/ 0x25,0x73,0x2a,0x28,0x25,0x64,0x2a,0x29,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d, +/*0038d0*/ 0x64,0x5f,0x77,0x68,0x65,0x72,0x65,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x74,0x24, +/*0038e0*/ 0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x74,0x72,0x61,0x63,0x65,0x2c,0x0d, +/*0038f0*/ 0x0a,0x09,0x5b,0x22,0x5e,0x6c,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f, +/*003900*/ 0x6c,0x6f,0x63,0x61,0x6c,0x73,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x68,0x24,0x22, +/*003910*/ 0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x68,0x65,0x6c,0x70,0x2c,0x0d,0x0a,0x09, +/*003920*/ 0x5b,0x22,0x5e,0x71,0x24,0x22,0x5d,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69, +/*003930*/ 0x6f,0x6e,0x28,0x29,0x20,0x64,0x62,0x67,0x2e,0x65,0x78,0x69,0x74,0x28,0x30,0x29, +/*003940*/ 0x3b,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x20,0x65,0x6e, +/*003950*/ 0x64,0x2c,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66, +/*003960*/ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6d,0x61,0x74,0x63,0x68,0x5f,0x63,0x6f, +/*003970*/ 0x6d,0x6d,0x61,0x6e,0x64,0x28,0x6c,0x69,0x6e,0x65,0x29,0x0d,0x0a,0x09,0x66,0x6f, +/*003980*/ 0x72,0x20,0x70,0x61,0x74,0x2c,0x20,0x66,0x75,0x6e,0x63,0x20,0x69,0x6e,0x20,0x70, +/*003990*/ 0x61,0x69,0x72,0x73,0x28,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x73,0x29,0x20,0x64, +/*0039a0*/ 0x6f,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x75,0x72,0x6e,0x20,0x74, +/*0039b0*/ 0x68,0x65,0x20,0x6d,0x61,0x74,0x63,0x68,0x69,0x6e,0x67,0x20,0x63,0x6f,0x6d,0x6d, +/*0039c0*/ 0x61,0x6e,0x64,0x20,0x61,0x6e,0x64,0x20,0x63,0x61,0x70,0x74,0x75,0x72,0x65,0x20, +/*0039d0*/ 0x61,0x72,0x67,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20, +/*0039e0*/ 0x6c,0x69,0x6e,0x65,0x3a,0x66,0x69,0x6e,0x64,0x28,0x70,0x61,0x74,0x29,0x20,0x74, +/*0039f0*/ 0x68,0x65,0x6e,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x75,0x6e,0x63,0x2c, +/*003a00*/ 0x20,0x6c,0x69,0x6e,0x65,0x3a,0x6d,0x61,0x74,0x63,0x68,0x28,0x70,0x61,0x74,0x29, +/*003a10*/ 0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*003a20*/ 0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x52,0x75,0x6e,0x20,0x61,0x20,0x63,0x6f,0x6d,0x6d, +/*003a30*/ 0x61,0x6e,0x64,0x20,0x6c,0x69,0x6e,0x65,0x0d,0x0a,0x2d,0x2d,0x20,0x52,0x65,0x74, +/*003a40*/ 0x75,0x72,0x6e,0x73,0x20,0x74,0x72,0x75,0x65,0x20,0x69,0x66,0x20,0x74,0x68,0x65, +/*003a50*/ 0x20,0x52,0x45,0x50,0x4c,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x65,0x78,0x69, +/*003a60*/ 0x74,0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x6f,0x6b,0x20,0x66, +/*003a70*/ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x0d, +/*003a80*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*003a90*/ 0x72,0x75,0x6e,0x5f,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x28,0x6c,0x69,0x6e,0x65, +/*003aa0*/ 0x29,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x47,0x44,0x42,0x2f,0x4c,0x4c,0x44,0x42,0x20, +/*003ab0*/ 0x65,0x78,0x69,0x74,0x20,0x6f,0x6e,0x20,0x63,0x74,0x72,0x6c,0x2d,0x64,0x0d,0x0a, +/*003ac0*/ 0x09,0x69,0x66,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20, +/*003ad0*/ 0x74,0x68,0x65,0x6e,0x20,0x64,0x62,0x67,0x2e,0x65,0x78,0x69,0x74,0x28,0x31,0x29, +/*003ae0*/ 0x3b,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x20,0x65,0x6e, +/*003af0*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x52,0x65,0x2d,0x65,0x78,0x65, +/*003b00*/ 0x63,0x75,0x74,0x65,0x20,0x74,0x68,0x65,0x20,0x6c,0x61,0x73,0x74,0x20,0x63,0x6f, +/*003b10*/ 0x6d,0x6d,0x61,0x6e,0x64,0x20,0x69,0x66,0x20,0x79,0x6f,0x75,0x20,0x70,0x72,0x65, +/*003b20*/ 0x73,0x73,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x2e,0x0d,0x0a,0x09,0x69,0x66,0x20, +/*003b30*/ 0x6c,0x69,0x6e,0x65,0x20,0x3d,0x3d,0x20,0x22,0x22,0x20,0x74,0x68,0x65,0x6e,0x20, +/*003b40*/ 0x6c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x6c,0x61,0x73,0x74,0x5f,0x63,0x6d,0x64,0x20, +/*003b50*/ 0x6f,0x72,0x20,0x22,0x68,0x22,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09, +/*003b60*/ 0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x2c,0x20,0x63, +/*003b70*/ 0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x5f,0x61,0x72,0x67,0x20,0x3d,0x20,0x6d,0x61,0x74, +/*003b80*/ 0x63,0x68,0x5f,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x28,0x6c,0x69,0x6e,0x65,0x29, +/*003b90*/ 0x0d,0x0a,0x09,0x69,0x66,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x74,0x68, +/*003ba0*/ 0x65,0x6e,0x0d,0x0a,0x09,0x09,0x6c,0x61,0x73,0x74,0x5f,0x63,0x6d,0x64,0x20,0x3d, +/*003bb0*/ 0x20,0x6c,0x69,0x6e,0x65,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x75,0x6e,0x70,0x61, +/*003bc0*/ 0x63,0x6b,0x28,0x7b,0x2e,0x2e,0x2e,0x7d,0x29,0x20,0x70,0x72,0x65,0x76,0x65,0x6e, +/*003bd0*/ 0x74,0x73,0x20,0x74,0x61,0x69,0x6c,0x20,0x63,0x61,0x6c,0x6c,0x20,0x65,0x6c,0x69, +/*003be0*/ 0x6d,0x69,0x6e,0x61,0x74,0x69,0x6f,0x6e,0x20,0x73,0x6f,0x20,0x74,0x68,0x65,0x20, +/*003bf0*/ 0x73,0x74,0x61,0x63,0x6b,0x20,0x66,0x72,0x61,0x6d,0x65,0x20,0x69,0x6e,0x64,0x69, +/*003c00*/ 0x63,0x65,0x73,0x20,0x61,0x72,0x65,0x20,0x70,0x72,0x65,0x64,0x69,0x63,0x74,0x61, +/*003c10*/ 0x62,0x6c,0x65,0x2e,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x75, +/*003c20*/ 0x6e,0x70,0x61,0x63,0x6b,0x28,0x7b,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x28,0x63, +/*003c30*/ 0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x5f,0x61,0x72,0x67,0x29,0x7d,0x29,0x0d,0x0a,0x09, +/*003c40*/ 0x65,0x6c,0x73,0x65,0x69,0x66,0x20,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f, +/*003c50*/ 0x65,0x76,0x61,0x6c,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74, +/*003c60*/ 0x75,0x72,0x6e,0x20,0x75,0x6e,0x70,0x61,0x63,0x6b,0x28,0x7b,0x63,0x6d,0x64,0x5f, +/*003c70*/ 0x65,0x76,0x61,0x6c,0x28,0x6c,0x69,0x6e,0x65,0x29,0x7d,0x29,0x0d,0x0a,0x09,0x65, +/*003c80*/ 0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65, +/*003c90*/ 0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45, +/*003ca0*/ 0x72,0x72,0x6f,0x72,0x3a,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*003cb0*/ 0x53,0x45,0x54,0x2e,0x2e,0x22,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x27, +/*003cc0*/ 0x25,0x73,0x27,0x20,0x6e,0x6f,0x74,0x20,0x72,0x65,0x63,0x6f,0x67,0x6e,0x69,0x7a, +/*003cd0*/ 0x65,0x64,0x2e,0x5c,0x6e,0x54,0x79,0x70,0x65,0x20,0x27,0x68,0x27,0x20,0x61,0x6e, +/*003ce0*/ 0x64,0x20,0x70,0x72,0x65,0x73,0x73,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66, +/*003cf0*/ 0x6f,0x72,0x20,0x61,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x6c,0x69,0x73, +/*003d00*/ 0x74,0x2e,0x22,0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x0d,0x0a,0x09,0x09,0x72,0x65, +/*003d10*/ 0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x65,0x6e,0x64, +/*003d20*/ 0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x72,0x65,0x70,0x6c,0x20,0x3d,0x20, +/*003d30*/ 0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x72,0x65,0x61,0x73,0x6f,0x6e,0x29, +/*003d40*/ 0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x53,0x6b,0x69,0x70,0x20,0x66,0x72,0x61,0x6d,0x65, +/*003d50*/ 0x73,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x73,0x6f,0x75,0x72,0x63,0x65, +/*003d60*/ 0x20,0x69,0x6e,0x66,0x6f,0x2e,0x0d,0x0a,0x09,0x77,0x68,0x69,0x6c,0x65,0x20,0x6e, +/*003d70*/ 0x6f,0x74,0x20,0x66,0x72,0x61,0x6d,0x65,0x5f,0x68,0x61,0x73,0x5f,0x6c,0x69,0x6e, +/*003d80*/ 0x65,0x28,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28, +/*003d90*/ 0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66, +/*003da0*/ 0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b, +/*003db0*/ 0x5f,0x4c,0x45,0x56,0x45,0x4c,0x20,0x2d,0x20,0x33,0x29,0x29,0x20,0x64,0x6f,0x0d, +/*003dc0*/ 0x0a,0x09,0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74, +/*003dd0*/ 0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f, +/*003de0*/ 0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b, +/*003df0*/ 0x20,0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x6c,0x6f, +/*003e00*/ 0x63,0x61,0x6c,0x20,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67, +/*003e10*/ 0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69, +/*003e20*/ 0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20, +/*003e30*/ 0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x20, +/*003e40*/ 0x2d,0x20,0x33,0x29,0x0d,0x0a,0x09,0x72,0x65,0x61,0x73,0x6f,0x6e,0x20,0x3d,0x20, +/*003e50*/ 0x72,0x65,0x61,0x73,0x6f,0x6e,0x20,0x61,0x6e,0x64,0x20,0x28,0x43,0x4f,0x4c,0x4f, +/*003e60*/ 0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x62,0x72,0x65,0x61,0x6b, +/*003e70*/ 0x20,0x76,0x69,0x61,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*003e80*/ 0x44,0x2e,0x2e,0x72,0x65,0x61,0x73,0x6f,0x6e,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e, +/*003e90*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x29,0x20,0x6f,0x72,0x20,0x22,0x22,0x0d,0x0a,0x09, +/*003ea0*/ 0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x72,0x65,0x61,0x73, +/*003eb0*/ 0x6f,0x6e,0x2e,0x2e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x73,0x74,0x61,0x63,0x6b, +/*003ec0*/ 0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66,0x6f,0x28,0x69,0x6e,0x66,0x6f, +/*003ed0*/ 0x29,0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66,0x20,0x74,0x6f,0x6e,0x75,0x6d, +/*003ee0*/ 0x62,0x65,0x72,0x28,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77,0x68,0x65, +/*003ef0*/ 0x72,0x65,0x29,0x20,0x74,0x68,0x65,0x6e,0x20,0x77,0x68,0x65,0x72,0x65,0x28,0x69, +/*003f00*/ 0x6e,0x66,0x6f,0x2c,0x20,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77,0x68, +/*003f10*/ 0x65,0x72,0x65,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65, +/*003f20*/ 0x70,0x65,0x61,0x74,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x75, +/*003f30*/ 0x63,0x63,0x65,0x73,0x73,0x2c,0x20,0x64,0x6f,0x6e,0x65,0x2c,0x20,0x68,0x6f,0x6f, +/*003f40*/ 0x6b,0x20,0x3d,0x20,0x70,0x63,0x61,0x6c,0x6c,0x28,0x72,0x75,0x6e,0x5f,0x63,0x6f, +/*003f50*/ 0x6d,0x6d,0x61,0x6e,0x64,0x2c,0x20,0x64,0x62,0x67,0x2e,0x72,0x65,0x61,0x64,0x28, +/*003f60*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75, +/*003f70*/ 0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x3e,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c, +/*003f80*/ 0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x29,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66, +/*003f90*/ 0x20,0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09, +/*003fa0*/ 0x09,0x09,0x64,0x65,0x62,0x75,0x67,0x2e,0x73,0x65,0x74,0x68,0x6f,0x6f,0x6b,0x28, +/*003fb0*/ 0x68,0x6f,0x6f,0x6b,0x20,0x61,0x6e,0x64,0x20,0x68,0x6f,0x6f,0x6b,0x28,0x30,0x29, +/*003fc0*/ 0x2c,0x20,0x22,0x63,0x72,0x6c,0x22,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6c,0x73,0x65, +/*003fd0*/ 0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6d,0x65,0x73,0x73,0x61, +/*003fe0*/ 0x67,0x65,0x20,0x3d,0x20,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e, +/*003ff0*/ 0x22,0x49,0x4e,0x54,0x45,0x52,0x4e,0x41,0x4c,0x20,0x44,0x45,0x42,0x55,0x47,0x47, +/*004000*/ 0x45,0x52,0x2e,0x4c,0x55,0x41,0x20,0x45,0x52,0x52,0x4f,0x52,0x2e,0x20,0x41,0x42, +/*004010*/ 0x4f,0x52,0x54,0x49,0x4e,0x47,0x5c,0x6e,0x3a,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*004020*/ 0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x20,0x22,0x2e,0x2e,0x64,0x6f, +/*004030*/ 0x6e,0x65,0x0d,0x0a,0x09,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65, +/*004040*/ 0x6c,0x6e,0x28,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*004050*/ 0x65,0x72,0x72,0x6f,0x72,0x28,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a, +/*004060*/ 0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c,0x20,0x64,0x6f, +/*004070*/ 0x6e,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x4d,0x61, +/*004080*/ 0x6b,0x65,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x20, +/*004090*/ 0x6f,0x62,0x6a,0x65,0x63,0x74,0x20,0x63,0x61,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x20, +/*0040a0*/ 0x6c,0x69,0x6b,0x65,0x20,0x61,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x2e, +/*0040b0*/ 0x0d,0x0a,0x64,0x62,0x67,0x20,0x3d,0x20,0x73,0x65,0x74,0x6d,0x65,0x74,0x61,0x74, +/*0040c0*/ 0x61,0x62,0x6c,0x65,0x28,0x7b,0x7d,0x2c,0x20,0x7b,0x0d,0x0a,0x09,0x5f,0x5f,0x63, +/*0040d0*/ 0x61,0x6c,0x6c,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x5f, +/*0040e0*/ 0x2c,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x74,0x6f,0x70, +/*0040f0*/ 0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x2c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x29, +/*004100*/ 0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e, +/*004110*/ 0x20,0x74,0x68,0x65,0x6e,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x65,0x6e,0x64, +/*004120*/ 0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x74,0x6f,0x70,0x5f,0x6f,0x66,0x66,0x73, +/*004130*/ 0x65,0x74,0x20,0x3d,0x20,0x28,0x74,0x6f,0x70,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74, +/*004140*/ 0x20,0x6f,0x72,0x20,0x30,0x29,0x0d,0x0a,0x09,0x09,0x73,0x74,0x61,0x63,0x6b,0x5f, +/*004150*/ 0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d, +/*004160*/ 0x20,0x74,0x6f,0x70,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x0d,0x0a,0x09,0x09,0x73, +/*004170*/ 0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x20,0x3d,0x20,0x74,0x6f,0x70,0x5f,0x6f, +/*004180*/ 0x66,0x66,0x73,0x65,0x74,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x64,0x65,0x62, +/*004190*/ 0x75,0x67,0x2e,0x73,0x65,0x74,0x68,0x6f,0x6f,0x6b,0x28,0x68,0x6f,0x6f,0x6b,0x5f, +/*0041a0*/ 0x6e,0x65,0x78,0x74,0x28,0x31,0x2c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x6f, +/*0041b0*/ 0x72,0x20,0x22,0x64,0x62,0x67,0x28,0x29,0x22,0x29,0x2c,0x20,0x22,0x63,0x72,0x6c, +/*0041c0*/ 0x22,0x29,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x0d,0x0a,0x09,0x65, +/*0041d0*/ 0x6e,0x64,0x2c,0x0d,0x0a,0x7d,0x29,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x45,0x78, +/*0041e0*/ 0x70,0x6f,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65, +/*0041f0*/ 0x72,0x27,0x73,0x20,0x49,0x4f,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73, +/*004200*/ 0x2e,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x72,0x65,0x61,0x64,0x20,0x3d,0x20,0x64,0x62, +/*004210*/ 0x67,0x5f,0x72,0x65,0x61,0x64,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x77,0x72,0x69,0x74, +/*004220*/ 0x65,0x20,0x3d,0x20,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x0d,0x0a,0x64, +/*004230*/ 0x62,0x67,0x2e,0x73,0x68,0x6f,0x72,0x74,0x65,0x6e,0x5f,0x70,0x61,0x74,0x68,0x20, +/*004240*/ 0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x70,0x61,0x74,0x68, +/*004250*/ 0x29,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x70,0x61,0x74,0x68,0x20,0x65,0x6e, +/*004260*/ 0x64,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x65,0x78,0x69,0x74,0x20,0x3d,0x20,0x66,0x75, +/*004270*/ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x65,0x72,0x72,0x29,0x20,0x6f,0x73,0x2e,0x65, +/*004280*/ 0x78,0x69,0x74,0x28,0x65,0x72,0x72,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a, +/*004290*/ 0x64,0x62,0x67,0x2e,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x20,0x3d,0x20,0x64,0x62, +/*0042a0*/ 0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x0d,0x0a,0x0d,0x0a,0x64,0x62,0x67, +/*0042b0*/ 0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x5f,0x64,0x65,0x70,0x74,0x68,0x20,0x3d,0x20, +/*0042c0*/ 0x33,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x20,0x3d,0x20, +/*0042d0*/ 0x70,0x72,0x65,0x74,0x74,0x79,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x70,0x70,0x20,0x3d, +/*0042e0*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x76,0x61,0x6c,0x75,0x65,0x2c, +/*0042f0*/ 0x20,0x64,0x65,0x70,0x74,0x68,0x29,0x20,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74, +/*004300*/ 0x65,0x6c,0x6e,0x28,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x28,0x76, +/*004310*/ 0x61,0x6c,0x75,0x65,0x2c,0x20,0x64,0x65,0x70,0x74,0x68,0x29,0x29,0x20,0x65,0x6e, +/*004320*/ 0x64,0x0d,0x0a,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77,0x68, +/*004330*/ 0x65,0x72,0x65,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x64,0x62,0x67, +/*004340*/ 0x2e,0x61,0x75,0x74,0x6f,0x5f,0x65,0x76,0x61,0x6c,0x20,0x3d,0x20,0x66,0x61,0x6c, +/*004350*/ 0x73,0x65,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6c,0x75,0x61,0x5f, +/*004360*/ 0x65,0x72,0x72,0x6f,0x72,0x2c,0x20,0x6c,0x75,0x61,0x5f,0x61,0x73,0x73,0x65,0x72, +/*004370*/ 0x74,0x20,0x3d,0x20,0x65,0x72,0x72,0x6f,0x72,0x2c,0x20,0x61,0x73,0x73,0x65,0x72, +/*004380*/ 0x74,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x57,0x6f,0x72,0x6b,0x73,0x20,0x6c,0x69, +/*004390*/ 0x6b,0x65,0x20,0x65,0x72,0x72,0x6f,0x72,0x28,0x29,0x2c,0x20,0x62,0x75,0x74,0x20, +/*0043a0*/ 0x69,0x6e,0x76,0x6f,0x6b,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75, +/*0043b0*/ 0x67,0x67,0x65,0x72,0x2e,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*0043c0*/ 0x64,0x62,0x67,0x2e,0x65,0x72,0x72,0x6f,0x72,0x28,0x65,0x72,0x72,0x2c,0x20,0x6c, +/*0043d0*/ 0x65,0x76,0x65,0x6c,0x29,0x0d,0x0a,0x09,0x6c,0x65,0x76,0x65,0x6c,0x20,0x3d,0x20, +/*0043e0*/ 0x6c,0x65,0x76,0x65,0x6c,0x20,0x6f,0x72,0x20,0x31,0x0d,0x0a,0x09,0x64,0x62,0x67, +/*0043f0*/ 0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52, +/*004400*/ 0x45,0x44,0x2e,0x2e,0x22,0x45,0x52,0x52,0x4f,0x52,0x3a,0x20,0x22,0x2e,0x2e,0x43, +/*004410*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x64,0x62,0x67,0x2e, +/*004420*/ 0x70,0x72,0x65,0x74,0x74,0x79,0x28,0x65,0x72,0x72,0x29,0x29,0x0d,0x0a,0x09,0x64, +/*004430*/ 0x62,0x67,0x28,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x6c,0x65,0x76,0x65,0x6c,0x2c, +/*004440*/ 0x20,0x22,0x64,0x62,0x67,0x2e,0x65,0x72,0x72,0x6f,0x72,0x28,0x29,0x22,0x29,0x0d, +/*004450*/ 0x0a,0x09,0x0d,0x0a,0x09,0x6c,0x75,0x61,0x5f,0x65,0x72,0x72,0x6f,0x72,0x28,0x65, +/*004460*/ 0x72,0x72,0x2c,0x20,0x6c,0x65,0x76,0x65,0x6c,0x29,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*004470*/ 0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x57,0x6f,0x72,0x6b,0x73,0x20,0x6c,0x69,0x6b,0x65, +/*004480*/ 0x20,0x61,0x73,0x73,0x65,0x72,0x74,0x28,0x29,0x2c,0x20,0x62,0x75,0x74,0x20,0x69, +/*004490*/ 0x6e,0x76,0x6f,0x6b,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75,0x67, +/*0044a0*/ 0x67,0x65,0x72,0x20,0x6f,0x6e,0x20,0x61,0x20,0x66,0x61,0x69,0x6c,0x75,0x72,0x65, +/*0044b0*/ 0x2e,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x62,0x67,0x2e, +/*0044c0*/ 0x61,0x73,0x73,0x65,0x72,0x74,0x28,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e, +/*0044d0*/ 0x2c,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20, +/*0044e0*/ 0x6e,0x6f,0x74,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x20,0x74,0x68, +/*0044f0*/ 0x65,0x6e,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c, +/*004500*/ 0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x52, +/*004510*/ 0x52,0x4f,0x52,0x3a,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53, +/*004520*/ 0x45,0x54,0x2e,0x2e,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a,0x09,0x09, +/*004530*/ 0x64,0x62,0x67,0x28,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x31,0x2c,0x20,0x22,0x64, +/*004540*/ 0x62,0x67,0x2e,0x61,0x73,0x73,0x65,0x72,0x74,0x28,0x29,0x22,0x29,0x0d,0x0a,0x09, +/*004550*/ 0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*004560*/ 0x6c,0x75,0x61,0x5f,0x61,0x73,0x73,0x65,0x72,0x74,0x28,0x63,0x6f,0x6e,0x64,0x69, +/*004570*/ 0x74,0x69,0x6f,0x6e,0x2c,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a, +/*004580*/ 0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x57,0x6f,0x72,0x6b,0x73,0x20, +/*004590*/ 0x6c,0x69,0x6b,0x65,0x20,0x70,0x63,0x61,0x6c,0x6c,0x28,0x29,0x2c,0x20,0x62,0x75, +/*0045a0*/ 0x74,0x20,0x69,0x6e,0x76,0x6f,0x6b,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x64,0x65, +/*0045b0*/ 0x62,0x75,0x67,0x67,0x65,0x72,0x20,0x6f,0x6e,0x20,0x61,0x6e,0x20,0x65,0x72,0x72, +/*0045c0*/ 0x6f,0x72,0x2e,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x62, +/*0045d0*/ 0x67,0x2e,0x63,0x61,0x6c,0x6c,0x28,0x66,0x2c,0x20,0x2e,0x2e,0x2e,0x29,0x0d,0x0a, +/*0045e0*/ 0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x78,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66, +/*0045f0*/ 0x2c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x65,0x72,0x72,0x29,0x0d, +/*004600*/ 0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*004610*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x52,0x52,0x4f,0x52, +/*004620*/ 0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54, +/*004630*/ 0x2e,0x2e,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x28,0x65,0x72,0x72, +/*004640*/ 0x29,0x29,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x28,0x66,0x61,0x6c,0x73,0x65,0x2c, +/*004650*/ 0x20,0x31,0x2c,0x20,0x22,0x64,0x62,0x67,0x2e,0x63,0x61,0x6c,0x6c,0x28,0x29,0x22, +/*004660*/ 0x29,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*004670*/ 0x65,0x72,0x72,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x2c,0x20,0x2e,0x2e,0x2e,0x29,0x0d, +/*004680*/ 0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x45,0x72,0x72,0x6f,0x72, +/*004690*/ 0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x20,0x68,0x61,0x6e,0x64,0x6c,0x65,0x72, +/*0046a0*/ 0x20,0x74,0x68,0x61,0x74,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x75,0x73,0x65, +/*0046b0*/ 0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x6c,0x75,0x61,0x5f,0x70,0x63,0x61,0x6c,0x6c, +/*0046c0*/ 0x28,0x29,0x2e,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x62, +/*0046d0*/ 0x67,0x2e,0x6d,0x73,0x67,0x68,0x28,0x2e,0x2e,0x2e,0x29,0x0d,0x0a,0x09,0x69,0x66, +/*0046e0*/ 0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x32, +/*0046f0*/ 0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72, +/*004700*/ 0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e, +/*004710*/ 0x2e,0x22,0x45,0x52,0x52,0x4f,0x52,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*004720*/ 0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x64,0x62,0x67,0x2e,0x70,0x72,0x65, +/*004730*/ 0x74,0x74,0x79,0x28,0x2e,0x2e,0x2e,0x29,0x29,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67, +/*004740*/ 0x28,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x31,0x2c,0x20,0x22,0x64,0x62,0x67,0x2e, +/*004750*/ 0x6d,0x73,0x67,0x68,0x28,0x29,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d, +/*004760*/ 0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*004770*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67, +/*004780*/ 0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*004790*/ 0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x45,0x72,0x72,0x6f,0x72,0x20, +/*0047a0*/ 0x64,0x69,0x64,0x20,0x6e,0x6f,0x74,0x20,0x6f,0x63,0x63,0x75,0x72,0x20,0x69,0x6e, +/*0047b0*/ 0x20,0x4c,0x75,0x61,0x20,0x63,0x6f,0x64,0x65,0x2e,0x20,0x45,0x78,0x65,0x63,0x75, +/*0047c0*/ 0x74,0x69,0x6f,0x6e,0x20,0x77,0x69,0x6c,0x6c,0x20,0x63,0x6f,0x6e,0x74,0x69,0x6e, +/*0047d0*/ 0x75,0x65,0x20,0x61,0x66,0x74,0x65,0x72,0x20,0x64,0x62,0x67,0x5f,0x70,0x63,0x61, +/*0047e0*/ 0x6c,0x6c,0x28,0x29,0x2e,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09, +/*0047f0*/ 0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x2e,0x2e,0x2e,0x0d,0x0a,0x65, +/*004800*/ 0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x41,0x73,0x73,0x75,0x6d,0x65,0x20, +/*004810*/ 0x73,0x74,0x64,0x69,0x6e,0x2f,0x6f,0x75,0x74,0x20,0x61,0x72,0x65,0x20,0x54,0x54, +/*004820*/ 0x59,0x73,0x20,0x75,0x6e,0x6c,0x65,0x73,0x73,0x20,0x77,0x65,0x20,0x63,0x61,0x6e, +/*004830*/ 0x20,0x75,0x73,0x65,0x20,0x4c,0x75,0x61,0x4a,0x49,0x54,0x27,0x73,0x20,0x46,0x46, +/*004840*/ 0x49,0x20,0x74,0x6f,0x20,0x70,0x72,0x6f,0x70,0x65,0x72,0x6c,0x79,0x20,0x63,0x68, +/*004850*/ 0x65,0x63,0x6b,0x20,0x74,0x68,0x65,0x6d,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c, +/*004860*/ 0x20,0x73,0x74,0x64,0x69,0x6e,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x3d,0x20, +/*004870*/ 0x74,0x72,0x75,0x65,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x74,0x64,0x6f, +/*004880*/ 0x75,0x74,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x3d,0x20,0x74,0x72,0x75,0x65, +/*004890*/ 0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e, +/*0048a0*/ 0x61,0x6c,0x6c,0x79,0x20,0x65,0x6e,0x61,0x62,0x6c,0x65,0x20,0x74,0x68,0x65,0x20, +/*0048b0*/ 0x4c,0x75,0x61,0x4a,0x49,0x54,0x20,0x46,0x46,0x49,0x2e,0x0d,0x0a,0x6c,0x6f,0x63, +/*0048c0*/ 0x61,0x6c,0x20,0x66,0x66,0x69,0x20,0x3d,0x20,0x28,0x6a,0x69,0x74,0x20,0x61,0x6e, +/*0048d0*/ 0x64,0x20,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x28,0x22,0x66,0x66,0x69,0x22,0x29, +/*0048e0*/ 0x29,0x0d,0x0a,0x69,0x66,0x20,0x66,0x66,0x69,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a, +/*0048f0*/ 0x09,0x66,0x66,0x69,0x2e,0x63,0x64,0x65,0x66,0x5b,0x5b,0x0d,0x0a,0x09,0x09,0x69, +/*004900*/ 0x6e,0x74,0x20,0x69,0x73,0x61,0x74,0x74,0x79,0x28,0x69,0x6e,0x74,0x29,0x3b,0x20, +/*004910*/ 0x2f,0x2f,0x20,0x55,0x6e,0x69,0x78,0x0d,0x0a,0x09,0x09,0x69,0x6e,0x74,0x20,0x5f, +/*004920*/ 0x69,0x73,0x61,0x74,0x74,0x79,0x28,0x69,0x6e,0x74,0x29,0x3b,0x20,0x2f,0x2f,0x20, +/*004930*/ 0x57,0x69,0x6e,0x64,0x6f,0x77,0x73,0x0d,0x0a,0x09,0x09,0x76,0x6f,0x69,0x64,0x20, +/*004940*/ 0x66,0x72,0x65,0x65,0x28,0x76,0x6f,0x69,0x64,0x20,0x2a,0x70,0x74,0x72,0x29,0x3b, +/*004950*/ 0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x63,0x68,0x61,0x72,0x20,0x2a,0x72,0x65, +/*004960*/ 0x61,0x64,0x6c,0x69,0x6e,0x65,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x63,0x68,0x61, +/*004970*/ 0x72,0x20,0x2a,0x29,0x3b,0x0d,0x0a,0x09,0x09,0x69,0x6e,0x74,0x20,0x61,0x64,0x64, +/*004980*/ 0x5f,0x68,0x69,0x73,0x74,0x6f,0x72,0x79,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x63, +/*004990*/ 0x68,0x61,0x72,0x20,0x2a,0x29,0x3b,0x0d,0x0a,0x09,0x5d,0x5d,0x0d,0x0a,0x09,0x0d, +/*0049a0*/ 0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e, +/*0049b0*/ 0x20,0x67,0x65,0x74,0x5f,0x66,0x75,0x6e,0x63,0x5f,0x6f,0x72,0x5f,0x6e,0x69,0x6c, +/*0049c0*/ 0x28,0x73,0x79,0x6d,0x29,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73, +/*0049d0*/ 0x75,0x63,0x63,0x65,0x73,0x73,0x2c,0x20,0x66,0x75,0x6e,0x63,0x20,0x3d,0x20,0x70, +/*0049e0*/ 0x63,0x61,0x6c,0x6c,0x28,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x20, +/*0049f0*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x66,0x69,0x2e,0x43,0x5b,0x73,0x79,0x6d, +/*004a00*/ 0x5d,0x20,0x65,0x6e,0x64,0x29,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e, +/*004a10*/ 0x20,0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x20,0x61,0x6e,0x64,0x20,0x66,0x75,0x6e, +/*004a20*/ 0x63,0x20,0x6f,0x72,0x20,0x6e,0x69,0x6c,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a, +/*004a30*/ 0x09,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x73,0x61,0x74,0x74,0x79, +/*004a40*/ 0x20,0x3d,0x20,0x67,0x65,0x74,0x5f,0x66,0x75,0x6e,0x63,0x5f,0x6f,0x72,0x5f,0x6e, +/*004a50*/ 0x69,0x6c,0x28,0x22,0x69,0x73,0x61,0x74,0x74,0x79,0x22,0x29,0x20,0x6f,0x72,0x20, +/*004a60*/ 0x67,0x65,0x74,0x5f,0x66,0x75,0x6e,0x63,0x5f,0x6f,0x72,0x5f,0x6e,0x69,0x6c,0x28, +/*004a70*/ 0x22,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x22,0x29,0x20,0x6f,0x72,0x20,0x28,0x66, +/*004a80*/ 0x66,0x69,0x2e,0x6c,0x6f,0x61,0x64,0x28,0x22,0x75,0x63,0x72,0x74,0x62,0x61,0x73, +/*004a90*/ 0x65,0x22,0x29,0x29,0x5b,0x22,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x22,0x5d,0x0d, +/*004aa0*/ 0x0a,0x09,0x73,0x74,0x64,0x69,0x6e,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x3d, +/*004ab0*/ 0x20,0x69,0x73,0x61,0x74,0x74,0x79,0x28,0x30,0x29,0x0d,0x0a,0x09,0x73,0x74,0x64, +/*004ac0*/ 0x6f,0x75,0x74,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x3d,0x20,0x69,0x73,0x61, +/*004ad0*/ 0x74,0x74,0x79,0x28,0x31,0x29,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d, +/*004ae0*/ 0x2d,0x20,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x6c,0x79,0x20, +/*004af0*/ 0x65,0x6e,0x61,0x62,0x6c,0x65,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x73,0x75,0x70, +/*004b00*/ 0x70,0x6f,0x72,0x74,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x6f,0x6c, +/*004b10*/ 0x6f,0x72,0x5f,0x6d,0x61,0x79,0x62,0x65,0x5f,0x73,0x75,0x70,0x70,0x6f,0x72,0x74, +/*004b20*/ 0x65,0x64,0x20,0x3d,0x20,0x28,0x73,0x74,0x64,0x6f,0x75,0x74,0x5f,0x69,0x73,0x61, +/*004b30*/ 0x74,0x74,0x79,0x20,0x61,0x6e,0x64,0x20,0x6f,0x73,0x2e,0x67,0x65,0x74,0x65,0x6e, +/*004b40*/ 0x76,0x28,0x22,0x54,0x45,0x52,0x4d,0x22,0x29,0x20,0x61,0x6e,0x64,0x20,0x6f,0x73, +/*004b50*/ 0x2e,0x67,0x65,0x74,0x65,0x6e,0x76,0x28,0x22,0x54,0x45,0x52,0x4d,0x22,0x29,0x20, +/*004b60*/ 0x7e,0x3d,0x20,0x22,0x64,0x75,0x6d,0x62,0x22,0x29,0x0d,0x0a,0x69,0x66,0x20,0x63, +/*004b70*/ 0x6f,0x6c,0x6f,0x72,0x5f,0x6d,0x61,0x79,0x62,0x65,0x5f,0x73,0x75,0x70,0x70,0x6f, +/*004b80*/ 0x72,0x74,0x65,0x64,0x20,0x61,0x6e,0x64,0x20,0x6e,0x6f,0x74,0x20,0x6f,0x73,0x2e, +/*004b90*/ 0x67,0x65,0x74,0x65,0x6e,0x76,0x28,0x22,0x44,0x42,0x47,0x5f,0x4e,0x4f,0x43,0x4f, +/*004ba0*/ 0x4c,0x4f,0x52,0x22,0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x43,0x4f,0x4c, +/*004bb0*/ 0x4f,0x52,0x5f,0x47,0x52,0x41,0x59,0x20,0x3d,0x20,0x73,0x74,0x72,0x69,0x6e,0x67, +/*004bc0*/ 0x2e,0x63,0x68,0x61,0x72,0x28,0x32,0x37,0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b,0x39, +/*004bd0*/ 0x30,0x6d,0x22,0x0d,0x0a,0x09,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x20, +/*004be0*/ 0x3d,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x63,0x68,0x61,0x72,0x28,0x32,0x37, +/*004bf0*/ 0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b,0x39,0x31,0x6d,0x22,0x0d,0x0a,0x09,0x43,0x4f, +/*004c00*/ 0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x20,0x3d,0x20,0x73,0x74,0x72,0x69,0x6e, +/*004c10*/ 0x67,0x2e,0x63,0x68,0x61,0x72,0x28,0x32,0x37,0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b, +/*004c20*/ 0x39,0x34,0x6d,0x22,0x0d,0x0a,0x09,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*004c30*/ 0x4c,0x4f,0x57,0x20,0x3d,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x63,0x68,0x61, +/*004c40*/ 0x72,0x28,0x32,0x37,0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b,0x33,0x33,0x6d,0x22,0x0d, +/*004c50*/ 0x0a,0x09,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x20,0x3d,0x20, +/*004c60*/ 0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x63,0x68,0x61,0x72,0x28,0x32,0x37,0x29,0x20, +/*004c70*/ 0x2e,0x2e,0x20,0x22,0x5b,0x30,0x6d,0x22,0x0d,0x0a,0x09,0x47,0x52,0x45,0x45,0x4e, +/*004c80*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x20,0x3d,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e, +/*004c90*/ 0x63,0x68,0x61,0x72,0x28,0x32,0x37,0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b,0x39,0x32, +/*004ca0*/ 0x6d,0x20,0x3d,0x3e,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*004cb0*/ 0x53,0x45,0x54,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x69,0x66,0x20,0x73, +/*004cc0*/ 0x74,0x64,0x69,0x6e,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x61,0x6e,0x64,0x20, +/*004cd0*/ 0x6e,0x6f,0x74,0x20,0x6f,0x73,0x2e,0x67,0x65,0x74,0x65,0x6e,0x76,0x28,0x22,0x44, +/*004ce0*/ 0x42,0x47,0x5f,0x4e,0x4f,0x52,0x45,0x41,0x44,0x4c,0x49,0x4e,0x45,0x22,0x29,0x20, +/*004cf0*/ 0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66,0x75,0x6e, +/*004d00*/ 0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*004d10*/ 0x20,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x20,0x3d,0x20,0x72,0x65,0x71, +/*004d20*/ 0x75,0x69,0x72,0x65,0x20,0x27,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x27, +/*004d30*/ 0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x4c,0x6f,0x61,0x64,0x20, +/*004d40*/ 0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x68,0x69,0x73,0x74,0x6f,0x72,0x79,0x20, +/*004d50*/ 0x66,0x72,0x6f,0x6d,0x20,0x7e,0x2f,0x2e,0x6c,0x75,0x61,0x5f,0x68,0x69,0x73,0x74, +/*004d60*/ 0x6f,0x72,0x79,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x68,0x69,0x73, +/*004d70*/ 0x74,0x5f,0x70,0x61,0x74,0x68,0x20,0x3d,0x20,0x6f,0x73,0x2e,0x67,0x65,0x74,0x65, +/*004d80*/ 0x6e,0x76,0x28,0x27,0x48,0x4f,0x4d,0x45,0x27,0x29,0x20,0x2e,0x2e,0x20,0x27,0x2f, +/*004d90*/ 0x2e,0x6c,0x75,0x61,0x5f,0x68,0x69,0x73,0x74,0x6f,0x72,0x79,0x27,0x0d,0x0a,0x09, +/*004da0*/ 0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x68,0x69,0x73,0x74,0x6f, +/*004db0*/ 0x72,0x79,0x6c,0x6f,0x61,0x64,0x28,0x68,0x69,0x73,0x74,0x5f,0x70,0x61,0x74,0x68, +/*004dc0*/ 0x29,0x0d,0x0a,0x09,0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x68, +/*004dd0*/ 0x69,0x73,0x74,0x6f,0x72,0x79,0x73,0x65,0x74,0x6d,0x61,0x78,0x6c,0x65,0x6e,0x28, +/*004de0*/ 0x35,0x30,0x29,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*004df0*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x61,0x75,0x74,0x6f,0x63,0x6f, +/*004e00*/ 0x6d,0x70,0x6c,0x65,0x74,0x65,0x28,0x65,0x6e,0x76,0x2c,0x20,0x69,0x6e,0x70,0x75, +/*004e10*/ 0x74,0x2c,0x20,0x6d,0x61,0x74,0x63,0x68,0x65,0x73,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*004e20*/ 0x66,0x6f,0x72,0x20,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x5f,0x20,0x69,0x6e,0x20,0x70, +/*004e30*/ 0x61,0x69,0x72,0x73,0x28,0x65,0x6e,0x76,0x29,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09, +/*004e40*/ 0x09,0x09,0x69,0x66,0x20,0x6e,0x61,0x6d,0x65,0x3a,0x6d,0x61,0x74,0x63,0x68,0x28, +/*004e50*/ 0x27,0x5e,0x27,0x20,0x2e,0x2e,0x20,0x69,0x6e,0x70,0x75,0x74,0x20,0x2e,0x2e,0x20, +/*004e60*/ 0x27,0x2e,0x2a,0x27,0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x09, +/*004e70*/ 0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x61,0x64,0x64,0x63,0x6f, +/*004e80*/ 0x6d,0x70,0x6c,0x65,0x74,0x69,0x6f,0x6e,0x28,0x6d,0x61,0x74,0x63,0x68,0x65,0x73, +/*004e90*/ 0x2c,0x20,0x6e,0x61,0x6d,0x65,0x29,0x0d,0x0a,0x09,0x09,0x09,0x09,0x65,0x6e,0x64, +/*004ea0*/ 0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d, +/*004eb0*/ 0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x41,0x75,0x74,0x6f,0x2d,0x63, +/*004ec0*/ 0x6f,0x6d,0x70,0x6c,0x65,0x74,0x69,0x6f,0x6e,0x20,0x66,0x6f,0x72,0x20,0x6c,0x6f, +/*004ed0*/ 0x63,0x61,0x6c,0x73,0x20,0x61,0x6e,0x64,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x73, +/*004ee0*/ 0x0d,0x0a,0x09,0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x73,0x65, +/*004ef0*/ 0x74,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x74,0x69,0x6f,0x6e,0x28,0x66,0x75,0x6e,0x63, +/*004f00*/ 0x74,0x69,0x6f,0x6e,0x28,0x6d,0x61,0x74,0x63,0x68,0x65,0x73,0x2c,0x20,0x69,0x6e, +/*004f10*/ 0x70,0x75,0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d,0x20,0x46,0x69,0x72,0x73, +/*004f20*/ 0x74,0x2c,0x20,0x63,0x68,0x65,0x63,0x6b,0x20,0x74,0x68,0x65,0x20,0x6c,0x6f,0x63, +/*004f30*/ 0x61,0x6c,0x73,0x20,0x61,0x6e,0x64,0x20,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x73, +/*004f40*/ 0x2e,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x76,0x20, +/*004f50*/ 0x3d,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73, +/*004f60*/ 0x28,0x31,0x2c,0x20,0x74,0x72,0x75,0x65,0x29,0x0d,0x0a,0x09,0x09,0x09,0x61,0x75, +/*004f70*/ 0x74,0x6f,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x74,0x65,0x28,0x65,0x6e,0x76,0x2c,0x20, +/*004f80*/ 0x69,0x6e,0x70,0x75,0x74,0x2c,0x20,0x6d,0x61,0x74,0x63,0x68,0x65,0x73,0x29,0x0d, +/*004f90*/ 0x0a,0x09,0x09,0x09,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d,0x20,0x54,0x68,0x65,0x6e, +/*004fa0*/ 0x2c,0x20,0x63,0x68,0x65,0x63,0x6b,0x20,0x74,0x68,0x65,0x20,0x69,0x6d,0x70,0x6c, +/*004fb0*/ 0x69,0x63,0x69,0x74,0x20,0x65,0x6e,0x76,0x69,0x72,0x6f,0x6e,0x6d,0x65,0x6e,0x74, +/*004fc0*/ 0x2e,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x76,0x20,0x3d,0x20,0x67,0x65,0x74,0x6d, +/*004fd0*/ 0x65,0x74,0x61,0x74,0x61,0x62,0x6c,0x65,0x28,0x65,0x6e,0x76,0x29,0x2e,0x5f,0x5f, +/*004fe0*/ 0x69,0x6e,0x64,0x65,0x78,0x0d,0x0a,0x09,0x09,0x09,0x61,0x75,0x74,0x6f,0x63,0x6f, +/*004ff0*/ 0x6d,0x70,0x6c,0x65,0x74,0x65,0x28,0x65,0x6e,0x76,0x2c,0x20,0x69,0x6e,0x70,0x75, +/*005000*/ 0x74,0x2c,0x20,0x6d,0x61,0x74,0x63,0x68,0x65,0x73,0x29,0x0d,0x0a,0x09,0x09,0x65, +/*005010*/ 0x6e,0x64,0x29,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x2e,0x72, +/*005020*/ 0x65,0x61,0x64,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x70, +/*005030*/ 0x72,0x6f,0x6d,0x70,0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*005040*/ 0x20,0x73,0x74,0x72,0x20,0x3d,0x20,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65, +/*005050*/ 0x2e,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x28,0x70,0x72,0x6f,0x6d,0x70, +/*005060*/ 0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x69,0x66,0x20,0x73,0x74,0x72,0x20,0x61,0x6e, +/*005070*/ 0x64,0x20,0x6e,0x6f,0x74,0x20,0x73,0x74,0x72,0x3a,0x6d,0x61,0x74,0x63,0x68,0x20, +/*005080*/ 0x22,0x5e,0x25,0x73,0x2a,0x24,0x22,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09, +/*005090*/ 0x09,0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x68,0x69,0x73,0x74, +/*0050a0*/ 0x6f,0x72,0x79,0x61,0x64,0x64,0x28,0x73,0x74,0x72,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*0050b0*/ 0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x68,0x69,0x73,0x74,0x6f, +/*0050c0*/ 0x72,0x79,0x73,0x61,0x76,0x65,0x28,0x68,0x69,0x73,0x74,0x5f,0x70,0x61,0x74,0x68, +/*0050d0*/ 0x29,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x72,0x65, +/*0050e0*/ 0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x72,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d, +/*0050f0*/ 0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*005100*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65, +/*005110*/ 0x62,0x75,0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43, +/*005120*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x4c,0x69,0x6e, +/*005130*/ 0x65,0x6e,0x6f,0x69,0x73,0x65,0x20,0x73,0x75,0x70,0x70,0x6f,0x72,0x74,0x20,0x65, +/*005140*/ 0x6e,0x61,0x62,0x6c,0x65,0x64,0x2e,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x29, +/*005150*/ 0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69, +/*005160*/ 0x6f,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x65,0x6e,0x61,0x62,0x6c,0x65,0x20,0x4c,0x75, +/*005170*/ 0x61,0x4a,0x49,0x54,0x20,0x72,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x20,0x73,0x75, +/*005180*/ 0x70,0x70,0x6f,0x72,0x74,0x2e,0x0d,0x0a,0x09,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66, +/*005190*/ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20, +/*0051a0*/ 0x64,0x62,0x67,0x2e,0x72,0x65,0x61,0x64,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20, +/*0051b0*/ 0x61,0x6e,0x64,0x20,0x66,0x66,0x69,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09, +/*0051c0*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x72,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x20, +/*0051d0*/ 0x3d,0x20,0x66,0x66,0x69,0x2e,0x6c,0x6f,0x61,0x64,0x28,0x22,0x72,0x65,0x61,0x64, +/*0051e0*/ 0x6c,0x69,0x6e,0x65,0x22,0x29,0x0d,0x0a,0x09,0x09,0x09,0x64,0x62,0x67,0x2e,0x72, +/*0051f0*/ 0x65,0x61,0x64,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x70, +/*005200*/ 0x72,0x6f,0x6d,0x70,0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61, +/*005210*/ 0x6c,0x20,0x63,0x73,0x74,0x72,0x20,0x3d,0x20,0x72,0x65,0x61,0x64,0x6c,0x69,0x6e, +/*005220*/ 0x65,0x2e,0x72,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x28,0x70,0x72,0x6f,0x6d,0x70, +/*005230*/ 0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x09,0x69,0x66,0x20,0x63,0x73,0x74,0x72,0x20, +/*005240*/ 0x7e,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09, +/*005250*/ 0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x74,0x72,0x20,0x3d,0x20,0x66,0x66, +/*005260*/ 0x69,0x2e,0x73,0x74,0x72,0x69,0x6e,0x67,0x28,0x63,0x73,0x74,0x72,0x29,0x0d,0x0a, +/*005270*/ 0x09,0x09,0x09,0x09,0x09,0x69,0x66,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x6d, +/*005280*/ 0x61,0x74,0x63,0x68,0x28,0x73,0x74,0x72,0x2c,0x20,0x22,0x5b,0x5e,0x25,0x73,0x5d, +/*005290*/ 0x2b,0x22,0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x09,0x09,0x09, +/*0052a0*/ 0x72,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x2e,0x61,0x64,0x64,0x5f,0x68,0x69,0x73, +/*0052b0*/ 0x74,0x6f,0x72,0x79,0x28,0x63,0x73,0x74,0x72,0x29,0x0d,0x0a,0x09,0x09,0x09,0x09, +/*0052c0*/ 0x09,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x09,0x09,0x09,0x09,0x09,0x66,0x66,0x69, +/*0052d0*/ 0x2e,0x43,0x2e,0x66,0x72,0x65,0x65,0x28,0x63,0x73,0x74,0x72,0x29,0x0d,0x0a,0x09, +/*0052e0*/ 0x09,0x09,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x72,0x0d,0x0a, +/*0052f0*/ 0x09,0x09,0x09,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x09,0x09,0x09,0x72, +/*005300*/ 0x65,0x74,0x75,0x72,0x6e,0x20,0x6e,0x69,0x6c,0x0d,0x0a,0x09,0x09,0x09,0x09,0x65, +/*005310*/ 0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x64, +/*005320*/ 0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52, +/*005330*/ 0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67, +/*005340*/ 0x65,0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*005350*/ 0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x52,0x65,0x61,0x64,0x6c,0x69,0x6e, +/*005360*/ 0x65,0x20,0x73,0x75,0x70,0x70,0x6f,0x72,0x74,0x20,0x65,0x6e,0x61,0x62,0x6c,0x65, +/*005370*/ 0x64,0x2e,0x22,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6e, +/*005380*/ 0x64,0x29,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x44,0x65, +/*005390*/ 0x74,0x65,0x63,0x74,0x20,0x4c,0x75,0x61,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e, +/*0053a0*/ 0x2e,0x0d,0x0a,0x69,0x66,0x20,0x6a,0x69,0x74,0x20,0x74,0x68,0x65,0x6e,0x20,0x2d, +/*0053b0*/ 0x2d,0x20,0x4c,0x75,0x61,0x4a,0x49,0x54,0x0d,0x0a,0x09,0x4c,0x55,0x41,0x5f,0x4a, +/*0053c0*/ 0x49,0x54,0x5f,0x53,0x45,0x54,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x57,0x4f,0x52,0x4b, +/*0053d0*/ 0x41,0x52,0x4f,0x55,0x4e,0x44,0x20,0x3d,0x20,0x2d,0x31,0x0d,0x0a,0x09,0x64,0x62, +/*0053e0*/ 0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*0053f0*/ 0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67,0x65, +/*005400*/ 0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*005410*/ 0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x4c,0x6f,0x61,0x64,0x65,0x64,0x20,0x66, +/*005420*/ 0x6f,0x72,0x20,0x22,0x2e,0x2e,0x6a,0x69,0x74,0x2e,0x76,0x65,0x72,0x73,0x69,0x6f, +/*005430*/ 0x6e,0x29,0x0d,0x0a,0x65,0x6c,0x73,0x65,0x69,0x66,0x20,0x22,0x4c,0x75,0x61,0x20, +/*005440*/ 0x35,0x2e,0x31,0x22,0x20,0x3c,0x3d,0x20,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e, +/*005450*/ 0x20,0x61,0x6e,0x64,0x20,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x20,0x3c,0x3d, +/*005460*/ 0x20,0x22,0x4c,0x75,0x61,0x20,0x35,0x2e,0x34,0x22,0x20,0x74,0x68,0x65,0x6e,0x0d, +/*005470*/ 0x0a,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f, +/*005480*/ 0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62, +/*005490*/ 0x75,0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f, +/*0054a0*/ 0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x4c,0x6f,0x61,0x64, +/*0054b0*/ 0x65,0x64,0x20,0x66,0x6f,0x72,0x20,0x22,0x2e,0x2e,0x5f,0x56,0x45,0x52,0x53,0x49, +/*0054c0*/ 0x4f,0x4e,0x29,0x0d,0x0a,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x64,0x62,0x67,0x5f, +/*0054d0*/ 0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45, +/*0054e0*/ 0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x2e, +/*0054f0*/ 0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*005500*/ 0x53,0x45,0x54,0x2e,0x2e,0x22,0x4e,0x6f,0x74,0x20,0x74,0x65,0x73,0x74,0x65,0x64, +/*005510*/ 0x20,0x61,0x67,0x61,0x69,0x6e,0x73,0x74,0x20,0x22,0x2e,0x2e,0x5f,0x56,0x45,0x52, +/*005520*/ 0x53,0x49,0x4f,0x4e,0x29,0x0d,0x0a,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74, +/*005530*/ 0x65,0x6c,0x6e,0x28,0x22,0x50,0x6c,0x65,0x61,0x73,0x65,0x20,0x73,0x65,0x6e,0x64, +/*005540*/ 0x20,0x6d,0x65,0x20,0x66,0x65,0x65,0x64,0x62,0x61,0x63,0x6b,0x21,0x22,0x29,0x0d, +/*005550*/ 0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64, +/*005560*/ 0x62,0x67,0x0d,0x0a +}; + +const unsigned DEBUGGER_SRC_LEN = (unsigned)sizeof(DEBUGGER_SRC); + + +int luaopen_debugger(lua_State *lua){ + if( + luaL_loadbufferx(lua, DEBUGGER_SRC, DEBUGGER_SRC_LEN, "", NULL) || + lua_pcall(lua, 0, LUA_MULTRET, 0) + ) lua_error(lua); + + // Or you could load it from disk: + // if(luaL_dofile(lua, "debugger.lua")) lua_error(lua); + + return 1; +} + +static const char *MODULE_NAME = "DEBUGGER_LUA_MODULE"; +static const char *MSGH = "DEBUGGER_LUA_MSGH"; + +void dbg_setup(lua_State *lua, const char *name, const char *globalName, lua_CFunction readFunc, lua_CFunction writeFunc){ + // Check that the module name was not already defined. + lua_getfield(lua, LUA_REGISTRYINDEX, MODULE_NAME); + assert(lua_isnil(lua, -1) || strcmp(name, luaL_checkstring(lua, -1))); + lua_pop(lua, 1); + + // Push the module name into the registry. + lua_pushstring(lua, name); + lua_setfield(lua, LUA_REGISTRYINDEX, MODULE_NAME); + + // Preload the module + luaL_requiref(lua, name, luaopen_debugger, false); + + // Insert the msgh function into the registry. + lua_getfield(lua, -1, "msgh"); + lua_setfield(lua, LUA_REGISTRYINDEX, MSGH); + + if(readFunc){ + lua_pushcfunction(lua, readFunc); + lua_setfield(lua, -2, "read"); + } + + if(writeFunc){ + lua_pushcfunction(lua, writeFunc); + lua_setfield(lua, -2, "write"); + } + + if(globalName){ + lua_setglobal(lua, globalName); + } else { + lua_pop(lua, 1); + } +} + +void dbg_setup_default(lua_State *lua){ + dbg_setup(lua, "debugger", "dbg", NULL, NULL); +} + +int dbg_pcall(lua_State *lua, int nargs, int nresults, int msgh){ + // Call regular lua_pcall() if a message handler is provided. + if(msgh) return lua_pcall(lua, nargs, nresults, msgh); + + // Grab the msgh function out of the registry. + lua_getfield(lua, LUA_REGISTRYINDEX, MSGH); + if(lua_isnil(lua, -1)){ + luaL_error(lua, "Tried to call dbg_call() before calling dbg_setup()."); + } + + // Move the error handler just below the function. + msgh = lua_gettop(lua) - (1 + nargs); + lua_insert(lua, msgh); + + // Call the function. + int err = lua_pcall(lua, nargs, nresults, msgh); + + // Remove the debug handler. + lua_remove(lua, msgh); + + return err; +} diff --git a/engine/split/3rd_nuklear.h b/engine/split/3rd_nuklear.h index 7b61063..6d22f23 100644 --- a/engine/split/3rd_nuklear.h +++ b/engine/split/3rd_nuklear.h @@ -25275,6 +25275,7 @@ nk_selectable_text(struct nk_context *ctx, const char *str, int len, state = nk_widget(&bounds, ctx); if (!state) return 0; in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; + return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds, str, len, align, value, &style->selectable, in, style->font); } diff --git a/engine/split/3rd_nuklear_filebrowser.h.bak b/engine/split/3rd_nuklear_filebrowser.h.bak new file mode 100644 index 0000000..ffa3f34 --- /dev/null +++ b/engine/split/3rd_nuklear_filebrowser.h.bak @@ -0,0 +1,400 @@ +// file browser for nuklear, based on https://github.com/vurtun/nuklear/blob/master/example/file_browser.c (public domain) +// - rlyeh, public domain +// +// changelog: +// - ported to FWK api +// - namespaced symbols +// - diverse win32 fixes +// - adaptive cols/rows +// - removed nk_begin()/nk_end() pairs +// - dangling nk_group_begin/end() pairs +// - simplified file<->media_group concept +// - minor cosmetics + +#ifdef _WIN32 +#include // _getcwd() +#else +#include // getcwd() +#include // getpwuid() +#endif + +#if 1 +#define BROWSER_PRINTF(...) do {} while(0) +#else +#define BROWSER_PRINTF printf +#endif + +enum browser_groups { + BROWSER_FOLDER, + BROWSER_HOME, + BROWSER_DESKTOP, + BROWSER_COMPUTER, + BROWSER_PROJECT, + BROWSER_MAXFOLDERS, + + BROWSER_MAXTYPES = 64, +}; + +struct browser_media_group { + unsigned icon; + const char *extensions; +}; + +struct browser_media { + int font; + int icon_sheet; + struct nk_image custom_folders[BROWSER_MAXFOLDERS]; + struct nk_image custom_files[BROWSER_MAXTYPES]; + struct browser_media_group group[BROWSER_MAXTYPES]; +} media = {0}; + +void browser_config_dir(struct nk_image icon, unsigned counter) { + if( counter < BROWSER_MAXFOLDERS ) { + media.custom_folders[ counter ] = icon; + } +} + +void browser_config_type(struct nk_image icon, const char *extensions) { + static int counter = 0; + if( counter < BROWSER_MAXTYPES ) { + media.custom_files[ counter ] = icon; + media.group[ counter ].icon = counter; + media.group[ counter ].extensions = extensions; + ++counter; + } +} + +#define BROWSER_MAX_PATH 512 +struct browser { + /* path */ + char file[BROWSER_MAX_PATH]; // selection + char directory[BROWSER_MAX_PATH]; // current cwd while browsing + + char home[BROWSER_MAX_PATH]; + char desktop[BROWSER_MAX_PATH]; + char computer[BROWSER_MAX_PATH]; + char project[BROWSER_MAX_PATH]; // cwd when first invoked + + /* directory content */ + array(char*) files; + array(char*) directories; + size_t file_count; + size_t dir_count; + + /* view mode */ + bool listing; + float zooming; +}; + +static struct nk_image* media_icon_for_file(const char *file) { + /* extract extension .xxx from file */ + char *ext = strrchr(file, '.'); + if( ext && strlen(ext) < 16 ) { + char ext_dot[16+1]; + snprintf(ext_dot, 16, "%s.", ext); + /* check for all file definition of all groups for fitting extension. skip first group (default) */ + for (int i = 1; i < BROWSER_MAXTYPES && media.group[i].extensions; ++i) { + if( strstri(media.group[i].extensions, ext_dot) ) { + return &media.custom_files[ media.group[i].icon ]; + } + } + } + + // return first (default) group + return &media.custom_files[0]; +} + + +static void browser_reload_directory_content(struct browser *browser, const char *path) { + if(path[0] == '\0') path = va("./"); + if(!strend(path, "/")) path = va("%s/", path); + + for(int i = 0; i < array_count(browser->files); ++i) FREE(browser->files[i]); + for(int i = 0; i < array_count(browser->directories); ++i) FREE(browser->directories[i]); + + array_resize(browser->files, 0); + array_resize(browser->directories, 0); + + BROWSER_PRINTF("searching at %s\n", path); + + const char **list = file_list(path, "*"); + for( int i = 0; list[i]; ++i ) { + + char *absolute = file_pathabs(ifndef(win32, list[i], va("%s/%s", path, list[i]))); // ../dir/./file.ext -> c:/prj/dir/file.ext + BROWSER_PRINTF("%s->%s %d->", list[i], absolute, file_directory(absolute) ); + + if( file_directory(absolute) ) { + // remove last '/' if present. ok to overwrite absolute var, file_*() API returns writeable strings. + char *dir = absolute; if( dir[ strlen(dir) - 1 ] == '/' ) dir[ strlen(dir) - 1 ] = '\0'; + + dir = file_name(dir); // /home/rlyeh/prj/fwk/art -> art + BROWSER_PRINTF("%s\n", dir); + + if( dir[0] != '.' ) // skip special files, folders and internal files like .git or .art.zip + array_push(browser->directories, STRDUP(dir)); + } else { + const char *fname = file_name(absolute); + + BROWSER_PRINTF("%s\n", fname); + + if( fname[0] != '.' ) // skip special files, folders and internal files like .git or .art.zip + array_push(browser->files, STRDUP(fname)); + } + } + + browser->file_count = array_count(browser->files); + browser->dir_count = array_count(browser->directories); +} + +static void browser_chdir_and_reload_directory_content(struct browser *browser, const char *path) { + if( path != browser->directory ) strncpy(browser->directory, path, BROWSER_MAX_PATH); + browser_reload_directory_content(browser, path); +} + +static void browser_init(struct browser *browser) { + memset(browser, 0, sizeof(*browser)); + { + /* load files and sub-directory list */ + const char *home = getenv("HOME"); +#ifdef _WIN32 + if (!home) home = getenv("USERPROFILE"); +#else + if (!home) home = getpwuid(getuid())->pw_dir; +#endif + snprintf(browser->home, BROWSER_MAX_PATH, "%s/", home); + snprintf(browser->desktop, BROWSER_MAX_PATH, "%s/Desktop/", home); + snprintf(browser->computer, BROWSER_MAX_PATH, "%s", ifdef(win32, va("%.*s", 3, getenv("windir")), "/")); + { + ifdef(win32, _getcwd, getcwd)(browser->project, sizeof(browser->project) - 1); // -1 == room for '/' + strcat(browser->project, "/"); + } + + BROWSER_PRINTF("%s\n", browser->home); + BROWSER_PRINTF("%s\n", browser->desktop); + BROWSER_PRINTF("%s\n", browser->computer); + BROWSER_PRINTF("%s\n", browser->project); + + browser_chdir_and_reload_directory_content(browser, browser->project); + } +} + +static void browser_free(struct browser *browser) { + for(int i = 0; i < array_count(browser->files); ++i) FREE(browser->files[i]); + for(int i = 0; i < array_count(browser->directories); ++i) FREE(browser->directories[i]); + array_free(browser->files); + array_free(browser->directories); + memset(browser, 0, sizeof(*browser)); +} + +static int browser_run(struct nk_context *ctx, struct browser *browser, int windowed, struct nk_rect total_space) { + int clicked = 0; + + static float ratio[] = {0.25f, NK_UNDEFINED}; + + float spacing_x = ctx->style.window.spacing.x; + + /* output path directory selector in the menubar */ + ctx->style.window.spacing.x = 0; + if( windowed ) nk_menubar_begin(ctx); + { + char *d = browser->directory; +#ifdef _WIN32 + char *begin = d; +#else + char *begin = d + 1; +#endif + nk_layout_row_template_begin(ctx, 25); + nk_layout_row_template_push_variable(ctx, 40); + nk_layout_row_template_push_variable(ctx, 40); + nk_layout_row_template_push_variable(ctx, 40); + nk_layout_row_template_end(ctx); + + if (nk_button_label(ctx, !browser->listing ? ICON_MD_LIST : ICON_MD_GRID_VIEW)) { + browser->listing ^= 1; + } + + while (*d++) { + if (*d == '/') { + *d = '\0'; + if (nk_button_label(ctx, va("%s" ICON_MD_ARROW_RIGHT, file_name(begin)))) { + *d++ = '/'; *d = '\0'; + browser_chdir_and_reload_directory_content(browser, browser->directory); + break; + } + *d = '/'; + begin = d + 1; + } + } + } + if( windowed ) nk_menubar_end(ctx); + ctx->style.window.spacing.x = spacing_x; + +if(nk_window_has_focus(ctx)) +browser->zooming = clampf( browser->zooming + input_diff(MOUSE_W) * 0.1, 1, 3); + +bool compact = 0, tiny = browser->listing; // compact, no left panel. tiny, no large icons +size_t cols = total_space.w / (100 * browser->zooming); +int icon_height = (67 * browser->zooming) * (tiny ? 0.33 : 1.); // icon height (96) + button padding (??). originally: 135 +/**/ if( tiny ) cols = (int)cols+1.5, cols /= 2, compact = total_space.w < 500; // cols <= 2; +else cols = (int)cols+1, compact = total_space.w < 500; // cols <= 5; +if( cols < 1 ) cols=1; + + /* window layout */ + nk_layout_row(ctx, NK_DYNAMIC, total_space.h, compact ? 1 : 2, compact ? ratio+1 : ratio); + if( !compact ) + if( nk_group_begin(ctx, "Special", NK_WINDOW_NO_SCROLLBAR) ) { + nk_layout_row_dynamic(ctx, 40, 1); + + if (nk_button_image_label(ctx,media.custom_folders[BROWSER_HOME],"Home",NK_TEXT_RIGHT)) + browser_chdir_and_reload_directory_content(browser, browser->home); + + if (nk_button_image_label(ctx,media.custom_folders[BROWSER_DESKTOP],"Desktop",NK_TEXT_RIGHT)) + browser_chdir_and_reload_directory_content(browser, browser->desktop); + + if (nk_button_image_label(ctx,media.custom_folders[BROWSER_COMPUTER],"Computer",NK_TEXT_RIGHT)) + browser_chdir_and_reload_directory_content(browser, browser->computer); + + if (nk_button_image_label(ctx,media.custom_folders[BROWSER_PROJECT],"Project",NK_TEXT_RIGHT)) + browser_chdir_and_reload_directory_content(browser, browser->project); + + nk_group_end(ctx); + } + + /* output directory content window */ + if(nk_group_begin(ctx, "Content", windowed ? NK_WINDOW_NO_SCROLLBAR : 0)) { + int index = -1; + size_t i = 0, j = 0, k = 0; + size_t rows = 0; + size_t count = browser->dir_count + browser->file_count; + + rows = count / cols; + for (i = 0; i <= rows; i += 1) { + if(!tiny) + {size_t n = j + cols; + nk_layout_row_dynamic(ctx, icon_height, (int)cols); + for (; j < count && j < n; ++j) { + /* draw one row of icons */ + if (j < browser->dir_count) { + /* draw and execute directory buttons */ + if (nk_button_image(ctx,media.custom_folders[BROWSER_FOLDER])) + index = (int)j; + } else { + /* draw and execute files buttons */ + struct nk_image *icon; + size_t fileIndex = ((size_t)j - browser->dir_count); + icon = media_icon_for_file(browser->files[fileIndex]); + if (nk_button_image(ctx, *icon)) { + snprintf(browser->file, BROWSER_MAX_PATH, "%s%s", browser->directory, browser->files[fileIndex]); + clicked = 1; + } + } + }} + if(!tiny) + {size_t n = k + cols; + nk_layout_row_dynamic(ctx, 20, (int)cols); + for (; k < count && k < n; k++) { + /* draw one row of labels */ + if (k < browser->dir_count) { + nk_label(ctx, browser->directories[k], NK_TEXT_CENTERED); + } else { + size_t t = k-browser->dir_count; + nk_label(ctx,browser->files[t],NK_TEXT_CENTERED); + } + }} + if(tiny) + {size_t n = j + cols; + nk_layout_row_dynamic(ctx, icon_height, (int)cols); + for (; j < count && j < n; ++j) { + /* draw one row of icons */ + if (j < browser->dir_count) { + /* draw and execute directory buttons */ + if (nk_button_image_label(ctx,media.custom_folders[BROWSER_FOLDER], browser->directories[j],NK_TEXT_RIGHT)) + index = (int)j; + } else { + /* draw and execute files buttons */ + struct nk_image *icon; + size_t fileIndex = ((size_t)j - browser->dir_count); + icon = media_icon_for_file(browser->files[fileIndex]); + size_t t = j-browser->dir_count; + if (nk_button_image_label(ctx, *icon, browser->files[t],NK_TEXT_RIGHT)) { + snprintf(browser->file, BROWSER_MAX_PATH, "%s%s", browser->directory, browser->files[fileIndex]); + clicked = 1; + } + } +#if 0 + bool has_focus = nk_window_has_focus(ctx); // @fixme: move out of loop + bool has_popups = ui_popups(); // @fixme: move out of loop + if( !has_popups && has_focus ) { + struct nk_rect bounds = nk_widget_bounds(ctx); + if (nk_input_is_mouse_hovering_rect(&ctx->input, bounds) ) { + + char *name = j < browser->dir_count ? browser->directories[j] : browser->files[j-browser->dir_count]; + + char fullpath[PATH_MAX]; + snprintf(fullpath, PATH_MAX, "%s%s", browser->directory, name); + + struct stat t = {0}; + if( stat( fullpath, &t ) != -1 ) { + char tooltip[256]; + snprintf(tooltip, 256, + "Path: %s\n" + "Type: %lld\n" // file type and mode + "Size: %lld\n" // file size + "Owner: %lld\n" // user ID of file owner + "Modified: %s (%lld)", // last modification date + name, (int64_t)t.st_mode, (int64_t)t.st_size, (int64_t)t.st_uid, ctime(&t.st_mtime), (int64_t)t.st_mtime + ); + nk_tooltip(ctx, tooltip); + } + } + } +#endif + }} + } + + if (index != -1) { + BROWSER_PRINTF("%s + %s = ", browser->directory, browser->directories[index]); + size_t n = strlen(browser->directory); + snprintf(browser->directory + n, BROWSER_MAX_PATH - n, "%s/", browser->directories[index]); + BROWSER_PRINTF("%s\n", browser->directory); + browser_chdir_and_reload_directory_content(browser, browser->directory); + } + nk_group_end(ctx); + } + + return clicked; +} + +static struct nk_image icon_load(const char *filename) { + texture_t t = texture(filename, 0); + return nk_image_id((int)t.id); +} + +static struct nk_image icon_load_rect(unsigned id, unsigned w, unsigned h, unsigned wcell, unsigned hcell, unsigned col, unsigned row) { + return nk_subimage_id((int)id, w, h, (struct nk_rect){ wcell * col, hcell * row, wcell, hcell }); +} + + +/* demo: + + struct browser browser = {0}; + browser_init(&browser); + browser_config_dir(nk_image, BROWSER_HOME); + browser_config_dir(nk_image, BROWSER_PROJECT); + // [...] + browser_config_type(nk_image, ".ext1.ext2.ext3."); + browser_config_type(nk_image, ".ext1.ext2.ext3."); + browser_config_type(nk_image, ".ext1.ext2.ext3."); + // [...] + + [...] + + if( nk_begin(ctx, "window", ...) ) { + struct nk_rect total_space = nk_window_get_content_region(ctx); + if( browser_run(ctx, &browser, 0, total_space) ) { + puts( browser->directory ); + puts( browser->file ); + } + } + nk_end(); +*/ diff --git a/engine/split/3rd_stb_image.h b/engine/split/3rd_stb_image.h index 245eaa9..3f78b49 100644 --- a/engine/split/3rd_stb_image.h +++ b/engine/split/3rd_stb_image.h @@ -1328,7 +1328,7 @@ STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int #if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) { - return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); } #endif @@ -1345,8 +1345,8 @@ static FILE *stbi__fopen(char const *filename, char const *mode) return 0; #if defined(_MSC_VER) && _MSC_VER >= 1400 - if (0 != _wfopen_s(&f, wFilename, wMode)) - f = 0; + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; #else f = _wfopen(wFilename, wMode); #endif @@ -3436,8 +3436,8 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j) m = stbi__get_marker(j); } else { if (!stbi__process_marker(j, m)) return 1; - m = stbi__get_marker(j); - } + m = stbi__get_marker(j); + } } if (j->progressive) stbi__jpeg_finish(j); @@ -5330,7 +5330,7 @@ static int stbi__png_is16(stbi__context *s) stbi__png p; p.s = s; if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) - return 0; + return 0; if (p.depth != 16) { stbi__rewind(p.s); return 0; @@ -5574,7 +5574,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn // ensures the number computed in the second half of the test can't overflow. if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { - return stbi__errpuc("bad offset", "Corrupt BMP"); + return stbi__errpuc("bad offset", "Corrupt BMP"); } else { stbi__skip(s, info.offset - bytes_read_so_far); } @@ -7339,7 +7339,7 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) info.all_a = 255; p = stbi__bmp_parse_header(s, &info); if (p == NULL) { - stbi__rewind( s ); + stbi__rewind( s ); return 0; } if (x) *x = s->img_x; @@ -7532,7 +7532,7 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req if (ri->bits_per_channel == 16) { out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); } else { - out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); } if (out == NULL) return out; // stbi__convert_format frees input on failure } diff --git a/engine/split/3rd_stb_image_write.h b/engine/split/3rd_stb_image_write.h index e3aaa39..e4b32ed 100644 --- a/engine/split/3rd_stb_image_write.h +++ b/engine/split/3rd_stb_image_write.h @@ -493,11 +493,11 @@ static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, c { if (comp != 4) { // write RGB bitmap - int pad = (-x*3) & 3; - return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, - "11 4 22 4" "4 44 22 444444", - 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header - 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header } else { // RGBA bitmaps need a v4 header // use BI_BITFIELDS mode with 32bpp and alpha mask diff --git a/engine/split/3rd_stb_vorbis.h b/engine/split/3rd_stb_vorbis.h index a41ae1e..3e5c250 100644 --- a/engine/split/3rd_stb_vorbis.h +++ b/engine/split/3rd_stb_vorbis.h @@ -2594,14 +2594,14 @@ static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, float k00,k11; float l00,l11; - k00 = z[-0] - z[-8]; - k11 = z[-1] - z[-9]; + k00 = z[-0] - z[ -8]; + k11 = z[-1] - z[ -9]; l00 = z[-2] - z[-10]; l11 = z[-3] - z[-11]; - z[-0] = z[-0] + z[-8]; - z[-1] = z[-1] + z[-9]; - z[ -2] = z[ -2] + z[-10]; - z[ -3] = z[ -3] + z[-11]; + z[ -0] = z[-0] + z[ -8]; + z[ -1] = z[-1] + z[ -9]; + z[ -2] = z[-2] + z[-10]; + z[ -3] = z[-3] + z[-11]; z[ -8] = k00; z[ -9] = k11; z[-10] = (l00+l11) * A2; @@ -3661,7 +3661,7 @@ static int start_decoder(vorb *f) f->comment_list = NULL; if (f->comment_list_length > 0) { - f->comment_list = (char**)setup_malloc(f, sizeof(char*) * (f->comment_list_length)); + f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length)); if (f->comment_list == NULL) return error(f, VORBIS_outofmem); } diff --git a/engine/split/v4k.c.inl b/engine/split/v4k.c.inl index 911e2d9..0b980be 100644 --- a/engine/split/v4k.c.inl +++ b/engine/split/v4k.c.inl @@ -98,18 +98,6 @@ #include "v4k" #endif -#define do_threadlock(mutexptr) \ - for( int init_ = !!(mutexptr) || (thread_mutex_init( (mutexptr) = CALLOC(1, sizeof(thread_mutex_t)) ), 1); init_; init_ = 0) \ - for( int lock_ = (thread_mutex_lock( mutexptr ), 1); lock_; lock_ = (thread_mutex_unlock( mutexptr ), 0) ) - -API void *ui_handle(); -#define ui_push_hspace(px) \ - (int xx = px; xx; xx = 0) \ - for(struct nk_context *ctx = (struct nk_context*)ui_handle(); ctx; ctx = 0 ) \ - for(struct nk_panel *layout = ui_ctx->current->layout; layout; ) \ - for( xx = (layout->at_x += px, layout->bounds.w -= px, 0); layout; layout->at_x -= px, layout->bounds.w += px, layout = 0 ) - - //----------------------------------------------------------------------------- // C files @@ -160,10 +148,10 @@ API void *ui_handle(); {{FILE:v4k_scene.c}} -{{FILE:v4k_time.c}} - {{FILE:v4k_system.c}} +{{FILE:v4k_time.c}} + {{FILE:v4k_profile.c}} {{FILE:v4k_video.c}} diff --git a/engine/split/v4k.h.inl b/engine/split/v4k.h.inl index 11842d9..2fb6359 100644 --- a/engine/split/v4k.h.inl +++ b/engine/split/v4k.h.inl @@ -118,10 +118,10 @@ extern "C" { {{FILE:v4k_editor.h}} -{{FILE:v4k_font.h}} - {{FILE:v4k_file.h}} +{{FILE:v4k_font.h}} + {{FILE:v4k_input.h}} {{FILE:v4k_memory.h}} @@ -146,10 +146,10 @@ extern "C" { {{FILE:v4k_string.h}} -{{FILE:v4k_time.h}} - {{FILE:v4k_system.h}} +{{FILE:v4k_time.h}} + {{FILE:v4k_ui.h}} {{FILE:v4k_video.h}} @@ -170,7 +170,7 @@ extern "C" { #include #define gladLoadGL(func) (glewExperimental = true, glewInit() == GLEW_OK) #else - #if is(win32) /*&& is(tcc)*/ // && WITH_DLL + #if is(win32) /*&& is(tcc)*/ // && ENABLE_DLL #ifdef GLAD_API_CALL #undef GLAD_API_CALL #endif diff --git a/engine/split/v4k.x.inl b/engine/split/v4k.x.inl index 88ccaf4..417f40e 100644 --- a/engine/split/v4k.x.inl +++ b/engine/split/v4k.x.inl @@ -24,6 +24,7 @@ #define JO_MPEG_COMPONENTS 3 // jo_mpeg #define JSON5_C // json5 #define LUA_IMPL // lua544 +#define LUA_USE_POPEN 1 // for lite editor #define MINIAUDIO_IMPLEMENTATION // miniaudio #define MA_NO_FLAC // miniaudio #define NK_GLFW_GL3_IMPLEMENTATION // nuklear @@ -52,7 +53,7 @@ #define BQ_WEBSOCKET_IMPLEMENTATION // websocket #define XML_C // xml #ifdef __APPLE__ -#define MA_NO_RUNTIME_LINKING // miniaudio +#define MA_NO_RUNTIME_LINKING // miniaudio osx #define _GLFW_COCOA // glfw osx #elif defined _WIN32 #define _GLFW_WIN32 // glfw win32 @@ -101,7 +102,6 @@ errno_t fopen_s( ); #endif - //--- {{FILE:3rd_glfw3.h}} #undef timeGetTime @@ -171,18 +171,28 @@ static char *ui_filter = 0; #undef g {{FILE:3rd_polychop.h}} #define expr expr2 // 3rd_lua.h +#define EVAL_EXTEND_CONSTANTS \ + for( int vk = input_enum(id), *once = &vk; once; once = 0) \ + if( vk >= 0 ) push(ev, vk); +#define EVAL_EXTEND_FUNCTIONS \ + /**/ if(!strcmp(id, "input") && nargs ==1) push(ev, input(pop(ev))); \ + else if(!strcmp(id, "down") && nargs ==1) push(ev, input_down(pop(ev))); \ + else if(!strcmp(id, "held") && nargs ==1) push(ev, input_held(pop(ev))); \ + else if(!strcmp(id, "up") && nargs ==1) push(ev, input_up(pop(ev))); \ + else if(!strcmp(id, "idle") && nargs ==1) push(ev, input_idle(pop(ev))); {{FILE:3rd_eval.h}} -// #define SQLITE_OMIT_LOAD_EXTENSION -// #define SQLITE_CORE 1 -// #define SQLITE_DEBUG 1 -// #define Token SQToken -// #define Table SQTable -// #define rehash sqlite3__rehash -// #undef NB -//{{FILE/*:*/3rd_sqlite3.c}} -// #undef Token -// #undef Table -// #undef rehash -// #undef NB -// #undef threadid +{{FILE:3rd_luadebugger.h}} +//#define SQLITE_OMIT_LOAD_EXTENSION +//#define SQLITE_CORE 1 +//#define SQLITE_DEBUG 1 +//#define Token SQToken +//#define Table SQTable +//#define rehash sqlite3__rehash +//#undef NB +//{ {FILE:3rd_sqlite3.c}} +//#undef Token +//#undef Table +//#undef rehash +//#undef NB +//#undef threadid #endif // V4K_3RD diff --git a/engine/split/v4k_ai.c b/engine/split/v4k_ai.c index a6869b2..f4937fa 100644 --- a/engine/split/v4k_ai.c +++ b/engine/split/v4k_ai.c @@ -343,7 +343,7 @@ int pathfind_astar(int width, int height, const unsigned* map, vec2i src, vec2i #error ASTAR_POS_INDEX(p) should specify macro to map position to index #endif - #ifndef ASTAR_MAX_INDEX + #ifndef ASTAR_MAX_INDEX #error ASTAR_MAX_INDEX should specify max count of indices the position can map to #endif @@ -434,7 +434,7 @@ int pathfind_astar(int width, int height, const unsigned* map, vec2i src, vec2i i = p; \ p = (i - 1) / 2; \ } \ - } while (0) + } while (0) #define ASTAR_HEAP_POP() \ do { \ @@ -625,7 +625,7 @@ int pathfind_astar(int width, int height, const unsigned* map, vec2i src, vec2i // [ ] CompareKeys(keyVar1, operator < <= > >= == !=, keyVar2) // [ ] SetTags(names=blank,cooldownTime=inf,bIsCooldownAdditive=false) // [ ] HasTags(names=blank,bAllRequired=true) -// [ ] PushToStack(keyVar,itemObj): creates a new stack if one doesn’t exist, and stores it in the passed variable name, and then pushes ‘item’ object onto it. +// [ ] PushToStack(keyVar,itemObj): creates a new stack if one doesnt exist, and stores it in the passed variable name, and then pushes item object onto it. // [ ] PopFromStack(keyVar,itemVar): pop pops an item off the stack, and stores it in the itemVar variable, failing if the stack is already empty. // [ ] IsEmptyStack(keyVar): checks if the stack passed is empty and returns success if it is, and failure if its not. // [ ] Communication Node: This is a type of action node that allows an AI agent to communicate with other agents or entities in the game world. The node takes an input specifying the message to be communicated and the recipient(s) of the message (wildmask,l/p/f/g prefixes). The node then sends the message to the designated recipient(s) and returns success when the communication is completed. This node can be useful for implementing behaviors that require the AI agent to coordinate with other agents or to convey information to the player. It could use a radius argument to specify the maximum allowed distance for the recipients. diff --git a/engine/split/v4k_extend.c b/engine/split/v4k_extend.c index 3fb9277..5d410a8 100644 --- a/engine/split/v4k_extend.c +++ b/engine/split/v4k_extend.c @@ -1,28 +1,35 @@ // dll ------------------------------------------------------------------------ +/* deprecated #if is(win32) # include -# define dlopen(name,mode) (void*)( (name) ? LoadLibraryA(name) : GetModuleHandle(NULL)) -# define dlsym(handle,symbol) GetProcAddress((HMODULE)handle, symbol ) +# define dlopen(name,flags) (void*)( (name) ? LoadLibraryA(name) : GetModuleHandleA(NULL)) +# define dlsym(handle,symbol) GetProcAddress((HMODULE)(handle), symbol ) # define dlclose(handle) 0 #else # include +# define dlopen(name,flags) (void*)( (name) ? dlopen(name, flags) : NULL ) +# define dlsym(handle,symbol) dlsym( (handle) ? (handle) : ifdef(osx,RTLD_SELF,NULL), symbol ) #endif - -void* dll(const char *filename, const char *symbol) { -/* - char *buf, *base = file_name(filename); - if( file_exists(buf = va("%s", base)) || - file_exists(buf = va("%s.dll", base)) || - file_exists(buf = va("%s.so", base)) || - file_exists(buf = va("lib%s.so", base)) || - file_exists(buf = va("%s.dylib", base)) ) { - filename = buf; - } */ - void *dll = dlopen(filename, RTLD_NOW | RTLD_LOCAL); - dll = dll ? dlsym(dll, symbol) : 0; - return dll; + +void* dll(const char *fname, const char *symbol) { + if( fname && !file_exist(fname) ) { + char *buf, *path = file_path(fname), *base = file_base(fname); + if( file_exist(buf = va("%s%s.dll", path, base)) || + file_exist(buf = va("%s%s.so", path, base)) || + file_exist(buf = va("%slib%s.so", path, base)) || + file_exist(buf = va("%s%s.dylib", path, base)) ) { + fname = (const char *)buf; + } else { + return NULL; + } + } +#if is(win32) + return (void*)GetProcAddress(fname ? LoadLibraryA(fname) : GetModuleHandleA(NULL), symbol); +#else + return dlsym(fname ? dlopen(fname, RTLD_NOW|RTLD_LOCAL) : ifdef(osx, RTLD_SELF, NULL), symbol); +#endif } #if 0 // demo: cl demo.c /LD && REM dll @@ -210,3 +217,72 @@ bool script_tests() { } #undef XMACRO + +// script v2 ------------------------------------------------------------------ + +#define luaL_dostringsafe(L, str) \ + luaL_dostring(L, \ + "xpcall(function()\n" \ + str \ + "end, function(err)\n" \ + " print('Error: ' .. tostring(err))\n" \ + " print(debug.traceback(nil, 2))\n" \ + " if core and core.on_error then\n" \ + " pcall(core.on_error, err)\n" \ + " end\n" \ + " os.exit(1)\n" \ + "end)" \ + ); + +static int f_vfs_read(lua_State *L) { + char *file = file_normalize(luaL_checkstring(L, 1)); + if( strbegi(file, app_path()) ) file += strlen(app_path()); + strswap(file+1, ".", "/"); + strswap(file+1, "/lua", ".lua"); + int len; char *data = vfs_load(file, &len); + if( len ) { + data = memcpy(MALLOC(len+1), data, len), data[len] = 0; + //tty_color(data ? GREEN : RED); + //printf("%s (%s)\n%s", file, data ? "ok" : "failed", data); + //tty_color(0); + } + return lua_pushstring(L, data), 1; // "\n\tcannot find `%s` within mounted zipfiles", file), 1; +} + +// add our zip loader at the end of package.loaders +void lua_add_ziploader(lua_State* L) { + lua_pushcfunction( L, f_vfs_read ); + lua_setglobal( L, "vfs_read" ); + + luaL_dostringsafe(L, +// "package.path = [[;;<>;]]\n" // .. package.path\n" + "package.searchers[#package.searchers + 1] = function(libraryname)\n" + " for pattern in string.gmatch( package.path, '[^;]+' ) do\n" + " local proper_path = string.gsub(pattern, '?', libraryname)\n" + " local f = vfs_read(proper_path)\n" + " if f ~= nil then\n" + " return load(f, proper_path)\n" + " end\n" + " end\n" + " return nil\n" + "end\n" + ); +} + +void *script_init_env(unsigned flags) { + if( flags & SCRIPT_LUA ) { + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + + if( flags & SCRIPT_DEBUGGER ) { + // Register debuggers/inspectors + // luaL_dostringsafe(L, "I = require('inspect').inspect\n"); + dbg_setup_default(L); + } + + lua_add_ziploader(L); + return L; + } + + return 0; +} diff --git a/engine/split/v4k_extend.h b/engine/split/v4k_extend.h index 43eb9e3..3254ffa 100644 --- a/engine/split/v4k_extend.h +++ b/engine/split/v4k_extend.h @@ -22,3 +22,13 @@ API void script_bind_function(const char *c_name, void *c_function); API void script_call(const char *lua_function); API bool script_tests(); + +// ----------------------------------------------------------------------------- +// script framework + +enum { + SCRIPT_LUA = 1, + SCRIPT_DEBUGGER = 2, +}; + +API void *script_init_env(unsigned flags); diff --git a/engine/split/v4k_file.c b/engine/split/v4k_file.c index 2f86edb..30cbe29 100644 --- a/engine/split/v4k_file.c +++ b/engine/split/v4k_file.c @@ -161,7 +161,7 @@ char *file_id(const char *pathfile) { char *ext = strchr(base, '.'); if (ext) ext[0] = '\0'; // remove all extensions #else // extensionless for audio/images only (materials: diffuse.tga and diffuse.png will match) char *ext = strrchr(base, '.'); //if (ext) ext[0] = '\0'; // remove all extensions - if(ext) if( strstr(".jpg.png.bmp.tga"".", ext) || strstr(".ogg.mp3.wav.mod.xm.flac"".", ext) || strstr(".mp4.ogv.avi.mkv.wmv.mpg.mpeg"".", ext) ) { + if(ext) if( strstr(".jpg.png.bmp.tga.hdr"".", ext) || strstr(".ogg.mp3.wav.mod.xm.flac"".", ext) || strstr(".mp4.ogv.avi.mkv.wmv.mpg.mpeg"".", ext) ) { ext = strchr(base, '.'); ext[0] = '\0'; //strcpy(ext, "_xxx"); } diff --git a/engine/split/v4k_input.h b/engine/split/v4k_input.h index 5c17fa4..88cb154 100644 --- a/engine/split/v4k_input.h +++ b/engine/split/v4k_input.h @@ -99,7 +99,7 @@ enum INPUT_ENUMS { KEY_PAD1,KEY_PAD2,KEY_PAD3,KEY_PAD4,KEY_PAD5,KEY_PAD6,KEY_PAD7,KEY_PAD8,KEY_PAD9,KEY_PAD0, // beware: complicated on laptops KEY_PADADD,KEY_PADSUB,KEY_PADMUL,KEY_PADDIV,KEY_PADDOT,KEY_PADENTER, // beware: complicated on laptops - MOUSE_L, MOUSE_M, MOUSE_R, + MOUSE_L, MOUSE_M, MOUSE_R, // @todo: MOUSE_CLICKS, GAMEPAD_CONNECTED, GAMEPAD_A, GAMEPAD_B, GAMEPAD_X, GAMEPAD_Y, GAMEPAD_UP, GAMEPAD_DOWN, GAMEPAD_LEFT, GAMEPAD_RIGHT, GAMEPAD_MENU, GAMEPAD_START, GAMEPAD_LB, GAMEPAD_RB, GAMEPAD_LTHUMB, GAMEPAD_RTHUMB, diff --git a/engine/split/v4k_render.h b/engine/split/v4k_render.h index 1eccd77..5971acc 100644 --- a/engine/split/v4k_render.h +++ b/engine/split/v4k_render.h @@ -106,6 +106,7 @@ enum TEXTURE_FLAGS { // @fixme TEXTURE_SRGB = 1 << 24, TEXTURE_BGR = 1 << 25, + TEXTURE_BGRA = TEXTURE_BGR, TEXTURE_ARRAY = 1 << 26, }; diff --git a/engine/split/v4k_string.c b/engine/split/v4k_string.c index e38594a..34a5aa0 100644 --- a/engine/split/v4k_string.c +++ b/engine/split/v4k_string.c @@ -13,7 +13,7 @@ char* tempvl(const char *fmt, va_list vl) { static __thread char buf[STACK_ALLOC]; #else int heap = 1; - static __thread int STACK_ALLOC = 128*1024; + static __thread int STACK_ALLOC = 512*1024; static __thread char *buf = 0; if(!buf) buf = REALLOC(0, STACK_ALLOC); // @leak #endif static __thread int cur = 0; //printf("string stack %d/%d\n", cur, STACK_ALLOC); diff --git a/engine/split/v4k_string.h b/engine/split/v4k_string.h index 7ef04a9..439f962 100644 --- a/engine/split/v4k_string.h +++ b/engine/split/v4k_string.h @@ -5,6 +5,7 @@ API char* tempvl(const char *fmt, va_list); API char* tempva(const char *fmt, ...); #define va(...) (((&printf) || printf(__VA_ARGS__), tempva(__VA_ARGS__))) // vs2015 check trick +#define vac (const char*)va // string: allocated api (heap). FREE() after use API char* strcatf(char **s, const char *buf); diff --git a/engine/split/v4k_time.c b/engine/split/v4k_time.c index c2b113e..a2d0d26 100644 --- a/engine/split/v4k_time.c +++ b/engine/split/v4k_time.c @@ -509,8 +509,8 @@ void curve_add(curve_t *c, vec3 p) { array_push(c->points, p); } -void curve_finish( curve_t *c, int k ) { - assert( k > 0 ); +void curve_end( curve_t *c, int k ) { + ASSERT( k > 0 ); array_free(c->lengths); array_free(c->samples); diff --git a/engine/split/v4k_time.h b/engine/split/v4k_time.h index a14ac5a..3aadecd 100644 --- a/engine/split/v4k_time.h +++ b/engine/split/v4k_time.h @@ -151,6 +151,6 @@ typedef struct curve_t { API curve_t curve(); API void curve_add(curve_t *c, vec3 p); -API void curve_finish(curve_t *c, int num_points); +API void curve_end(curve_t *c, int num_points); API vec3 curve_eval(curve_t *c, float dt, unsigned *color); API void curve_destroy(curve_t *c); diff --git a/engine/split/v4k_ui.c b/engine/split/v4k_ui.c index 969b355..6a0181d 100644 --- a/engine/split/v4k_ui.c +++ b/engine/split/v4k_ui.c @@ -2503,7 +2503,7 @@ int ui_browse(const char **output, bool *inlined) { // if(ui_ctx->current) bounds = nk_window_get_bounds(ui_ctx), P(bounds); // if(ui_ctx->current) bounds = nk_window_get_content_region(ui_ctx), P(bounds); // if(ui_ctx->current) nk_layout_peek(&bounds, ui_ctx), P(bounds); - // // if(ui_ctx->current) nk_layout_widget_space(&bounds, ui_ctx, ui_ctx->current, nk_false), P(bounds); // note: cant be used within a panel + // if(ui_ctx->current) nk_layout_widget_space(&bounds, ui_ctx, ui_ctx->current, nk_false), P(bounds); // note: cant be used within a panel // #undef P // panel diff --git a/engine/split/v4k_window.c b/engine/split/v4k_window.c index e886385..3502896 100644 --- a/engine/split/v4k_window.c +++ b/engine/split/v4k_window.c @@ -971,10 +971,10 @@ void window_cursor_shape(unsigned mode) { 0, GLFW_ARROW_CURSOR, GLFW_IBEAM_CURSOR, - GLFW_CROSSHAIR_CURSOR, - GLFW_HAND_CURSOR, GLFW_HRESIZE_CURSOR, GLFW_VRESIZE_CURSOR, + GLFW_HAND_CURSOR, + GLFW_CROSSHAIR_CURSOR, }; do_once { static unsigned pixels[16 * 16] = { 0x01000000 }; // ABGR(le) glfw3 note: A(0x00) means 0xFF for some reason @@ -1067,4 +1067,17 @@ int window_has_maximize() { return ifdef(ems, 0, glfwGetWindowAttrib(window, GLFW_MAXIMIZED) == GLFW_TRUE); } +const char *window_clipboard() { + return glfwGetClipboardString(window); +} +void window_setclipboard(const char *text) { + glfwSetClipboardString(window, text); +} +static +double window_scale() { // ok? @testme + float xscale, yscale; + GLFWmonitor *monitor = glfwGetPrimaryMonitor(); + glfwGetMonitorContentScale(monitor, &xscale, &yscale); + return maxi(xscale, yscale); +} diff --git a/engine/split/v4k_window.h b/engine/split/v4k_window.h index c097a49..94f1fe3 100644 --- a/engine/split/v4k_window.h +++ b/engine/split/v4k_window.h @@ -85,11 +85,14 @@ enum CURSOR_SHAPES { CURSOR_NONE, CURSOR_HW_ARROW, // default CURSOR_HW_IBEAM, // i-beam text cursor - CURSOR_HW_CROSS, // crosshair - CURSOR_HW_HAND, // hand, clickable CURSOR_HW_HDRAG, // horizontal drag/resize CURSOR_HW_VDRAG, // vertical drag/resize + CURSOR_HW_HAND, // hand, clickable + CURSOR_HW_CROSS, // crosshair CURSOR_SW_AUTO, // software cursor, ui driven. note: this is the only icon that may be recorded or snapshotted }; API void window_cursor_shape(unsigned shape); + +API const char *window_clipboard(); +API void window_setclipboard(const char *text); diff --git a/engine/v4k b/engine/v4k index fd6b71f..bdcf1b4 100644 --- a/engine/v4k +++ b/engine/v4k @@ -13952,6 +13952,7 @@ int gladLoadGL( GLADloadfunc load) { #define JO_MPEG_COMPONENTS 3 // jo_mpeg #define JSON5_C // json5 #define LUA_IMPL // lua544 +#define LUA_USE_POPEN 1 // for lite editor #define MINIAUDIO_IMPLEMENTATION // miniaudio #define MA_NO_FLAC // miniaudio #define NK_GLFW_GL3_IMPLEMENTATION // nuklear @@ -13980,7 +13981,7 @@ int gladLoadGL( GLADloadfunc load) { #define BQ_WEBSOCKET_IMPLEMENTATION // websocket #define XML_C // xml #ifdef __APPLE__ -#define MA_NO_RUNTIME_LINKING // miniaudio +#define MA_NO_RUNTIME_LINKING // miniaudio osx #define _GLFW_COCOA // glfw osx #elif defined _WIN32 #define _GLFW_WIN32 // glfw win32 @@ -14029,7 +14030,6 @@ errno_t fopen_s( ); #endif - //--- #line 1 "engine/split/3rd_glfw3.h" #ifndef __EMSCRIPTEN__ @@ -56529,14 +56529,14 @@ static void imdct_step3_inner_s_loop_ld654(int n, float *e, int i_off, float *A, float k00,k11; float l00,l11; - k00 = z[-0] - z[-8]; - k11 = z[-1] - z[-9]; + k00 = z[-0] - z[ -8]; + k11 = z[-1] - z[ -9]; l00 = z[-2] - z[-10]; l11 = z[-3] - z[-11]; - z[-0] = z[-0] + z[-8]; - z[-1] = z[-1] + z[-9]; - z[ -2] = z[ -2] + z[-10]; - z[ -3] = z[ -3] + z[-11]; + z[ -0] = z[-0] + z[ -8]; + z[ -1] = z[-1] + z[ -9]; + z[ -2] = z[-2] + z[-10]; + z[ -3] = z[-3] + z[-11]; z[ -8] = k00; z[ -9] = k11; z[-10] = (l00+l11) * A2; @@ -57596,7 +57596,7 @@ static int start_decoder(vorb *f) f->comment_list = NULL; if (f->comment_list_length > 0) { - f->comment_list = (char**)setup_malloc(f, sizeof(char*) * (f->comment_list_length)); + f->comment_list = (char**) setup_malloc(f, sizeof(char*) * (f->comment_list_length)); if (f->comment_list == NULL) return error(f, VORBIS_outofmem); } @@ -182887,7 +182887,7 @@ STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int #if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) { - return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); } #endif @@ -182904,8 +182904,8 @@ static FILE *stbi__fopen(char const *filename, char const *mode) return 0; #if defined(_MSC_VER) && _MSC_VER >= 1400 - if (0 != _wfopen_s(&f, wFilename, wMode)) - f = 0; + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; #else f = _wfopen(wFilename, wMode); #endif @@ -184995,8 +184995,8 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j) m = stbi__get_marker(j); } else { if (!stbi__process_marker(j, m)) return 1; - m = stbi__get_marker(j); - } + m = stbi__get_marker(j); + } } if (j->progressive) stbi__jpeg_finish(j); @@ -186889,7 +186889,7 @@ static int stbi__png_is16(stbi__context *s) stbi__png p; p.s = s; if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) - return 0; + return 0; if (p.depth != 16) { stbi__rewind(p.s); return 0; @@ -187133,7 +187133,7 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn // ensures the number computed in the second half of the test can't overflow. if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { - return stbi__errpuc("bad offset", "Corrupt BMP"); + return stbi__errpuc("bad offset", "Corrupt BMP"); } else { stbi__skip(s, info.offset - bytes_read_so_far); } @@ -188898,7 +188898,7 @@ static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) info.all_a = 255; p = stbi__bmp_parse_header(s, &info); if (p == NULL) { - stbi__rewind( s ); + stbi__rewind( s ); return 0; } if (x) *x = s->img_x; @@ -189091,7 +189091,7 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req if (ri->bits_per_channel == 16) { out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); } else { - out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); } if (out == NULL) return out; // stbi__convert_format frees input on failure } @@ -190041,11 +190041,11 @@ static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, c { if (comp != 4) { // write RGB bitmap - int pad = (-x*3) & 3; - return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, - "11 4 22 4" "4 44 22 444444", - 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header - 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header } else { // RGBA bitmaps need a v4 header // use BI_BITFIELDS mode with 32bpp and alpha mask @@ -216555,6 +216555,7 @@ nk_selectable_text(struct nk_context *ctx, const char *str, int len, state = nk_widget(&bounds, ctx); if (!state) return 0; in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; + return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds, str, len, align, value, &style->selectable, in, style->font); } @@ -236090,8 +236091,12 @@ struct dir { // --- -#if !defined(S_ISDIR) -# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#ifndef S_ISDIR +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) #endif int dir_yield(dir *d, const char *pathfile, char *name, int namelen) { @@ -277528,12 +277533,12 @@ Compiling ---------- Simple TLS client: -`$ gcc tlshello.c -o tlshello -ltomcrypt -ltommath -DLTM_DESC` +`$ gcc tlshello.c -o tlshello -ltomcrypt -ltommath -DLTM_DESC` For debuging tls connections, the DEBUG flag must be set (-DDEBUG). Simple TLS server: -`$ gcc tlsserverhello.c -o tlsserverhello -ltomcrypt -ltommath -DLTM_DESC` +`$ gcc tlsserverhello.c -o tlsserverhello -ltomcrypt -ltommath -DLTM_DESC` The entire library is a single c file that you just include in your source. @@ -277554,7 +277559,7 @@ TLSe supports KTLS on linux kernel 4.13 or higher. KTLS is a TLS implementation Usage ---------- -You just +You just `#include "tlse.c"` in your code. Everything is a single file. @@ -277965,7 +277970,7 @@ int tls_make_ktls(struct TLSContext *context, int socket); int tls_unmake_ktls(struct TLSContext *context, int socket); /* Creates a new DTLS random cookie secret to be used in HelloVerifyRequest (server-side). - It is recommended to call this function from time to time, to protect against some + It is recommended to call this function from time to time, to protect against some DoS attacks. */ void dtls_reset_cookie_secret(); @@ -278059,17 +278064,17 @@ int tls_remote_error(struct TLSContext *context); /******************************************************************************** Copyright (c) 2016-2023, Eduard Suica All rights reserved. - + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. @@ -278884,7 +278889,7 @@ int chacha20_poly1305_aead(struct chacha_ctx *ctx, unsigned char *pt, unsigned unsigned int counter = 1; chacha_ivsetup_96bitnonce(ctx, NULL, (unsigned char *)&counter); chacha_encrypt_bytes(ctx, pt, out, len); - + poly1305_context aead_ctx; _private_tls_poly1305_init(&aead_ctx, poly_key); _private_tls_poly1305_update(&aead_ctx, aad, aad_len); @@ -278904,7 +278909,7 @@ int chacha20_poly1305_aead(struct chacha_ctx *ctx, unsigned char *pt, unsigned _private_tls_poly1305_update(&aead_ctx, trail, 16); _private_tls_poly1305_finish(&aead_ctx, out + len); - + return len + POLY1305_TAGLEN; } #endif @@ -279276,19 +279281,19 @@ struct TLSContext { unsigned char cipher_spec_set; TLSCipher crypto; TLSHash *handshake_hash; - + unsigned char *message_buffer; unsigned int message_buffer_len; uint64_t remote_sequence_number; uint64_t local_sequence_number; - + unsigned char connection_status; unsigned char critical_error; unsigned char error_code; - + unsigned char *tls_buffer; unsigned int tls_buffer_len; - + unsigned char *application_buffer; unsigned int application_buffer_len; unsigned char is_child; @@ -279448,10 +279453,10 @@ void _private_b64_decodeblock(unsigned char in[4], unsigned char out[3]) { int _private_b64_decode(const char *in_buffer, int in_buffer_size, unsigned char *out_buffer) { unsigned char in[4], out[3], v; int i, len; - + const char *ptr = in_buffer; char *out_ptr = (char *)out_buffer; - + while (ptr <= in_buffer + in_buffer_size) { for (len = 0, i = 0; i < 4 && (ptr <= in_buffer + in_buffer_size); i++) { v = 0; @@ -279519,26 +279524,26 @@ int _private_tls_dh_shared_secret(DHKey *private_key, DHKey *public_key, unsigne void *tmp; unsigned long x; int err; - + if ((!private_key) || (!public_key) || (!out) || (!outlen)) return TLS_GENERIC_ERROR; - + /* compute y^x mod p */ if ((err = mp_init(&tmp)) != CRYPT_OK) return err; - + if ((err = mp_exptmod(public_key->y, private_key->x, private_key->p, tmp)) != CRYPT_OK) { mp_clear(tmp); return err; } - + x = (unsigned long)mp_unsigned_bin_size(tmp); if (*outlen < x) { err = CRYPT_BUFFER_OVERFLOW; mp_clear(tmp); return err; } - + if ((err = mp_to_unsigned_bin(tmp, out)) != CRYPT_OK) { mp_clear(tmp); return err; @@ -279554,10 +279559,10 @@ unsigned char *_private_tls_decrypt_dhe(struct TLSContext *context, const unsign DEBUG_PRINT("No private DHE key set\n"); return NULL; } - + unsigned long out_size = len; void *Yc = NULL; - + if (mp_init(&Yc)) { DEBUG_PRINT("ERROR CREATING Yc\n"); return NULL; @@ -279571,7 +279576,7 @@ unsigned char *_private_tls_decrypt_dhe(struct TLSContext *context, const unsign unsigned char *out = (unsigned char *)TLS_MALLOC(len); DHKey client_key; memset(&client_key, 0, sizeof(DHKey)); - + client_key.p = context->dhe->p; client_key.g = context->dhe->g; client_key.y = Yc; @@ -279600,15 +279605,15 @@ unsigned char *_private_tls_decrypt_ecc_dhe(struct TLSContext *context, const un DEBUG_PRINT("No private ECC DHE key set\n"); return NULL; } - + const struct ECCCurveParameters *curve; if (context->curve) curve = context->curve; else curve = default_curve; - + ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&curve->dp; - + ecc_key client_key; memset(&client_key, 0, sizeof(client_key)); if (ecc_ansi_x963_import_ex(buffer, len, &client_key, dp)) { @@ -279617,7 +279622,7 @@ unsigned char *_private_tls_decrypt_ecc_dhe(struct TLSContext *context, const un } unsigned char *out = (unsigned char *)TLS_MALLOC(len); unsigned long out_size = len; - + int err = ecc_shared_secret(context->ecc_dhe, &client_key, out, &out_size); ecc_free(&client_key); if (clear_key) @@ -279644,7 +279649,7 @@ unsigned char *_private_tls_decrypt_rsa(struct TLSContext *context, const unsign rsa_key key; int err; err = rsa_import(context->private_key->der_bytes, context->private_key->der_len, &key); - + if (err) { DEBUG_PRINT("Error importing RSA key (code: %i)\n", err); return NULL; @@ -279678,7 +279683,7 @@ unsigned char *_private_tls_encrypt_rsa(struct TLSContext *context, const unsign rsa_key key; int err; err = rsa_import(context->certificates[0]->der_bytes, context->certificates[0]->der_len, &key); - + if (err) { DEBUG_PRINT("Error importing RSA certificate (code: %i)\n", err); return NULL; @@ -279702,28 +279707,28 @@ int _private_rsa_verify_hash_md5sha1(const unsigned char *sig, unsigned long sig unsigned long modulus_bitlen, modulus_bytelen, x; int err; unsigned char *tmpbuf = NULL; - + if ((hash == NULL) || (sig == NULL) || (stat == NULL) || (key == NULL) || (!siglen) || (!hashlen)) return TLS_GENERIC_ERROR; - + *stat = 0; - + modulus_bitlen = mp_count_bits((key->N)); - + modulus_bytelen = mp_unsigned_bin_size((key->N)); if (modulus_bytelen != siglen) return TLS_GENERIC_ERROR; - + tmpbuf = (unsigned char *)TLS_MALLOC(siglen); if (!tmpbuf) return TLS_GENERIC_ERROR; - + x = siglen; if ((err = ltc_mp.rsa_me(sig, siglen, tmpbuf, &x, PK_PUBLIC, key)) != CRYPT_OK) { TLS_FREE(tmpbuf); return err; } - + if (x != siglen) { TLS_FREE(tmpbuf); return CRYPT_INVALID_PACKET; @@ -279734,7 +279739,7 @@ int _private_rsa_verify_hash_md5sha1(const unsigned char *sig, unsigned long sig TLS_FREE(tmpbuf); return TLS_GENERIC_ERROR; } - + int decoded = 0; err = pkcs_1_v1_5_decode(tmpbuf, x, LTC_PKCS_1_EMSA, modulus_bitlen, out, &out_len, &decoded); if (decoded) { @@ -279743,7 +279748,7 @@ int _private_rsa_verify_hash_md5sha1(const unsigned char *sig, unsigned long sig *stat = 1; } } - + TLS_FREE(tmpbuf); TLS_FREE(out); return err; @@ -279754,7 +279759,7 @@ int _private_tls_verify_rsa(struct TLSContext *context, unsigned int hash_type, tls_init(); rsa_key key; int err; - + if (context->is_server) { if ((!len) || (!context->client_certificates) || (!context->client_certificates_count) || (!context->client_certificates[0]) || (!context->client_certificates[0]->der_bytes) || (!context->client_certificates[0]->der_len)) { @@ -279882,12 +279887,12 @@ int _private_tls_verify_rsa(struct TLSContext *context, unsigned int hash_type, int _private_rsa_sign_hash_md5sha1(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; - + if ((in == NULL) || (out == NULL) || (outlen == NULL) || (key == NULL)) return TLS_GENERIC_ERROR; - + modulus_bitlen = mp_count_bits((key->N)); - + modulus_bytelen = mp_unsigned_bin_size((key->N)); if (modulus_bytelen > *outlen) { *outlen = modulus_bytelen; @@ -279897,7 +279902,7 @@ int _private_rsa_sign_hash_md5sha1(const unsigned char *in, unsigned long inlen, err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x); if (err != CRYPT_OK) return err; - + return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key); } #endif @@ -279911,7 +279916,7 @@ int _private_tls_sign_rsa(struct TLSContext *context, unsigned int hash_type, co rsa_key key; int err; err = rsa_import(context->private_key->der_bytes, context->private_key->der_len, &key); - + if (err) { DEBUG_PRINT("Error importing RSA certificate (code: %i)\n", err); return TLS_GENERIC_ERROR; @@ -280020,7 +280025,7 @@ int _private_tls_sign_rsa(struct TLSContext *context, unsigned int hash_type, co rsa_free(&key); if (err) return 0; - + return 1; } @@ -280028,11 +280033,11 @@ int _private_tls_sign_rsa(struct TLSContext *context, unsigned int hash_type, co static int _private_tls_is_point(ecc_key *key) { void *prime, *b, *t1, *t2; int err; - + if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL)) != CRYPT_OK) { return err; } - + /* load prime and b */ if ((err = mp_read_radix(prime, TLS_TOMCRYPT_PRIVATE_DP(key)->prime, 16)) != CRYPT_OK) { goto error; @@ -280040,12 +280045,12 @@ static int _private_tls_is_point(ecc_key *key) { if ((err = mp_read_radix(b, TLS_TOMCRYPT_PRIVATE_DP(key)->B, 16)) != CRYPT_OK) { goto error; } - + /* compute y^2 */ if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; } - + /* compute x^3 */ if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; @@ -280056,12 +280061,12 @@ static int _private_tls_is_point(ecc_key *key) { if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; } - + /* compute y^2 - x^3 */ if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; } - + /* compute y^2 - x^3 + 3x */ if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; @@ -280085,14 +280090,14 @@ static int _private_tls_is_point(ecc_key *key) { goto error; } } - + /* compare to b */ if (mp_cmp(t1, b) != LTC_MP_EQ) { err = CRYPT_INVALID_PACKET; } else { err = CRYPT_OK; } - + error: mp_clear_multi(prime, b, t1, t2, NULL); return err; @@ -280100,15 +280105,15 @@ error: int _private_tls_ecc_import_key(const unsigned char *private_key, int private_len, const unsigned char *public_key, int public_len, ecc_key *key, const ltc_ecc_set_type *dp) { int err; - + if ((!key) || (!ltc_mp.name)) return CRYPT_MEM; - + key->type = PK_PRIVATE; - + if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) return CRYPT_MEM; - + if ((public_len) && (!public_key[0])) { public_key++; public_len--; @@ -280117,33 +280122,33 @@ int _private_tls_ecc_import_key(const unsigned char *private_key, int private_le mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)public_key + 1 + ((public_len - 1) >> 1), (public_len - 1) >> 1)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)private_key, private_len)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + TLS_TOMCRYPT_PRIVATE_SET_INDEX(key, -1); TLS_TOMCRYPT_PRIVATE_DP(key) = dp; - + /* set z */ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + /* is it a point on the curve? */ if ((err = _private_tls_is_point(key)) != CRYPT_OK) { DEBUG_PRINT("KEY IS NOT ON CURVE\n"); mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + /* we're good */ return CRYPT_OK; } @@ -280154,9 +280159,9 @@ int _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, DEBUG_PRINT("No private ECDSA key set\n"); return TLS_GENERIC_ERROR; } - + const struct ECCCurveParameters *curve = NULL; - + switch (context->ec_private_key->ec_algorithm) { case 19: curve = &secp192r1; @@ -280182,16 +280187,16 @@ int _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, default: DEBUG_PRINT("UNSUPPORTED CURVE\n"); } - + if (!curve) return TLS_GENERIC_ERROR; - + tls_init(); ecc_key key; int err; - + ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&curve->dp; - + // broken ... fix this err = _private_tls_ecc_import_key(context->ec_private_key->priv, context->ec_private_key->priv_len, context->ec_private_key->pk, context->ec_private_key->pk_len, &key, dp); if (err) { @@ -280270,7 +280275,7 @@ int _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, hash_len = 36; break; } - + if (err) { DEBUG_PRINT("Unsupported hash type: %i\n", hash_type); return TLS_GENERIC_ERROR; @@ -280283,22 +280288,22 @@ int _private_tls_sign_ecdsa(struct TLSContext *context, unsigned int hash_type, ecc_free(&key); if (err) return 0; - + return 1; } #if defined(TLS_CLIENT_ECDSA) || defined(WITH_TLS_13) int _private_tls_ecc_import_pk(const unsigned char *public_key, int public_len, ecc_key *key, const ltc_ecc_set_type *dp) { int err; - + if ((!key) || (!ltc_mp.name)) return CRYPT_MEM; - + key->type = PK_PUBLIC; - + if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) return CRYPT_MEM; - + if ((public_len) && (!public_key[0])) { public_key++; public_len--; @@ -280307,29 +280312,29 @@ int _private_tls_ecc_import_pk(const unsigned char *public_key, int public_len, mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)public_key + 1 + ((public_len - 1) >> 1), (public_len - 1) >> 1)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - - + + TLS_TOMCRYPT_PRIVATE_SET_INDEX(key, -1); TLS_TOMCRYPT_PRIVATE_DP(key) = dp; - + /* set z */ if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + /* is it a point on the curve? */ if ((err = _private_tls_is_point(key)) != CRYPT_OK) { DEBUG_PRINT("KEY IS NOT ON CURVE\n"); mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL); return err; } - + /* we're good */ return CRYPT_OK; } @@ -280471,10 +280476,10 @@ void _private_tls_sleep(unsigned int microseconds) { Sleep(microseconds/1000); #else struct timespec ts; - + ts.tv_sec = (unsigned int) (microseconds / 1000000); ts.tv_nsec = (unsigned int) (microseconds % 1000000) * 1000ul; - + nanosleep(&ts, NULL); #endif } @@ -280493,10 +280498,10 @@ void _private_tls_prf_helper(int hash_idx, unsigned long dlen, unsigned char *ou unsigned char digest_out1[TLS_MAX_HASH_LEN]; unsigned int i; hmac_state hmac; - + hmac_init(&hmac, hash_idx, secret, secret_len); hmac_process(&hmac, label, label_len); - + hmac_process(&hmac, seed, seed_len); if ((seed_b) && (seed_b_len)) hmac_process(&hmac, seed_b, seed_b_len); @@ -280510,19 +280515,19 @@ void _private_tls_prf_helper(int hash_idx, unsigned long dlen, unsigned char *ou if ((seed_b) && (seed_b_len)) hmac_process(&hmac, seed_b, seed_b_len); hmac_done(&hmac, digest_out1, &dlen); - + unsigned int copylen = outlen; if (copylen > dlen) copylen = dlen; - + for (i = 0; i < copylen; i++) { output[idx++] ^= digest_out1[i]; outlen--; } - + if (!outlen) break; - + hmac_init(&hmac, hash_idx, secret, secret_len); hmac_process(&hmac, digest_out0, dlen); hmac_done(&hmac, digest_out0, &dlen); @@ -280592,18 +280597,18 @@ void _private_tls_hkdf_expand(unsigned int mac_length, unsigned char *output, un i2++; hmac_process(&hmac, &i2, 1); hmac_done(&hmac, digest_out, &dlen); - + unsigned int copylen = outlen; if (copylen > dlen) copylen = (unsigned int)dlen; - + for (i = 0; i < copylen; i++) { output[idx++] = digest_out[i]; outlen--; } - + if (!outlen) - break; + break; } } @@ -280627,7 +280632,7 @@ void _private_tls_prf(struct TLSContext *context, int md5_hash_idx = find_hash("md5"); int sha1_hash_idx = find_hash("sha1"); int half_secret = (secret_len + 1) / 2; - + memset(output, 0, outlen); _private_tls_prf_helper(md5_hash_idx, 16, output, outlen, secret, half_secret, label, label_len, seed, seed_len, seed_b, seed_b_len); _private_tls_prf_helper(sha1_hash_idx, 20, output, outlen, secret + (secret_len - half_secret), secret_len - half_secret, label, label_len, seed, seed_len, seed_b, seed_b_len); @@ -280645,10 +280650,10 @@ void _private_tls_prf(struct TLSContext *context, hash_idx = find_hash("sha256"); unsigned int i; hmac_state hmac; - + hmac_init(&hmac, hash_idx, secret, secret_len); hmac_process(&hmac, label, label_len); - + hmac_process(&hmac, seed, seed_len); if ((seed_b) && (seed_b_len)) hmac_process(&hmac, seed_b, seed_b_len); @@ -280662,19 +280667,19 @@ void _private_tls_prf(struct TLSContext *context, if ((seed_b) && (seed_b_len)) hmac_process(&hmac, seed_b, seed_b_len); hmac_done(&hmac, digest_out1, &dlen); - + unsigned int copylen = outlen; if (copylen > dlen) copylen = (unsigned int)dlen; - + for (i = 0; i < copylen; i++) { output[idx++] = digest_out1[i]; outlen--; } - + if (!outlen) break; - + hmac_init(&hmac, hash_idx, secret, secret_len); hmac_process(&hmac, digest_out0, dlen); hmac_done(&hmac, digest_out0, &dlen); @@ -280795,8 +280800,8 @@ int _private_tls13_key(struct TLSContext *context, int handshake) { unsigned int mac_length = _private_tls_mac_length(context); if ((!context->premaster_key) || (!context->premaster_key_len)) - return 0; - + return 0; + if ((!key_length) || (!mac_length)) { DEBUG_PRINT("KEY EXPANSION FAILED, KEY LENGTH: %i, MAC LENGTH: %i\n", key_length, mac_length); return 0; @@ -280901,7 +280906,7 @@ int _private_tls13_key(struct TLSContext *context, int handshake) { DEBUG_DUMP_HEX_LABEL("CLIENT IV", clientiv, iv_length) DEBUG_DUMP_HEX_LABEL("SERVER KEY", serverkey, key_length) DEBUG_DUMP_HEX_LABEL("SERVER IV", serveriv, iv_length) - + TLS_FREE(context->finished_key); TLS_FREE(context->remote_finished_key); if (handshake) { @@ -280974,7 +280979,7 @@ int _private_tls13_key(struct TLSContext *context, int handshake) { } context->local_sequence_number = 0; context->remote_sequence_number = 0; - + // extract client_mac_key(mac_key_length) // extract server_mac_key(mac_key_length) // extract client_key(enc_key_length) @@ -280991,13 +280996,13 @@ int _private_tls_expand_key(struct TLSContext *context) { if ((context->version == TLS_V13) || (context->version == DTLS_V13)) return 0; #endif - + if ((!context->master_key) || (!context->master_key_len)) return 0; - + int key_length = _private_tls_key_length(context); int mac_length = _private_tls_mac_length(context); - + if ((!key_length) || (!mac_length)) { DEBUG_PRINT("KEY EXPANSION FAILED, KEY LENGTH: %i, MAC LENGTH: %i\n", key_length, mac_length); return 0; @@ -281012,13 +281017,13 @@ int _private_tls_expand_key(struct TLSContext *context) { _private_tls_prf(context, key, sizeof(key), context->master_key, context->master_key_len, (unsigned char *)"key expansion", 13, context->local_random, TLS_SERVER_RANDOM_SIZE, context->remote_random, TLS_CLIENT_RANDOM_SIZE); else _private_tls_prf(context, key, sizeof(key), context->master_key, context->master_key_len, (unsigned char *)"key expansion", 13, context->remote_random, TLS_SERVER_RANDOM_SIZE, context->local_random, TLS_CLIENT_RANDOM_SIZE); - + DEBUG_DUMP_HEX_LABEL("LOCAL RANDOM ", context->local_random, TLS_SERVER_RANDOM_SIZE); DEBUG_DUMP_HEX_LABEL("REMOTE RANDOM", context->remote_random, TLS_CLIENT_RANDOM_SIZE); DEBUG_PRINT("\n=========== EXPANSION ===========\n"); DEBUG_DUMP_HEX(key, TLS_MAX_KEY_EXPANSION_SIZE); DEBUG_PRINT("\n"); - + int pos = 0; #ifdef TLS_WITH_CHACHA20_POLY1305 if (is_aead == 2) { @@ -281040,7 +281045,7 @@ int _private_tls_expand_key(struct TLSContext *context) { pos += mac_length; } } - + clientkey = &key[pos]; pos += key_length; serverkey = &key[pos]; @@ -281056,7 +281061,7 @@ int _private_tls_expand_key(struct TLSContext *context) { DEBUG_DUMP_HEX_LABEL("SERVER KEY", serverkey, key_length) DEBUG_DUMP_HEX_LABEL("SERVER IV", serveriv, iv_length) DEBUG_DUMP_HEX_LABEL("SERVER MAC KEY", context->is_server ? context->crypto.ctx_local_mac.local_mac : context->crypto.ctx_remote_mac.remote_mac, mac_length) - + if (context->is_server) { #ifdef TLS_WITH_CHACHA20_POLY1305 if (is_aead == 2) { @@ -281084,7 +281089,7 @@ int _private_tls_expand_key(struct TLSContext *context) { if (_private_tls_crypto_create(context, key_length, clientkey, clientiv, serverkey, serveriv)) return 0; } - + if (context->exportable) { TLS_FREE(context->exportable_keys); context->exportable_keys = (unsigned char *)TLS_MALLOC(key_length * 2); @@ -281099,7 +281104,7 @@ int _private_tls_expand_key(struct TLSContext *context) { context->exportable_size = key_length * 2; } } - + // extract client_mac_key(mac_key_length) // extract server_mac_key(mac_key_length) // extract client_key(enc_key_length) @@ -281178,14 +281183,14 @@ unsigned char *tls_pem_decode(const unsigned char *data_in, unsigned int input_l for (i = 0; i < input_length; i++) { if ((data_in[i] == '\n') || (data_in[i] == '\r')) continue; - + if (data_in[i] != '-') { // read entire line while ((i < input_length) && (data_in[i] != '\n')) i++; continue; } - + if (data_in[i] == '-') { unsigned int end_idx = i; //read until end of line @@ -281216,7 +281221,7 @@ int _is_oid(const unsigned char *oid, const unsigned char *compare_to, int compa while ((oid[i]) && (i < compare_to_len)) { if (oid[i] != compare_to[i]) return 0; - + i++; } return 1; @@ -281229,7 +281234,7 @@ int _is_oid2(const unsigned char *oid, const unsigned char *compare_to, int comp while (i < compare_to_len) { if (oid[i] != compare_to[i]) return 0; - + i++; } return 1; @@ -281246,17 +281251,17 @@ int tls_certificate_valid_subject_name(const unsigned char *cert_subject, const // no subjects ... if (((!cert_subject) || (!cert_subject[0])) && ((!subject) || (!subject[0]))) return 0; - + if ((!subject) || (!subject[0])) return bad_certificate; - + if ((!cert_subject) || (!cert_subject[0])) return bad_certificate; - + // exact match if (!strcmp((const char *)cert_subject, subject)) return 0; - + const char *wildcard = strchr((const char *)cert_subject, '*'); if (wildcard) { // 6.4.3 (1) The client SHOULD NOT attempt to match a presented identifier in @@ -281287,7 +281292,7 @@ int tls_certificate_valid_subject_name(const unsigned char *cert_subject, const return 0; } } - + return bad_certificate; } @@ -281512,7 +281517,7 @@ char *tls_certificate_to_string(struct TLSCertificate *cert, char *buffer, int l default: res += snprintf(buffer + res, len - res, "not supported):\n"); } - + for (i = 0; i < cert->sign_len; i++) res += snprintf(buffer + res, len - res, "%02x", (int)cert->sign_key[i]); } @@ -281592,32 +281597,32 @@ void tls_certificate_set_algorithm(struct TLSContext *context, unsigned int *alg } if (len != 9) return; - + if (_is_oid(val, TLS_RSA_SIGN_SHA256_OID, 9)) { *algorithm = TLS_RSA_SIGN_SHA256; return; } - + if (_is_oid(val, TLS_RSA_SIGN_RSA_OID, 9)) { *algorithm = TLS_RSA_SIGN_RSA; return; } - + if (_is_oid(val, TLS_RSA_SIGN_SHA1_OID, 9)) { *algorithm = TLS_RSA_SIGN_SHA1; return; } - + if (_is_oid(val, TLS_RSA_SIGN_SHA512_OID, 9)) { *algorithm = TLS_RSA_SIGN_SHA512; return; } - + if (_is_oid(val, TLS_RSA_SIGN_SHA384_OID, 9)) { *algorithm = TLS_RSA_SIGN_SHA384; return; } - + if (_is_oid(val, TLS_RSA_SIGN_MD5_OID, 9)) { *algorithm = TLS_RSA_SIGN_MD5; return; @@ -281754,14 +281759,14 @@ int _private_tls_crypto_create(struct TLSContext *context, int key_length, unsig if (is_aead) { int res1 = gcm_init(&context->crypto.ctx_local.aes_gcm_local, cipherID, localkey, key_length); int res2 = gcm_init(&context->crypto.ctx_remote.aes_gcm_remote, cipherID, remotekey, key_length); - + if ((res1) || (res2)) return TLS_GENERIC_ERROR; context->crypto.created = 2; } else { int res1 = cbc_start(cipherID, localiv, localkey, key_length, 0, &context->crypto.ctx_local.aes_local); int res2 = cbc_start(cipherID, remoteiv, remotekey, key_length, 0, &context->crypto.ctx_remote.aes_remote); - + if ((res1) || (res2)) return TLS_GENERIC_ERROR; context->crypto.created = 1; @@ -281780,7 +281785,7 @@ int _private_tls_crypto_encrypt(struct TLSContext *context, unsigned char *buf, int _private_tls_crypto_decrypt(struct TLSContext *context, unsigned char *buf, unsigned char *pt, unsigned int len) { if (context->crypto.created == 1) return cbc_decrypt(buf, pt, len, &context->crypto.ctx_remote.aes_remote); - + memset(pt, 0, len); return TLS_GENERIC_ERROR; } @@ -281802,7 +281807,7 @@ void _private_tls_crypto_done(struct TLSContext *context) { } void tls_packet_update(struct TLSPacket *packet) { - if ((packet) && (!packet->broken)) { + if ((packet) && (!packet->broken)) { int footer_size = 0; #ifdef WITH_TLS_13 if ((packet->context) && ((packet->context->version == TLS_V13) || (packet->context->version == DTLS_V13)) && (packet->context->cipher_spec_set) && (packet->context->crypto.created)) { @@ -281850,7 +281855,7 @@ void tls_packet_update(struct TLSPacket *packet) { unsigned int length = 0; unsigned char padding = 0; unsigned int pt_length = packet->len - header_size; - + if (packet->context->crypto.created == 1) { mac_size = _private_tls_mac_length(packet->context); #ifdef TLS_LEGACY_SUPPORT @@ -281898,10 +281903,10 @@ void tls_packet_update(struct TLSPacket *packet) { } else _private_tls_hmac_message(1, packet->context, packet->buf, packet->len, NULL, 0, buf + buf_pos, mac_size, 0); buf_pos += mac_size; - + memset(buf + buf_pos, padding - 1, padding); buf_pos += padding; - + //DEBUG_DUMP_HEX_LABEL("PT BUFFER", buf, length); _private_tls_crypto_encrypt(packet->context, buf, ct + header_size, length); TLS_FREE(packet->buf); @@ -281996,10 +282001,10 @@ void tls_packet_update(struct TLSPacket *packet) { gcm_reset(&packet->context->crypto.ctx_local.aes_gcm_local); gcm_add_iv(&packet->context->crypto.ctx_local.aes_gcm_local, iv, 12); - gcm_add_aad(&packet->context->crypto.ctx_local.aes_gcm_local, aad, aad_size); + gcm_add_aad(&packet->context->crypto.ctx_local.aes_gcm_local, aad, aad_size); gcm_process(&packet->context->crypto.ctx_local.aes_gcm_local, packet->buf + header_size, pt_length, ct + ct_pos, GCM_ENCRYPT); ct_pos += pt_length; - + unsigned long taglen = TLS_GCM_TAG_LEN; gcm_done(&packet->context->crypto.ctx_local.aes_gcm_local, ct + ct_pos, &taglen); ct_pos += taglen; @@ -282040,12 +282045,12 @@ void tls_packet_update(struct TLSPacket *packet) { int tls_packet_append(struct TLSPacket *packet, const unsigned char *buf, unsigned int len) { if ((!packet) || (packet->broken)) return -1; - + if (!len) return 0; - + unsigned int new_len = packet->len + len; - + if (new_len > packet->size) { packet->size = (new_len / TLS_BLOB_INCREMENT + 1) * TLS_BLOB_INCREMENT; packet->buf = (unsigned char *)TLS_REALLOC(packet->buf, packet->size); @@ -282082,7 +282087,7 @@ int tls_packet_uint24(struct TLSPacket *packet, unsigned int i) { buf[1] = i / 0x100; i %= 0x100; buf[2] = i; - + return tls_packet_append(packet, buf, 3); } @@ -282141,7 +282146,7 @@ void _private_tls_destroy_hash(struct TLSContext *context) { void _private_tls_create_hash(struct TLSContext *context) { if (!context) return; - + TLSHash *hash = _private_tls_ensure_hash(context); if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) { int hash_size = _private_tls_mac_length(context); @@ -282232,11 +282237,11 @@ int _private_tls_change_hash_type(struct TLSContext *context) { int _private_tls_done_hash(struct TLSContext *context, unsigned char *hout) { if (!context) return 0; - + TLSHash *hash = _private_tls_ensure_hash(context); if (!hash->created) return 0; - + int hash_size = 0; if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) { unsigned char temp[TLS_MAX_SHA_SIZE]; @@ -282290,11 +282295,11 @@ int _private_tls_get_hash_idx(struct TLSContext *context) { int _private_tls_get_hash(struct TLSContext *context, unsigned char *hout) { if (!context) return 0; - + TLSHash *hash = _private_tls_ensure_hash(context); if (!hash->created) return 0; - + int hash_size = 0; if ((context->version == TLS_V12) || (context->version == DTLS_V12) || (context->version == TLS_V13) || (context->version == DTLS_V13)) { hash_size = _private_tls_mac_length(context); @@ -282313,15 +282318,15 @@ int _private_tls_get_hash(struct TLSContext *context, unsigned char *hout) { #ifdef TLS_LEGACY_SUPPORT // TLS_V11 hash_state prec; - + memcpy(&prec, &hash->hash32, sizeof(hash_state)); md5_done(&hash->hash32, hout); memcpy(&hash->hash32, &prec, sizeof(hash_state)); - + memcpy(&prec, &hash->hash2, sizeof(hash_state)); sha1_done(&hash->hash2, hout + 16); memcpy(&hash->hash2, &prec, sizeof(hash_state)); - + hash_size = TLS_V11_HASH_SIZE; #endif } @@ -282334,7 +282339,7 @@ int _private_tls_write_packet(struct TLSPacket *packet) { struct TLSContext *context = packet->context; if (!context) return -1; - + if (context->tls_buffer) { int len = context->tls_buffer_len + packet->len; context->tls_buffer = (unsigned char *)TLS_REALLOC(context->tls_buffer, len); @@ -282362,7 +282367,7 @@ int _private_tls_write_app_data(struct TLSContext *context, const unsigned char return -1; if ((!buf) || (!buf_len)) return 0; - + int len = context->application_buffer_len + buf_len; context->application_buffer = (unsigned char *)TLS_REALLOC(context->application_buffer, len); if (!context->application_buffer) { @@ -282451,7 +282456,7 @@ int tls_established(struct TLSContext *context) { if (context) { if (context->critical_error) return -1; - + if (context->connection_status == 0xFF) return 1; @@ -282478,7 +282483,7 @@ int tls_read(struct TLSContext *context, unsigned char *buf, unsigned int size) if ((context->application_buffer) && (context->application_buffer_len)) { if (context->application_buffer_len < size) size = context->application_buffer_len; - + memcpy(buf, context->application_buffer, size); if (context->application_buffer_len == size) { TLS_FREE(context->application_buffer); @@ -282518,7 +282523,7 @@ const struct ECCCurveParameters *tls_set_curve(struct TLSContext *context, const struct TLSContext *tls_accept(struct TLSContext *context) { if ((!context) || (!context->is_server)) return NULL; - + struct TLSContext *child = (struct TLSContext *)TLS_MALLOC(sizeof(struct TLSContext)); if (child) { memset(child, 0, sizeof(struct TLSContext)); @@ -282579,13 +282584,13 @@ void _private_tls_ecc_dhe_create(struct TLSContext *context) { int tls_set_default_dhe_pg(struct TLSContext *context, const char *p_hex_str, const char *g_hex_str) { if ((!context) || (context->is_child) || (!context->is_server) || (!p_hex_str) || (!g_hex_str)) return 0; - + TLS_FREE(context->default_dhe_p); TLS_FREE(context->default_dhe_g); - + context->default_dhe_p = NULL; context->default_dhe_g = NULL; - + size_t p_len = strlen(p_hex_str); size_t g_len = strlen(g_hex_str); if ((p_len <= 0) || (g_len <= 0)) @@ -282596,10 +282601,10 @@ int tls_set_default_dhe_pg(struct TLSContext *context, const char *p_hex_str, co context->default_dhe_g = (char *)TLS_MALLOC(g_len + 1); if (!context->default_dhe_g) return 0; - + memcpy(context->default_dhe_p, p_hex_str, p_len); context->default_dhe_p[p_len] = 0; - + memcpy(context->default_dhe_g, g_hex_str, g_len); context->default_dhe_g[g_len] = 0; return 1; @@ -283099,10 +283104,10 @@ const char *tls_cipher_name(struct TLSContext *context) { #ifdef TLS_FORWARD_SECRECY int _private_tls_dh_export_Y(unsigned char *Ybuf, unsigned long *Ylen, DHKey *key) { unsigned long len; - + if ((Ybuf == NULL) || (Ylen == NULL) || (key == NULL)) return TLS_GENERIC_ERROR; - + len = mp_unsigned_bin_size(key->y); if (len > *Ylen) return TLS_GENERIC_ERROR; @@ -283114,37 +283119,37 @@ int _private_tls_dh_export_Y(unsigned char *Ybuf, unsigned long *Ylen, DHKey *ke int _private_tls_dh_export_pqY(unsigned char *pbuf, unsigned long *plen, unsigned char *gbuf, unsigned long *glen, unsigned char *Ybuf, unsigned long *Ylen, DHKey *key) { unsigned long len; int err; - + if ((pbuf == NULL) || (plen == NULL) || (gbuf == NULL) || (glen == NULL) || (Ybuf == NULL) || (Ylen == NULL) || (key == NULL)) return TLS_GENERIC_ERROR; - + len = mp_unsigned_bin_size(key->y); if (len > *Ylen) return TLS_GENERIC_ERROR; - + if ((err = mp_to_unsigned_bin(key->y, Ybuf)) != CRYPT_OK) return err; - + *Ylen = len; - + len = mp_unsigned_bin_size(key->p); if (len > *plen) return TLS_GENERIC_ERROR; - + if ((err = mp_to_unsigned_bin(key->p, pbuf)) != CRYPT_OK) return err; - + *plen = len; - + len = mp_unsigned_bin_size(key->g); if (len > *glen) return TLS_GENERIC_ERROR; - + if ((err = mp_to_unsigned_bin(key->g, gbuf)) != CRYPT_OK) return err; - + *glen = len; - + return 0; } @@ -283161,32 +283166,32 @@ int _private_tls_dh_make_key(int keysize, DHKey *key, const char *pbuf, const ch int err; if (!key) return TLS_GENERIC_ERROR; - + static prng_state prng; int wprng = find_prng("sprng"); if ((err = prng_is_valid(wprng)) != CRYPT_OK) return err; - + buf = (unsigned char *)TLS_MALLOC(keysize); if (!buf) return TLS_NO_MEMORY; - + if (rng_make_prng(keysize, wprng, &prng, NULL) != CRYPT_OK) { TLS_FREE(buf); return TLS_GENERIC_ERROR; } - + if (prng_descriptor[wprng].read(buf, keysize, &prng) != (unsigned long)keysize) { TLS_FREE(buf); return TLS_GENERIC_ERROR; } - + if ((err = mp_init_multi(&key->g, &key->p, &key->x, &key->y, NULL)) != CRYPT_OK) { TLS_FREE(buf); - + return TLS_GENERIC_ERROR; } - + if (gbuf_len <= 0) { if ((err = mp_read_radix(key->g, gbuf, 16)) != CRYPT_OK) { TLS_FREE(buf); @@ -283200,7 +283205,7 @@ int _private_tls_dh_make_key(int keysize, DHKey *key, const char *pbuf, const ch return TLS_GENERIC_ERROR; } } - + if (pbuf_len <= 0) { if ((err = mp_read_radix(key->p, pbuf, 16)) != CRYPT_OK) { TLS_FREE(buf); @@ -283214,19 +283219,19 @@ int _private_tls_dh_make_key(int keysize, DHKey *key, const char *pbuf, const ch return TLS_GENERIC_ERROR; } } - + if ((err = mp_read_unsigned_bin(key->x, buf, keysize)) != CRYPT_OK) { TLS_FREE(buf); _private_tls_dh_clear_key(key); return TLS_GENERIC_ERROR; } - + if ((err = mp_exptmod(key->g, key->x, key->p, key->y)) != CRYPT_OK) { TLS_FREE(buf); _private_tls_dh_clear_key(key); return TLS_GENERIC_ERROR; } - + TLS_FREE(buf); return 0; } @@ -283259,7 +283264,7 @@ struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) { DEBUG_PRINT("CANNOT BUILD CLIENT KEY EXCHANGE MESSAGE FOR SERVERS\n"); return NULL; } - + struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 0); tls_packet_uint8(packet, 0x10); #ifdef TLS_FORWARD_SECRECY @@ -283272,7 +283277,7 @@ struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) { unsigned long dh_p_len = sizeof(dh_p); unsigned long dh_g_len = sizeof(dh_g); unsigned long dh_Ys_len = sizeof(dh_Ys); - + if (_private_tls_dh_export_pqY(dh_p, &dh_p_len, dh_g, &dh_g_len, dh_Ys, &dh_Ys_len, context->dhe)) { DEBUG_PRINT("ERROR EXPORTING DHE KEY %p\n", context->dhe); TLS_FREE(packet); @@ -283290,7 +283295,7 @@ struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) { if (context->ecc_dhe) { unsigned char out[TLS_MAX_RSA_KEY]; unsigned long out_len = TLS_MAX_RSA_KEY; - + if (ecc_ansi_x963_export(context->ecc_dhe, out, &out_len)) { DEBUG_PRINT("Error exporting ECC key\n"); TLS_FREE(packet); @@ -283304,7 +283309,7 @@ struct TLSPacket *tls_build_client_key_exchange(struct TLSContext *context) { } tls_packet_uint8(packet, out_len); tls_packet_append(packet, out, out_len); - } + } #ifdef TLS_CURVE25519 else if ((context->curve == &x25519) && (context->client_secret)) { @@ -283347,7 +283352,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int DEBUG_PRINT("CANNOT BUILD SERVER KEY EXCHANGE MESSAGE FOR CLIENTS\n"); return NULL; } - + struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, context->version, 0); tls_packet_uint8(packet, 0x0C); unsigned char dummy[3]; @@ -283359,7 +283364,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int if (method == KEA_dhe_rsa) { tls_init(); _private_tls_dhe_create(context); - + const char *default_dhe_p = context->default_dhe_p; const char *default_dhe_g = context->default_dhe_g; int key_size; @@ -283377,31 +283382,31 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int context->dhe = NULL; return NULL; } - + unsigned char dh_Ys[0xFFF]; unsigned char dh_p[0xFFF]; unsigned char dh_g[0xFFF]; unsigned long dh_p_len = sizeof(dh_p); unsigned long dh_g_len = sizeof(dh_g); unsigned long dh_Ys_len = sizeof(dh_Ys); - + if (_private_tls_dh_export_pqY(dh_p, &dh_p_len, dh_g, &dh_g_len, dh_Ys, &dh_Ys_len, context->dhe)) { DEBUG_PRINT("ERROR EXPORTING DHE KEY\n"); TLS_FREE(packet); return NULL; } - + DEBUG_PRINT("LEN: %lu (%lu, %lu)\n", dh_Ys_len, dh_p_len, dh_g_len); DEBUG_DUMP_HEX_LABEL("DHE PK", dh_Ys, dh_Ys_len); DEBUG_DUMP_HEX_LABEL("DHE P", dh_p, dh_p_len); DEBUG_DUMP_HEX_LABEL("DHE G", dh_g, dh_g_len); - + tls_packet_uint16(packet, dh_p_len); tls_packet_append(packet, dh_p, dh_p_len); - + tls_packet_uint16(packet, dh_g_len); tls_packet_append(packet, dh_g, dh_g_len); - + tls_packet_uint16(packet, dh_Ys_len); tls_packet_append(packet, dh_Ys, dh_Ys_len); //dh_p @@ -283416,9 +283421,9 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int tls_packet_uint16(packet, context->curve->iana); tls_init(); _private_tls_ecc_dhe_create(context); - + ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&context->curve->dp; - + if (ecc_make_key_ex(NULL, find_prng("sprng"), context->ecc_dhe, dp)) { TLS_FREE(context->ecc_dhe); context->ecc_dhe = NULL; @@ -283442,7 +283447,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int DEBUG_PRINT("Unsupported ephemeral method: %i\n", method); return NULL; } - + // signature unsigned int params_len = packet->len - start_len; unsigned int message_len = params_len + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE; @@ -283450,7 +283455,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int if (message) { unsigned char out[TLS_MAX_RSA_KEY]; unsigned long out_len = TLS_MAX_RSA_KEY; - + int hash_algorithm; if ((context->version != TLS_V13) && (context->version != DTLS_V13) && (context->version != TLS_V12) && (context->version != DTLS_V12)) { hash_algorithm = _md5_sha1; @@ -283459,7 +283464,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int hash_algorithm = sha256; else hash_algorithm = sha1; - + #ifdef TLS_ECDSA_SUPPORTED if (tls_is_ecdsa(context)) { if ((context->version == TLS_V13) || (context->version == DTLS_V13) || (context->version == TLS_V12) || (context->version == DTLS_V12)) @@ -283473,7 +283478,7 @@ struct TLSPacket *tls_build_server_key_exchange(struct TLSContext *context, int tls_packet_uint8(packet, rsa_sign); } } - + memcpy(message, context->remote_random, TLS_CLIENT_RANDOM_SIZE); memcpy(message + TLS_CLIENT_RANDOM_SIZE, context->local_random, TLS_SERVER_RANDOM_SIZE); memcpy(message + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE, packet->buf + start_len, params_len); @@ -283667,7 +283672,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad // fallback ... this should never happen if (!context->cipher) context->cipher = TLS_DHE_RSA_WITH_AES_128_CBC_SHA; - + tls_packet_uint16(packet, context->cipher); // no compression tls_packet_uint8(packet, 0); @@ -283677,7 +283682,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad #ifdef WITH_TLS_13 if ((context->version == TLS_V13) || (context->version == DTLS_V13)) { tls_packet_uint16(packet, extension_len); - } else + } else #endif { tls_packet_uint16(packet, 5 + extension_len); @@ -283855,7 +283860,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad int sni_len = 0; if (context->sni) sni_len = strlen(context->sni); - + #ifdef TLS_CLIENT_ECDHE extension_len += 12; #endif @@ -283872,7 +283877,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad } #endif tls_packet_uint16(packet, extension_len); - + if (sni_len) { // sni extension tls_packet_uint16(packet, 0x00); @@ -283984,9 +283989,9 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad tls_packet_uint16(packet, shared_key_short + 6); tls_packet_uint16(packet, shared_key_short + 4); - _private_tls_ecc_dhe_create(context); + _private_tls_ecc_dhe_create(context); ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&secp256r1.dp; - + if (ecc_make_key_ex(NULL, find_prng("sprng"), context->ecc_dhe, dp)) { TLS_FREE(context->ecc_dhe); context->ecc_dhe = NULL; @@ -284027,7 +284032,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad } } #endif - + if ((!packet->broken) && (packet->buf)) { int remaining = packet->len - start_len; int payload_pos = 6; @@ -284051,7 +284056,7 @@ struct TLSPacket *tls_build_hello(struct TLSContext *context, int tls13_downgrad struct TLSPacket *tls_certificate_request(struct TLSContext *context) { if ((!context) || (!context->is_server)) return NULL; - + unsigned short packet_version = context->version; struct TLSPacket *packet = tls_create_packet(context, TLS_HANDSHAKE, packet_version, 0); if (packet) { @@ -284162,7 +284167,7 @@ int _private_dtls_build_cookie(struct TLSContext *context) { struct TLSPacket *tls_build_verify_request(struct TLSContext *context) { if ((!context->is_server) || (!context->dtls)) return NULL; - + if ((!context->dtls_cookie) || (!context->dtls_cookie_len)) { if (!_private_dtls_build_cookie(context)) return NULL; @@ -284409,7 +284414,7 @@ int _private_tls_parse_key_share(struct TLSContext *context, const unsigned char } out2 = (unsigned char *)TLS_MALLOC(key_size); out_size = key_size; - + int err = ecc_shared_secret(context->ecc_dhe, &client_key, out2, &out_size); ecc_free(&client_key); @@ -284468,7 +284473,7 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu DEBUG_PRINT("UNEXPECTED HELLO MESSAGE\n"); return TLS_UNEXPECTED_MESSAGE; } - + int res = 0; int downgraded = 0; int hello_min_size = context->dtls ? TLS_CLIENT_HELLO_MINSIZE + 8 : TLS_CLIENT_HELLO_MINSIZE; @@ -284484,11 +284489,11 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu res += 8; } CHECK_SIZE(bytes_to_follow, buf_len - res, TLS_NEED_MORE_DATA) - + CHECK_SIZE(2, buf_len - res, TLS_NEED_MORE_DATA) unsigned short version = ntohs(*(unsigned short *)&buf[res]); unsigned short cipher = 0; - + res += 2; VERSION_SUPPORTED(version, TLS_NOT_SAFE) DEBUG_PRINT("VERSION REQUIRED BY REMOTE %x, VERSION NOW %x\n", (int)version, (int)context->version); @@ -284513,7 +284518,7 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu #endif memcpy(context->remote_random, &buf[res], TLS_CLIENT_RANDOM_SIZE); res += TLS_CLIENT_RANDOM_SIZE; - + unsigned char session_len = buf[res++]; CHECK_SIZE(session_len, buf_len - res, TLS_NEED_MORE_DATA) if ((session_len) && (session_len <= TLS_MAX_SESSION_ID)) { @@ -284567,11 +284572,11 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu cipher_buffer = &buf[res]; res += cipher_len; - + CHECK_SIZE(1, buf_len - res, TLS_NEED_MORE_DATA) unsigned char compression_list_size = buf[res++]; CHECK_SIZE(compression_list_size, buf_len - res, TLS_NEED_MORE_DATA) - + // no compression support res += compression_list_size; } else { @@ -284594,15 +284599,15 @@ int tls_parse_hello(struct TLSContext *context, const unsigned char *buf, int bu return TLS_COMPRESSION_NOT_SUPPORTED; } } - + if (res > 0) { if (context->is_server) *write_packets = 2; if (context->connection_status != 4) context->connection_status = 1; } - - + + if (res > 2) res += 2; #ifdef WITH_TLS_13 @@ -284830,7 +284835,7 @@ int tls_parse_certificate(struct TLSContext *context, const unsigned char *buf, int res = 0; CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA) unsigned int size_of_all_certificates = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; - + if (size_of_all_certificates <= 4) return 3 + size_of_all_certificates; res += 3; @@ -284852,7 +284857,7 @@ int tls_parse_certificate(struct TLSContext *context, const unsigned char *buf, CHECK_SIZE(size_of_all_certificates, buf_len - res, TLS_NEED_MORE_DATA); int size = size_of_all_certificates; - + int idx = 0; int valid_certificate = 0; while (size > 0) { @@ -284877,7 +284882,7 @@ int tls_parse_certificate(struct TLSContext *context, const unsigned char *buf, break; } remaining -= certificate_size2; - + struct TLSCertificate *cert = asn1_parse(context, &buf[res2], certificate_size2, is_client); if (cert) { if (certificate_size2) { @@ -284962,7 +284967,7 @@ int _private_tls_parse_random(struct TLSContext *context, const unsigned char *b size = ntohs(*(unsigned short *)buf); res += 2; } - + CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA) unsigned int out_len = 0; unsigned char *random = NULL; @@ -284978,7 +284983,7 @@ int _private_tls_parse_random(struct TLSContext *context, const unsigned char *b default: random = _private_tls_decrypt_rsa(context, &buf[res], size, &out_len); } - + if ((random) && (out_len > 2)) { DEBUG_DUMP_HEX_LABEL("PRE MASTER KEY", random, out_len); TLS_FREE(context->premaster_key); @@ -284999,7 +285004,7 @@ int _private_tls_build_random(struct TLSPacket *packet) { int bytes = 48; if (!tls_random(rand_bytes, bytes)) return TLS_GENERIC_ERROR; - + // max supported version if (packet->context->is_server) *(unsigned short *)rand_bytes = htons(packet->context->version); @@ -285009,18 +285014,18 @@ int _private_tls_build_random(struct TLSPacket *packet) { else *(unsigned short *)rand_bytes = htons(TLS_V12); //DEBUG_DUMP_HEX_LABEL("PREMASTER KEY", rand_bytes, bytes); - + TLS_FREE(packet->context->premaster_key); packet->context->premaster_key = (unsigned char *)TLS_MALLOC(bytes); if (!packet->context->premaster_key) return TLS_NO_MEMORY; - + packet->context->premaster_key_len = bytes; memcpy(packet->context->premaster_key, rand_bytes, packet->context->premaster_key_len); - + unsigned int out_len; unsigned char *random = _private_tls_encrypt_rsa(packet->context, packet->context->premaster_key, packet->context->premaster_key_len, &out_len); - + _private_tls_compute_key(packet->context, bytes); if ((random) && (out_len > 2)) { tls_packet_uint24(packet, out_len + 2); @@ -285033,7 +285038,7 @@ int _private_tls_build_random(struct TLSPacket *packet) { TLS_FREE(random); if (res) return res; - + return out_len + 2; } @@ -285072,10 +285077,10 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha } const unsigned char *packet_ref = buf + res; CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA); - + if (!size) return res; - + unsigned char has_ds_params = 0; unsigned int key_size = 0; #ifdef TLS_FORWARD_SECRECY @@ -285148,14 +285153,14 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha return TLS_BROKEN_PACKET; res += dh_res; DEBUG_PRINT("\n"); - + DEBUG_PRINT(" dh_q: "); dh_res = _private_tls_parse_dh(&buf[res], buf_len - res, &dh_g, &dh_g_len); if (dh_res <= 0) return TLS_BROKEN_PACKET; res += dh_res; DEBUG_PRINT("\n"); - + DEBUG_PRINT(" dh_Ys: "); dh_res = _private_tls_parse_dh(&buf[res], buf_len - res, &dh_Ys, &dh_Ys_len); if (dh_res <= 0) @@ -285179,7 +285184,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha // check signature unsigned int message_len = packet_size + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE; unsigned char *message = (unsigned char *)TLS_MALLOC(message_len); - if (message) { + if (message) { memcpy(message, context->local_random, TLS_CLIENT_RANDOM_SIZE); memcpy(message + TLS_CLIENT_RANDOM_SIZE, context->remote_random, TLS_SERVER_RANDOM_SIZE); memcpy(message + TLS_CLIENT_RANDOM_SIZE + TLS_SERVER_RANDOM_SIZE, packet_ref, packet_size); @@ -285190,7 +285195,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha TLS_FREE(message); return TLS_BROKEN_PACKET; } - } else + } else #endif { if (_private_tls_verify_rsa(context, hash_algorithm, signature, sign_size, message, message_len) != 1) { @@ -285201,7 +285206,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha } TLS_FREE(message); } - + if (buf_len - res) { DEBUG_PRINT("EXTRA %i BYTES AT THE END OF MESSAGE\n", buf_len - res); DEBUG_DUMP_HEX(&buf[res], buf_len - res); @@ -285221,7 +285226,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha context->dhe = NULL; return TLS_GENERIC_ERROR; } - + unsigned int dh_key_size = 0; unsigned char *key = _private_tls_decrypt_dhe(context, dh_Ys, dh_Ys_len, &dh_key_size, 0); DEBUG_DUMP_HEX_LABEL("DH COMMON SECRET", key, dh_key_size); @@ -285245,7 +285250,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha DEBUG_PRINT("ERROR IN TLS_MALLOC"); return TLS_GENERIC_ERROR; } - + tls_random(context->client_secret, 32); context->client_secret[0] &= 248; @@ -285264,7 +285269,7 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha { tls_init(); _private_tls_ecc_dhe_create(context); - + ltc_ecc_set_type *dp = (ltc_ecc_set_type *)&curve->dp; if (ecc_make_key_ex(NULL, find_prng("sprng"), context->ecc_dhe, dp)) { TLS_FREE(context->ecc_dhe); @@ -285272,10 +285277,10 @@ int tls_parse_server_key_exchange(struct TLSContext *context, const unsigned cha DEBUG_PRINT("Error generating ECC key\n"); return TLS_GENERIC_ERROR; } - + TLS_FREE(context->premaster_key); context->premaster_key_len = 0; - + unsigned int out_len = 0; context->premaster_key = _private_tls_decrypt_ecc_dhe(context, pk_key, key_size, &out_len, 0); if (context->premaster_key) @@ -285295,7 +285300,7 @@ int tls_parse_client_key_exchange(struct TLSContext *context, const unsigned cha int res = 0; int dh_res = 0; CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA) - + unsigned int size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; res += 3; if (context->dtls) { @@ -285309,14 +285314,14 @@ int tls_parse_client_key_exchange(struct TLSContext *context, const unsigned cha if (!size) return res; - + dh_res = _private_tls_parse_random(context, &buf[res], size); if (dh_res <= 0) { DEBUG_PRINT("broken key\n"); return TLS_BROKEN_PACKET; } DEBUG_PRINT("\n"); - + res += size; context->connection_status = 2; return res; @@ -285325,7 +285330,7 @@ int tls_parse_client_key_exchange(struct TLSContext *context, const unsigned cha int tls_parse_server_hello_done(struct TLSContext *context, const unsigned char *buf, int buf_len) { int res = 0; CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA) - + unsigned int size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; res += 3; if (context->dtls) { @@ -285334,9 +285339,9 @@ int tls_parse_server_hello_done(struct TLSContext *context, const unsigned char return dtls_check; res += 8; } - + CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA); - + res += size; return res; } @@ -285346,11 +285351,11 @@ int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int DEBUG_PRINT("UNEXPECTED FINISHED MESSAGE\n"); return TLS_UNEXPECTED_MESSAGE; } - + int res = 0; *write_packets = 0; CHECK_SIZE(3, buf_len, TLS_NEED_MORE_DATA) - + unsigned int size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; res += 3; if (context->dtls) { @@ -285359,14 +285364,14 @@ int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int return dtls_check; res += 8; } - + if (size < TLS_MIN_FINISHED_OPAQUE_LEN) { DEBUG_PRINT("Invalid finished pachet size: %i\n", size); return TLS_BROKEN_PACKET; } - + CHECK_SIZE(size, buf_len - res, TLS_NEED_MORE_DATA); - + unsigned char hash[TLS_MAX_SHA_SIZE]; unsigned int hash_len = _private_tls_get_hash(context, hash); @@ -285412,13 +285417,13 @@ int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int DEBUG_PRINT("Error in TLS_MALLOC (%i bytes)\n", (int)size); return TLS_NO_MEMORY; } - + // server verifies client's message if (context->is_server) _private_tls_prf(context, out, size, context->master_key, context->master_key_len, (unsigned char *)"client finished", 15, hash, hash_len, NULL, 0); else _private_tls_prf(context, out, size, context->master_key, context->master_key_len, (unsigned char *)"server finished", 15, hash, hash_len, NULL, 0); - + if (memcmp(out, &buf[res], size)) { TLS_FREE(out); DEBUG_PRINT("Finished validation error (sequence number, local: %i, remote: %i)\n", (int)context->local_sequence_number, (int)context->remote_sequence_number); @@ -285460,7 +285465,7 @@ int tls_parse_finished(struct TLSContext *context, const unsigned char *buf, int int tls_parse_verify_tls13(struct TLSContext *context, const unsigned char *buf, int buf_len) { CHECK_SIZE(7, buf_len, TLS_NEED_MORE_DATA) unsigned int size = buf[0] * 0x10000 + buf[1] * 0x100 + buf[2]; - + if (size < 2) return buf_len; @@ -285533,7 +285538,7 @@ int tls_parse_verify(struct TLSContext *context, const unsigned char *buf, int b CHECK_SIZE(size, bytes_to_follow - 4, TLS_BAD_CERTIFICATE) DEBUG_PRINT("ALGORITHM %i/%i (%i)\n", hash, algorithm, (int)size); DEBUG_DUMP_HEX_LABEL("VERIFY", &buf[7], bytes_to_follow - 7); - + res = _private_tls_verify_rsa(context, hash, &buf[7], size, context->cached_handshake, context->cached_handshake_len); } else { #ifdef TLS_LEGACY_SUPPORT @@ -285766,12 +285771,12 @@ int tls_parse_payload(struct TLSContext *context, const unsigned char *buf, int } if ((type != 0x00) && (update_hash)) _private_tls_update_hash(context, buf, payload_size + 1); - + if (certificate_verify_alert != no_error) { _private_tls_write_packet(tls_build_alert(context, 1, certificate_verify_alert)); context->critical_error = 1; } - + if (payload_res < 0) { switch (payload_res) { case TLS_UNEXPECTED_MESSAGE: @@ -285819,7 +285824,7 @@ int tls_parse_payload(struct TLSContext *context, const unsigned char *buf, int } if (certificate_verify_alert != no_error) payload_res = TLS_BAD_CERTIFICATE; - + // except renegotiation switch (write_packets) { case 1: @@ -285947,7 +285952,7 @@ unsigned int _private_tls_hmac_message(unsigned char local, struct TLSContext *c hash_idx = find_hash("sha384"); else hash_idx = find_hash("sha256"); - + if (hmac_init(&hash, hash_idx, local ? context->crypto.ctx_local_mac.local_mac : context->crypto.ctx_remote_mac.remote_mac, mac_size)) return 0; @@ -285962,7 +285967,7 @@ unsigned int _private_tls_hmac_message(unsigned char local, struct TLSContext *c if (hmac_process(&hash, (unsigned char *)&squence_number, sizeof(uint64_t))) return 0; - + if (hmac_process(&hash, buf, buf_len)) return 0; if ((buf2) && (buf_len2)) { @@ -285972,7 +285977,7 @@ unsigned int _private_tls_hmac_message(unsigned char local, struct TLSContext *c unsigned long ref_outlen = outlen; if (hmac_done(&hash, out, &ref_outlen)) return 0; - + return (unsigned int)ref_outlen; } @@ -285982,9 +285987,9 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le res = 13; int header_size = res; int payload_res = 0; - + CHECK_SIZE(res, buf_len, TLS_NEED_MORE_DATA) - + unsigned char type = *buf; int buf_pos = 1; @@ -286079,7 +286084,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le } DEBUG_DUMP_HEX_LABEL("aad", aad, aad_size); DEBUG_DUMP_HEX_LABEL("aad iv", iv, 12); - + int res0 = gcm_add_iv(&context->crypto.ctx_remote.aes_gcm_remote, iv, 12); int res1 = gcm_add_aad(&context->crypto.ctx_remote.aes_gcm_remote, aad, aad_size); memset(pt, 0, length); @@ -286170,7 +286175,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le rem = pt_length % 16; if (rem) _private_tls_poly1305_update(&ctx, zeropad, 16 - rem); - + _private_tls_U32TO8(&trail[0], aad_size == 5 ? 5 : 13); *(int *)&trail[4] = 0; _private_tls_U32TO8(&trail[8], pt_length); @@ -286203,7 +286208,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le } unsigned char padding_byte = pt[length - 1]; unsigned char padding = padding_byte + 1; - + // poodle check int padding_index = length - padding; if (padding_index > 0) { @@ -286219,11 +286224,11 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le } } } - + unsigned int decrypted_length = length; if (padding < decrypted_length) decrypted_length -= padding; - + DEBUG_DUMP_HEX_LABEL("decrypted", pt, decrypted_length); ptr = pt; #ifdef TLS_LEGACY_SUPPORT @@ -286238,7 +286243,7 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le } #endif length = decrypted_length; - + unsigned int mac_size = _private_tls_mac_length(context); if ((length < mac_size) || (!mac_size)) { TLS_FREE(pt); @@ -286247,9 +286252,9 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le _private_tls_write_packet(tls_build_alert(context, 1, decrypt_error)); return TLS_BROKEN_PACKET; } - + length -= mac_size; - + const unsigned char *message_hmac = &ptr[length]; unsigned char hmac_out[TLS_MAX_MAC_SIZE]; unsigned char temp_buf[5]; @@ -286347,22 +286352,22 @@ int tls_parse_message(struct TLSContext *context, unsigned char *buf, int buf_le return TLS_NOT_UNDERSTOOD; } TLS_FREE(pt); - + if (payload_res < 0) return payload_res; - + if (res > 0) return header_size + length; - + return res; } unsigned int asn1_get_len(const unsigned char *buffer, int buf_len, unsigned int *octets) { *octets = 0; - + if (buf_len < 1) return 0; - + unsigned char size = buffer[0]; int i; if (size & 0x80) { @@ -286377,7 +286382,7 @@ unsigned int asn1_get_len(const unsigned char *buffer, int buf_len, unsigned int return 0; unsigned int long_size = 0; unsigned int coef = 1; - + for (i = ref_octets; i > 0; i--) { long_size += buffer[i] * coef; coef *= 0x100; @@ -286442,7 +286447,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(16); if (!hash) return NULL; - + err = md5_init(&state); if (!err) { err = md5_process(&state, message, message_len); @@ -286455,7 +286460,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(20); if (!hash) return NULL; - + err = sha1_init(&state); if (!err) { err = sha1_process(&state, message, message_len); @@ -286469,7 +286474,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(32); if (!hash) return NULL; - + err = sha256_init(&state); if (!err) { err = sha256_process(&state, message, message_len); @@ -286482,7 +286487,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(48); if (!hash) return NULL; - + err = sha384_init(&state); if (!err) { err = sha384_process(&state, message, message_len); @@ -286495,7 +286500,7 @@ unsigned char *_private_tls_compute_hash(int algorithm, const unsigned char *mes hash = (unsigned char *)TLS_MALLOC(64); if (!hash) return NULL; - + err = sha512_init(&state); if (!err) { err = sha512_process(&state, message, message_len); @@ -286518,7 +286523,7 @@ int tls_certificate_verify_signature(struct TLSCertificate *cert, struct TLSCert int hash_len = _private_tls_hash_len(cert->algorithm); if (hash_len <= 0) return 0; - + int hash_index = -1; switch (cert->algorithm) { case TLS_RSA_SIGN_MD5: @@ -286567,7 +286572,7 @@ int tls_certificate_verify_signature(struct TLSCertificate *cert, struct TLSCert return ecc_stat; } #endif - + rsa_key key; int err = rsa_import(parent->der_bytes, parent->der_len, &key); if (err) { @@ -286595,14 +286600,14 @@ int tls_certificate_verify_signature(struct TLSCertificate *cert, struct TLSCert int tls_certificate_chain_is_valid(struct TLSCertificate **certificates, int len) { if ((!certificates) || (!len)) return bad_certificate; - + int i; len--; - + // expired certificate or not yet valid ? if (tls_certificate_is_valid(certificates[0])) return bad_certificate; - + // check for (i = 0; i < len; i++) { // certificate in chain is expired ? @@ -286685,7 +286690,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, for (i1 = 1; i1 < level; i1++) DEBUG_PRINT(" "); #endif - + if ((length) && (constructed)) { switch (type) { case 0x03: @@ -286749,7 +286754,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, if (_is_field(fields, pk_id)) { if (has_key) *has_key = 1; - + if (idx == 1) tls_certificate_set_key(cert, &buffer[pos], length); else @@ -286794,7 +286799,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, case 0x03: if (_is_field(fields, pk_id)) { if (has_key) - *has_key = 1; + *has_key = 1; } // bitstream DEBUG_PRINT("BITSTREAM(%i): ", length); @@ -286856,7 +286861,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, } if (_is_field(fields, algorithm_id)) tls_certificate_set_algorithm(context, &cert->algorithm, &buffer[pos], length); - + DEBUG_PRINT("OBJECT IDENTIFIER(%i): ", length); DEBUG_DUMP_HEX(&buffer[pos], length); DEBUG_PRINT("\n"); @@ -286881,7 +286886,7 @@ int _private_asn1_parse(struct TLSContext *context, struct TLSCertificate *cert, DEBUG_PRINT("UTC TIME: ["); DEBUG_DUMP(&buffer[pos], length); DEBUG_PRINT("]\n"); - + if (_is_field(fields, validity_id)) { if (idx == 1) tls_certificate_set_copy_date(&cert->not_before, &buffer[pos], length); @@ -286991,7 +286996,7 @@ struct TLSCertificate *asn1_parse(struct TLSContext *context, const unsigned cha int tls_load_certificates(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size) { if (!context) return TLS_GENERIC_ERROR; - + unsigned int len; int idx = 0; do { @@ -287000,7 +287005,7 @@ int tls_load_certificates(struct TLSContext *context, const unsigned char *pem_b break; struct TLSCertificate *cert = asn1_parse(context, data, len, 0); if (cert) { - if ((cert->version == 2) + if ((cert->version == 2) #ifdef TLS_X509_V1_SUPPORT || (cert->version == 0) #endif @@ -287039,7 +287044,7 @@ int tls_load_certificates(struct TLSContext *context, const unsigned char *pem_b int tls_load_private_key(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size) { if (!context) return TLS_GENERIC_ERROR; - + unsigned int len; int idx = 0; do { @@ -287330,7 +287335,7 @@ struct TLSPacket *tls_build_finished(struct TLSContext *context) { unsigned char out[TLS_MIN_FINISHED_OPAQUE_LEN]; #endif unsigned int hash_len; - + // server verifies client's message if (context->is_server) { #ifdef WITH_TLS_13 @@ -287445,7 +287450,7 @@ struct TLSPacket *tls_build_message(struct TLSContext *context, const unsigned c int tls_client_connect(struct TLSContext *context) { if ((context->is_server) || (context->critical_error)) return TLS_UNEXPECTED_MESSAGE; - + return _private_tls_write_packet(tls_build_hello(context, 0)); } @@ -287516,7 +287521,7 @@ int tls_consume_stream(struct TLSContext *context, const unsigned char *buf, int unsigned int index = 0; unsigned int tls_buffer_len = context->message_buffer_len; int err_flag = 0; - + int tls_header_size; int tls_size_offset; @@ -287609,7 +287614,7 @@ int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsign DEBUG_PRINT("CANNOT EXPORT CONTEXT %i\n", (int)context->connection_status); return 0; } - + struct TLSPacket *packet = tls_create_packet(NULL, TLS_SERIALIZED_OBJECT, context->version, 0); // export buffer version tls_packet_uint8(packet, 0x01); @@ -287619,7 +287624,7 @@ int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsign tls_packet_uint8(packet, 2); else tls_packet_uint8(packet, context->is_server); - + if (context->crypto.created == 2) { // aead #ifdef WITH_TLS_13 @@ -287646,20 +287651,20 @@ int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsign } else { unsigned char iv[TLS_AES_IV_LENGTH]; unsigned long len = TLS_AES_IV_LENGTH; - + memset(iv, 0, TLS_AES_IV_LENGTH); cbc_getiv(iv, &len, &context->crypto.ctx_local.aes_local); tls_packet_uint8(packet, TLS_AES_IV_LENGTH); tls_packet_append(packet, iv, len); - + memset(iv, 0, TLS_AES_IV_LENGTH); cbc_getiv(iv, &len, &context->crypto.ctx_remote.aes_remote); tls_packet_append(packet, iv, TLS_AES_IV_LENGTH); } - + tls_packet_uint8(packet, context->exportable_size); tls_packet_append(packet, context->exportable_keys, context->exportable_size); - + if (context->crypto.created == 2) { tls_packet_uint8(packet, 0); #ifdef TLS_WITH_CHACHA20_POLY1305 @@ -287681,25 +287686,25 @@ int tls_export_context(struct TLSContext *context, unsigned char *buffer, unsign tls_packet_append(packet, context->crypto.ctx_local_mac.local_mac, mac_length); tls_packet_append(packet, context->crypto.ctx_remote_mac.remote_mac, mac_length); } - + if (small_version) { tls_packet_uint16(packet, 0); } else { tls_packet_uint16(packet, context->master_key_len); tls_packet_append(packet, context->master_key, context->master_key_len); } - + uint64_t sequence_number = htonll(context->local_sequence_number); tls_packet_append(packet, (unsigned char *)&sequence_number, sizeof(uint64_t)); sequence_number = htonll(context->remote_sequence_number); tls_packet_append(packet, (unsigned char *)&sequence_number, sizeof(uint64_t)); - + tls_packet_uint32(packet, context->tls_buffer_len); tls_packet_append(packet, context->tls_buffer, context->tls_buffer_len); - + tls_packet_uint32(packet, context->message_buffer_len); tls_packet_append(packet, context->message_buffer, context->message_buffer_len); - + tls_packet_uint32(packet, context->application_buffer_len); tls_packet_append(packet, context->application_buffer, context->application_buffer_len); tls_packet_uint8(packet, context->dtls); @@ -287745,7 +287750,7 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int context->is_child = 1; } else context->is_server = server; - + unsigned char local_iv[TLS_AES_IV_LENGTH]; unsigned char remote_iv[TLS_AES_IV_LENGTH]; unsigned char iv_len = buffer[10]; @@ -287754,14 +287759,14 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int tls_destroy_context(context); return NULL; } - + // get the initialization vectors int buf_pos = 11; memcpy(local_iv, &buffer[buf_pos], iv_len); buf_pos += iv_len; memcpy(remote_iv, &buffer[buf_pos], iv_len); buf_pos += iv_len; - + unsigned char key_lengths = buffer[buf_pos++]; TLS_IMPORT_CHECK_SIZE(buf_pos, key_lengths, buf_len) memcpy(temp, &buffer[buf_pos], key_lengths); @@ -287815,19 +287820,19 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int } } memset(temp, 0, sizeof(temp)); - + unsigned char mac_length = buffer[buf_pos++]; if (mac_length > TLS_MAX_MAC_SIZE) { DEBUG_PRINT("INVALID MAC SIZE\n"); tls_destroy_context(context); return NULL; } - + if (mac_length) { TLS_IMPORT_CHECK_SIZE(buf_pos, mac_length, buf_len) memcpy(context->crypto.ctx_local_mac.local_mac, &buffer[buf_pos], mac_length); buf_pos += mac_length; - + TLS_IMPORT_CHECK_SIZE(buf_pos, mac_length, buf_len) memcpy(context->crypto.ctx_remote_mac.remote_mac, &buffer[buf_pos], mac_length); buf_pos += mac_length; @@ -287851,7 +287856,7 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int buf_pos += CHACHA_BLOCKLEN; } #endif - + TLS_IMPORT_CHECK_SIZE(buf_pos, 2, buf_len) unsigned short master_key_len = ntohs(*(unsigned short *)(buffer + buf_pos)); buf_pos += 2; @@ -287864,14 +287869,14 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int } buf_pos += master_key_len; } - + TLS_IMPORT_CHECK_SIZE(buf_pos, 16, buf_len) - + context->local_sequence_number = ntohll(*(uint64_t *)&buffer[buf_pos]); buf_pos += 8; context->remote_sequence_number = ntohll(*(uint64_t *)&buffer[buf_pos]); buf_pos += 8; - + TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len) unsigned int tls_buffer_len = ntohl(*(unsigned int *)&buffer[buf_pos]); buf_pos += 4; @@ -287884,7 +287889,7 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int } buf_pos += tls_buffer_len; } - + TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len) unsigned int message_buffer_len = ntohl(*(unsigned int *)&buffer[buf_pos]); buf_pos += 4; @@ -287897,7 +287902,7 @@ struct TLSContext *tls_import_context(const unsigned char *buffer, unsigned int } buf_pos += message_buffer_len; } - + TLS_IMPORT_CHECK_SIZE(buf_pos, 4, buf_len) unsigned int application_buffer_len = ntohl(*(unsigned int *)&buffer[buf_pos]); buf_pos += 4; @@ -287933,7 +287938,7 @@ int tls_is_broken(struct TLSContext *context) { int tls_request_client_certificate(struct TLSContext *context) { if ((!context) || (!context->is_server)) return 0; - + context->request_client_certificate = 1; return 1; } @@ -287941,7 +287946,7 @@ int tls_request_client_certificate(struct TLSContext *context) { int tls_client_verified(struct TLSContext *context) { if ((!context) || (context->critical_error)) return 0; - + return (context->client_verified == 1); } @@ -287973,17 +287978,17 @@ int tls_sni_set(struct TLSContext *context, const char *sni) { int tls_load_root_certificates(struct TLSContext *context, const unsigned char *pem_buffer, int pem_size) { if (!context) return TLS_GENERIC_ERROR; - + unsigned int len; int idx = 0; - + do { unsigned char *data = tls_pem_decode(pem_buffer, pem_size, idx++, &len); if ((!data) || (!len)) break; struct TLSCertificate *cert = asn1_parse(NULL, data, len, 0); if (cert) { - if ((cert->version == 2) + if ((cert->version == 2) #ifdef TLS_X509_V1_SUPPORT || (cert->version == 0) #endif @@ -288015,7 +288020,7 @@ int tls_load_root_certificates(struct TLSContext *context, const unsigned char * int tls_default_verify(struct TLSContext *context, struct TLSCertificate **certificate_chain, int len) { int i; int err; - + if (certificate_chain) { for (i = 0; i < len; i++) { struct TLSCertificate *certificate = certificate_chain[i]; @@ -288029,18 +288034,18 @@ int tls_default_verify(struct TLSContext *context, struct TLSCertificate **certi err = tls_certificate_chain_is_valid(certificate_chain, len); if (err) return err; - + // check certificate subject if ((!context->is_server) && (context->sni) && (len > 0) && (certificate_chain)) { err = tls_certificate_valid_subject(certificate_chain[0], context->sni); if (err) return err; } - + err = tls_certificate_chain_is_valid_root(context, certificate_chain, len); if (err) return err; - + DEBUG_PRINT("Certificate OK\n"); return no_error; } @@ -288289,7 +288294,7 @@ int SSL_CTX_use_PrivateKey_file(struct TLSContext *context, const char *filename int size = _private_tls_read_from_file(filename, buf, sizeof(buf)); if (size > 0) return tls_load_private_key(context, buf, size); - + return size; } @@ -288365,14 +288370,14 @@ void *SSL_userdata(struct TLSContext *context) { SSLUserData *ssl_data = (SSLUserData *)context->user_data; if (!ssl_data) return NULL; - + return ssl_data->user_data; } int SSL_CTX_root_ca(struct TLSContext *context, const char *pem_filename) { if (!context) return TLS_GENERIC_ERROR; - + int count = TLS_GENERIC_ERROR; FILE *f = fopen(pem_filename, "rb"); if (f) { @@ -288473,7 +288478,7 @@ int SSL_connect(struct TLSContext *context) { res = _tls_ssl_private_send_pending(ssl_data->fd, context); if (res < 0) return res; - + int read_size; unsigned char client_message[0xFFFF]; @@ -288497,7 +288502,7 @@ int SSL_shutdown(struct TLSContext *context) { SSLUserData *ssl_data = (SSLUserData *)context->user_data; if ((!ssl_data) || (ssl_data->fd < 0)) return TLS_GENERIC_ERROR; - + tls_close_notify(context); return 0; } @@ -288508,7 +288513,7 @@ int SSL_write(struct TLSContext *context, const void *buf, unsigned int len) { SSLUserData *ssl_data = (SSLUserData *)context->user_data; if ((!ssl_data) || (ssl_data->fd < 0)) return TLS_GENERIC_ERROR; - + int written_size = tls_write(context, (const unsigned char *)buf, len); if (written_size > 0) { int res = _tls_ssl_private_send_pending(ssl_data->fd, context); @@ -288521,7 +288526,7 @@ int SSL_write(struct TLSContext *context, const void *buf, unsigned int len) { int SSL_read(struct TLSContext *context, void *buf, unsigned int len) { if (!context) return TLS_GENERIC_ERROR; - + if (context->application_buffer_len) return tls_read(context, (unsigned char *)buf, len); @@ -288530,7 +288535,7 @@ int SSL_read(struct TLSContext *context, void *buf, unsigned int len) { return TLS_GENERIC_ERROR; if (tls_established(context) != 1) return TLS_GENERIC_ERROR; - + unsigned char client_message[0xFFFF]; // accept int read_size; @@ -288543,7 +288548,7 @@ int SSL_read(struct TLSContext *context, void *buf, unsigned int len) { } if ((read_size <= 0) && (!context->application_buffer_len)) return read_size; - + return tls_read(context, (unsigned char *)buf, len); } @@ -313365,6 +313370,15 @@ API void ProgressiveMesh(int vert_n, int vert_stride, const float *v, int tri_n, */ #line 0 #define expr expr2 // 3rd_lua.h +#define EVAL_EXTEND_CONSTANTS \ + for( int vk = input_enum(id), *once = &vk; once; once = 0) \ + if( vk >= 0 ) push(ev, vk); +#define EVAL_EXTEND_FUNCTIONS \ + /**/ if(!strcmp(id, "input") && nargs ==1) push(ev, input(pop(ev))); \ + else if(!strcmp(id, "down") && nargs ==1) push(ev, input_down(pop(ev))); \ + else if(!strcmp(id, "held") && nargs ==1) push(ev, input_held(pop(ev))); \ + else if(!strcmp(id, "up") && nargs ==1) push(ev, input_up(pop(ev))); \ + else if(!strcmp(id, "idle") && nargs ==1) push(ev, input_idle(pop(ev))); #line 1 "engine/split/3rd_eval.h" /* A mathematical expression evaluator. * It uses a recursive descent parser internally. @@ -313875,17 +313889,1497 @@ int main() { } #endif #line 0 -// #define SQLITE_OMIT_LOAD_EXTENSION -// #define SQLITE_CORE 1 -// #define SQLITE_DEBUG 1 -// #define Token SQToken -// #define Table SQTable -// #define rehash sqlite3__rehash -// #undef NB -//{{FILE/*:*/3rd_sqlite3.c}} -// #undef Token -// #undef Table -// #undef rehash -// #undef NB -// #undef threadid +#line 1 "engine/split/3rd_luadebugger.h" +/* + Copyright (c) 2023 Scott Lembcke and Howling Moon Software + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#include +#include +#include +#include + +//#include +//#include + +static const char DEBUGGER_SRC[] = { +/*000000*/ 0x2d,0x2d,0x5b,0x5b,0x0d,0x0a,0x09,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74, +/*000010*/ 0x20,0x28,0x63,0x29,0x20,0x32,0x30,0x32,0x33,0x20,0x53,0x63,0x6f,0x74,0x74,0x20, +/*000020*/ 0x4c,0x65,0x6d,0x62,0x63,0x6b,0x65,0x20,0x61,0x6e,0x64,0x20,0x48,0x6f,0x77,0x6c, +/*000030*/ 0x69,0x6e,0x67,0x20,0x4d,0x6f,0x6f,0x6e,0x20,0x53,0x6f,0x66,0x74,0x77,0x61,0x72, +/*000040*/ 0x65,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x50,0x65,0x72,0x6d,0x69,0x73,0x73,0x69,0x6f, +/*000050*/ 0x6e,0x20,0x69,0x73,0x20,0x68,0x65,0x72,0x65,0x62,0x79,0x20,0x67,0x72,0x61,0x6e, +/*000060*/ 0x74,0x65,0x64,0x2c,0x20,0x66,0x72,0x65,0x65,0x20,0x6f,0x66,0x20,0x63,0x68,0x61, +/*000070*/ 0x72,0x67,0x65,0x2c,0x20,0x74,0x6f,0x20,0x61,0x6e,0x79,0x20,0x70,0x65,0x72,0x73, +/*000080*/ 0x6f,0x6e,0x20,0x6f,0x62,0x74,0x61,0x69,0x6e,0x69,0x6e,0x67,0x20,0x61,0x20,0x63, +/*000090*/ 0x6f,0x70,0x79,0x0d,0x0a,0x09,0x6f,0x66,0x20,0x74,0x68,0x69,0x73,0x20,0x73,0x6f, +/*0000a0*/ 0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x61,0x6e,0x64,0x20,0x61,0x73,0x73,0x6f,0x63, +/*0000b0*/ 0x69,0x61,0x74,0x65,0x64,0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x61,0x74, +/*0000c0*/ 0x69,0x6f,0x6e,0x20,0x66,0x69,0x6c,0x65,0x73,0x20,0x28,0x74,0x68,0x65,0x20,0x22, +/*0000d0*/ 0x53,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x22,0x29,0x2c,0x20,0x74,0x6f,0x20,0x64, +/*0000e0*/ 0x65,0x61,0x6c,0x0d,0x0a,0x09,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x53,0x6f,0x66, +/*0000f0*/ 0x74,0x77,0x61,0x72,0x65,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x72,0x65, +/*000100*/ 0x73,0x74,0x72,0x69,0x63,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x69,0x6e,0x63,0x6c,0x75, +/*000110*/ 0x64,0x69,0x6e,0x67,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x6c,0x69,0x6d, +/*000120*/ 0x69,0x74,0x61,0x74,0x69,0x6f,0x6e,0x20,0x74,0x68,0x65,0x20,0x72,0x69,0x67,0x68, +/*000130*/ 0x74,0x73,0x0d,0x0a,0x09,0x74,0x6f,0x20,0x75,0x73,0x65,0x2c,0x20,0x63,0x6f,0x70, +/*000140*/ 0x79,0x2c,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x2c,0x20,0x6d,0x65,0x72,0x67,0x65, +/*000150*/ 0x2c,0x20,0x70,0x75,0x62,0x6c,0x69,0x73,0x68,0x2c,0x20,0x64,0x69,0x73,0x74,0x72, +/*000160*/ 0x69,0x62,0x75,0x74,0x65,0x2c,0x20,0x73,0x75,0x62,0x6c,0x69,0x63,0x65,0x6e,0x73, +/*000170*/ 0x65,0x2c,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x73,0x65,0x6c,0x6c,0x0d,0x0a, +/*000180*/ 0x09,0x63,0x6f,0x70,0x69,0x65,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x53, +/*000190*/ 0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x2c,0x20,0x61,0x6e,0x64,0x20,0x74,0x6f,0x20, +/*0001a0*/ 0x70,0x65,0x72,0x6d,0x69,0x74,0x20,0x70,0x65,0x72,0x73,0x6f,0x6e,0x73,0x20,0x74, +/*0001b0*/ 0x6f,0x20,0x77,0x68,0x6f,0x6d,0x20,0x74,0x68,0x65,0x20,0x53,0x6f,0x66,0x74,0x77, +/*0001c0*/ 0x61,0x72,0x65,0x20,0x69,0x73,0x0d,0x0a,0x09,0x66,0x75,0x72,0x6e,0x69,0x73,0x68, +/*0001d0*/ 0x65,0x64,0x20,0x74,0x6f,0x20,0x64,0x6f,0x20,0x73,0x6f,0x2c,0x20,0x73,0x75,0x62, +/*0001e0*/ 0x6a,0x65,0x63,0x74,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x66,0x6f,0x6c,0x6c, +/*0001f0*/ 0x6f,0x77,0x69,0x6e,0x67,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x73, +/*000200*/ 0x3a,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x54,0x68,0x65,0x20,0x61,0x62,0x6f,0x76,0x65, +/*000210*/ 0x20,0x63,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x6e,0x6f,0x74,0x69,0x63, +/*000220*/ 0x65,0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x69,0x73,0x20,0x70,0x65,0x72,0x6d,0x69, +/*000230*/ 0x73,0x73,0x69,0x6f,0x6e,0x20,0x6e,0x6f,0x74,0x69,0x63,0x65,0x20,0x73,0x68,0x61, +/*000240*/ 0x6c,0x6c,0x20,0x62,0x65,0x20,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x64,0x20,0x69, +/*000250*/ 0x6e,0x0d,0x0a,0x09,0x61,0x6c,0x6c,0x20,0x63,0x6f,0x70,0x69,0x65,0x73,0x20,0x6f, +/*000260*/ 0x72,0x20,0x73,0x75,0x62,0x73,0x74,0x61,0x6e,0x74,0x69,0x61,0x6c,0x20,0x70,0x6f, +/*000270*/ 0x72,0x74,0x69,0x6f,0x6e,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x53,0x6f, +/*000280*/ 0x66,0x74,0x77,0x61,0x72,0x65,0x2e,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x54,0x48,0x45, +/*000290*/ 0x20,0x53,0x4f,0x46,0x54,0x57,0x41,0x52,0x45,0x20,0x49,0x53,0x20,0x50,0x52,0x4f, +/*0002a0*/ 0x56,0x49,0x44,0x45,0x44,0x20,0x22,0x41,0x53,0x20,0x49,0x53,0x22,0x2c,0x20,0x57, +/*0002b0*/ 0x49,0x54,0x48,0x4f,0x55,0x54,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x59,0x20, +/*0002c0*/ 0x4f,0x46,0x20,0x41,0x4e,0x59,0x20,0x4b,0x49,0x4e,0x44,0x2c,0x20,0x45,0x58,0x50, +/*0002d0*/ 0x52,0x45,0x53,0x53,0x20,0x4f,0x52,0x0d,0x0a,0x09,0x49,0x4d,0x50,0x4c,0x49,0x45, +/*0002e0*/ 0x44,0x2c,0x20,0x49,0x4e,0x43,0x4c,0x55,0x44,0x49,0x4e,0x47,0x20,0x42,0x55,0x54, +/*0002f0*/ 0x20,0x4e,0x4f,0x54,0x20,0x4c,0x49,0x4d,0x49,0x54,0x45,0x44,0x20,0x54,0x4f,0x20, +/*000300*/ 0x54,0x48,0x45,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x49,0x45,0x53,0x20,0x4f, +/*000310*/ 0x46,0x20,0x4d,0x45,0x52,0x43,0x48,0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49,0x54, +/*000320*/ 0x59,0x2c,0x0d,0x0a,0x09,0x46,0x49,0x54,0x4e,0x45,0x53,0x53,0x20,0x46,0x4f,0x52, +/*000330*/ 0x20,0x41,0x20,0x50,0x41,0x52,0x54,0x49,0x43,0x55,0x4c,0x41,0x52,0x20,0x50,0x55, +/*000340*/ 0x52,0x50,0x4f,0x53,0x45,0x20,0x41,0x4e,0x44,0x20,0x4e,0x4f,0x4e,0x49,0x4e,0x46, +/*000350*/ 0x52,0x49,0x4e,0x47,0x45,0x4d,0x45,0x4e,0x54,0x2e,0x20,0x49,0x4e,0x20,0x4e,0x4f, +/*000360*/ 0x20,0x45,0x56,0x45,0x4e,0x54,0x20,0x53,0x48,0x41,0x4c,0x4c,0x20,0x54,0x48,0x45, +/*000370*/ 0x0d,0x0a,0x09,0x41,0x55,0x54,0x48,0x4f,0x52,0x53,0x20,0x4f,0x52,0x20,0x43,0x4f, +/*000380*/ 0x50,0x59,0x52,0x49,0x47,0x48,0x54,0x20,0x48,0x4f,0x4c,0x44,0x45,0x52,0x53,0x20, +/*000390*/ 0x42,0x45,0x20,0x4c,0x49,0x41,0x42,0x4c,0x45,0x20,0x46,0x4f,0x52,0x20,0x41,0x4e, +/*0003a0*/ 0x59,0x20,0x43,0x4c,0x41,0x49,0x4d,0x2c,0x20,0x44,0x41,0x4d,0x41,0x47,0x45,0x53, +/*0003b0*/ 0x20,0x4f,0x52,0x20,0x4f,0x54,0x48,0x45,0x52,0x0d,0x0a,0x09,0x4c,0x49,0x41,0x42, +/*0003c0*/ 0x49,0x4c,0x49,0x54,0x59,0x2c,0x20,0x57,0x48,0x45,0x54,0x48,0x45,0x52,0x20,0x49, +/*0003d0*/ 0x4e,0x20,0x41,0x4e,0x20,0x41,0x43,0x54,0x49,0x4f,0x4e,0x20,0x4f,0x46,0x20,0x43, +/*0003e0*/ 0x4f,0x4e,0x54,0x52,0x41,0x43,0x54,0x2c,0x20,0x54,0x4f,0x52,0x54,0x20,0x4f,0x52, +/*0003f0*/ 0x20,0x4f,0x54,0x48,0x45,0x52,0x57,0x49,0x53,0x45,0x2c,0x20,0x41,0x52,0x49,0x53, +/*000400*/ 0x49,0x4e,0x47,0x20,0x46,0x52,0x4f,0x4d,0x2c,0x0d,0x0a,0x09,0x4f,0x55,0x54,0x20, +/*000410*/ 0x4f,0x46,0x20,0x4f,0x52,0x20,0x49,0x4e,0x20,0x43,0x4f,0x4e,0x4e,0x45,0x43,0x54, +/*000420*/ 0x49,0x4f,0x4e,0x20,0x57,0x49,0x54,0x48,0x20,0x54,0x48,0x45,0x20,0x53,0x4f,0x46, +/*000430*/ 0x54,0x57,0x41,0x52,0x45,0x20,0x4f,0x52,0x20,0x54,0x48,0x45,0x20,0x55,0x53,0x45, +/*000440*/ 0x20,0x4f,0x52,0x20,0x4f,0x54,0x48,0x45,0x52,0x20,0x44,0x45,0x41,0x4c,0x49,0x4e, +/*000450*/ 0x47,0x53,0x20,0x49,0x4e,0x20,0x54,0x48,0x45,0x0d,0x0a,0x09,0x53,0x4f,0x46,0x54, +/*000460*/ 0x57,0x41,0x52,0x45,0x2e,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x54,0x4f,0x44,0x4f,0x3a, +/*000470*/ 0x0d,0x0a,0x09,0x2a,0x20,0x50,0x72,0x69,0x6e,0x74,0x20,0x73,0x68,0x6f,0x72,0x74, +/*000480*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x61,0x72,0x67,0x75,0x6d,0x65, +/*000490*/ 0x6e,0x74,0x73,0x20,0x61,0x73,0x20,0x70,0x61,0x72,0x74,0x20,0x6f,0x66,0x20,0x73, +/*0004a0*/ 0x74,0x61,0x63,0x6b,0x20,0x6c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x0d,0x0a, +/*0004b0*/ 0x09,0x2a,0x20,0x50,0x72,0x6f,0x70,0x65,0x72,0x6c,0x79,0x20,0x68,0x61,0x6e,0x64, +/*0004c0*/ 0x6c,0x65,0x20,0x62,0x65,0x69,0x6e,0x67,0x20,0x72,0x65,0x65,0x6e,0x74,0x72,0x61, +/*0004d0*/ 0x6e,0x74,0x20,0x64,0x75,0x65,0x20,0x74,0x6f,0x20,0x63,0x6f,0x72,0x6f,0x75,0x74, +/*0004e0*/ 0x69,0x6e,0x65,0x73,0x2e,0x0d,0x0a,0x5d,0x5d,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63, +/*0004f0*/ 0x61,0x6c,0x20,0x64,0x62,0x67,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x55,0x73,0x65, +/*000500*/ 0x20,0x41,0x4e,0x53,0x49,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x63,0x6f,0x64,0x65, +/*000510*/ 0x73,0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x6f,0x6d,0x70,0x74,0x20, +/*000520*/ 0x62,0x79,0x20,0x64,0x65,0x66,0x61,0x75,0x6c,0x74,0x2e,0x0d,0x0a,0x6c,0x6f,0x63, +/*000530*/ 0x61,0x6c,0x20,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x47,0x52,0x41,0x59,0x20,0x3d,0x20, +/*000540*/ 0x22,0x22,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*000550*/ 0x52,0x45,0x44,0x20,0x3d,0x20,0x22,0x22,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*000560*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x20,0x3d,0x20,0x22,0x22,0x0d, +/*000570*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*000580*/ 0x4c,0x4f,0x57,0x20,0x3d,0x20,0x22,0x22,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*000590*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x20,0x3d,0x20,0x22,0x22, +/*0005a0*/ 0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41, +/*0005b0*/ 0x52,0x45,0x54,0x20,0x3d,0x20,0x22,0x20,0x3d,0x3e,0x20,0x22,0x0d,0x0a,0x0d,0x0a, +/*0005c0*/ 0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x70, +/*0005d0*/ 0x72,0x65,0x74,0x74,0x79,0x28,0x6f,0x62,0x6a,0x2c,0x20,0x6d,0x61,0x78,0x5f,0x64, +/*0005e0*/ 0x65,0x70,0x74,0x68,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20,0x6d,0x61,0x78,0x5f,0x64, +/*0005f0*/ 0x65,0x70,0x74,0x68,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x74,0x68,0x65,0x6e, +/*000600*/ 0x20,0x6d,0x61,0x78,0x5f,0x64,0x65,0x70,0x74,0x68,0x20,0x3d,0x20,0x64,0x62,0x67, +/*000610*/ 0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x5f,0x64,0x65,0x70,0x74,0x68,0x20,0x65,0x6e, +/*000620*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x75,0x72,0x6e, +/*000630*/ 0x73,0x20,0x74,0x72,0x75,0x65,0x20,0x69,0x66,0x20,0x61,0x20,0x74,0x61,0x62,0x6c, +/*000640*/ 0x65,0x20,0x68,0x61,0x73,0x20,0x61,0x20,0x5f,0x5f,0x74,0x6f,0x73,0x74,0x72,0x69, +/*000650*/ 0x6e,0x67,0x20,0x6d,0x65,0x74,0x61,0x6d,0x65,0x74,0x68,0x6f,0x64,0x2e,0x0d,0x0a, +/*000660*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*000670*/ 0x63,0x6f,0x65,0x72,0x63,0x65,0x61,0x62,0x6c,0x65,0x28,0x74,0x62,0x6c,0x29,0x0d, +/*000680*/ 0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6d,0x65,0x74,0x61,0x20,0x3d,0x20, +/*000690*/ 0x67,0x65,0x74,0x6d,0x65,0x74,0x61,0x74,0x61,0x62,0x6c,0x65,0x28,0x74,0x62,0x6c, +/*0006a0*/ 0x29,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x6d,0x65,0x74, +/*0006b0*/ 0x61,0x20,0x61,0x6e,0x64,0x20,0x6d,0x65,0x74,0x61,0x2e,0x5f,0x5f,0x74,0x6f,0x73, +/*0006c0*/ 0x74,0x72,0x69,0x6e,0x67,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d, +/*0006d0*/ 0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e, +/*0006e0*/ 0x20,0x72,0x65,0x63,0x75,0x72,0x73,0x65,0x28,0x6f,0x62,0x6a,0x2c,0x20,0x64,0x65, +/*0006f0*/ 0x70,0x74,0x68,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x74,0x79,0x70,0x65,0x28, +/*000700*/ 0x6f,0x62,0x6a,0x29,0x20,0x3d,0x3d,0x20,0x22,0x73,0x74,0x72,0x69,0x6e,0x67,0x22, +/*000710*/ 0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d,0x20,0x44,0x75,0x6d, +/*000720*/ 0x70,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x73,0x6f,0x20, +/*000730*/ 0x74,0x68,0x61,0x74,0x20,0x65,0x73,0x63,0x61,0x70,0x65,0x20,0x73,0x65,0x71,0x75, +/*000740*/ 0x65,0x6e,0x63,0x65,0x73,0x20,0x61,0x72,0x65,0x20,0x70,0x72,0x69,0x6e,0x74,0x65, +/*000750*/ 0x64,0x2e,0x0d,0x0a,0x09,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74, +/*000760*/ 0x72,0x69,0x6e,0x67,0x2e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x28,0x22,0x25,0x71,0x22, +/*000770*/ 0x2c,0x20,0x6f,0x62,0x6a,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6c,0x73,0x65,0x69,0x66, +/*000780*/ 0x20,0x74,0x79,0x70,0x65,0x28,0x6f,0x62,0x6a,0x29,0x20,0x3d,0x3d,0x20,0x22,0x74, +/*000790*/ 0x61,0x62,0x6c,0x65,0x22,0x20,0x61,0x6e,0x64,0x20,0x64,0x65,0x70,0x74,0x68,0x20, +/*0007a0*/ 0x3c,0x20,0x6d,0x61,0x78,0x5f,0x64,0x65,0x70,0x74,0x68,0x20,0x61,0x6e,0x64,0x20, +/*0007b0*/ 0x6e,0x6f,0x74,0x20,0x63,0x6f,0x65,0x72,0x63,0x65,0x61,0x62,0x6c,0x65,0x28,0x6f, +/*0007c0*/ 0x62,0x6a,0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63, +/*0007d0*/ 0x61,0x6c,0x20,0x73,0x74,0x72,0x20,0x3d,0x20,0x22,0x7b,0x22,0x0d,0x0a,0x09,0x09, +/*0007e0*/ 0x09,0x0d,0x0a,0x09,0x09,0x09,0x66,0x6f,0x72,0x20,0x6b,0x2c,0x20,0x76,0x20,0x69, +/*0007f0*/ 0x6e,0x20,0x70,0x61,0x69,0x72,0x73,0x28,0x6f,0x62,0x6a,0x29,0x20,0x64,0x6f,0x0d, +/*000800*/ 0x0a,0x09,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x70,0x61,0x69,0x72,0x20, +/*000810*/ 0x3d,0x20,0x70,0x72,0x65,0x74,0x74,0x79,0x28,0x6b,0x2c,0x20,0x30,0x29,0x2e,0x2e, +/*000820*/ 0x22,0x20,0x3d,0x20,0x22,0x2e,0x2e,0x72,0x65,0x63,0x75,0x72,0x73,0x65,0x28,0x76, +/*000830*/ 0x2c,0x20,0x64,0x65,0x70,0x74,0x68,0x20,0x2b,0x20,0x31,0x29,0x0d,0x0a,0x09,0x09, +/*000840*/ 0x09,0x09,0x73,0x74,0x72,0x20,0x3d,0x20,0x73,0x74,0x72,0x2e,0x2e,0x28,0x73,0x74, +/*000850*/ 0x72,0x20,0x3d,0x3d,0x20,0x22,0x7b,0x22,0x20,0x61,0x6e,0x64,0x20,0x70,0x61,0x69, +/*000860*/ 0x72,0x20,0x6f,0x72,0x20,0x22,0x2c,0x20,0x22,0x2e,0x2e,0x70,0x61,0x69,0x72,0x29, +/*000870*/ 0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x0d,0x0a,0x09, +/*000880*/ 0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x72,0x2e,0x2e,0x22,0x7d, +/*000890*/ 0x22,0x0d,0x0a,0x09,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d, +/*0008a0*/ 0x20,0x74,0x6f,0x73,0x74,0x72,0x69,0x6e,0x67,0x28,0x29,0x20,0x63,0x61,0x6e,0x20, +/*0008b0*/ 0x66,0x61,0x69,0x6c,0x20,0x69,0x66,0x20,0x74,0x68,0x65,0x72,0x65,0x20,0x69,0x73, +/*0008c0*/ 0x20,0x61,0x6e,0x20,0x65,0x72,0x72,0x6f,0x72,0x20,0x69,0x6e,0x20,0x61,0x20,0x5f, +/*0008d0*/ 0x5f,0x74,0x6f,0x73,0x74,0x72,0x69,0x6e,0x67,0x20,0x6d,0x65,0x74,0x61,0x6d,0x65, +/*0008e0*/ 0x74,0x68,0x6f,0x64,0x2e,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*0008f0*/ 0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x2c,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d, +/*000900*/ 0x20,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28, +/*000910*/ 0x29,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x6f,0x73,0x74,0x72,0x69,0x6e, +/*000920*/ 0x67,0x28,0x6f,0x62,0x6a,0x29,0x20,0x65,0x6e,0x64,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*000930*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x20, +/*000940*/ 0x61,0x6e,0x64,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x6f,0x72,0x20,0x22,0x3c,0x21, +/*000950*/ 0x21,0x65,0x72,0x72,0x6f,0x72,0x20,0x69,0x6e,0x20,0x5f,0x5f,0x74,0x6f,0x73,0x74, +/*000960*/ 0x72,0x69,0x6e,0x67,0x20,0x6d,0x65,0x74,0x61,0x6d,0x65,0x74,0x68,0x6f,0x64,0x21, +/*000970*/ 0x21,0x3e,0x22,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6e, +/*000980*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x72,0x65, +/*000990*/ 0x63,0x75,0x72,0x73,0x65,0x28,0x6f,0x62,0x6a,0x2c,0x20,0x30,0x29,0x0d,0x0a,0x65, +/*0009a0*/ 0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x54,0x68,0x65,0x20,0x73,0x74,0x61, +/*0009b0*/ 0x63,0x6b,0x20,0x6c,0x65,0x76,0x65,0x6c,0x20,0x74,0x68,0x61,0x74,0x20,0x63,0x6d, +/*0009c0*/ 0x64,0x5f,0x2a,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x20,0x75,0x73, +/*0009d0*/ 0x65,0x20,0x74,0x6f,0x20,0x61,0x63,0x63,0x65,0x73,0x73,0x20,0x6c,0x6f,0x63,0x61, +/*0009e0*/ 0x6c,0x73,0x20,0x6f,0x72,0x20,0x69,0x6e,0x66,0x6f,0x0d,0x0a,0x2d,0x2d,0x20,0x54, +/*0009f0*/ 0x68,0x65,0x20,0x73,0x74,0x72,0x75,0x63,0x74,0x75,0x72,0x65,0x20,0x6f,0x66,0x20, +/*000a00*/ 0x74,0x68,0x65,0x20,0x63,0x6f,0x64,0x65,0x20,0x76,0x65,0x72,0x79,0x20,0x63,0x61, +/*000a10*/ 0x72,0x65,0x66,0x75,0x6c,0x6c,0x79,0x20,0x65,0x6e,0x73,0x75,0x72,0x65,0x73,0x20, +/*000a20*/ 0x74,0x68,0x69,0x73,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x43,0x4d,0x44, +/*000a30*/ 0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x20,0x3d,0x20,0x36, +/*000a40*/ 0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x4c,0x6f,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20, +/*000a50*/ 0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x74,0x6f,0x70,0x20,0x6f,0x66,0x20,0x74,0x68, +/*000a60*/ 0x65,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x6f,0x75,0x74,0x73,0x69,0x64,0x65,0x20, +/*000a70*/ 0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x2e, +/*000a80*/ 0x0d,0x0a,0x2d,0x2d,0x20,0x41,0x64,0x6a,0x75,0x73,0x74,0x65,0x64,0x20,0x62,0x79, +/*000a90*/ 0x20,0x73,0x6f,0x6d,0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x20,0x65, +/*000aa0*/ 0x6e,0x74,0x72,0x79,0x70,0x6f,0x69,0x6e,0x74,0x73,0x2e,0x0d,0x0a,0x6c,0x6f,0x63, +/*000ab0*/ 0x61,0x6c,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x20,0x3d,0x20,0x30, +/*000ac0*/ 0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x54,0x68,0x65,0x20,0x63,0x75,0x72,0x72,0x65, +/*000ad0*/ 0x6e,0x74,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x66,0x72,0x61,0x6d,0x65,0x20,0x69, +/*000ae0*/ 0x6e,0x64,0x65,0x78,0x2e,0x0d,0x0a,0x2d,0x2d,0x20,0x43,0x68,0x61,0x6e,0x67,0x65, +/*000af0*/ 0x64,0x20,0x75,0x73,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x75,0x70,0x2f,0x64, +/*000b00*/ 0x6f,0x77,0x6e,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x73,0x0d,0x0a,0x6c,0x6f, +/*000b10*/ 0x63,0x61,0x6c,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63, +/*000b20*/ 0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x30,0x0d,0x0a,0x0d,0x0a, +/*000b30*/ 0x2d,0x2d,0x20,0x4c,0x75,0x61,0x4a,0x49,0x54,0x20,0x68,0x61,0x73,0x20,0x61,0x6e, +/*000b40*/ 0x20,0x6f,0x66,0x66,0x20,0x62,0x79,0x20,0x6f,0x6e,0x65,0x20,0x62,0x75,0x67,0x20, +/*000b50*/ 0x77,0x68,0x65,0x6e,0x20,0x73,0x65,0x74,0x74,0x69,0x6e,0x67,0x20,0x6c,0x6f,0x63, +/*000b60*/ 0x61,0x6c,0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x73,0x2e,0x0d,0x0a,0x6c, +/*000b70*/ 0x6f,0x63,0x61,0x6c,0x20,0x4c,0x55,0x41,0x5f,0x4a,0x49,0x54,0x5f,0x53,0x45,0x54, +/*000b80*/ 0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x57,0x4f,0x52,0x4b,0x41,0x52,0x4f,0x55,0x4e,0x44, +/*000b90*/ 0x20,0x3d,0x20,0x30,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x44,0x65,0x66,0x61,0x75, +/*000ba0*/ 0x6c,0x74,0x20,0x64,0x62,0x67,0x2e,0x72,0x65,0x61,0x64,0x20,0x66,0x75,0x6e,0x63, +/*000bb0*/ 0x74,0x69,0x6f,0x6e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63, +/*000bc0*/ 0x74,0x69,0x6f,0x6e,0x20,0x64,0x62,0x67,0x5f,0x72,0x65,0x61,0x64,0x28,0x70,0x72, +/*000bd0*/ 0x6f,0x6d,0x70,0x74,0x29,0x0d,0x0a,0x09,0x64,0x62,0x67,0x2e,0x77,0x72,0x69,0x74, +/*000be0*/ 0x65,0x28,0x70,0x72,0x6f,0x6d,0x70,0x74,0x29,0x0d,0x0a,0x09,0x69,0x6f,0x2e,0x66, +/*000bf0*/ 0x6c,0x75,0x73,0x68,0x28,0x29,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*000c00*/ 0x69,0x6f,0x2e,0x72,0x65,0x61,0x64,0x28,0x29,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a, +/*000c10*/ 0x0d,0x0a,0x2d,0x2d,0x20,0x44,0x65,0x66,0x61,0x75,0x6c,0x74,0x20,0x64,0x62,0x67, +/*000c20*/ 0x2e,0x77,0x72,0x69,0x74,0x65,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x0d, +/*000c30*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*000c40*/ 0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x74,0x72,0x29,0x0d,0x0a, +/*000c50*/ 0x09,0x69,0x6f,0x2e,0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x74,0x72,0x29,0x0d,0x0a, +/*000c60*/ 0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e, +/*000c70*/ 0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c, +/*000c80*/ 0x6e,0x28,0x73,0x74,0x72,0x2c,0x20,0x2e,0x2e,0x2e,0x29,0x0d,0x0a,0x09,0x69,0x66, +/*000c90*/ 0x20,0x73,0x65,0x6c,0x65,0x63,0x74,0x28,0x22,0x23,0x22,0x2c,0x20,0x2e,0x2e,0x2e, +/*000ca0*/ 0x29,0x20,0x3d,0x3d,0x20,0x30,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x64, +/*000cb0*/ 0x62,0x67,0x2e,0x77,0x72,0x69,0x74,0x65,0x28,0x28,0x73,0x74,0x72,0x20,0x6f,0x72, +/*000cc0*/ 0x20,0x22,0x3c,0x4e,0x55,0x4c,0x4c,0x3e,0x22,0x29,0x2e,0x2e,0x22,0x5c,0x6e,0x22, +/*000cd0*/ 0x29,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x2e, +/*000ce0*/ 0x77,0x72,0x69,0x74,0x65,0x28,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x66,0x6f,0x72, +/*000cf0*/ 0x6d,0x61,0x74,0x28,0x73,0x74,0x72,0x2e,0x2e,0x22,0x5c,0x6e,0x22,0x2c,0x20,0x2e, +/*000d00*/ 0x2e,0x2e,0x29,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*000d10*/ 0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f, +/*000d20*/ 0x6e,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x6c,0x6f,0x63,0x28,0x66,0x69,0x6c, +/*000d30*/ 0x65,0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*000d40*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x66,0x69,0x6c,0x65, +/*000d50*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22, +/*000d60*/ 0x3a,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57, +/*000d70*/ 0x2e,0x2e,0x6c,0x69,0x6e,0x65,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*000d80*/ 0x53,0x45,0x54,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66, +/*000d90*/ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x73, +/*000da0*/ 0x74,0x61,0x63,0x6b,0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66,0x6f,0x28, +/*000db0*/ 0x69,0x6e,0x66,0x6f,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x69, +/*000dc0*/ 0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x73,0x6f, +/*000dd0*/ 0x75,0x72,0x63,0x65,0x3a,0x6d,0x61,0x74,0x63,0x68,0x28,0x22,0x40,0x28,0x2e,0x2a, +/*000de0*/ 0x29,0x22,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x6f,0x75,0x72, +/*000df0*/ 0x63,0x65,0x20,0x3d,0x20,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20,0x61,0x6e, +/*000e00*/ 0x64,0x20,0x64,0x62,0x67,0x2e,0x73,0x68,0x6f,0x72,0x74,0x65,0x6e,0x5f,0x70,0x61, +/*000e10*/ 0x74,0x68,0x28,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x29,0x20,0x6f,0x72,0x20, +/*000e20*/ 0x69,0x6e,0x66,0x6f,0x2e,0x73,0x68,0x6f,0x72,0x74,0x5f,0x73,0x72,0x63,0x0d,0x0a, +/*000e30*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6e,0x61,0x6d,0x65,0x77,0x68,0x61,0x74,0x20, +/*000e40*/ 0x3d,0x20,0x28,0x69,0x6e,0x66,0x6f,0x2e,0x6e,0x61,0x6d,0x65,0x77,0x68,0x61,0x74, +/*000e50*/ 0x20,0x3d,0x3d,0x20,0x22,0x22,0x20,0x61,0x6e,0x64,0x20,0x22,0x63,0x68,0x75,0x6e, +/*000e60*/ 0x6b,0x20,0x61,0x74,0x22,0x20,0x6f,0x72,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x6e,0x61, +/*000e70*/ 0x6d,0x65,0x77,0x68,0x61,0x74,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*000e80*/ 0x6e,0x61,0x6d,0x65,0x20,0x3d,0x20,0x28,0x69,0x6e,0x66,0x6f,0x2e,0x6e,0x61,0x6d, +/*000e90*/ 0x65,0x20,0x61,0x6e,0x64,0x20,0x22,0x27,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*000ea0*/ 0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x69,0x6e,0x66,0x6f,0x2e,0x6e,0x61,0x6d,0x65, +/*000eb0*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22, +/*000ec0*/ 0x27,0x22,0x20,0x6f,0x72,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x6c,0x6f,0x63, +/*000ed0*/ 0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x6c,0x69, +/*000ee0*/ 0x6e,0x65,0x64,0x65,0x66,0x69,0x6e,0x65,0x64,0x29,0x29,0x0d,0x0a,0x09,0x72,0x65, +/*000ef0*/ 0x74,0x75,0x72,0x6e,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x6c,0x6f,0x63,0x28, +/*000f00*/ 0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72, +/*000f10*/ 0x72,0x65,0x6e,0x74,0x6c,0x69,0x6e,0x65,0x29,0x2e,0x2e,0x22,0x20,0x69,0x6e,0x20, +/*000f20*/ 0x22,0x2e,0x2e,0x6e,0x61,0x6d,0x65,0x77,0x68,0x61,0x74,0x2e,0x2e,0x22,0x20,0x22, +/*000f30*/ 0x2e,0x2e,0x6e,0x61,0x6d,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c, +/*000f40*/ 0x6f,0x63,0x61,0x6c,0x20,0x72,0x65,0x70,0x6c,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20, +/*000f50*/ 0x52,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x20,0x66,0x6f,0x72, +/*000f60*/ 0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x66,0x72,0x61,0x6d,0x65,0x73,0x20,0x77,0x69, +/*000f70*/ 0x74,0x68,0x6f,0x75,0x74,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x0d,0x0a,0x2d, +/*000f80*/ 0x2d,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x73, +/*000f90*/ 0x20,0x43,0x20,0x66,0x72,0x61,0x6d,0x65,0x73,0x2c,0x20,0x4c,0x75,0x61,0x20,0x62, +/*000fa0*/ 0x79,0x74,0x65,0x63,0x6f,0x64,0x65,0x2c,0x20,0x61,0x6e,0x64,0x20,0x60,0x6c,0x6f, +/*000fb0*/ 0x61,0x64,0x73,0x74,0x72,0x69,0x6e,0x67,0x60,0x20,0x66,0x75,0x6e,0x63,0x74,0x69, +/*000fc0*/ 0x6f,0x6e,0x73,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74, +/*000fd0*/ 0x69,0x6f,0x6e,0x20,0x66,0x72,0x61,0x6d,0x65,0x5f,0x68,0x61,0x73,0x5f,0x6c,0x69, +/*000fe0*/ 0x6e,0x65,0x28,0x69,0x6e,0x66,0x6f,0x29,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*000ff0*/ 0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x6c,0x69,0x6e,0x65, +/*001000*/ 0x20,0x3e,0x3d,0x20,0x30,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63, +/*001010*/ 0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x68,0x6f,0x6f,0x6b, +/*001020*/ 0x5f,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x72,0x65,0x70,0x6c,0x5f,0x74,0x68, +/*001030*/ 0x72,0x65,0x73,0x68,0x6f,0x6c,0x64,0x29,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72, +/*001040*/ 0x6e,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x6f,0x66,0x66,0x73,0x65, +/*001050*/ 0x74,0x2c,0x20,0x72,0x65,0x61,0x73,0x6f,0x6e,0x29,0x0d,0x0a,0x09,0x09,0x72,0x65, +/*001060*/ 0x74,0x75,0x72,0x6e,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x65,0x76, +/*001070*/ 0x65,0x6e,0x74,0x2c,0x20,0x5f,0x29,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d,0x20,0x53, +/*001080*/ 0x6b,0x69,0x70,0x20,0x65,0x76,0x65,0x6e,0x74,0x73,0x20,0x74,0x68,0x61,0x74,0x20, +/*001090*/ 0x64,0x6f,0x6e,0x27,0x74,0x20,0x68,0x61,0x76,0x65,0x20,0x6c,0x69,0x6e,0x65,0x20, +/*0010a0*/ 0x69,0x6e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x69,0x6f,0x6e,0x2e,0x0d,0x0a,0x09,0x09, +/*0010b0*/ 0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x66,0x72,0x61,0x6d,0x65,0x5f,0x68,0x61, +/*0010c0*/ 0x73,0x5f,0x6c,0x69,0x6e,0x65,0x28,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74, +/*0010d0*/ 0x69,0x6e,0x66,0x6f,0x28,0x32,0x29,0x29,0x20,0x74,0x68,0x65,0x6e,0x20,0x72,0x65, +/*0010e0*/ 0x74,0x75,0x72,0x6e,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x0d,0x0a,0x09, +/*0010f0*/ 0x09,0x09,0x2d,0x2d,0x20,0x54,0x61,0x69,0x6c,0x20,0x63,0x61,0x6c,0x6c,0x73,0x20, +/*001100*/ 0x61,0x72,0x65,0x20,0x73,0x70,0x65,0x63,0x69,0x66,0x69,0x63,0x61,0x6c,0x6c,0x79, +/*001110*/ 0x20,0x69,0x67,0x6e,0x6f,0x72,0x65,0x64,0x20,0x73,0x69,0x6e,0x63,0x65,0x20,0x74, +/*001120*/ 0x68,0x65,0x79,0x20,0x61,0x6c,0x73,0x6f,0x20,0x77,0x69,0x6c,0x6c,0x20,0x68,0x61, +/*001130*/ 0x76,0x65,0x20,0x74,0x61,0x69,0x6c,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x73,0x20, +/*001140*/ 0x74,0x6f,0x20,0x62,0x61,0x6c,0x61,0x6e,0x63,0x65,0x20,0x6f,0x75,0x74,0x2e,0x0d, +/*001150*/ 0x0a,0x09,0x09,0x09,0x69,0x66,0x20,0x65,0x76,0x65,0x6e,0x74,0x20,0x3d,0x3d,0x20, +/*001160*/ 0x22,0x63,0x61,0x6c,0x6c,0x22,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09, +/*001170*/ 0x09,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x6f,0x66,0x66,0x73,0x65,0x74, +/*001180*/ 0x20,0x2b,0x20,0x31,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6c,0x73,0x65,0x69,0x66,0x20, +/*001190*/ 0x65,0x76,0x65,0x6e,0x74,0x20,0x3d,0x3d,0x20,0x22,0x72,0x65,0x74,0x75,0x72,0x6e, +/*0011a0*/ 0x22,0x20,0x61,0x6e,0x64,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3e,0x20,0x72, +/*0011b0*/ 0x65,0x70,0x6c,0x5f,0x74,0x68,0x72,0x65,0x73,0x68,0x6f,0x6c,0x64,0x20,0x74,0x68, +/*0011c0*/ 0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x09,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d, +/*0011d0*/ 0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2d,0x20,0x31,0x0d,0x0a,0x09,0x09,0x09, +/*0011e0*/ 0x65,0x6c,0x73,0x65,0x69,0x66,0x20,0x65,0x76,0x65,0x6e,0x74,0x20,0x3d,0x3d,0x20, +/*0011f0*/ 0x22,0x6c,0x69,0x6e,0x65,0x22,0x20,0x61,0x6e,0x64,0x20,0x6f,0x66,0x66,0x73,0x65, +/*001200*/ 0x74,0x20,0x3c,0x3d,0x20,0x72,0x65,0x70,0x6c,0x5f,0x74,0x68,0x72,0x65,0x73,0x68, +/*001210*/ 0x6f,0x6c,0x64,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x09,0x72,0x65, +/*001220*/ 0x70,0x6c,0x28,0x72,0x65,0x61,0x73,0x6f,0x6e,0x29,0x0d,0x0a,0x09,0x09,0x09,0x65, +/*001230*/ 0x6e,0x64,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d, +/*001240*/ 0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x68,0x6f, +/*001250*/ 0x6f,0x6b,0x5f,0x73,0x74,0x65,0x70,0x20,0x3d,0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x66, +/*001260*/ 0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x31,0x29,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c, +/*001270*/ 0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x6e,0x65,0x78,0x74,0x20,0x3d,0x20,0x68,0x6f,0x6f, +/*001280*/ 0x6b,0x5f,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x30,0x29,0x0d,0x0a,0x6c,0x6f, +/*001290*/ 0x63,0x61,0x6c,0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x66,0x69,0x6e,0x69,0x73,0x68,0x20, +/*0012a0*/ 0x3d,0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x2d, +/*0012b0*/ 0x31,0x29,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x43,0x72,0x65,0x61,0x74,0x65,0x20, +/*0012c0*/ 0x61,0x20,0x74,0x61,0x62,0x6c,0x65,0x20,0x6f,0x66,0x20,0x61,0x6c,0x6c,0x20,0x74, +/*0012d0*/ 0x68,0x65,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x6c,0x79,0x20,0x61,0x63,0x63,0x65,0x73, +/*0012e0*/ 0x73,0x69,0x62,0x6c,0x65,0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x73,0x2e, +/*0012f0*/ 0x0d,0x0a,0x2d,0x2d,0x20,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x20,0x61,0x72,0x65, +/*001300*/ 0x20,0x6e,0x6f,0x74,0x20,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x64,0x20,0x77,0x68, +/*001310*/ 0x65,0x6e,0x20,0x72,0x75,0x6e,0x6e,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x6c, +/*001320*/ 0x6f,0x63,0x61,0x6c,0x73,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x2c,0x20,0x62, +/*001330*/ 0x75,0x74,0x20,0x61,0x72,0x65,0x20,0x77,0x68,0x65,0x6e,0x20,0x72,0x75,0x6e,0x6e, +/*001340*/ 0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x70,0x72,0x69,0x6e,0x74,0x20,0x63,0x6f, +/*001350*/ 0x6d,0x6d,0x61,0x6e,0x64,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75, +/*001360*/ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x62,0x69,0x6e, +/*001370*/ 0x64,0x69,0x6e,0x67,0x73,0x28,0x6f,0x66,0x66,0x73,0x65,0x74,0x2c,0x20,0x69,0x6e, +/*001380*/ 0x63,0x6c,0x75,0x64,0x65,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x29,0x0d,0x0a, +/*001390*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6c,0x65,0x76,0x65,0x6c,0x20,0x3d,0x20,0x6f, +/*0013a0*/ 0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e, +/*0013b0*/ 0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x43, +/*0013c0*/ 0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x0d,0x0a, +/*0013d0*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x20,0x3d,0x20,0x64,0x65, +/*0013e0*/ 0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x6c,0x65,0x76,0x65, +/*0013f0*/ 0x6c,0x29,0x2e,0x66,0x75,0x6e,0x63,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*001400*/ 0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x20,0x3d,0x20,0x7b,0x7d,0x0d,0x0a,0x09, +/*001410*/ 0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x72,0x69,0x65,0x76,0x65,0x20,0x74, +/*001420*/ 0x68,0x65,0x20,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x73,0x0d,0x0a,0x09,0x64,0x6f, +/*001430*/ 0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20,0x3d,0x20,0x31,0x3b,0x20,0x77,0x68, +/*001440*/ 0x69,0x6c,0x65,0x20,0x74,0x72,0x75,0x65,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x6c, +/*001450*/ 0x6f,0x63,0x61,0x6c,0x20,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x76,0x61,0x6c,0x75,0x65, +/*001460*/ 0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x75,0x70,0x76,0x61, +/*001470*/ 0x6c,0x75,0x65,0x28,0x66,0x75,0x6e,0x63,0x2c,0x20,0x69,0x29,0x0d,0x0a,0x09,0x09, +/*001480*/ 0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x6e,0x61,0x6d,0x65,0x20,0x74,0x68,0x65,0x6e, +/*001490*/ 0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x62,0x69, +/*0014a0*/ 0x6e,0x64,0x69,0x6e,0x67,0x73,0x5b,0x6e,0x61,0x6d,0x65,0x5d,0x20,0x3d,0x20,0x76, +/*0014b0*/ 0x61,0x6c,0x75,0x65,0x0d,0x0a,0x09,0x09,0x69,0x20,0x3d,0x20,0x69,0x20,0x2b,0x20, +/*0014c0*/ 0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a, +/*0014d0*/ 0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x72,0x69,0x65,0x76,0x65,0x20,0x74,0x68,0x65, +/*0014e0*/ 0x20,0x6c,0x6f,0x63,0x61,0x6c,0x73,0x20,0x28,0x6f,0x76,0x65,0x72,0x77,0x72,0x69, +/*0014f0*/ 0x74,0x69,0x6e,0x67,0x20,0x61,0x6e,0x79,0x20,0x75,0x70,0x76,0x61,0x6c,0x75,0x65, +/*001500*/ 0x73,0x29,0x0d,0x0a,0x09,0x64,0x6f,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20, +/*001510*/ 0x3d,0x20,0x31,0x3b,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x74,0x72,0x75,0x65,0x20, +/*001520*/ 0x64,0x6f,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6e,0x61,0x6d,0x65, +/*001530*/ 0x2c,0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e, +/*001540*/ 0x67,0x65,0x74,0x6c,0x6f,0x63,0x61,0x6c,0x28,0x6c,0x65,0x76,0x65,0x6c,0x2c,0x20, +/*001550*/ 0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x6e,0x61,0x6d, +/*001560*/ 0x65,0x20,0x74,0x68,0x65,0x6e,0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65,0x6e,0x64, +/*001570*/ 0x0d,0x0a,0x09,0x09,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x5b,0x6e,0x61,0x6d, +/*001580*/ 0x65,0x5d,0x20,0x3d,0x20,0x76,0x61,0x6c,0x75,0x65,0x0d,0x0a,0x09,0x09,0x69,0x20, +/*001590*/ 0x3d,0x20,0x69,0x20,0x2b,0x20,0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x20,0x65,0x6e, +/*0015a0*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x72,0x69,0x65, +/*0015b0*/ 0x76,0x65,0x20,0x74,0x68,0x65,0x20,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x20,0x28, +/*0015c0*/ 0x77,0x6f,0x72,0x6b,0x73,0x20,0x69,0x6e,0x20,0x4c,0x75,0x61,0x20,0x35,0x2e,0x32, +/*0015d0*/ 0x20,0x61,0x6e,0x64,0x20,0x4c,0x75,0x61,0x4a,0x49,0x54,0x29,0x0d,0x0a,0x09,0x6c, +/*0015e0*/ 0x6f,0x63,0x61,0x6c,0x20,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x20,0x3d,0x20,0x7b, +/*0015f0*/ 0x7d,0x0d,0x0a,0x09,0x64,0x6f,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20,0x3d, +/*001600*/ 0x20,0x31,0x3b,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x74,0x72,0x75,0x65,0x20,0x64, +/*001610*/ 0x6f,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6e,0x61,0x6d,0x65,0x2c, +/*001620*/ 0x20,0x76,0x61,0x6c,0x75,0x65,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67, +/*001630*/ 0x65,0x74,0x6c,0x6f,0x63,0x61,0x6c,0x28,0x6c,0x65,0x76,0x65,0x6c,0x2c,0x20,0x2d, +/*001640*/ 0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x6e,0x61,0x6d, +/*001650*/ 0x65,0x20,0x74,0x68,0x65,0x6e,0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65,0x6e,0x64, +/*001660*/ 0x0d,0x0a,0x09,0x09,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x5b,0x69,0x5d,0x20,0x3d, +/*001670*/ 0x20,0x76,0x61,0x6c,0x75,0x65,0x0d,0x0a,0x09,0x09,0x69,0x20,0x3d,0x20,0x69,0x20, +/*001680*/ 0x2b,0x20,0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09, +/*001690*/ 0x69,0x66,0x20,0x23,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x20,0x3e,0x20,0x30,0x20, +/*0016a0*/ 0x74,0x68,0x65,0x6e,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x5b,0x22,0x2e, +/*0016b0*/ 0x2e,0x2e,0x22,0x5d,0x20,0x3d,0x20,0x76,0x61,0x72,0x61,0x72,0x67,0x73,0x20,0x65, +/*0016c0*/ 0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66,0x20,0x69,0x6e,0x63,0x6c,0x75, +/*0016d0*/ 0x64,0x65,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x20,0x74,0x68,0x65,0x6e,0x0d, +/*0016e0*/ 0x0a,0x09,0x09,0x2d,0x2d,0x20,0x49,0x6e,0x20,0x4c,0x75,0x61,0x20,0x35,0x2e,0x32, +/*0016f0*/ 0x2c,0x20,0x79,0x6f,0x75,0x20,0x68,0x61,0x76,0x65,0x20,0x74,0x6f,0x20,0x67,0x65, +/*001700*/ 0x74,0x20,0x74,0x68,0x65,0x20,0x65,0x6e,0x76,0x69,0x72,0x6f,0x6e,0x6d,0x65,0x6e, +/*001710*/ 0x74,0x20,0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x72,0x6f,0x6d,0x20,0x74,0x68,0x65, +/*001720*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x27,0x73,0x20,0x6c,0x6f,0x63,0x61, +/*001730*/ 0x6c,0x73,0x2e,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x76, +/*001740*/ 0x20,0x3d,0x20,0x28,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x20,0x3c,0x3d,0x20, +/*001750*/ 0x22,0x4c,0x75,0x61,0x20,0x35,0x2e,0x31,0x22,0x20,0x61,0x6e,0x64,0x20,0x67,0x65, +/*001760*/ 0x74,0x66,0x65,0x6e,0x76,0x28,0x66,0x75,0x6e,0x63,0x29,0x20,0x6f,0x72,0x20,0x62, +/*001770*/ 0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x2e,0x5f,0x45,0x4e,0x56,0x29,0x0d,0x0a,0x09, +/*001780*/ 0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x65,0x74,0x6d,0x65,0x74,0x61,0x74, +/*001790*/ 0x61,0x62,0x6c,0x65,0x28,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x2c,0x20,0x7b, +/*0017a0*/ 0x5f,0x5f,0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x20,0x65,0x6e,0x76,0x20,0x6f,0x72, +/*0017b0*/ 0x20,0x5f,0x47,0x7d,0x29,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09, +/*0017c0*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x0d, +/*0017d0*/ 0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d, +/*0017e0*/ 0x20,0x55,0x73,0x65,0x64,0x20,0x61,0x73,0x20,0x61,0x20,0x5f,0x5f,0x6e,0x65,0x77, +/*0017f0*/ 0x69,0x6e,0x64,0x65,0x78,0x20,0x6d,0x65,0x74,0x61,0x6d,0x65,0x74,0x68,0x6f,0x64, +/*001800*/ 0x20,0x74,0x6f,0x20,0x6d,0x6f,0x64,0x69,0x66,0x79,0x20,0x76,0x61,0x72,0x69,0x61, +/*001810*/ 0x62,0x6c,0x65,0x73,0x20,0x69,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x65,0x76,0x61,0x6c, +/*001820*/ 0x28,0x29,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74, +/*001830*/ 0x69,0x6f,0x6e,0x20,0x6d,0x75,0x74,0x61,0x74,0x65,0x5f,0x62,0x69,0x6e,0x64,0x69, +/*001840*/ 0x6e,0x67,0x73,0x28,0x5f,0x2c,0x20,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x76,0x61,0x6c, +/*001850*/ 0x75,0x65,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x46,0x55,0x4e,0x43, +/*001860*/ 0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x20,0x3d,0x20, +/*001870*/ 0x33,0x20,0x2d,0x2d,0x20,0x53,0x74,0x61,0x63,0x6b,0x20,0x64,0x65,0x70,0x74,0x68, +/*001880*/ 0x20,0x6f,0x66,0x20,0x74,0x68,0x69,0x73,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f, +/*001890*/ 0x6e,0x2e,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6c,0x65,0x76,0x65,0x6c, +/*0018a0*/ 0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74, +/*0018b0*/ 0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x46,0x55,0x4e,0x43,0x5f,0x53, +/*0018c0*/ 0x54,0x41,0x43,0x4b,0x5f,0x4f,0x46,0x46,0x53,0x45,0x54,0x20,0x2b,0x20,0x43,0x4d, +/*0018d0*/ 0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x0d,0x0a,0x09, +/*0018e0*/ 0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x53,0x65,0x74,0x20,0x61,0x20,0x6c,0x6f,0x63,0x61, +/*0018f0*/ 0x6c,0x2e,0x0d,0x0a,0x09,0x64,0x6f,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20, +/*001900*/ 0x3d,0x20,0x31,0x3b,0x20,0x72,0x65,0x70,0x65,0x61,0x74,0x0d,0x0a,0x09,0x09,0x6c, +/*001910*/ 0x6f,0x63,0x61,0x6c,0x20,0x76,0x61,0x72,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67, +/*001920*/ 0x2e,0x67,0x65,0x74,0x6c,0x6f,0x63,0x61,0x6c,0x28,0x6c,0x65,0x76,0x65,0x6c,0x2c, +/*001930*/ 0x20,0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x61,0x6d,0x65,0x20,0x3d, +/*001940*/ 0x3d,0x20,0x76,0x61,0x72,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x64, +/*001950*/ 0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52, +/*001960*/ 0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67, +/*001970*/ 0x65,0x72,0x2e,0x6c,0x75,0x61,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43, +/*001980*/ 0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x53,0x65,0x74,0x20,0x6c,0x6f,0x63,0x61,0x6c, +/*001990*/ 0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c, +/*0019a0*/ 0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x6e,0x61,0x6d,0x65,0x2e,0x2e,0x43, +/*0019b0*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*0019c0*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x73,0x65,0x74, +/*0019d0*/ 0x6c,0x6f,0x63,0x61,0x6c,0x28,0x6c,0x65,0x76,0x65,0x6c,0x20,0x2b,0x20,0x4c,0x55, +/*0019e0*/ 0x41,0x5f,0x4a,0x49,0x54,0x5f,0x53,0x45,0x54,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x57, +/*0019f0*/ 0x4f,0x52,0x4b,0x41,0x52,0x4f,0x55,0x4e,0x44,0x2c,0x20,0x69,0x2c,0x20,0x76,0x61, +/*001a00*/ 0x6c,0x75,0x65,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x69, +/*001a10*/ 0x20,0x3d,0x20,0x69,0x20,0x2b,0x20,0x31,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c, +/*001a20*/ 0x20,0x76,0x61,0x72,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x65,0x6e,0x64,0x0d, +/*001a30*/ 0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x53,0x65,0x74,0x20,0x61,0x6e,0x20,0x75, +/*001a40*/ 0x70,0x76,0x61,0x6c,0x75,0x65,0x2e,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*001a50*/ 0x66,0x75,0x6e,0x63,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74, +/*001a60*/ 0x69,0x6e,0x66,0x6f,0x28,0x6c,0x65,0x76,0x65,0x6c,0x29,0x2e,0x66,0x75,0x6e,0x63, +/*001a70*/ 0x0d,0x0a,0x09,0x64,0x6f,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x20,0x3d,0x20, +/*001a80*/ 0x31,0x3b,0x20,0x72,0x65,0x70,0x65,0x61,0x74,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63, +/*001a90*/ 0x61,0x6c,0x20,0x76,0x61,0x72,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67, +/*001aa0*/ 0x65,0x74,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x28,0x66,0x75,0x6e,0x63,0x2c,0x20, +/*001ab0*/ 0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x61,0x6d,0x65,0x20,0x3d,0x3d, +/*001ac0*/ 0x20,0x76,0x61,0x72,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x64,0x62, +/*001ad0*/ 0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*001ae0*/ 0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67,0x65, +/*001af0*/ 0x72,0x2e,0x6c,0x75,0x61,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41, +/*001b00*/ 0x52,0x45,0x54,0x2e,0x2e,0x22,0x53,0x65,0x74,0x20,0x75,0x70,0x76,0x61,0x6c,0x75, +/*001b10*/ 0x65,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e, +/*001b20*/ 0x2e,0x6e,0x61,0x6d,0x65,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53, +/*001b30*/ 0x45,0x54,0x29,0x0d,0x0a,0x09,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64, +/*001b40*/ 0x65,0x62,0x75,0x67,0x2e,0x73,0x65,0x74,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x28, +/*001b50*/ 0x66,0x75,0x6e,0x63,0x2c,0x20,0x69,0x2c,0x20,0x76,0x61,0x6c,0x75,0x65,0x29,0x0d, +/*001b60*/ 0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x69,0x20,0x3d,0x20,0x69,0x20, +/*001b70*/ 0x2b,0x20,0x31,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c,0x20,0x76,0x61,0x72,0x20, +/*001b80*/ 0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09, +/*001b90*/ 0x2d,0x2d,0x20,0x53,0x65,0x74,0x20,0x61,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x2e, +/*001ba0*/ 0x0d,0x0a,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*001bb0*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65, +/*001bc0*/ 0x62,0x75,0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x22,0x2e,0x2e,0x47,0x52,0x45, +/*001bd0*/ 0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x53,0x65,0x74,0x20,0x67, +/*001be0*/ 0x6c,0x6f,0x62,0x61,0x6c,0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x20,0x22, +/*001bf0*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x6e,0x61, +/*001c00*/ 0x6d,0x65,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x29, +/*001c10*/ 0x0d,0x0a,0x09,0x5f,0x47,0x5b,0x6e,0x61,0x6d,0x65,0x5d,0x20,0x3d,0x20,0x76,0x61, +/*001c20*/ 0x6c,0x75,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x43, +/*001c30*/ 0x6f,0x6d,0x70,0x69,0x6c,0x65,0x20,0x61,0x6e,0x20,0x65,0x78,0x70,0x72,0x65,0x73, +/*001c40*/ 0x73,0x69,0x6f,0x6e,0x20,0x77,0x69,0x74,0x68,0x20,0x74,0x68,0x65,0x20,0x67,0x69, +/*001c50*/ 0x76,0x65,0x6e,0x20,0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x20,0x62,0x69,0x6e, +/*001c60*/ 0x64,0x69,0x6e,0x67,0x73,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75, +/*001c70*/ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x5f,0x63, +/*001c80*/ 0x68,0x75,0x6e,0x6b,0x28,0x62,0x6c,0x6f,0x63,0x6b,0x2c,0x20,0x65,0x6e,0x76,0x29, +/*001c90*/ 0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20, +/*001ca0*/ 0x3d,0x20,0x22,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x20, +/*001cb0*/ 0x52,0x45,0x50,0x4c,0x22,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x68, +/*001cc0*/ 0x75,0x6e,0x6b,0x20,0x3d,0x20,0x6e,0x69,0x6c,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69, +/*001cd0*/ 0x66,0x20,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x20,0x3c,0x3d,0x20,0x22,0x4c, +/*001ce0*/ 0x75,0x61,0x20,0x35,0x2e,0x31,0x22,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09, +/*001cf0*/ 0x63,0x68,0x75,0x6e,0x6b,0x20,0x3d,0x20,0x6c,0x6f,0x61,0x64,0x73,0x74,0x72,0x69, +/*001d00*/ 0x6e,0x67,0x28,0x62,0x6c,0x6f,0x63,0x6b,0x2c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65, +/*001d10*/ 0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x74,0x68, +/*001d20*/ 0x65,0x6e,0x20,0x73,0x65,0x74,0x66,0x65,0x6e,0x76,0x28,0x63,0x68,0x75,0x6e,0x6b, +/*001d30*/ 0x2c,0x20,0x65,0x6e,0x76,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6c,0x73, +/*001d40*/ 0x65,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x54,0x68,0x65,0x20,0x4c,0x75,0x61,0x20, +/*001d50*/ 0x35,0x2e,0x32,0x20,0x77,0x61,0x79,0x20,0x69,0x73,0x20,0x61,0x20,0x62,0x69,0x74, +/*001d60*/ 0x20,0x63,0x6c,0x65,0x61,0x6e,0x65,0x72,0x0d,0x0a,0x09,0x09,0x63,0x68,0x75,0x6e, +/*001d70*/ 0x6b,0x20,0x3d,0x20,0x6c,0x6f,0x61,0x64,0x28,0x62,0x6c,0x6f,0x63,0x6b,0x2c,0x20, +/*001d80*/ 0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x22,0x74,0x22,0x2c,0x20,0x65,0x6e,0x76, +/*001d90*/ 0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66,0x20, +/*001da0*/ 0x6e,0x6f,0x74,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x74,0x68,0x65,0x6e,0x20,0x64, +/*001db0*/ 0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52, +/*001dc0*/ 0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x72,0x72,0x6f,0x72,0x3a,0x20,0x43,0x6f, +/*001dd0*/ 0x75,0x6c,0x64,0x20,0x6e,0x6f,0x74,0x20,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x20, +/*001de0*/ 0x62,0x6c,0x6f,0x63,0x6b,0x3a,0x5c,0x6e,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*001df0*/ 0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x62,0x6c,0x6f,0x63,0x6b,0x29,0x20,0x65, +/*001e00*/ 0x6e,0x64,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x63,0x68,0x75,0x6e, +/*001e10*/ 0x6b,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*001e20*/ 0x53,0x4f,0x55,0x52,0x43,0x45,0x5f,0x43,0x41,0x43,0x48,0x45,0x20,0x3d,0x20,0x7b, +/*001e30*/ 0x7d,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74, +/*001e40*/ 0x69,0x6f,0x6e,0x20,0x77,0x68,0x65,0x72,0x65,0x28,0x69,0x6e,0x66,0x6f,0x2c,0x20, +/*001e50*/ 0x63,0x6f,0x6e,0x74,0x65,0x78,0x74,0x5f,0x6c,0x69,0x6e,0x65,0x73,0x29,0x0d,0x0a, +/*001e60*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x3d,0x20, +/*001e70*/ 0x53,0x4f,0x55,0x52,0x43,0x45,0x5f,0x43,0x41,0x43,0x48,0x45,0x5b,0x69,0x6e,0x66, +/*001e80*/ 0x6f,0x2e,0x73,0x6f,0x75,0x72,0x63,0x65,0x5d,0x0d,0x0a,0x09,0x69,0x66,0x20,0x6e, +/*001e90*/ 0x6f,0x74,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a, +/*001ea0*/ 0x09,0x09,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x3d,0x20,0x7b,0x7d,0x0d,0x0a,0x09, +/*001eb0*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20, +/*001ec0*/ 0x3d,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x73,0x6f,0x75,0x72,0x63,0x65,0x3a,0x6d,0x61, +/*001ed0*/ 0x74,0x63,0x68,0x28,0x22,0x40,0x28,0x2e,0x2a,0x29,0x22,0x29,0x0d,0x0a,0x09,0x09, +/*001ee0*/ 0x69,0x66,0x20,0x66,0x69,0x6c,0x65,0x6e,0x61,0x6d,0x65,0x20,0x74,0x68,0x65,0x6e, +/*001ef0*/ 0x0d,0x0a,0x09,0x09,0x09,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66,0x75,0x6e,0x63,0x74, +/*001f00*/ 0x69,0x6f,0x6e,0x28,0x29,0x20,0x66,0x6f,0x72,0x20,0x6c,0x69,0x6e,0x65,0x20,0x69, +/*001f10*/ 0x6e,0x20,0x69,0x6f,0x2e,0x6c,0x69,0x6e,0x65,0x73,0x28,0x66,0x69,0x6c,0x65,0x6e, +/*001f20*/ 0x61,0x6d,0x65,0x29,0x20,0x64,0x6f,0x20,0x74,0x61,0x62,0x6c,0x65,0x2e,0x69,0x6e, +/*001f30*/ 0x73,0x65,0x72,0x74,0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x6c,0x69,0x6e, +/*001f40*/ 0x65,0x29,0x20,0x65,0x6e,0x64,0x20,0x65,0x6e,0x64,0x29,0x0d,0x0a,0x09,0x09,0x65, +/*001f50*/ 0x6c,0x73,0x65,0x69,0x66,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x73,0x6f,0x75,0x72,0x63, +/*001f60*/ 0x65,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x66,0x6f,0x72,0x20,0x6c, +/*001f70*/ 0x69,0x6e,0x65,0x20,0x69,0x6e,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x73,0x6f,0x75,0x72, +/*001f80*/ 0x63,0x65,0x3a,0x67,0x6d,0x61,0x74,0x63,0x68,0x28,0x22,0x28,0x2e,0x2d,0x29,0x5c, +/*001f90*/ 0x6e,0x22,0x29,0x20,0x64,0x6f,0x20,0x74,0x61,0x62,0x6c,0x65,0x2e,0x69,0x6e,0x73, +/*001fa0*/ 0x65,0x72,0x74,0x28,0x73,0x6f,0x75,0x72,0x63,0x65,0x2c,0x20,0x6c,0x69,0x6e,0x65, +/*001fb0*/ 0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09, +/*001fc0*/ 0x53,0x4f,0x55,0x52,0x43,0x45,0x5f,0x43,0x41,0x43,0x48,0x45,0x5b,0x69,0x6e,0x66, +/*001fd0*/ 0x6f,0x2e,0x73,0x6f,0x75,0x72,0x63,0x65,0x5d,0x20,0x3d,0x20,0x73,0x6f,0x75,0x72, +/*001fe0*/ 0x63,0x65,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66, +/*001ff0*/ 0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x61,0x6e,0x64,0x20,0x73,0x6f,0x75,0x72, +/*002000*/ 0x63,0x65,0x5b,0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x6c, +/*002010*/ 0x69,0x6e,0x65,0x5d,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x66,0x6f,0x72, +/*002020*/ 0x20,0x69,0x20,0x3d,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72,0x72,0x65,0x6e, +/*002030*/ 0x74,0x6c,0x69,0x6e,0x65,0x20,0x2d,0x20,0x63,0x6f,0x6e,0x74,0x65,0x78,0x74,0x5f, +/*002040*/ 0x6c,0x69,0x6e,0x65,0x73,0x2c,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x63,0x75,0x72,0x72, +/*002050*/ 0x65,0x6e,0x74,0x6c,0x69,0x6e,0x65,0x20,0x2b,0x20,0x63,0x6f,0x6e,0x74,0x65,0x78, +/*002060*/ 0x74,0x5f,0x6c,0x69,0x6e,0x65,0x73,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x09,0x6c, +/*002070*/ 0x6f,0x63,0x61,0x6c,0x20,0x74,0x61,0x62,0x5f,0x6f,0x72,0x5f,0x63,0x61,0x72,0x65, +/*002080*/ 0x74,0x20,0x3d,0x20,0x28,0x69,0x20,0x3d,0x3d,0x20,0x69,0x6e,0x66,0x6f,0x2e,0x63, +/*002090*/ 0x75,0x72,0x72,0x65,0x6e,0x74,0x6c,0x69,0x6e,0x65,0x20,0x61,0x6e,0x64,0x20,0x20, +/*0020a0*/ 0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x20,0x6f,0x72,0x20,0x22, +/*0020b0*/ 0x20,0x20,0x20,0x20,0x22,0x29,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*0020c0*/ 0x20,0x6c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x5b,0x69, +/*0020d0*/ 0x5d,0x0d,0x0a,0x09,0x09,0x09,0x69,0x66,0x20,0x6c,0x69,0x6e,0x65,0x20,0x74,0x68, +/*0020e0*/ 0x65,0x6e,0x20,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*0020f0*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x47,0x52,0x41,0x59,0x2e,0x2e,0x22,0x25,0x20,0x34,0x64, +/*002100*/ 0x22,0x2e,0x2e,0x74,0x61,0x62,0x5f,0x6f,0x72,0x5f,0x63,0x61,0x72,0x65,0x74,0x2e, +/*002110*/ 0x2e,0x22,0x25,0x73,0x22,0x2c,0x20,0x69,0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x20, +/*002120*/ 0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6c,0x73, +/*002130*/ 0x65,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e, +/*002140*/ 0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x72,0x72, +/*002150*/ 0x6f,0x72,0x3a,0x20,0x53,0x6f,0x75,0x72,0x63,0x65,0x20,0x6e,0x6f,0x74,0x20,0x61, +/*002160*/ 0x76,0x61,0x69,0x6c,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x22,0x2e,0x2e, +/*002170*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x69,0x6e,0x66,0x6f, +/*002180*/ 0x2e,0x73,0x68,0x6f,0x72,0x74,0x5f,0x73,0x72,0x63,0x29,0x3b,0x0d,0x0a,0x09,0x65, +/*002190*/ 0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66, +/*0021a0*/ 0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20, +/*0021b0*/ 0x57,0x65,0x65,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e,0x20,0x64,0x69,0x66,0x66, +/*0021c0*/ 0x65,0x72,0x65,0x6e,0x63,0x65,0x73,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x75, +/*0021d0*/ 0x6e,0x70,0x61,0x63,0x6b,0x20,0x3d,0x20,0x75,0x6e,0x70,0x61,0x63,0x6b,0x20,0x6f, +/*0021e0*/ 0x72,0x20,0x74,0x61,0x62,0x6c,0x65,0x2e,0x75,0x6e,0x70,0x61,0x63,0x6b,0x0d,0x0a, +/*0021f0*/ 0x6c,0x6f,0x63,0x61,0x6c,0x20,0x70,0x61,0x63,0x6b,0x20,0x3d,0x20,0x66,0x75,0x6e, +/*002200*/ 0x63,0x74,0x69,0x6f,0x6e,0x28,0x2e,0x2e,0x2e,0x29,0x20,0x72,0x65,0x74,0x75,0x72, +/*002210*/ 0x6e,0x20,0x7b,0x6e,0x20,0x3d,0x20,0x73,0x65,0x6c,0x65,0x63,0x74,0x28,0x22,0x23, +/*002220*/ 0x22,0x2c,0x20,0x2e,0x2e,0x2e,0x29,0x2c,0x20,0x2e,0x2e,0x2e,0x7d,0x20,0x65,0x6e, +/*002230*/ 0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74, +/*002240*/ 0x69,0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x73,0x74,0x65,0x70,0x28,0x29,0x0d,0x0a, +/*002250*/ 0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f, +/*002260*/ 0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f, +/*002270*/ 0x70,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x2c, +/*002280*/ 0x20,0x68,0x6f,0x6f,0x6b,0x5f,0x73,0x74,0x65,0x70,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*002290*/ 0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f, +/*0022a0*/ 0x6e,0x20,0x63,0x6d,0x64,0x5f,0x6e,0x65,0x78,0x74,0x28,0x29,0x0d,0x0a,0x09,0x73, +/*0022b0*/ 0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66, +/*0022c0*/ 0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x0d, +/*0022d0*/ 0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x2c,0x20,0x68, +/*0022e0*/ 0x6f,0x6f,0x6b,0x5f,0x6e,0x65,0x78,0x74,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d, +/*0022f0*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*002300*/ 0x63,0x6d,0x64,0x5f,0x66,0x69,0x6e,0x69,0x73,0x68,0x28,0x29,0x0d,0x0a,0x09,0x6c, +/*002310*/ 0x6f,0x63,0x61,0x6c,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74, +/*002320*/ 0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x20,0x2d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f, +/*002330*/ 0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x0d,0x0a, +/*002340*/ 0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f, +/*002350*/ 0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f, +/*002360*/ 0x70,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x2c, +/*002370*/ 0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3c,0x20,0x30,0x20,0x61,0x6e,0x64,0x20, +/*002380*/ 0x68,0x6f,0x6f,0x6b,0x5f,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x28,0x6f,0x66,0x66, +/*002390*/ 0x73,0x65,0x74,0x20,0x2d,0x20,0x31,0x29,0x20,0x6f,0x72,0x20,0x68,0x6f,0x6f,0x6b, +/*0023a0*/ 0x5f,0x66,0x69,0x6e,0x69,0x73,0x68,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a, +/*0023b0*/ 0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63, +/*0023c0*/ 0x6d,0x64,0x5f,0x70,0x72,0x69,0x6e,0x74,0x28,0x65,0x78,0x70,0x72,0x29,0x0d,0x0a, +/*0023d0*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x76,0x20,0x3d,0x20,0x6c,0x6f,0x63, +/*0023e0*/ 0x61,0x6c,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x28,0x31,0x2c,0x20,0x74, +/*0023f0*/ 0x72,0x75,0x65,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x68,0x75, +/*002400*/ 0x6e,0x6b,0x20,0x3d,0x20,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x5f,0x63,0x68,0x75, +/*002410*/ 0x6e,0x6b,0x28,0x22,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x22,0x2e,0x2e,0x65,0x78, +/*002420*/ 0x70,0x72,0x2c,0x20,0x65,0x6e,0x76,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20,0x63,0x68, +/*002430*/ 0x75,0x6e,0x6b,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x74,0x68,0x65,0x6e,0x20, +/*002440*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x20,0x65,0x6e,0x64, +/*002450*/ 0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x43,0x61,0x6c,0x6c,0x20,0x74,0x68, +/*002460*/ 0x65,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x61,0x6e,0x64,0x20,0x63,0x6f,0x6c,0x6c, +/*002470*/ 0x65,0x63,0x74,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x2e, +/*002480*/ 0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73, +/*002490*/ 0x20,0x3d,0x20,0x70,0x61,0x63,0x6b,0x28,0x70,0x63,0x61,0x6c,0x6c,0x28,0x63,0x68, +/*0024a0*/ 0x75,0x6e,0x6b,0x2c,0x20,0x75,0x6e,0x70,0x61,0x63,0x6b,0x28,0x72,0x61,0x77,0x67, +/*0024b0*/ 0x65,0x74,0x28,0x65,0x6e,0x76,0x2c,0x20,0x22,0x2e,0x2e,0x2e,0x22,0x29,0x20,0x6f, +/*0024c0*/ 0x72,0x20,0x7b,0x7d,0x29,0x29,0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20, +/*0024d0*/ 0x54,0x68,0x65,0x20,0x66,0x69,0x72,0x73,0x74,0x20,0x72,0x65,0x73,0x75,0x6c,0x74, +/*0024e0*/ 0x20,0x69,0x73,0x20,0x74,0x68,0x65,0x20,0x70,0x63,0x61,0x6c,0x6c,0x20,0x65,0x72, +/*0024f0*/ 0x72,0x6f,0x72,0x2e,0x0d,0x0a,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x72,0x65, +/*002500*/ 0x73,0x75,0x6c,0x74,0x73,0x5b,0x31,0x5d,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09, +/*002510*/ 0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c, +/*002520*/ 0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x72,0x72,0x6f,0x72,0x3a,0x22, +/*002530*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22, +/*002540*/ 0x20,0x22,0x2e,0x2e,0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x5b,0x32,0x5d,0x29,0x0d, +/*002550*/ 0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*002560*/ 0x6f,0x75,0x74,0x70,0x75,0x74,0x20,0x3d,0x20,0x22,0x22,0x0d,0x0a,0x09,0x09,0x66, +/*002570*/ 0x6f,0x72,0x20,0x69,0x20,0x3d,0x20,0x32,0x2c,0x20,0x72,0x65,0x73,0x75,0x6c,0x74, +/*002580*/ 0x73,0x2e,0x6e,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x09,0x6f,0x75,0x74,0x70,0x75, +/*002590*/ 0x74,0x20,0x3d,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x2e,0x2e,0x28,0x69,0x20,0x7e, +/*0025a0*/ 0x3d,0x20,0x32,0x20,0x61,0x6e,0x64,0x20,0x22,0x2c,0x20,0x22,0x20,0x6f,0x72,0x20, +/*0025b0*/ 0x22,0x22,0x29,0x2e,0x2e,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x28, +/*0025c0*/ 0x72,0x65,0x73,0x75,0x6c,0x74,0x73,0x5b,0x69,0x5d,0x29,0x0d,0x0a,0x09,0x09,0x65, +/*0025d0*/ 0x6e,0x64,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6f,0x75,0x74, +/*0025e0*/ 0x70,0x75,0x74,0x20,0x3d,0x3d,0x20,0x22,0x22,0x20,0x74,0x68,0x65,0x6e,0x20,0x6f, +/*0025f0*/ 0x75,0x74,0x70,0x75,0x74,0x20,0x3d,0x20,0x22,0x3c,0x6e,0x6f,0x20,0x72,0x65,0x73, +/*002600*/ 0x75,0x6c,0x74,0x3e,0x22,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67, +/*002610*/ 0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42, +/*002620*/ 0x4c,0x55,0x45,0x2e,0x2e,0x65,0x78,0x70,0x72,0x2e,0x2e,0x20,0x47,0x52,0x45,0x45, +/*002630*/ 0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x6f,0x75,0x74,0x70,0x75,0x74,0x29, +/*002640*/ 0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75, +/*002650*/ 0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d, +/*002660*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*002670*/ 0x63,0x6d,0x64,0x5f,0x65,0x76,0x61,0x6c,0x28,0x63,0x6f,0x64,0x65,0x29,0x0d,0x0a, +/*002680*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x76,0x20,0x3d,0x20,0x6c,0x6f,0x63, +/*002690*/ 0x61,0x6c,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x28,0x31,0x2c,0x20,0x74, +/*0026a0*/ 0x72,0x75,0x65,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6d,0x75,0x74, +/*0026b0*/ 0x61,0x62,0x6c,0x65,0x5f,0x65,0x6e,0x76,0x20,0x3d,0x20,0x73,0x65,0x74,0x6d,0x65, +/*0026c0*/ 0x74,0x61,0x74,0x61,0x62,0x6c,0x65,0x28,0x7b,0x7d,0x2c,0x20,0x7b,0x0d,0x0a,0x09, +/*0026d0*/ 0x09,0x5f,0x5f,0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x20,0x65,0x6e,0x76,0x2c,0x0d, +/*0026e0*/ 0x0a,0x09,0x09,0x5f,0x5f,0x6e,0x65,0x77,0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x20, +/*0026f0*/ 0x6d,0x75,0x74,0x61,0x74,0x65,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x2c, +/*002700*/ 0x0d,0x0a,0x09,0x7d,0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*002710*/ 0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x3d,0x20,0x63,0x6f,0x6d,0x70,0x69,0x6c,0x65, +/*002720*/ 0x5f,0x63,0x68,0x75,0x6e,0x6b,0x28,0x63,0x6f,0x64,0x65,0x2c,0x20,0x6d,0x75,0x74, +/*002730*/ 0x61,0x62,0x6c,0x65,0x5f,0x65,0x6e,0x76,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20,0x63, +/*002740*/ 0x68,0x75,0x6e,0x6b,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x74,0x68,0x65,0x6e, +/*002750*/ 0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x20,0x65,0x6e, +/*002760*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x43,0x61,0x6c,0x6c,0x20,0x74, +/*002770*/ 0x68,0x65,0x20,0x63,0x68,0x75,0x6e,0x6b,0x20,0x61,0x6e,0x64,0x20,0x63,0x6f,0x6c, +/*002780*/ 0x6c,0x65,0x63,0x74,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x73, +/*002790*/ 0x2e,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x75,0x63,0x63,0x65,0x73, +/*0027a0*/ 0x73,0x2c,0x20,0x65,0x72,0x72,0x20,0x3d,0x20,0x70,0x63,0x61,0x6c,0x6c,0x28,0x63, +/*0027b0*/ 0x68,0x75,0x6e,0x6b,0x2c,0x20,0x75,0x6e,0x70,0x61,0x63,0x6b,0x28,0x72,0x61,0x77, +/*0027c0*/ 0x67,0x65,0x74,0x28,0x65,0x6e,0x76,0x2c,0x20,0x22,0x2e,0x2e,0x2e,0x22,0x29,0x20, +/*0027d0*/ 0x6f,0x72,0x20,0x7b,0x7d,0x29,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74, +/*0027e0*/ 0x20,0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09, +/*0027f0*/ 0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c, +/*002800*/ 0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x72,0x72,0x6f,0x72,0x3a,0x22, +/*002810*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22, +/*002820*/ 0x20,0x22,0x2e,0x2e,0x74,0x6f,0x73,0x74,0x72,0x69,0x6e,0x67,0x28,0x65,0x72,0x72, +/*002830*/ 0x29,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65, +/*002840*/ 0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*002850*/ 0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f, +/*002860*/ 0x6e,0x20,0x63,0x6d,0x64,0x5f,0x64,0x6f,0x77,0x6e,0x28,0x29,0x0d,0x0a,0x09,0x6c, +/*002870*/ 0x6f,0x63,0x61,0x6c,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74, +/*002880*/ 0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73, +/*002890*/ 0x65,0x74,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x6e,0x66,0x6f,0x0d, +/*0028a0*/ 0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x70,0x65,0x61,0x74,0x20,0x2d,0x2d,0x20,0x46, +/*0028b0*/ 0x69,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x6e,0x65,0x78,0x74,0x20,0x66,0x72,0x61, +/*0028c0*/ 0x6d,0x65,0x20,0x77,0x69,0x74,0x68,0x20,0x61,0x20,0x66,0x69,0x6c,0x65,0x2e,0x0d, +/*0028d0*/ 0x0a,0x09,0x09,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x6f,0x66,0x66,0x73, +/*0028e0*/ 0x65,0x74,0x20,0x2b,0x20,0x31,0x0d,0x0a,0x09,0x09,0x69,0x6e,0x66,0x6f,0x20,0x3d, +/*0028f0*/ 0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x6f, +/*002900*/ 0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43, +/*002910*/ 0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x29,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c, +/*002920*/ 0x20,0x6e,0x6f,0x74,0x20,0x69,0x6e,0x66,0x6f,0x20,0x6f,0x72,0x20,0x66,0x72,0x61, +/*002930*/ 0x6d,0x65,0x5f,0x68,0x61,0x73,0x5f,0x6c,0x69,0x6e,0x65,0x28,0x69,0x6e,0x66,0x6f, +/*002940*/ 0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66,0x20,0x69,0x6e,0x66,0x6f,0x20,0x74, +/*002950*/ 0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73, +/*002960*/ 0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x6f,0x66, +/*002970*/ 0x66,0x73,0x65,0x74,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74, +/*002980*/ 0x65,0x6c,0x6e,0x28,0x22,0x49,0x6e,0x73,0x70,0x65,0x63,0x74,0x69,0x6e,0x67,0x20, +/*002990*/ 0x66,0x72,0x61,0x6d,0x65,0x3a,0x20,0x22,0x2e,0x2e,0x66,0x6f,0x72,0x6d,0x61,0x74, +/*0029a0*/ 0x5f,0x73,0x74,0x61,0x63,0x6b,0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66, +/*0029b0*/ 0x6f,0x28,0x69,0x6e,0x66,0x6f,0x29,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x74, +/*0029c0*/ 0x6f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x28,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f, +/*0029d0*/ 0x5f,0x77,0x68,0x65,0x72,0x65,0x29,0x20,0x74,0x68,0x65,0x6e,0x20,0x77,0x68,0x65, +/*0029e0*/ 0x72,0x65,0x28,0x69,0x6e,0x66,0x6f,0x2c,0x20,0x64,0x62,0x67,0x2e,0x61,0x75,0x74, +/*0029f0*/ 0x6f,0x5f,0x77,0x68,0x65,0x72,0x65,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65, +/*002a00*/ 0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65, +/*002a10*/ 0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63, +/*002a20*/ 0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74, +/*002a30*/ 0x20,0x2b,0x20,0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56, +/*002a40*/ 0x45,0x4c,0x29,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65, +/*002a50*/ 0x6c,0x6e,0x28,0x22,0x41,0x6c,0x72,0x65,0x61,0x64,0x79,0x20,0x61,0x74,0x20,0x74, +/*002a60*/ 0x68,0x65,0x20,0x62,0x6f,0x74,0x74,0x6f,0x6d,0x20,0x6f,0x66,0x20,0x74,0x68,0x65, +/*002a70*/ 0x20,0x73,0x74,0x61,0x63,0x6b,0x2e,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d, +/*002a80*/ 0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73, +/*002a90*/ 0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*002aa0*/ 0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x75,0x70,0x28, +/*002ab0*/ 0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6f,0x66,0x66,0x73,0x65,0x74, +/*002ac0*/ 0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74, +/*002ad0*/ 0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*002ae0*/ 0x69,0x6e,0x66,0x6f,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x70,0x65,0x61,0x74, +/*002af0*/ 0x20,0x2d,0x2d,0x20,0x46,0x69,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x6e,0x65,0x78, +/*002b00*/ 0x74,0x20,0x66,0x72,0x61,0x6d,0x65,0x20,0x77,0x69,0x74,0x68,0x20,0x61,0x20,0x66, +/*002b10*/ 0x69,0x6c,0x65,0x2e,0x0d,0x0a,0x09,0x09,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d, +/*002b20*/ 0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2d,0x20,0x31,0x0d,0x0a,0x09,0x09,0x69, +/*002b30*/ 0x66,0x20,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3c,0x20,0x73,0x74,0x61,0x63,0x6b, +/*002b40*/ 0x5f,0x74,0x6f,0x70,0x20,0x74,0x68,0x65,0x6e,0x20,0x69,0x6e,0x66,0x6f,0x20,0x3d, +/*002b50*/ 0x20,0x6e,0x69,0x6c,0x3b,0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65,0x6e,0x64,0x0d, +/*002b60*/ 0x0a,0x09,0x09,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e, +/*002b70*/ 0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b, +/*002b80*/ 0x20,0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c, +/*002b90*/ 0x29,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c,0x20,0x66,0x72,0x61,0x6d,0x65,0x5f, +/*002ba0*/ 0x68,0x61,0x73,0x5f,0x6c,0x69,0x6e,0x65,0x28,0x69,0x6e,0x66,0x6f,0x29,0x0d,0x0a, +/*002bb0*/ 0x09,0x0d,0x0a,0x09,0x69,0x66,0x20,0x69,0x6e,0x66,0x6f,0x20,0x74,0x68,0x65,0x6e, +/*002bc0*/ 0x0d,0x0a,0x09,0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63, +/*002bd0*/ 0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x6f,0x66,0x66,0x73,0x65, +/*002be0*/ 0x74,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e, +/*002bf0*/ 0x28,0x22,0x49,0x6e,0x73,0x70,0x65,0x63,0x74,0x69,0x6e,0x67,0x20,0x66,0x72,0x61, +/*002c00*/ 0x6d,0x65,0x3a,0x20,0x22,0x2e,0x2e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x73,0x74, +/*002c10*/ 0x61,0x63,0x6b,0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66,0x6f,0x28,0x69, +/*002c20*/ 0x6e,0x66,0x6f,0x29,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x74,0x6f,0x6e,0x75, +/*002c30*/ 0x6d,0x62,0x65,0x72,0x28,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77,0x68, +/*002c40*/ 0x65,0x72,0x65,0x29,0x20,0x74,0x68,0x65,0x6e,0x20,0x77,0x68,0x65,0x72,0x65,0x28, +/*002c50*/ 0x69,0x6e,0x66,0x6f,0x2c,0x20,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77, +/*002c60*/ 0x68,0x65,0x72,0x65,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65, +/*002c70*/ 0x0d,0x0a,0x09,0x09,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67, +/*002c80*/ 0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69, +/*002c90*/ 0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20, +/*002ca0*/ 0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x29, +/*002cb0*/ 0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28, +/*002cc0*/ 0x22,0x41,0x6c,0x72,0x65,0x61,0x64,0x79,0x20,0x61,0x74,0x20,0x74,0x68,0x65,0x20, +/*002cd0*/ 0x74,0x6f,0x70,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x63,0x6b, +/*002ce0*/ 0x2e,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72, +/*002cf0*/ 0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64, +/*002d00*/ 0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69, +/*002d10*/ 0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x77,0x68,0x65,0x72,0x65,0x28,0x63,0x6f,0x6e, +/*002d20*/ 0x74,0x65,0x78,0x74,0x5f,0x6c,0x69,0x6e,0x65,0x73,0x29,0x0d,0x0a,0x09,0x6c,0x6f, +/*002d30*/ 0x63,0x61,0x6c,0x20,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67, +/*002d40*/ 0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69, +/*002d50*/ 0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20, +/*002d60*/ 0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x29, +/*002d70*/ 0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x28,0x69,0x6e,0x66,0x6f,0x20, +/*002d80*/ 0x61,0x6e,0x64,0x20,0x77,0x68,0x65,0x72,0x65,0x28,0x69,0x6e,0x66,0x6f,0x2c,0x20, +/*002d90*/ 0x74,0x6f,0x6e,0x75,0x6d,0x62,0x65,0x72,0x28,0x63,0x6f,0x6e,0x74,0x65,0x78,0x74, +/*002da0*/ 0x5f,0x6c,0x69,0x6e,0x65,0x73,0x29,0x20,0x6f,0x72,0x20,0x35,0x29,0x29,0x0d,0x0a, +/*002db0*/ 0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e, +/*002dc0*/ 0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x74,0x72,0x61,0x63,0x65,0x28, +/*002dd0*/ 0x29,0x0d,0x0a,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28, +/*002de0*/ 0x22,0x49,0x6e,0x73,0x70,0x65,0x63,0x74,0x69,0x6e,0x67,0x20,0x66,0x72,0x61,0x6d, +/*002df0*/ 0x65,0x20,0x25,0x64,0x22,0x2c,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73, +/*002e00*/ 0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2d,0x20,0x73,0x74, +/*002e10*/ 0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x29,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*002e20*/ 0x20,0x69,0x20,0x3d,0x20,0x30,0x3b,0x20,0x77,0x68,0x69,0x6c,0x65,0x20,0x74,0x72, +/*002e30*/ 0x75,0x65,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69, +/*002e40*/ 0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69, +/*002e50*/ 0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x20,0x2b,0x20, +/*002e60*/ 0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x20, +/*002e70*/ 0x2b,0x20,0x69,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x6e,0x6f,0x74,0x20,0x69, +/*002e80*/ 0x6e,0x66,0x6f,0x20,0x74,0x68,0x65,0x6e,0x20,0x62,0x72,0x65,0x61,0x6b,0x20,0x65, +/*002e90*/ 0x6e,0x64,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20, +/*002ea0*/ 0x69,0x73,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x5f,0x66,0x72,0x61,0x6d,0x65, +/*002eb0*/ 0x20,0x3d,0x20,0x28,0x69,0x20,0x2b,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f, +/*002ec0*/ 0x70,0x20,0x3d,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65, +/*002ed0*/ 0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x29,0x0d,0x0a,0x09,0x09,0x6c,0x6f, +/*002ee0*/ 0x63,0x61,0x6c,0x20,0x74,0x61,0x62,0x5f,0x6f,0x72,0x5f,0x63,0x61,0x72,0x65,0x74, +/*002ef0*/ 0x20,0x3d,0x20,0x28,0x69,0x73,0x5f,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x5f,0x66, +/*002f00*/ 0x72,0x61,0x6d,0x65,0x20,0x61,0x6e,0x64,0x20,0x20,0x47,0x52,0x45,0x45,0x4e,0x5f, +/*002f10*/ 0x43,0x41,0x52,0x45,0x54,0x20,0x6f,0x72,0x20,0x22,0x20,0x20,0x20,0x20,0x22,0x29, +/*002f20*/ 0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28, +/*002f30*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x47,0x52,0x41,0x59,0x2e,0x2e,0x22,0x25,0x20,0x34, +/*002f40*/ 0x64,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e, +/*002f50*/ 0x2e,0x74,0x61,0x62,0x5f,0x6f,0x72,0x5f,0x63,0x61,0x72,0x65,0x74,0x2e,0x2e,0x22, +/*002f60*/ 0x25,0x73,0x22,0x2c,0x20,0x69,0x2c,0x20,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x73, +/*002f70*/ 0x74,0x61,0x63,0x6b,0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66,0x6f,0x28, +/*002f80*/ 0x69,0x6e,0x66,0x6f,0x29,0x29,0x0d,0x0a,0x09,0x09,0x69,0x20,0x3d,0x20,0x69,0x20, +/*002f90*/ 0x2b,0x20,0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72, +/*002fa0*/ 0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64, +/*002fb0*/ 0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69, +/*002fc0*/ 0x6f,0x6e,0x20,0x63,0x6d,0x64,0x5f,0x6c,0x6f,0x63,0x61,0x6c,0x73,0x28,0x29,0x0d, +/*002fd0*/ 0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73, +/*002fe0*/ 0x20,0x3d,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67, +/*002ff0*/ 0x73,0x28,0x31,0x2c,0x20,0x66,0x61,0x6c,0x73,0x65,0x29,0x0d,0x0a,0x09,0x0d,0x0a, +/*003000*/ 0x09,0x2d,0x2d,0x20,0x47,0x65,0x74,0x20,0x61,0x6c,0x6c,0x20,0x74,0x68,0x65,0x20, +/*003010*/ 0x76,0x61,0x72,0x69,0x61,0x62,0x6c,0x65,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67, +/*003020*/ 0x20,0x6e,0x61,0x6d,0x65,0x73,0x20,0x61,0x6e,0x64,0x20,0x73,0x6f,0x72,0x74,0x20, +/*003030*/ 0x74,0x68,0x65,0x6d,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6b,0x65,0x79, +/*003040*/ 0x73,0x20,0x3d,0x20,0x7b,0x7d,0x0d,0x0a,0x09,0x66,0x6f,0x72,0x20,0x6b,0x2c,0x20, +/*003050*/ 0x5f,0x20,0x69,0x6e,0x20,0x70,0x61,0x69,0x72,0x73,0x28,0x62,0x69,0x6e,0x64,0x69, +/*003060*/ 0x6e,0x67,0x73,0x29,0x20,0x64,0x6f,0x20,0x74,0x61,0x62,0x6c,0x65,0x2e,0x69,0x6e, +/*003070*/ 0x73,0x65,0x72,0x74,0x28,0x6b,0x65,0x79,0x73,0x2c,0x20,0x6b,0x29,0x20,0x65,0x6e, +/*003080*/ 0x64,0x0d,0x0a,0x09,0x74,0x61,0x62,0x6c,0x65,0x2e,0x73,0x6f,0x72,0x74,0x28,0x6b, +/*003090*/ 0x65,0x79,0x73,0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x66,0x6f,0x72,0x20,0x5f,0x2c, +/*0030a0*/ 0x20,0x6b,0x20,0x69,0x6e,0x20,0x69,0x70,0x61,0x69,0x72,0x73,0x28,0x6b,0x65,0x79, +/*0030b0*/ 0x73,0x29,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x76, +/*0030c0*/ 0x20,0x3d,0x20,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73,0x5b,0x6b,0x5d,0x0d,0x0a, +/*0030d0*/ 0x09,0x09,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x53,0x6b,0x69,0x70,0x20,0x74,0x68, +/*0030e0*/ 0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x20,0x6f,0x62,0x6a,0x65,0x63, +/*0030f0*/ 0x74,0x20,0x69,0x74,0x73,0x65,0x6c,0x66,0x2c,0x20,0x22,0x28,0x2a,0x69,0x6e,0x74, +/*003100*/ 0x65,0x72,0x6e,0x61,0x6c,0x29,0x22,0x20,0x76,0x61,0x6c,0x75,0x65,0x73,0x2c,0x20, +/*003110*/ 0x61,0x6e,0x64,0x20,0x4c,0x75,0x61,0x20,0x35,0x2e,0x32,0x27,0x73,0x20,0x5f,0x45, +/*003120*/ 0x4e,0x56,0x20,0x6f,0x62,0x6a,0x65,0x63,0x74,0x2e,0x0d,0x0a,0x09,0x09,0x69,0x66, +/*003130*/ 0x20,0x6e,0x6f,0x74,0x20,0x72,0x61,0x77,0x65,0x71,0x75,0x61,0x6c,0x28,0x76,0x2c, +/*003140*/ 0x20,0x64,0x62,0x67,0x29,0x20,0x61,0x6e,0x64,0x20,0x6b,0x20,0x7e,0x3d,0x20,0x22, +/*003150*/ 0x5f,0x45,0x4e,0x56,0x22,0x20,0x61,0x6e,0x64,0x20,0x6e,0x6f,0x74,0x20,0x6b,0x3a, +/*003160*/ 0x6d,0x61,0x74,0x63,0x68,0x28,0x22,0x25,0x28,0x2e,0x2a,0x25,0x29,0x22,0x29,0x20, +/*003170*/ 0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69, +/*003180*/ 0x74,0x65,0x6c,0x6e,0x28,0x22,0x20,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*003190*/ 0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x6b,0x2e,0x2e,0x20,0x47,0x52,0x45,0x45,0x4e, +/*0031a0*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74, +/*0031b0*/ 0x74,0x79,0x28,0x76,0x29,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09, +/*0031c0*/ 0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*0031d0*/ 0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f, +/*0031e0*/ 0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6d,0x64, +/*0031f0*/ 0x5f,0x68,0x65,0x6c,0x70,0x28,0x29,0x0d,0x0a,0x09,0x64,0x62,0x67,0x2e,0x77,0x72, +/*003200*/ 0x69,0x74,0x65,0x28,0x22,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*003210*/ 0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x3c,0x72,0x65,0x74,0x75, +/*003220*/ 0x72,0x6e,0x3e,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45, +/*003230*/ 0x54,0x2e,0x2e,0x22,0x72,0x65,0x2d,0x72,0x75,0x6e,0x20,0x6c,0x61,0x73,0x74,0x20, +/*003240*/ 0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e, +/*003250*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x63, +/*003260*/ 0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e, +/*003270*/ 0x2e,0x22,0x28,0x6f,0x6e,0x74,0x69,0x6e,0x75,0x65,0x29,0x22,0x2e,0x2e,0x47,0x52, +/*003280*/ 0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x63,0x6f,0x6e,0x74, +/*003290*/ 0x69,0x6e,0x75,0x65,0x20,0x65,0x78,0x65,0x63,0x75,0x74,0x69,0x6f,0x6e,0x5c,0x6e, +/*0032a0*/ 0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55, +/*0032b0*/ 0x45,0x2e,0x2e,0x22,0x20,0x20,0x73,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*0032c0*/ 0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x74,0x65,0x70,0x29,0x22,0x2e, +/*0032d0*/ 0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x73, +/*0032e0*/ 0x74,0x65,0x70,0x20,0x66,0x6f,0x72,0x77,0x61,0x72,0x64,0x20,0x62,0x79,0x20,0x6f, +/*0032f0*/ 0x6e,0x65,0x20,0x6c,0x69,0x6e,0x65,0x20,0x28,0x69,0x6e,0x74,0x6f,0x20,0x66,0x75, +/*003300*/ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x29,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e, +/*003310*/ 0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20, +/*003320*/ 0x6e,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57, +/*003330*/ 0x2e,0x2e,0x22,0x28,0x65,0x78,0x74,0x29,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e, +/*003340*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x73,0x74,0x65,0x70,0x20,0x66,0x6f, +/*003350*/ 0x72,0x77,0x61,0x72,0x64,0x20,0x62,0x79,0x20,0x6f,0x6e,0x65,0x20,0x6c,0x69,0x6e, +/*003360*/ 0x65,0x20,0x28,0x73,0x6b,0x69,0x70,0x70,0x69,0x6e,0x67,0x20,0x6f,0x76,0x65,0x72, +/*003370*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73,0x29,0x5c,0x6e,0x22,0x0d,0x0a, +/*003380*/ 0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e, +/*003390*/ 0x22,0x20,0x20,0x66,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*0033a0*/ 0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x69,0x6e,0x69,0x73,0x68,0x29,0x22,0x2e,0x2e, +/*0033b0*/ 0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x73,0x74, +/*0033c0*/ 0x65,0x70,0x20,0x66,0x6f,0x72,0x77,0x61,0x72,0x64,0x20,0x75,0x6e,0x74,0x69,0x6c, +/*0033d0*/ 0x20,0x65,0x78,0x69,0x74,0x69,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72, +/*0033e0*/ 0x72,0x65,0x6e,0x74,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x5c,0x6e,0x22, +/*0033f0*/ 0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45, +/*003400*/ 0x2e,0x2e,0x22,0x20,0x20,0x75,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59, +/*003410*/ 0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x70,0x29,0x22,0x2e,0x2e,0x47,0x52, +/*003420*/ 0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x6d,0x6f,0x76,0x65, +/*003430*/ 0x20,0x75,0x70,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x62,0x79, +/*003440*/ 0x20,0x6f,0x6e,0x65,0x20,0x66,0x72,0x61,0x6d,0x65,0x5c,0x6e,0x22,0x0d,0x0a,0x09, +/*003450*/ 0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22, +/*003460*/ 0x20,0x20,0x64,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c, +/*003470*/ 0x4f,0x57,0x2e,0x2e,0x22,0x28,0x6f,0x77,0x6e,0x29,0x22,0x2e,0x2e,0x47,0x52,0x45, +/*003480*/ 0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x6d,0x6f,0x76,0x65,0x20, +/*003490*/ 0x64,0x6f,0x77,0x6e,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x63,0x6b,0x20,0x62, +/*0034a0*/ 0x79,0x20,0x6f,0x6e,0x65,0x20,0x66,0x72,0x61,0x6d,0x65,0x5c,0x6e,0x22,0x0d,0x0a, +/*0034b0*/ 0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e, +/*0034c0*/ 0x22,0x20,0x20,0x77,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*0034d0*/ 0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x68,0x65,0x72,0x65,0x29,0x20,0x22,0x2e,0x2e, +/*0034e0*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x5b,0x6c,0x69, +/*0034f0*/ 0x6e,0x65,0x20,0x63,0x6f,0x75,0x6e,0x74,0x5d,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45, +/*003500*/ 0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x70,0x72,0x69,0x6e,0x74,0x20, +/*003510*/ 0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x63,0x6f,0x64,0x65,0x20,0x61,0x72,0x6f,0x75, +/*003520*/ 0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x63,0x75,0x72,0x72,0x65,0x6e,0x74,0x20,0x6c, +/*003530*/ 0x69,0x6e,0x65,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*003540*/ 0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x65,0x22,0x2e,0x2e,0x43, +/*003550*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x76, +/*003560*/ 0x61,0x6c,0x29,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55, +/*003570*/ 0x45,0x2e,0x2e,0x22,0x5b,0x73,0x74,0x61,0x74,0x65,0x6d,0x65,0x6e,0x74,0x5d,0x22, +/*003580*/ 0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22, +/*003590*/ 0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x74, +/*0035a0*/ 0x65,0x6d,0x65,0x6e,0x74,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f, +/*0035b0*/ 0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x70,0x22,0x2e, +/*0035c0*/ 0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22, +/*0035d0*/ 0x28,0x72,0x69,0x6e,0x74,0x29,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*0035e0*/ 0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x5b,0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69, +/*0035f0*/ 0x6f,0x6e,0x5d,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45, +/*003600*/ 0x54,0x2e,0x2e,0x22,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x20,0x74,0x68,0x65,0x20, +/*003610*/ 0x65,0x78,0x70,0x72,0x65,0x73,0x73,0x69,0x6f,0x6e,0x20,0x61,0x6e,0x64,0x20,0x70, +/*003620*/ 0x72,0x69,0x6e,0x74,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x73,0x75,0x6c,0x74,0x5c, +/*003630*/ 0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c, +/*003640*/ 0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x74,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*003650*/ 0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x72,0x61,0x63,0x65,0x29, +/*003660*/ 0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e, +/*003670*/ 0x22,0x70,0x72,0x69,0x6e,0x74,0x20,0x74,0x68,0x65,0x20,0x73,0x74,0x61,0x63,0x6b, +/*003680*/ 0x20,0x74,0x72,0x61,0x63,0x65,0x5c,0x6e,0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43, +/*003690*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e,0x22,0x20,0x20,0x6c,0x22, +/*0036a0*/ 0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e, +/*0036b0*/ 0x22,0x28,0x6f,0x63,0x61,0x6c,0x73,0x29,0x22,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e, +/*0036c0*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x70,0x72,0x69,0x6e,0x74,0x20,0x74, +/*0036d0*/ 0x68,0x65,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x61,0x72,0x67,0x75, +/*0036e0*/ 0x6d,0x65,0x6e,0x74,0x73,0x2c,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x73,0x20,0x61,0x6e, +/*0036f0*/ 0x64,0x20,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x73,0x2e,0x5c,0x6e,0x22,0x0d,0x0a, +/*003700*/ 0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x2e,0x2e, +/*003710*/ 0x22,0x20,0x20,0x68,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*003720*/ 0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x65,0x6c,0x70,0x29,0x22,0x2e,0x2e,0x47,0x52, +/*003730*/ 0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x70,0x72,0x69,0x6e, +/*003740*/ 0x74,0x20,0x74,0x68,0x69,0x73,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x5c,0x6e, +/*003750*/ 0x22,0x0d,0x0a,0x09,0x09,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55, +/*003760*/ 0x45,0x2e,0x2e,0x22,0x20,0x20,0x71,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*003770*/ 0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x28,0x75,0x69,0x74,0x29,0x22,0x2e, +/*003780*/ 0x2e,0x47,0x52,0x45,0x45,0x4e,0x5f,0x43,0x41,0x52,0x45,0x54,0x2e,0x2e,0x22,0x68, +/*003790*/ 0x61,0x6c,0x74,0x20,0x65,0x78,0x65,0x63,0x75,0x74,0x69,0x6f,0x6e,0x5c,0x6e,0x22, +/*0037a0*/ 0x0d,0x0a,0x09,0x29,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x61, +/*0037b0*/ 0x6c,0x73,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61, +/*0037c0*/ 0x6c,0x20,0x6c,0x61,0x73,0x74,0x5f,0x63,0x6d,0x64,0x20,0x3d,0x20,0x66,0x61,0x6c, +/*0037d0*/ 0x73,0x65,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x6f,0x6d,0x6d, +/*0037e0*/ 0x61,0x6e,0x64,0x73,0x20,0x3d,0x20,0x7b,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x63,0x24, +/*0037f0*/ 0x22,0x5d,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x20, +/*003800*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x20,0x65,0x6e,0x64,0x2c, +/*003810*/ 0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x73,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64, +/*003820*/ 0x5f,0x73,0x74,0x65,0x70,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x6e,0x24,0x22,0x5d, +/*003830*/ 0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x6e,0x65,0x78,0x74,0x2c,0x0d,0x0a,0x09,0x5b, +/*003840*/ 0x22,0x5e,0x66,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x66,0x69,0x6e, +/*003850*/ 0x69,0x73,0x68,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x70,0x25,0x73,0x2b,0x28,0x2e, +/*003860*/ 0x2a,0x29,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x70,0x72,0x69,0x6e, +/*003870*/ 0x74,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x65,0x25,0x73,0x2b,0x28,0x2e,0x2a,0x29, +/*003880*/ 0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x65,0x76,0x61,0x6c,0x2c,0x0d, +/*003890*/ 0x0a,0x09,0x5b,0x22,0x5e,0x75,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f, +/*0038a0*/ 0x75,0x70,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x64,0x24,0x22,0x5d,0x20,0x3d,0x20, +/*0038b0*/ 0x63,0x6d,0x64,0x5f,0x64,0x6f,0x77,0x6e,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x77, +/*0038c0*/ 0x25,0x73,0x2a,0x28,0x25,0x64,0x2a,0x29,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d, +/*0038d0*/ 0x64,0x5f,0x77,0x68,0x65,0x72,0x65,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x74,0x24, +/*0038e0*/ 0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x74,0x72,0x61,0x63,0x65,0x2c,0x0d, +/*0038f0*/ 0x0a,0x09,0x5b,0x22,0x5e,0x6c,0x24,0x22,0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f, +/*003900*/ 0x6c,0x6f,0x63,0x61,0x6c,0x73,0x2c,0x0d,0x0a,0x09,0x5b,0x22,0x5e,0x68,0x24,0x22, +/*003910*/ 0x5d,0x20,0x3d,0x20,0x63,0x6d,0x64,0x5f,0x68,0x65,0x6c,0x70,0x2c,0x0d,0x0a,0x09, +/*003920*/ 0x5b,0x22,0x5e,0x71,0x24,0x22,0x5d,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69, +/*003930*/ 0x6f,0x6e,0x28,0x29,0x20,0x64,0x62,0x67,0x2e,0x65,0x78,0x69,0x74,0x28,0x30,0x29, +/*003940*/ 0x3b,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x20,0x65,0x6e, +/*003950*/ 0x64,0x2c,0x0d,0x0a,0x7d,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66, +/*003960*/ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x6d,0x61,0x74,0x63,0x68,0x5f,0x63,0x6f, +/*003970*/ 0x6d,0x6d,0x61,0x6e,0x64,0x28,0x6c,0x69,0x6e,0x65,0x29,0x0d,0x0a,0x09,0x66,0x6f, +/*003980*/ 0x72,0x20,0x70,0x61,0x74,0x2c,0x20,0x66,0x75,0x6e,0x63,0x20,0x69,0x6e,0x20,0x70, +/*003990*/ 0x61,0x69,0x72,0x73,0x28,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x73,0x29,0x20,0x64, +/*0039a0*/ 0x6f,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x52,0x65,0x74,0x75,0x72,0x6e,0x20,0x74, +/*0039b0*/ 0x68,0x65,0x20,0x6d,0x61,0x74,0x63,0x68,0x69,0x6e,0x67,0x20,0x63,0x6f,0x6d,0x6d, +/*0039c0*/ 0x61,0x6e,0x64,0x20,0x61,0x6e,0x64,0x20,0x63,0x61,0x70,0x74,0x75,0x72,0x65,0x20, +/*0039d0*/ 0x61,0x72,0x67,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20, +/*0039e0*/ 0x6c,0x69,0x6e,0x65,0x3a,0x66,0x69,0x6e,0x64,0x28,0x70,0x61,0x74,0x29,0x20,0x74, +/*0039f0*/ 0x68,0x65,0x6e,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x75,0x6e,0x63,0x2c, +/*003a00*/ 0x20,0x6c,0x69,0x6e,0x65,0x3a,0x6d,0x61,0x74,0x63,0x68,0x28,0x70,0x61,0x74,0x29, +/*003a10*/ 0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*003a20*/ 0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x52,0x75,0x6e,0x20,0x61,0x20,0x63,0x6f,0x6d,0x6d, +/*003a30*/ 0x61,0x6e,0x64,0x20,0x6c,0x69,0x6e,0x65,0x0d,0x0a,0x2d,0x2d,0x20,0x52,0x65,0x74, +/*003a40*/ 0x75,0x72,0x6e,0x73,0x20,0x74,0x72,0x75,0x65,0x20,0x69,0x66,0x20,0x74,0x68,0x65, +/*003a50*/ 0x20,0x52,0x45,0x50,0x4c,0x20,0x73,0x68,0x6f,0x75,0x6c,0x64,0x20,0x65,0x78,0x69, +/*003a60*/ 0x74,0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x68,0x6f,0x6f,0x6b,0x20,0x66, +/*003a70*/ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x66,0x61,0x63,0x74,0x6f,0x72,0x79,0x0d, +/*003a80*/ 0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*003a90*/ 0x72,0x75,0x6e,0x5f,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x28,0x6c,0x69,0x6e,0x65, +/*003aa0*/ 0x29,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x47,0x44,0x42,0x2f,0x4c,0x4c,0x44,0x42,0x20, +/*003ab0*/ 0x65,0x78,0x69,0x74,0x20,0x6f,0x6e,0x20,0x63,0x74,0x72,0x6c,0x2d,0x64,0x0d,0x0a, +/*003ac0*/ 0x09,0x69,0x66,0x20,0x6c,0x69,0x6e,0x65,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20, +/*003ad0*/ 0x74,0x68,0x65,0x6e,0x20,0x64,0x62,0x67,0x2e,0x65,0x78,0x69,0x74,0x28,0x31,0x29, +/*003ae0*/ 0x3b,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x74,0x72,0x75,0x65,0x20,0x65,0x6e, +/*003af0*/ 0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x52,0x65,0x2d,0x65,0x78,0x65, +/*003b00*/ 0x63,0x75,0x74,0x65,0x20,0x74,0x68,0x65,0x20,0x6c,0x61,0x73,0x74,0x20,0x63,0x6f, +/*003b10*/ 0x6d,0x6d,0x61,0x6e,0x64,0x20,0x69,0x66,0x20,0x79,0x6f,0x75,0x20,0x70,0x72,0x65, +/*003b20*/ 0x73,0x73,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x2e,0x0d,0x0a,0x09,0x69,0x66,0x20, +/*003b30*/ 0x6c,0x69,0x6e,0x65,0x20,0x3d,0x3d,0x20,0x22,0x22,0x20,0x74,0x68,0x65,0x6e,0x20, +/*003b40*/ 0x6c,0x69,0x6e,0x65,0x20,0x3d,0x20,0x6c,0x61,0x73,0x74,0x5f,0x63,0x6d,0x64,0x20, +/*003b50*/ 0x6f,0x72,0x20,0x22,0x68,0x22,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09, +/*003b60*/ 0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x2c,0x20,0x63, +/*003b70*/ 0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x5f,0x61,0x72,0x67,0x20,0x3d,0x20,0x6d,0x61,0x74, +/*003b80*/ 0x63,0x68,0x5f,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x28,0x6c,0x69,0x6e,0x65,0x29, +/*003b90*/ 0x0d,0x0a,0x09,0x69,0x66,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x74,0x68, +/*003ba0*/ 0x65,0x6e,0x0d,0x0a,0x09,0x09,0x6c,0x61,0x73,0x74,0x5f,0x63,0x6d,0x64,0x20,0x3d, +/*003bb0*/ 0x20,0x6c,0x69,0x6e,0x65,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x75,0x6e,0x70,0x61, +/*003bc0*/ 0x63,0x6b,0x28,0x7b,0x2e,0x2e,0x2e,0x7d,0x29,0x20,0x70,0x72,0x65,0x76,0x65,0x6e, +/*003bd0*/ 0x74,0x73,0x20,0x74,0x61,0x69,0x6c,0x20,0x63,0x61,0x6c,0x6c,0x20,0x65,0x6c,0x69, +/*003be0*/ 0x6d,0x69,0x6e,0x61,0x74,0x69,0x6f,0x6e,0x20,0x73,0x6f,0x20,0x74,0x68,0x65,0x20, +/*003bf0*/ 0x73,0x74,0x61,0x63,0x6b,0x20,0x66,0x72,0x61,0x6d,0x65,0x20,0x69,0x6e,0x64,0x69, +/*003c00*/ 0x63,0x65,0x73,0x20,0x61,0x72,0x65,0x20,0x70,0x72,0x65,0x64,0x69,0x63,0x74,0x61, +/*003c10*/ 0x62,0x6c,0x65,0x2e,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x75, +/*003c20*/ 0x6e,0x70,0x61,0x63,0x6b,0x28,0x7b,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x28,0x63, +/*003c30*/ 0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x5f,0x61,0x72,0x67,0x29,0x7d,0x29,0x0d,0x0a,0x09, +/*003c40*/ 0x65,0x6c,0x73,0x65,0x69,0x66,0x20,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f, +/*003c50*/ 0x65,0x76,0x61,0x6c,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74, +/*003c60*/ 0x75,0x72,0x6e,0x20,0x75,0x6e,0x70,0x61,0x63,0x6b,0x28,0x7b,0x63,0x6d,0x64,0x5f, +/*003c70*/ 0x65,0x76,0x61,0x6c,0x28,0x6c,0x69,0x6e,0x65,0x29,0x7d,0x29,0x0d,0x0a,0x09,0x65, +/*003c80*/ 0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65, +/*003c90*/ 0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45, +/*003ca0*/ 0x72,0x72,0x6f,0x72,0x3a,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*003cb0*/ 0x53,0x45,0x54,0x2e,0x2e,0x22,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x27, +/*003cc0*/ 0x25,0x73,0x27,0x20,0x6e,0x6f,0x74,0x20,0x72,0x65,0x63,0x6f,0x67,0x6e,0x69,0x7a, +/*003cd0*/ 0x65,0x64,0x2e,0x5c,0x6e,0x54,0x79,0x70,0x65,0x20,0x27,0x68,0x27,0x20,0x61,0x6e, +/*003ce0*/ 0x64,0x20,0x70,0x72,0x65,0x73,0x73,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66, +/*003cf0*/ 0x6f,0x72,0x20,0x61,0x20,0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x6c,0x69,0x73, +/*003d00*/ 0x74,0x2e,0x22,0x2c,0x20,0x6c,0x69,0x6e,0x65,0x29,0x0d,0x0a,0x09,0x09,0x72,0x65, +/*003d10*/ 0x74,0x75,0x72,0x6e,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x65,0x6e,0x64, +/*003d20*/ 0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x72,0x65,0x70,0x6c,0x20,0x3d,0x20, +/*003d30*/ 0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x72,0x65,0x61,0x73,0x6f,0x6e,0x29, +/*003d40*/ 0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x53,0x6b,0x69,0x70,0x20,0x66,0x72,0x61,0x6d,0x65, +/*003d50*/ 0x73,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0x20,0x73,0x6f,0x75,0x72,0x63,0x65, +/*003d60*/ 0x20,0x69,0x6e,0x66,0x6f,0x2e,0x0d,0x0a,0x09,0x77,0x68,0x69,0x6c,0x65,0x20,0x6e, +/*003d70*/ 0x6f,0x74,0x20,0x66,0x72,0x61,0x6d,0x65,0x5f,0x68,0x61,0x73,0x5f,0x6c,0x69,0x6e, +/*003d80*/ 0x65,0x28,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28, +/*003d90*/ 0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66, +/*003da0*/ 0x66,0x73,0x65,0x74,0x20,0x2b,0x20,0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b, +/*003db0*/ 0x5f,0x4c,0x45,0x56,0x45,0x4c,0x20,0x2d,0x20,0x33,0x29,0x29,0x20,0x64,0x6f,0x0d, +/*003dc0*/ 0x0a,0x09,0x09,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69,0x6e,0x73,0x70,0x65,0x63,0x74, +/*003dd0*/ 0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d,0x20,0x73,0x74,0x61,0x63,0x6b,0x5f, +/*003de0*/ 0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b, +/*003df0*/ 0x20,0x31,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x6c,0x6f, +/*003e00*/ 0x63,0x61,0x6c,0x20,0x69,0x6e,0x66,0x6f,0x20,0x3d,0x20,0x64,0x65,0x62,0x75,0x67, +/*003e10*/ 0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x73,0x74,0x61,0x63,0x6b,0x5f,0x69, +/*003e20*/ 0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x2b,0x20, +/*003e30*/ 0x43,0x4d,0x44,0x5f,0x53,0x54,0x41,0x43,0x4b,0x5f,0x4c,0x45,0x56,0x45,0x4c,0x20, +/*003e40*/ 0x2d,0x20,0x33,0x29,0x0d,0x0a,0x09,0x72,0x65,0x61,0x73,0x6f,0x6e,0x20,0x3d,0x20, +/*003e50*/ 0x72,0x65,0x61,0x73,0x6f,0x6e,0x20,0x61,0x6e,0x64,0x20,0x28,0x43,0x4f,0x4c,0x4f, +/*003e60*/ 0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x62,0x72,0x65,0x61,0x6b, +/*003e70*/ 0x20,0x76,0x69,0x61,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*003e80*/ 0x44,0x2e,0x2e,0x72,0x65,0x61,0x73,0x6f,0x6e,0x2e,0x2e,0x47,0x52,0x45,0x45,0x4e, +/*003e90*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x29,0x20,0x6f,0x72,0x20,0x22,0x22,0x0d,0x0a,0x09, +/*003ea0*/ 0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x72,0x65,0x61,0x73, +/*003eb0*/ 0x6f,0x6e,0x2e,0x2e,0x66,0x6f,0x72,0x6d,0x61,0x74,0x5f,0x73,0x74,0x61,0x63,0x6b, +/*003ec0*/ 0x5f,0x66,0x72,0x61,0x6d,0x65,0x5f,0x69,0x6e,0x66,0x6f,0x28,0x69,0x6e,0x66,0x6f, +/*003ed0*/ 0x29,0x29,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x69,0x66,0x20,0x74,0x6f,0x6e,0x75,0x6d, +/*003ee0*/ 0x62,0x65,0x72,0x28,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77,0x68,0x65, +/*003ef0*/ 0x72,0x65,0x29,0x20,0x74,0x68,0x65,0x6e,0x20,0x77,0x68,0x65,0x72,0x65,0x28,0x69, +/*003f00*/ 0x6e,0x66,0x6f,0x2c,0x20,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77,0x68, +/*003f10*/ 0x65,0x72,0x65,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65, +/*003f20*/ 0x70,0x65,0x61,0x74,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x75, +/*003f30*/ 0x63,0x63,0x65,0x73,0x73,0x2c,0x20,0x64,0x6f,0x6e,0x65,0x2c,0x20,0x68,0x6f,0x6f, +/*003f40*/ 0x6b,0x20,0x3d,0x20,0x70,0x63,0x61,0x6c,0x6c,0x28,0x72,0x75,0x6e,0x5f,0x63,0x6f, +/*003f50*/ 0x6d,0x6d,0x61,0x6e,0x64,0x2c,0x20,0x64,0x62,0x67,0x2e,0x72,0x65,0x61,0x64,0x28, +/*003f60*/ 0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75, +/*003f70*/ 0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x3e,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c, +/*003f80*/ 0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x29,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66, +/*003f90*/ 0x20,0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09, +/*003fa0*/ 0x09,0x09,0x64,0x65,0x62,0x75,0x67,0x2e,0x73,0x65,0x74,0x68,0x6f,0x6f,0x6b,0x28, +/*003fb0*/ 0x68,0x6f,0x6f,0x6b,0x20,0x61,0x6e,0x64,0x20,0x68,0x6f,0x6f,0x6b,0x28,0x30,0x29, +/*003fc0*/ 0x2c,0x20,0x22,0x63,0x72,0x6c,0x22,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6c,0x73,0x65, +/*003fd0*/ 0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6d,0x65,0x73,0x73,0x61, +/*003fe0*/ 0x67,0x65,0x20,0x3d,0x20,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e, +/*003ff0*/ 0x22,0x49,0x4e,0x54,0x45,0x52,0x4e,0x41,0x4c,0x20,0x44,0x45,0x42,0x55,0x47,0x47, +/*004000*/ 0x45,0x52,0x2e,0x4c,0x55,0x41,0x20,0x45,0x52,0x52,0x4f,0x52,0x2e,0x20,0x41,0x42, +/*004010*/ 0x4f,0x52,0x54,0x49,0x4e,0x47,0x5c,0x6e,0x3a,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*004020*/ 0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x20,0x22,0x2e,0x2e,0x64,0x6f, +/*004030*/ 0x6e,0x65,0x0d,0x0a,0x09,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65, +/*004040*/ 0x6c,0x6e,0x28,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*004050*/ 0x65,0x72,0x72,0x6f,0x72,0x28,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a, +/*004060*/ 0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x75,0x6e,0x74,0x69,0x6c,0x20,0x64,0x6f, +/*004070*/ 0x6e,0x65,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x4d,0x61, +/*004080*/ 0x6b,0x65,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x20, +/*004090*/ 0x6f,0x62,0x6a,0x65,0x63,0x74,0x20,0x63,0x61,0x6c,0x6c,0x61,0x62,0x6c,0x65,0x20, +/*0040a0*/ 0x6c,0x69,0x6b,0x65,0x20,0x61,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x2e, +/*0040b0*/ 0x0d,0x0a,0x64,0x62,0x67,0x20,0x3d,0x20,0x73,0x65,0x74,0x6d,0x65,0x74,0x61,0x74, +/*0040c0*/ 0x61,0x62,0x6c,0x65,0x28,0x7b,0x7d,0x2c,0x20,0x7b,0x0d,0x0a,0x09,0x5f,0x5f,0x63, +/*0040d0*/ 0x61,0x6c,0x6c,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x5f, +/*0040e0*/ 0x2c,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x74,0x6f,0x70, +/*0040f0*/ 0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x2c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x29, +/*004100*/ 0x0d,0x0a,0x09,0x09,0x69,0x66,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e, +/*004110*/ 0x20,0x74,0x68,0x65,0x6e,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x65,0x6e,0x64, +/*004120*/ 0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x74,0x6f,0x70,0x5f,0x6f,0x66,0x66,0x73, +/*004130*/ 0x65,0x74,0x20,0x3d,0x20,0x28,0x74,0x6f,0x70,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74, +/*004140*/ 0x20,0x6f,0x72,0x20,0x30,0x29,0x0d,0x0a,0x09,0x09,0x73,0x74,0x61,0x63,0x6b,0x5f, +/*004150*/ 0x69,0x6e,0x73,0x70,0x65,0x63,0x74,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x20,0x3d, +/*004160*/ 0x20,0x74,0x6f,0x70,0x5f,0x6f,0x66,0x66,0x73,0x65,0x74,0x0d,0x0a,0x09,0x09,0x73, +/*004170*/ 0x74,0x61,0x63,0x6b,0x5f,0x74,0x6f,0x70,0x20,0x3d,0x20,0x74,0x6f,0x70,0x5f,0x6f, +/*004180*/ 0x66,0x66,0x73,0x65,0x74,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x64,0x65,0x62, +/*004190*/ 0x75,0x67,0x2e,0x73,0x65,0x74,0x68,0x6f,0x6f,0x6b,0x28,0x68,0x6f,0x6f,0x6b,0x5f, +/*0041a0*/ 0x6e,0x65,0x78,0x74,0x28,0x31,0x2c,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x6f, +/*0041b0*/ 0x72,0x20,0x22,0x64,0x62,0x67,0x28,0x29,0x22,0x29,0x2c,0x20,0x22,0x63,0x72,0x6c, +/*0041c0*/ 0x22,0x29,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x0d,0x0a,0x09,0x65, +/*0041d0*/ 0x6e,0x64,0x2c,0x0d,0x0a,0x7d,0x29,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x45,0x78, +/*0041e0*/ 0x70,0x6f,0x73,0x65,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75,0x67,0x67,0x65, +/*0041f0*/ 0x72,0x27,0x73,0x20,0x49,0x4f,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x73, +/*004200*/ 0x2e,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x72,0x65,0x61,0x64,0x20,0x3d,0x20,0x64,0x62, +/*004210*/ 0x67,0x5f,0x72,0x65,0x61,0x64,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x77,0x72,0x69,0x74, +/*004220*/ 0x65,0x20,0x3d,0x20,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x0d,0x0a,0x64, +/*004230*/ 0x62,0x67,0x2e,0x73,0x68,0x6f,0x72,0x74,0x65,0x6e,0x5f,0x70,0x61,0x74,0x68,0x20, +/*004240*/ 0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x28,0x70,0x61,0x74,0x68, +/*004250*/ 0x29,0x20,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x70,0x61,0x74,0x68,0x20,0x65,0x6e, +/*004260*/ 0x64,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x65,0x78,0x69,0x74,0x20,0x3d,0x20,0x66,0x75, +/*004270*/ 0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x65,0x72,0x72,0x29,0x20,0x6f,0x73,0x2e,0x65, +/*004280*/ 0x78,0x69,0x74,0x28,0x65,0x72,0x72,0x29,0x20,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a, +/*004290*/ 0x64,0x62,0x67,0x2e,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x20,0x3d,0x20,0x64,0x62, +/*0042a0*/ 0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x0d,0x0a,0x0d,0x0a,0x64,0x62,0x67, +/*0042b0*/ 0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x5f,0x64,0x65,0x70,0x74,0x68,0x20,0x3d,0x20, +/*0042c0*/ 0x33,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x20,0x3d,0x20, +/*0042d0*/ 0x70,0x72,0x65,0x74,0x74,0x79,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x70,0x70,0x20,0x3d, +/*0042e0*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x76,0x61,0x6c,0x75,0x65,0x2c, +/*0042f0*/ 0x20,0x64,0x65,0x70,0x74,0x68,0x29,0x20,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74, +/*004300*/ 0x65,0x6c,0x6e,0x28,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x28,0x76, +/*004310*/ 0x61,0x6c,0x75,0x65,0x2c,0x20,0x64,0x65,0x70,0x74,0x68,0x29,0x29,0x20,0x65,0x6e, +/*004320*/ 0x64,0x0d,0x0a,0x0d,0x0a,0x64,0x62,0x67,0x2e,0x61,0x75,0x74,0x6f,0x5f,0x77,0x68, +/*004330*/ 0x65,0x72,0x65,0x20,0x3d,0x20,0x66,0x61,0x6c,0x73,0x65,0x0d,0x0a,0x64,0x62,0x67, +/*004340*/ 0x2e,0x61,0x75,0x74,0x6f,0x5f,0x65,0x76,0x61,0x6c,0x20,0x3d,0x20,0x66,0x61,0x6c, +/*004350*/ 0x73,0x65,0x0d,0x0a,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x6c,0x75,0x61,0x5f, +/*004360*/ 0x65,0x72,0x72,0x6f,0x72,0x2c,0x20,0x6c,0x75,0x61,0x5f,0x61,0x73,0x73,0x65,0x72, +/*004370*/ 0x74,0x20,0x3d,0x20,0x65,0x72,0x72,0x6f,0x72,0x2c,0x20,0x61,0x73,0x73,0x65,0x72, +/*004380*/ 0x74,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x57,0x6f,0x72,0x6b,0x73,0x20,0x6c,0x69, +/*004390*/ 0x6b,0x65,0x20,0x65,0x72,0x72,0x6f,0x72,0x28,0x29,0x2c,0x20,0x62,0x75,0x74,0x20, +/*0043a0*/ 0x69,0x6e,0x76,0x6f,0x6b,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75, +/*0043b0*/ 0x67,0x67,0x65,0x72,0x2e,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20, +/*0043c0*/ 0x64,0x62,0x67,0x2e,0x65,0x72,0x72,0x6f,0x72,0x28,0x65,0x72,0x72,0x2c,0x20,0x6c, +/*0043d0*/ 0x65,0x76,0x65,0x6c,0x29,0x0d,0x0a,0x09,0x6c,0x65,0x76,0x65,0x6c,0x20,0x3d,0x20, +/*0043e0*/ 0x6c,0x65,0x76,0x65,0x6c,0x20,0x6f,0x72,0x20,0x31,0x0d,0x0a,0x09,0x64,0x62,0x67, +/*0043f0*/ 0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52, +/*004400*/ 0x45,0x44,0x2e,0x2e,0x22,0x45,0x52,0x52,0x4f,0x52,0x3a,0x20,0x22,0x2e,0x2e,0x43, +/*004410*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x64,0x62,0x67,0x2e, +/*004420*/ 0x70,0x72,0x65,0x74,0x74,0x79,0x28,0x65,0x72,0x72,0x29,0x29,0x0d,0x0a,0x09,0x64, +/*004430*/ 0x62,0x67,0x28,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x6c,0x65,0x76,0x65,0x6c,0x2c, +/*004440*/ 0x20,0x22,0x64,0x62,0x67,0x2e,0x65,0x72,0x72,0x6f,0x72,0x28,0x29,0x22,0x29,0x0d, +/*004450*/ 0x0a,0x09,0x0d,0x0a,0x09,0x6c,0x75,0x61,0x5f,0x65,0x72,0x72,0x6f,0x72,0x28,0x65, +/*004460*/ 0x72,0x72,0x2c,0x20,0x6c,0x65,0x76,0x65,0x6c,0x29,0x0d,0x0a,0x65,0x6e,0x64,0x0d, +/*004470*/ 0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x57,0x6f,0x72,0x6b,0x73,0x20,0x6c,0x69,0x6b,0x65, +/*004480*/ 0x20,0x61,0x73,0x73,0x65,0x72,0x74,0x28,0x29,0x2c,0x20,0x62,0x75,0x74,0x20,0x69, +/*004490*/ 0x6e,0x76,0x6f,0x6b,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x64,0x65,0x62,0x75,0x67, +/*0044a0*/ 0x67,0x65,0x72,0x20,0x6f,0x6e,0x20,0x61,0x20,0x66,0x61,0x69,0x6c,0x75,0x72,0x65, +/*0044b0*/ 0x2e,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x62,0x67,0x2e, +/*0044c0*/ 0x61,0x73,0x73,0x65,0x72,0x74,0x28,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e, +/*0044d0*/ 0x2c,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a,0x09,0x69,0x66,0x20, +/*0044e0*/ 0x6e,0x6f,0x74,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x20,0x74,0x68, +/*0044f0*/ 0x65,0x6e,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c, +/*004500*/ 0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x52, +/*004510*/ 0x52,0x4f,0x52,0x3a,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53, +/*004520*/ 0x45,0x54,0x2e,0x2e,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a,0x09,0x09, +/*004530*/ 0x64,0x62,0x67,0x28,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x31,0x2c,0x20,0x22,0x64, +/*004540*/ 0x62,0x67,0x2e,0x61,0x73,0x73,0x65,0x72,0x74,0x28,0x29,0x22,0x29,0x0d,0x0a,0x09, +/*004550*/ 0x65,0x6e,0x64,0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*004560*/ 0x6c,0x75,0x61,0x5f,0x61,0x73,0x73,0x65,0x72,0x74,0x28,0x63,0x6f,0x6e,0x64,0x69, +/*004570*/ 0x74,0x69,0x6f,0x6e,0x2c,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x29,0x0d,0x0a, +/*004580*/ 0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x57,0x6f,0x72,0x6b,0x73,0x20, +/*004590*/ 0x6c,0x69,0x6b,0x65,0x20,0x70,0x63,0x61,0x6c,0x6c,0x28,0x29,0x2c,0x20,0x62,0x75, +/*0045a0*/ 0x74,0x20,0x69,0x6e,0x76,0x6f,0x6b,0x65,0x73,0x20,0x74,0x68,0x65,0x20,0x64,0x65, +/*0045b0*/ 0x62,0x75,0x67,0x67,0x65,0x72,0x20,0x6f,0x6e,0x20,0x61,0x6e,0x20,0x65,0x72,0x72, +/*0045c0*/ 0x6f,0x72,0x2e,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x62, +/*0045d0*/ 0x67,0x2e,0x63,0x61,0x6c,0x6c,0x28,0x66,0x2c,0x20,0x2e,0x2e,0x2e,0x29,0x0d,0x0a, +/*0045e0*/ 0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x78,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66, +/*0045f0*/ 0x2c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x65,0x72,0x72,0x29,0x0d, +/*004600*/ 0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*004610*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x45,0x52,0x52,0x4f,0x52, +/*004620*/ 0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54, +/*004630*/ 0x2e,0x2e,0x64,0x62,0x67,0x2e,0x70,0x72,0x65,0x74,0x74,0x79,0x28,0x65,0x72,0x72, +/*004640*/ 0x29,0x29,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x28,0x66,0x61,0x6c,0x73,0x65,0x2c, +/*004650*/ 0x20,0x31,0x2c,0x20,0x22,0x64,0x62,0x67,0x2e,0x63,0x61,0x6c,0x6c,0x28,0x29,0x22, +/*004660*/ 0x29,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20, +/*004670*/ 0x65,0x72,0x72,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x2c,0x20,0x2e,0x2e,0x2e,0x29,0x0d, +/*004680*/ 0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x45,0x72,0x72,0x6f,0x72, +/*004690*/ 0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x20,0x68,0x61,0x6e,0x64,0x6c,0x65,0x72, +/*0046a0*/ 0x20,0x74,0x68,0x61,0x74,0x20,0x63,0x61,0x6e,0x20,0x62,0x65,0x20,0x75,0x73,0x65, +/*0046b0*/ 0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x6c,0x75,0x61,0x5f,0x70,0x63,0x61,0x6c,0x6c, +/*0046c0*/ 0x28,0x29,0x2e,0x0d,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x62, +/*0046d0*/ 0x67,0x2e,0x6d,0x73,0x67,0x68,0x28,0x2e,0x2e,0x2e,0x29,0x0d,0x0a,0x09,0x69,0x66, +/*0046e0*/ 0x20,0x64,0x65,0x62,0x75,0x67,0x2e,0x67,0x65,0x74,0x69,0x6e,0x66,0x6f,0x28,0x32, +/*0046f0*/ 0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72, +/*004700*/ 0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e, +/*004710*/ 0x2e,0x22,0x45,0x52,0x52,0x4f,0x52,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*004720*/ 0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x64,0x62,0x67,0x2e,0x70,0x72,0x65, +/*004730*/ 0x74,0x74,0x79,0x28,0x2e,0x2e,0x2e,0x29,0x29,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67, +/*004740*/ 0x28,0x66,0x61,0x6c,0x73,0x65,0x2c,0x20,0x31,0x2c,0x20,0x22,0x64,0x62,0x67,0x2e, +/*004750*/ 0x6d,0x73,0x67,0x68,0x28,0x29,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6c,0x73,0x65,0x0d, +/*004760*/ 0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*004770*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67, +/*004780*/ 0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f, +/*004790*/ 0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x45,0x72,0x72,0x6f,0x72,0x20, +/*0047a0*/ 0x64,0x69,0x64,0x20,0x6e,0x6f,0x74,0x20,0x6f,0x63,0x63,0x75,0x72,0x20,0x69,0x6e, +/*0047b0*/ 0x20,0x4c,0x75,0x61,0x20,0x63,0x6f,0x64,0x65,0x2e,0x20,0x45,0x78,0x65,0x63,0x75, +/*0047c0*/ 0x74,0x69,0x6f,0x6e,0x20,0x77,0x69,0x6c,0x6c,0x20,0x63,0x6f,0x6e,0x74,0x69,0x6e, +/*0047d0*/ 0x75,0x65,0x20,0x61,0x66,0x74,0x65,0x72,0x20,0x64,0x62,0x67,0x5f,0x70,0x63,0x61, +/*0047e0*/ 0x6c,0x6c,0x28,0x29,0x2e,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09, +/*0047f0*/ 0x0d,0x0a,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x2e,0x2e,0x2e,0x0d,0x0a,0x65, +/*004800*/ 0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x41,0x73,0x73,0x75,0x6d,0x65,0x20, +/*004810*/ 0x73,0x74,0x64,0x69,0x6e,0x2f,0x6f,0x75,0x74,0x20,0x61,0x72,0x65,0x20,0x54,0x54, +/*004820*/ 0x59,0x73,0x20,0x75,0x6e,0x6c,0x65,0x73,0x73,0x20,0x77,0x65,0x20,0x63,0x61,0x6e, +/*004830*/ 0x20,0x75,0x73,0x65,0x20,0x4c,0x75,0x61,0x4a,0x49,0x54,0x27,0x73,0x20,0x46,0x46, +/*004840*/ 0x49,0x20,0x74,0x6f,0x20,0x70,0x72,0x6f,0x70,0x65,0x72,0x6c,0x79,0x20,0x63,0x68, +/*004850*/ 0x65,0x63,0x6b,0x20,0x74,0x68,0x65,0x6d,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c, +/*004860*/ 0x20,0x73,0x74,0x64,0x69,0x6e,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x3d,0x20, +/*004870*/ 0x74,0x72,0x75,0x65,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x74,0x64,0x6f, +/*004880*/ 0x75,0x74,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x3d,0x20,0x74,0x72,0x75,0x65, +/*004890*/ 0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e, +/*0048a0*/ 0x61,0x6c,0x6c,0x79,0x20,0x65,0x6e,0x61,0x62,0x6c,0x65,0x20,0x74,0x68,0x65,0x20, +/*0048b0*/ 0x4c,0x75,0x61,0x4a,0x49,0x54,0x20,0x46,0x46,0x49,0x2e,0x0d,0x0a,0x6c,0x6f,0x63, +/*0048c0*/ 0x61,0x6c,0x20,0x66,0x66,0x69,0x20,0x3d,0x20,0x28,0x6a,0x69,0x74,0x20,0x61,0x6e, +/*0048d0*/ 0x64,0x20,0x72,0x65,0x71,0x75,0x69,0x72,0x65,0x28,0x22,0x66,0x66,0x69,0x22,0x29, +/*0048e0*/ 0x29,0x0d,0x0a,0x69,0x66,0x20,0x66,0x66,0x69,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a, +/*0048f0*/ 0x09,0x66,0x66,0x69,0x2e,0x63,0x64,0x65,0x66,0x5b,0x5b,0x0d,0x0a,0x09,0x09,0x69, +/*004900*/ 0x6e,0x74,0x20,0x69,0x73,0x61,0x74,0x74,0x79,0x28,0x69,0x6e,0x74,0x29,0x3b,0x20, +/*004910*/ 0x2f,0x2f,0x20,0x55,0x6e,0x69,0x78,0x0d,0x0a,0x09,0x09,0x69,0x6e,0x74,0x20,0x5f, +/*004920*/ 0x69,0x73,0x61,0x74,0x74,0x79,0x28,0x69,0x6e,0x74,0x29,0x3b,0x20,0x2f,0x2f,0x20, +/*004930*/ 0x57,0x69,0x6e,0x64,0x6f,0x77,0x73,0x0d,0x0a,0x09,0x09,0x76,0x6f,0x69,0x64,0x20, +/*004940*/ 0x66,0x72,0x65,0x65,0x28,0x76,0x6f,0x69,0x64,0x20,0x2a,0x70,0x74,0x72,0x29,0x3b, +/*004950*/ 0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x63,0x68,0x61,0x72,0x20,0x2a,0x72,0x65, +/*004960*/ 0x61,0x64,0x6c,0x69,0x6e,0x65,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x63,0x68,0x61, +/*004970*/ 0x72,0x20,0x2a,0x29,0x3b,0x0d,0x0a,0x09,0x09,0x69,0x6e,0x74,0x20,0x61,0x64,0x64, +/*004980*/ 0x5f,0x68,0x69,0x73,0x74,0x6f,0x72,0x79,0x28,0x63,0x6f,0x6e,0x73,0x74,0x20,0x63, +/*004990*/ 0x68,0x61,0x72,0x20,0x2a,0x29,0x3b,0x0d,0x0a,0x09,0x5d,0x5d,0x0d,0x0a,0x09,0x0d, +/*0049a0*/ 0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e, +/*0049b0*/ 0x20,0x67,0x65,0x74,0x5f,0x66,0x75,0x6e,0x63,0x5f,0x6f,0x72,0x5f,0x6e,0x69,0x6c, +/*0049c0*/ 0x28,0x73,0x79,0x6d,0x29,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73, +/*0049d0*/ 0x75,0x63,0x63,0x65,0x73,0x73,0x2c,0x20,0x66,0x75,0x6e,0x63,0x20,0x3d,0x20,0x70, +/*0049e0*/ 0x63,0x61,0x6c,0x6c,0x28,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x20, +/*0049f0*/ 0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x66,0x66,0x69,0x2e,0x43,0x5b,0x73,0x79,0x6d, +/*004a00*/ 0x5d,0x20,0x65,0x6e,0x64,0x29,0x0d,0x0a,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e, +/*004a10*/ 0x20,0x73,0x75,0x63,0x63,0x65,0x73,0x73,0x20,0x61,0x6e,0x64,0x20,0x66,0x75,0x6e, +/*004a20*/ 0x63,0x20,0x6f,0x72,0x20,0x6e,0x69,0x6c,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x0d,0x0a, +/*004a30*/ 0x09,0x0d,0x0a,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x69,0x73,0x61,0x74,0x74,0x79, +/*004a40*/ 0x20,0x3d,0x20,0x67,0x65,0x74,0x5f,0x66,0x75,0x6e,0x63,0x5f,0x6f,0x72,0x5f,0x6e, +/*004a50*/ 0x69,0x6c,0x28,0x22,0x69,0x73,0x61,0x74,0x74,0x79,0x22,0x29,0x20,0x6f,0x72,0x20, +/*004a60*/ 0x67,0x65,0x74,0x5f,0x66,0x75,0x6e,0x63,0x5f,0x6f,0x72,0x5f,0x6e,0x69,0x6c,0x28, +/*004a70*/ 0x22,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x22,0x29,0x20,0x6f,0x72,0x20,0x28,0x66, +/*004a80*/ 0x66,0x69,0x2e,0x6c,0x6f,0x61,0x64,0x28,0x22,0x75,0x63,0x72,0x74,0x62,0x61,0x73, +/*004a90*/ 0x65,0x22,0x29,0x29,0x5b,0x22,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x22,0x5d,0x0d, +/*004aa0*/ 0x0a,0x09,0x73,0x74,0x64,0x69,0x6e,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x3d, +/*004ab0*/ 0x20,0x69,0x73,0x61,0x74,0x74,0x79,0x28,0x30,0x29,0x0d,0x0a,0x09,0x73,0x74,0x64, +/*004ac0*/ 0x6f,0x75,0x74,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x3d,0x20,0x69,0x73,0x61, +/*004ad0*/ 0x74,0x74,0x79,0x28,0x31,0x29,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d, +/*004ae0*/ 0x2d,0x20,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x61,0x6c,0x6c,0x79,0x20, +/*004af0*/ 0x65,0x6e,0x61,0x62,0x6c,0x65,0x20,0x63,0x6f,0x6c,0x6f,0x72,0x20,0x73,0x75,0x70, +/*004b00*/ 0x70,0x6f,0x72,0x74,0x2e,0x0d,0x0a,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x63,0x6f,0x6c, +/*004b10*/ 0x6f,0x72,0x5f,0x6d,0x61,0x79,0x62,0x65,0x5f,0x73,0x75,0x70,0x70,0x6f,0x72,0x74, +/*004b20*/ 0x65,0x64,0x20,0x3d,0x20,0x28,0x73,0x74,0x64,0x6f,0x75,0x74,0x5f,0x69,0x73,0x61, +/*004b30*/ 0x74,0x74,0x79,0x20,0x61,0x6e,0x64,0x20,0x6f,0x73,0x2e,0x67,0x65,0x74,0x65,0x6e, +/*004b40*/ 0x76,0x28,0x22,0x54,0x45,0x52,0x4d,0x22,0x29,0x20,0x61,0x6e,0x64,0x20,0x6f,0x73, +/*004b50*/ 0x2e,0x67,0x65,0x74,0x65,0x6e,0x76,0x28,0x22,0x54,0x45,0x52,0x4d,0x22,0x29,0x20, +/*004b60*/ 0x7e,0x3d,0x20,0x22,0x64,0x75,0x6d,0x62,0x22,0x29,0x0d,0x0a,0x69,0x66,0x20,0x63, +/*004b70*/ 0x6f,0x6c,0x6f,0x72,0x5f,0x6d,0x61,0x79,0x62,0x65,0x5f,0x73,0x75,0x70,0x70,0x6f, +/*004b80*/ 0x72,0x74,0x65,0x64,0x20,0x61,0x6e,0x64,0x20,0x6e,0x6f,0x74,0x20,0x6f,0x73,0x2e, +/*004b90*/ 0x67,0x65,0x74,0x65,0x6e,0x76,0x28,0x22,0x44,0x42,0x47,0x5f,0x4e,0x4f,0x43,0x4f, +/*004ba0*/ 0x4c,0x4f,0x52,0x22,0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x43,0x4f,0x4c, +/*004bb0*/ 0x4f,0x52,0x5f,0x47,0x52,0x41,0x59,0x20,0x3d,0x20,0x73,0x74,0x72,0x69,0x6e,0x67, +/*004bc0*/ 0x2e,0x63,0x68,0x61,0x72,0x28,0x32,0x37,0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b,0x39, +/*004bd0*/ 0x30,0x6d,0x22,0x0d,0x0a,0x09,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x44,0x20, +/*004be0*/ 0x3d,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x63,0x68,0x61,0x72,0x28,0x32,0x37, +/*004bf0*/ 0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b,0x39,0x31,0x6d,0x22,0x0d,0x0a,0x09,0x43,0x4f, +/*004c00*/ 0x4c,0x4f,0x52,0x5f,0x42,0x4c,0x55,0x45,0x20,0x3d,0x20,0x73,0x74,0x72,0x69,0x6e, +/*004c10*/ 0x67,0x2e,0x63,0x68,0x61,0x72,0x28,0x32,0x37,0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b, +/*004c20*/ 0x39,0x34,0x6d,0x22,0x0d,0x0a,0x09,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c, +/*004c30*/ 0x4c,0x4f,0x57,0x20,0x3d,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x63,0x68,0x61, +/*004c40*/ 0x72,0x28,0x32,0x37,0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b,0x33,0x33,0x6d,0x22,0x0d, +/*004c50*/ 0x0a,0x09,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x20,0x3d,0x20, +/*004c60*/ 0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x63,0x68,0x61,0x72,0x28,0x32,0x37,0x29,0x20, +/*004c70*/ 0x2e,0x2e,0x20,0x22,0x5b,0x30,0x6d,0x22,0x0d,0x0a,0x09,0x47,0x52,0x45,0x45,0x4e, +/*004c80*/ 0x5f,0x43,0x41,0x52,0x45,0x54,0x20,0x3d,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e, +/*004c90*/ 0x63,0x68,0x61,0x72,0x28,0x32,0x37,0x29,0x20,0x2e,0x2e,0x20,0x22,0x5b,0x39,0x32, +/*004ca0*/ 0x6d,0x20,0x3d,0x3e,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*004cb0*/ 0x53,0x45,0x54,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x69,0x66,0x20,0x73, +/*004cc0*/ 0x74,0x64,0x69,0x6e,0x5f,0x69,0x73,0x61,0x74,0x74,0x79,0x20,0x61,0x6e,0x64,0x20, +/*004cd0*/ 0x6e,0x6f,0x74,0x20,0x6f,0x73,0x2e,0x67,0x65,0x74,0x65,0x6e,0x76,0x28,0x22,0x44, +/*004ce0*/ 0x42,0x47,0x5f,0x4e,0x4f,0x52,0x45,0x41,0x44,0x4c,0x49,0x4e,0x45,0x22,0x29,0x20, +/*004cf0*/ 0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66,0x75,0x6e, +/*004d00*/ 0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*004d10*/ 0x20,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x20,0x3d,0x20,0x72,0x65,0x71, +/*004d20*/ 0x75,0x69,0x72,0x65,0x20,0x27,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x27, +/*004d30*/ 0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x4c,0x6f,0x61,0x64,0x20, +/*004d40*/ 0x63,0x6f,0x6d,0x6d,0x61,0x6e,0x64,0x20,0x68,0x69,0x73,0x74,0x6f,0x72,0x79,0x20, +/*004d50*/ 0x66,0x72,0x6f,0x6d,0x20,0x7e,0x2f,0x2e,0x6c,0x75,0x61,0x5f,0x68,0x69,0x73,0x74, +/*004d60*/ 0x6f,0x72,0x79,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x68,0x69,0x73, +/*004d70*/ 0x74,0x5f,0x70,0x61,0x74,0x68,0x20,0x3d,0x20,0x6f,0x73,0x2e,0x67,0x65,0x74,0x65, +/*004d80*/ 0x6e,0x76,0x28,0x27,0x48,0x4f,0x4d,0x45,0x27,0x29,0x20,0x2e,0x2e,0x20,0x27,0x2f, +/*004d90*/ 0x2e,0x6c,0x75,0x61,0x5f,0x68,0x69,0x73,0x74,0x6f,0x72,0x79,0x27,0x0d,0x0a,0x09, +/*004da0*/ 0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x68,0x69,0x73,0x74,0x6f, +/*004db0*/ 0x72,0x79,0x6c,0x6f,0x61,0x64,0x28,0x68,0x69,0x73,0x74,0x5f,0x70,0x61,0x74,0x68, +/*004dc0*/ 0x29,0x0d,0x0a,0x09,0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x68, +/*004dd0*/ 0x69,0x73,0x74,0x6f,0x72,0x79,0x73,0x65,0x74,0x6d,0x61,0x78,0x6c,0x65,0x6e,0x28, +/*004de0*/ 0x35,0x30,0x29,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*004df0*/ 0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x61,0x75,0x74,0x6f,0x63,0x6f, +/*004e00*/ 0x6d,0x70,0x6c,0x65,0x74,0x65,0x28,0x65,0x6e,0x76,0x2c,0x20,0x69,0x6e,0x70,0x75, +/*004e10*/ 0x74,0x2c,0x20,0x6d,0x61,0x74,0x63,0x68,0x65,0x73,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*004e20*/ 0x66,0x6f,0x72,0x20,0x6e,0x61,0x6d,0x65,0x2c,0x20,0x5f,0x20,0x69,0x6e,0x20,0x70, +/*004e30*/ 0x61,0x69,0x72,0x73,0x28,0x65,0x6e,0x76,0x29,0x20,0x64,0x6f,0x0d,0x0a,0x09,0x09, +/*004e40*/ 0x09,0x09,0x69,0x66,0x20,0x6e,0x61,0x6d,0x65,0x3a,0x6d,0x61,0x74,0x63,0x68,0x28, +/*004e50*/ 0x27,0x5e,0x27,0x20,0x2e,0x2e,0x20,0x69,0x6e,0x70,0x75,0x74,0x20,0x2e,0x2e,0x20, +/*004e60*/ 0x27,0x2e,0x2a,0x27,0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x09, +/*004e70*/ 0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x61,0x64,0x64,0x63,0x6f, +/*004e80*/ 0x6d,0x70,0x6c,0x65,0x74,0x69,0x6f,0x6e,0x28,0x6d,0x61,0x74,0x63,0x68,0x65,0x73, +/*004e90*/ 0x2c,0x20,0x6e,0x61,0x6d,0x65,0x29,0x0d,0x0a,0x09,0x09,0x09,0x09,0x65,0x6e,0x64, +/*004ea0*/ 0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d, +/*004eb0*/ 0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x2d,0x2d,0x20,0x41,0x75,0x74,0x6f,0x2d,0x63, +/*004ec0*/ 0x6f,0x6d,0x70,0x6c,0x65,0x74,0x69,0x6f,0x6e,0x20,0x66,0x6f,0x72,0x20,0x6c,0x6f, +/*004ed0*/ 0x63,0x61,0x6c,0x73,0x20,0x61,0x6e,0x64,0x20,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x73, +/*004ee0*/ 0x0d,0x0a,0x09,0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x73,0x65, +/*004ef0*/ 0x74,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x74,0x69,0x6f,0x6e,0x28,0x66,0x75,0x6e,0x63, +/*004f00*/ 0x74,0x69,0x6f,0x6e,0x28,0x6d,0x61,0x74,0x63,0x68,0x65,0x73,0x2c,0x20,0x69,0x6e, +/*004f10*/ 0x70,0x75,0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d,0x20,0x46,0x69,0x72,0x73, +/*004f20*/ 0x74,0x2c,0x20,0x63,0x68,0x65,0x63,0x6b,0x20,0x74,0x68,0x65,0x20,0x6c,0x6f,0x63, +/*004f30*/ 0x61,0x6c,0x73,0x20,0x61,0x6e,0x64,0x20,0x75,0x70,0x76,0x61,0x6c,0x75,0x65,0x73, +/*004f40*/ 0x2e,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x65,0x6e,0x76,0x20, +/*004f50*/ 0x3d,0x20,0x6c,0x6f,0x63,0x61,0x6c,0x5f,0x62,0x69,0x6e,0x64,0x69,0x6e,0x67,0x73, +/*004f60*/ 0x28,0x31,0x2c,0x20,0x74,0x72,0x75,0x65,0x29,0x0d,0x0a,0x09,0x09,0x09,0x61,0x75, +/*004f70*/ 0x74,0x6f,0x63,0x6f,0x6d,0x70,0x6c,0x65,0x74,0x65,0x28,0x65,0x6e,0x76,0x2c,0x20, +/*004f80*/ 0x69,0x6e,0x70,0x75,0x74,0x2c,0x20,0x6d,0x61,0x74,0x63,0x68,0x65,0x73,0x29,0x0d, +/*004f90*/ 0x0a,0x09,0x09,0x09,0x0d,0x0a,0x09,0x09,0x09,0x2d,0x2d,0x20,0x54,0x68,0x65,0x6e, +/*004fa0*/ 0x2c,0x20,0x63,0x68,0x65,0x63,0x6b,0x20,0x74,0x68,0x65,0x20,0x69,0x6d,0x70,0x6c, +/*004fb0*/ 0x69,0x63,0x69,0x74,0x20,0x65,0x6e,0x76,0x69,0x72,0x6f,0x6e,0x6d,0x65,0x6e,0x74, +/*004fc0*/ 0x2e,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x76,0x20,0x3d,0x20,0x67,0x65,0x74,0x6d, +/*004fd0*/ 0x65,0x74,0x61,0x74,0x61,0x62,0x6c,0x65,0x28,0x65,0x6e,0x76,0x29,0x2e,0x5f,0x5f, +/*004fe0*/ 0x69,0x6e,0x64,0x65,0x78,0x0d,0x0a,0x09,0x09,0x09,0x61,0x75,0x74,0x6f,0x63,0x6f, +/*004ff0*/ 0x6d,0x70,0x6c,0x65,0x74,0x65,0x28,0x65,0x6e,0x76,0x2c,0x20,0x69,0x6e,0x70,0x75, +/*005000*/ 0x74,0x2c,0x20,0x6d,0x61,0x74,0x63,0x68,0x65,0x73,0x29,0x0d,0x0a,0x09,0x09,0x65, +/*005010*/ 0x6e,0x64,0x29,0x0d,0x0a,0x09,0x09,0x0d,0x0a,0x09,0x09,0x64,0x62,0x67,0x2e,0x72, +/*005020*/ 0x65,0x61,0x64,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x70, +/*005030*/ 0x72,0x6f,0x6d,0x70,0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c, +/*005040*/ 0x20,0x73,0x74,0x72,0x20,0x3d,0x20,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65, +/*005050*/ 0x2e,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x28,0x70,0x72,0x6f,0x6d,0x70, +/*005060*/ 0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x69,0x66,0x20,0x73,0x74,0x72,0x20,0x61,0x6e, +/*005070*/ 0x64,0x20,0x6e,0x6f,0x74,0x20,0x73,0x74,0x72,0x3a,0x6d,0x61,0x74,0x63,0x68,0x20, +/*005080*/ 0x22,0x5e,0x25,0x73,0x2a,0x24,0x22,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09, +/*005090*/ 0x09,0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x68,0x69,0x73,0x74, +/*0050a0*/ 0x6f,0x72,0x79,0x61,0x64,0x64,0x28,0x73,0x74,0x72,0x29,0x0d,0x0a,0x09,0x09,0x09, +/*0050b0*/ 0x09,0x6c,0x69,0x6e,0x65,0x6e,0x6f,0x69,0x73,0x65,0x2e,0x68,0x69,0x73,0x74,0x6f, +/*0050c0*/ 0x72,0x79,0x73,0x61,0x76,0x65,0x28,0x68,0x69,0x73,0x74,0x5f,0x70,0x61,0x74,0x68, +/*0050d0*/ 0x29,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x72,0x65, +/*0050e0*/ 0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x72,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d, +/*0050f0*/ 0x0a,0x09,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43, +/*005100*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65, +/*005110*/ 0x62,0x75,0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43, +/*005120*/ 0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x4c,0x69,0x6e, +/*005130*/ 0x65,0x6e,0x6f,0x69,0x73,0x65,0x20,0x73,0x75,0x70,0x70,0x6f,0x72,0x74,0x20,0x65, +/*005140*/ 0x6e,0x61,0x62,0x6c,0x65,0x64,0x2e,0x22,0x29,0x0d,0x0a,0x09,0x65,0x6e,0x64,0x29, +/*005150*/ 0x0d,0x0a,0x09,0x0d,0x0a,0x09,0x2d,0x2d,0x20,0x43,0x6f,0x6e,0x64,0x69,0x74,0x69, +/*005160*/ 0x6f,0x6e,0x61,0x6c,0x6c,0x79,0x20,0x65,0x6e,0x61,0x62,0x6c,0x65,0x20,0x4c,0x75, +/*005170*/ 0x61,0x4a,0x49,0x54,0x20,0x72,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x20,0x73,0x75, +/*005180*/ 0x70,0x70,0x6f,0x72,0x74,0x2e,0x0d,0x0a,0x09,0x70,0x63,0x61,0x6c,0x6c,0x28,0x66, +/*005190*/ 0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x29,0x0d,0x0a,0x09,0x09,0x69,0x66,0x20, +/*0051a0*/ 0x64,0x62,0x67,0x2e,0x72,0x65,0x61,0x64,0x20,0x3d,0x3d,0x20,0x6e,0x69,0x6c,0x20, +/*0051b0*/ 0x61,0x6e,0x64,0x20,0x66,0x66,0x69,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09, +/*0051c0*/ 0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x72,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x20, +/*0051d0*/ 0x3d,0x20,0x66,0x66,0x69,0x2e,0x6c,0x6f,0x61,0x64,0x28,0x22,0x72,0x65,0x61,0x64, +/*0051e0*/ 0x6c,0x69,0x6e,0x65,0x22,0x29,0x0d,0x0a,0x09,0x09,0x09,0x64,0x62,0x67,0x2e,0x72, +/*0051f0*/ 0x65,0x61,0x64,0x20,0x3d,0x20,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x28,0x70, +/*005200*/ 0x72,0x6f,0x6d,0x70,0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x09,0x6c,0x6f,0x63,0x61, +/*005210*/ 0x6c,0x20,0x63,0x73,0x74,0x72,0x20,0x3d,0x20,0x72,0x65,0x61,0x64,0x6c,0x69,0x6e, +/*005220*/ 0x65,0x2e,0x72,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x28,0x70,0x72,0x6f,0x6d,0x70, +/*005230*/ 0x74,0x29,0x0d,0x0a,0x09,0x09,0x09,0x09,0x69,0x66,0x20,0x63,0x73,0x74,0x72,0x20, +/*005240*/ 0x7e,0x3d,0x20,0x6e,0x69,0x6c,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09, +/*005250*/ 0x09,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x20,0x73,0x74,0x72,0x20,0x3d,0x20,0x66,0x66, +/*005260*/ 0x69,0x2e,0x73,0x74,0x72,0x69,0x6e,0x67,0x28,0x63,0x73,0x74,0x72,0x29,0x0d,0x0a, +/*005270*/ 0x09,0x09,0x09,0x09,0x09,0x69,0x66,0x20,0x73,0x74,0x72,0x69,0x6e,0x67,0x2e,0x6d, +/*005280*/ 0x61,0x74,0x63,0x68,0x28,0x73,0x74,0x72,0x2c,0x20,0x22,0x5b,0x5e,0x25,0x73,0x5d, +/*005290*/ 0x2b,0x22,0x29,0x20,0x74,0x68,0x65,0x6e,0x0d,0x0a,0x09,0x09,0x09,0x09,0x09,0x09, +/*0052a0*/ 0x72,0x65,0x61,0x64,0x6c,0x69,0x6e,0x65,0x2e,0x61,0x64,0x64,0x5f,0x68,0x69,0x73, +/*0052b0*/ 0x74,0x6f,0x72,0x79,0x28,0x63,0x73,0x74,0x72,0x29,0x0d,0x0a,0x09,0x09,0x09,0x09, +/*0052c0*/ 0x09,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x09,0x09,0x09,0x09,0x09,0x66,0x66,0x69, +/*0052d0*/ 0x2e,0x43,0x2e,0x66,0x72,0x65,0x65,0x28,0x63,0x73,0x74,0x72,0x29,0x0d,0x0a,0x09, +/*0052e0*/ 0x09,0x09,0x09,0x09,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x73,0x74,0x72,0x0d,0x0a, +/*0052f0*/ 0x09,0x09,0x09,0x09,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x09,0x09,0x09,0x09,0x72, +/*005300*/ 0x65,0x74,0x75,0x72,0x6e,0x20,0x6e,0x69,0x6c,0x0d,0x0a,0x09,0x09,0x09,0x09,0x65, +/*005310*/ 0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x09,0x09,0x64, +/*005320*/ 0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52, +/*005330*/ 0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67, +/*005340*/ 0x65,0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52, +/*005350*/ 0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x52,0x65,0x61,0x64,0x6c,0x69,0x6e, +/*005360*/ 0x65,0x20,0x73,0x75,0x70,0x70,0x6f,0x72,0x74,0x20,0x65,0x6e,0x61,0x62,0x6c,0x65, +/*005370*/ 0x64,0x2e,0x22,0x29,0x0d,0x0a,0x09,0x09,0x65,0x6e,0x64,0x0d,0x0a,0x09,0x65,0x6e, +/*005380*/ 0x64,0x29,0x0d,0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x2d,0x2d,0x20,0x44,0x65, +/*005390*/ 0x74,0x65,0x63,0x74,0x20,0x4c,0x75,0x61,0x20,0x76,0x65,0x72,0x73,0x69,0x6f,0x6e, +/*0053a0*/ 0x2e,0x0d,0x0a,0x69,0x66,0x20,0x6a,0x69,0x74,0x20,0x74,0x68,0x65,0x6e,0x20,0x2d, +/*0053b0*/ 0x2d,0x20,0x4c,0x75,0x61,0x4a,0x49,0x54,0x0d,0x0a,0x09,0x4c,0x55,0x41,0x5f,0x4a, +/*0053c0*/ 0x49,0x54,0x5f,0x53,0x45,0x54,0x4c,0x4f,0x43,0x41,0x4c,0x5f,0x57,0x4f,0x52,0x4b, +/*0053d0*/ 0x41,0x52,0x4f,0x55,0x4e,0x44,0x20,0x3d,0x20,0x2d,0x31,0x0d,0x0a,0x09,0x64,0x62, +/*0053e0*/ 0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*0053f0*/ 0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67,0x65, +/*005400*/ 0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f, +/*005410*/ 0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x4c,0x6f,0x61,0x64,0x65,0x64,0x20,0x66, +/*005420*/ 0x6f,0x72,0x20,0x22,0x2e,0x2e,0x6a,0x69,0x74,0x2e,0x76,0x65,0x72,0x73,0x69,0x6f, +/*005430*/ 0x6e,0x29,0x0d,0x0a,0x65,0x6c,0x73,0x65,0x69,0x66,0x20,0x22,0x4c,0x75,0x61,0x20, +/*005440*/ 0x35,0x2e,0x31,0x22,0x20,0x3c,0x3d,0x20,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e, +/*005450*/ 0x20,0x61,0x6e,0x64,0x20,0x5f,0x56,0x45,0x52,0x53,0x49,0x4f,0x4e,0x20,0x3c,0x3d, +/*005460*/ 0x20,0x22,0x4c,0x75,0x61,0x20,0x35,0x2e,0x34,0x22,0x20,0x74,0x68,0x65,0x6e,0x0d, +/*005470*/ 0x0a,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f, +/*005480*/ 0x4c,0x4f,0x52,0x5f,0x59,0x45,0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62, +/*005490*/ 0x75,0x67,0x67,0x65,0x72,0x2e,0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f, +/*0054a0*/ 0x4c,0x4f,0x52,0x5f,0x52,0x45,0x53,0x45,0x54,0x2e,0x2e,0x22,0x4c,0x6f,0x61,0x64, +/*0054b0*/ 0x65,0x64,0x20,0x66,0x6f,0x72,0x20,0x22,0x2e,0x2e,0x5f,0x56,0x45,0x52,0x53,0x49, +/*0054c0*/ 0x4f,0x4e,0x29,0x0d,0x0a,0x65,0x6c,0x73,0x65,0x0d,0x0a,0x09,0x64,0x62,0x67,0x5f, +/*0054d0*/ 0x77,0x72,0x69,0x74,0x65,0x6c,0x6e,0x28,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x59,0x45, +/*0054e0*/ 0x4c,0x4c,0x4f,0x57,0x2e,0x2e,0x22,0x64,0x65,0x62,0x75,0x67,0x67,0x65,0x72,0x2e, +/*0054f0*/ 0x6c,0x75,0x61,0x3a,0x20,0x22,0x2e,0x2e,0x43,0x4f,0x4c,0x4f,0x52,0x5f,0x52,0x45, +/*005500*/ 0x53,0x45,0x54,0x2e,0x2e,0x22,0x4e,0x6f,0x74,0x20,0x74,0x65,0x73,0x74,0x65,0x64, +/*005510*/ 0x20,0x61,0x67,0x61,0x69,0x6e,0x73,0x74,0x20,0x22,0x2e,0x2e,0x5f,0x56,0x45,0x52, +/*005520*/ 0x53,0x49,0x4f,0x4e,0x29,0x0d,0x0a,0x09,0x64,0x62,0x67,0x5f,0x77,0x72,0x69,0x74, +/*005530*/ 0x65,0x6c,0x6e,0x28,0x22,0x50,0x6c,0x65,0x61,0x73,0x65,0x20,0x73,0x65,0x6e,0x64, +/*005540*/ 0x20,0x6d,0x65,0x20,0x66,0x65,0x65,0x64,0x62,0x61,0x63,0x6b,0x21,0x22,0x29,0x0d, +/*005550*/ 0x0a,0x65,0x6e,0x64,0x0d,0x0a,0x0d,0x0a,0x72,0x65,0x74,0x75,0x72,0x6e,0x20,0x64, +/*005560*/ 0x62,0x67,0x0d,0x0a +}; + +const unsigned DEBUGGER_SRC_LEN = (unsigned)sizeof(DEBUGGER_SRC); + + +int luaopen_debugger(lua_State *lua){ + if( + luaL_loadbufferx(lua, DEBUGGER_SRC, DEBUGGER_SRC_LEN, "", NULL) || + lua_pcall(lua, 0, LUA_MULTRET, 0) + ) lua_error(lua); + + // Or you could load it from disk: + // if(luaL_dofile(lua, "debugger.lua")) lua_error(lua); + + return 1; +} + +static const char *MODULE_NAME = "DEBUGGER_LUA_MODULE"; +static const char *MSGH = "DEBUGGER_LUA_MSGH"; + +void dbg_setup(lua_State *lua, const char *name, const char *globalName, lua_CFunction readFunc, lua_CFunction writeFunc){ + // Check that the module name was not already defined. + lua_getfield(lua, LUA_REGISTRYINDEX, MODULE_NAME); + assert(lua_isnil(lua, -1) || strcmp(name, luaL_checkstring(lua, -1))); + lua_pop(lua, 1); + + // Push the module name into the registry. + lua_pushstring(lua, name); + lua_setfield(lua, LUA_REGISTRYINDEX, MODULE_NAME); + + // Preload the module + luaL_requiref(lua, name, luaopen_debugger, false); + + // Insert the msgh function into the registry. + lua_getfield(lua, -1, "msgh"); + lua_setfield(lua, LUA_REGISTRYINDEX, MSGH); + + if(readFunc){ + lua_pushcfunction(lua, readFunc); + lua_setfield(lua, -2, "read"); + } + + if(writeFunc){ + lua_pushcfunction(lua, writeFunc); + lua_setfield(lua, -2, "write"); + } + + if(globalName){ + lua_setglobal(lua, globalName); + } else { + lua_pop(lua, 1); + } +} + +void dbg_setup_default(lua_State *lua){ + dbg_setup(lua, "debugger", "dbg", NULL, NULL); +} + +int dbg_pcall(lua_State *lua, int nargs, int nresults, int msgh){ + // Call regular lua_pcall() if a message handler is provided. + if(msgh) return lua_pcall(lua, nargs, nresults, msgh); + + // Grab the msgh function out of the registry. + lua_getfield(lua, LUA_REGISTRYINDEX, MSGH); + if(lua_isnil(lua, -1)){ + luaL_error(lua, "Tried to call dbg_call() before calling dbg_setup()."); + } + + // Move the error handler just below the function. + msgh = lua_gettop(lua) - (1 + nargs); + lua_insert(lua, msgh); + + // Call the function. + int err = lua_pcall(lua, nargs, nresults, msgh); + + // Remove the debug handler. + lua_remove(lua, msgh); + + return err; +} +#line 0 +//#define SQLITE_OMIT_LOAD_EXTENSION +//#define SQLITE_CORE 1 +//#define SQLITE_DEBUG 1 +//#define Token SQToken +//#define Table SQTable +//#define rehash sqlite3__rehash +//#undef NB +//{ {FILE:3rd_sqlite3.c}} +//#undef Token +//#undef Table +//#undef rehash +//#undef NB +//#undef threadid #endif // V4K_3RD diff --git a/engine/v4k.c b/engine/v4k.c index e1a4198..871fc96 100644 --- a/engine/v4k.c +++ b/engine/v4k.c @@ -98,18 +98,6 @@ #include "v4k" #endif -#define do_threadlock(mutexptr) \ - for( int init_ = !!(mutexptr) || (thread_mutex_init( (mutexptr) = CALLOC(1, sizeof(thread_mutex_t)) ), 1); init_; init_ = 0) \ - for( int lock_ = (thread_mutex_lock( mutexptr ), 1); lock_; lock_ = (thread_mutex_unlock( mutexptr ), 0) ) - -API void *ui_handle(); -#define ui_push_hspace(px) \ - (int xx = px; xx; xx = 0) \ - for(struct nk_context *ctx = (struct nk_context*)ui_handle(); ctx; ctx = 0 ) \ - for(struct nk_panel *layout = ui_ctx->current->layout; layout; ) \ - for( xx = (layout->at_x += px, layout->bounds.w -= px, 0); layout; layout->at_x -= px, layout->bounds.w += px, layout = 0 ) - - //----------------------------------------------------------------------------- // C files @@ -528,7 +516,7 @@ char* tempvl(const char *fmt, va_list vl) { static __thread char buf[STACK_ALLOC]; #else int heap = 1; - static __thread int STACK_ALLOC = 128*1024; + static __thread int STACK_ALLOC = 512*1024; static __thread char *buf = 0; if(!buf) buf = REALLOC(0, STACK_ALLOC); // @leak #endif static __thread int cur = 0; //printf("string stack %d/%d\n", cur, STACK_ALLOC); @@ -3558,7 +3546,7 @@ int ui_browse(const char **output, bool *inlined) { // if(ui_ctx->current) bounds = nk_window_get_bounds(ui_ctx), P(bounds); // if(ui_ctx->current) bounds = nk_window_get_content_region(ui_ctx), P(bounds); // if(ui_ctx->current) nk_layout_peek(&bounds, ui_ctx), P(bounds); - // // if(ui_ctx->current) nk_layout_widget_space(&bounds, ui_ctx, ui_ctx->current, nk_false), P(bounds); // note: cant be used within a panel + // if(ui_ctx->current) nk_layout_widget_space(&bounds, ui_ctx, ui_ctx->current, nk_false), P(bounds); // note: cant be used within a panel // #undef P // panel @@ -6946,29 +6934,36 @@ bool data_tests() { #line 1 "engine/split/v4k_extend.c" // dll ------------------------------------------------------------------------ +/* deprecated #if is(win32) # include -# define dlopen(name,mode) (void*)( (name) ? LoadLibraryA(name) : GetModuleHandle(NULL)) -# define dlsym(handle,symbol) GetProcAddress((HMODULE)handle, symbol ) +# define dlopen(name,flags) (void*)( (name) ? LoadLibraryA(name) : GetModuleHandleA(NULL)) +# define dlsym(handle,symbol) GetProcAddress((HMODULE)(handle), symbol ) # define dlclose(handle) 0 #else # include +# define dlopen(name,flags) (void*)( (name) ? dlopen(name, flags) : NULL ) +# define dlsym(handle,symbol) dlsym( (handle) ? (handle) : ifdef(osx,RTLD_SELF,NULL), symbol ) #endif - -void* dll(const char *filename, const char *symbol) { -/* - char *buf, *base = file_name(filename); - if( file_exists(buf = va("%s", base)) || - file_exists(buf = va("%s.dll", base)) || - file_exists(buf = va("%s.so", base)) || - file_exists(buf = va("lib%s.so", base)) || - file_exists(buf = va("%s.dylib", base)) ) { - filename = buf; - } */ - void *dll = dlopen(filename, RTLD_NOW | RTLD_LOCAL); - dll = dll ? dlsym(dll, symbol) : 0; - return dll; + +void* dll(const char *fname, const char *symbol) { + if( fname && !file_exist(fname) ) { + char *buf, *path = file_path(fname), *base = file_base(fname); + if( file_exist(buf = va("%s%s.dll", path, base)) || + file_exist(buf = va("%s%s.so", path, base)) || + file_exist(buf = va("%slib%s.so", path, base)) || + file_exist(buf = va("%s%s.dylib", path, base)) ) { + fname = (const char *)buf; + } else { + return NULL; + } + } +#if is(win32) + return (void*)GetProcAddress(fname ? LoadLibraryA(fname) : GetModuleHandleA(NULL), symbol); +#else + return dlsym(fname ? dlopen(fname, RTLD_NOW|RTLD_LOCAL) : ifdef(osx, RTLD_SELF, NULL), symbol); +#endif } #if 0 // demo: cl demo.c /LD && REM dll @@ -7156,6 +7151,75 @@ bool script_tests() { } #undef XMACRO + +// script v2 ------------------------------------------------------------------ + +#define luaL_dostringsafe(L, str) \ + luaL_dostring(L, \ + "xpcall(function()\n" \ + str \ + "end, function(err)\n" \ + " print('Error: ' .. tostring(err))\n" \ + " print(debug.traceback(nil, 2))\n" \ + " if core and core.on_error then\n" \ + " pcall(core.on_error, err)\n" \ + " end\n" \ + " os.exit(1)\n" \ + "end)" \ + ); + +static int f_vfs_read(lua_State *L) { + char *file = file_normalize(luaL_checkstring(L, 1)); + if( strbegi(file, app_path()) ) file += strlen(app_path()); + strswap(file+1, ".", "/"); + strswap(file+1, "/lua", ".lua"); + int len; char *data = vfs_load(file, &len); + if( len ) { + data = memcpy(MALLOC(len+1), data, len), data[len] = 0; + //tty_color(data ? GREEN : RED); + //printf("%s (%s)\n%s", file, data ? "ok" : "failed", data); + //tty_color(0); + } + return lua_pushstring(L, data), 1; // "\n\tcannot find `%s` within mounted zipfiles", file), 1; +} + +// add our zip loader at the end of package.loaders +void lua_add_ziploader(lua_State* L) { + lua_pushcfunction( L, f_vfs_read ); + lua_setglobal( L, "vfs_read" ); + + luaL_dostringsafe(L, +// "package.path = [[;;<>;]]\n" // .. package.path\n" + "package.searchers[#package.searchers + 1] = function(libraryname)\n" + " for pattern in string.gmatch( package.path, '[^;]+' ) do\n" + " local proper_path = string.gsub(pattern, '?', libraryname)\n" + " local f = vfs_read(proper_path)\n" + " if f ~= nil then\n" + " return load(f, proper_path)\n" + " end\n" + " end\n" + " return nil\n" + "end\n" + ); +} + +void *script_init_env(unsigned flags) { + if( flags & SCRIPT_LUA ) { + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + + if( flags & SCRIPT_DEBUGGER ) { + // Register debuggers/inspectors + // luaL_dostringsafe(L, "I = require('inspect').inspect\n"); + dbg_setup_default(L); + } + + lua_add_ziploader(L); + return L; + } + + return 0; +} #line 0 #line 1 "engine/split/v4k_file.c" @@ -7322,7 +7386,7 @@ char *file_id(const char *pathfile) { char *ext = strchr(base, '.'); if (ext) ext[0] = '\0'; // remove all extensions #else // extensionless for audio/images only (materials: diffuse.tga and diffuse.png will match) char *ext = strrchr(base, '.'); //if (ext) ext[0] = '\0'; // remove all extensions - if(ext) if( strstr(".jpg.png.bmp.tga"".", ext) || strstr(".ogg.mp3.wav.mod.xm.flac"".", ext) || strstr(".mp4.ogv.avi.mkv.wmv.mpg.mpeg"".", ext) ) { + if(ext) if( strstr(".jpg.png.bmp.tga.hdr"".", ext) || strstr(".ogg.mp3.wav.mod.xm.flac"".", ext) || strstr(".mp4.ogv.avi.mkv.wmv.mpg.mpeg"".", ext) ) { ext = strchr(base, '.'); ext[0] = '\0'; //strcpy(ext, "_xxx"); } @@ -22306,646 +22370,6 @@ void scene_render(int flags) { } #line 0 -#line 1 "engine/split/v4k_time.c" -// ---------------------------------------------------------------------------- -// time - -#if 0 -uint64_t time_gpu() { - GLint64 t = 123456789; - glGetInteger64v(GL_TIMESTAMP, &t); - return (uint64_t)t; -} -#endif -uint64_t date() { - time_t epoch = time(0); - struct tm *ti = localtime(&epoch); - return atoi64(va("%04d%02d%02d%02d%02d%02d",ti->tm_year+1900,ti->tm_mon+1,ti->tm_mday,ti->tm_hour,ti->tm_min,ti->tm_sec)); -} -char *date_string() { - time_t epoch = time(0); - struct tm *ti = localtime(&epoch); - return va("%04d-%02d-%02d %02d:%02d:%02d",ti->tm_year+1900,ti->tm_mon+1,ti->tm_mday,ti->tm_hour,ti->tm_min,ti->tm_sec); -} -uint64_t date_epoch() { - time_t epoch = time(0); - return epoch; -} -#if 0 -double time_ss() { - return glfwGetTime(); -} -double time_ms() { - return glfwGetTime() * 1000.0; -} -uint64_t time_us() { - return (uint64_t)(glfwGetTime() * 1000000.0); // @fixme: use a high resolution timer instead, or time_gpu below -} -uint64_t sleep_us(uint64_t us) { // @fixme: use a high resolution sleeper instead - return sleep_ms( us / 1000.0 ); -} -double sleep_ms(double ms) { - double now = time_ms(); - if( ms <= 0 ) { -#if is(win32) - Sleep(0); // yield -#else - usleep(0); -#endif - } else { -#if is(win32) - Sleep(ms); -#else - usleep(ms * 1000); -#endif - } - return time_ms() - now; -} -double sleep_ss(double ss) { - return sleep_ms( ss * 1000 ) / 1000.0; -} -#endif - -// high-perf functions - -#define TIMER_E3 1000ULL -#define TIMER_E6 1000000ULL -#define TIMER_E9 1000000000ULL - -#ifdef CLOCK_MONOTONIC_RAW -#define TIME_MONOTONIC CLOCK_MONOTONIC_RAW -#elif defined CLOCK_MONOTONIC -#define TIME_MONOTONIC CLOCK_MONOTONIC -#else -// #define TIME_MONOTONIC CLOCK_REALTIME // untested -#endif - -static uint64_t nanotimer(uint64_t *out_freq) { - if( out_freq ) { -#if is(win32) - LARGE_INTEGER li; - QueryPerformanceFrequency(&li); - *out_freq = li.QuadPart; -//#elif is(ANDROID) -// *out_freq = CLOCKS_PER_SEC; -#elif defined TIME_MONOTONIC - *out_freq = TIMER_E9; -#else - *out_freq = TIMER_E6; -#endif - } -#if is(win32) - LARGE_INTEGER li; - QueryPerformanceCounter(&li); - return (uint64_t)li.QuadPart; -//#elif is(ANDROID) -// return (uint64_t)clock(); -#elif defined TIME_MONOTONIC - struct timespec ts; - clock_gettime(TIME_MONOTONIC, &ts); - return (TIMER_E9 * (uint64_t)ts.tv_sec) + ts.tv_nsec; -#else - struct timeval tv; - gettimeofday(&tv, NULL); - return (TIMER_E6 * (uint64_t)tv.tv_sec) + tv.tv_usec; -#endif -} - -uint64_t time_ns() { - static uint64_t epoch = 0; - static uint64_t freq = 0; - if( !freq ) { - epoch = nanotimer(&freq); - } - - uint64_t a = nanotimer(NULL) - epoch; - uint64_t b = TIMER_E9; - uint64_t c = freq; - - // Computes (a*b)/c without overflow, as long as both (a*b) and the overall result fit into 64-bits. - // [ref] https://github.com/rust-lang/rust/blob/3809bbf47c8557bd149b3e52ceb47434ca8378d5/src/libstd/sys_common/mod.rs#L124 - uint64_t q = a / c; - uint64_t r = a % c; - return q * b + r * b / c; -} -uint64_t time_us() { - return time_ns() / TIMER_E3; -} -uint64_t time_ms() { - return time_ns() / TIMER_E6; -} -double time_ss() { - return time_ns() / 1e9; // TIMER_E9; -} -double time_mm() { - return time_ss() / 60; -} -double time_hh() { - return time_mm() / 60; -} - -void sleep_ns( double ns ) { -#if is(win32) - if( ns >= 100 ) { - LARGE_INTEGER li; // Windows sleep in 100ns units - HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL); - li.QuadPart = (LONGLONG)(__int64)(-ns/100); // Negative for relative time - SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE); - WaitForSingleObject(timer, INFINITE); - CloseHandle(timer); -#else - if( ns > 0 ) { - struct timespec wait = {0}; - wait.tv_sec = ns / 1e9; - wait.tv_nsec = ns - wait.tv_sec * 1e9; - nanosleep(&wait, NULL); -#endif - } else { -#if is(win32) - Sleep(0); // yield, Sleep(0), SwitchToThread -#else - usleep(0); -#endif - } -} -void sleep_us( double us ) { - sleep_ns(us * 1e3); -} -void sleep_ms( double ms ) { - sleep_ns(ms * 1e6); -} -void sleep_ss( double ss ) { - sleep_ns(ss * 1e9); -} - -// ---------------------------------------------------------------------------- -// timer - -struct timer_internal_t { - unsigned ms; - unsigned (*callback)(unsigned interval, void *arg); - void *arg; - thread_ptr_t thd; -}; - -static int timer_func(void *arg) { - struct timer_internal_t *p = (struct timer_internal_t*)arg; - - sleep_ms( p->ms ); - - for( ;; ) { - unsigned then = time_ms(); - - p->ms = p->callback(p->ms, p->arg); - if( !p->ms ) break; - - unsigned now = time_ms(); - unsigned lapse = now - then; - int diff = p->ms - lapse; - sleep_ms( diff <= 0 ? 0 : diff ); - } - - thread_exit(0); - return 0; -} - -static __thread array(struct timer_internal_t *) timers; - -unsigned timer(unsigned ms, unsigned (*callback)(unsigned ms, void *arg), void *arg) { - struct timer_internal_t *p = MALLOC( sizeof(struct timer_internal_t) ); - p->ms = ms; - p->callback = callback; - p->arg = arg; - p->thd = thread_init( timer_func, p, "", 0 ); - - array_push(timers, p); - return array_count(timers); -} -void timer_destroy(unsigned i) { - if( i-- ) { - thread_join(timers[i]->thd); - thread_term(timers[i]->thd); - FREE(timers[i]); - timers[i] = 0; - } -} - -// ---------------------------------------------------------------------------- -// guid - -//typedef vec3i guid; - -guid guid_create() { - static __thread unsigned counter = 0; - static uint64_t appid = 0; do_once appid = hash_str(app_name()); - - union conv { - struct { - unsigned timestamp : 32; - unsigned threadid : 16; // inverted order in LE - unsigned appid : 16; // - unsigned counter : 32; - }; - vec3i v3; - } c; - c.timestamp = date_epoch() - 0x65000000; - c.appid = (unsigned)appid; - c.threadid = (unsigned)(uintptr_t)thread_current_thread_id(); - c.counter = ++counter; - - return c.v3; -} - -// ---------------------------------------------------------------------------- -// ease - -float ease_nop(float t) { return 0; } -float ease_linear(float t) { return t; } - -float ease_out_sine(float t) { return sinf(t*(C_PI*0.5f)); } -float ease_out_quad(float t) { return -(t*(t-2)); } -float ease_out_cubic(float t) { float f=t-1; return f*f*f+1; } -float ease_out_quart(float t) { float f=t-1; return f*f*f*(1-t)+1; } -float ease_out_quint(float t) { float f=(t-1); return f*f*f*f*f+1; } -float ease_out_expo(float t) { return (t >= 1) ? t : 1-powf(2,-10*t); } -float ease_out_circ(float t) { return sqrtf((2-t)*t); } -float ease_out_back(float t) { float f=1-t; return 1-(f*f*f-f*sinf(f*C_PI)); } -float ease_out_elastic(float t) { return sinf(-13*(C_PI*0.5f)*(t+1))*powf(2,-10*t)+1; } -float ease_out_bounce(float t) { return (t < 4.f/11) ? (121.f*t*t)/16 : (t < 8.f/11) ? (363.f/40*t*t)-(99.f/10*t)+17.f/5 : (t < 9.f/10) ? (4356.f/361*t*t)-(35442.f/1805*t)+16061.f/1805 : (54.f/5*t*t)-(513.f/25*t)+268.f/25; } - -float ease_in_sine(float t) { return 1+sinf((t-1)*(C_PI*0.5f)); } -float ease_in_quad(float t) { return t*t; } -float ease_in_cubic(float t) { return t*t*t; } -float ease_in_quart(float t) { return t*t*t*t; } -float ease_in_quint(float t) { return t*t*t*t*t; } -float ease_in_expo(float t) { return (t <= 0) ? t : powf(2,10*(t-1)); } -float ease_in_circ(float t) { return 1-sqrtf(1-(t*t)); } -float ease_in_back(float t) { return t*t*t-t*sinf(t*C_PI); } -float ease_in_elastic(float t) { return sinf(13*(C_PI*0.5f)*t)*powf(2,10*(t-1)); } -float ease_in_bounce(float t) { return 1-ease_out_bounce(1-t); } - -float ease_inout_sine(float t) { return 0.5f*(1-cosf(t*C_PI)); } -float ease_inout_quad(float t) { return (t < 0.5f) ? 2*t*t : (-2*t*t)+(4*t)-1; } -float ease_inout_cubic(float t) { float f; return (t < 0.5f) ? 4*t*t*t : (f=(2*t)-2,0.5f*f*f*f+1); } -float ease_inout_quart(float t) { float f; return (t < 0.5f) ? 8*t*t*t*t : (f=(t-1),-8*f*f*f*f+1); } -float ease_inout_quint(float t) { float f; return (t < 0.5f) ? 16*t*t*t*t*t : (f=((2*t)-2),0.5f*f*f*f*f*f+1); } -float ease_inout_expo(float t) { return (t <= 0 || t >= 1) ? t : t < 0.5f ? 0.5f*powf(2,(20*t)-10) : -0.5f*powf(2,(-20*t)+10)+1; } -float ease_inout_circ(float t) { return t < 0.5f ? 0.5f*(1-sqrtf(1-4*(t*t))) : 0.5f*(sqrtf(-((2*t)-3)*((2*t)-1))+1); } -float ease_inout_back(float t) { float f; return t < 0.5f ? (f=2*t,0.5f*(f*f*f-f*sinf(f*C_PI))) : (f=(1-(2*t-1)),0.5f*(1-(f*f*f-f*sinf(f*C_PI)))+0.5f); } -float ease_inout_elastic(float t) { return t < 0.5f ? 0.5f*sinf(13*(C_PI*0.5f)*(2*t))*powf(2,10*((2*t)-1)) : 0.5f*(sinf(-13*(C_PI*0.5f)*((2*t-1)+1))*powf(2,-10*(2*t-1))+2); } -float ease_inout_bounce(float t) { return t < 0.5f ? 0.5f*ease_in_bounce(t*2) : 0.5f*ease_out_bounce(t*2-1)+0.5f; } - -float ease_inout_perlin(float t) { float t3=t*t*t,t4=t3*t,t5=t4*t; return 6*t5-15*t4+10*t3; } - -float ease(float t01, unsigned mode) { - typedef float (*easing)(float); - easing modes[] = { - ease_out_sine, - ease_out_quad, - ease_out_cubic, - ease_out_quart, - ease_out_quint, - ease_out_expo, - ease_out_circ, - ease_out_back, - ease_out_elastic, - ease_out_bounce, - - ease_in_sine, - ease_in_quad, - ease_in_cubic, - ease_in_quart, - ease_in_quint, - ease_in_expo, - ease_in_circ, - ease_in_back, - ease_in_elastic, - ease_in_bounce, - - ease_inout_sine, - ease_inout_quad, - ease_inout_cubic, - ease_inout_quart, - ease_inout_quint, - ease_inout_expo, - ease_inout_circ, - ease_inout_back, - ease_inout_elastic, - ease_inout_bounce, - - ease_nop, - ease_linear, - ease_inout_perlin, - }; - return modes[clampi(mode, 0, countof(modes))](clampf(t01,0,1)); -} - -float ease_pong(float t, unsigned fn) { return 1 - ease(t, fn); } -float ease_ping_pong(float t, unsigned fn1, unsigned fn2) { return t < 0.5 ? ease(t*2,fn1) : ease(1-(t-0.5)*2,fn2); } -float ease_pong_ping(float t, unsigned fn1, unsigned fn2) { return 1 - ease_ping_pong(t,fn1,fn2); } - - -const char **ease_enums() { - static const char *list[] = { - "ease_out_sine", - "ease_out_quad", - "ease_out_cubic", - "ease_out_quart", - "ease_out_quint", - "ease_out_expo", - "ease_out_circ", - "ease_out_back", - "ease_out_elastic", - "ease_out_bounce", - - "ease_in_sine", - "ease_in_quad", - "ease_in_cubic", - "ease_in_quart", - "ease_in_quint", - "ease_in_expo", - "ease_in_circ", - "ease_in_back", - "ease_in_elastic", - "ease_in_bounce", - - "ease_inout_sine", - "ease_inout_quad", - "ease_inout_cubic", - "ease_inout_quart", - "ease_inout_quint", - "ease_inout_expo", - "ease_inout_circ", - "ease_inout_back", - "ease_inout_elastic", - "ease_inout_bounce", - - "ease_nop", - "ease_linear", - "ease_inout_perlin", - - 0 - }; - return list; -} - -const char *ease_enum(unsigned mode) { - return mode[ ease_enums() ]; -} - -/*AUTORUN { - ENUM(EASE_LINEAR|EASE_OUT); - ENUM(EASE_SINE|EASE_OUT); - ENUM(EASE_QUAD|EASE_OUT); - ENUM(EASE_CUBIC|EASE_OUT); - ENUM(EASE_QUART|EASE_OUT); - ENUM(EASE_QUINT|EASE_OUT); - ENUM(EASE_EXPO|EASE_OUT); - ENUM(EASE_CIRC|EASE_OUT); - ENUM(EASE_BACK|EASE_OUT); - ENUM(EASE_ELASTIC|EASE_OUT); - ENUM(EASE_BOUNCE|EASE_OUT); - - ENUM(EASE_SINE|EASE_IN); - ENUM(EASE_QUAD|EASE_IN); - ENUM(EASE_CUBIC|EASE_IN); - ENUM(EASE_QUART|EASE_IN); - ENUM(EASE_QUINT|EASE_IN); - ENUM(EASE_EXPO|EASE_IN); - ENUM(EASE_CIRC|EASE_IN); - ENUM(EASE_BACK|EASE_IN); - ENUM(EASE_ELASTIC|EASE_IN); - ENUM(EASE_BOUNCE|EASE_IN); - - ENUM(EASE_SINE|EASE_INOUT); - ENUM(EASE_QUAD|EASE_INOUT); - ENUM(EASE_CUBIC|EASE_INOUT); - ENUM(EASE_QUART|EASE_INOUT); - ENUM(EASE_QUINT|EASE_INOUT); - ENUM(EASE_EXPO|EASE_INOUT); - ENUM(EASE_CIRC|EASE_INOUT); - ENUM(EASE_BACK|EASE_INOUT); - ENUM(EASE_ELASTIC|EASE_INOUT); - ENUM(EASE_BOUNCE|EASE_INOUT); - - ENUM(EASE_NOP); - ENUM(EASE_LINEAR); - ENUM(EASE_INOUT_PERLIN); -};*/ - -// ---------------------------------------------------------------------------- -// tween - -tween_t tween() { - tween_t tw = {0}; - return tw; -} - -float tween_update(tween_t *tw, float dt) { - if( !array_count(tw->keyframes) ) return 0.0f; - - for( int i = 0, end = array_count(tw->keyframes) - 1; i < end; ++i ) { - tween_keyframe_t *kf1 = &tw->keyframes[i]; - tween_keyframe_t *kf2 = &tw->keyframes[i + 1]; - if (tw->time >= kf1->t && tw->time <= kf2->t) { - float localT = (tw->time - kf1->t) / (kf2->t - kf1->t); - float easedT = ease(localT, kf1->ease); - tw->result = mix3(kf1->v, kf2->v, easedT); - break; - } - } - - float done = (tw->time / tw->duration); - tw->time += dt; - return clampf(done, 0.0f, 1.0f); -} - -void tween_reset(tween_t *tw) { - tw->time = 0.0f; -} - -void tween_destroy(tween_t *tw) { - tween_t tw_ = {0}; - array_free(tw->keyframes); - *tw = tw_; -} - -static INLINE -int tween_comp_keyframes(const void *a, const void *b) { - float t1 = ((const tween_keyframe_t*)a)->t; - float t2 = ((const tween_keyframe_t*)b)->t; - return (t1 > t2) - (t1 < t2); -} - -void tween_setkey(tween_t *tw, float t, vec3 v, unsigned mode) { - tween_keyframe_t keyframe = { t, v, mode }; - array_push(tw->keyframes, keyframe); - array_sort(tw->keyframes, tween_comp_keyframes); - tw->duration = array_back(tw->keyframes)->t; -} - -void tween_delkey(tween_t *tw, float t) { // @todo: untested - for( int i = 0, end = array_count(tw->keyframes); i < end; i++ ) { - if( tw->keyframes[i].t == t ) { - array_erase_slow(tw->keyframes, i); - tw->duration = array_back(tw->keyframes)->t; - return; - } - } -} - -// ---------------------------------------------------------------------------- -// curve - -curve_t curve() { - curve_t c = {0}; - return c; -} - -static INLINE -vec3 catmull( vec3 p0, vec3 p1, vec3 p2, vec3 p3, float t ) { - float t2 = t*t; - float t3 = t*t*t; - - vec3 c; - c.x = 0.5 * ((2 * p1.x) + (-p0.x + p2.x) * t + (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 + (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3); - c.y = 0.5 * ((2 * p1.y) + (-p0.y + p2.y) * t + (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 + (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3); - c.z = 0.5 * ((2 * p1.z) + (-p0.z + p2.z) * t + (2 * p0.z - 5 * p1.z + 4 * p2.z - p3.z) * t2 + (-p0.z + 3 * p1.z - 3 * p2.z + p3.z) * t3); - return c; -} - -void curve_add(curve_t *c, vec3 p) { - array_push(c->points, p); -} - -void curve_finish( curve_t *c, int k ) { - assert( k > 0 ); - - array_free(c->lengths); - array_free(c->samples); - array_free(c->indices); - array_free(c->colors); - - // refit points[N] to samples[K] - int N = array_count(c->points); - if( k < N ) { - // truncate: expected k-points lesser or equal than existing N points - for( int i = 0; i <= k; ++i ) { - float s = (float)i / k; - int t = s * (N-1); - array_push(c->samples, c->points[t]); - - float p = fmod(i, N-1) / (N-1); // [0..1) - int is_control_point = p <= 0 || p >= 1; - array_push(c->colors, is_control_point ? ORANGE: BLUE); - } - - } else { - // interpolate: expected k-points greater than existing N-points - --N; - int upper = N - (k%N); - int lower = (k%N); - if(upper < lower) - k += upper; - else - k -= lower; - - int points_per_segment = (k / N); - ++N; - - int looped = len3sq(sub3(c->points[0], *array_back(c->points))) < 0.1; - - for( int i = 0; i <= k; ++i ) { - int point = i % points_per_segment; - float p = point / (float)points_per_segment; // [0..1) - int t = i / points_per_segment; - - // linear - vec3 l = mix3(c->points[t], c->points[t+(i!=k)], p); - - // printf("%d) %d>%d %f\n", i, t, t+(i!=k), p); - ASSERT(p <= 1); - - // catmull - int p0 = t - 1; - int p1 = t + 0; - int p2 = t + 1; - int p3 = t + 2; - if( looped ) - { - int M = N-1; - if(p0<0) p0+=M; else if(p0>=M) p0-=M; - if(p1<0) p1+=M; else if(p1>=M) p1-=M; - if(p2<0) p2+=M; else if(p2>=M) p2-=M; - if(p3<0) p3+=M; else if(p3>=M) p3-=M; - } - else - { - int M = N-1; - if(p0<0) p0=0; else if(p0>=M) p0=M; - if(p1<0) p1=0; else if(p1>=M) p1=M; - if(p2<0) p2=0; else if(p2>=M) p2=M; - if(p3<0) p3=0; else if(p3>=M) p3=M; - } - vec3 m = catmull(c->points[p0],c->points[p1],c->points[p2],c->points[p3],p); - l = m; - - array_push(c->samples, l); - - int is_control_point = p <= 0 || p >= 1; - array_push(c->colors, is_control_point ? ORANGE: BLUE); - } - } - - array_push(c->lengths, 0 ); - for( int i = 1; i <= k; ++i ) { - // approximate curve length at every sample point - array_push(c->lengths, len3(sub3(c->samples[i], c->samples[i-1])) + c->lengths[i-1] ); - } - // normalize lengths to be between 0 and 1 - float maxv = c->lengths[k]; - for( int i = 1; i <= k; ++i ) c->lengths[i] /= maxv; - - array_push(c->indices, 0 ); - for( int i = 0/*1*/; i indices) + 1; j lengths[j] lengths[j] > 0.01) - array_push(c->indices, j ); - } -} - -vec3 curve_eval(curve_t *c, float dt, unsigned *color) { - unsigned nil; if(!color) color = &nil; - dt = clampf(dt, 0.0f, 1.0f); - int l = (int)(array_count(c->indices) - 1); - int p = (int)(dt * l); - int t = c->indices[p]; - - t %= (array_count(c->indices)-1); - vec3 pos = mix3(c->samples[t], c->samples[t+1], dt * l - p); - *color = c->colors[t]; - - return pos; -} - -void curve_destroy(curve_t *c) { - array_free(c->lengths); - array_free(c->colors); - array_free(c->samples); - array_free(c->points); - array_free(c->indices); -} -#line 0 - #line 1 "engine/split/v4k_system.c" #if (is(tcc) && is(linux)) || (is(gcc) && !is(mingw)) // || is(clang) int __argc; char **__argv; @@ -23874,6 +23298,646 @@ int (test)(const char *file, int line, const char *expr, bool result) { } #line 0 +#line 1 "engine/split/v4k_time.c" +// ---------------------------------------------------------------------------- +// time + +#if 0 +uint64_t time_gpu() { + GLint64 t = 123456789; + glGetInteger64v(GL_TIMESTAMP, &t); + return (uint64_t)t; +} +#endif +uint64_t date() { + time_t epoch = time(0); + struct tm *ti = localtime(&epoch); + return atoi64(va("%04d%02d%02d%02d%02d%02d",ti->tm_year+1900,ti->tm_mon+1,ti->tm_mday,ti->tm_hour,ti->tm_min,ti->tm_sec)); +} +char *date_string() { + time_t epoch = time(0); + struct tm *ti = localtime(&epoch); + return va("%04d-%02d-%02d %02d:%02d:%02d",ti->tm_year+1900,ti->tm_mon+1,ti->tm_mday,ti->tm_hour,ti->tm_min,ti->tm_sec); +} +uint64_t date_epoch() { + time_t epoch = time(0); + return epoch; +} +#if 0 +double time_ss() { + return glfwGetTime(); +} +double time_ms() { + return glfwGetTime() * 1000.0; +} +uint64_t time_us() { + return (uint64_t)(glfwGetTime() * 1000000.0); // @fixme: use a high resolution timer instead, or time_gpu below +} +uint64_t sleep_us(uint64_t us) { // @fixme: use a high resolution sleeper instead + return sleep_ms( us / 1000.0 ); +} +double sleep_ms(double ms) { + double now = time_ms(); + if( ms <= 0 ) { +#if is(win32) + Sleep(0); // yield +#else + usleep(0); +#endif + } else { +#if is(win32) + Sleep(ms); +#else + usleep(ms * 1000); +#endif + } + return time_ms() - now; +} +double sleep_ss(double ss) { + return sleep_ms( ss * 1000 ) / 1000.0; +} +#endif + +// high-perf functions + +#define TIMER_E3 1000ULL +#define TIMER_E6 1000000ULL +#define TIMER_E9 1000000000ULL + +#ifdef CLOCK_MONOTONIC_RAW +#define TIME_MONOTONIC CLOCK_MONOTONIC_RAW +#elif defined CLOCK_MONOTONIC +#define TIME_MONOTONIC CLOCK_MONOTONIC +#else +// #define TIME_MONOTONIC CLOCK_REALTIME // untested +#endif + +static uint64_t nanotimer(uint64_t *out_freq) { + if( out_freq ) { +#if is(win32) + LARGE_INTEGER li; + QueryPerformanceFrequency(&li); + *out_freq = li.QuadPart; +//#elif is(ANDROID) +// *out_freq = CLOCKS_PER_SEC; +#elif defined TIME_MONOTONIC + *out_freq = TIMER_E9; +#else + *out_freq = TIMER_E6; +#endif + } +#if is(win32) + LARGE_INTEGER li; + QueryPerformanceCounter(&li); + return (uint64_t)li.QuadPart; +//#elif is(ANDROID) +// return (uint64_t)clock(); +#elif defined TIME_MONOTONIC + struct timespec ts; + clock_gettime(TIME_MONOTONIC, &ts); + return (TIMER_E9 * (uint64_t)ts.tv_sec) + ts.tv_nsec; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return (TIMER_E6 * (uint64_t)tv.tv_sec) + tv.tv_usec; +#endif +} + +uint64_t time_ns() { + static uint64_t epoch = 0; + static uint64_t freq = 0; + if( !freq ) { + epoch = nanotimer(&freq); + } + + uint64_t a = nanotimer(NULL) - epoch; + uint64_t b = TIMER_E9; + uint64_t c = freq; + + // Computes (a*b)/c without overflow, as long as both (a*b) and the overall result fit into 64-bits. + // [ref] https://github.com/rust-lang/rust/blob/3809bbf47c8557bd149b3e52ceb47434ca8378d5/src/libstd/sys_common/mod.rs#L124 + uint64_t q = a / c; + uint64_t r = a % c; + return q * b + r * b / c; +} +uint64_t time_us() { + return time_ns() / TIMER_E3; +} +uint64_t time_ms() { + return time_ns() / TIMER_E6; +} +double time_ss() { + return time_ns() / 1e9; // TIMER_E9; +} +double time_mm() { + return time_ss() / 60; +} +double time_hh() { + return time_mm() / 60; +} + +void sleep_ns( double ns ) { +#if is(win32) + if( ns >= 100 ) { + LARGE_INTEGER li; // Windows sleep in 100ns units + HANDLE timer = CreateWaitableTimer(NULL, TRUE, NULL); + li.QuadPart = (LONGLONG)(__int64)(-ns/100); // Negative for relative time + SetWaitableTimer(timer, &li, 0, NULL, NULL, FALSE); + WaitForSingleObject(timer, INFINITE); + CloseHandle(timer); +#else + if( ns > 0 ) { + struct timespec wait = {0}; + wait.tv_sec = ns / 1e9; + wait.tv_nsec = ns - wait.tv_sec * 1e9; + nanosleep(&wait, NULL); +#endif + } else { +#if is(win32) + Sleep(0); // yield, Sleep(0), SwitchToThread +#else + usleep(0); +#endif + } +} +void sleep_us( double us ) { + sleep_ns(us * 1e3); +} +void sleep_ms( double ms ) { + sleep_ns(ms * 1e6); +} +void sleep_ss( double ss ) { + sleep_ns(ss * 1e9); +} + +// ---------------------------------------------------------------------------- +// timer + +struct timer_internal_t { + unsigned ms; + unsigned (*callback)(unsigned interval, void *arg); + void *arg; + thread_ptr_t thd; +}; + +static int timer_func(void *arg) { + struct timer_internal_t *p = (struct timer_internal_t*)arg; + + sleep_ms( p->ms ); + + for( ;; ) { + unsigned then = time_ms(); + + p->ms = p->callback(p->ms, p->arg); + if( !p->ms ) break; + + unsigned now = time_ms(); + unsigned lapse = now - then; + int diff = p->ms - lapse; + sleep_ms( diff <= 0 ? 0 : diff ); + } + + thread_exit(0); + return 0; +} + +static __thread array(struct timer_internal_t *) timers; + +unsigned timer(unsigned ms, unsigned (*callback)(unsigned ms, void *arg), void *arg) { + struct timer_internal_t *p = MALLOC( sizeof(struct timer_internal_t) ); + p->ms = ms; + p->callback = callback; + p->arg = arg; + p->thd = thread_init( timer_func, p, "", 0 ); + + array_push(timers, p); + return array_count(timers); +} +void timer_destroy(unsigned i) { + if( i-- ) { + thread_join(timers[i]->thd); + thread_term(timers[i]->thd); + FREE(timers[i]); + timers[i] = 0; + } +} + +// ---------------------------------------------------------------------------- +// guid + +//typedef vec3i guid; + +guid guid_create() { + static __thread unsigned counter = 0; + static uint64_t appid = 0; do_once appid = hash_str(app_name()); + + union conv { + struct { + unsigned timestamp : 32; + unsigned threadid : 16; // inverted order in LE + unsigned appid : 16; // + unsigned counter : 32; + }; + vec3i v3; + } c; + c.timestamp = date_epoch() - 0x65000000; + c.appid = (unsigned)appid; + c.threadid = (unsigned)(uintptr_t)thread_current_thread_id(); + c.counter = ++counter; + + return c.v3; +} + +// ---------------------------------------------------------------------------- +// ease + +float ease_nop(float t) { return 0; } +float ease_linear(float t) { return t; } + +float ease_out_sine(float t) { return sinf(t*(C_PI*0.5f)); } +float ease_out_quad(float t) { return -(t*(t-2)); } +float ease_out_cubic(float t) { float f=t-1; return f*f*f+1; } +float ease_out_quart(float t) { float f=t-1; return f*f*f*(1-t)+1; } +float ease_out_quint(float t) { float f=(t-1); return f*f*f*f*f+1; } +float ease_out_expo(float t) { return (t >= 1) ? t : 1-powf(2,-10*t); } +float ease_out_circ(float t) { return sqrtf((2-t)*t); } +float ease_out_back(float t) { float f=1-t; return 1-(f*f*f-f*sinf(f*C_PI)); } +float ease_out_elastic(float t) { return sinf(-13*(C_PI*0.5f)*(t+1))*powf(2,-10*t)+1; } +float ease_out_bounce(float t) { return (t < 4.f/11) ? (121.f*t*t)/16 : (t < 8.f/11) ? (363.f/40*t*t)-(99.f/10*t)+17.f/5 : (t < 9.f/10) ? (4356.f/361*t*t)-(35442.f/1805*t)+16061.f/1805 : (54.f/5*t*t)-(513.f/25*t)+268.f/25; } + +float ease_in_sine(float t) { return 1+sinf((t-1)*(C_PI*0.5f)); } +float ease_in_quad(float t) { return t*t; } +float ease_in_cubic(float t) { return t*t*t; } +float ease_in_quart(float t) { return t*t*t*t; } +float ease_in_quint(float t) { return t*t*t*t*t; } +float ease_in_expo(float t) { return (t <= 0) ? t : powf(2,10*(t-1)); } +float ease_in_circ(float t) { return 1-sqrtf(1-(t*t)); } +float ease_in_back(float t) { return t*t*t-t*sinf(t*C_PI); } +float ease_in_elastic(float t) { return sinf(13*(C_PI*0.5f)*t)*powf(2,10*(t-1)); } +float ease_in_bounce(float t) { return 1-ease_out_bounce(1-t); } + +float ease_inout_sine(float t) { return 0.5f*(1-cosf(t*C_PI)); } +float ease_inout_quad(float t) { return (t < 0.5f) ? 2*t*t : (-2*t*t)+(4*t)-1; } +float ease_inout_cubic(float t) { float f; return (t < 0.5f) ? 4*t*t*t : (f=(2*t)-2,0.5f*f*f*f+1); } +float ease_inout_quart(float t) { float f; return (t < 0.5f) ? 8*t*t*t*t : (f=(t-1),-8*f*f*f*f+1); } +float ease_inout_quint(float t) { float f; return (t < 0.5f) ? 16*t*t*t*t*t : (f=((2*t)-2),0.5f*f*f*f*f*f+1); } +float ease_inout_expo(float t) { return (t <= 0 || t >= 1) ? t : t < 0.5f ? 0.5f*powf(2,(20*t)-10) : -0.5f*powf(2,(-20*t)+10)+1; } +float ease_inout_circ(float t) { return t < 0.5f ? 0.5f*(1-sqrtf(1-4*(t*t))) : 0.5f*(sqrtf(-((2*t)-3)*((2*t)-1))+1); } +float ease_inout_back(float t) { float f; return t < 0.5f ? (f=2*t,0.5f*(f*f*f-f*sinf(f*C_PI))) : (f=(1-(2*t-1)),0.5f*(1-(f*f*f-f*sinf(f*C_PI)))+0.5f); } +float ease_inout_elastic(float t) { return t < 0.5f ? 0.5f*sinf(13*(C_PI*0.5f)*(2*t))*powf(2,10*((2*t)-1)) : 0.5f*(sinf(-13*(C_PI*0.5f)*((2*t-1)+1))*powf(2,-10*(2*t-1))+2); } +float ease_inout_bounce(float t) { return t < 0.5f ? 0.5f*ease_in_bounce(t*2) : 0.5f*ease_out_bounce(t*2-1)+0.5f; } + +float ease_inout_perlin(float t) { float t3=t*t*t,t4=t3*t,t5=t4*t; return 6*t5-15*t4+10*t3; } + +float ease(float t01, unsigned mode) { + typedef float (*easing)(float); + easing modes[] = { + ease_out_sine, + ease_out_quad, + ease_out_cubic, + ease_out_quart, + ease_out_quint, + ease_out_expo, + ease_out_circ, + ease_out_back, + ease_out_elastic, + ease_out_bounce, + + ease_in_sine, + ease_in_quad, + ease_in_cubic, + ease_in_quart, + ease_in_quint, + ease_in_expo, + ease_in_circ, + ease_in_back, + ease_in_elastic, + ease_in_bounce, + + ease_inout_sine, + ease_inout_quad, + ease_inout_cubic, + ease_inout_quart, + ease_inout_quint, + ease_inout_expo, + ease_inout_circ, + ease_inout_back, + ease_inout_elastic, + ease_inout_bounce, + + ease_nop, + ease_linear, + ease_inout_perlin, + }; + return modes[clampi(mode, 0, countof(modes))](clampf(t01,0,1)); +} + +float ease_pong(float t, unsigned fn) { return 1 - ease(t, fn); } +float ease_ping_pong(float t, unsigned fn1, unsigned fn2) { return t < 0.5 ? ease(t*2,fn1) : ease(1-(t-0.5)*2,fn2); } +float ease_pong_ping(float t, unsigned fn1, unsigned fn2) { return 1 - ease_ping_pong(t,fn1,fn2); } + + +const char **ease_enums() { + static const char *list[] = { + "ease_out_sine", + "ease_out_quad", + "ease_out_cubic", + "ease_out_quart", + "ease_out_quint", + "ease_out_expo", + "ease_out_circ", + "ease_out_back", + "ease_out_elastic", + "ease_out_bounce", + + "ease_in_sine", + "ease_in_quad", + "ease_in_cubic", + "ease_in_quart", + "ease_in_quint", + "ease_in_expo", + "ease_in_circ", + "ease_in_back", + "ease_in_elastic", + "ease_in_bounce", + + "ease_inout_sine", + "ease_inout_quad", + "ease_inout_cubic", + "ease_inout_quart", + "ease_inout_quint", + "ease_inout_expo", + "ease_inout_circ", + "ease_inout_back", + "ease_inout_elastic", + "ease_inout_bounce", + + "ease_nop", + "ease_linear", + "ease_inout_perlin", + + 0 + }; + return list; +} + +const char *ease_enum(unsigned mode) { + return mode[ ease_enums() ]; +} + +/*AUTORUN { + ENUM(EASE_LINEAR|EASE_OUT); + ENUM(EASE_SINE|EASE_OUT); + ENUM(EASE_QUAD|EASE_OUT); + ENUM(EASE_CUBIC|EASE_OUT); + ENUM(EASE_QUART|EASE_OUT); + ENUM(EASE_QUINT|EASE_OUT); + ENUM(EASE_EXPO|EASE_OUT); + ENUM(EASE_CIRC|EASE_OUT); + ENUM(EASE_BACK|EASE_OUT); + ENUM(EASE_ELASTIC|EASE_OUT); + ENUM(EASE_BOUNCE|EASE_OUT); + + ENUM(EASE_SINE|EASE_IN); + ENUM(EASE_QUAD|EASE_IN); + ENUM(EASE_CUBIC|EASE_IN); + ENUM(EASE_QUART|EASE_IN); + ENUM(EASE_QUINT|EASE_IN); + ENUM(EASE_EXPO|EASE_IN); + ENUM(EASE_CIRC|EASE_IN); + ENUM(EASE_BACK|EASE_IN); + ENUM(EASE_ELASTIC|EASE_IN); + ENUM(EASE_BOUNCE|EASE_IN); + + ENUM(EASE_SINE|EASE_INOUT); + ENUM(EASE_QUAD|EASE_INOUT); + ENUM(EASE_CUBIC|EASE_INOUT); + ENUM(EASE_QUART|EASE_INOUT); + ENUM(EASE_QUINT|EASE_INOUT); + ENUM(EASE_EXPO|EASE_INOUT); + ENUM(EASE_CIRC|EASE_INOUT); + ENUM(EASE_BACK|EASE_INOUT); + ENUM(EASE_ELASTIC|EASE_INOUT); + ENUM(EASE_BOUNCE|EASE_INOUT); + + ENUM(EASE_NOP); + ENUM(EASE_LINEAR); + ENUM(EASE_INOUT_PERLIN); +};*/ + +// ---------------------------------------------------------------------------- +// tween + +tween_t tween() { + tween_t tw = {0}; + return tw; +} + +float tween_update(tween_t *tw, float dt) { + if( !array_count(tw->keyframes) ) return 0.0f; + + for( int i = 0, end = array_count(tw->keyframes) - 1; i < end; ++i ) { + tween_keyframe_t *kf1 = &tw->keyframes[i]; + tween_keyframe_t *kf2 = &tw->keyframes[i + 1]; + if (tw->time >= kf1->t && tw->time <= kf2->t) { + float localT = (tw->time - kf1->t) / (kf2->t - kf1->t); + float easedT = ease(localT, kf1->ease); + tw->result = mix3(kf1->v, kf2->v, easedT); + break; + } + } + + float done = (tw->time / tw->duration); + tw->time += dt; + return clampf(done, 0.0f, 1.0f); +} + +void tween_reset(tween_t *tw) { + tw->time = 0.0f; +} + +void tween_destroy(tween_t *tw) { + tween_t tw_ = {0}; + array_free(tw->keyframes); + *tw = tw_; +} + +static INLINE +int tween_comp_keyframes(const void *a, const void *b) { + float t1 = ((const tween_keyframe_t*)a)->t; + float t2 = ((const tween_keyframe_t*)b)->t; + return (t1 > t2) - (t1 < t2); +} + +void tween_setkey(tween_t *tw, float t, vec3 v, unsigned mode) { + tween_keyframe_t keyframe = { t, v, mode }; + array_push(tw->keyframes, keyframe); + array_sort(tw->keyframes, tween_comp_keyframes); + tw->duration = array_back(tw->keyframes)->t; +} + +void tween_delkey(tween_t *tw, float t) { // @todo: untested + for( int i = 0, end = array_count(tw->keyframes); i < end; i++ ) { + if( tw->keyframes[i].t == t ) { + array_erase_slow(tw->keyframes, i); + tw->duration = array_back(tw->keyframes)->t; + return; + } + } +} + +// ---------------------------------------------------------------------------- +// curve + +curve_t curve() { + curve_t c = {0}; + return c; +} + +static INLINE +vec3 catmull( vec3 p0, vec3 p1, vec3 p2, vec3 p3, float t ) { + float t2 = t*t; + float t3 = t*t*t; + + vec3 c; + c.x = 0.5 * ((2 * p1.x) + (-p0.x + p2.x) * t + (2 * p0.x - 5 * p1.x + 4 * p2.x - p3.x) * t2 + (-p0.x + 3 * p1.x - 3 * p2.x + p3.x) * t3); + c.y = 0.5 * ((2 * p1.y) + (-p0.y + p2.y) * t + (2 * p0.y - 5 * p1.y + 4 * p2.y - p3.y) * t2 + (-p0.y + 3 * p1.y - 3 * p2.y + p3.y) * t3); + c.z = 0.5 * ((2 * p1.z) + (-p0.z + p2.z) * t + (2 * p0.z - 5 * p1.z + 4 * p2.z - p3.z) * t2 + (-p0.z + 3 * p1.z - 3 * p2.z + p3.z) * t3); + return c; +} + +void curve_add(curve_t *c, vec3 p) { + array_push(c->points, p); +} + +void curve_end( curve_t *c, int k ) { + ASSERT( k > 0 ); + + array_free(c->lengths); + array_free(c->samples); + array_free(c->indices); + array_free(c->colors); + + // refit points[N] to samples[K] + int N = array_count(c->points); + if( k < N ) { + // truncate: expected k-points lesser or equal than existing N points + for( int i = 0; i <= k; ++i ) { + float s = (float)i / k; + int t = s * (N-1); + array_push(c->samples, c->points[t]); + + float p = fmod(i, N-1) / (N-1); // [0..1) + int is_control_point = p <= 0 || p >= 1; + array_push(c->colors, is_control_point ? ORANGE: BLUE); + } + + } else { + // interpolate: expected k-points greater than existing N-points + --N; + int upper = N - (k%N); + int lower = (k%N); + if(upper < lower) + k += upper; + else + k -= lower; + + int points_per_segment = (k / N); + ++N; + + int looped = len3sq(sub3(c->points[0], *array_back(c->points))) < 0.1; + + for( int i = 0; i <= k; ++i ) { + int point = i % points_per_segment; + float p = point / (float)points_per_segment; // [0..1) + int t = i / points_per_segment; + + // linear + vec3 l = mix3(c->points[t], c->points[t+(i!=k)], p); + + // printf("%d) %d>%d %f\n", i, t, t+(i!=k), p); + ASSERT(p <= 1); + + // catmull + int p0 = t - 1; + int p1 = t + 0; + int p2 = t + 1; + int p3 = t + 2; + if( looped ) + { + int M = N-1; + if(p0<0) p0+=M; else if(p0>=M) p0-=M; + if(p1<0) p1+=M; else if(p1>=M) p1-=M; + if(p2<0) p2+=M; else if(p2>=M) p2-=M; + if(p3<0) p3+=M; else if(p3>=M) p3-=M; + } + else + { + int M = N-1; + if(p0<0) p0=0; else if(p0>=M) p0=M; + if(p1<0) p1=0; else if(p1>=M) p1=M; + if(p2<0) p2=0; else if(p2>=M) p2=M; + if(p3<0) p3=0; else if(p3>=M) p3=M; + } + vec3 m = catmull(c->points[p0],c->points[p1],c->points[p2],c->points[p3],p); + l = m; + + array_push(c->samples, l); + + int is_control_point = p <= 0 || p >= 1; + array_push(c->colors, is_control_point ? ORANGE: BLUE); + } + } + + array_push(c->lengths, 0 ); + for( int i = 1; i <= k; ++i ) { + // approximate curve length at every sample point + array_push(c->lengths, len3(sub3(c->samples[i], c->samples[i-1])) + c->lengths[i-1] ); + } + // normalize lengths to be between 0 and 1 + float maxv = c->lengths[k]; + for( int i = 1; i <= k; ++i ) c->lengths[i] /= maxv; + + array_push(c->indices, 0 ); + for( int i = 0/*1*/; i indices) + 1; j lengths[j] lengths[j] > 0.01) + array_push(c->indices, j ); + } +} + +vec3 curve_eval(curve_t *c, float dt, unsigned *color) { + unsigned nil; if(!color) color = &nil; + dt = clampf(dt, 0.0f, 1.0f); + int l = (int)(array_count(c->indices) - 1); + int p = (int)(dt * l); + int t = c->indices[p]; + + t %= (array_count(c->indices)-1); + vec3 pos = mix3(c->samples[t], c->samples[t+1], dt * l - p); + *color = c->colors[t]; + + return pos; +} + +void curve_destroy(curve_t *c) { + array_free(c->lengths); + array_free(c->colors); + array_free(c->samples); + array_free(c->points); + array_free(c->indices); +} +#line 0 + #line 1 "engine/split/v4k_profile.c" #if ENABLE_PROFILER profiler_t profiler; @@ -25139,10 +25203,10 @@ void window_cursor_shape(unsigned mode) { 0, GLFW_ARROW_CURSOR, GLFW_IBEAM_CURSOR, - GLFW_CROSSHAIR_CURSOR, - GLFW_HAND_CURSOR, GLFW_HRESIZE_CURSOR, GLFW_VRESIZE_CURSOR, + GLFW_HAND_CURSOR, + GLFW_CROSSHAIR_CURSOR, }; do_once { static unsigned pixels[16 * 16] = { 0x01000000 }; // ABGR(le) glfw3 note: A(0x00) means 0xFF for some reason @@ -25235,7 +25299,20 @@ int window_has_maximize() { return ifdef(ems, 0, glfwGetWindowAttrib(window, GLFW_MAXIMIZED) == GLFW_TRUE); } +const char *window_clipboard() { + return glfwGetClipboardString(window); +} +void window_setclipboard(const char *text) { + glfwSetClipboardString(window, text); +} +static +double window_scale() { // ok? @testme + float xscale, yscale; + GLFWmonitor *monitor = glfwGetPrimaryMonitor(); + glfwGetMonitorContentScale(monitor, &xscale, &yscale); + return maxi(xscale, yscale); +} #line 0 #line 1 "engine/split/v4k_obj.c" @@ -26590,7 +26667,7 @@ int pathfind_astar(int width, int height, const unsigned* map, vec2i src, vec2i #error ASTAR_POS_INDEX(p) should specify macro to map position to index #endif - #ifndef ASTAR_MAX_INDEX + #ifndef ASTAR_MAX_INDEX #error ASTAR_MAX_INDEX should specify max count of indices the position can map to #endif @@ -26681,7 +26758,7 @@ int pathfind_astar(int width, int height, const unsigned* map, vec2i src, vec2i i = p; \ p = (i - 1) / 2; \ } \ - } while (0) + } while (0) #define ASTAR_HEAP_POP() \ do { \ @@ -26872,7 +26949,7 @@ int pathfind_astar(int width, int height, const unsigned* map, vec2i src, vec2i // [ ] CompareKeys(keyVar1, operator < <= > >= == !=, keyVar2) // [ ] SetTags(names=blank,cooldownTime=inf,bIsCooldownAdditive=false) // [ ] HasTags(names=blank,bAllRequired=true) -// [ ] PushToStack(keyVar,itemObj): creates a new stack if one doesn’t exist, and stores it in the passed variable name, and then pushes ‘item’ object onto it. +// [ ] PushToStack(keyVar,itemObj): creates a new stack if one doesnt exist, and stores it in the passed variable name, and then pushes item object onto it. // [ ] PopFromStack(keyVar,itemVar): pop pops an item off the stack, and stores it in the itemVar variable, failing if the stack is already empty. // [ ] IsEmptyStack(keyVar): checks if the stack passed is empty and returns success if it is, and failure if its not. // [ ] Communication Node: This is a type of action node that allows an AI agent to communicate with other agents or entities in the game world. The node takes an input specifying the message to be communicated and the recipient(s) of the message (wildmask,l/p/f/g prefixes). The node then sends the message to the designated recipient(s) and returns success when the communication is completed. This node can be useful for implementing behaviors that require the AI agent to coordinate with other agents or to convey information to the player. It could use a radius argument to specify the maximum allowed distance for the recipients. diff --git a/engine/v4k.h b/engine/v4k.h index 69a434f..1d36367 100644 --- a/engine/v4k.h +++ b/engine/v4k.h @@ -1986,6 +1986,16 @@ API void script_bind_function(const char *c_name, void *c_function); API void script_call(const char *lua_function); API bool script_tests(); + +// ----------------------------------------------------------------------------- +// script framework + +enum { + SCRIPT_LUA = 1, + SCRIPT_DEBUGGER = 2, +}; + +API void *script_init_env(unsigned flags); #line 0 #line 1 "engine/split/v4k_editor.h" @@ -2035,98 +2045,6 @@ API void kit_locale( const char *langcode_iso639_1 ); // set current locale: en API char* kit_translate( const char *id ); // perform a translation, given current locale #line 0 -#line 1 "engine/split/v4k_font.h" -// ----------------------------------------------------------------------------- -// font framework -// - rlyeh, public domain - -// font size tags -#define FONT_H1 "\1" // largest -#define FONT_H2 "\2" -#define FONT_H3 "\3" -#define FONT_H4 "\4" -#define FONT_H5 "\5" -#define FONT_H6 "\6" // smallest - -// font color tags -#define FONT_COLOR1 "\x10" -#define FONT_COLOR2 "\x11" -#define FONT_COLOR3 "\x12" -#define FONT_COLOR4 "\x13" -#define FONT_COLOR5 "\x14" -#define FONT_COLOR6 "\x15" -#define FONT_COLOR7 "\x16" -#define FONT_COLOR8 "\x17" -#define FONT_COLOR9 "\x18" -#define FONT_COLOR10 "\x19" - -// font face tags -#define FONT_FACE1 "\x1a" -#define FONT_FACE2 "\x1b" -#define FONT_FACE3 "\x1c" -#define FONT_FACE4 "\x1d" -#define FONT_FACE5 "\x1e" -#define FONT_FACE6 "\x1f" - -// font align tags -#define FONT_LEFT "\\<" -#define FONT_CENTER "\\|" -#define FONT_RIGHT "\\>" -#define FONT_TOP "\\^" -#define FONT_MIDDLE "\\-" -#define FONT_BASELINE "\\_" -#define FONT_BOTTOM "\\v" - -// font flags -enum FONT_FLAGS { - // font atlas size - FONT_512 = 0x0, - FONT_1024 = 0x1, - FONT_2048 = 0x2, - FONT_4096 = 0x4, - - // font oversampling - FONT_NO_OVERSAMPLE = 0x0, - FONT_OVERSAMPLE_X = 0x08, - FONT_OVERSAMPLE_Y = 0x10, - - // unicode ranges - FONT_ASCII = 0x800, // Compatible charset - FONT_AR = 0x001000, // Arabic and Arabic-Indic digits - FONT_ZH = 0x002000, // Chinese Simplified (@todo: add ZH_FULL) - FONT_EL = 0x004000, // Greek, Coptic, modern Georgian, Svan, Mingrelian, Ancient Greek - FONT_EM = 0x008000, // Emoji - FONT_EU = 0x010000, // Eastern/western Europe, IPA, Latin ext A/B - FONT_HE = 0x020000, // Hebrew, Yiddish, Ladino, and other diaspora languages - FONT_JP = 0x040000, // Hiragana, Katakana, Punctuations, Half-width chars - FONT_KR = 0x080000, // Korean, Hangul - FONT_RU = 0x100000, // Cyrillic + ext A/B - FONT_TH = 0x200000, // Thai - FONT_VI = 0x400000, // Vietnamese - FONT_CJK = FONT_ZH|FONT_JP|FONT_KR, - - // FONT_DEFAULTS = FONT_512 | FONT_NO_OVERSAMPLE | FONT_ASCII, -}; - -// configures -API void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags); -API void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags); -API void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6); -API void font_color(const char *color_tag, uint32_t color); - -// commands -API vec2 font_xy(); -API void font_goto(float x, float y); -API vec2 font_print(const char *text); -API vec2 font_rect(const char *text); -// void font_clip(vec2 topleft, vec2 bottomright); -// void font_wrap(vec2 topleft, vec2 bottomright); - -// syntax highlighting -API void* font_colorize(const char *text, const char *comma_types, const char *comma_keywords); // comma separated tokens. expensive, please cache result. -API vec2 font_highlight(const char *text, const void *colors); -#line 0 - #line 1 "engine/split/v4k_file.h" // ----------------------------------------------------------------------------- // files, cache and virtual filesystem (registered directories and/or compressed zip archives). @@ -2227,6 +2145,98 @@ API void ini_destroy(ini_t); API bool ini_write(const char *filename, const char *section, const char *key, const char *value); #line 0 +#line 1 "engine/split/v4k_font.h" +// ----------------------------------------------------------------------------- +// font framework +// - rlyeh, public domain + +// font size tags +#define FONT_H1 "\1" // largest +#define FONT_H2 "\2" +#define FONT_H3 "\3" +#define FONT_H4 "\4" +#define FONT_H5 "\5" +#define FONT_H6 "\6" // smallest + +// font color tags +#define FONT_COLOR1 "\x10" +#define FONT_COLOR2 "\x11" +#define FONT_COLOR3 "\x12" +#define FONT_COLOR4 "\x13" +#define FONT_COLOR5 "\x14" +#define FONT_COLOR6 "\x15" +#define FONT_COLOR7 "\x16" +#define FONT_COLOR8 "\x17" +#define FONT_COLOR9 "\x18" +#define FONT_COLOR10 "\x19" + +// font face tags +#define FONT_FACE1 "\x1a" +#define FONT_FACE2 "\x1b" +#define FONT_FACE3 "\x1c" +#define FONT_FACE4 "\x1d" +#define FONT_FACE5 "\x1e" +#define FONT_FACE6 "\x1f" + +// font align tags +#define FONT_LEFT "\\<" +#define FONT_CENTER "\\|" +#define FONT_RIGHT "\\>" +#define FONT_TOP "\\^" +#define FONT_MIDDLE "\\-" +#define FONT_BASELINE "\\_" +#define FONT_BOTTOM "\\v" + +// font flags +enum FONT_FLAGS { + // font atlas size + FONT_512 = 0x0, + FONT_1024 = 0x1, + FONT_2048 = 0x2, + FONT_4096 = 0x4, + + // font oversampling + FONT_NO_OVERSAMPLE = 0x0, + FONT_OVERSAMPLE_X = 0x08, + FONT_OVERSAMPLE_Y = 0x10, + + // unicode ranges + FONT_ASCII = 0x800, // Compatible charset + FONT_AR = 0x001000, // Arabic and Arabic-Indic digits + FONT_ZH = 0x002000, // Chinese Simplified (@todo: add ZH_FULL) + FONT_EL = 0x004000, // Greek, Coptic, modern Georgian, Svan, Mingrelian, Ancient Greek + FONT_EM = 0x008000, // Emoji + FONT_EU = 0x010000, // Eastern/western Europe, IPA, Latin ext A/B + FONT_HE = 0x020000, // Hebrew, Yiddish, Ladino, and other diaspora languages + FONT_JP = 0x040000, // Hiragana, Katakana, Punctuations, Half-width chars + FONT_KR = 0x080000, // Korean, Hangul + FONT_RU = 0x100000, // Cyrillic + ext A/B + FONT_TH = 0x200000, // Thai + FONT_VI = 0x400000, // Vietnamese + FONT_CJK = FONT_ZH|FONT_JP|FONT_KR, + + // FONT_DEFAULTS = FONT_512 | FONT_NO_OVERSAMPLE | FONT_ASCII, +}; + +// configures +API void font_face(const char *face_tag, const char *filename_ttf, float font_size, unsigned flags); +API void font_face_from_mem(const char *tag, const void *ttf_buffer, unsigned ttf_len, float font_size, unsigned flags); +API void font_scales(const char *face_tag, float h1, float h2, float h3, float h4, float h5, float h6); +API void font_color(const char *color_tag, uint32_t color); + +// commands +API vec2 font_xy(); +API void font_goto(float x, float y); +API vec2 font_print(const char *text); +API vec2 font_rect(const char *text); +// void font_clip(vec2 topleft, vec2 bottomright); +// void font_wrap(vec2 topleft, vec2 bottomright); + +// syntax highlighting +API void* font_colorize(const char *text, const char *comma_types, const char *comma_keywords); // comma separated tokens. expensive, please cache result. +API vec2 font_highlight(const char *text, const void *colors); +#line 0 + #line 1 "engine/split/v4k_input.h" // ----------------------------------------------------------------------------- // input framework @@ -2329,7 +2339,7 @@ enum INPUT_ENUMS { KEY_PAD1,KEY_PAD2,KEY_PAD3,KEY_PAD4,KEY_PAD5,KEY_PAD6,KEY_PAD7,KEY_PAD8,KEY_PAD9,KEY_PAD0, // beware: complicated on laptops KEY_PADADD,KEY_PADSUB,KEY_PADMUL,KEY_PADDIV,KEY_PADDOT,KEY_PADENTER, // beware: complicated on laptops - MOUSE_L, MOUSE_M, MOUSE_R, + MOUSE_L, MOUSE_M, MOUSE_R, // @todo: MOUSE_CLICKS, GAMEPAD_CONNECTED, GAMEPAD_A, GAMEPAD_B, GAMEPAD_X, GAMEPAD_Y, GAMEPAD_UP, GAMEPAD_DOWN, GAMEPAD_LEFT, GAMEPAD_RIGHT, GAMEPAD_MENU, GAMEPAD_START, GAMEPAD_LB, GAMEPAD_RB, GAMEPAD_LTHUMB, GAMEPAD_RTHUMB, @@ -3192,6 +3202,7 @@ enum TEXTURE_FLAGS { // @fixme TEXTURE_SRGB = 1 << 24, TEXTURE_BGR = 1 << 25, + TEXTURE_BGRA = TEXTURE_BGR, TEXTURE_ARRAY = 1 << 26, }; @@ -3986,6 +3997,7 @@ API light_t* scene_index_light(unsigned index); API char* tempvl(const char *fmt, va_list); API char* tempva(const char *fmt, ...); #define va(...) (((&printf) || printf(__VA_ARGS__), tempva(__VA_ARGS__))) // vs2015 check trick +#define vac (const char*)va // string: allocated api (heap). FREE() after use API char* strcatf(char **s, const char *buf); @@ -4072,6 +4084,93 @@ API unsigned quark_intern( quarks_db*, const char *string ); API const char *quark_string( quarks_db*, unsigned key ); #line 0 +#line 1 "engine/split/v4k_system.h" +// ----------------------------------------------------------------------------- +// system framework utils +// - rlyeh, public domain. +// +// Note: Windows users add `/Zi` compilation flags, else add `-g` and/or `-ldl` flags +// Note: If you are linking your binary using GNU ld you need to add --export-dynamic + +API void* thread( int (*thread_func)(void* user_data), void* user_data ); +API void thread_destroy( void *thd ); + +API int argc(); +API char* argv(int); + +API int flag(const char *commalist); // --arg // app_flag? +API const char* option(const char *commalist, const char *defaults); // --arg=string or --arg string +API int optioni(const char *commalist, int defaults); // --arg=integer or --arg integer // argvi() ? +API float optionf(const char *commalist, float defaults); // --arg=float or --arg float // flagf() ? + +API void tty_attach(); +API void tty_detach(); +API void tty_color(unsigned color); +API void tty_reset(); + +API const char* app_exec(const char *command); // returns ("%15d %s", retcode, output_last_line) +API int app_spawn(const char *command); +API int app_cores(); +API int app_battery(); /// returns battery level [1..100]. also positive if charging (+), negative if discharging (-), and 0 if no battery is present. + +API const char* app_name(); +API const char* app_path(); +API const char* app_cache(); +API const char* app_temp(); +API const char* app_cmdline(); + +API void app_beep(); +API void app_hang(); +API void app_crash(); +API void app_singleton(const char *guid); +API bool app_open(const char *folder_file_or_url); + +API const char* app_loadfile(); +API const char* app_savefile(); + + +API char* callstack( int traces ); // write callstack into a temporary string. <0 traces to invert order. do not free(). +API int callstackf( FILE *fp, int traces ); // write callstack to file. <0 traces to invert order. + +API void die(const char *message); +API void alert(const char *message); +API void hexdump( const void *ptr, unsigned len ); +API void hexdumpf( FILE *fp, const void *ptr, unsigned len, int width ); +API void breakpoint(); +API bool has_debugger(); + +API void trap_install(void); +API const char *trap_name(int signal); // helper util +API void trap_on_ignore(int signal); // helper util +API void trap_on_quit(int signal); // helper util +API void trap_on_abort(int signal); // helper util +API void trap_on_debug(int signal); // helper util + +#define PANIC(...) PANIC(va(__VA_ARGS__), strrchr(__FILE__, '/')?(strrchr(__FILE__, '/')+2):__FILE__, __LINE__) // die() ? +API int (PANIC)(const char *error, const char *file, int line); + +#define PRINTF(...) PRINTF(va(__VA_ARGS__), 1[#__VA_ARGS__] == '!' ? callstack(+48) : "", strrchr(__FILE__, '/')?(strrchr(__FILE__, '/')+2):__FILE__, __LINE__, __FUNCTION__) +API int (PRINTF)(const char *text, const char *stack, const char *file, int line, const char *function); + +#define test(expr) test(strrchr(__FILE__, '/')?(strrchr(__FILE__, '/')+2):__FILE__,__LINE__,#expr,!!(expr)) +API int (test)(const char *file, int line, const char *expr, bool result); + +#if ENABLE_AUTOTESTS +#define AUTOTEST AUTORUN +#else +#define AUTOTEST static void concat(concat(concat(disabled_test_, __LINE__), _), __COUNTER__)() +#endif + +// AUTOTEST { test(1<2); } + +#if ENABLE_RETAIL +#undef PRINTF +#define PRINTF(...) 0 +#undef test +#define test(expr) 0 +#endif +#line 0 + #line 1 "engine/split/v4k_time.h" // ----------------------------------------------------------------------------- // time framework utils @@ -4226,98 +4325,11 @@ typedef struct curve_t { API curve_t curve(); API void curve_add(curve_t *c, vec3 p); -API void curve_finish(curve_t *c, int num_points); +API void curve_end(curve_t *c, int num_points); API vec3 curve_eval(curve_t *c, float dt, unsigned *color); API void curve_destroy(curve_t *c); #line 0 -#line 1 "engine/split/v4k_system.h" -// ----------------------------------------------------------------------------- -// system framework utils -// - rlyeh, public domain. -// -// Note: Windows users add `/Zi` compilation flags, else add `-g` and/or `-ldl` flags -// Note: If you are linking your binary using GNU ld you need to add --export-dynamic - -API void* thread( int (*thread_func)(void* user_data), void* user_data ); -API void thread_destroy( void *thd ); - -API int argc(); -API char* argv(int); - -API int flag(const char *commalist); // --arg // app_flag? -API const char* option(const char *commalist, const char *defaults); // --arg=string or --arg string -API int optioni(const char *commalist, int defaults); // --arg=integer or --arg integer // argvi() ? -API float optionf(const char *commalist, float defaults); // --arg=float or --arg float // flagf() ? - -API void tty_attach(); -API void tty_detach(); -API void tty_color(unsigned color); -API void tty_reset(); - -API const char* app_exec(const char *command); // returns ("%15d %s", retcode, output_last_line) -API int app_spawn(const char *command); -API int app_cores(); -API int app_battery(); /// returns battery level [1..100]. also positive if charging (+), negative if discharging (-), and 0 if no battery is present. - -API const char* app_name(); -API const char* app_path(); -API const char* app_cache(); -API const char* app_temp(); -API const char* app_cmdline(); - -API void app_beep(); -API void app_hang(); -API void app_crash(); -API void app_singleton(const char *guid); -API bool app_open(const char *folder_file_or_url); - -API const char* app_loadfile(); -API const char* app_savefile(); - - -API char* callstack( int traces ); // write callstack into a temporary string. <0 traces to invert order. do not free(). -API int callstackf( FILE *fp, int traces ); // write callstack to file. <0 traces to invert order. - -API void die(const char *message); -API void alert(const char *message); -API void hexdump( const void *ptr, unsigned len ); -API void hexdumpf( FILE *fp, const void *ptr, unsigned len, int width ); -API void breakpoint(); -API bool has_debugger(); - -API void trap_install(void); -API const char *trap_name(int signal); // helper util -API void trap_on_ignore(int signal); // helper util -API void trap_on_quit(int signal); // helper util -API void trap_on_abort(int signal); // helper util -API void trap_on_debug(int signal); // helper util - -#define PANIC(...) PANIC(va(__VA_ARGS__), strrchr(__FILE__, '/')?(strrchr(__FILE__, '/')+2):__FILE__, __LINE__) // die() ? -API int (PANIC)(const char *error, const char *file, int line); - -#define PRINTF(...) PRINTF(va(__VA_ARGS__), 1[#__VA_ARGS__] == '!' ? callstack(+48) : "", strrchr(__FILE__, '/')?(strrchr(__FILE__, '/')+2):__FILE__, __LINE__, __FUNCTION__) -API int (PRINTF)(const char *text, const char *stack, const char *file, int line, const char *function); - -#define test(expr) test(strrchr(__FILE__, '/')?(strrchr(__FILE__, '/')+2):__FILE__,__LINE__,#expr,!!(expr)) -API int (test)(const char *file, int line, const char *expr, bool result); - -#if ENABLE_AUTOTESTS -#define AUTOTEST AUTORUN -#else -#define AUTOTEST static void concat(concat(concat(disabled_test_, __LINE__), _), __COUNTER__)() -#endif - -// AUTOTEST { test(1<2); } - -#if ENABLE_RETAIL -#undef PRINTF -#define PRINTF(...) 0 -#undef test -#define test(expr) 0 -#endif -#line 0 - #line 1 "engine/split/v4k_ui.h" // ----------------------------------------------------------------------------- // immediate ui framework @@ -4541,14 +4553,17 @@ enum CURSOR_SHAPES { CURSOR_NONE, CURSOR_HW_ARROW, // default CURSOR_HW_IBEAM, // i-beam text cursor - CURSOR_HW_CROSS, // crosshair - CURSOR_HW_HAND, // hand, clickable CURSOR_HW_HDRAG, // horizontal drag/resize CURSOR_HW_VDRAG, // vertical drag/resize + CURSOR_HW_HAND, // hand, clickable + CURSOR_HW_CROSS, // crosshair CURSOR_SW_AUTO, // software cursor, ui driven. note: this is the only icon that may be recorded or snapshotted }; API void window_cursor_shape(unsigned shape); + +API const char *window_clipboard(); +API void window_setclipboard(const char *text); #line 0 // ---- @@ -4565,7 +4580,7 @@ API void window_cursor_shape(unsigned shape); #include #define gladLoadGL(func) (glewExperimental = true, glewInit() == GLEW_OK) #else - #if is(win32) /*&& is(tcc)*/ // && WITH_DLL + #if is(win32) /*&& is(tcc)*/ // && ENABLE_DLL #ifdef GLAD_API_CALL #undef GLAD_API_CALL #endif diff --git a/fwk_diff.WinMerge b/fwk_diff.WinMerge index 572baea..d39817a 100644 --- a/fwk_diff.WinMerge +++ b/fwk_diff.WinMerge @@ -3,7 +3,7 @@ C:\Projects\v4k\_fwk\ C:\Projects\fwk-mirror\ - *.cpp,*.h,*.c + *.cpp,*.h,*.c,*.inl,*.lua 1 0 1 diff --git a/tools/3rd_tinyobjloader.h b/tools/3rd_tinyobjloader.h deleted file mode 100644 index 308e5e5..0000000 --- a/tools/3rd_tinyobjloader.h +++ /dev/null @@ -1,1271 +0,0 @@ -// -// Copyright 2012-2016, Syoyo Fujita. -// -// Licensed under 2-clause BSD license. -// - -// -// version 0.9.22: Introduce `load_flags_t`. -// version 0.9.20: Fixes creating per-face material using `usemtl`(#68) -// version 0.9.17: Support n-polygon and crease tag(OpenSubdiv extension) -// version 0.9.16: Make tinyobjloader header-only -// version 0.9.15: Change API to handle no mtl file case correctly(#58) -// version 0.9.14: Support specular highlight, bump, displacement and alpha -// map(#53) -// version 0.9.13: Report "Material file not found message" in `err`(#46) -// version 0.9.12: Fix groups being ignored if they have 'usemtl' just before -// 'g' (#44) -// version 0.9.11: Invert `Tr` parameter(#43) -// version 0.9.10: Fix seg fault on windows. -// version 0.9.9 : Replace atof() with custom parser. -// version 0.9.8 : Fix multi-materials(per-face material ID). -// version 0.9.7 : Support multi-materials(per-face material ID) per -// object/group. -// version 0.9.6 : Support Ni(index of refraction) mtl parameter. -// Parse transmittance material parameter correctly. -// version 0.9.5 : Parse multiple group name. -// Add support of specifying the base path to load material -// file. -// version 0.9.4 : Initial support of group tag(g) -// version 0.9.3 : Fix parsing triple 'x/y/z' -// version 0.9.2 : Add more .mtl load support -// version 0.9.1 : Add initial .mtl load support -// version 0.9.0 : Initial -// - -// -// Use this in *one* .cc -// #define TINYOBJLOADER_IMPLEMENTATION -// #include "tiny_obj_loader.h" -// - -#ifndef TINY_OBJ_LOADER_H_ -#define TINY_OBJ_LOADER_H_ - -#include -#include -#include -#include - -namespace tinyobj { - -typedef struct { - std::string name; - - float ambient[3]; - float diffuse[3]; - float specular[3]; - float transmittance[3]; - float emission[3]; - float shininess; - float ior; // index of refraction - float dissolve; // 1 == opaque; 0 == fully transparent - // illumination model (see http://www.fileformat.info/format/material/) - int illum; - - int dummy; // Suppress padding warning. - - std::string ambient_texname; // map_Ka - std::string diffuse_texname; // map_Kd - std::string specular_texname; // map_Ks - std::string specular_highlight_texname; // map_Ns - std::string bump_texname; // map_bump, bump - std::string displacement_texname; // disp - std::string alpha_texname; // map_d - std::map unknown_parameter; -} material_t; - -typedef struct { - std::string name; - - std::vector intValues; - std::vector floatValues; - std::vector stringValues; -} tag_t; - -typedef struct { - std::vector positions; - std::vector normals; - std::vector texcoords; - std::vector indices; - std::vector - num_vertices; // The number of vertices per face. Up to 255. - std::vector material_ids; // per-face material ID - std::vector tags; // SubD tag -} mesh_t; - -typedef struct { - std::string name; - mesh_t mesh; -} shape_t; - -typedef enum { - triangulation = 1, // used whether triangulate polygon face in .obj - calculate_normals = - 2, // used whether calculate the normals if the .obj normals are empty - // Some nice stuff here -} load_flags_t; - -class float3 { -public: - float3() : x(0.0f), y(0.0f), z(0.0f) {} - - float3(float coord_x, float coord_y, float coord_z) - : x(coord_x), y(coord_y), z(coord_z) {} - - float3(const float3 &from, const float3 &to) { - coord[0] = to.coord[0] - from.coord[0]; - coord[1] = to.coord[1] - from.coord[1]; - coord[2] = to.coord[2] - from.coord[2]; - } - - float3 crossproduct(const float3 &vec) { - float a = y * vec.z - z * vec.y; - float b = z * vec.x - x * vec.z; - float c = x * vec.y - y * vec.x; - return float3(a, b, c); - } - - void normalize() { - const float length = std::sqrt( - (coord[0] * coord[0]) + (coord[1] * coord[1]) + (coord[2] * coord[2])); - if (length != 1) { - coord[0] = (coord[0] / length); - coord[1] = (coord[1] / length); - coord[2] = (coord[2] / length); - } - } - -private: - union { - float coord[3]; - struct { - float x, y, z; - }; - }; -}; - -class MaterialReader { -public: - MaterialReader() {} - virtual ~MaterialReader(); - - virtual bool operator()(const std::string &matId, - std::vector &materials, - std::map &matMap, - std::string &err) = 0; -}; - -class MaterialFileReader : public MaterialReader { -public: - MaterialFileReader(const std::string &mtl_basepath) - : m_mtlBasePath(mtl_basepath) {} - virtual ~MaterialFileReader() {} - virtual bool operator()(const std::string &matId, - std::vector &materials, - std::map &matMap, std::string &err); - -private: - std::string m_mtlBasePath; -}; - -/// Loads .obj from a file. -/// 'shapes' will be filled with parsed shape data -/// The function returns error string. -/// Returns true when loading .obj become success. -/// Returns warning and error message into `err` -/// 'mtl_basepath' is optional, and used for base path for .mtl file. -/// 'optional flags -bool LoadObj(std::vector &shapes, // [output] - std::vector &materials, // [output] - std::string &err, // [output] - const char *filename, const char *mtl_basepath = NULL, - unsigned int flags = 1); - -/// Loads object from a std::istream, uses GetMtlIStreamFn to retrieve -/// std::istream for materials. -/// Returns true when loading .obj become success. -/// Returns warning and error message into `err` -bool LoadObj(std::vector &shapes, // [output] - std::vector &materials, // [output] - std::string &err, // [output] - std::istream &inStream, MaterialReader &readMatFn, - unsigned int flags = 1); - -/// Loads materials into std::map -void LoadMtl(std::map &material_map, // [output] - std::vector &materials, // [output] - std::istream &inStream); -} - -#ifdef TINYOBJLOADER_IMPLEMENTATION -#include -#include -#include -#include -#include -#include - -#include -#include - -//#include "tiny_obj_loader.h" - -namespace tinyobj { - -MaterialReader::~MaterialReader() {} - -#define TINYOBJ_SSCANF_BUFFER_SIZE (4096) - -struct vertex_index { - int v_idx, vt_idx, vn_idx; - vertex_index() : v_idx(-1), vt_idx(-1), vn_idx(-1) {} - explicit vertex_index(int idx) : v_idx(idx), vt_idx(idx), vn_idx(idx) {} - vertex_index(int vidx, int vtidx, int vnidx) - : v_idx(vidx), vt_idx(vtidx), vn_idx(vnidx) {} -}; - -struct tag_sizes { - tag_sizes() : num_ints(0), num_floats(0), num_strings(0) {} - int num_ints; - int num_floats; - int num_strings; -}; - -// for std::map -static inline bool operator<(const vertex_index &a, const vertex_index &b) { - if (a.v_idx != b.v_idx) - return (a.v_idx < b.v_idx); - if (a.vn_idx != b.vn_idx) - return (a.vn_idx < b.vn_idx); - if (a.vt_idx != b.vt_idx) - return (a.vt_idx < b.vt_idx); - - return false; -} - -struct obj_shape { - std::vector v; - std::vector vn; - std::vector vt; -}; - -// See -// http://stackoverflow.com/questions/6089231/getting-std-ifstream-to-handle-lf-cr-and-crlf -std::istream &safeGetline(std::istream &is, std::string &t) { - t.clear(); - - // The characters in the stream are read one-by-one using a std::streambuf. - // That is faster than reading them one-by-one using the std::istream. - // Code that uses streambuf this way must be guarded by a sentry object. - // The sentry object performs various tasks, - // such as thread synchronization and updating the stream state. - - std::istream::sentry se(is, true); - std::streambuf *sb = is.rdbuf(); - - for (;;) { - int c = sb->sbumpc(); - switch (c) { - case '\n': - return is; - case '\r': - if (sb->sgetc() == '\n') - sb->sbumpc(); - return is; - case EOF: - // Also handle the case when the last line has no line ending - if (t.empty()) - is.setstate(std::ios::eofbit); - return is; - default: - t += (char)c; - } - } -} - -#define IS_SPACE(x) (((x) == ' ') || ((x) == '\t')) -#define IS_DIGIT(x) ((unsigned int)((x) - '0') < (unsigned int)10) -#define IS_NEW_LINE(x) (((x) == '\r') || ((x) == '\n') || ((x) == '\0')) - -// Make index zero-base, and also support relative index. -static inline int fixIndex(int idx, int n) { - if (idx > 0) - return idx - 1; - if (idx == 0) - return 0; - return n + idx; // negative value = relative -} - -static inline std::string parseString(const char *&token) { - std::string s; - token += strspn(token, " \t"); - size_t e = strcspn(token, " \t\r"); - s = std::string(token, &token[e]); - token += e; - return s; -} - -static inline int parseInt(const char *&token) { - token += strspn(token, " \t"); - int i = atoi(token); - token += strcspn(token, " \t\r"); - return i; -} - -// Tries to parse a floating point number located at s. -// -// s_end should be a location in the string where reading should absolutely -// stop. For example at the end of the string, to prevent buffer overflows. -// -// Parses the following EBNF grammar: -// sign = "+" | "-" ; -// END = ? anything not in digit ? -// digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; -// integer = [sign] , digit , {digit} ; -// decimal = integer , ["." , integer] ; -// float = ( decimal , END ) | ( decimal , ("E" | "e") , integer , END ) ; -// -// Valid strings are for example: -// -0 +3.1417e+2 -0.0E-3 1.0324 -1.41 11e2 -// -// If the parsing is a success, result is set to the parsed value and true -// is returned. -// -// The function is greedy and will parse until any of the following happens: -// - a non-conforming character is encountered. -// - s_end is reached. -// -// The following situations triggers a failure: -// - s >= s_end. -// - parse failure. -// -static bool tryParseDouble(const char *s, const char *s_end, double *result) { - if (s >= s_end) { - return false; - } - - double mantissa = 0.0; - // This exponent is base 2 rather than 10. - // However the exponent we parse is supposed to be one of ten, - // thus we must take care to convert the exponent/and or the - // mantissa to a * 2^E, where a is the mantissa and E is the - // exponent. - // To get the final double we will use ldexp, it requires the - // exponent to be in base 2. - int exponent = 0; - - // NOTE: THESE MUST BE DECLARED HERE SINCE WE ARE NOT ALLOWED - // TO JUMP OVER DEFINITIONS. - char sign = '+'; - char exp_sign = '+'; - char const *curr = s; - - // How many characters were read in a loop. - int read = 0; - // Tells whether a loop terminated due to reaching s_end. - bool end_not_reached = false; - - /* - BEGIN PARSING. - */ - - // Find out what sign we've got. - if (*curr == '+' || *curr == '-') { - sign = *curr; - curr++; - } else if (IS_DIGIT(*curr)) { /* Pass through. */ - } else { - goto fail; - } - - // Read the integer part. - while ((end_not_reached = (curr != s_end)) && IS_DIGIT(*curr)) { - mantissa *= 10; - mantissa += static_cast(*curr - 0x30); - curr++; - read++; - } - - // We must make sure we actually got something. - if (read == 0) - goto fail; - // We allow numbers of form "#", "###" etc. - if (!end_not_reached) - goto assemble; - - // Read the decimal part. - if (*curr == '.') { - curr++; - read = 1; - while ((end_not_reached = (curr != s_end)) && IS_DIGIT(*curr)) { - // NOTE: Don't use powf here, it will absolutely murder precision. - mantissa += static_cast(*curr - 0x30) * pow(10.0, -read); - read++; - curr++; - } - } else if (*curr == 'e' || *curr == 'E') { - } else { - goto assemble; - } - - if (!end_not_reached) - goto assemble; - - // Read the exponent part. - if (*curr == 'e' || *curr == 'E') { - curr++; - // Figure out if a sign is present and if it is. - if ((end_not_reached = (curr != s_end)) && (*curr == '+' || *curr == '-')) { - exp_sign = *curr; - curr++; - } else if (IS_DIGIT(*curr)) { /* Pass through. */ - } else { - // Empty E is not allowed. - goto fail; - } - - read = 0; - while ((end_not_reached = (curr != s_end)) && IS_DIGIT(*curr)) { - exponent *= 10; - exponent += static_cast(*curr - 0x30); - curr++; - read++; - } - exponent *= (exp_sign == '+' ? 1 : -1); - if (read == 0) - goto fail; - } - -assemble: - *result = - (sign == '+' ? 1 : -1) * ldexp(mantissa * pow(5.0, exponent), exponent); - return true; -fail: - return false; -} -static inline float parseFloat(const char *&token) { - token += strspn(token, " \t"); -#ifdef TINY_OBJ_LOADER_OLD_FLOAT_PARSER - float f = (float)atof(token); - token += strcspn(token, " \t\r"); -#else - const char *end = token + strcspn(token, " \t\r"); - double val = 0.0; - tryParseDouble(token, end, &val); - float f = static_cast(val); - token = end; -#endif - return f; -} - -static inline void parseFloat2(float &x, float &y, const char *&token) { - x = parseFloat(token); - y = parseFloat(token); -} - -static inline void parseFloat3(float &x, float &y, float &z, - const char *&token) { - x = parseFloat(token); - y = parseFloat(token); - z = parseFloat(token); -} - -static tag_sizes parseTagTriple(const char *&token) { - tag_sizes ts; - - ts.num_ints = atoi(token); - token += strcspn(token, "/ \t\r"); - if (token[0] != '/') { - return ts; - } - token++; - - ts.num_floats = atoi(token); - token += strcspn(token, "/ \t\r"); - if (token[0] != '/') { - return ts; - } - token++; - - ts.num_strings = atoi(token); - token += strcspn(token, "/ \t\r") + 1; - - return ts; -} - -// Parse triples: i, i/j/k, i//k, i/j -static vertex_index parseTriple(const char *&token, int vsize, int vnsize, - int vtsize) { - vertex_index vi(-1); - - vi.v_idx = fixIndex(atoi(token), vsize); - token += strcspn(token, "/ \t\r"); - if (token[0] != '/') { - return vi; - } - token++; - - // i//k - if (token[0] == '/') { - token++; - vi.vn_idx = fixIndex(atoi(token), vnsize); - token += strcspn(token, "/ \t\r"); - return vi; - } - - // i/j/k or i/j - vi.vt_idx = fixIndex(atoi(token), vtsize); - token += strcspn(token, "/ \t\r"); - if (token[0] != '/') { - return vi; - } - - // i/j/k - token++; // skip '/' - vi.vn_idx = fixIndex(atoi(token), vnsize); - token += strcspn(token, "/ \t\r"); - return vi; -} - -static unsigned int -updateVertex(std::map &vertexCache, - std::vector &positions, std::vector &normals, - std::vector &texcoords, - const std::vector &in_positions, - const std::vector &in_normals, - const std::vector &in_texcoords, const vertex_index &i) { - const std::map::iterator it = vertexCache.find(i); - - if (it != vertexCache.end()) { - // found cache - return it->second; - } - - assert(in_positions.size() > static_cast(3 * i.v_idx + 2)); - - positions.push_back(in_positions[3 * static_cast(i.v_idx) + 0]); - positions.push_back(in_positions[3 * static_cast(i.v_idx) + 1]); - positions.push_back(in_positions[3 * static_cast(i.v_idx) + 2]); - - if ((i.vn_idx >= 0) && - (static_cast(i.vn_idx * 3 + 2) < in_normals.size())) { - normals.push_back(in_normals[3 * static_cast(i.vn_idx) + 0]); - normals.push_back(in_normals[3 * static_cast(i.vn_idx) + 1]); - normals.push_back(in_normals[3 * static_cast(i.vn_idx) + 2]); - } - - if ((i.vt_idx >= 0) && - (static_cast(i.vt_idx * 2 + 1) < in_texcoords.size())) { - texcoords.push_back(in_texcoords[2 * static_cast(i.vt_idx) + 0]); - texcoords.push_back(in_texcoords[2 * static_cast(i.vt_idx) + 1]); - } - - unsigned int idx = static_cast(positions.size() / 3 - 1); - vertexCache[i] = idx; - - return idx; -} - -static void InitMaterial(material_t &material) { - material.name = ""; - material.ambient_texname = ""; - material.diffuse_texname = ""; - material.specular_texname = ""; - material.specular_highlight_texname = ""; - material.bump_texname = ""; - material.displacement_texname = ""; - material.alpha_texname = ""; - for (int i = 0; i < 3; i++) { - material.ambient[i] = 0.f; - material.diffuse[i] = 0.f; - material.specular[i] = 0.f; - material.transmittance[i] = 0.f; - material.emission[i] = 0.f; - } - material.illum = 0; - material.dissolve = 1.f; - material.shininess = 1.f; - material.ior = 1.f; - material.unknown_parameter.clear(); -} - -static bool exportFaceGroupToShape( - shape_t &shape, std::map vertexCache, - const std::vector &in_positions, - const std::vector &in_normals, - const std::vector &in_texcoords, - const std::vector > &faceGroup, - std::vector &tags, const int material_id, const std::string &name, - bool clearCache, unsigned int flags, std::string &err) { - if (faceGroup.empty()) { - return false; - } - - bool triangulate((flags & triangulation) == triangulation); - bool normals_calculation((flags & calculate_normals) == calculate_normals); - - // Flatten vertices and indices - for (size_t i = 0; i < faceGroup.size(); i++) { - const std::vector &face = faceGroup[i]; - - vertex_index i0 = face[0]; - vertex_index i1(-1); - vertex_index i2 = face[1]; - - size_t npolys = face.size(); - - if (triangulate) { - - // Polygon -> triangle fan conversion - for (size_t k = 2; k < npolys; k++) { - i1 = i2; - i2 = face[k]; - - unsigned int v0 = updateVertex( - vertexCache, shape.mesh.positions, shape.mesh.normals, - shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i0); - unsigned int v1 = updateVertex( - vertexCache, shape.mesh.positions, shape.mesh.normals, - shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i1); - unsigned int v2 = updateVertex( - vertexCache, shape.mesh.positions, shape.mesh.normals, - shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i2); - - shape.mesh.indices.push_back(v0); - shape.mesh.indices.push_back(v1); - shape.mesh.indices.push_back(v2); - - shape.mesh.num_vertices.push_back(3); - shape.mesh.material_ids.push_back(material_id); - } - } else { - - for (size_t k = 0; k < npolys; k++) { - unsigned int v = - updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, - shape.mesh.texcoords, in_positions, in_normals, - in_texcoords, face[k]); - - shape.mesh.indices.push_back(v); - } - - shape.mesh.num_vertices.push_back(static_cast(npolys)); - shape.mesh.material_ids.push_back(material_id); // per face - } - } - - if (normals_calculation && shape.mesh.normals.empty()) { - const size_t nIndexs = shape.mesh.indices.size(); - if (nIndexs % 3 == 0) { - shape.mesh.normals.resize(shape.mesh.positions.size()); - for (size_t iIndices = 0; iIndices < nIndexs; iIndices += 3) { - float3 v1, v2, v3; - memcpy(&v1, &shape.mesh.positions[shape.mesh.indices[iIndices] * 3], - sizeof(float3)); - memcpy(&v2, &shape.mesh.positions[shape.mesh.indices[iIndices + 1] * 3], - sizeof(float3)); - memcpy(&v3, &shape.mesh.positions[shape.mesh.indices[iIndices + 2] * 3], - sizeof(float3)); - - float3 v12(v1, v2); - float3 v13(v1, v3); - - float3 normal = v12.crossproduct(v13); - normal.normalize(); - - memcpy(&shape.mesh.normals[shape.mesh.indices[iIndices] * 3], &normal, - sizeof(float3)); - memcpy(&shape.mesh.normals[shape.mesh.indices[iIndices + 1] * 3], - &normal, sizeof(float3)); - memcpy(&shape.mesh.normals[shape.mesh.indices[iIndices + 2] * 3], - &normal, sizeof(float3)); - } - } else { - - std::stringstream ss; - ss << "WARN: The shape " << name - << " does not have a topology of triangles, therfore the normals " - "calculation could not be performed. Select the " - "tinyobj::triangulation flag for this object." - << std::endl; - err += ss.str(); - } - } - - shape.name = name; - shape.mesh.tags.swap(tags); - - if (clearCache) - vertexCache.clear(); - - return true; -} - -void LoadMtl(std::map &material_map, - std::vector &materials, std::istream &inStream) { - - // Create a default material anyway. - material_t material; - InitMaterial(material); - - while (inStream.peek() != -1) { - std::string linebuf; - safeGetline(inStream, linebuf); - - // Trim trailing whitespace - if (linebuf.size() > 0) { - linebuf = linebuf.substr(0, linebuf.find_last_not_of(" \t") + 1); - } - - // Trim newline '\r\n' or '\n' - if (linebuf.size() > 0) { - if (linebuf[linebuf.size() - 1] == '\n') - linebuf.erase(linebuf.size() - 1); - } - if (linebuf.size() > 0) { - if (linebuf[linebuf.size() - 1] == '\r') - linebuf.erase(linebuf.size() - 1); - } - - // Skip if empty line. - if (linebuf.empty()) { - continue; - } - - // Skip leading space. - const char *token = linebuf.c_str(); - token += strspn(token, " \t"); - - assert(token); - if (token[0] == '\0') - continue; // empty line - - if (token[0] == '#') - continue; // comment line - - // new mtl - if ((0 == strncmp(token, "newmtl", 6)) && IS_SPACE((token[6]))) { - // flush previous material. - if (!material.name.empty()) { - material_map.insert(std::pair( - material.name, static_cast(materials.size()))); - materials.push_back(material); - } - - // initial temporary material - InitMaterial(material); - - // set new mtl name - char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; - token += 7; -#ifdef _MSC_VER - sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); -#else - sscanf(token, "%s", namebuf); -#endif - material.name = namebuf; - continue; - } - - // ambient - if (token[0] == 'K' && token[1] == 'a' && IS_SPACE((token[2]))) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.ambient[0] = r; - material.ambient[1] = g; - material.ambient[2] = b; - continue; - } - - // diffuse - if (token[0] == 'K' && token[1] == 'd' && IS_SPACE((token[2]))) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.diffuse[0] = r; - material.diffuse[1] = g; - material.diffuse[2] = b; - continue; - } - - // specular - if (token[0] == 'K' && token[1] == 's' && IS_SPACE((token[2]))) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.specular[0] = r; - material.specular[1] = g; - material.specular[2] = b; - continue; - } - - // transmittance - if (token[0] == 'K' && token[1] == 't' && IS_SPACE((token[2]))) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.transmittance[0] = r; - material.transmittance[1] = g; - material.transmittance[2] = b; - continue; - } - - // ior(index of refraction) - if (token[0] == 'N' && token[1] == 'i' && IS_SPACE((token[2]))) { - token += 2; - material.ior = parseFloat(token); - continue; - } - - // emission - if (token[0] == 'K' && token[1] == 'e' && IS_SPACE(token[2])) { - token += 2; - float r, g, b; - parseFloat3(r, g, b, token); - material.emission[0] = r; - material.emission[1] = g; - material.emission[2] = b; - continue; - } - - // shininess - if (token[0] == 'N' && token[1] == 's' && IS_SPACE(token[2])) { - token += 2; - material.shininess = parseFloat(token); - continue; - } - - // illum model - if (0 == strncmp(token, "illum", 5) && IS_SPACE(token[5])) { - token += 6; - material.illum = parseInt(token); - continue; - } - - // dissolve - if ((token[0] == 'd' && IS_SPACE(token[1]))) { - token += 1; - material.dissolve = parseFloat(token); - continue; - } - if (token[0] == 'T' && token[1] == 'r' && IS_SPACE(token[2])) { - token += 2; - // Invert value of Tr(assume Tr is in range [0, 1]) - material.dissolve = 1.0f - parseFloat(token); - continue; - } - - // ambient texture - if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { - token += 7; - material.ambient_texname = token; - continue; - } - - // diffuse texture - if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { - token += 7; - material.diffuse_texname = token; - continue; - } - - // specular texture - if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { - token += 7; - material.specular_texname = token; - continue; - } - - // specular highlight texture - if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { - token += 7; - material.specular_highlight_texname = token; - continue; - } - - // bump texture - if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { - token += 9; - material.bump_texname = token; - continue; - } - - // alpha texture - if ((0 == strncmp(token, "map_d", 5)) && IS_SPACE(token[5])) { - token += 6; - material.alpha_texname = token; - continue; - } - - // bump texture - if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { - token += 5; - material.bump_texname = token; - continue; - } - - // displacement texture - if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { - token += 5; - material.displacement_texname = token; - continue; - } - - // unknown parameter - const char *_space = strchr(token, ' '); - if (!_space) { - _space = strchr(token, '\t'); - } - if (_space) { - std::ptrdiff_t len = _space - token; - std::string key(token, static_cast(len)); - std::string value = _space + 1; - material.unknown_parameter.insert( - std::pair(key, value)); - } - } - // flush last material. - material_map.insert(std::pair( - material.name, static_cast(materials.size()))); - materials.push_back(material); -} - -bool MaterialFileReader::operator()(const std::string &matId, - std::vector &materials, - std::map &matMap, - std::string &err) { - std::string filepath; - - if (!m_mtlBasePath.empty()) { - filepath = std::string(m_mtlBasePath) + matId; - } else { - filepath = matId; - } - - std::ifstream matIStream(filepath.c_str()); - LoadMtl(matMap, materials, matIStream); - if (!matIStream) { - std::stringstream ss; - ss << "WARN: Material file [ " << filepath - << " ] not found. Created a default material."; - err += ss.str(); - } - return true; -} - -bool LoadObj(std::vector &shapes, // [output] - std::vector &materials, // [output] - std::string &err, const char *filename, const char *mtl_basepath, - unsigned int flags) { - - shapes.clear(); - - std::stringstream errss; - - std::ifstream ifs(filename); - if (!ifs) { - errss << "Cannot open file [" << filename << "]" << std::endl; - err = errss.str(); - return false; - } - - std::string basePath; - if (mtl_basepath) { - basePath = mtl_basepath; - } - MaterialFileReader matFileReader(basePath); - - return LoadObj(shapes, materials, err, ifs, matFileReader, flags); -} - -bool LoadObj(std::vector &shapes, // [output] - std::vector &materials, // [output] - std::string &err, std::istream &inStream, - MaterialReader &readMatFn, unsigned int flags) { - - std::stringstream errss; - - std::vector v; - std::vector vn; - std::vector vt; - std::vector tags; - std::vector > faceGroup; - std::string name; - - // material - std::map material_map; - std::map vertexCache; - int material = -1; - - shape_t shape; - - while (inStream.peek() != -1) { - std::string linebuf; - safeGetline(inStream, linebuf); - - // Trim newline '\r\n' or '\n' - if (linebuf.size() > 0) { - if (linebuf[linebuf.size() - 1] == '\n') - linebuf.erase(linebuf.size() - 1); - } - if (linebuf.size() > 0) { - if (linebuf[linebuf.size() - 1] == '\r') - linebuf.erase(linebuf.size() - 1); - } - - // Skip if empty line. - if (linebuf.empty()) { - continue; - } - - // Skip leading space. - const char *token = linebuf.c_str(); - token += strspn(token, " \t"); - - assert(token); - if (token[0] == '\0') - continue; // empty line - - if (token[0] == '#') - continue; // comment line - - // vertex - if (token[0] == 'v' && IS_SPACE((token[1]))) { - token += 2; - float x, y, z; - parseFloat3(x, y, z, token); - v.push_back(x); - v.push_back(y); - v.push_back(z); - continue; - } - - // normal - if (token[0] == 'v' && token[1] == 'n' && IS_SPACE((token[2]))) { - token += 3; - float x, y, z; - parseFloat3(x, y, z, token); - vn.push_back(x); - vn.push_back(y); - vn.push_back(z); - continue; - } - - // texcoord - if (token[0] == 'v' && token[1] == 't' && IS_SPACE((token[2]))) { - token += 3; - float x, y; - parseFloat2(x, y, token); - vt.push_back(x); - vt.push_back(y); - continue; - } - - // face - if (token[0] == 'f' && IS_SPACE((token[1]))) { - token += 2; - token += strspn(token, " \t"); - - std::vector face; - face.reserve(3); - - while (!IS_NEW_LINE(token[0])) { - vertex_index vi = parseTriple(token, static_cast(v.size() / 3), - static_cast(vn.size() / 3), - static_cast(vt.size() / 2)); - face.push_back(vi); - size_t n = strspn(token, " \t\r"); - token += n; - } - - // replace with emplace_back + std::move on C++11 - faceGroup.push_back(std::vector()); - faceGroup[faceGroup.size() - 1].swap(face); - - continue; - } - - // use mtl - if ((0 == strncmp(token, "usemtl", 6)) && IS_SPACE((token[6]))) { - - char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; - token += 7; -#ifdef _MSC_VER - sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); -#else - sscanf(token, "%s", namebuf); -#endif - - int newMaterialId = -1; - if (material_map.find(namebuf) != material_map.end()) { - newMaterialId = material_map[namebuf]; - } else { - // { error!! material not found } - } - - if (newMaterialId != material) { - // Create per-face material - exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags, - material, name, true, flags, err); - faceGroup.clear(); - material = newMaterialId; - } - - continue; - } - - // load mtl - if ((0 == strncmp(token, "mtllib", 6)) && IS_SPACE((token[6]))) { - char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; - token += 7; -#ifdef _MSC_VER - sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); -#else - sscanf(token, "%s", namebuf); -#endif - - std::string err_mtl; - bool ok = readMatFn(namebuf, materials, material_map, err_mtl); - err += err_mtl; - - if (!ok) { - faceGroup.clear(); // for safety - return false; - } - - continue; - } - - // group name - if (token[0] == 'g' && IS_SPACE((token[1]))) { - - // flush previous face group. - bool ret = - exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags, - material, name, true, flags, err); - if (ret) { - shapes.push_back(shape); - } - - shape = shape_t(); - - // material = -1; - faceGroup.clear(); - - std::vector names; - names.reserve(2); - - while (!IS_NEW_LINE(token[0])) { - std::string str = parseString(token); - names.push_back(str); - token += strspn(token, " \t\r"); // skip tag - } - - assert(names.size() > 0); - - // names[0] must be 'g', so skip the 0th element. - if (names.size() > 1) { - name = names[1]; - } else { - name = ""; - } - - continue; - } - - // object name - if (token[0] == 'o' && IS_SPACE((token[1]))) { - - // flush previous face group. - bool ret = - exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, tags, - material, name, true, flags, err); - if (ret) { - shapes.push_back(shape); - } - - // material = -1; - faceGroup.clear(); - shape = shape_t(); - - // @todo { multiple object name? } - char namebuf[TINYOBJ_SSCANF_BUFFER_SIZE]; - token += 2; -#ifdef _MSC_VER - sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); -#else - sscanf(token, "%s", namebuf); -#endif - name = std::string(namebuf); - - continue; - } - - if (token[0] == 't' && IS_SPACE(token[1])) { - tag_t tag; - - char namebuf[4096]; - token += 2; -#ifdef _MSC_VER - sscanf_s(token, "%s", namebuf, (unsigned)_countof(namebuf)); -#else - sscanf(token, "%s", namebuf); -#endif - tag.name = std::string(namebuf); - - token += tag.name.size() + 1; - - tag_sizes ts = parseTagTriple(token); - - tag.intValues.resize(static_cast(ts.num_ints)); - - for (size_t i = 0; i < static_cast(ts.num_ints); ++i) { - tag.intValues[i] = atoi(token); - token += strcspn(token, "/ \t\r") + 1; - } - - tag.floatValues.resize(static_cast(ts.num_floats)); - for (size_t i = 0; i < static_cast(ts.num_floats); ++i) { - tag.floatValues[i] = parseFloat(token); - token += strcspn(token, "/ \t\r") + 1; - } - - tag.stringValues.resize(static_cast(ts.num_strings)); - for (size_t i = 0; i < static_cast(ts.num_strings); ++i) { - char stringValueBuffer[4096]; - -#ifdef _MSC_VER - sscanf_s(token, "%s", stringValueBuffer, - (unsigned)_countof(stringValueBuffer)); -#else - sscanf(token, "%s", stringValueBuffer); -#endif - tag.stringValues[i] = stringValueBuffer; - token += tag.stringValues[i].size() + 1; - } - - tags.push_back(tag); - } - - // Ignore unknown command. - } - - bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, - tags, material, name, true, flags, err); - if (ret) { - shapes.push_back(shape); - } - faceGroup.clear(); // for safety - - err += errss.str(); - - return true; -} - -} // namespace - -#endif - -#endif // TINY_OBJ_LOADER_H_ diff --git a/tools/MAKE_assimp.bat b/tools/MAKE_assimp.bat new file mode 100644 index 0000000..4d74cab --- /dev/null +++ b/tools/MAKE_assimp.bat @@ -0,0 +1,35 @@ +#!/bin/bash 2>nul || goto :windows + +# linux + osx ----------------------------------------------------------------- +cd `dirname $0` + +git clone https://github.com/assimp/assimp && cd assimp && git checkout 05115b07 +cmake -DCMAKE_BUILD_TYPE=Release -DASSIMP_BUILD_TESTS=OFF . +make -j 8 +cp bin/libassimp.so ../libassimp.so +cp bin/libassimp.so ../libassimp.so.5 +cp bin/libassimp.so ../libassimp.so.5.1.4 +cp bin/libassimp.dylib ../libassimp.dylib +cp bin/libassimp.dylib ../libassimp.5.dylib +cp bin/libassimp.dylib ../libassimp.5.0.1.dylib +cd .. + +cc ass2iqe.c -o ass2iqe.linux -O2 -I assimp/include/ libassimp.so -lm +cc ass2iqe.c -o ass2iqe.osx -O2 -I assimp/include/ libassimp.dylib -lm + +exit + + +:windows ----------------------------------------------------------------------- +@echo off +cd "%~dp0" + +git clone https://github.com/assimp/assimp && md assimp\.build && pushd assimp\.build && git checkout 05115b07 +cmake .. -DCMAKE_BUILD_TYPE=Release && (make || msbuild assimp.sln -m -p:Configuration=Release) +popd + +xcopy /y assimp\.build\bin\release\*.dll +xcopy /y assimp\.build\lib\release\*.lib + +copy /y assimp\include\assimp\config.h.in assimp\config.h && fart -- assimp\config.h "cmakedefine" "//#define" +cl ass2iqe.c -I . -I assimp\include assimp-vc14?-mt.lib /O2 /Oy /MT /DNDEBUG diff --git a/tools/MAKE_glslcc.bat b/tools/MAKE_glslcc.bat new file mode 100644 index 0000000..638f758 --- /dev/null +++ b/tools/MAKE_glslcc.bat @@ -0,0 +1,24 @@ +#!/bin/bash 2>nul || goto :windows + +# linux + osx ----------------------------------------------------------------- +cd `dirname $0` + +git clone https://github.com/septag/glslcc && mkdir glslcc/.build +cd glslcc/.build +cmake .. -B . -DCMAKE_BUILD_TYPE=Release +make -j 8 +# cp -f glslcc/.build/src/Release/glslcc.exe . +cd ".." + +exit + + +:windows ----------------------------------------------------------------------- +@echo off +cd "%~dp0" + +git clone https://github.com/septag/glslcc && md glslcc\.build && pushd glslcc\.build +cmake .. -B . -DCMAKE_BUILD_TYPE=Release && (make || msbuild glslcc.sln -m -p:Configuration=Release) +popd + +xcopy /y glslcc\.build\src\Release\glslcc.exe \ No newline at end of file diff --git a/tools/_manifest.lua b/tools/_manifest.lua deleted file mode 100644 index 31fb223..0000000 --- a/tools/_manifest.lua +++ /dev/null @@ -1,4 +0,0 @@ -return { - "_preload.lua", - "ninja.lua", -} diff --git a/tools/_preload.lua b/tools/_preload.lua deleted file mode 100644 index a3a426f..0000000 --- a/tools/_preload.lua +++ /dev/null @@ -1,61 +0,0 @@ --- --- Name: premake-ninja/_preload.lua --- Purpose: Define the ninja action. --- Author: Dmitry Ivanov --- Created: 2015/07/04 --- Copyright: (c) 2015 Dmitry Ivanov --- - - local p = premake - - newaction - { - -- Metadata for the command line and help system - trigger = "ninja", - shortname = "ninja", - description = "Ninja is a small build system with a focus on speed", - - -- The capabilities of this action - valid_kinds = {"ConsoleApp", "WindowedApp", "SharedLib", "StaticLib", "None"}, -- Not supported: Makefile, Packaging, SharedItems, Utility - valid_languages = {"C", "C++"}, - valid_tools = {cc = { "gcc", "clang", "msc" }}, - - toolset = iif(os.target() == "windows", "msc-v142", -- Visual Studio 2019 - iif(os.target() == "macosx", "clang", - "gcc")), - - -- Workspace and project generation logic - onWorkspace = function(wks) - p.eol("\r\n") - p.indent(" ") - p.generate(wks, "build.ninja", p.modules.ninja.generateWorkspace) - end, - onProject = function(prj) - p.eol("\r\n") - p.indent(" ") - p.modules.ninja.generateProject(prj) - end, - onBranch = function(prj) - p.eol("\r\n") - p.indent(" ") - p.modules.ninja.generateProject(prj) - end, - onCleanSolution = function(sln) - -- TODO - end, - onCleanProject = function(prj) - -- TODO - end, - onCleanTarget = function(prj) - -- TODO - end, - } - - --- --- Decide when the full module should be loaded. --- - - return function(cfg) - return (_ACTION == "ninja") - end diff --git a/tools/ass2iqe.exe b/tools/ass2iqe.exe index 0ba5d64..a71607e 100644 Binary files a/tools/ass2iqe.exe and b/tools/ass2iqe.exe differ diff --git a/tools/ass2iqe.linux b/tools/ass2iqe.linux index e2659f3..ec0be59 100644 Binary files a/tools/ass2iqe.linux and b/tools/ass2iqe.linux differ diff --git a/tools/assimp-vc143-mt.dll b/tools/assimp-vc143-mt.dll index 9f54f8c..337a656 100644 Binary files a/tools/assimp-vc143-mt.dll and b/tools/assimp-vc143-mt.dll differ diff --git a/tools/color2trans.c b/tools/color2trans.c deleted file mode 100644 index ee4760a..0000000 --- a/tools/color2trans.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "v4k.h" - -int main() { - if (argc() < 3) { - printf("%s [color] [trans]\n", argv(0)); - return 1; - } - - FILE *f = fopen(argv(1), "rb"); - if (!f) { - printf("File not found.\n"); - return 2; - } - - //stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); - int x, y, bpp; - char *buf = stbi_load_from_file() - - return 0; -} \ No newline at end of file diff --git a/tools/cook.c b/tools/cook.c index 101d2ca..6ebfa4b 100644 --- a/tools/cook.c +++ b/tools/cook.c @@ -1,7 +1,7 @@ #define V4K_IMPLEMENTATION #define COOK_ON_DEMAND 0 #define COOK_FROM_TERMINAL 1 -#include "../engine/joint/v4k.h" +#include "joint/v4k.h" int main(int argc, const char **argv) { double timer = time_ss(); @@ -30,7 +30,7 @@ int main(int argc, const char **argv) { } // compiled with: -// tcc cook.c -// cl cook.c /openmp /Os /Ox /O2 /Oy /MT /DNDEBUG /GL /GF /Gw /arch:AVX2 /link /OPT:ICF /LTCG -// cc -ObjC cook.c -o cook.osx -framework Cocoa -framework IOKit -framework audiotoolbox -O3 -// cc cook.c -o cook.linux -lm -lpthread -ldl -lX11 -O3 +// tcc cook.c -I..\engine +// cl cook.c -I..\engine /openmp /Os /Ox /O2 /Oy /MT /DNDEBUG /GL /GF /Gw /arch:AVX2 /link /OPT:ICF /LTCG +// cc -ObjC cook.c -I../engine -o cook.osx -framework Cocoa -framework IOKit -framework audiotoolbox -O3 +// cc cook.c -I../engine -o cook.linux -lm -lpthread -ldl -lX11 -O3 diff --git a/tools/cook.exe b/tools/cook.exe index c24498f..fc373e5 100644 Binary files a/tools/cook.exe and b/tools/cook.exe differ diff --git a/tools/cook.linux b/tools/cook.linux index b2411f0..14fa12e 100644 Binary files a/tools/cook.linux and b/tools/cook.linux differ diff --git a/tools/editor/3rd_lite.h b/tools/editor/3rd_lite.h new file mode 100644 index 0000000..bbffabe --- /dev/null +++ b/tools/editor/3rd_lite.h @@ -0,0 +1,1152 @@ +// Copyright (c) 2020 rxi +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// [doc] https://rxi.github.io/lite_an_implementation_overview.html +// [chg] differences from https://github.com/rxi/lite listed below: +// +// a) amalgamated as single-file source. +// b) platform agnostic now (no more specific SDL calls; tested with GLFW backend). +// c) specific `lt_` platform bits have been moved out to an external file (lite_sys.h) +// d) lua, stb-truetype and lite_sys headers *must be included* beforehand. +// e) embeddable: reverted loop handler from framework to library mode. see: lt_init/lt_tick +// f) data folders reorganized as data/themes, data/languages/ and data/plugins/. +// g) DATADIR path can be specified now and no longer forced to be EXEDIR/data/. +// h) packaged with a bunch of handy plugins from https://github.com/rxi/lite-plugins +// i) packaged with all color themes from https://github.com/rxi/lite-colors +// j) merged a few pending PRs and pending fixes from original repo. +// k) Lua sources fixed for Lua >= 5.2 +// +// All contributions released under same MIT licensing terms than original code. +// - rlyeh. + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef S_ISDIR +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif + +// ---------------------------------------------------------------------------- +// lite/api.h + +#define API_TYPE_FONT "Font" + +// ---------------------------------------------------------------------------- +// lite/renderer.h + +typedef struct RenImage RenImage; +typedef struct RenFont RenFont; + +typedef struct { uint8_t b, g, r, a; } RenColor; +//typedef struct { int x, y, width, height; } RenRect; +typedef lt_rect RenRect; + + +void ren_init(void *win); +void ren_update_rects(RenRect *rects, int count); +void ren_set_clip_rect(RenRect rect); +void ren_get_size(int *x, int *y); + +RenImage* ren_new_image(int width, int height); +void ren_free_image(RenImage *image); + +RenFont* ren_load_font(const char *filename, float size); +void ren_free_font(RenFont *font); +void ren_set_font_tab_width(RenFont *font, int n); +int ren_get_font_tab_width(RenFont *font); +int ren_get_font_width(RenFont *font, const char *text); +int ren_get_font_height(RenFont *font); + +void ren_draw_rect(RenRect rect, RenColor color); +void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color); +int ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color); + +// ---------------------------------------------------------------------------- +// lite/rencache.h + +void rencache_show_debug(bool enable); +void rencache_free_font(RenFont *font); +void rencache_set_clip_rect(RenRect rect); +void rencache_draw_rect(RenRect rect, RenColor color); +int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color); +void rencache_invalidate(void); +void rencache_begin_frame(void); +void rencache_end_frame(void); + +// ---------------------------------------------------------------------------- +// lite/renderer.c + +#define MAX_GLYPHSET 256 + +struct RenImage { + RenColor *pixels; + int width, height; +}; + +typedef struct { + RenImage *image; + stbtt_bakedchar glyphs[256]; +} GlyphSet; + +struct RenFont { + void *data; + stbtt_fontinfo stbfont; + GlyphSet *sets[MAX_GLYPHSET]; + float size; + int height; +}; + +static struct { int left, top, right, bottom; } clip; + +static const char* codepoint_to_utf8(unsigned c) { //< @r-lyeh + static char s[4+1]; + lt_memset(s, 0, 5); + /**/ if (c < 0x80) s[0] = c, s[1] = 0; + else if (c < 0x800) s[0] = 0xC0 | ((c >> 6) & 0x1F), s[1] = 0x80 | ( c & 0x3F), s[2] = 0; + else if (c < 0x10000) s[0] = 0xE0 | ((c >> 12) & 0x0F), s[1] = 0x80 | ((c >> 6) & 0x3F), s[2] = 0x80 | ( c & 0x3F), s[3] = 0; + else if (c < 0x110000) s[0] = 0xF0 | ((c >> 18) & 0x07), s[1] = 0x80 | ((c >> 12) & 0x3F), s[2] = 0x80 | ((c >> 6) & 0x3F), s[3] = 0x80 | (c & 0x3F), s[4] = 0; + return s; +} +static const char* utf8_to_codepoint(const char *p, unsigned *dst) { + unsigned res, n; + switch (*p & 0xf0) { + case 0xf0 : res = *p & 0x07; n = 3; break; + case 0xe0 : res = *p & 0x0f; n = 2; break; + case 0xd0 : + case 0xc0 : res = *p & 0x1f; n = 1; break; + default : res = *p; n = 0; break; + } + while (n-- && *p++) { //< https://github.com/rxi/lite/issues/262 + res = (res << 6) | (*p & 0x3f); //< https://github.com/rxi/lite/issues/262 + } + *dst = res; + return p + 1; +} + +void ren_init(void *win) { + lt_surface *surf = lt_getsurface(lt_window()); + ren_set_clip_rect( (RenRect) { 0, 0, surf->w, surf->h } ); +} + + +void ren_update_rects(RenRect *rects, int count) { + lt_updatesurfacerects(lt_getsurface(lt_window()), (lt_rect*) rects, count); +} + + +void ren_set_clip_rect(RenRect rect) { + clip.left = rect.x; + clip.top = rect.y; + clip.right = rect.x + rect.width; + clip.bottom = rect.y + rect.height; +} + + +void ren_get_size(int *x, int *y) { + lt_surface *surf = lt_getsurface(window); + *x = surf->w; + *y = surf->h; +} + + +RenImage* ren_new_image(int width, int height) { + lt_assert(width > 0 && height > 0); + RenImage *image = lt_malloc(sizeof(RenImage) + width * height * sizeof(RenColor)); + image->pixels = (void*) (image + 1); + image->width = width; + image->height = height; + return image; +} + + +void ren_free_image(RenImage *image) { + lt_free(image); +} + + +static GlyphSet* load_glyphset(RenFont *font, int idx) { + GlyphSet *set = lt_calloc(1, sizeof(GlyphSet)); + + /* init image */ + int width = 128; + int height = 128; +retry: + set->image = ren_new_image(width, height); + + /* load glyphs */ + float s = + stbtt_ScaleForMappingEmToPixels(&font->stbfont, 1) / + stbtt_ScaleForPixelHeight(&font->stbfont, 1); + int res = stbtt_BakeFontBitmap( + font->data, 0, font->size * s, (void*) set->image->pixels, + width, height, idx * 256, 256, set->glyphs); + + /* retry with a larger image buffer if the buffer wasn't large enough */ + if (res < 0) { + width *= 2; + height *= 2; + ren_free_image(set->image); + goto retry; + } + + /* adjust glyph yoffsets and xadvance */ + int ascent, descent, linegap; + stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap); + float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, font->size); + int scaled_ascent = ascent * scale + 0.5; + for (int i = 0; i < 256; i++) { + set->glyphs[i].yoff += scaled_ascent; + set->glyphs[i].xadvance = floor(set->glyphs[i].xadvance); + } + + /* convert 8bit data to 32bit */ + for (int i = width * height - 1; i >= 0; i--) { + uint8_t n = *((uint8_t*) set->image->pixels + i); + set->image->pixels[i] = (RenColor) { .r = 255, .g = 255, .b = 255, .a = n }; + } + + return set; +} + + +static GlyphSet* get_glyphset(RenFont *font, int codepoint) { + int idx = (codepoint >> 8) % MAX_GLYPHSET; + if (!font->sets[idx]) { + font->sets[idx] = load_glyphset(font, idx); + } + return font->sets[idx]; +} + + +RenFont* ren_load_font(const char *filename, float size) { + /* load font into buffer */ //< @r-lyeh: load font file before allocating `font` + char *fontdata = lt_load_file(filename, NULL); + if( !fontdata ) return NULL; + + RenFont *font = NULL; + + /* init font */ + font = lt_calloc(1, sizeof(RenFont)); + font->size = size; + font->data = fontdata; + + /* init stbfont */ + int ok = stbtt_InitFont(&font->stbfont, font->data, 0); + if (!ok) { + if (font) { lt_free(font->data); } + lt_free(font); + return NULL; + } + + /* get height and scale */ + int ascent, descent, linegap; + stbtt_GetFontVMetrics(&font->stbfont, &ascent, &descent, &linegap); + float scale = stbtt_ScaleForMappingEmToPixels(&font->stbfont, size); + font->height = (ascent - descent + linegap) * scale + 0.5; + + /* make tab and newline glyphs invisible */ + stbtt_bakedchar *g = get_glyphset(font, '\n')->glyphs; + g['\t'].x1 = g['\t'].x0; + g['\n'].x1 = g['\n'].x0; + + return font; +} + + +void ren_free_font(RenFont *font) { + for (int i = 0; i < MAX_GLYPHSET; i++) { + GlyphSet *set = font->sets[i]; + if (set) { + ren_free_image(set->image); + lt_free(set); + } + } + lt_free(font->data); + lt_free(font); +} + + +void ren_set_font_tab_width(RenFont *font, int n) { + GlyphSet *set = get_glyphset(font, '\t'); + set->glyphs['\t'].xadvance = n; +} + + +int ren_get_font_tab_width(RenFont *font) { + GlyphSet *set = get_glyphset(font, '\t'); + return set->glyphs['\t'].xadvance; +} + + +int ren_get_font_width(RenFont *font, const char *text) { + int x = 0; + const char *p = text; + unsigned codepoint; + while (*p) { + p = utf8_to_codepoint(p, &codepoint); + GlyphSet *set = get_glyphset(font, codepoint); + stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff]; + x += g->xadvance; + } + return x; +} + + +int ren_get_font_height(RenFont *font) { + return font->height; +} + + +static inline RenColor blend_pixel(RenColor dst, RenColor src) { + int ia = 0xff - src.a; + dst.r = ((src.r * src.a) + (dst.r * ia)) >> 8; + dst.g = ((src.g * src.a) + (dst.g * ia)) >> 8; + dst.b = ((src.b * src.a) + (dst.b * ia)) >> 8; + return dst; +} + + +static inline RenColor blend_pixel2(RenColor dst, RenColor src, RenColor color) { + src.a = (src.a * color.a) >> 8; + int ia = 0xff - src.a; + dst.r = ((src.r * color.r * src.a) >> 16) + ((dst.r * ia) >> 8); + dst.g = ((src.g * color.g * src.a) >> 16) + ((dst.g * ia) >> 8); + dst.b = ((src.b * color.b * src.a) >> 16) + ((dst.b * ia) >> 8); + return dst; +} + + +#define rect_draw_loop(expr) \ + for (int j = y1; j < y2; j++) { \ + for (int i = x1; i < x2; i++) { \ + *d = expr; \ + d++; \ + } \ + d += dr; \ + } + +void ren_draw_rect(RenRect rect, RenColor color) { + if (color.a == 0) { return; } + + int x1 = rect.x < clip.left ? clip.left : rect.x; + int y1 = rect.y < clip.top ? clip.top : rect.y; + int x2 = rect.x + rect.width; + int y2 = rect.y + rect.height; + x2 = x2 > clip.right ? clip.right : x2; + y2 = y2 > clip.bottom ? clip.bottom : y2; + + lt_surface *surf = lt_getsurface(window); + RenColor *d = (RenColor*) surf->pixels; + d += x1 + y1 * surf->w; + int dr = surf->w - (x2 - x1); + + if (color.a == 0xff) { + rect_draw_loop(color); + } else { + rect_draw_loop(blend_pixel(*d, color)); + } +} + + +void ren_draw_image(RenImage *image, RenRect *sub, int x, int y, RenColor color) { + if (color.a == 0) { return; } + + /* clip */ + int n; + if ((n = clip.left - x) > 0) { sub->width -= n; sub->x += n; x += n; } + if ((n = clip.top - y) > 0) { sub->height -= n; sub->y += n; y += n; } + if ((n = x + sub->width - clip.right ) > 0) { sub->width -= n; } + if ((n = y + sub->height - clip.bottom) > 0) { sub->height -= n; } + + if (sub->width <= 0 || sub->height <= 0) { + return; + } + + /* draw */ + lt_surface *surf = lt_getsurface(window); + RenColor *s = image->pixels; + RenColor *d = (RenColor*) surf->pixels; + s += sub->x + sub->y * image->width; + d += x + y * surf->w; + int sr = image->width - sub->width; + int dr = surf->w - sub->width; + + for (int j = 0; j < sub->height; j++) { + for (int i = 0; i < sub->width; i++) { + *d = blend_pixel2(*d, *s, color); + d++; + s++; + } + d += dr; + s += sr; + } +} + + +int ren_draw_text(RenFont *font, const char *text, int x, int y, RenColor color) { + RenRect rect; + const char *p = text; + unsigned codepoint; + while (*p) { + p = utf8_to_codepoint(p, &codepoint); + GlyphSet *set = get_glyphset(font, codepoint); + stbtt_bakedchar *g = &set->glyphs[codepoint & 0xff]; + rect.x = g->x0; + rect.y = g->y0; + rect.width = g->x1 - g->x0; + rect.height = g->y1 - g->y0; + ren_draw_image(set->image, &rect, x + g->xoff, y + g->yoff, color); + x += g->xadvance; + } + return x; +} + +// ---------------------------------------------------------------------------- +// lite/renderer_font.c + +static int f_load(lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + float size = luaL_checknumber(L, 2); + RenFont **self = lua_newuserdata(L, sizeof(*self)); + luaL_setmetatable(L, API_TYPE_FONT); + *self = ren_load_font(filename, size); + if (!*self) { luaL_error(L, "failed to load font"); } + return 1; +} + + +static int f_set_tab_width(lua_State *L) { + RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + int n = luaL_checknumber(L, 2); + ren_set_font_tab_width(*self, n); + return 0; +} + + +static int f_gc(lua_State *L) { + RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + if (*self) { rencache_free_font(*self); } + return 0; +} + + +static int f_get_width(lua_State *L) { + RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + const char *text = luaL_checkstring(L, 2); + lua_pushnumber(L, ren_get_font_width(*self, text) ); + return 1; +} + + +static int f_get_height(lua_State *L) { + RenFont **self = luaL_checkudata(L, 1, API_TYPE_FONT); + lua_pushnumber(L, ren_get_font_height(*self) ); + return 1; +} + + +int luaopen_renderer_font(lua_State *L) { + static const luaL_Reg lib[] = { + { "__gc", f_gc }, + { "load", f_load }, + { "set_tab_width", f_set_tab_width }, + { "get_width", f_get_width }, + { "get_height", f_get_height }, + { NULL, NULL } + }; + luaL_newmetatable(L, API_TYPE_FONT); + luaL_setfuncs(L, lib, 0); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + return 1; +} + +// ---------------------------------------------------------------------------- +// lite/renderer_api.c + +static RenColor checkcolor(lua_State *L, int idx, int def) { + RenColor color; + if (lua_isnoneornil(L, idx)) { + return (RenColor) { def, def, def, 255 }; + } + lua_rawgeti(L, idx, 1); + lua_rawgeti(L, idx, 2); + lua_rawgeti(L, idx, 3); + lua_rawgeti(L, idx, 4); + color.r = luaL_checknumber(L, -4); + color.g = luaL_checknumber(L, -3); + color.b = luaL_checknumber(L, -2); + color.a = luaL_optnumber(L, -1, 255); + lua_pop(L, 4); + return color; +} + + +static int f_show_debug(lua_State *L) { + luaL_checkany(L, 1); + rencache_show_debug(lua_toboolean(L, 1)); + return 0; +} + + +static int f_get_size(lua_State *L) { + int w, h; + ren_get_size(&w, &h); + lua_pushnumber(L, w); + lua_pushnumber(L, h); + return 2; +} + + +static int f_begin_frame(lua_State *L) { + rencache_begin_frame(); + return 0; +} + + +static int f_end_frame(lua_State *L) { + rencache_end_frame(); + return 0; +} + + +static int f_set_clip_rect(lua_State *L) { + RenRect rect; + rect.x = luaL_checknumber(L, 1); + rect.y = luaL_checknumber(L, 2); + rect.width = luaL_checknumber(L, 3); + rect.height = luaL_checknumber(L, 4); + rencache_set_clip_rect(rect); + return 0; +} + + +static int f_draw_rect(lua_State *L) { + RenRect rect; + rect.x = luaL_checknumber(L, 1); + rect.y = luaL_checknumber(L, 2); + rect.width = luaL_checknumber(L, 3); + rect.height = luaL_checknumber(L, 4); + RenColor color = checkcolor(L, 5, 255); + rencache_draw_rect(rect, color); + return 0; +} + + +static int f_draw_text(lua_State *L) { + RenFont **font = luaL_checkudata(L, 1, API_TYPE_FONT); + const char *text = luaL_checkstring(L, 2); + int x = luaL_checknumber(L, 3); + int y = luaL_checknumber(L, 4); + RenColor color = checkcolor(L, 5, 255); + x = rencache_draw_text(*font, text, x, y, color); + lua_pushnumber(L, x); + return 1; +} + +int luaopen_renderer(lua_State *L) { + static const luaL_Reg lib[] = { + { "show_debug", f_show_debug }, + { "get_size", f_get_size }, + { "begin_frame", f_begin_frame }, + { "end_frame", f_end_frame }, + { "set_clip_rect", f_set_clip_rect }, + { "draw_rect", f_draw_rect }, + { "draw_text", f_draw_text }, + { NULL, NULL } + }; + luaL_newlib(L, lib); + luaopen_renderer_font(L); + lua_setfield(L, -2, "font"); + return 1; +} + +// ---------------------------------------------------------------------------- +// lite/rencache.c + +/* a cache over the software renderer -- all drawing operations are stored as +** commands when issued. At the end of the frame we write the commands to a grid +** of hash values, take the cells that have changed since the previous frame, +** merge them into dirty rectangles and redraw only those regions */ + +#define CELLS_X 80 +#define CELLS_Y 50 +#define CELL_SIZE 96 +#define COMMAND_BUF_SIZE (1024 * 512) + +enum { FREE_FONT, SET_CLIP, DRAW_TEXT, DRAW_RECT }; + +typedef struct { + int type, size; + RenRect rect; + RenColor color; + RenFont *font; + int tab_width; + char text[0]; +} Command; + + +static unsigned cells_buf1[CELLS_X * CELLS_Y]; +static unsigned cells_buf2[CELLS_X * CELLS_Y]; +static unsigned *cells_prev = cells_buf1; +static unsigned *cells = cells_buf2; +static RenRect rect_buf[CELLS_X * CELLS_Y / 2]; +static char command_buf[COMMAND_BUF_SIZE]; +static int command_buf_idx; +static RenRect screen_rect; +static bool show_debug; + + +/* 32bit fnv-1a hash */ +#define HASH_INITIAL 2166136261 + +static void hash(unsigned *h, const void *data, int size) { + const unsigned char *p = data; + while (size--) { + *h = (*h ^ *p++) * 16777619; + } +} + + +static inline int cell_idx(int x, int y) { + return x + y * CELLS_X; +} + + +static inline bool rects_overlap(RenRect a, RenRect b) { + return b.x + b.width >= a.x && b.x <= a.x + a.width + && b.y + b.height >= a.y && b.y <= a.y + a.height; +} + + +static RenRect intersect_rects(RenRect a, RenRect b) { + int x1 = maxi(a.x, b.x); + int y1 = maxi(a.y, b.y); + int x2 = mini(a.x + a.width, b.x + b.width); + int y2 = mini(a.y + a.height, b.y + b.height); + return (RenRect) { x1, y1, max(0, x2 - x1), max(0, y2 - y1) }; +} + + +static RenRect merge_rects(RenRect a, RenRect b) { + int x1 = mini(a.x, b.x); + int y1 = mini(a.y, b.y); + int x2 = maxi(a.x + a.width, b.x + b.width); + int y2 = maxi(a.y + a.height, b.y + b.height); + return (RenRect) { x1, y1, x2 - x1, y2 - y1 }; +} + + +static Command* push_command(int type, int size) { + size_t alignment = 7; // alignof(max_align_t) - 1; //< C11 https://github.com/rxi/lite/pull/292/commits/ad1bdf56e3f212446e1c61fd45de8b94de5e2bc3 + size = (size + alignment) & ~alignment; //< https://github.com/rxi/lite/pull/292/commits/ad1bdf56e3f212446e1c61fd45de8b94de5e2bc3 + Command *cmd = (Command*) (command_buf + command_buf_idx); + int n = command_buf_idx + size; + if (n > COMMAND_BUF_SIZE) { + fprintf(stderr, "Warning: (" __FILE__ "): exhausted command buffer\n"); + return NULL; + } + command_buf_idx = n; + lt_memset(cmd, 0, sizeof(Command)); + cmd->type = type; + cmd->size = size; + return cmd; +} + + +static bool next_command(Command **prev) { + if (*prev == NULL) { + *prev = (Command*) command_buf; + } else { + *prev = (Command*) (((char*) *prev) + (*prev)->size); + } + return *prev != ((Command*) (command_buf + command_buf_idx)); +} + + +void rencache_show_debug(bool enable) { + show_debug = enable; +} + + +void rencache_free_font(RenFont *font) { + Command *cmd = push_command(FREE_FONT, sizeof(Command)); + if (cmd) { cmd->font = font; } +} + + +void rencache_set_clip_rect(RenRect rect) { + Command *cmd = push_command(SET_CLIP, sizeof(Command)); + if (cmd) { cmd->rect = intersect_rects(rect, screen_rect); } +} + + +void rencache_draw_rect(RenRect rect, RenColor color) { + if (!rects_overlap(screen_rect, rect)) { return; } + Command *cmd = push_command(DRAW_RECT, sizeof(Command)); + if (cmd) { + cmd->rect = rect; + cmd->color = color; + } +} + + +int rencache_draw_text(RenFont *font, const char *text, int x, int y, RenColor color) { + RenRect rect; + rect.x = x; + rect.y = y; + rect.width = ren_get_font_width(font, text); + rect.height = ren_get_font_height(font); + + if (rects_overlap(screen_rect, rect)) { + int sz = strlen(text) + 1; + Command *cmd = push_command(DRAW_TEXT, sizeof(Command) + sz); + if (cmd) { + memcpy(cmd->text, text, sz); + cmd->color = color; + cmd->font = font; + cmd->rect = rect; + cmd->tab_width = ren_get_font_tab_width(font); + } + } + + return x + rect.width; +} + + +void rencache_invalidate(void) { + lt_memset(cells_prev, 0xff, sizeof(cells_buf1)); +} + + +void rencache_begin_frame(void) { + /* reset all cells if the screen width/height has changed */ + int w, h; + ren_get_size(&w, &h); + if (screen_rect.width != w || h != screen_rect.height) { + screen_rect.width = w; + screen_rect.height = h; + rencache_invalidate(); + } +} + + +static void update_overlapping_cells(RenRect r, unsigned h) { + int x1 = r.x / CELL_SIZE; + int y1 = r.y / CELL_SIZE; + int x2 = (r.x + r.width) / CELL_SIZE; + int y2 = (r.y + r.height) / CELL_SIZE; + + for (int y = y1; y <= y2; y++) { + for (int x = x1; x <= x2; x++) { + int idx = cell_idx(x, y); + hash(&cells[idx], &h, sizeof(h)); + } + } +} + + +static void push_rect(RenRect r, int *count) { + /* try to merge with existing rectangle */ + for (int i = *count - 1; i >= 0; i--) { + RenRect *rp = &rect_buf[i]; + if (rects_overlap(*rp, r)) { + *rp = merge_rects(*rp, r); + return; + } + } + /* couldn't merge with previous rectangle: push */ + rect_buf[(*count)++] = r; +} + + +void rencache_end_frame(void) { + /* update cells from commands */ + Command *cmd = NULL; + RenRect cr = screen_rect; + while (next_command(&cmd)) { + if (cmd->type == SET_CLIP) { cr = cmd->rect; } + RenRect r = intersect_rects(cmd->rect, cr); + if (r.width == 0 || r.height == 0) { continue; } + unsigned h = HASH_INITIAL; + hash(&h, cmd, cmd->size); + update_overlapping_cells(r, h); + } + + /* push rects for all cells changed from last frame, reset cells */ + int rect_count = 0; + int max_x = screen_rect.width / CELL_SIZE + 1; + int max_y = screen_rect.height / CELL_SIZE + 1; + for (int y = 0; y < max_y; y++) { + for (int x = 0; x < max_x; x++) { + /* compare previous and current cell for change */ + int idx = cell_idx(x, y); + if (cells[idx] != cells_prev[idx]) { + push_rect((RenRect) { x, y, 1, 1 }, &rect_count); + } + cells_prev[idx] = HASH_INITIAL; + } + } + + /* expand rects from cells to pixels */ + for (int i = 0; i < rect_count; i++) { + RenRect *r = &rect_buf[i]; + r->x *= CELL_SIZE; + r->y *= CELL_SIZE; + r->width *= CELL_SIZE; + r->height *= CELL_SIZE; + *r = intersect_rects(*r, screen_rect); + } + + /* redraw updated regions */ + bool has_free_commands = false; + for (int i = 0; i < rect_count; i++) { + /* draw */ + RenRect r = rect_buf[i]; + ren_set_clip_rect(r); + + cmd = NULL; + while (next_command(&cmd)) { + switch (cmd->type) { + case FREE_FONT: + has_free_commands = true; + break; + case SET_CLIP: + ren_set_clip_rect(intersect_rects(cmd->rect, r)); + break; + case DRAW_RECT: + ren_draw_rect(cmd->rect, cmd->color); + break; + case DRAW_TEXT: + ren_set_font_tab_width(cmd->font, cmd->tab_width); + ren_draw_text(cmd->font, cmd->text, cmd->rect.x, cmd->rect.y, cmd->color); + break; + } + } + + if (show_debug) { + RenColor color = { rand(), rand(), rand(), 50 }; + ren_draw_rect(r, color); + } + } + + /* update dirty rects */ + if (rect_count > 0) { + ren_update_rects(rect_buf, rect_count); + } + + /* free fonts */ + if (has_free_commands) { + cmd = NULL; + while (next_command(&cmd)) { + if (cmd->type == FREE_FONT) { + ren_free_font(cmd->font); + } + } + } + + /* swap cell buffer and reset */ + unsigned *tmp = cells; + cells = cells_prev; + cells_prev = tmp; + command_buf_idx = 0; +} + +// ---------------------------------------------------------------------------- +// lite/system.c + +static int f_set_cursor(lua_State *L) { + static const char *cursor_opts[] = { + "arrow", + "ibeam", + "sizeh", + "sizev", + "hand", + NULL + }; + int n = luaL_checkoption(L, 1, "arrow", cursor_opts); + lt_setcursor(n); + return 0; +} + +static int f_set_window_title(lua_State *L) { + const char *title = luaL_checkstring(L, 1); + lt_setwindowtitle(title); + return 0; +} +static int f_set_window_mode(lua_State *L) { + static const char *window_opts[] = { "normal", "maximized", "fullscreen", 0 }; + enum { WIN_NORMAL, WIN_MAXIMIZED, WIN_FULLSCREEN }; + int n = luaL_checkoption(L, 1, "normal", window_opts); + lt_setwindowmode(n); + return 0; +} +static int f_window_has_focus(lua_State *L) { + unsigned flags = lt_haswindowfocus(); + lua_pushboolean(L, flags); + return 1; +} + +static int f_show_confirm_dialog(lua_State *L) { + const char *title = luaL_checkstring(L, 1); + const char *msg = luaL_checkstring(L, 2); + int id = lt_prompt(msg, title); // 0:no, 1:yes + lua_pushboolean(L, !!id); + return 1; +} + +static int f_chdir(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + int err = chdir(path); + if (err) { luaL_error(L, "chdir() failed"); } + return 0; +} +static int f_list_dir(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + lua_newtable(L); + lt_globpath(L, path); + return 1; +} +static int f_absolute_path(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + char *res = lt_realpath(path, NULL); + if (!res) { return 0; } + lua_pushstring(L, res); + lt_realpath_free(res); + return 1; +} +static int f_get_file_info(lua_State *L) { + const char *path = luaL_checkstring(L, 1); + + struct stat s; + int err = stat(path, &s); + if (err < 0) { + lua_pushnil(L); + lua_pushstring(L, strerror(errno)); + return 2; + } + + lua_newtable(L); + lua_pushnumber(L, s.st_mtime); + lua_setfield(L, -2, "modified"); + + lua_pushnumber(L, s.st_size); + lua_setfield(L, -2, "size"); + + if (S_ISREG(s.st_mode)) { + lua_pushstring(L, "file"); + } else if (S_ISDIR(s.st_mode)) { + lua_pushstring(L, "dir"); + } else { + lua_pushnil(L); + } + lua_setfield(L, -2, "type"); + + return 1; +} + + +static int f_get_clipboard(lua_State *L) { + const char *text = lt_getclipboard(lt_window()); + if (!text) { return 0; } + lua_pushstring(L, text); + return 1; +} +static int f_set_clipboard(lua_State *L) { + const char *text = luaL_checkstring(L, 1); + lt_setclipboard(lt_window(), text); + return 0; +} + + +static int f_get_time(lua_State *L) { + double ss = lt_time_ms() / 1000.0; + lua_pushnumber(L, ss); + return 1; +} +static int f_sleep(lua_State *L) { + double ss = luaL_checknumber(L, 1); + lt_sleep_ms(ss * 1000); + return 0; +} + + +static int f_exec(lua_State *L) { + size_t len; + const char *cmd = luaL_checklstring(L, 1, &len); + char *buf = lt_malloc(len + 32); + if (!buf) { luaL_error(L, "buffer allocation failed"); } +#if _WIN32 + sprintf(buf, "cmd /c \"%s\"", cmd); + WinExec(buf, SW_HIDE); +#else + sprintf(buf, "%s &", cmd); + int res = system(buf); +#endif + lt_free(buf); + return 0; +} + + +static int f_fuzzy_match(lua_State *L) { + const char *str = luaL_checkstring(L, 1); + const char *ptn = luaL_checkstring(L, 2); + int score = 0; + int run = 0; + + while (*str && *ptn) { + while (*str == ' ') { str++; } + while (*ptn == ' ') { ptn++; } + if (tolower(*str) == tolower(*ptn)) { + score += run * 10 - (*str != *ptn); + run++; + ptn++; + } else { + score -= 10; + run = 0; + } + str++; + } + if (*ptn) { return 0; } + + lua_pushnumber(L, score - (int) strlen(str)); + return 1; +} + +static int f_poll_event(lua_State *L) { // init.lua > core.step() wakes on mousemoved || inputtext + int rc = lt_poll_event(L); + return rc; +} + +int luaopen_system(lua_State *L) { + static const luaL_Reg lib[] = { + { "poll_event", f_poll_event }, + { "set_cursor", f_set_cursor }, + { "set_window_title", f_set_window_title }, + { "set_window_mode", f_set_window_mode }, + { "window_has_focus", f_window_has_focus }, + { "show_confirm_dialog", f_show_confirm_dialog }, + { "chdir", f_chdir }, + { "list_dir", f_list_dir }, + { "absolute_path", f_absolute_path }, + { "get_file_info", f_get_file_info }, + { "get_clipboard", f_get_clipboard }, + { "set_clipboard", f_set_clipboard }, + { "get_time", f_get_time }, + { "sleep", f_sleep }, + { "exec", f_exec }, + { "fuzzy_match", f_fuzzy_match }, + { NULL, NULL } + }; + luaL_newlib(L, lib); + return 1; +} + +// ---------------------------------------------------------------------------- +// lite/api/api.c + +void api_load_libs(lua_State *L) { + static const luaL_Reg libs[] = { + { "system", luaopen_system }, + { "renderer", luaopen_renderer }, + { NULL, NULL } + }; + for (int i = 0; libs[i].name; i++) { + luaL_requiref(L, libs[i].name, libs[i].func, 1); + } +} + +// ---------------------------------------------------------------------------- +// lite/main.c + +void lt_init(lua_State *L, void *handle, const char *pathdata, int argc, char **argv, float scale, const char *platform, const char *pathexe) { + // setup renderer + ren_init(handle); + + // setup lua context + api_load_libs(L); + + lua_newtable(L); + for (int i = 0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i + 1); + } + lua_setglobal(L, "ARGS"); + + lua_pushstring(L, "1.11"); + lua_setglobal(L, "VERSION"); + + lua_pushstring(L, platform); + lua_setglobal(L, "PLATFORM"); + + lua_pushnumber(L, scale); + lua_setglobal(L, "SCALE"); + + lua_pushstring(L, pathdata); + lua_setglobal(L, "DATADIR"); + + lua_pushstring(L, pathexe); + lua_setglobal(L, "EXEFILE"); + + // init lite + luaL_dostring(L, "core = {}"); + luaL_dostring(L, + "xpcall(function()\n" + " SCALE = tonumber(os.getenv(\"LITE_SCALE\")) or SCALE\n" + " PATHSEP = package.config:sub(1, 1)\n" + " EXEDIR = EXEFILE:match(\"^(.+)[/\\\\].*$\")\n" + " package.path = EXEDIR .. '/data/?.lua;' .. package.path\n" + " package.path = EXEDIR .. '/data/?/init.lua;' .. package.path\n" + " core = require('core')\n" + " core.init()\n" + "end, function(err)\n" + " print('Error: ' .. tostring(err))\n" + " print(debug.traceback(nil, 2))\n" + " if core and core.on_error then\n" + " pcall(core.on_error, err)\n" + " end\n" + " os.exit(1)\n" + "end)" + ); +} +void lt_tick(struct lua_State *L) { + luaL_dostring(L, + "xpcall(function()\n" + " core.run1()\n" + "end, function(err)\n" + " print('Error: ' .. tostring(err))\n" + " print(debug.traceback(nil, 2))\n" + " if core and core.on_error then\n" + " pcall(core.on_error, err)\n" + " end\n" + " os.exit(1)\n" + "end)" + ); +} diff --git a/tools/editor/3rd_lite_sys.h b/tools/editor/3rd_lite_sys.h new file mode 100644 index 0000000..ccb1dd7 --- /dev/null +++ b/tools/editor/3rd_lite_sys.h @@ -0,0 +1,264 @@ +// lite editor, platform details +// - rlyeh, public domain + +#define LT_DATAPATH "/lite" + +#define lt_assert(x) ASSERT(x) + +#define lt_realpath(p, q) file_pathabs(p) +#define lt_realpath_free(p) + +#define lt_malloc(n) MALLOC(n) +#define lt_calloc(n,m) CALLOC(n,m) +#define lt_free(p) FREE(p) +#define lt_memcpy(d,s,c) memcpy(d,s,c) +#define lt_memset(p,ch,c) memset(p,ch,c) + +#define lt_time_ms() time_ms() +#define lt_sleep_ms(ms) sleep_ms(ms) + +#define lt_getclipboard(w) window_clipboard() +#define lt_setclipboard(w,s) window_setclipboard(s) + +#define lt_window() window_handle() +#define lt_setwindowmode(m) window_fullscreen(m == 2), (m < 2 && (window_maximize(m),1)) // 0:normal,1:maximized,2:fullscreen +#define lt_setwindowtitle(t) //window_title(t) +#define lt_haswindowfocus() window_has_focus() +#define lt_setcursor(shape) window_cursor_shape(lt_events & (1<<31) ? CURSOR_SW_AUTO : shape+1) // 0:arrow,1:ibeam,2:sizeh,3:sizev,4:hand + +#define lt_prompt(msg,title) ifndef(win32, 0, (MessageBoxA(0, msg, title, MB_YESNO | MB_ICONWARNING) == IDYES)) + +unsigned lt_events = ~0u; +int lt_mx = 0, lt_my = 0, lt_wx = 0, lt_wy = 0, lt_ww = 0, lt_wh = 0; + +typedef struct lt_surface { + unsigned w, h; + void *pixels; + texture_t t; +} lt_surface; + +typedef struct lt_rect { + int x, y, width, height; +} lt_rect; + +lt_surface *lt_getsurface(void *window) { + static lt_surface s = {0}; + return &s; +} +void lt_updatesurfacerects(lt_surface *s, lt_rect* rects, unsigned count) { + // update contents + texture_update(&s->t, s->w, s->h, 4, s->pixels, TEXTURE_LINEAR|TEXTURE_BGRA); +} + +void ren_set_clip_rect(struct lt_rect rect); +void rencache_invalidate(void); +int lt_resizesurface(lt_surface *s, int ww, int wh) { + s->w = ww, s->h = wh; + if( s->t.id == 0 || s->w != s->t.w || s->h != s->t.h ) { + // invalidate tiles + ren_set_clip_rect( (lt_rect) { 0, 0, s->w, s->h } ); + rencache_invalidate(); + + // texture clear + if( !s->t.id ) s->t = texture_create(1, 1, 4, " ", TEXTURE_LINEAR|TEXTURE_RGBA|TEXTURE_BYTE ); + s->pixels = REALLOC(s->pixels, s->w * s->h * 4); + memset(s->pixels, 0, s->w * s->h * 4); + + // texture update + lt_updatesurfacerects(s,0,0); + return 1; // resized + } + return 0; // unchanged +} + +void *lt_load_file(const char *filename, int *size) { + int datalen; char *data = file_load(filename, &datalen); + if( !data || !datalen ) { + filename = (const char *)file_normalize(filename); + if( strbegi(filename, app_path()) ) filename += strlen(app_path()); + data = vfs_load(filename, &datalen); + } + if (size) *size = 0; + if (!data) { return NULL; } + if (size) *size = datalen; + // return permanent buffers here, as file_load() and vfs_load() do return temporaries + data = memcpy(MALLOC(datalen+1), data, datalen); + data[datalen] = 0; + return data; +} + +const char* lt_button_name(int button) { + if(button == GLFW_MOUSE_BUTTON_1) return "left"; + if(button == GLFW_MOUSE_BUTTON_2) return "middle"; + if(button == GLFW_MOUSE_BUTTON_3) return "right"; + return "?"; +} + +char* lt_key_name(char *dst, int key, int vk, int mods) { + // @todo: ALTGR -> left ctrl + right alt + + if( key == GLFW_KEY_UP ) return "up"; + if( key == GLFW_KEY_DOWN ) return "down"; + if( key == GLFW_KEY_LEFT ) return "left"; + if( key == GLFW_KEY_RIGHT ) return "right"; + if( key == GLFW_KEY_LEFT_ALT ) return "left alt"; + if( key == GLFW_KEY_RIGHT_ALT ) return "right alt"; + if( key == GLFW_KEY_LEFT_SHIFT ) return "left shift"; + if( key == GLFW_KEY_RIGHT_SHIFT ) return "right shift"; + if( key == GLFW_KEY_LEFT_CONTROL ) return "left ctrl"; + if( key == GLFW_KEY_RIGHT_CONTROL ) return "right ctrl"; + if( key == GLFW_KEY_LEFT_SUPER ) return "left windows"; + if( key == GLFW_KEY_RIGHT_SUPER ) return "left windows"; + + if( key == GLFW_KEY_ESCAPE ) return "escape"; + if( key == GLFW_KEY_BACKSPACE ) return "backspace"; + if( key == GLFW_KEY_ENTER ) return "return"; + if( key == GLFW_KEY_KP_ENTER ) return "keypad enter"; + if( key == GLFW_KEY_TAB ) return "tab"; + if( key == GLFW_KEY_CAPS_LOCK ) return "capslock"; + + if( key == GLFW_KEY_HOME ) return "home"; + if( key == GLFW_KEY_END ) return "end"; + if( key == GLFW_KEY_INSERT ) return "insert"; + if( key == GLFW_KEY_DELETE ) return "delete"; + if( key == GLFW_KEY_PAGE_UP ) return "pageup"; + if( key == GLFW_KEY_PAGE_DOWN ) return "pagedown"; + + if( key == GLFW_KEY_F1 ) return "f1"; + if( key == GLFW_KEY_F2 ) return "f2"; + if( key == GLFW_KEY_F3 ) return "f3"; + if( key == GLFW_KEY_F4 ) return "f4"; + if( key == GLFW_KEY_F5 ) return "f5"; + if( key == GLFW_KEY_F6 ) return "f6"; + if( key == GLFW_KEY_F7 ) return "f7"; + if( key == GLFW_KEY_F8 ) return "f8"; + if( key == GLFW_KEY_F9 ) return "f9"; + if( key == GLFW_KEY_F10 ) return "f10"; + if( key == GLFW_KEY_F11 ) return "f11"; + if( key == GLFW_KEY_F12 ) return "f12"; + + const char *name = glfwGetKeyName(key, vk); + strcpy(dst, name ? name : ""); + char *p = dst; + while (*p) { + *p = tolower(*p); + p++; + } + return dst; +} + +void lt_globpath(struct lua_State*L, const char *path) { + unsigned j = 0; + + if(!strend(path, "/")) path = (const char *)va("%s/", path); + for( dir *d = dir_open(path, ""); d; dir_close(d), d = 0 ) { + for( unsigned i = 0, end = dir_count(d); i < end; ++i ) { + char *name = dir_name(d,i); + char *last = name + strlen(name) - 1; + if( *last == '/' ) *last = '\0'; + name = file_name(name); + lua_pushstring(L, name); + lua_rawseti(L, -2, ++j); + } + } + + for( const char *section = strstri(path, LT_DATAPATH); section && section[sizeof(LT_DATAPATH)-1] == '/'; section = 0) { + array(char*) list = vfs_list("**"); + for( unsigned i = 0, end = array_count(list); i < end; ++i ) { + char *name = list[i]; + if( !strstri(name, section+1) ) continue; + lua_pushstring(L, file_name(name)); + lua_rawseti(L, -2, ++j); + } + if( array_count(list) ) return; + } +} + +int lt_emit_event(lua_State *L, const char *event_name, const char *event_fmt, ...) { + int count = 0; + lua_pushstring(L, event_name); + if( event_fmt ) { + va_list va; + va_start(va, event_fmt); + for( ; event_fmt[count]; ++count ) { + /**/ if( event_fmt[count] == 'd' ) { int d = va_arg(va, int); lua_pushnumber(L, d); } + else if( event_fmt[count] == 'f' ) { double f = va_arg(va, double); lua_pushnumber(L, f); } + else if( event_fmt[count] == 's' ) { const char *s = va_arg(va, const char *); lua_pushstring(L, s); } + } + va_end(va); + } + return 1+count; +} + +int printi(int i) { + // printf("clicks: %d\n", i); + return i; +} + +static const char* codepoint_to_utf8(unsigned c); +int lt_poll_event(lua_State *L) { // init.lua > core.step() wakes on mousemoved || inputtext + int rc = 0; + char buf[16]; + static int prevx = 0, prevy = 0; + + static unsigned clicks_time = 0, clicks = 0; + if( (lt_time_ms() - clicks_time) > 400 ) clicks = 0; + + // + + for( GLEQevent e; gleqNextEvent(&e); gleqFreeEvent(&e) ) + if( lt_events & e.type ) + switch (e.type) { + default: + break; case GLEQ_WINDOW_CLOSED: // it used to be ok. depends on window_swap() flow + rc += lt_emit_event(L, "quit", NULL); + return rc; + + break; case GLEQ_WINDOW_MOVED: + lt_wx = e.pos.x; + lt_wy = e.pos.y; + + break; case GLEQ_WINDOW_RESIZED: + rc += lt_emit_event(L, "resized", "dd", lt_ww = e.size.width, lt_wh = e.size.height); + lt_resizesurface(lt_getsurface(lt_window()), lt_ww, lt_wh); + + break; case GLEQ_WINDOW_REFRESH: + rc += lt_emit_event(L, "exposed", NULL); + rencache_invalidate(); + + break; case GLEQ_FILE_DROPPED: + rc += lt_emit_event(L, "filedropped", "sdd", e.file.paths[0], lt_mx, lt_my); + + break; case GLEQ_KEY_PRESSED: + case GLEQ_KEY_REPEATED: + rc += lt_emit_event(L, "keypressed", "s", lt_key_name(buf, e.keyboard.key, e.keyboard.scancode, e.keyboard.mods)); + goto bottom; + + break; case GLEQ_KEY_RELEASED: + rc += lt_emit_event(L, "keyreleased", "s", lt_key_name(buf, e.keyboard.key, e.keyboard.scancode, e.keyboard.mods)); + goto bottom; + + break; case GLEQ_CODEPOINT_INPUT: + rc += lt_emit_event(L, "textinput", "s", codepoint_to_utf8(e.codepoint)); + + break; case GLEQ_BUTTON_PRESSED: + rc += lt_emit_event(L, "mousepressed", "sddd", lt_button_name(e.mouse.button), lt_mx, lt_my, printi(1 + clicks)); + + break; case GLEQ_BUTTON_RELEASED: + clicks += e.mouse.button == GLFW_MOUSE_BUTTON_1; + clicks_time = lt_time_ms(); + rc += lt_emit_event(L, "mousereleased", "sdd", lt_button_name(e.mouse.button), lt_mx, lt_my); + + break; case GLEQ_CURSOR_MOVED: + lt_mx = e.pos.x - lt_wx, lt_my = e.pos.y - lt_wy; + rc += lt_emit_event(L, "mousemoved", "dddd", lt_mx, lt_my, lt_mx - prevx, lt_my - prevy); + prevx = lt_mx, prevy = lt_my; + + break; case GLEQ_SCROLLED: + rc += lt_emit_event(L, "mousewheel", "f", e.scroll.y); + } + +bottom:; + + return rc; +} diff --git a/tools/editor/3rd_lite_sys_gleq.h b/tools/editor/3rd_lite_sys_gleq.h new file mode 100644 index 0000000..105431e --- /dev/null +++ b/tools/editor/3rd_lite_sys_gleq.h @@ -0,0 +1,419 @@ +/* + * GLEQ - A basic event queue for GLFW 3 + * Copyright © Camilla Löwy + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would + * be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + */ + +#ifndef GLEQ_HEADER_FILE +#define GLEQ_HEADER_FILE + +// #include + +#ifdef GLEQ_STATIC + #define GLEQDEF static +#else + #define GLEQDEF extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum +{ + GLEQ_NONE = 0, + GLEQ_WINDOW_MOVED = 1<<1, + GLEQ_WINDOW_RESIZED = 1<<2, + GLEQ_WINDOW_CLOSED = 1<<3, + GLEQ_WINDOW_REFRESH = 1<<4, + GLEQ_WINDOW_FOCUSED = 1<<5, + GLEQ_WINDOW_DEFOCUSED = 1<<6, + GLEQ_WINDOW_ICONIFIED = 1<<7, + GLEQ_WINDOW_UNICONIFIED = 1<<8, + GLEQ_FRAMEBUFFER_RESIZED = 1<<9, + GLEQ_BUTTON_PRESSED = 1<<10, + GLEQ_BUTTON_RELEASED = 1<<11, + GLEQ_CURSOR_MOVED = 1<<12, + GLEQ_CURSOR_ENTERED = 1<<13, + GLEQ_CURSOR_LEFT = 1<<14, + GLEQ_SCROLLED = 1<<15, + GLEQ_KEY_PRESSED = 1<<16, + GLEQ_KEY_REPEATED = 1<<17, + GLEQ_KEY_RELEASED = 1<<18, + GLEQ_CODEPOINT_INPUT = 1<<19, + GLEQ_MONITOR_CONNECTED = 1<<20, + GLEQ_MONITOR_DISCONNECTED = 1<<21, +#if GLFW_VERSION_MINOR >= 1 + GLEQ_FILE_DROPPED = 1<<22, +#endif +#if GLFW_VERSION_MINOR >= 2 + GLEQ_JOYSTICK_CONNECTED = 1<<23, + GLEQ_JOYSTICK_DISCONNECTED = 1<<24, +#endif +#if GLFW_VERSION_MINOR >= 3 + GLEQ_WINDOW_MAXIMIZED = 1<<25, + GLEQ_WINDOW_UNMAXIMIZED = 1<<26, + GLEQ_WINDOW_SCALE_CHANGED = 1<<27, +#endif +} GLEQtype; + +typedef struct GLEQevent +{ + unsigned/*GLEQtype*/ type; + union { + GLFWwindow* window; + GLFWmonitor* monitor; + int joystick; + }; + union { + struct { + int x; + int y; + } pos; + struct { + int width; + int height; + } size; + struct { + double x; + double y; + } scroll; + struct { + int key; + int scancode; + int mods; + } keyboard; + struct { + int button; + int mods; + } mouse; + unsigned int codepoint; +#if GLFW_VERSION_MINOR >= 1 + struct { + char** paths; + int count; + } file; +#endif +#if GLFW_VERSION_MINOR >= 3 + struct { + float x; + float y; + } scale; +#endif + }; +} GLEQevent; + +GLEQDEF void gleqInit(void); +GLEQDEF void gleqTrackWindow(GLFWwindow* window); + +GLEQDEF int gleqNextEvent(GLEQevent* event); +GLEQDEF void gleqFreeEvent(GLEQevent* event); + +#ifdef __cplusplus +} +#endif + +#ifdef GLEQ_IMPLEMENTATION + +#include +#include +#include + +#ifndef GLEQ_CAPACITY + #define GLEQ_CAPACITY 1024 +#endif + +static struct +{ + GLEQevent events[GLEQ_CAPACITY]; + size_t head; + size_t tail; +} gleq_queue = { {0}, 0, 0 }; + +static char* gleq_strdup(const char* string) +{ + const size_t size = strlen(string) + 1; + char* result = (char*) malloc(size); + memcpy(result, string, size); + return result; +} + +static GLEQevent* gleq_new_event(void) +{ + GLEQevent* event = gleq_queue.events + gleq_queue.head; + gleq_queue.head = (gleq_queue.head + 1) % GLEQ_CAPACITY; + assert(gleq_queue.head != gleq_queue.tail); + memset(event, 0, sizeof(GLEQevent)); + return event; +} + +static void gleq_window_pos_callback(GLFWwindow* window, int x, int y) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_WINDOW_MOVED; + event->window = window; + event->pos.x = x; + event->pos.y = y; +} + +static void gleq_window_size_callback(GLFWwindow* window, int width, int height) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_WINDOW_RESIZED; + event->window = window; + event->size.width = width; + event->size.height = height; +} + +static void gleq_window_close_callback(GLFWwindow* window) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_WINDOW_CLOSED; + event->window = window; +} + +static void gleq_window_refresh_callback(GLFWwindow* window) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_WINDOW_REFRESH; + event->window = window; +} + +static void gleq_window_focus_callback(GLFWwindow* window, int focused) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + + if (focused) + event->type = GLEQ_WINDOW_FOCUSED; + else + event->type = GLEQ_WINDOW_DEFOCUSED; +} + +static void gleq_window_iconify_callback(GLFWwindow* window, int iconified) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + + if (iconified) + event->type = GLEQ_WINDOW_ICONIFIED; + else + event->type = GLEQ_WINDOW_UNICONIFIED; +} + +static void gleq_framebuffer_size_callback(GLFWwindow* window, int width, int height) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_FRAMEBUFFER_RESIZED; + event->window = window; + event->size.width = width; + event->size.height = height; +} + +static void gleq_mouse_button_callback(GLFWwindow* window, int button, int action, int mods) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + event->mouse.button = button; + event->mouse.mods = mods; + + if (action == GLFW_PRESS) + event->type = GLEQ_BUTTON_PRESSED; + else if (action == GLFW_RELEASE) + event->type = GLEQ_BUTTON_RELEASED; +} + +static void gleq_cursor_pos_callback(GLFWwindow* window, double x, double y) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_CURSOR_MOVED; + event->window = window; + event->pos.x = (int) x; + event->pos.y = (int) y; +} + +static void gleq_cursor_enter_callback(GLFWwindow* window, int entered) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + + if (entered) + event->type = GLEQ_CURSOR_ENTERED; + else + event->type = GLEQ_CURSOR_LEFT; +} + +static void gleq_scroll_callback(GLFWwindow* window, double x, double y) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_SCROLLED; + event->window = window; + event->scroll.x = x; + event->scroll.y = y; +} + +static void gleq_key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + event->keyboard.key = key; + event->keyboard.scancode = scancode; + event->keyboard.mods = mods; + + if (action == GLFW_PRESS) + event->type = GLEQ_KEY_PRESSED; + else if (action == GLFW_RELEASE) + event->type = GLEQ_KEY_RELEASED; + else if (action == GLFW_REPEAT) + event->type = GLEQ_KEY_REPEATED; +} + +static void gleq_char_callback(GLFWwindow* window, unsigned int codepoint) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_CODEPOINT_INPUT; + event->window = window; + event->codepoint = codepoint; +} + +static void gleq_monitor_callback(GLFWmonitor* monitor, int action) +{ + GLEQevent* event = gleq_new_event(); + event->monitor = monitor; + + if (action == GLFW_CONNECTED) + event->type = GLEQ_MONITOR_CONNECTED; + else if (action == GLFW_DISCONNECTED) + event->type = GLEQ_MONITOR_DISCONNECTED; +} + +#if GLFW_VERSION_MINOR >= 1 +static void gleq_file_drop_callback(GLFWwindow* window, int count, const char** paths) +{ + GLEQevent* event = gleq_new_event(); + event->type = GLEQ_FILE_DROPPED; + event->window = window; + event->file.paths = (char**) malloc(count * sizeof(char*)); + event->file.count = count; + + while (count--) + event->file.paths[count] = gleq_strdup(paths[count]); +} +#endif + +#if GLFW_VERSION_MINOR >= 2 +static void gleq_joystick_callback(int jid, int action) +{ + GLEQevent* event = gleq_new_event(); + event->joystick = jid; + + if (action == GLFW_CONNECTED) + event->type = GLEQ_JOYSTICK_CONNECTED; + else if (action == GLFW_DISCONNECTED) + event->type = GLEQ_JOYSTICK_DISCONNECTED; +} +#endif + +#if GLFW_VERSION_MINOR >= 3 +static void gleq_window_maximize_callback(GLFWwindow* window, int maximized) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + + if (maximized) + event->type = GLEQ_WINDOW_MAXIMIZED; + else + event->type = GLEQ_WINDOW_UNMAXIMIZED; +} + +static void gleq_window_content_scale_callback(GLFWwindow* window, float xscale, float yscale) +{ + GLEQevent* event = gleq_new_event(); + event->window = window; + event->type = GLEQ_WINDOW_SCALE_CHANGED; + event->scale.x = xscale; + event->scale.y = yscale; +} +#endif + +GLEQDEF void gleqInit(void) +{ + glfwSetMonitorCallback(gleq_monitor_callback); +#if GLFW_VERSION_MINOR >= 2 + glfwSetJoystickCallback(gleq_joystick_callback); +#endif +} + +GLEQDEF void gleqTrackWindow(GLFWwindow* window) +{ + glfwSetWindowPosCallback(window, gleq_window_pos_callback); + glfwSetWindowSizeCallback(window, gleq_window_size_callback); + glfwSetWindowCloseCallback(window, gleq_window_close_callback); + glfwSetWindowRefreshCallback(window, gleq_window_refresh_callback); + glfwSetWindowFocusCallback(window, gleq_window_focus_callback); + glfwSetWindowIconifyCallback(window, gleq_window_iconify_callback); + glfwSetFramebufferSizeCallback(window, gleq_framebuffer_size_callback); + glfwSetMouseButtonCallback(window, gleq_mouse_button_callback); + glfwSetCursorPosCallback(window, gleq_cursor_pos_callback); + glfwSetCursorEnterCallback(window, gleq_cursor_enter_callback); + glfwSetScrollCallback(window, gleq_scroll_callback); + glfwSetKeyCallback(window, gleq_key_callback); + glfwSetCharCallback(window, gleq_char_callback); +#if GLFW_VERSION_MINOR >= 1 + glfwSetDropCallback(window, gleq_file_drop_callback); +#endif +#if GLFW_VERSION_MINOR >= 3 + glfwSetWindowMaximizeCallback(window, gleq_window_maximize_callback); + glfwSetWindowContentScaleCallback(window, gleq_window_content_scale_callback); +#endif +} + +GLEQDEF int gleqNextEvent(GLEQevent* event) +{ + memset(event, 0, sizeof(GLEQevent)); + + if (gleq_queue.head != gleq_queue.tail) + { + *event = gleq_queue.events[gleq_queue.tail]; + gleq_queue.tail = (gleq_queue.tail + 1) % GLEQ_CAPACITY; + } + + return event->type != GLEQ_NONE; +} + +GLEQDEF void gleqFreeEvent(GLEQevent* event) +{ +#if GLFW_VERSION_MINOR >= 1 + if (event->type == GLEQ_FILE_DROPPED) + { + while (event->file.count--) + free(event->file.paths[event->file.count]); + + free(event->file.paths); + } +#endif + + memset(event, 0, sizeof(GLEQevent)); +} + +#endif /* GLEQ_IMPLEMENTATION */ + +#endif /* GLEQ_HEADER_FILE */ diff --git a/tools/editor/art/lite/data/core/command.lua b/tools/editor/art/lite/data/core/command.lua new file mode 100644 index 0000000..5164a13 --- /dev/null +++ b/tools/editor/art/lite/data/core/command.lua @@ -0,0 +1,69 @@ +local core = require "core" +local command = {} + +command.map = {} + +local always_true = function() return true end + + +function command.add(predicate, map) + predicate = predicate or always_true + if type(predicate) == "string" then + predicate = require(predicate) + end + if type(predicate) == "table" then + local class = predicate + predicate = function() return core.active_view:is(class) end + end + for name, fn in pairs(map) do + assert(not command.map[name], "command already exists: " .. name) + command.map[name] = { predicate = predicate, perform = fn } + end +end + + +local function capitalize_first(str) + return str:sub(1, 1):upper() .. str:sub(2) +end + +function command.prettify_name(name) + return name:gsub(":", ": "):gsub("-", " "):gsub("%S+", capitalize_first) +end + + +function command.get_all_valid() + local res = {} + for name, cmd in pairs(command.map) do + if cmd.predicate() then + table.insert(res, name) + end + end + return res +end + + +local function perform(name) + local cmd = command.map[name] + if cmd and cmd.predicate() then + cmd.perform() + return true + end + return false +end + + +function command.perform(...) + local ok, res = core.try(perform, ...) + return not ok or res +end + + +function command.add_defaults() + local reg = { "core", "root", "command", "doc", "findreplace" } + for _, name in ipairs(reg) do + require("core.commands." .. name) + end +end + + +return command diff --git a/tools/editor/art/lite/data/core/commands/command.lua b/tools/editor/art/lite/data/core/commands/command.lua new file mode 100644 index 0000000..f0b8007 --- /dev/null +++ b/tools/editor/art/lite/data/core/commands/command.lua @@ -0,0 +1,30 @@ +local core = require "core" +local command = require "core.command" +local CommandView = require "core.commandview" + +local function has_commandview() + return core.active_view:is(CommandView) +end + + +command.add(has_commandview, { + ["command:submit"] = function() + core.active_view:submit() + end, + + ["command:complete"] = function() + core.active_view:complete() + end, + + ["command:escape"] = function() + core.active_view:exit() + end, + + ["command:select-previous"] = function() + core.active_view:move_suggestion_idx(1) + end, + + ["command:select-next"] = function() + core.active_view:move_suggestion_idx(-1) + end, +}) diff --git a/tools/editor/art/lite/data/core/commands/core.lua b/tools/editor/art/lite/data/core/commands/core.lua new file mode 100644 index 0000000..4ca8f02 --- /dev/null +++ b/tools/editor/art/lite/data/core/commands/core.lua @@ -0,0 +1,105 @@ +local core = require "core" +local common = require "core.common" +local command = require "core.command" +local keymap = require "core.keymap" +local LogView = require "core.logview" + + +local fullscreen = false + +command.add(nil, { + ["core:quit"] = function() + core.quit() + end, + + ["core:force-quit"] = function() + core.quit(true) + end, + + ["core:toggle-fullscreen"] = function() + fullscreen = not fullscreen + system.set_window_mode(fullscreen and "fullscreen" or "normal") + end, + + ["core:reload-module"] = function() + core.command_view:enter("Reload Module", function(text, item) + local text = item and item.text or text + core.reload_module(text) + core.log("Reloaded module %q", text) + end, function(text) + local items = {} + for name in pairs(package.loaded) do + table.insert(items, name) + end + return common.fuzzy_match(items, text) + end) + end, + + ["core:find-command"] = function() + local commands = command.get_all_valid() + core.command_view:enter("Do Command", function(text, item) + if item then + command.perform(item.command) + end + end, function(text) + local res = common.fuzzy_match(commands, text) + for i, name in ipairs(res) do + res[i] = { + text = command.prettify_name(name), + info = keymap.get_binding(name), + command = name, + } + end + return res + end) + end, + + ["core:find-file"] = function() + core.command_view:enter("Open File From Project", function(text, item) + text = item and item.text or text + core.root_view:open_doc(core.open_doc(text)) + end, function(text) + local files = {} + for _, item in pairs(core.project_files) do + if item.type == "file" then + table.insert(files, item.filename) + end + end + return common.fuzzy_match(files, text) + end) + end, + + ["core:new-doc"] = function() + core.root_view:open_doc(core.open_doc()) + end, + + ["core:open-file"] = function() + core.command_view:enter("Open File", function(text) + core.root_view:open_doc(core.open_doc(text)) + end, common.path_suggest) + end, + + ["core:open-log"] = function() + local node = core.root_view:get_active_node() + node:add_view(LogView()) + end, + + ["core:open-user-module"] = function() + if system.get_file_info(EXEDIR .. "/data/user/init.lua") then --< @r-lyeh + core.root_view:open_doc(core.open_doc(EXEDIR .. "/data/user/init.lua")) + else + core.root_view:open_doc(core.open_doc(DATADIR .. "/data/user/init.lua")) + end + end, + + ["core:open-project-module"] = function() + local filename = ".lite_project.lua" + if system.get_file_info(filename) then + core.root_view:open_doc(core.open_doc(filename)) + else + local doc = core.open_doc() + core.root_view:open_doc(doc) + doc:save(filename) + end + end, +}) diff --git a/tools/editor/art/lite/data/core/commands/doc.lua b/tools/editor/art/lite/data/core/commands/doc.lua new file mode 100644 index 0000000..494901e --- /dev/null +++ b/tools/editor/art/lite/data/core/commands/doc.lua @@ -0,0 +1,392 @@ +local core = require "core" +local command = require "core.command" +local common = require "core.common" +local config = require "core.config" +local translate = require "core.doc.translate" +local DocView = require "core.docview" + + +local function dv() + return core.active_view +end + + +local function doc() + return core.active_view.doc +end + + +local function get_indent_string() + if config.tab_type == "hard" then + return "\t" + end + return string.rep(" ", config.indent_size) +end + + +local function insert_at_start_of_selected_lines(text, skip_empty) + local line1, col1, line2, col2, swap = doc():get_selection(true) + for line = line1, line2 do + local line_text = doc().lines[line] + if (not skip_empty or line_text:find("%S")) then + doc():insert(line, 1, text) + end + end + doc():set_selection(line1, col1 + #text, line2, col2 + #text, swap) +end + + +local function remove_from_start_of_selected_lines(text, skip_empty) + local line1, col1, line2, col2, swap = doc():get_selection(true) + for line = line1, line2 do + local line_text = doc().lines[line] + if line_text:sub(1, #text) == text + and (not skip_empty or line_text:find("%S")) + then + doc():remove(line, 1, line, #text + 1) + end + end + doc():set_selection(line1, col1 - #text, line2, col2 - #text, swap) +end + + +local function append_line_if_last_line(line) + if line >= #doc().lines then + doc():insert(line, math.huge, "\n") + end +end + + +local function save(filename) + doc():save(filename) + core.log("Saved \"%s\"", doc().filename) +end + + +local commands = { + ["doc:undo"] = function() + doc():undo() + end, + + ["doc:redo"] = function() + doc():redo() + end, + + ["doc:cut"] = function() + if doc():has_selection() then + local text = doc():get_text(doc():get_selection()) + system.set_clipboard(text) + doc():delete_to(0) +--< https://github.com/rxi/lite/pull/209/commits/479c58fb3dbaa0467afeffa815dd6e2a425281fa + else + local line = doc():get_selection() + local text = doc().lines[line] + system.set_clipboard(text) + core.line_in_clipboard = text + if line < #doc().lines then + doc():remove(line, 1, line + 1, 1) + else + doc():remove(line - 1, math.huge, line, math.huge) + end + end +--< + end, + + ["doc:copy"] = function() +--< https://github.com/rxi/lite/pull/209/commits/479c58fb3dbaa0467afeffa815dd6e2a425281fa + local line1, col1, line2, col2, text = doc():get_selection() + if doc():has_selection() then + text = doc():get_text(line1, col1, line2, col2) + else + text = doc().lines[line1] + core.line_in_clipboard = text + end +--< + system.set_clipboard(text) + end, + + ["doc:paste"] = function() +--< https://github.com/rxi/lite/pull/209/commits/479c58fb3dbaa0467afeffa815dd6e2a425281fa + local clipboard = system.get_clipboard():gsub("\r", "") + if core.line_in_clipboard == clipboard then + local line, col = doc():get_selection() + doc():insert(line, 1, clipboard) + doc():set_selection(line+1, col) + else + doc():text_input(clipboard) + end +--< + end, + + ["doc:newline"] = function() + local line, col = doc():get_selection() + local indent = doc().lines[line]:match("^[\t ]*") + if col <= #indent then + indent = indent:sub(#indent + 2 - col) + end + doc():text_input("\n" .. indent) + end, + + ["doc:newline-below"] = function() + local line = doc():get_selection() + local indent = doc().lines[line]:match("^[\t ]*") + doc():insert(line, math.huge, "\n" .. indent) + doc():set_selection(line + 1, math.huge) + end, + + ["doc:newline-above"] = function() + local line = doc():get_selection() + local indent = doc().lines[line]:match("^[\t ]*") + doc():insert(line, 1, indent .. "\n") + doc():set_selection(line, math.huge) + end, + + ["doc:delete"] = function() + local line, col = doc():get_selection() + if not doc():has_selection() and doc().lines[line]:find("^%s*$", col) then + doc():remove(line, col, line, math.huge) + end + doc():delete_to(translate.next_char) + end, + + ["doc:backspace"] = function() + local line, col = doc():get_selection() + if not doc():has_selection() then + local text = doc():get_text(line, 1, line, col) + if #text >= config.indent_size and text:find("^ *$") then + doc():delete_to(0, -config.indent_size) + return + end + end + doc():delete_to(translate.previous_char) + end, + + ["doc:select-all"] = function() + doc():set_selection(1, 1, math.huge, math.huge) + end, + + ["doc:select-none"] = function() + local line, col = doc():get_selection() + doc():set_selection(line, col) + end, + + ["doc:select-lines"] = function() + local line1, _, line2, _, swap = doc():get_selection(true) + append_line_if_last_line(line2) + doc():set_selection(line1, 1, line2 + 1, 1, swap) + end, + + ["doc:select-word"] = function() + local line1, col1 = doc():get_selection(true) + local line1, col1 = translate.start_of_word(doc(), line1, col1) + local line2, col2 = translate.end_of_word(doc(), line1, col1) + doc():set_selection(line2, col2, line1, col1) + end, + + ["doc:join-lines"] = function() + local line1, _, line2 = doc():get_selection(true) + if line1 == line2 then line2 = line2 + 1 end + local text = doc():get_text(line1, 1, line2, math.huge) +--< https://github.com/rxi/lite/pull/209/commits/479c58fb3dbaa0467afeffa815dd6e2a425281fa + text = text:gsub("\n[\t ]*", " ") +--< + doc():insert(line1, 1, text) + doc():remove(line1, #text + 1, line2, math.huge) + if doc():has_selection() then + doc():set_selection(line1, math.huge) + end + end, + + ["doc:indent"] = function() + local text = get_indent_string() + if doc():has_selection() then + insert_at_start_of_selected_lines(text) + else + doc():text_input(text) + end + end, + + ["doc:unindent"] = function() + local text = get_indent_string() + remove_from_start_of_selected_lines(text) + end, + + ["doc:duplicate-lines"] = function() + local line1, col1, line2, col2, swap = doc():get_selection(true) + append_line_if_last_line(line2) + local text = doc():get_text(line1, 1, line2 + 1, 1) + doc():insert(line2 + 1, 1, text) + local n = line2 - line1 + 1 + doc():set_selection(line1 + n, col1, line2 + n, col2, swap) + end, + + ["doc:delete-lines"] = function() + local line1, col1, line2 = doc():get_selection(true) + append_line_if_last_line(line2) + doc():remove(line1, 1, line2 + 1, 1) + doc():set_selection(line1, col1) + end, + + ["doc:move-lines-up"] = function() + local line1, col1, line2, col2, swap = doc():get_selection(true) + append_line_if_last_line(line2) + if line1 > 1 then + local text = doc().lines[line1 - 1] + doc():insert(line2 + 1, 1, text) + doc():remove(line1 - 1, 1, line1, 1) + doc():set_selection(line1 - 1, col1, line2 - 1, col2, swap) + end + end, + + ["doc:move-lines-down"] = function() + local line1, col1, line2, col2, swap = doc():get_selection(true) + append_line_if_last_line(line2 + 1) + if line2 < #doc().lines then + local text = doc().lines[line2 + 1] + doc():remove(line2 + 1, 1, line2 + 2, 1) + doc():insert(line1, 1, text) + doc():set_selection(line1 + 1, col1, line2 + 1, col2, swap) + end + end, + + ["doc:toggle-line-comments"] = function() + local comment = doc().syntax.comment + if not comment then return end + local comment_text = comment .. " " + local line1, _, line2 = doc():get_selection(true) + local uncomment = true + for line = line1, line2 do + local text = doc().lines[line] + if text:find("%S") and text:find(comment_text, 1, true) ~= 1 then + uncomment = false + end + end + if uncomment then + remove_from_start_of_selected_lines(comment_text, true) + else + insert_at_start_of_selected_lines(comment_text, true) + end + end, + + ["doc:upper-case"] = function() + doc():replace(string.upper) + end, + + ["doc:lower-case"] = function() + doc():replace(string.lower) + end, + + ["doc:go-to-line"] = function() + local dv = dv() + + local items + local function init_items() + if items then return end + items = {} + local mt = { __tostring = function(x) return x.text end } + for i, line in ipairs(dv.doc.lines) do + local item = { text = line:sub(1, -2), line = i, info = "line: " .. i } + table.insert(items, setmetatable(item, mt)) + end + end + + core.command_view:enter("Go To Line", function(text, item) + local line = item and item.line or tonumber(text) + if not line then + core.error("Invalid line number or unmatched string") + return + end + dv.doc:set_selection(line, 1 ) + dv:scroll_to_line(line, true) + + end, function(text) + if not text:find("^%d*$") then + init_items() + return common.fuzzy_match(items, text) + end + end) + end, + + ["doc:toggle-line-ending"] = function() + doc().crlf = not doc().crlf + end, + + ["doc:save-as"] = function() + if doc().filename then + core.command_view:set_text(doc().filename) + end + core.command_view:enter("Save As", function(filename) + save(filename) + end, common.path_suggest) + end, + + ["doc:save"] = function() + if doc().filename then + save() + else + command.perform("doc:save-as") + end + end, + + ["doc:rename"] = function() + local old_filename = doc().filename + if not old_filename then + core.error("Cannot rename unsaved doc") + return + end + core.command_view:set_text(old_filename) + core.command_view:enter("Rename", function(filename) + doc():save(filename) + core.log("Renamed \"%s\" to \"%s\"", old_filename, filename) + if filename ~= old_filename then + os.remove(old_filename) + end + end, common.path_suggest) + end, +} + + +local translations = { + ["previous-char"] = translate.previous_char, + ["next-char"] = translate.next_char, + ["previous-word-start"] = translate.previous_word_start, + ["next-word-end"] = translate.next_word_end, + ["previous-block-start"] = translate.previous_block_start, + ["next-block-end"] = translate.next_block_end, + ["start-of-doc"] = translate.start_of_doc, + ["end-of-doc"] = translate.end_of_doc, + ["start-of-line"] = translate.start_of_line, + ["end-of-line"] = translate.end_of_line, + ["start-of-word"] = translate.start_of_word, + ["end-of-word"] = translate.end_of_word, + ["previous-line"] = DocView.translate.previous_line, + ["next-line"] = DocView.translate.next_line, + ["previous-page"] = DocView.translate.previous_page, + ["next-page"] = DocView.translate.next_page, +} + +for name, fn in pairs(translations) do + commands["doc:move-to-" .. name] = function() doc():move_to(fn, dv()) end + commands["doc:select-to-" .. name] = function() doc():select_to(fn, dv()) end + commands["doc:delete-to-" .. name] = function() doc():delete_to(fn, dv()) end +end + +commands["doc:move-to-previous-char"] = function() + if doc():has_selection() then + local line, col = doc():get_selection(true) + doc():set_selection(line, col) + else + doc():move_to(translate.previous_char) + end +end + +commands["doc:move-to-next-char"] = function() + if doc():has_selection() then + local _, _, line, col = doc():get_selection(true) + doc():set_selection(line, col) + else + doc():move_to(translate.next_char) + end +end + +command.add("core.docview", commands) diff --git a/tools/editor/art/lite/data/core/commands/findreplace.lua b/tools/editor/art/lite/data/core/commands/findreplace.lua new file mode 100644 index 0000000..937c410 --- /dev/null +++ b/tools/editor/art/lite/data/core/commands/findreplace.lua @@ -0,0 +1,170 @@ +local core = require "core" +local command = require "core.command" +local config = require "core.config" +local search = require "core.doc.search" +local DocView = require "core.docview" + +local max_previous_finds = 50 + + +local function doc() + return core.active_view.doc +end + + +local previous_finds +local last_doc +local last_fn, last_text + + +local function push_previous_find(doc, sel) + if last_doc ~= doc then + last_doc = doc + previous_finds = {} + end + if #previous_finds >= max_previous_finds then + table.remove(previous_finds, 1) + end + table.insert(previous_finds, sel or { doc:get_selection() }) +end + + +local function find(label, search_fn) + local dv = core.active_view + local sel = { dv.doc:get_selection() } + local text = dv.doc:get_text(table.unpack(sel)) + local found = false + + core.command_view:set_text(text, true) + + core.command_view:enter(label, function(text) + if found then + last_fn, last_text = search_fn, text + previous_finds = {} + push_previous_find(dv.doc, sel) + else + core.error("Couldn't find %q", text) + dv.doc:set_selection(table.unpack(sel)) + dv:scroll_to_make_visible(sel[1], sel[2]) + end + + end, function(text) + local ok, line1, col1, line2, col2 = pcall(search_fn, dv.doc, sel[1], sel[2], text) + if ok and line1 and text ~= "" then + dv.doc:set_selection(line2, col2, line1, col1) + dv:scroll_to_line(line2, true) + found = true + else + dv.doc:set_selection(table.unpack(sel)) + found = false + end + + end, function(explicit) + if explicit then + dv.doc:set_selection(table.unpack(sel)) + dv:scroll_to_make_visible(sel[1], sel[2]) + end + end) +end + + +local function replace(kind, default, fn) + core.command_view:set_text(default, true) + + core.command_view:enter("Find To Replace " .. kind, function(old) + core.command_view:set_text(old, true) + + local s = string.format("Replace %s %q With", kind, old) + core.command_view:enter(s, function(new) + local n = doc():replace(function(text) + return fn(text, old, new) + end) + core.log("Replaced %d instance(s) of %s %q with %q", n, kind, old, new) + end) + end) +end + + +local function has_selection() + return core.active_view:is(DocView) + and core.active_view.doc:has_selection() +end + +command.add(has_selection, { + ["find-replace:select-next"] = function() + local l1, c1, l2, c2 = doc():get_selection(true) + local text = doc():get_text(l1, c1, l2, c2) + local l1, c1, l2, c2 = search.find(doc(), l2, c2, text, { wrap = true }) + if l2 then doc():set_selection(l2, c2, l1, c1) end + end +}) + +command.add("core.docview", { + ["find-replace:find"] = function() + find("Find Text", function(doc, line, col, text) + local opt = { wrap = true, no_case = true } + return search.find(doc, line, col, text, opt) + end) + end, + + ["find-replace:find-pattern"] = function() + find("Find Text Pattern", function(doc, line, col, text) + local opt = { wrap = true, no_case = true, pattern = true } + return search.find(doc, line, col, text, opt) + end) + end, + + ["find-replace:repeat-find"] = function() + if not last_fn then + core.error("No find to continue from") + else + local line, col = doc():get_selection() + local line1, col1, line2, col2 = last_fn(doc(), line, col, last_text) + if line1 then + push_previous_find(doc()) + doc():set_selection(line2, col2, line1, col1) + core.active_view:scroll_to_line(line2, true) + end + end + end, + + ["find-replace:previous-find"] = function() + local sel = table.remove(previous_finds) + if not sel or doc() ~= last_doc then + core.error("No previous finds") + return + end + doc():set_selection(table.unpack(sel)) + core.active_view:scroll_to_line(sel[3], true) + end, + + ["find-replace:replace"] = function() + replace("Text", "", function(text, old, new) + return text:gsub(old:gsub("%W", "%%%1"), new:gsub("%%", "%%%%"), nil) + end) + end, + + ["find-replace:replace-pattern"] = function() + replace("Pattern", "", function(text, old, new) + return text:gsub(old, new) + end) + end, + + ["find-replace:replace-symbol"] = function() + local first = "" + if doc():has_selection() then + local text = doc():get_text(doc():get_selection()) + first = text:match(config.symbol_pattern) or "" + end + replace("Symbol", first, function(text, old, new) + local n = 0 + local res = text:gsub(config.symbol_pattern, function(sym) + if old == sym then + n = n + 1 + return new + end + end) + return res, n + end) + end, +}) diff --git a/tools/editor/art/lite/data/core/commands/root.lua b/tools/editor/art/lite/data/core/commands/root.lua new file mode 100644 index 0000000..58c83e2 --- /dev/null +++ b/tools/editor/art/lite/data/core/commands/root.lua @@ -0,0 +1,105 @@ +local core = require "core" +local style = require "core.style" +local DocView = require "core.docview" +local command = require "core.command" +local common = require "core.common" + + +local t = { + ["root:close"] = function() + local node = core.root_view:get_active_node() + node:close_active_view(core.root_view.root_node) + end, + + ["root:switch-to-previous-tab"] = function() + local node = core.root_view:get_active_node() + local idx = node:get_view_idx(core.active_view) + idx = idx - 1 + if idx < 1 then idx = #node.views end + node:set_active_view(node.views[idx]) + end, + + ["root:switch-to-next-tab"] = function() + local node = core.root_view:get_active_node() + local idx = node:get_view_idx(core.active_view) + idx = idx + 1 + if idx > #node.views then idx = 1 end + node:set_active_view(node.views[idx]) + end, + + ["root:move-tab-left"] = function() + local node = core.root_view:get_active_node() + local idx = node:get_view_idx(core.active_view) + if idx > 1 then + table.remove(node.views, idx) + table.insert(node.views, idx - 1, core.active_view) + end + end, + + ["root:move-tab-right"] = function() + local node = core.root_view:get_active_node() + local idx = node:get_view_idx(core.active_view) + if idx < #node.views then + table.remove(node.views, idx) + table.insert(node.views, idx + 1, core.active_view) + end + end, + + ["root:shrink"] = function() + local node = core.root_view:get_active_node() + local parent = node:get_parent_node(core.root_view.root_node) + local n = (parent.a == node) and -0.1 or 0.1 + parent.divider = common.clamp(parent.divider + n, 0.1, 0.9) + end, + + ["root:grow"] = function() + local node = core.root_view:get_active_node() + local parent = node:get_parent_node(core.root_view.root_node) + local n = (parent.a == node) and 0.1 or -0.1 + parent.divider = common.clamp(parent.divider + n, 0.1, 0.9) + end, +} + + +for i = 1, 9 do + t["root:switch-to-tab-" .. i] = function() + local node = core.root_view:get_active_node() + local view = node.views[i] + if view then + node:set_active_view(view) + end + end +end + + +for _, dir in ipairs { "left", "right", "up", "down" } do + t["root:split-" .. dir] = function() + local node = core.root_view:get_active_node() + local av = node.active_view + node:split(dir) + if av:is(DocView) then + core.root_view:open_doc(av.doc) + end + end + + t["root:switch-to-" .. dir] = function() + local node = core.root_view:get_active_node() + local x, y + if dir == "left" or dir == "right" then + y = node.position.y + node.size.y / 2 + x = node.position.x + (dir == "left" and -1 or node.size.x + style.divider_size) + else + x = node.position.x + node.size.x / 2 + y = node.position.y + (dir == "up" and -1 or node.size.y + style.divider_size) + end + local node = core.root_view.root_node:get_child_overlapping_point(x, y) + if not node:get_locked_size() then + core.set_active_view(node.active_view) + end + end +end + +command.add(function() + local node = core.root_view:get_active_node() + return not node:get_locked_size() +end, t) diff --git a/tools/editor/art/lite/data/core/commandview.lua b/tools/editor/art/lite/data/core/commandview.lua new file mode 100644 index 0000000..3fbb1ff --- /dev/null +++ b/tools/editor/art/lite/data/core/commandview.lua @@ -0,0 +1,256 @@ +local core = require "core" +local common = require "core.common" +local style = require "core.style" +local Doc = require "core.doc" +local DocView = require "core.docview" +local View = require "core.view" + + +local SingleLineDoc = Doc:extend() + +function SingleLineDoc:insert(line, col, text) + SingleLineDoc.super.insert(self, line, col, text:gsub("\n", "")) +end + + +local CommandView = DocView:extend() + +local max_suggestions = 10 + +local noop = function() end + +local default_state = { + submit = noop, + suggest = noop, + cancel = noop, +} + + +function CommandView:new() + CommandView.super.new(self, SingleLineDoc()) + self.suggestion_idx = 1 + self.suggestions = {} + self.suggestions_height = 0 + self.last_change_id = 0 + self.gutter_width = 0 + self.gutter_text_brightness = 0 + self.selection_offset = 0 + self.state = default_state + self.font = "font" + self.size.y = 0 + self.label = "" +end + + +function CommandView:get_name() + return View.get_name(self) +end + + +function CommandView:get_line_screen_position() + local x = CommandView.super.get_line_screen_position(self, 1) + local _, y = self:get_content_offset() + local lh = self:get_line_height() + return x, y + (self.size.y - lh) / 2 +end + + +function CommandView:get_scrollable_size() + return 0 +end + + +function CommandView:scroll_to_make_visible() + -- no-op function to disable this functionality +end + + +function CommandView:get_text() + return self.doc:get_text(1, 1, 1, math.huge) +end + + +function CommandView:set_text(text, select) + self.doc:remove(1, 1, math.huge, math.huge) + self.doc:text_input(text) + if select then + self.doc:set_selection(math.huge, math.huge, 1, 1) + end +end + + +function CommandView:move_suggestion_idx(dir) + local n = self.suggestion_idx + dir + self.suggestion_idx = common.clamp(n, 1, #self.suggestions) + self:complete() + self.last_change_id = self.doc:get_change_id() +end + + +function CommandView:complete() + if #self.suggestions > 0 then + self:set_text(self.suggestions[self.suggestion_idx].text) + end +end + + +function CommandView:submit() + local suggestion = self.suggestions[self.suggestion_idx] + local text = self:get_text() + local submit = self.state.submit + self:exit(true) + submit(text, suggestion) +end + + +function CommandView:enter(text, submit, suggest, cancel) + if self.state ~= default_state then + return + end + self.state = { + submit = submit or noop, + suggest = suggest or noop, + cancel = cancel or noop, + } + core.set_active_view(self) + self:update_suggestions() + self.gutter_text_brightness = 100 + self.label = text .. ": " +end + + +function CommandView:exit(submitted, inexplicit) + if core.active_view == self then + core.set_active_view(core.last_active_view) + end + local cancel = self.state.cancel + self.state = default_state + self.doc:reset() + self.suggestions = {} + if not submitted then cancel(not inexplicit) end +end + + +function CommandView:get_gutter_width() + return self.gutter_width +end + + +function CommandView:get_suggestion_line_height() + return self:get_font():get_height() + style.padding.y +end + + +function CommandView:update_suggestions() + local t = self.state.suggest(self:get_text()) or {} + local res = {} + for i, item in ipairs(t) do + if i == max_suggestions then + break + end + if type(item) == "string" then + item = { text = item } + end + res[i] = item + end + self.suggestions = res + self.suggestion_idx = 1 +end + + +function CommandView:update() + CommandView.super.update(self) + + if core.active_view ~= self and self.state ~= default_state then + self:exit(false, true) + end + + -- update suggestions if text has changed + if self.last_change_id ~= self.doc:get_change_id() then + self:update_suggestions() + self.last_change_id = self.doc:get_change_id() + end + + -- update gutter text color brightness + self:move_towards("gutter_text_brightness", 0, 0.1) + + -- update gutter width + local dest = self:get_font():get_width(self.label) + style.padding.x + if self.size.y <= 0 then + self.gutter_width = dest + else + self:move_towards("gutter_width", dest) + end + + -- update suggestions box height + local lh = self:get_suggestion_line_height() + local dest = #self.suggestions * lh + self:move_towards("suggestions_height", dest) + + -- update suggestion cursor offset + local dest = self.suggestion_idx * self:get_suggestion_line_height() + self:move_towards("selection_offset", dest) + + -- update size based on whether this is the active_view + local dest = 0 + if self == core.active_view then + dest = style.font:get_height() + style.padding.y * 2 + end + self:move_towards(self.size, "y", dest) +end + + +function CommandView:draw_line_highlight() + -- no-op function to disable this functionality +end + + +function CommandView:draw_line_gutter(idx, x, y) + local yoffset = self:get_line_text_y_offset() + local pos = self.position + local color = common.lerp(style.text, style.accent, self.gutter_text_brightness / 100) + core.push_clip_rect(pos.x, pos.y, self:get_gutter_width(), self.size.y) + x = x + style.padding.x + renderer.draw_text(self:get_font(), self.label, x, y + yoffset, color) + core.pop_clip_rect() +end + + +local function draw_suggestions_box(self) + local lh = self:get_suggestion_line_height() + local dh = style.divider_size + local x, _ = self:get_line_screen_position() + local h = math.ceil(self.suggestions_height) + local rx, ry, rw, rh = self.position.x, self.position.y - h - dh, self.size.x, h + + -- draw suggestions background + if #self.suggestions > 0 then + renderer.draw_rect(rx, ry, rw, rh, style.background3) + renderer.draw_rect(rx, ry - dh, rw, dh, style.divider) + local y = self.position.y - self.selection_offset - dh + renderer.draw_rect(rx, y, rw, lh, style.line_highlight) + end + + -- draw suggestion text + core.push_clip_rect(rx, ry, rw, rh) + for i, item in ipairs(self.suggestions) do + local color = (i == self.suggestion_idx) and style.accent or style.text + local y = self.position.y - i * lh - dh + common.draw_text(self:get_font(), color, item.text, nil, x, y, 0, lh) + + if item.info then + local w = self.size.x - x - style.padding.x + common.draw_text(self:get_font(), style.dim, item.info, "right", x, y, w, lh) + end + end + core.pop_clip_rect() +end + + +function CommandView:draw() + CommandView.super.draw(self) + core.root_view:defer_draw(draw_suggestions_box, self) +end + + +return CommandView diff --git a/tools/editor/art/lite/data/core/common.lua b/tools/editor/art/lite/data/core/common.lua new file mode 100644 index 0000000..80fe6a4 --- /dev/null +++ b/tools/editor/art/lite/data/core/common.lua @@ -0,0 +1,147 @@ +local common = {} + + +function common.is_utf8_cont(char) + local byte = char:byte() + return byte >= 0x80 and byte < 0xc0 +end + + +function common.utf8_chars(text) + return text:gmatch("[\0-\x7f\xc2-\xf4][\x80-\xbf]*") +end + +--< https://github.com/rxi/lite/issues/300 +function common.utf8_len(text) + local len = 0 + for char in common.utf8_chars(text) do len = len + 1 end + return len +end +--< + +function common.clamp(n, lo, hi) + return math.max(math.min(n, hi), lo) +end + + +function common.round(n) + return n >= 0 and math.floor(n + 0.5) or math.ceil(n - 0.5) +end + + +function common.lerp(a, b, t) + if type(a) ~= "table" then + return a + (b - a) * t + end + local res = {} + for k, v in pairs(b) do + res[k] = common.lerp(a[k], v, t) + end + return res +end + + +function common.color(str) + local r, g, b, a = str:match("#(%x%x)(%x%x)(%x%x)") + if r then + r = tonumber(r, 16) + g = tonumber(g, 16) + b = tonumber(b, 16) + a = 1 + elseif str:match("rgba?%s*%([%d%s%.,]+%)") then + local f = str:gmatch("[%d.]+") + r = (f() or 0) + g = (f() or 0) + b = (f() or 0) + a = f() or 1 + else + error(string.format("bad color string '%s'", str)) + end + return r, g, b, a * 0xff +end + + +local function compare_score(a, b) + return a.score > b.score +end + +local function fuzzy_match_items(items, needle) + local res = {} + for _, item in ipairs(items) do + local score = system.fuzzy_match(tostring(item), needle) + if score then + table.insert(res, { text = item, score = score }) + end + end + table.sort(res, compare_score) + for i, item in ipairs(res) do + res[i] = item.text + end + return res +end + + +function common.fuzzy_match(haystack, needle) + if type(haystack) == "table" then + return fuzzy_match_items(haystack, needle) + end + return system.fuzzy_match(haystack, needle) +end + + +function common.path_suggest(text) + local path, name = text:match("^(.-)([^/\\]*)$") + local files = system.list_dir(path == "" and "." or path) or {} + local res = {} + for _, file in ipairs(files) do + file = path .. file + local info = system.get_file_info(file) + if info then + if info.type == "dir" then + file = file .. PATHSEP + end + if file:lower():find(text:lower(), nil, true) == 1 then + table.insert(res, file) + end + end + end + return res +end + + +function common.match_pattern(text, pattern, ...) + if type(pattern) == "string" then + return text:find(pattern, ...) + end + for _, p in ipairs(pattern) do + local s, e = common.match_pattern(text, p, ...) + if s then return s, e end + end + return false +end + + +function common.draw_text(font, color, text, align, x,y,w,h) + local tw, th = font:get_width(text), font:get_height(text) + if align == "center" then + x = x + (w - tw) / 2 + elseif align == "right" then + x = x + (w - tw) + end + y = common.round(y + (h - th) / 2) + return renderer.draw_text(font, text, x, y, color), y + th +end + + +function common.bench(name, fn, ...) + local start = system.get_time() + local res = fn(...) + local t = system.get_time() - start + local ms = t * 1000 + local per = (t / (1 / 60)) * 100 + print(string.format("*** %-16s : %8.3fms %6.2f%%", name, ms, per)) + return res +end + + +return common diff --git a/tools/editor/art/lite/data/core/config.lua b/tools/editor/art/lite/data/core/config.lua new file mode 100644 index 0000000..098a869 --- /dev/null +++ b/tools/editor/art/lite/data/core/config.lua @@ -0,0 +1,24 @@ +local config = {} + +config.project_scan_rate = 5000 --< @r-lyeh: 5 -> 5000: from 5ms to 5s +config.fps = 60 +config.max_log_items = 80 +config.message_timeout = 3 +config.mouse_wheel_scroll = 50 * SCALE +config.file_size_limit = 10 +config.ignore_files = "^%." +config.symbol_pattern = "[%a_][%w_]*" +config.non_word_chars = " \t\n/\\()\"':,.;<>~!@#$%^&*|+=[]{}`?-" +config.undo_merge_timeout = 0.3 +config.max_undos = 10000 +config.highlight_current_line = true +config.line_height = 1.2 +config.indent_size = 2 +config.tab_type = "soft" +config.line_limit = 80 +config.project_scan_depth = 5 +config.project_max_files_per_folder = 2000 +config.blink_period = 1.3 --< https://github.com/rxi/lite/issues/235 +config.tabs_allowed = true --< https://github.com/rxi/lite/issues/191 + +return config diff --git a/tools/editor/art/lite/data/core/doc/highlighter.lua b/tools/editor/art/lite/data/core/doc/highlighter.lua new file mode 100644 index 0000000..e7650d0 --- /dev/null +++ b/tools/editor/art/lite/data/core/doc/highlighter.lua @@ -0,0 +1,80 @@ +local core = require "core" +local config = require "core.config" +local tokenizer = require "core.tokenizer" +local Object = require "core.object" + + +local Highlighter = Object:extend() + + +function Highlighter:new(doc) + self.doc = doc + self:reset() + + -- init incremental syntax highlighting + core.add_thread(function() + while true do + if self.first_invalid_line > self.max_wanted_line then + self.max_wanted_line = 0 + coroutine.yield(1 / config.fps) + + else + local max = math.min(self.first_invalid_line + 40, self.max_wanted_line) + + for i = self.first_invalid_line, max do + local state = (i > 1) and self.lines[i - 1].state + local line = self.lines[i] + if not (line and line.init_state == state) then + self.lines[i] = self:tokenize_line(i, state) + end + end + + self.first_invalid_line = max + 1 + core.redraw = true + coroutine.yield() + end + end + end, self) +end + + +function Highlighter:reset() + self.lines = {} + self.first_invalid_line = 1 + self.max_wanted_line = 0 +end + + +function Highlighter:invalidate(idx) + self.first_invalid_line = math.min(self.first_invalid_line, idx) + self.max_wanted_line = math.min(self.max_wanted_line, #self.doc.lines) +end + + +function Highlighter:tokenize_line(idx, state) + local res = {} + res.init_state = state + res.text = self.doc.lines[idx] + res.tokens, res.state = tokenizer.tokenize(self.doc.syntax, res.text, state) + return res +end + + +function Highlighter:get_line(idx) + local line = self.lines[idx] + if not line or line.text ~= self.doc.lines[idx] then + local prev = self.lines[idx - 1] + line = self:tokenize_line(idx, prev and prev.state) + self.lines[idx] = line + end + self.max_wanted_line = math.max(self.max_wanted_line, idx) + return line +end + + +function Highlighter:each_token(idx) + return tokenizer.each_token(self:get_line(idx).tokens) +end + + +return Highlighter diff --git a/tools/editor/art/lite/data/core/doc/init.lua b/tools/editor/art/lite/data/core/doc/init.lua new file mode 100644 index 0000000..83b5fc0 --- /dev/null +++ b/tools/editor/art/lite/data/core/doc/init.lua @@ -0,0 +1,393 @@ +local Object = require "core.object" +local Highlighter = require "core.doc.highlighter" +local syntax = require "core.syntax" +local config = require "core.config" +local common = require "core.common" + + +local Doc = Object:extend() + + +local function split_lines(text) + local res = {} + for line in (text .. "\n"):gmatch("(.-)\n") do + table.insert(res, line) + end + return res +end + + +local function splice(t, at, remove, insert) + insert = insert or {} + local offset = #insert - remove + local old_len = #t + if offset < 0 then + for i = at - offset, old_len - offset do + t[i + offset] = t[i] + end + elseif offset > 0 then + for i = old_len, at, -1 do + t[i + offset] = t[i] + end + end + for i, item in ipairs(insert) do + t[at + i - 1] = item + end +end + + +function Doc:new(filename) + self:reset() + if filename then + self:load(filename) + end +end + + +function Doc:reset() + self.lines = { "\n" } + self.selection = { a = { line=1, col=1 }, b = { line=1, col=1 } } + self.undo_stack = { idx = 1 } + self.redo_stack = { idx = 1 } + self.clean_change_id = 1 + self.highlighter = Highlighter(self) + self:reset_syntax() +end + + +function Doc:reset_syntax() + local header = self:get_text(1, 1, self:position_offset(1, 1, 128)) + local syn = syntax.get(self.filename or "", header) + if self.syntax ~= syn then + self.syntax = syn + self.highlighter:reset() + end +end + + +function Doc:load(filename) + local fp = assert( io.open(filename, "rb") ) + self:reset() + self.filename = filename + self.lines = {} + for line in fp:lines() do + if line:byte(-1) == 13 then + line = line:sub(1, -2) + self.crlf = true + end + table.insert(self.lines, line .. "\n") + end + if #self.lines == 0 then + table.insert(self.lines, "\n") + end + fp:close() + self:reset_syntax() +end + + +function Doc:save(filename) + filename = filename or assert(self.filename, "no filename set to default to") + local fp = assert( io.open(filename, "wb") ) + for _, line in ipairs(self.lines) do + if self.crlf then line = line:gsub("\n", "\r\n") end + fp:write(line) + end + fp:close() + self.filename = filename or self.filename + self:reset_syntax() + self:clean() +end + + +function Doc:get_name() + return self.filename or "unsaved" +end + + +function Doc:is_dirty() + return self.clean_change_id ~= self:get_change_id() +end + + +function Doc:clean() + self.clean_change_id = self:get_change_id() +end + + +function Doc:get_change_id() + return self.undo_stack.idx +end + + +function Doc:set_selection(line1, col1, line2, col2, swap) + assert(not line2 == not col2, "expected 2 or 4 arguments") + if swap then line1, col1, line2, col2 = line2, col2, line1, col1 end + line1, col1 = self:sanitize_position(line1, col1) + line2, col2 = self:sanitize_position(line2 or line1, col2 or col1) + self.selection.a.line, self.selection.a.col = line1, col1 + self.selection.b.line, self.selection.b.col = line2, col2 +end + + +local function sort_positions(line1, col1, line2, col2) + if line1 > line2 + or line1 == line2 and col1 > col2 then + return line2, col2, line1, col1, true + end + return line1, col1, line2, col2, false +end + + +function Doc:get_selection(sort) + local a, b = self.selection.a, self.selection.b + if sort then + return sort_positions(a.line, a.col, b.line, b.col) + end + return a.line, a.col, b.line, b.col +end + + +function Doc:has_selection() + local a, b = self.selection.a, self.selection.b + return not (a.line == b.line and a.col == b.col) +end + + +function Doc:sanitize_selection() + self:set_selection(self:get_selection()) +end + + +function Doc:sanitize_position(line, col) + line = common.clamp(line, 1, #self.lines) + col = common.clamp(col, 1, #self.lines[line]) + return line, col +end + + +local function position_offset_func(self, line, col, fn, ...) + line, col = self:sanitize_position(line, col) + return fn(self, line, col, ...) +end + + +local function position_offset_byte(self, line, col, offset) + line, col = self:sanitize_position(line, col) + col = col + offset + while line > 1 and col < 1 do + line = line - 1 + col = col + #self.lines[line] + end + while line < #self.lines and col > #self.lines[line] do + col = col - #self.lines[line] + line = line + 1 + end + return self:sanitize_position(line, col) +end + + +local function position_offset_linecol(self, line, col, lineoffset, coloffset) + return self:sanitize_position(line + lineoffset, col + coloffset) +end + + +function Doc:position_offset(line, col, ...) + if type(...) ~= "number" then + return position_offset_func(self, line, col, ...) + elseif select("#", ...) == 1 then + return position_offset_byte(self, line, col, ...) + elseif select("#", ...) == 2 then + return position_offset_linecol(self, line, col, ...) + else + error("bad number of arguments") + end +end + + +function Doc:get_text(line1, col1, line2, col2) + line1, col1 = self:sanitize_position(line1, col1) + line2, col2 = self:sanitize_position(line2, col2) + line1, col1, line2, col2 = sort_positions(line1, col1, line2, col2) + if line1 == line2 then + return self.lines[line1]:sub(col1, col2 - 1) + end + local lines = { self.lines[line1]:sub(col1) } + for i = line1 + 1, line2 - 1 do + table.insert(lines, self.lines[i]) + end + table.insert(lines, self.lines[line2]:sub(1, col2 - 1)) + return table.concat(lines) +end + + +function Doc:get_char(line, col) + line, col = self:sanitize_position(line, col) + return self.lines[line]:sub(col, col) +end + + +local function push_undo(undo_stack, time, type, ...) + undo_stack[undo_stack.idx] = { type = type, time = time, ... } + undo_stack[undo_stack.idx - config.max_undos] = nil + undo_stack.idx = undo_stack.idx + 1 +end + + +local function pop_undo(self, undo_stack, redo_stack) + -- pop command + local cmd = undo_stack[undo_stack.idx - 1] + if not cmd then return end + undo_stack.idx = undo_stack.idx - 1 + + -- handle command + if cmd.type == "insert" then + local line, col, text = table.unpack(cmd) + self:raw_insert(line, col, text, redo_stack, cmd.time) + + elseif cmd.type == "remove" then + local line1, col1, line2, col2 = table.unpack(cmd) + self:raw_remove(line1, col1, line2, col2, redo_stack, cmd.time) + + elseif cmd.type == "selection" then + self.selection.a.line, self.selection.a.col = cmd[1], cmd[2] + self.selection.b.line, self.selection.b.col = cmd[3], cmd[4] + end + + -- if next undo command is within the merge timeout then treat as a single + -- command and continue to execute it + local next = undo_stack[undo_stack.idx - 1] + if next and math.abs(cmd.time - next.time) < config.undo_merge_timeout then + return pop_undo(self, undo_stack, redo_stack) + end +end + + +function Doc:raw_insert(line, col, text, undo_stack, time) + -- split text into lines and merge with line at insertion point + local lines = split_lines(text) + local before = self.lines[line]:sub(1, col - 1) + local after = self.lines[line]:sub(col) + for i = 1, #lines - 1 do + lines[i] = lines[i] .. "\n" + end + lines[1] = before .. lines[1] + lines[#lines] = lines[#lines] .. after + + -- splice lines into line array + splice(self.lines, line, 1, lines) + + -- push undo + local line2, col2 = self:position_offset(line, col, #text) + push_undo(undo_stack, time, "selection", self:get_selection()) + push_undo(undo_stack, time, "remove", line, col, line2, col2) + + -- update highlighter and assure selection is in bounds + self.highlighter:invalidate(line) + self:sanitize_selection() +end + + +function Doc:raw_remove(line1, col1, line2, col2, undo_stack, time) + -- push undo + local text = self:get_text(line1, col1, line2, col2) + push_undo(undo_stack, time, "selection", self:get_selection()) + push_undo(undo_stack, time, "insert", line1, col1, text) + + -- get line content before/after removed text + local before = self.lines[line1]:sub(1, col1 - 1) + local after = self.lines[line2]:sub(col2) + + -- splice line into line array + splice(self.lines, line1, line2 - line1 + 1, { before .. after }) + + -- update highlighter and assure selection is in bounds + self.highlighter:invalidate(line1) + self:sanitize_selection() +end + + +function Doc:insert(line, col, text) + self.redo_stack = { idx = 1 } + line, col = self:sanitize_position(line, col) + self:raw_insert(line, col, text, self.undo_stack, system.get_time()) +end + + +function Doc:remove(line1, col1, line2, col2) + self.redo_stack = { idx = 1 } + line1, col1 = self:sanitize_position(line1, col1) + line2, col2 = self:sanitize_position(line2, col2) + line1, col1, line2, col2 = sort_positions(line1, col1, line2, col2) + self:raw_remove(line1, col1, line2, col2, self.undo_stack, system.get_time()) +end + + +function Doc:undo() + pop_undo(self, self.undo_stack, self.redo_stack) +end + + +function Doc:redo() + pop_undo(self, self.redo_stack, self.undo_stack) +end + + +function Doc:text_input(text) + if self:has_selection() then + self:delete_to() + end + local line, col = self:get_selection() + self:insert(line, col, text) + self:move_to(#text) +end + + +function Doc:replace(fn) + local line1, col1, line2, col2, swap + local had_selection = self:has_selection() + if had_selection then + line1, col1, line2, col2, swap = self:get_selection(true) + else + line1, col1, line2, col2 = 1, 1, #self.lines, #self.lines[#self.lines] + end + local old_text = self:get_text(line1, col1, line2, col2) + local new_text, n = fn(old_text) + if old_text ~= new_text then + self:insert(line2, col2, new_text) + self:remove(line1, col1, line2, col2) + if had_selection then + line2, col2 = self:position_offset(line1, col1, #new_text) + self:set_selection(line1, col1, line2, col2, swap) + end + end + return n +end + + +function Doc:delete_to(...) + local line, col = self:get_selection(true) + if self:has_selection() then + self:remove(self:get_selection()) + else + local line2, col2 = self:position_offset(line, col, ...) + self:remove(line, col, line2, col2) + line, col = sort_positions(line, col, line2, col2) + end + self:set_selection(line, col) +end + + +function Doc:move_to(...) + local line, col = self:get_selection() + self:set_selection(self:position_offset(line, col, ...)) +end + + +function Doc:select_to(...) + local line, col, line2, col2 = self:get_selection() + line, col = self:position_offset(line, col, ...) + self:set_selection(line, col, line2, col2) +end + + +return Doc diff --git a/tools/editor/art/lite/data/core/doc/search.lua b/tools/editor/art/lite/data/core/doc/search.lua new file mode 100644 index 0000000..fe57523 --- /dev/null +++ b/tools/editor/art/lite/data/core/doc/search.lua @@ -0,0 +1,52 @@ +local search = {} + +local default_opt = {} + + +local function pattern_lower(str) + if str:sub(1, 1) == "%" then + return str + end + return str:lower() +end + + +local function init_args(doc, line, col, text, opt) + opt = opt or default_opt + line, col = doc:sanitize_position(line, col) + + if opt.no_case then + if opt.pattern then + text = text:gsub("%%?.", pattern_lower) + else + text = text:lower() + end + end + + return doc, line, col, text, opt +end + + +function search.find(doc, line, col, text, opt) + doc, line, col, text, opt = init_args(doc, line, col, text, opt) + + for line = line, #doc.lines do + local line_text = doc.lines[line] + if opt.no_case then + line_text = line_text:lower() + end + local s, e = line_text:find(text, col, not opt.pattern) + if s then + return line, s, line, e + 1 + end + col = 1 + end + + if opt.wrap then + opt = { no_case = opt.no_case, pattern = opt.pattern } + return search.find(doc, 1, 1, text, opt) + end +end + + +return search diff --git a/tools/editor/art/lite/data/core/doc/translate.lua b/tools/editor/art/lite/data/core/doc/translate.lua new file mode 100644 index 0000000..b084e89 --- /dev/null +++ b/tools/editor/art/lite/data/core/doc/translate.lua @@ -0,0 +1,136 @@ +local common = require "core.common" +local config = require "core.config" + +-- functions for translating a Doc position to another position these functions +-- can be passed to Doc:move_to|select_to|delete_to() + +local translate = {} + + +local function is_non_word(char) + return config.non_word_chars:find(char, nil, true) +end + + +function translate.previous_char(doc, line, col) + repeat + line, col = doc:position_offset(line, col, -1) + until not common.is_utf8_cont(doc:get_char(line, col)) + return line, col +end + + +function translate.next_char(doc, line, col) + repeat + line, col = doc:position_offset(line, col, 1) + until not common.is_utf8_cont(doc:get_char(line, col)) + return line, col +end + + +function translate.previous_word_start(doc, line, col) + local prev + while line > 1 or col > 1 do + local l, c = doc:position_offset(line, col, -1) + local char = doc:get_char(l, c) + if prev and prev ~= char or not is_non_word(char) then + break + end + prev, line, col = char, l, c + end + return translate.start_of_word(doc, line, col) +end + + +function translate.next_word_end(doc, line, col) + local prev + local end_line, end_col = translate.end_of_doc(doc, line, col) + while line < end_line or col < end_col do + local char = doc:get_char(line, col) + if prev and prev ~= char or not is_non_word(char) then + break + end + line, col = doc:position_offset(line, col, 1) + prev = char + end + return translate.end_of_word(doc, line, col) +end + + +function translate.start_of_word(doc, line, col) + while true do + local line2, col2 = doc:position_offset(line, col, -1) + local char = doc:get_char(line2, col2) + if is_non_word(char) + or line == line2 and col == col2 then + break + end + line, col = line2, col2 + end + return line, col +end + + +function translate.end_of_word(doc, line, col) + while true do + local line2, col2 = doc:position_offset(line, col, 1) + local char = doc:get_char(line, col) + if is_non_word(char) + or line == line2 and col == col2 then + break + end + line, col = line2, col2 + end + return line, col +end + + +function translate.previous_block_start(doc, line, col) + while true do + line = line - 1 + if line <= 1 then + return 1, 1 + end + if doc.lines[line-1]:find("^%s*$") + and not doc.lines[line]:find("^%s*$") then + return line, (doc.lines[line]:find("%S")) + end + end +end + + +function translate.next_block_end(doc, line, col) + while true do + if line >= #doc.lines then + return #doc.lines, 1 + end + if doc.lines[line+1]:find("^%s*$") + and not doc.lines[line]:find("^%s*$") then + return line+1, #doc.lines[line+1] + end + line = line + 1 + end +end + + +function translate.start_of_line(doc, line, col) + return line, 1 +end + + +function translate.end_of_line(doc, line, col) + return line, math.huge +end + + +function translate.start_of_doc(doc, line, col) + return 1, 1 +end + + +function translate.end_of_doc(doc, line, col) + return #doc.lines, #doc.lines[#doc.lines] +end + + +return translate diff --git a/tools/editor/art/lite/data/core/docview.lua b/tools/editor/art/lite/data/core/docview.lua new file mode 100644 index 0000000..154ff79 --- /dev/null +++ b/tools/editor/art/lite/data/core/docview.lua @@ -0,0 +1,383 @@ +local core = require "core" +local common = require "core.common" +local config = require "core.config" +local style = require "core.style" +local keymap = require "core.keymap" +local translate = require "core.doc.translate" +local View = require "core.view" + + +local DocView = View:extend() + + +local function move_to_line_offset(dv, line, col, offset) + local xo = dv.last_x_offset + if xo.line ~= line or xo.col ~= col then + xo.offset = dv:get_col_x_offset(line, col) + end + xo.line = line + offset + xo.col = dv:get_x_offset_col(line + offset, xo.offset) + return xo.line, xo.col +end + + +DocView.translate = { + ["previous_page"] = function(doc, line, col, dv) + local min, max = dv:get_visible_line_range() + return line - (max - min), 1 + end, + + ["next_page"] = function(doc, line, col, dv) + local min, max = dv:get_visible_line_range() + return line + (max - min), 1 + end, + + ["previous_line"] = function(doc, line, col, dv) + if line == 1 then + return 1, 1 + end + return move_to_line_offset(dv, line, col, -1) + end, + + ["next_line"] = function(doc, line, col, dv) + if line == #doc.lines then + return #doc.lines, math.huge + end + return move_to_line_offset(dv, line, col, 1) + end, +} + + + +function DocView:new(doc) + DocView.super.new(self) + self.cursor = "ibeam" + self.scrollable = true + self.doc = assert(doc) + self.font = "code_font" + self.last_x_offset = {} + self.blink_timer = 0 +end + + +function DocView:try_close(do_close) + if self.doc:is_dirty() + and #core.get_views_referencing_doc(self.doc) == 1 then + core.command_view:enter("Unsaved Changes; Confirm Close", function(_, item) + if item.text:match("^[cC]") then + do_close() + elseif item.text:match("^[sS]") then + self.doc:save() + do_close() + end + end, function(text) + local items = {} + if not text:find("^[^cC]") then table.insert(items, "Close Without Saving") end + if not text:find("^[^sS]") then table.insert(items, "Save And Close") end + return items + end) + else + do_close() + end +end + + +function DocView:get_name() + local post = self.doc:is_dirty() and "*" or "" + local name = self.doc:get_name() + return name:match("[^/%\\]*$") .. post +end + + +function DocView:get_scrollable_size() + return self:get_line_height() * (#self.doc.lines - 1) + self.size.y +end + + +function DocView:get_font() + return style[self.font] +end + + +function DocView:get_line_height() + return math.floor(self:get_font():get_height() * config.line_height) +end + + +function DocView:get_gutter_width() + return self:get_font():get_width(#self.doc.lines) + style.padding.x * 2 +end + + +function DocView:get_line_screen_position(idx) + local x, y = self:get_content_offset() + local lh = self:get_line_height() + local gw = self:get_gutter_width() + return x + gw, y + (idx-1) * lh + style.padding.y +end + + +function DocView:get_line_text_y_offset() + --< https://github.com/rxi/lite/pull/275/commits/eb9946862d1540e89d86ec2ffe78ab4962002511 + local th = self:get_font():get_height() + return math.floor(th*config.line_height - th) + --< +end + + +function DocView:get_visible_line_range() + local x, y, x2, y2 = self:get_content_bounds() + local lh = self:get_line_height() + local minline = math.max(1, math.floor(y / lh)) + local maxline = math.min(#self.doc.lines, math.floor(y2 / lh) + 1) + return minline, maxline +end + + +function DocView:get_col_x_offset(line, col) + local text = self.doc.lines[line] + if not text then return 0 end + return self:get_font():get_width(text:sub(1, col - 1)) +end + + +function DocView:get_x_offset_col(line, x) + local text = self.doc.lines[line] + + local xoffset, last_i, i = 0, 1, 1 + for char in common.utf8_chars(text) do + local w = self:get_font():get_width(char) + if xoffset >= x then + return (xoffset - x > w / 2) and last_i or i + end + xoffset = xoffset + w + last_i = i + i = i + #char + end + + return #text +end + + +function DocView:resolve_screen_position(x, y) + local ox, oy = self:get_line_screen_position(1) + local line = math.floor((y - oy) / self:get_line_height()) + 1 + line = common.clamp(line, 1, #self.doc.lines) + local col = self:get_x_offset_col(line, x - ox) + return line, col +end + + +function DocView:scroll_to_line(line, ignore_if_visible, instant) + local min, max = self:get_visible_line_range() + if not (ignore_if_visible and line > min and line < max) then + local lh = self:get_line_height() + self.scroll.to.y = math.max(0, lh * (line - 1) - self.size.y / 2) + if instant then + self.scroll.y = self.scroll.to.y + end + end +end + + +function DocView:scroll_to_make_visible(line, col) + local min = self:get_line_height() * (line - 1) + local max = self:get_line_height() * (line + 2) - self.size.y + self.scroll.to.y = math.min(self.scroll.to.y, min) + self.scroll.to.y = math.max(self.scroll.to.y, max) + local gw = self:get_gutter_width() + local xoffset = self:get_col_x_offset(line, col) + local max = xoffset - self.size.x + gw + self.size.x / 5 + self.scroll.to.x = math.max(0, max) +end + + +local function mouse_selection(doc, clicks, line1, col1, line2, col2) + local swap = line2 < line1 or line2 == line1 and col2 <= col1 + if swap then + line1, col1, line2, col2 = line2, col2, line1, col1 + end + if clicks % 4 == 2 then + line1, col1 = translate.start_of_word(doc, line1, col1) + line2, col2 = translate.end_of_word(doc, line2, col2) + elseif clicks % 4 == 3 then + if line2 == #doc.lines and doc.lines[#doc.lines] ~= "\n" then + doc:insert(math.huge, math.huge, "\n") + end + line1, col1, line2, col2 = line1, 1, line2 + 1, 1 + end + if swap then + return line2, col2, line1, col1 + end + return line1, col1, line2, col2 +end + + +function DocView:on_mouse_pressed(button, x, y, clicks) + local caught = DocView.super.on_mouse_pressed(self, button, x, y, clicks) + if caught then + return + end + if keymap.modkeys["shift"] then + if clicks % 2 == 1 then + local line1, col1 = select(3, self.doc:get_selection()) + local line2, col2 = self:resolve_screen_position(x, y) + self.doc:set_selection(line2, col2, line1, col1) + end + else + local line, col = self:resolve_screen_position(x, y) + self.doc:set_selection(mouse_selection(self.doc, clicks, line, col, line, col)) + self.mouse_selecting = { line, col, clicks = clicks } + end + self.blink_timer = 0 +end + + +function DocView:on_mouse_moved(x, y, ...) + DocView.super.on_mouse_moved(self, x, y, ...) + + if self:scrollbar_overlaps_point(x, y) or self.dragging_scrollbar then + self.cursor = "arrow" + else + self.cursor = "ibeam" + end + + if self.mouse_selecting then + local l1, c1 = self:resolve_screen_position(x, y) + local l2, c2 = table.unpack(self.mouse_selecting) + local clicks = self.mouse_selecting.clicks + self.doc:set_selection(mouse_selection(self.doc, clicks, l1, c1, l2, c2)) + end +end + + +function DocView:on_mouse_released(button) + DocView.super.on_mouse_released(self, button) + self.mouse_selecting = nil +end + + +function DocView:on_text_input(text) + self.doc:text_input(text) +end + + +function DocView:update() + -- scroll to make caret visible and reset blink timer if it moved + local line, col = self.doc:get_selection() + if (line ~= self.last_line or col ~= self.last_col) and self.size.x > 0 then + if core.active_view == self then + self:scroll_to_make_visible(line, col) + end + self.blink_timer = 0 + self.last_line, self.last_col = line, col + end + + -- update blink timer + if self == core.active_view and not self.mouse_selecting then + local n = config.blink_period / 2 + local prev = self.blink_timer + self.blink_timer = (self.blink_timer + 1 / config.fps) % config.blink_period + if (self.blink_timer > n) ~= (prev > n) then + core.redraw = true + end + end + + DocView.super.update(self) +end + + +function DocView:draw_line_highlight(x, y) + local lh = self:get_line_height() + renderer.draw_rect(x, y, self.size.x, lh, style.line_highlight) +end + + +function DocView:draw_line_text(idx, x, y) + local tx, ty = x, y + self:get_line_text_y_offset() + local font = self:get_font() + for _, type, text in self.doc.highlighter:each_token(idx) do + local color = style.syntax[type] + tx = renderer.draw_text(font, text, tx, ty, color) + end +end + + +function DocView:draw_line_body(idx, x, y) + local line, col = self.doc:get_selection() + + -- draw selection if it overlaps this line + local line1, col1, line2, col2 = self.doc:get_selection(true) + if idx >= line1 and idx <= line2 then + local text = self.doc.lines[idx] + if line1 ~= idx then col1 = 1 end + if line2 ~= idx then col2 = #text + 1 end + local x1 = x + self:get_col_x_offset(idx, col1) + local x2 = x + self:get_col_x_offset(idx, col2) + local lh = self:get_line_height() + renderer.draw_rect(x1, y, x2 - x1, lh, style.selection) + end + + -- draw line highlight if caret is on this line + if config.highlight_current_line and not self.doc:has_selection() + and line == idx and core.active_view == self then + self:draw_line_highlight(x + self.scroll.x, y) + end + + -- draw line's text + self:draw_line_text(idx, x, y) + + -- draw caret if it overlaps this line + if line == idx and core.active_view == self + and self.blink_timer < config.blink_period / 2 + and system.window_has_focus() then + local lh = self:get_line_height() + local x1 = x + self:get_col_x_offset(line, col) + renderer.draw_rect(x1, y, style.caret_width, lh, style.caret) + end +end + + +function DocView:draw_line_gutter(idx, x, y) + local color = style.line_number + local line1, _, line2, _ = self.doc:get_selection(true) + if idx >= line1 and idx <= line2 then + color = style.line_number2 + end + local yoffset = self:get_line_text_y_offset() + x = x + style.padding.x + renderer.draw_text(self:get_font(), idx, x, y + yoffset, color) +end + + +function DocView:draw() + self:draw_background(style.background) + + local font = self:get_font() + font:set_tab_width(font:get_width(" ") * config.indent_size) + + local minline, maxline = self:get_visible_line_range() + local lh = self:get_line_height() + + local _, y = self:get_line_screen_position(minline) + local x = self.position.x + for i = minline, maxline do + self:draw_line_gutter(i, x, y) + y = y + lh + end + + local x, y = self:get_line_screen_position(minline) + local gw = self:get_gutter_width() + local pos = self.position + core.push_clip_rect(pos.x + gw, pos.y, self.size.x, self.size.y) + for i = minline, maxline do + self:draw_line_body(i, x, y) + y = y + lh + end + core.pop_clip_rect() + + self:draw_scrollbar() +end + + +return DocView diff --git a/tools/editor/art/lite/data/core/init.lua b/tools/editor/art/lite/data/core/init.lua new file mode 100644 index 0000000..f1ed391 --- /dev/null +++ b/tools/editor/art/lite/data/core/init.lua @@ -0,0 +1,511 @@ +require "core.strict" +local common = require "core.common" +local config = require "core.config" +local style = require "core.style" +local command +local keymap +local RootView +local StatusView +local CommandView +local Doc + +local core = {} + + +local function project_scan_thread() + local function diff_files(a, b) + if #a ~= #b then return true end + for i, v in ipairs(a) do + if b[i].filename ~= v.filename + or b[i].modified ~= v.modified then + return true + end + end + end + + local function compare_file(a, b) + return a.filename < b.filename + end + + local function get_files(path, t) + coroutine.yield() + t = t or {} + local size_limit = config.file_size_limit * 10e5 + local all = system.list_dir(path) or {} + local dirs, files = {}, {} + + for _, file in ipairs(all) do + if not common.match_pattern(file, config.ignore_files) then + local file = (path ~= "." and path .. PATHSEP or "") .. file + local info = system.get_file_info(file) + if info and info.size < size_limit then + info.filename = file +--< https://github.com/0xd61/lite/blob/e5e7a2dc8c3e7d3f7f92ea5124bc111126ccfa1f/data/core/init.lua#L48-L68 + local _, depth1 = file:gsub("/","") + local _, depth2 = file:gsub("\\","") + if (depth1+depth2) < config.project_scan_depth or config.project_scan_depth == 0 then + table.insert(info.type == "dir" and dirs or files, info) + end + end + if (#dirs + #files) >= config.project_max_files_per_folder then break end +--< + end + end + + table.sort(dirs, compare_file) + for _, f in ipairs(dirs) do + table.insert(t, f) + get_files(f.filename, t) + end + + table.sort(files, compare_file) + for _, f in ipairs(files) do + table.insert(t, f) + end + + return t + end + + while true do + -- get project files and replace previous table if the new table is + -- different + local t = get_files(".") + if diff_files(core.project_files, t) then + core.project_files = t + core.redraw = true + end + + -- wait for next scan + coroutine.yield(config.project_scan_rate) + end +end + + +function core.init() + command = require "core.command" + keymap = require "core.keymap" + RootView = require "core.rootview" + StatusView = require "core.statusview" + CommandView = require "core.commandview" + Doc = require "core.doc" + + local project_dir = EXEDIR + local files = {} + for i = 2, #ARGS do + local info = system.get_file_info(ARGS[i]) or {} + if info.type == "file" then + table.insert(files, system.absolute_path(ARGS[i])) + elseif info.type == "dir" then + project_dir = ARGS[i] + end + end + + system.chdir(project_dir) + + core.frame_start = 0 + core.clip_rect_stack = {{ 0,0,0,0 }} + core.log_items = {} + core.docs = {} + core.threads = setmetatable({}, { __mode = "k" }) + core.project_files = {} + core.redraw = true + + core.root_view = RootView() + core.command_view = CommandView() + core.status_view = StatusView() + + core.root_view.root_node:split("down", core.command_view, true) + core.root_view.root_node.b:split("down", core.status_view, true) + + core.add_thread(project_scan_thread) + command.add_defaults() +--< @r-lyeh + local got_language_error = not core.load_languages() +--< + local got_plugin_error = not core.load_plugins() + local got_user_error = not core.try(require, "user") + local got_project_error = not core.load_project_module() + + for _, filename in ipairs(files) do + core.root_view:open_doc(core.open_doc(filename)) + end + + if got_language_error or got_plugin_error or got_user_error or got_project_error then + command.perform("core:open-log") + end +end + + +local temp_uid = math.floor(system.get_time() * 1000) % 0xffffffff +local temp_file_prefix = string.format(".lite_temp_%08x", tonumber(temp_uid)) --< @r-lyeh: tonumber() +local temp_file_counter = 0 + +local function delete_temp_files() + for _, filename in ipairs(system.list_dir(EXEDIR)) do + if filename:find(temp_file_prefix, 1, true) == 1 then + os.remove(EXEDIR .. PATHSEP .. filename) + end + end +end + +function core.temp_filename(ext) + temp_file_counter = temp_file_counter + 1 + return EXEDIR .. PATHSEP .. temp_file_prefix + .. string.format("%06x", temp_file_counter) .. (ext or "") +end + + +function core.quit(force) + if force then + delete_temp_files() + os.exit() + end + local dirty_count = 0 + local dirty_name + for _, doc in ipairs(core.docs) do + if doc:is_dirty() then + dirty_count = dirty_count + 1 + dirty_name = doc:get_name() + end + end + if dirty_count > 0 then + local text + if dirty_count == 1 then + text = string.format("\"%s\" has unsaved changes. Quit anyway?", dirty_name) + else + text = string.format("%d docs have unsaved changes. Quit anyway?", dirty_count) + end + local confirm = system.show_confirm_dialog("Unsaved Changes", text) + if not confirm then return end + end + core.quit(true) +end + + +function core.load_plugins() + local no_errors = true + local files = system.list_dir(DATADIR .. "/data/plugins") + for _, filename in ipairs(files) do + local modname = "plugins." .. filename:gsub(".lua$", "") + local ok = core.try(require, modname) + if ok then + core.log_quiet("Loaded plugin %q", modname) + else + no_errors = false + end + end + return no_errors +end + +--< @r-lyeh +function core.load_languages() + local no_errors = true + local files = system.list_dir(DATADIR .. "/data/languages") + for _, filename in ipairs(files) do + local modname = "languages." .. filename:gsub(".lua$", "") + local ok = core.try(require, modname) + if ok then + core.log_quiet("Loaded language %q", modname) + else + no_errors = false + end + end + return no_errors +end +--< + +function core.load_project_module() + local filename = ".lite_project.lua" + if system.get_file_info(filename) then + return core.try(function() + local fn, err = loadfile(filename) + if not fn then error("Error when loading project module:\n\t" .. err) end + fn() + core.log_quiet("Loaded project module") + end) + end + return true +end + + +function core.reload_module(name) + local old = package.loaded[name] + package.loaded[name] = nil + local new = require(name) + if type(old) == "table" then + for k, v in pairs(new) do old[k] = v end + package.loaded[name] = old + end +end + + +function core.set_active_view(view) + assert(view, "Tried to set active view to nil") + if view ~= core.active_view then + core.last_active_view = core.active_view + core.active_view = view + end +end + + +function core.add_thread(f, weak_ref) + local key = weak_ref or #core.threads + 1 + local fn = function() return core.try(f) end + core.threads[key] = { cr = coroutine.create(fn), wake = 0 } +end + + +function core.push_clip_rect(x, y, w, h) + local x2, y2, w2, h2 = table.unpack(core.clip_rect_stack[#core.clip_rect_stack]) + local r, b, r2, b2 = x+w, y+h, x2+w2, y2+h2 + x, y = math.max(x, x2), math.max(y, y2) + b, r = math.min(b, b2), math.min(r, r2) + w, h = r-x, b-y + table.insert(core.clip_rect_stack, { x, y, w, h }) + renderer.set_clip_rect(x, y, w, h) +end + + +function core.pop_clip_rect() + table.remove(core.clip_rect_stack) + local x, y, w, h = table.unpack(core.clip_rect_stack[#core.clip_rect_stack]) + renderer.set_clip_rect(x, y, w, h) +end + + +function core.open_doc(filename) + if filename then + -- try to find existing doc for filename + local abs_filename = system.absolute_path(filename) + for _, doc in ipairs(core.docs) do + if doc.filename + and abs_filename == system.absolute_path(doc.filename) then + return doc + end + end + end + -- no existing doc for filename; create new + local doc = Doc(filename) + table.insert(core.docs, doc) + core.log_quiet(filename and "Opened doc \"%s\"" or "Opened new doc", filename) + return doc +end + + +function core.get_views_referencing_doc(doc) + local res = {} + local views = core.root_view.root_node:get_children() + for _, view in ipairs(views) do + if view.doc == doc then table.insert(res, view) end + end + return res +end + + +local function log(icon, icon_color, fmt, ...) + local text = string.format(fmt, ...) + if icon then + core.status_view:show_message(icon, icon_color, text) + end + + local info = debug.getinfo(2, "Sl") + local at = string.format("%s:%d", info.short_src, info.currentline) + local item = { text = text, time = os.time(), at = at } + table.insert(core.log_items, item) + if #core.log_items > config.max_log_items then + table.remove(core.log_items, 1) + end + return item +end + + +function core.log(...) + return log("i", style.text, ...) +end + + +function core.log_quiet(...) + return log(nil, nil, ...) +end + + +function core.error(...) + return log("!", style.accent, ...) +end + + +function core.try(fn, ...) + local err + local ok, res = xpcall(fn, function(msg) + local item = core.error("%s", msg) + item.info = debug.traceback(nil, 2):gsub("\t", "") + err = msg + end, ...) + if ok then + return true, res + end + return false, err +end + + +function core.on_event(type, ...) + local did_keymap = false + if type == "textinput" then + core.root_view:on_text_input(...) + elseif type == "keypressed" then + did_keymap = keymap.on_key_pressed(...) + elseif type == "keyreleased" then + keymap.on_key_released(...) + elseif type == "mousemoved" then + core.root_view:on_mouse_moved(...) + elseif type == "mousepressed" then + core.root_view:on_mouse_pressed(...) + elseif type == "mousereleased" then + core.root_view:on_mouse_released(...) + elseif type == "mousewheel" then + core.root_view:on_mouse_wheel(...) + elseif type == "filedropped" then + local filename, mx, my = ... + local info = system.get_file_info(filename) + if info and info.type == "dir" then + system.exec(string.format("%q %q", EXEFILE, filename)) + else + local ok, doc = core.try(core.open_doc, filename) + if ok then + local node = core.root_view.root_node:get_child_overlapping_point(mx, my) + node:set_active_view(node.active_view) + core.root_view:open_doc(doc) + end + end + elseif type == "quit" then + core.quit() + end + return did_keymap +end + + +function core.step() + -- handle events + local did_keymap = false + local mouse_moved = false + local mouse = { x = 0, y = 0, dx = 0, dy = 0 } + + for type, a,b,c,d in system.poll_event do + if type == "mousemoved" then + mouse_moved = true + mouse.x, mouse.y = a, b + mouse.dx, mouse.dy = mouse.dx + c, mouse.dy + d + elseif type == "textinput" and did_keymap then + did_keymap = false + else + local _, res = core.try(core.on_event, type, a, b, c, d) + did_keymap = res or did_keymap + end + core.redraw = true + end + + if not core.redraw and not system.window_has_focus() then return false end --< https://github.com/rxi/lite/pull/285/commits/a38b89ca26dde1353cf1a6bcb2dc338ebc20473d + + if mouse_moved then + core.try(core.on_event, "mousemoved", mouse.x, mouse.y, mouse.dx, mouse.dy) + end + + local width, height = renderer.get_size() + + -- update + core.root_view.size.x, core.root_view.size.y = width, height + core.root_view:update() + if not core.redraw then return false end + core.redraw = false + + -- close unreferenced docs + for i = #core.docs, 1, -1 do + local doc = core.docs[i] + if #core.get_views_referencing_doc(doc) == 0 then + table.remove(core.docs, i) + core.log_quiet("Closed doc \"%s\"", doc:get_name()) + end + end + + -- update window title + local name = core.active_view:get_name() + local title = (name ~= "---") and (name .. " - lite") or "lite" + if title ~= core.window_title then + system.set_window_title(title) + core.window_title = title + end + + -- draw + renderer.begin_frame() + core.clip_rect_stack[1] = { 0, 0, width, height } + renderer.set_clip_rect(table.unpack(core.clip_rect_stack[1])) + core.root_view:draw() + renderer.end_frame() + return true +end + + +local run_threads = coroutine.wrap(function() + while true do + local max_time = 1 / config.fps - 0.004 + local ran_any_threads = false + + for k, thread in pairs(core.threads) do + -- run thread + if thread.wake < system.get_time() then + local _, wait = assert(coroutine.resume(thread.cr)) + if coroutine.status(thread.cr) == "dead" then + if type(k) == "number" then + table.remove(core.threads, k) + else + core.threads[k] = nil + end + elseif wait then + thread.wake = system.get_time() + wait + end + ran_any_threads = true + end + + -- stop running threads if we're about to hit the end of frame + if system.get_time() - core.frame_start > max_time then + coroutine.yield() + end + end + + if not ran_any_threads then coroutine.yield() end + end +end) + +--< @r-lyeh { split core.run() into core.run1() +function core.run1() + local did_redraw = core.step() + run_threads() + return did_redraw +end + +function core.run() + while true do + core.frame_start = system.get_time() + local did_redraw = core.run1() + local elapsed = system.get_time() - core.frame_start + system.sleep(math.max(0, 1 / config.fps - elapsed)) + end +end +--< @r-lyeh } split core.run() into core.run1() + +function core.on_error(err) + -- write error to file + local fp = io.open(EXEDIR .. "/error.txt", "wb") + fp:write("Error: " .. tostring(err) .. "\n") + fp:write(debug.traceback(nil, 4)) + fp:close() + -- save copy of all unsaved documents + for _, doc in ipairs(core.docs) do + if doc:is_dirty() and doc.filename then + doc:save(doc.filename .. "~") + end + end +end + + +return core diff --git a/tools/editor/art/lite/data/core/keymap.lua b/tools/editor/art/lite/data/core/keymap.lua new file mode 100644 index 0000000..4d48ed4 --- /dev/null +++ b/tools/editor/art/lite/data/core/keymap.lua @@ -0,0 +1,186 @@ +local command = require "core.command" +local keymap = {} + +keymap.modkeys = {} +keymap.map = {} +keymap.reverse_map = {} + +local modkey_map = { + ["left ctrl"] = "ctrl", + ["right ctrl"] = "ctrl", + ["left shift"] = "shift", + ["right shift"] = "shift", + ["left alt"] = "alt", + ["right alt"] = "altgr", +} + +local modkeys = { "ctrl", "alt", "altgr", "shift" } + +local function key_to_stroke(k) + local stroke = "" + for _, mk in ipairs(modkeys) do + if keymap.modkeys[mk] then + stroke = stroke .. mk .. "+" + end + end + return stroke .. k +end + + +function keymap.add(map, overwrite) + for stroke, commands in pairs(map) do + if type(commands) == "string" then + commands = { commands } + end + if overwrite then + keymap.map[stroke] = commands + else + keymap.map[stroke] = keymap.map[stroke] or {} + for i = #commands, 1, -1 do + table.insert(keymap.map[stroke], 1, commands[i]) + end + end + for _, cmd in ipairs(commands) do + keymap.reverse_map[cmd] = stroke + end + end +end + + +function keymap.get_binding(cmd) + return keymap.reverse_map[cmd] +end + + +function keymap.on_key_pressed(k) + local mk = modkey_map[k] + if mk then + keymap.modkeys[mk] = true + -- work-around for windows where `altgr` is treated as `ctrl+alt` + if mk == "altgr" then + keymap.modkeys["ctrl"] = false + end + else + local stroke = key_to_stroke(k) + local commands = keymap.map[stroke] + if commands then + for _, cmd in ipairs(commands) do + local performed = command.perform(cmd) + if performed then break end + end + return true + end + end + return false +end + + +function keymap.on_key_released(k) + local mk = modkey_map[k] + if mk then + keymap.modkeys[mk] = false + end +end + + +keymap.add { + ["ctrl+shift+p"] = "core:find-command", + ["ctrl+p"] = "core:find-file", + ["ctrl+o"] = "core:open-file", + ["ctrl+n"] = "core:new-doc", + ["alt+return"] = "core:toggle-fullscreen", + + ["alt+shift+j"] = "root:split-left", + ["alt+shift+l"] = "root:split-right", + ["alt+shift+i"] = "root:split-up", + ["alt+shift+k"] = "root:split-down", + ["alt+j"] = "root:switch-to-left", + ["alt+l"] = "root:switch-to-right", + ["alt+i"] = "root:switch-to-up", + ["alt+k"] = "root:switch-to-down", + + ["ctrl+w"] = "root:close", + ["ctrl+tab"] = "root:switch-to-next-tab", + ["ctrl+shift+tab"] = "root:switch-to-previous-tab", + ["ctrl+pageup"] = "root:move-tab-left", + ["ctrl+pagedown"] = "root:move-tab-right", + ["alt+1"] = "root:switch-to-tab-1", + ["alt+2"] = "root:switch-to-tab-2", + ["alt+3"] = "root:switch-to-tab-3", + ["alt+4"] = "root:switch-to-tab-4", + ["alt+5"] = "root:switch-to-tab-5", + ["alt+6"] = "root:switch-to-tab-6", + ["alt+7"] = "root:switch-to-tab-7", + ["alt+8"] = "root:switch-to-tab-8", + ["alt+9"] = "root:switch-to-tab-9", + + ["ctrl+f"] = "find-replace:find", + ["ctrl+r"] = "find-replace:replace", + ["f3"] = "find-replace:repeat-find", + ["shift+f3"] = "find-replace:previous-find", + ["ctrl+g"] = "doc:go-to-line", + ["ctrl+s"] = "doc:save", + ["ctrl+shift+s"] = "doc:save-as", + + ["ctrl+z"] = "doc:undo", + ["ctrl+y"] = "doc:redo", + ["ctrl+x"] = "doc:cut", + ["ctrl+c"] = "doc:copy", + ["ctrl+v"] = "doc:paste", + ["escape"] = { "command:escape", "doc:select-none" }, + ["tab"] = { "command:complete", "doc:indent" }, + ["shift+tab"] = "doc:unindent", + ["backspace"] = "doc:backspace", + ["shift+backspace"] = "doc:backspace", + ["ctrl+backspace"] = "doc:delete-to-previous-word-start", + ["ctrl+shift+backspace"] = "doc:delete-to-previous-word-start", + ["delete"] = "doc:delete", + ["shift+delete"] = "doc:delete", + ["ctrl+delete"] = "doc:delete-to-next-word-end", + ["ctrl+shift+delete"] = "doc:delete-to-next-word-end", + ["return"] = { "command:submit", "doc:newline" }, + ["keypad enter"] = { "command:submit", "doc:newline" }, + ["ctrl+return"] = "doc:newline-below", + ["ctrl+shift+return"] = "doc:newline-above", + ["ctrl+j"] = "doc:join-lines", + ["ctrl+a"] = "doc:select-all", + ["ctrl+d"] = { "find-replace:select-next", "doc:select-word" }, + ["ctrl+l"] = "doc:select-lines", + ["ctrl+/"] = "doc:toggle-line-comments", + ["ctrl+up"] = "doc:move-lines-up", + ["ctrl+down"] = "doc:move-lines-down", + ["ctrl+shift+d"] = "doc:duplicate-lines", + ["ctrl+shift+k"] = "doc:delete-lines", + + ["left"] = "doc:move-to-previous-char", + ["right"] = "doc:move-to-next-char", + ["up"] = { "command:select-previous", "doc:move-to-previous-line" }, + ["down"] = { "command:select-next", "doc:move-to-next-line" }, + ["ctrl+left"] = "doc:move-to-previous-word-start", + ["ctrl+right"] = "doc:move-to-next-word-end", + ["ctrl+["] = "doc:move-to-previous-block-start", + ["ctrl+]"] = "doc:move-to-next-block-end", + ["home"] = "doc:move-to-start-of-line", + ["end"] = "doc:move-to-end-of-line", + ["ctrl+home"] = "doc:move-to-start-of-doc", + ["ctrl+end"] = "doc:move-to-end-of-doc", + ["pageup"] = "doc:move-to-previous-page", + ["pagedown"] = "doc:move-to-next-page", + + ["shift+left"] = "doc:select-to-previous-char", + ["shift+right"] = "doc:select-to-next-char", + ["shift+up"] = "doc:select-to-previous-line", + ["shift+down"] = "doc:select-to-next-line", + ["ctrl+shift+left"] = "doc:select-to-previous-word-start", + ["ctrl+shift+right"] = "doc:select-to-next-word-end", + ["ctrl+shift+["] = "doc:select-to-previous-block-start", + ["ctrl+shift+]"] = "doc:select-to-next-block-end", + ["shift+home"] = "doc:select-to-start-of-line", + ["shift+end"] = "doc:select-to-end-of-line", + ["ctrl+shift+home"] = "doc:select-to-start-of-doc", + ["ctrl+shift+end"] = "doc:select-to-end-of-doc", + ["shift+pageup"] = "doc:select-to-previous-page", + ["shift+pagedown"] = "doc:select-to-next-page", +} + +return keymap diff --git a/tools/editor/art/lite/data/core/logview.lua b/tools/editor/art/lite/data/core/logview.lua new file mode 100644 index 0000000..d7142fb --- /dev/null +++ b/tools/editor/art/lite/data/core/logview.lua @@ -0,0 +1,74 @@ +local core = require "core" +local style = require "core.style" +local View = require "core.view" + + +local LogView = View:extend() + + +function LogView:new() + LogView.super.new(self) + self.last_item = core.log_items[#core.log_items] + self.scrollable = true + self.yoffset = 0 +end + + +function LogView:get_name() + return "Log" +end + + +function LogView:update() + local item = core.log_items[#core.log_items] + if self.last_item ~= item then + self.last_item = item + self.scroll.to.y = 0 + self.yoffset = -(style.font:get_height() + style.padding.y) + end + + self:move_towards("yoffset", 0) + + LogView.super.update(self) +end + + +local function draw_text_multiline(font, text, x, y, color) + local th = font:get_height() + local resx, resy = x, y + for line in text:gmatch("[^\n]+") do + resy = y + resx = renderer.draw_text(style.font, line, x, y, color) + y = y + th + end + return resx, resy +end + + +function LogView:draw() + self:draw_background(style.background) + + local ox, oy = self:get_content_offset() + local th = style.font:get_height() + local y = oy + style.padding.y + self.yoffset + + for i = #core.log_items, 1, -1 do + local x = ox + style.padding.x + local item = core.log_items[i] + local time = os.date(nil, item.time) + x = renderer.draw_text(style.font, time, x, y, style.dim) + x = x + style.padding.x + local subx = x + x, y = draw_text_multiline(style.font, item.text, x, y, style.text) + renderer.draw_text(style.font, " at " .. item.at, x, y, style.dim) + y = y + th + if item.info then + subx, y = draw_text_multiline(style.font, item.info, subx, y, style.dim) + y = y + th + end + y = y + style.padding.y + end +end + + +return LogView diff --git a/tools/editor/art/lite/data/core/object.lua b/tools/editor/art/lite/data/core/object.lua new file mode 100644 index 0000000..af41b7e --- /dev/null +++ b/tools/editor/art/lite/data/core/object.lua @@ -0,0 +1,58 @@ +local Object = {} +Object.__index = Object + + +function Object:new() +end + + +function Object:extend() + local cls = {} + for k, v in pairs(self) do + if k:find("__") == 1 then + cls[k] = v + end + end + cls.__index = cls + cls.super = self + setmetatable(cls, self) + return cls +end + + +function Object:implement(...) + for _, cls in pairs({...}) do + for k, v in pairs(cls) do + if self[k] == nil and type(v) == "function" then + self[k] = v + end + end + end +end + + +function Object:is(T) + local mt = getmetatable(self) + while mt do + if mt == T then + return true + end + mt = getmetatable(mt) + end + return false +end + + +function Object:__tostring() + return "Object" +end + + +function Object:__call(...) + local obj = setmetatable({}, self) + obj:new(...) + return obj +end + + +return Object diff --git a/tools/editor/art/lite/data/core/rootview.lua b/tools/editor/art/lite/data/core/rootview.lua new file mode 100644 index 0000000..b968fd3 --- /dev/null +++ b/tools/editor/art/lite/data/core/rootview.lua @@ -0,0 +1,506 @@ +local core = require "core" +local common = require "core.common" +local style = require "core.style" +local keymap = require "core.keymap" +local Object = require "core.object" +local View = require "core.view" +local DocView = require "core.docview" +local config = require "core.config" + + +local EmptyView = View:extend() + +local function draw_text(x, y, color) + local th = style.big_font:get_height() + local dh = th + style.padding.y * 2 + x = renderer.draw_text(style.big_font, "edit", x, y + (dh - th) / 2, color) --< @r-lyeh lite>edit + x = x + style.padding.x + renderer.draw_rect(x, y, math.ceil(1 * SCALE), dh, color) + local lines = { + { fmt = "%s to run a command", cmd = "core:find-command" }, + { fmt = "%s to open a file from the project", cmd = "core:find-file" }, + } + th = style.font:get_height() + y = y + (dh - th * 2 - style.padding.y) / 2 + local w = 0 + for _, line in ipairs(lines) do + local text = string.format(line.fmt, keymap.get_binding(line.cmd)) + w = math.max(w, renderer.draw_text(style.font, text, x + style.padding.x, y, color)) + y = y + th + style.padding.y + end + return w, dh +end + +function EmptyView:draw() + self:draw_background(style.background) + local w, h = draw_text(0, 0, { 0, 0, 0, 0 }) + local x = self.position.x + math.max(style.padding.x, (self.size.x - w) / 2) + local y = self.position.y + (self.size.y - h) / 2 + draw_text(x, y, style.dim) +end + + + +local Node = Object:extend() + +function Node:new(type) + self.type = type or "leaf" + self.position = { x = 0, y = 0 } + self.size = { x = 0, y = 0 } + self.views = {} + self.divider = 0.5 + if self.type == "leaf" then + self:add_view(EmptyView()) + end +end + + +function Node:propagate(fn, ...) + self.a[fn](self.a, ...) + self.b[fn](self.b, ...) +end + + +function Node:on_mouse_moved(x, y, ...) + self.hovered_tab = self:get_tab_overlapping_point(x, y) + if self.type == "leaf" then + self.active_view:on_mouse_moved(x, y, ...) + else + self:propagate("on_mouse_moved", x, y, ...) + end +end + + +function Node:on_mouse_released(...) + if self.type == "leaf" then + self.active_view:on_mouse_released(...) + else + self:propagate("on_mouse_released", ...) + end +end + + +function Node:consume(node) + for k, _ in pairs(self) do self[k] = nil end + for k, v in pairs(node) do self[k] = v end +end + + +local type_map = { up="vsplit", down="vsplit", left="hsplit", right="hsplit" } + +function Node:split(dir, view, locked) + assert(self.type == "leaf", "Tried to split non-leaf node") + local type = assert(type_map[dir], "Invalid direction") + local last_active = core.active_view + local child = Node() + child:consume(self) + self:consume(Node(type)) + self.a = child + self.b = Node() + if view then self.b:add_view(view) end + if locked then + self.b.locked = locked + core.set_active_view(last_active) + end + if dir == "up" or dir == "left" then + self.a, self.b = self.b, self.a + end + return child +end + + +function Node:close_active_view(root) + local do_close = function() + if #self.views > 1 then + local idx = self:get_view_idx(self.active_view) + table.remove(self.views, idx) + self:set_active_view(self.views[idx] or self.views[#self.views]) + else + local parent = self:get_parent_node(root) + local is_a = (parent.a == self) + local other = parent[is_a and "b" or "a"] + if other:get_locked_size() then + self.views = {} + self:add_view(EmptyView()) + else + parent:consume(other) + local p = parent + while p.type ~= "leaf" do + p = p[is_a and "a" or "b"] + end + p:set_active_view(p.active_view) + end + end + core.last_active_view = nil + end + self.active_view:try_close(do_close) +end + + +function Node:add_view(view) + assert(self.type == "leaf", "Tried to add view to non-leaf node") + assert(not self.locked, "Tried to add view to locked node") + if self.views[1] and self.views[1]:is(EmptyView) then + table.remove(self.views) + end + table.insert(self.views, view) + self:set_active_view(view) +end + + +function Node:set_active_view(view) + assert(self.type == "leaf", "Tried to set active view on non-leaf node") + self.active_view = view + core.set_active_view(view) +end + + +function Node:get_view_idx(view) + for i, v in ipairs(self.views) do + if v == view then return i end + end +end + + +function Node:get_node_for_view(view) + for _, v in ipairs(self.views) do + if v == view then return self end + end + if self.type ~= "leaf" then + return self.a:get_node_for_view(view) or self.b:get_node_for_view(view) + end +end + + +function Node:get_parent_node(root) + if root.a == self or root.b == self then + return root + elseif root.type ~= "leaf" then + return self:get_parent_node(root.a) or self:get_parent_node(root.b) + end +end + + +function Node:get_children(t) + t = t or {} + for _, view in ipairs(self.views) do + table.insert(t, view) + end + if self.a then self.a:get_children(t) end + if self.b then self.b:get_children(t) end + return t +end + + +function Node:get_divider_overlapping_point(px, py) + if self.type ~= "leaf" then + local p = 6 + local x, y, w, h = self:get_divider_rect() + x, y = x - p, y - p + w, h = w + p * 2, h + p * 2 + if px > x and py > y and px < x + w and py < y + h then + return self + end + return self.a:get_divider_overlapping_point(px, py) + or self.b:get_divider_overlapping_point(px, py) + end +end + + +function Node:get_tab_overlapping_point(px, py) + if #self.views == 1 then return nil end + local x, y, w, h = self:get_tab_rect(1) + if px >= x and py >= y and px < x + w * #self.views and py < y + h then + return math.floor((px - x) / w) + 1 + end +end + + +function Node:get_child_overlapping_point(x, y) + local child + if self.type == "leaf" then + return self + elseif self.type == "hsplit" then + child = (x < self.b.position.x) and self.a or self.b + elseif self.type == "vsplit" then + child = (y < self.b.position.y) and self.a or self.b + end + return child:get_child_overlapping_point(x, y) +end + + +function Node:get_tab_rect(idx) + if not config.tabs_allowed then return 0,0,0,0 end --< https://github.com/rxi/lite/issues/191 + local tw = math.min(style.tab_width, math.ceil(self.size.x / #self.views)) + local h = style.font:get_height() + style.padding.y * 2 + return self.position.x + (idx-1) * tw, self.position.y, tw, h +end + + +function Node:get_divider_rect() + local x, y = self.position.x, self.position.y + if self.type == "hsplit" then + return x + self.a.size.x, y, style.divider_size, self.size.y + elseif self.type == "vsplit" then + return x, y + self.a.size.y, self.size.x, style.divider_size + end +end + + +function Node:get_locked_size() + if self.type == "leaf" then + if self.locked then + local size = self.active_view.size + return size.x, size.y + end + else + local x1, y1 = self.a:get_locked_size() + local x2, y2 = self.b:get_locked_size() + if x1 and x2 then + local dsx = (x1 < 1 or x2 < 1) and 0 or style.divider_size + local dsy = (y1 < 1 or y2 < 1) and 0 or style.divider_size + return x1 + x2 + dsx, y1 + y2 + dsy + end + end +end + + +local function copy_position_and_size(dst, src) + dst.position.x, dst.position.y = src.position.x, src.position.y + dst.size.x, dst.size.y = src.size.x, src.size.y +end + + +-- calculating the sizes is the same for hsplits and vsplits, except the x/y +-- axis are swapped; this function lets us use the same code for both +local function calc_split_sizes(self, x, y, x1, x2) + local n + local ds = (x1 and x1 < 1 or x2 and x2 < 1) and 0 or style.divider_size + if x1 then + n = x1 + ds + elseif x2 then + n = self.size[x] - x2 + else + n = math.floor(self.size[x] * self.divider) + end + self.a.position[x] = self.position[x] + self.a.position[y] = self.position[y] + self.a.size[x] = n - ds + self.a.size[y] = self.size[y] + self.b.position[x] = self.position[x] + n + self.b.position[y] = self.position[y] + self.b.size[x] = self.size[x] - n + self.b.size[y] = self.size[y] +end + + +function Node:update_layout() + if self.type == "leaf" then + local av = self.active_view + if #self.views > 1 then + local _, _, _, th = self:get_tab_rect(1) + av.position.x, av.position.y = self.position.x, self.position.y + th + av.size.x, av.size.y = self.size.x, self.size.y - th + else + copy_position_and_size(av, self) + end + else + local x1, y1 = self.a:get_locked_size() + local x2, y2 = self.b:get_locked_size() + if self.type == "hsplit" then + calc_split_sizes(self, "x", "y", x1, x2) + elseif self.type == "vsplit" then + calc_split_sizes(self, "y", "x", y1, y2) + end + self.a:update_layout() + self.b:update_layout() + end +end + + +function Node:update() + if self.type == "leaf" then + for _, view in ipairs(self.views) do + view:update() + end + else + self.a:update() + self.b:update() + end +end + + +function Node:draw_tabs() + local x, y, _, h = self:get_tab_rect(1) + local ds = style.divider_size + core.push_clip_rect(x, y, self.size.x, h) + renderer.draw_rect(x, y, self.size.x, h, style.background2) + renderer.draw_rect(x, y + h - ds, self.size.x, ds, style.divider) + + for i, view in ipairs(self.views) do + local x, y, w, h = self:get_tab_rect(i) + local text = view:get_name() + local color = style.dim + if view == self.active_view then + color = style.text + renderer.draw_rect(x, y, w, h, style.background) + renderer.draw_rect(x + w, y, ds, h, style.divider) + renderer.draw_rect(x - ds, y, ds, h, style.divider) + end + if i == self.hovered_tab then + color = style.text + end + core.push_clip_rect(x, y, w, h) + x, w = x + style.padding.x, w - style.padding.x * 2 + local align = style.font:get_width(text) > w and "left" or "center" + common.draw_text(style.font, color, text, align, x, y, w, h) + core.pop_clip_rect() + end + + core.pop_clip_rect() +end + + +function Node:draw() + if self.type == "leaf" then + if #self.views > 1 and config.tabs_allowed then --< https://github.com/rxi/lite/issues/191 + self:draw_tabs() + end + local pos, size = self.active_view.position, self.active_view.size + core.push_clip_rect(pos.x, pos.y, size.x + pos.x % 1, size.y + pos.y % 1) + self.active_view:draw() + core.pop_clip_rect() + else + local x, y, w, h = self:get_divider_rect() + renderer.draw_rect(x, y, w, h, style.divider) + self:propagate("draw") + end +end + + + +local RootView = View:extend() + +function RootView:new() + RootView.super.new(self) + self.root_node = Node() + self.deferred_draws = {} + self.mouse = { x = 0, y = 0 } +end + + +function RootView:defer_draw(fn, ...) + table.insert(self.deferred_draws, 1, { fn = fn, ... }) +end + + +function RootView:get_active_node() + return self.root_node:get_node_for_view(core.active_view) +end + + +function RootView:open_doc(doc) + local node = self:get_active_node() + if node.locked and core.last_active_view then + core.set_active_view(core.last_active_view) + node = self:get_active_node() + end + assert(not node.locked, "Cannot open doc on locked node") + for i, view in ipairs(node.views) do + if view.doc == doc then + node:set_active_view(node.views[i]) + return view + end + end + local view = DocView(doc) + node:add_view(view) + self.root_node:update_layout() + view:scroll_to_line(view.doc:get_selection(), true, true) + return view +end + + +function RootView:on_mouse_pressed(button, x, y, clicks) + local div = self.root_node:get_divider_overlapping_point(x, y) + if div then + self.dragged_divider = div + return + end + local node = self.root_node:get_child_overlapping_point(x, y) + local idx = node:get_tab_overlapping_point(x, y) + if idx then + node:set_active_view(node.views[idx]) + if button == "middle" then + node:close_active_view(self.root_node) + end + else + core.set_active_view(node.active_view) + node.active_view:on_mouse_pressed(button, x, y, clicks) + end +end + + +function RootView:on_mouse_released(...) + if self.dragged_divider then + self.dragged_divider = nil + end + self.root_node:on_mouse_released(...) +end + + +function RootView:on_mouse_moved(x, y, dx, dy) + if self.dragged_divider then + local node = self.dragged_divider + if node.type == "hsplit" then + node.divider = node.divider + dx / node.size.x + else + node.divider = node.divider + dy / node.size.y + end + node.divider = common.clamp(node.divider, 0.01, 0.99) + return + end + + self.mouse.x, self.mouse.y = x, y + self.root_node:on_mouse_moved(x, y, dx, dy) + + local node = self.root_node:get_child_overlapping_point(x, y) + local div = self.root_node:get_divider_overlapping_point(x, y) + if div then + system.set_cursor(div.type == "hsplit" and "sizeh" or "sizev") + elseif node:get_tab_overlapping_point(x, y) then + system.set_cursor("arrow") + else + system.set_cursor(node.active_view.cursor) + end +end + + +function RootView:on_mouse_wheel(...) + local x, y = self.mouse.x, self.mouse.y + local node = self.root_node:get_child_overlapping_point(x, y) + node.active_view:on_mouse_wheel(...) +end + + +function RootView:on_text_input(...) + core.active_view:on_text_input(...) +end + + +function RootView:update() + copy_position_and_size(self.root_node, self) + self.root_node:update() + self.root_node:update_layout() +end + + +function RootView:draw() + self.root_node:draw() + while #self.deferred_draws > 0 do + local t = table.remove(self.deferred_draws) + t.fn(table.unpack(t)) + end +end + + +return RootView diff --git a/tools/editor/art/lite/data/core/statusview.lua b/tools/editor/art/lite/data/core/statusview.lua new file mode 100644 index 0000000..03164af --- /dev/null +++ b/tools/editor/art/lite/data/core/statusview.lua @@ -0,0 +1,145 @@ +local core = require "core" +local common = require "core.common" +local command = require "core.command" +local config = require "core.config" +local style = require "core.style" +local DocView = require "core.docview" +local LogView = require "core.logview" +local View = require "core.view" + + +local StatusView = View:extend() + +StatusView.separator = " " +StatusView.separator2 = " | " + + +function StatusView:new() + StatusView.super.new(self) + self.message_timeout = 0 + self.message = {} +end + + +function StatusView:on_mouse_pressed() + core.set_active_view(core.last_active_view) + if system.get_time() < self.message_timeout + and not core.active_view:is(LogView) then + command.perform "core:open-log" + end +end + + +function StatusView:show_message(icon, icon_color, text) + self.message = { + icon_color, style.icon_font, icon, + style.dim, style.font, StatusView.separator2, style.text, text + } + self.message_timeout = system.get_time() + config.message_timeout +end + + +function StatusView:update() + self.size.y = style.font:get_height() + style.padding.y * 2 + + if system.get_time() < self.message_timeout then + self.scroll.to.y = self.size.y + else + self.scroll.to.y = 0 + end + + StatusView.super.update(self) +end + + +local function draw_items(self, items, x, y, draw_fn) + local font = style.font + local color = style.text + + for _, item in ipairs(items) do + if type(item) == "userdata" then + font = item + elseif type(item) == "table" then + color = item + else + x = draw_fn(font, color, item, nil, x, y, 0, self.size.y) + end + end + + return x +end + + +local function text_width(font, _, text, _, x) + return x + font:get_width(text) +end + + +function StatusView:draw_items(items, right_align, yoffset) + local x, y = self:get_content_offset() + y = y + (yoffset or 0) + if right_align then + local w = draw_items(self, items, 0, 0, text_width) + x = x + self.size.x - w - style.padding.x + draw_items(self, items, x, y, common.draw_text) + else + x = x + style.padding.x + draw_items(self, items, x, y, common.draw_text) + end +end + + +function StatusView:get_items() + if getmetatable(core.active_view) == DocView then + local dv = core.active_view + local line, col = dv.doc:get_selection() + local dirty = dv.doc:is_dirty() + + --< https://github.com/rxi/lite/issues/300 + col = common.utf8_len(dv.doc:get_text(line, 1, line, col)) + 1 + --< + + return { + dirty and style.accent or style.text, style.icon_font, "f", + style.dim, style.font, self.separator2, style.text, + dv.doc.filename and style.text or style.dim, dv.doc:get_name(), + style.text, + self.separator, + "line: ", line, + self.separator, + col > config.line_limit and style.accent or style.text, "col: ", col, + style.text, + self.separator, + string.format("%.f%%", line / #dv.doc.lines * 100), --< @r-lyeh: %d -> %.f + }, { + style.icon_font, "g", + style.font, style.dim, self.separator2, style.text, + #dv.doc.lines, " lines", + self.separator, + dv.doc.crlf and "CRLF" or "LF" + } + end + + return {}, { + style.icon_font, "g", + style.font, style.dim, self.separator2, + #core.docs, style.text, " / ", + #core.project_files, " files" + } +end + + +function StatusView:draw() + self:draw_background(style.background2) + + if self.message then + self:draw_items(self.message, false, self.size.y) + end + + local left, right = self:get_items() + self:draw_items(left) + self:draw_items(right, true) +end + + +return StatusView diff --git a/tools/editor/art/lite/data/core/strict.lua b/tools/editor/art/lite/data/core/strict.lua new file mode 100644 index 0000000..7d4b9da --- /dev/null +++ b/tools/editor/art/lite/data/core/strict.lua @@ -0,0 +1,26 @@ +local strict = {} +strict.defined = {} + + +-- used to define a global variable +function global(t) + for k, v in pairs(t) do + strict.defined[k] = true + rawset(_G, k, v) + end +end + + +function strict.__newindex(t, k, v) + error("cannot set undefined variable: " .. k, 2) +end + + +function strict.__index(t, k) + if not strict.defined[k] then + error("cannot get undefined variable: " .. k, 2) + end +end + + +setmetatable(_G, strict) diff --git a/tools/editor/art/lite/data/core/style.lua b/tools/editor/art/lite/data/core/style.lua new file mode 100644 index 0000000..cf215d9 --- /dev/null +++ b/tools/editor/art/lite/data/core/style.lua @@ -0,0 +1,42 @@ +local common = require "core.common" +local style = {} + +style.padding = { x = common.round(14 * SCALE), y = common.round(7 * SCALE) } +style.divider_size = common.round(1 * SCALE) +style.scrollbar_size = common.round(4 * SCALE) +style.caret_width = common.round(2 * SCALE) +style.tab_width = common.round(170 * SCALE) + +style.font = renderer.font.load(DATADIR .. "/data/fonts/font.ttf", 14 * SCALE) +style.big_font = renderer.font.load(DATADIR .. "/data/fonts/font.ttf", 34 * SCALE) +style.icon_font = renderer.font.load(DATADIR .. "/data/fonts/icons.ttf", 14 * SCALE) +style.code_font = renderer.font.load(DATADIR .. "/data/fonts/monospace.ttf", 13.5 * SCALE) + +style.background = { common.color "#2e2e32" } +style.background2 = { common.color "#252529" } +style.background3 = { common.color "#252529" } +style.text = { common.color "#97979c" } +style.caret = { common.color "#93DDFA" } +style.accent = { common.color "#e1e1e6" } +style.dim = { common.color "#525257" } +style.divider = { common.color "#202024" } +style.selection = { common.color "#48484f" } +style.line_number = { common.color "#525259" } +style.line_number2 = { common.color "#83838f" } +style.line_highlight = { common.color "#343438" } +style.scrollbar = { common.color "#414146" } +style.scrollbar2 = { common.color "#4b4b52" } + +style.syntax = {} +style.syntax["normal"] = { common.color "#e1e1e6" } +style.syntax["symbol"] = { common.color "#e1e1e6" } +style.syntax["comment"] = { common.color "#676b6f" } +style.syntax["keyword"] = { common.color "#E58AC9" } +style.syntax["keyword2"] = { common.color "#F77483" } +style.syntax["number"] = { common.color "#FFA94D" } +style.syntax["literal"] = { common.color "#FFA94D" } +style.syntax["string"] = { common.color "#f7c95c" } +style.syntax["operator"] = { common.color "#93DDFA" } +style.syntax["function"] = { common.color "#93DDFA" } + +return style diff --git a/tools/editor/art/lite/data/core/syntax.lua b/tools/editor/art/lite/data/core/syntax.lua new file mode 100644 index 0000000..a763ac7 --- /dev/null +++ b/tools/editor/art/lite/data/core/syntax.lua @@ -0,0 +1,30 @@ +local common = require "core.common" + +local syntax = {} +syntax.items = {} + +local plain_text_syntax = { patterns = {}, symbols = {} } + + +function syntax.add(t) + table.insert(syntax.items, t) +end + + +local function find(string, field) + for i = #syntax.items, 1, -1 do + local t = syntax.items[i] + if common.match_pattern(string, t[field] or {}) then + return t + end + end +end + +function syntax.get(filename, header) + return find(filename, "files") + or find(header, "headers") + or plain_text_syntax +end + + +return syntax diff --git a/tools/editor/art/lite/data/core/tokenizer.lua b/tools/editor/art/lite/data/core/tokenizer.lua new file mode 100644 index 0000000..98aafc7 --- /dev/null +++ b/tools/editor/art/lite/data/core/tokenizer.lua @@ -0,0 +1,112 @@ +local tokenizer = {} + + +local function push_token(t, type, text) + local prev_type = t[#t-1] + local prev_text = t[#t] + if prev_type and (prev_type == type or prev_text:find("^%s*$")) then + t[#t-1] = type + t[#t] = prev_text .. text + else + table.insert(t, type) + table.insert(t, text) + end +end + + +local function is_escaped(text, idx, esc) + local byte = esc:byte() + local count = 0 + for i = idx - 1, 1, -1 do + if text:byte(i) ~= byte then break end + count = count + 1 + end + return count % 2 == 1 +end + + +local function find_non_escaped(text, pattern, offset, esc) + while true do + local s, e = text:find(pattern, offset) + if not s then break end + if esc and is_escaped(text, s, esc) then + offset = e + 1 + else + return s, e + end + end +end + + +function tokenizer.tokenize(syntax, text, state) + local res = {} + local i = 1 + + if #syntax.patterns == 0 then + return { "normal", text } + end + + while i <= #text do + -- continue trying to match the end pattern of a pair if we have a state set + if state then + local p = syntax.patterns[state] + local s, e = find_non_escaped(text, p.pattern[2], i, p.pattern[3]) + + if s then + push_token(res, p.type, text:sub(i, e)) + state = nil + i = e + 1 + else + push_token(res, p.type, text:sub(i)) + break + end + end + + -- find matching pattern + local matched = false + for n, p in ipairs(syntax.patterns) do + local pattern = (type(p.pattern) == "table") and p.pattern[1] or p.pattern + local s, e = text:find("^" .. pattern, i) + + if s then + -- matched pattern; make and add token + local t = text:sub(s, e) + push_token(res, syntax.symbols[t] or p.type, t) + + -- update state if this was a start|end pattern pair + if type(p.pattern) == "table" then + state = n + end + + -- move cursor past this token + i = e + 1 + matched = true + break + end + end + + -- consume character if we didn't match + if not matched then + push_token(res, "normal", text:sub(i, i)) + i = i + 1 + end + end + + return res, state +end + + +local function iter(t, i) + i = i + 2 + local type, text = t[i], t[i+1] + if type then + return i, type, text + end +end + +function tokenizer.each_token(t) + return iter, t, -1 +end + + +return tokenizer diff --git a/tools/editor/art/lite/data/core/view.lua b/tools/editor/art/lite/data/core/view.lua new file mode 100644 index 0000000..23d48af --- /dev/null +++ b/tools/editor/art/lite/data/core/view.lua @@ -0,0 +1,158 @@ +local core = require "core" +local config = require "core.config" +local style = require "core.style" +local common = require "core.common" +local Object = require "core.object" +local keymap = require "core.keymap" + + +local View = Object:extend() + + +function View:new() + self.position = { x = 0, y = 0 } + self.size = { x = 0, y = 0 } + self.scroll = { x = 0, y = 0, to = { x = 0, y = 0 } } + self.cursor = "arrow" + self.scrollable = false +end + + +function View:move_towards(t, k, dest, rate) + if type(t) ~= "table" then + return self:move_towards(self, t, k, dest, rate) + end + local val = t[k] + if math.abs(val - dest) < 0.5 then + t[k] = dest + else + t[k] = common.lerp(val, dest, rate or 0.5) + end + if val ~= dest then + core.redraw = true + end +end + + +function View:try_close(do_close) + do_close() +end + + +function View:get_name() + return "---" +end + + +function View:get_scrollable_size() + return math.huge +end + + +function View:get_scrollbar_rect() + local sz = self:get_scrollable_size() + if sz <= self.size.y or sz == math.huge then + return 0, 0, 0, 0 + end + local h = math.max(20, self.size.y * self.size.y / sz) + return + self.position.x + self.size.x - style.scrollbar_size, + self.position.y + self.scroll.y * (self.size.y - h) / (sz - self.size.y), + style.scrollbar_size, + h +end + + +function View:scrollbar_overlaps_point(x, y) + local sx, sy, sw, sh = self:get_scrollbar_rect() + return x >= sx - sw * 3 and x < sx + sw and y >= sy and y < sy + sh +end + + +function View:on_mouse_pressed(button, x, y, clicks) + if self:scrollbar_overlaps_point(x, y) then + self.dragging_scrollbar = true + return true + end +end + + +function View:on_mouse_released(button, x, y) + self.dragging_scrollbar = false +end + + +function View:on_mouse_moved(x, y, dx, dy) + if self.dragging_scrollbar then + local delta = self:get_scrollable_size() / self.size.y * dy + self.scroll.to.y = self.scroll.to.y + delta + end + self.hovered_scrollbar = self:scrollbar_overlaps_point(x, y) +end + + +function View:on_text_input(text) + -- no-op +end + + +function View:on_mouse_wheel(y) + if self.scrollable then + --< https://github.com/rxi/lite/pull/169/commits/aa70d3f7e89aeab7f07f0e0dbe482c1373597a9d + if keymap.modkeys['alt'] then + self.scroll.to.x = self.scroll.to.x + y * -config.mouse_wheel_scroll + else + self.scroll.to.y = self.scroll.to.y + y * -config.mouse_wheel_scroll + end + --< + end +end + + +function View:get_content_bounds() + local x = self.scroll.x + local y = self.scroll.y + return x, y, x + self.size.x, y + self.size.y +end + + +function View:get_content_offset() + local x = common.round(self.position.x - self.scroll.x) + local y = common.round(self.position.y - self.scroll.y) + return x, y +end + + +function View:clamp_scroll_position() + local max = self:get_scrollable_size() - self.size.y + self.scroll.to.y = common.clamp(self.scroll.to.y, 0, max) +end + + +function View:update() + self:clamp_scroll_position() + self:move_towards(self.scroll, "x", self.scroll.to.x, 0.3) + self:move_towards(self.scroll, "y", self.scroll.to.y, 0.3) +end + + +function View:draw_background(color) + local x, y = self.position.x, self.position.y + local w, h = self.size.x, self.size.y + renderer.draw_rect(x, y, w + x % 1, h + y % 1, color) +end + + +function View:draw_scrollbar() + local x, y, w, h = self:get_scrollbar_rect() + local highlight = self.hovered_scrollbar or self.dragging_scrollbar + local color = highlight and style.scrollbar2 or style.scrollbar + renderer.draw_rect(x, y, w, h, color) +end + + +function View:draw() +end + + +return View diff --git a/tools/editor/art/lite/data/fonts/font.ttf b/tools/editor/art/lite/data/fonts/font.ttf new file mode 100644 index 0000000..2b6392f Binary files /dev/null and b/tools/editor/art/lite/data/fonts/font.ttf differ diff --git a/tools/editor/art/lite/data/fonts/icons.ttf b/tools/editor/art/lite/data/fonts/icons.ttf new file mode 100644 index 0000000..d74fe73 Binary files /dev/null and b/tools/editor/art/lite/data/fonts/icons.ttf differ diff --git a/tools/editor/art/lite/data/fonts/monospace.ttf b/tools/editor/art/lite/data/fonts/monospace.ttf new file mode 100644 index 0000000..5919b5d Binary files /dev/null and b/tools/editor/art/lite/data/fonts/monospace.ttf differ diff --git a/tools/editor/art/lite/data/languages/language_c.lua b/tools/editor/art/lite/data/languages/language_c.lua new file mode 100644 index 0000000..8e8ee98 --- /dev/null +++ b/tools/editor/art/lite/data/languages/language_c.lua @@ -0,0 +1,59 @@ +local syntax = require "core.syntax" + +syntax.add { + files = { "%.c$", "%.h$", "%.inl$", "%.cpp$", "%.hpp$" }, + comment = "//", + patterns = { + { pattern = "//.-\n", type = "comment" }, + { pattern = { "/%*", "%*/" }, type = "comment" }, + { pattern = { "#", "[^\\]\n" }, type = "comment" }, + { pattern = { '"', '"', '\\' }, type = "string" }, + { pattern = { "'", "'", '\\' }, type = "string" }, + { pattern = "-?0x%x+", type = "number" }, + { pattern = "-?%d+[%d%.eE]*f?", type = "number" }, + { pattern = "-?%.?%d+f?", type = "number" }, + { pattern = "[%+%-=/%*%^%%<>!~|&]", type = "operator" }, + { pattern = "[%a_][%w_]*%f[(]", type = "function" }, + { pattern = "[%a_][%w_]*", type = "symbol" }, + }, + symbols = { + ["if"] = "keyword", + ["then"] = "keyword", + ["else"] = "keyword", + ["elseif"] = "keyword", + ["do"] = "keyword", + ["while"] = "keyword", + ["for"] = "keyword", + ["break"] = "keyword", + ["continue"] = "keyword", + ["return"] = "keyword", + ["goto"] = "keyword", + ["struct"] = "keyword", + ["union"] = "keyword", + ["typedef"] = "keyword", + ["enum"] = "keyword", + ["extern"] = "keyword", + ["static"] = "keyword", + ["volatile"] = "keyword", + ["const"] = "keyword", + ["inline"] = "keyword", + ["switch"] = "keyword", + ["case"] = "keyword", + ["default"] = "keyword", + ["auto"] = "keyword", + ["const"] = "keyword", + ["void"] = "keyword", + ["int"] = "keyword2", + ["short"] = "keyword2", + ["long"] = "keyword2", + ["float"] = "keyword2", + ["double"] = "keyword2", + ["char"] = "keyword2", + ["unsigned"] = "keyword2", + ["bool"] = "keyword2", + ["true"] = "literal", + ["false"] = "literal", + ["NULL"] = "literal", + }, +} + diff --git a/tools/editor/art/lite/data/languages/language_css.lua b/tools/editor/art/lite/data/languages/language_css.lua new file mode 100644 index 0000000..021c5d3 --- /dev/null +++ b/tools/editor/art/lite/data/languages/language_css.lua @@ -0,0 +1,23 @@ +local syntax = require "core.syntax" + +syntax.add { + files = { "%.css$" }, + patterns = { + { pattern = "\\.", type = "normal" }, + { pattern = "//.-\n", type = "comment" }, + { pattern = { "/%*", "%*/" }, type = "comment" }, + { pattern = { '"', '"', '\\' }, type = "string" }, + { pattern = { "'", "'", '\\' }, type = "string" }, + { pattern = "[%a][%w-]*%s*%f[:]", type = "keyword" }, + { pattern = "#%x+", type = "string" }, + { pattern = "-?%d+[%d%.]*p[xt]", type = "number" }, + { pattern = "-?%d+[%d%.]*deg", type = "number" }, + { pattern = "-?%d+[%d%.]*", type = "number" }, + { pattern = "[%a_][%w_]*", type = "symbol" }, + { pattern = "#[%a][%w_-]*", type = "keyword2" }, + { pattern = "@[%a][%w_-]*", type = "keyword2" }, + { pattern = "%.[%a][%w_-]*", type = "keyword2" }, + { pattern = "[{}:]", type = "operator" }, + }, + symbols = {}, +} diff --git a/tools/editor/art/lite/data/languages/language_js.lua b/tools/editor/art/lite/data/languages/language_js.lua new file mode 100644 index 0000000..e486099 --- /dev/null +++ b/tools/editor/art/lite/data/languages/language_js.lua @@ -0,0 +1,70 @@ +local syntax = require "core.syntax" + +syntax.add { + files = { "%.js$", "%.json$", "%.cson$" }, + comment = "//", + patterns = { + { pattern = "//.-\n", type = "comment" }, + { pattern = { "/%*", "%*/" }, type = "comment" }, + --< https://github.com/rxi/lite/pull/248/commits/1820b319381255dd377fa9ae373a8cde43b076da + { pattern = { '/', '/', '\\' }, type = "string" }, + --< + { pattern = { '"', '"', '\\' }, type = "string" }, + { pattern = { "'", "'", '\\' }, type = "string" }, + { pattern = { "`", "`", '\\' }, type = "string" }, + { pattern = "0x[%da-fA-F]+", type = "number" }, + { pattern = "-?%d+[%d%.eE]*", type = "number" }, + { pattern = "-?%.?%d+", type = "number" }, + { pattern = "[%+%-=/%*%^%%<>!~|&]", type = "operator" }, + { pattern = "[%a_][%w_]*%f[(]", type = "function" }, + { pattern = "[%a_][%w_]*", type = "symbol" }, + }, + symbols = { + ["async"] = "keyword", + ["await"] = "keyword", + ["break"] = "keyword", + ["case"] = "keyword", + ["catch"] = "keyword", + ["class"] = "keyword", + ["const"] = "keyword", + ["continue"] = "keyword", + ["debugger"] = "keyword", + ["default"] = "keyword", + ["delete"] = "keyword", + ["do"] = "keyword", + ["else"] = "keyword", + ["export"] = "keyword", + ["extends"] = "keyword", + ["finally"] = "keyword", + ["for"] = "keyword", + ["function"] = "keyword", + ["get"] = "keyword", + ["if"] = "keyword", + ["import"] = "keyword", + ["in"] = "keyword", + ["instanceof"] = "keyword", + ["let"] = "keyword", + ["new"] = "keyword", + ["return"] = "keyword", + ["set"] = "keyword", + ["static"] = "keyword", + ["super"] = "keyword", + ["switch"] = "keyword", + ["throw"] = "keyword", + ["try"] = "keyword", + ["typeof"] = "keyword", + ["var"] = "keyword", + ["void"] = "keyword", + ["while"] = "keyword", + ["with"] = "keyword", + ["yield"] = "keyword", + ["true"] = "literal", + ["false"] = "literal", + ["null"] = "literal", + ["undefined"] = "literal", + ["arguments"] = "keyword2", + ["Infinity"] = "keyword2", + ["NaN"] = "keyword2", + ["this"] = "keyword2", + }, +} diff --git a/tools/editor/art/lite/data/languages/language_lua.lua b/tools/editor/art/lite/data/languages/language_lua.lua new file mode 100644 index 0000000..915d273 --- /dev/null +++ b/tools/editor/art/lite/data/languages/language_lua.lua @@ -0,0 +1,50 @@ +local syntax = require "core.syntax" + +syntax.add { + files = "%.lua$", + headers = "^#!.*[ /]lua", + comment = "--", + patterns = { + { pattern = { '"', '"', '\\' }, type = "string" }, + { pattern = { "'", "'", '\\' }, type = "string" }, + { pattern = { "%[%[", "%]%]" }, type = "string" }, + { pattern = { "%-%-%[%[", "%]%]"}, type = "comment" }, + { pattern = "%-%-.-\n", type = "comment" }, + { pattern = "-?0x%x+", type = "number" }, + { pattern = "-?%d+[%d%.eE]*", type = "number" }, + { pattern = "-?%.?%d+", type = "number" }, + { pattern = "<%a+>", type = "keyword2" }, + { pattern = "%.%.%.?", type = "operator" }, + { pattern = "[<>~=]=", type = "operator" }, + { pattern = "[%+%-=/%*%^%%#<>]", type = "operator" }, + { pattern = "[%a_][%w_]*%s*%f[(\"{]", type = "function" }, + { pattern = "[%a_][%w_]*", type = "symbol" }, + { pattern = "::[%a_][%w_]*::", type = "function" }, + }, + symbols = { + ["if"] = "keyword", + ["then"] = "keyword", + ["else"] = "keyword", + ["elseif"] = "keyword", + ["end"] = "keyword", + ["do"] = "keyword", + ["function"] = "keyword", + ["repeat"] = "keyword", + ["until"] = "keyword", + ["while"] = "keyword", + ["for"] = "keyword", + ["break"] = "keyword", + ["return"] = "keyword", + ["local"] = "keyword", + ["in"] = "keyword", + ["not"] = "keyword", + ["and"] = "keyword", + ["or"] = "keyword", + ["goto"] = "keyword", + ["self"] = "keyword2", + ["true"] = "literal", + ["false"] = "literal", + ["nil"] = "literal", + }, +} + diff --git a/tools/editor/art/lite/data/languages/language_md.lua b/tools/editor/art/lite/data/languages/language_md.lua new file mode 100644 index 0000000..9f0f14e --- /dev/null +++ b/tools/editor/art/lite/data/languages/language_md.lua @@ -0,0 +1,21 @@ +local syntax = require "core.syntax" + +syntax.add { + files = { "%.md$", "%.markdown$" }, + patterns = { + { pattern = "\\.", type = "normal" }, + { pattern = { "" }, type = "comment" }, + { pattern = { "```", "```" }, type = "string" }, + { pattern = { "``", "``", "\\" }, type = "string" }, + { pattern = { "`", "`", "\\" }, type = "string" }, + { pattern = { "~~", "~~", "\\" }, type = "keyword2" }, + { pattern = "%-%-%-+", type = "comment" }, + { pattern = "%*%s+", type = "operator" }, + { pattern = { "%*", "[%*\n]", "\\" }, type = "operator" }, + { pattern = { "%_", "[%_\n]", "\\" }, type = "keyword2" }, + { pattern = "#.-\n", type = "keyword" }, + { pattern = "!?%[.-%]%(.-%)", type = "function" }, + { pattern = "https?://%S+", type = "function" }, + }, + symbols = { }, +} diff --git a/tools/editor/art/lite/data/languages/language_python.lua b/tools/editor/art/lite/data/languages/language_python.lua new file mode 100644 index 0000000..e6315c4 --- /dev/null +++ b/tools/editor/art/lite/data/languages/language_python.lua @@ -0,0 +1,55 @@ +local syntax = require "core.syntax" + +syntax.add { + files = { "%.py$", "%.pyw$" }, + headers = "^#!.*[ /]python", + comment = "#", + patterns = { + { pattern = { "#", "\n" }, type = "comment" }, + { pattern = { '[ruU]?"', '"', '\\' }, type = "string" }, + { pattern = { "[ruU]?'", "'", '\\' }, type = "string" }, + { pattern = { '"""', '"""' }, type = "string" }, + { pattern = "0x[%da-fA-F]+", type = "number" }, + { pattern = "-?%d+[%d%.eE]*", type = "number" }, + { pattern = "-?%.?%d+", type = "number" }, + { pattern = "[%+%-=/%*%^%%<>!~|&]", type = "operator" }, + { pattern = "[%a_][%w_]*%f[(]", type = "function" }, + { pattern = "[%a_][%w_]*", type = "symbol" }, + }, + symbols = { + ["class"] = "keyword", + ["finally"] = "keyword", + ["is"] = "keyword", + ["return"] = "keyword", + ["continue"] = "keyword", + ["for"] = "keyword", + ["lambda"] = "keyword", + ["try"] = "keyword", + ["def"] = "keyword", + ["from"] = "keyword", + ["nonlocal"] = "keyword", + ["while"] = "keyword", + ["and"] = "keyword", + ["global"] = "keyword", + ["not"] = "keyword", + ["with"] = "keyword", + ["as"] = "keyword", + ["elif"] = "keyword", + ["if"] = "keyword", + ["or"] = "keyword", + ["else"] = "keyword", + ["import"] = "keyword", + ["pass"] = "keyword", + ["break"] = "keyword", + ["except"] = "keyword", + ["in"] = "keyword", + ["del"] = "keyword", + ["raise"] = "keyword", + ["yield"] = "keyword", + ["assert"] = "keyword", + ["self"] = "keyword2", + ["None"] = "literal", + ["True"] = "literal", + ["False"] = "literal", + } +} diff --git a/tools/editor/art/lite/data/languages/language_xml.lua b/tools/editor/art/lite/data/languages/language_xml.lua new file mode 100644 index 0000000..5240bdc --- /dev/null +++ b/tools/editor/art/lite/data/languages/language_xml.lua @@ -0,0 +1,21 @@ +local syntax = require "core.syntax" + +syntax.add { + files = { "%.xml$", "%.html?$" }, + headers = "<%?xml", + patterns = { + { pattern = { "" }, type = "comment" }, + { pattern = { '%f[^>][^<]', '%f[<]' }, type = "normal" }, + { pattern = { '"', '"', '\\' }, type = "string" }, + { pattern = { "'", "'", '\\' }, type = "string" }, + { pattern = "0x[%da-fA-F]+", type = "number" }, + { pattern = "-?%d+[%d%.]*f?", type = "number" }, + { pattern = "-?%.?%d+f?", type = "number" }, + { pattern = "%f[^<]![%a_][%w_]*", type = "keyword2" }, + { pattern = "%f[^<][%a_][%w_]*", type = "function" }, + { pattern = "%f[^<]/[%a_][%w_]*", type = "function" }, + { pattern = "[%a_][%w_]*", type = "keyword" }, + { pattern = "[/<>=]", type = "operator" }, + }, + symbols = {}, +} diff --git a/tools/editor/art/lite/data/lite.license b/tools/editor/art/lite/data/lite.license new file mode 100644 index 0000000..39ddd05 --- /dev/null +++ b/tools/editor/art/lite/data/lite.license @@ -0,0 +1,19 @@ +Copyright (c) 2020 rxi + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/tools/editor/art/lite/data/lite.readme b/tools/editor/art/lite/data/lite.readme new file mode 100644 index 0000000..6081e8b --- /dev/null +++ b/tools/editor/art/lite/data/lite.readme @@ -0,0 +1,41 @@ +# lite +![screenshot](https://user-images.githubusercontent.com/3920290/81471642-6c165880-91ea-11ea-8cd1-fae7ae8f0bc4.png) + +A lightweight text editor written in Lua + +* **[Get lite](https://github.com/rxi/lite/releases/latest)** — Download + for Windows and Linux +* **[Get started](doc/usage.md)** — A quick overview on how to get started +* **[Get plugins](https://github.com/rxi/lite-plugins)** — Add additional + functionality +* **[Get color themes](https://github.com/rxi/lite-colors)** — Add additional colors + themes + +## Overview +lite is a lightweight text editor written mostly in Lua — it aims to provide +something practical, pretty, *small* and fast, implemented as simply as +possible; easy to modify and extend, or to use without doing either. + +## Customization +Additional functionality can be added through plugins which are available from +the [plugins repository](https://github.com/rxi/lite-plugins); additional color +themes can be found in the [colors repository](https://github.com/rxi/lite-colors). +The editor can be customized by making changes to the +[user module](data/user/init.lua). + +## Building +You can build the project yourself on Linux using the `build.sh` script +or on Windows using the `build.bat` script *([MinGW](https://nuwen.net/mingw.html) is required)*. +Note that the project does not need to be rebuilt if you are only making changes +to the Lua portion of the code. + +## Contributing +Any additional functionality that can be added through a plugin should be done +so as a plugin, after which a pull request to the +[plugins repository](https://github.com/rxi/lite-plugins) can be made. In hopes +of remaining lightweight, pull requests adding additional functionality to the +core will likely not be merged. Bug reports and bug fixes are welcome. + +## License +This project is free software; you can redistribute it and/or modify it under +the terms of the MIT license. See [LICENSE](LICENSE) for details. diff --git a/tools/editor/art/lite/data/lite.usage b/tools/editor/art/lite/data/lite.usage new file mode 100644 index 0000000..3b536cc --- /dev/null +++ b/tools/editor/art/lite/data/lite.usage @@ -0,0 +1,146 @@ +# lite + +![screenshot](https://user-images.githubusercontent.com/3920290/81471642-6c165880-91ea-11ea-8cd1-fae7ae8f0bc4.png) + +## Overview +lite is a lightweight text editor written mostly in Lua — it aims to provide +something practical, pretty, *small* and fast, implemented as simply as +possible; easy to modify and extend, or to use without doing either. + + +## Getting Started +When lite is started it's typically opened with a *project directory* — this +is the directory where your project's code and other data resides. The project +directory is set once when lite is started and, for the duration of the +session, cannot be changed. + +To open lite with a specific project directory the directory name can be passed +as a command-line argument *(`.` can be passed to use the current directory)* or +the directory can be dragged onto either the lite executable or a running +instance of lite. + +The main way of opening files in lite is through the `core:find-file` command +— this provides a fuzzy finder over all of the project's files and can be +opened using the **`ctrl+p`** shortcut by default. + +Commands can be run using keyboard shortcuts, or by using the `core:find-command` +command bound to **`ctrl+shift+p`** by default. For example, pressing +`ctrl+shift+p` and typing `newdoc` then pressing `return` would open a new +document. The current keyboard shortcut for a command can be seen to the right +of the command name on the command finder, thus to find the shortcut for a command +`ctrl+shift+p` can be pressed and the command name typed. + + +## User Module +lite can be configured through use of the user module. The user module can be +used for changing options in the config module, adding additional key bindings, +loading custom color themes, modifying the style or changing any other part of +lite to your personal preference. + +The user module is loaded by lite when the application starts, after the plugins +have been loaded. + +The user module can be modified by running the `core:open-user-module` command +or otherwise directly opening the `data/user/init.lua` file. + + +## Project Module +The project module is an optional module which is loaded from the current +project's directory when lite is started. Project modules can be useful for +things like adding custom commands for project-specific build systems, or +loading project-specific plugins. + +The project module is loaded by lite when the application starts, after both the +plugins and user module have been loaded. + +The project module can be edited by running the `core:open-project-module` +command — if the module does not exist for the current project when the +command is run it will be created. + + +## Commands +Commands in lite are used both through the command finder (`ctrl+shift+p`) and +by lite's keyboard shortcut system. Commands consist of 3 components: +* **Name** — The command name in the form of `namespace:action-name`, for + example: `doc:select-all` +* **Predicate** — A function that returns true if the command can be ran, for + example, for any document commands the predicate checks whether the active + view is a document +* **Function** — The function which performs the command itself + +Commands can be added using the `command.add` function provided by the +`core.command` module: +```lua +local core = require "core" +local command = require "core.command" + +command.add("core.docview", { + ["doc:save"] = function() + core.active_view.doc:save() + core.log("Saved '%s', core.active_view.doc.filename) + end +}) +``` + +Commands can be performed programatically (eg. from another command or by your +user module) by calling the `command.perform` function after requiring the +`command` module: +```lua +local command = require "core.command" +command.perform "core:quit" +``` + + +## Keymap +All keyboard shortcuts in lite are handled by the `core.keymap` module. A key +binding in lite maps a "stroke" (eg. `ctrl+q`) to one or more commands (eg. +`core:quit`). When the shortcut is pressed lite will iterate each command +assigned to that key and run the *predicate function* for that command — if the +predicate passes it stops iterating and runs the command. + +An example of where this used is the default binding of the `tab` key: +``` lua + ["tab"] = { "command:complete", "doc:indent" }, +``` +When tab is pressed the `command:complete` command is attempted which will only +succeed if the command-input at the bottom of the window is active. Otherwise +the `doc:indent` command is attempted which will only succeed if we have a +document as our active view. + +A new mapping can be added by your user module as follows: +```lua +local keymap = require "core.keymap" +keymap.add { ["ctrl+q"] = "core:quit" } +``` + + +## Plugins +Plugins in lite are normal lua modules and are treated as such — no +complicated plugin manager is provided, and, once a plugin is loaded, it is never +expected be to have to unload itself. + +To install a plugin simply drop it in the `data/plugins` directory — installed +plugins will be automatically loaded when lite starts. To uninstall a plugin the +plugin file can be deleted — any plugin (including those included with lite's +default installation) can be deleted to remove its functionality. + +If you want to load a plugin only under a certain circumstance (for example, +only on a given project) the plugin can be placed somewhere other than the +`data/plugins` directory so that it is not automatically loaded. The plugin can +then be loaded manually as needed by using the `require` function. + +Plugins can be downloaded from the [plugins repository](https://github.com/rxi/lite-plugins). + + +## Color Themes +Colors themes in lite are lua modules which overwrite the color fields of lite's +`core.style` module. Color themes should be placed in the `data/user/colors` +directory. + +A color theme can be set by requiring it in your user module: +```lua +require "user.colors.winter" +``` + +Color themes can be downloaded from the [color themes repository](https://github.com/rxi/lite-colors). + diff --git a/tools/editor/art/lite/data/plugins/autoinsert.lua b/tools/editor/art/lite/data/plugins/autoinsert.lua new file mode 100644 index 0000000..243e00b --- /dev/null +++ b/tools/editor/art/lite/data/plugins/autoinsert.lua @@ -0,0 +1,114 @@ +local core = require "core" +local translate = require "core.doc.translate" +local config = require "core.config" +local DocView = require "core.docview" +local command = require "core.command" +local keymap = require "core.keymap" + + +config.autoinsert_map = { + ["["] = "]", + ["{"] = "}", + ["("] = ")", + ['"'] = '"', + ["'"] = "'", + ["`"] = "`", +} + + +local function is_closer(chr) + for _, v in pairs(config.autoinsert_map) do + if v == chr then + return true + end + end +end + +local function count_char(text, chr) + local count = 0 + for _ in text:gmatch(chr) do + count = count + 1 + end + return count +end + + +local on_text_input = DocView.on_text_input + +function DocView:on_text_input(text) + local mapping = config.autoinsert_map[text] + + -- prevents plugin from operating on `CommandView` + if getmetatable(self) ~= DocView then + return on_text_input(self, text) + end + + -- wrap selection if we have a selection + if mapping and self.doc:has_selection() then + local l1, c1, l2, c2, swap = self.doc:get_selection(true) + self.doc:insert(l2, c2, mapping) + self.doc:insert(l1, c1, text) + self.doc:set_selection(l1, c1, l2, c2 + 2, swap) + return + end + + -- skip inserting closing text + local chr = self.doc:get_char(self.doc:get_selection()) + if text == chr and is_closer(chr) then + self.doc:move_to(1) + return + end + + -- don't insert closing quote if we have a non-even number on this line + local line = self.doc:get_selection() + if text == mapping and count_char(self.doc.lines[line], text) % 2 == 1 then + return on_text_input(self, text) + end + + -- auto insert closing bracket + if mapping and (chr:find("%s") or is_closer(chr) and chr ~= '"') then + on_text_input(self, text) + on_text_input(self, mapping) + self.doc:move_to(-1) + return + end + + on_text_input(self, text) +end + + + +local function predicate() + return getmetatable(core.active_view) == DocView + and not core.active_view.doc:has_selection() +end + +command.add(predicate, { + ["autoinsert:backspace"] = function() + local doc = core.active_view.doc + local l, c = doc:get_selection() + local chr = doc:get_char(l, c) + if config.autoinsert_map[doc:get_char(l, c - 1)] and is_closer(chr) then + doc:delete_to(1) + end + command.perform "doc:backspace" + end, + + ["autoinsert:delete-to-previous-word-start"] = function() + local doc = core.active_view.doc + local le, ce = translate.previous_word_start(doc, doc:get_selection()) + while true do + local l, c = doc:get_selection() + if l == le and c == ce then + break + end + command.perform "autoinsert:backspace" + end + end, +}) + +keymap.add { + ["backspace"] = "autoinsert:backspace", + ["ctrl+backspace"] = "autoinsert:delete-to-previous-word-start", + ["ctrl+shift+backspace"] = "autoinsert:delete-to-previous-word-start", +} diff --git a/tools/editor/art/lite/data/plugins/autowrap.lua b/tools/editor/art/lite/data/plugins/autowrap.lua new file mode 100644 index 0000000..85d4c24 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/autowrap.lua @@ -0,0 +1,35 @@ +require "plugins.reflow" +local config = require "core.config" +local command = require "core.command" +local DocView = require "core.docview" + +config.autowrap_files = { "%.md$", "%.txt$" } + + +local on_text_input = DocView.on_text_input + +DocView.on_text_input = function(self, ...) + on_text_input(self, ...) + + -- early-exit if the filename does not match a file type pattern + local filename = self.doc.filename or "" + local matched = false + for _, ptn in ipairs(config.autowrap_files) do + if filename:match(ptn) then + matched = true + break + end + end + if not matched then return end + + -- do automatic reflow on line if we're typing at the end of the line and have + -- reached the line limit + local line, col = self.doc:get_selection() + local text = self.doc:get_text(line, 1, line, math.huge) + if #text >= config.line_limit and col > #text then + command.perform("doc:select-lines") + command.perform("reflow:reflow") + command.perform("doc:move-to-next-char") + command.perform("doc:move-to-previous-char") + end +end diff --git a/tools/editor/art/lite/data/plugins/bracketmatch.lua b/tools/editor/art/lite/data/plugins/bracketmatch.lua new file mode 100644 index 0000000..4253de7 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/bracketmatch.lua @@ -0,0 +1,117 @@ +local core = require "core" +local style = require "core.style" +local command = require "core.command" +local keymap = require "core.keymap" +local DocView = require "core.docview" + +local bracket_maps = { + -- [ ] ( ) { } + { [91] = 93, [40] = 41, [123] = 125, step = 1 }, + -- ] [ ) ( } { + { [93] = 91, [41] = 40, [125] = 123, step = -1 }, +} + + +local function get_matching_bracket(doc, line, col, line_limit, open_byte, close_byte, step) + local end_line = line + line_limit * step + local depth = 0 + + while line ~= end_line do + local byte = doc.lines[line]:byte(col) + if byte == open_byte then + depth = depth + 1 + elseif byte == close_byte then + depth = depth - 1 + if depth == 0 then return line, col end + end + + local prev_line, prev_col = line, col + line, col = doc:position_offset(line, col, step) + if line == prev_line and col == prev_col then + break + end + end +end + + +local state = {} + +local function update_state(line_limit) + line_limit = line_limit or math.huge + + -- reset if we don't have a document (eg. DocView isn't focused) + local doc = core.active_view.doc + if not doc then + state = {} + return + end + + -- early exit if nothing has changed since the last call + local line, col = doc:get_selection() + local change_id = doc:get_change_id() + if state.doc == doc and state.line == line and state.col == col + and state.change_id == change_id and state.limit == line_limit then + return + end + + -- find matching bracket if we're on a bracket + local line2, col2 + for _, map in ipairs(bracket_maps) do + for i = 0, -1, -1 do + local line, col = doc:position_offset(line, col, i) + local open = doc.lines[line]:byte(col) + local close = map[open] + if close then + line2, col2 = get_matching_bracket(doc, line, col, line_limit, open, close, map.step) + goto found + end + end + end + ::found:: + + -- update + state = { + change_id = change_id, + doc = doc, + line = line, + col = col, + line2 = line2, + col2 = col2, + limit = line_limit, + } +end + + +local update = DocView.update + +function DocView:update(...) + update(self, ...) + update_state(100) +end + + +local draw_line_text = DocView.draw_line_text + +function DocView:draw_line_text(idx, x, y) + draw_line_text(self, idx, x, y) + + if self.doc == state.doc and idx == state.line2 then + local color = style.bracketmatch_color or style.syntax["function"] + local x1 = x + self:get_col_x_offset(idx, state.col2) + local x2 = x + self:get_col_x_offset(idx, state.col2 + 1) + local h = math.ceil(1 * SCALE) + renderer.draw_rect(x1, y + self:get_line_height() - h, x2 - x1, h, color) + end +end + + +command.add("core.docview", { + ["bracket-match:move-to-matching"] = function() + update_state() + if state.line2 then + core.active_view.doc:set_selection(state.line2, state.col2) + end + end, +}) + +keymap.add { ["ctrl+m"] = "bracket-match:move-to-matching" } diff --git a/tools/editor/art/lite/data/plugins/detectindent.lua b/tools/editor/art/lite/data/plugins/detectindent.lua new file mode 100644 index 0000000..7ef46e3 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/detectindent.lua @@ -0,0 +1,63 @@ +local core = require "core" +local command = require "core.command" +local config = require "core.config" +local DocView = require "core.docview" +local Doc = require "core.doc" + +local cache = setmetatable({}, { __mode = "k" }) + + +local function detect_indent(doc) + for _, text in ipairs(doc.lines) do + local str = text:match("^ +") + if str then return "soft", #str end + local str = text:match("^\t+") + if str then return "hard" end + end +end + + +local function update_cache(doc) + local type, size = detect_indent(doc) + if type then + cache[doc] = { type = type, size = size } + end +end + + +local new = Doc.new +function Doc:new(...) + new(self, ...) + update_cache(self) +end + +local clean = Doc.clean +function Doc:clean(...) + clean(self, ...) + update_cache(self) +end + + +local function with_indent_override(doc, fn, ...) + local c = cache[doc] + if not c then + return fn(...) + end + local type, size = config.tab_type, config.indent_size + config.tab_type, config.indent_size = c.type, c.size or config.indent_size + local r1, r2, r3 = fn(...) + config.tab_type, config.indent_size = type, size + return r1, r2, r3 +end + + +local perform = command.perform +function command.perform(...) + return with_indent_override(core.active_view.doc, perform, ...) +end + + +local draw = DocView.draw +function DocView:draw(...) + return with_indent_override(self.doc, draw, self, ...) +end diff --git a/tools/editor/art/lite/data/plugins/eofnewline.lua b/tools/editor/art/lite/data/plugins/eofnewline.lua new file mode 100644 index 0000000..d39d13a --- /dev/null +++ b/tools/editor/art/lite/data/plugins/eofnewline.lua @@ -0,0 +1,29 @@ +local core = require "core" +local command = require "core.command" +local Doc = require "core.doc" + +local function eof_newline(doc) + local leof,neof = #doc.lines,#doc.lines + for i = leof,1,-1 do + if not string.match(doc.lines[i],"^%s*$") then break end + neof = i + end + local eol,_ = string.find(doc.lines[neof],"\n") + if eol then + doc:remove(neof,eol,math.huge,math.huge) + return + end + doc:insert(neof,math.huge,"\n") +end + +command.add("core.docview", { + ["eof-newline:eof-newline"] = function() + eof_newline(core.active_view.doc) + end, +}) + +local save = Doc.save + Doc.save = function(self, ...) + eof_newline(self) + save(self, ...) +end diff --git a/tools/editor/art/lite/data/plugins/indentguide.lua b/tools/editor/art/lite/data/plugins/indentguide.lua new file mode 100644 index 0000000..daf7d8b --- /dev/null +++ b/tools/editor/art/lite/data/plugins/indentguide.lua @@ -0,0 +1,45 @@ +local style = require "core.style" +local config = require "core.config" +local DocView = require "core.docview" + + +local function get_line_spaces(doc, idx, dir) + local text = doc.lines[idx] + if not text then + return 0 + end + local s, e = text:find("^%s*") + if e == #text then + return get_line_spaces(doc, idx + dir, dir) + end + local n = 0 + for i = s, e do + n = n + (text:byte(i) == 9 and config.indent_size or 1) + end + return n +end + + +local function get_line_indent_guide_spaces(doc, idx) + if doc.lines[idx]:find("^%s*\n") then + return math.max( + get_line_spaces(doc, idx - 1, -1), + get_line_spaces(doc, idx + 1, 1)) + end + return get_line_spaces(doc, idx) +end + + +local draw_line_text = DocView.draw_line_text + +function DocView:draw_line_text(idx, x, y) + local spaces = get_line_indent_guide_spaces(self.doc, idx) + local sw = self:get_font():get_width(" ") + local w = math.ceil(1 * SCALE) + local h = self:get_line_height() + for i = 0, spaces - 1, config.indent_size do + local color = style.guide or style.selection + renderer.draw_rect(x + sw * i, y, w, h, color) + end + draw_line_text(self, idx, x, y) +end diff --git a/tools/editor/art/lite/data/plugins/lineguide.lua b/tools/editor/art/lite/data/plugins/lineguide.lua new file mode 100644 index 0000000..fc24567 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/lineguide.lua @@ -0,0 +1,18 @@ +local config = require "core.config" +local style = require "core.style" +local DocView = require "core.docview" + +local draw = DocView.draw + +function DocView:draw(...) + draw(self, ...) + + local offset = self:get_font():get_width("n") * config.line_limit + local x = self:get_line_screen_position(1) + offset + local y = self.position.y + local w = math.ceil(SCALE * 1) + local h = self.size.y + + local color = style.guide or style.selection + renderer.draw_rect(x, y, w, h, color) +end diff --git a/tools/editor/art/lite/data/plugins/macro.lua b/tools/editor/art/lite/data/plugins/macro.lua new file mode 100644 index 0000000..9f3b848 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/macro.lua @@ -0,0 +1,70 @@ +-- mod-version:3 +local core = require "core" +local command = require "core.command" +local keymap = require "core.keymap" + +local handled_events = { + ["keypressed"] = true, + ["keyreleased"] = true, + ["textinput"] = true, +} + +local state = "stopped" +local event_buffer = {} +local modkeys = {} + +local on_event = core.on_event + +core.on_event = function(type, ...) + local res = on_event(type, ...) + if state == "recording" and handled_events[type] then + table.insert(event_buffer, { type, ... }) + end + return res +end + + +local function clone(t) + local res = {} + for k, v in pairs(t) do res[k] = v end + return res +end + + +local function predicate() + return state ~= "playing" +end + + +command.add(predicate, { + ["macro:toggle-record"] = function() + if state == "stopped" then + state = "recording" + event_buffer = {} + modkeys = clone(keymap.modkeys) + core.log("Recording macro...") + else + state = "stopped" + core.log("Stopped recording macro (%d events)", #event_buffer) + end + end, + + ["macro:play"] = function() + state = "playing" + core.log("Playing macro... (%d events)", #event_buffer) + local mk = keymap.modkeys + keymap.modkeys = clone(modkeys) + for _, ev in ipairs(event_buffer) do + on_event(table.unpack(ev)) + core.root_view:update() + end + keymap.modkeys = mk + state = "stopped" + end, +}) + + +keymap.add { + ["ctrl+shift+;"] = "macro:toggle-record", + ["ctrl+;"] = "macro:play", +} diff --git a/tools/editor/art/lite/data/plugins/markers.lua b/tools/editor/art/lite/data/plugins/markers.lua new file mode 100644 index 0000000..b8d763c --- /dev/null +++ b/tools/editor/art/lite/data/plugins/markers.lua @@ -0,0 +1,103 @@ +-- Markers plugin for lite text editor +-- original implementation by Petri Häkkinen + +local core = require "core" +local command = require "core.command" +local keymap = require "core.keymap" +local style = require "core.style" +local DocView = require "core.docview" +local Doc = require "core.doc" + +local cache = {} -- this table contains subtables for each document, each subtable is a set of line numbers +setmetatable(cache, { + __mode = "k", + __index = function(t, k) + t[k] = {} + return t[k] + end, +}) + + +local function shift_lines(doc, at, diff) + if diff == 0 then return end + local t = {} + for line in pairs(cache[doc]) do + line = line >= at and line + diff or line + t[line] = true + end + cache[doc] = t +end + + +local raw_insert = Doc.raw_insert + +function Doc:raw_insert(line, col, text, ...) + raw_insert(self, line, col, text, ...) + local line_count = 0 + for _ in text:gmatch("\n") do + line_count = line_count + 1 + end + shift_lines(self, line, line_count) +end + + +local raw_remove = Doc.raw_remove + +function Doc:raw_remove(line1, col1, line2, col2, ...) + raw_remove(self, line1, col1, line2, col2, ...) + shift_lines(self, line2, line1 - line2) +end + + +local draw_line_gutter = DocView.draw_line_gutter + +function DocView:draw_line_gutter(idx, x, y) + if cache[self.doc] and cache[self.doc][idx] then + local h = self:get_line_height() + renderer.draw_rect(x, y, style.padding.x * 0.4, h, style.selection) + end + draw_line_gutter(self, idx, x, y) +end + + +command.add("core.docview", { + ["markers:toggle-marker"] = function() + local doc = core.active_view.doc + local line = doc:get_selection() + local markers = cache[doc] + + if markers[line] then + markers[line] = nil + else + markers[line] = true + end + end, + + ["markers:go-to-next-marker"] = function() + local doc = core.active_view.doc + local line = doc:get_selection() + local markers = cache[doc] + + local first_marker = math.huge + local next_marker = math.huge + for l, _ in pairs(markers) do + if l > line and l < next_marker then + next_marker = l + end + first_marker = math.min(first_marker, l) + end + if next_marker == math.huge then + next_marker = first_marker + end + if next_marker ~= math.huge then + doc:set_selection(next_marker, 1) + core.active_view:scroll_to_line(next_marker, true) + end + end, +}) + + +keymap.add { + ["ctrl+f2"] = "markers:toggle-marker", + ["f2"] = "markers:go-to-next-marker", +} diff --git a/tools/editor/art/lite/data/plugins/minimap.lua b/tools/editor/art/lite/data/plugins/minimap.lua new file mode 100644 index 0000000..8ef29a6 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/minimap.lua @@ -0,0 +1,295 @@ +local command = require "core.command" +local common = require "core.common" +local config = require "core.config" +local style = require "core.style" +local DocView = require "core.docview" + +-- General plugin settings +config.minimap_enabled = true +config.minimap_width = 100 +config.minimap_instant_scroll = false +config.minimap_syntax_highlight = true +config.minimap_scale = 1 +config.minimap_draw_background = true + +-- Configure size for rendering each char in the minimap +local char_height = 1 * SCALE * config.minimap_scale +local char_spacing = 0.8 * SCALE * config.minimap_scale +local line_spacing = 2 * SCALE * config.minimap_scale + +-- Overloaded since the default implementation adds a extra x3 size of hotspot for the mouse to hit the scrollbar. +local prev_scrollbar_overlaps_point = DocView.scrollbar_overlaps_point +DocView.scrollbar_overlaps_point = function(self, x, y) + if not config.minimap_enabled then return prev_scrollbar_overlaps_point(self, x, y) end + + local sx, sy, sw, sh = self:get_scrollbar_rect() + return x >= sx and x < sx + sw and y >= sy and y < sy + sh +end + +-- Helper function to determine if current file is too large to be shown fully inside the minimap area. +local function is_file_too_large(self) + local line_count = #self.doc.lines + local _, _, _, sh = self:get_scrollbar_rect() + + -- check if line count is too large to fit inside the minimap area + local max_minmap_lines = math.floor(sh / line_spacing) + return line_count > 1 and line_count > max_minmap_lines +end + +-- Overloaded with an extra check if the user clicked inside the minimap to automatically scroll to that line. +local prev_on_mouse_pressed = DocView.on_mouse_pressed +DocView.on_mouse_pressed = function(self, button, x, y, clicks) + if not config.minimap_enabled then return prev_on_mouse_pressed(self, button, x, y, clicks) end + + -- check if user clicked in the minimap area and jump directly to that line + -- unless they are actually trying to perform a drag + local minimap_hit = self:scrollbar_overlaps_point(x, y) + if minimap_hit then + local line_count = #self.doc.lines + local minimap_height = line_count * line_spacing + + -- check if line count is too large to fit inside the minimap area + local is_too_large = is_file_too_large(self) + if is_too_large then + local _, _, _, sh = self:get_scrollbar_rect() + minimap_height = sh + end + + -- calc which line to jump to + local dy = y - self.position.y + local jump_to_line = math.floor((dy / minimap_height) * line_count) + 1 + + local _, cy, _, cy2 = self:get_content_bounds() + local lh = self:get_line_height() + local visible_lines_count = math.max(1, (cy2 - cy) / lh) + local visible_lines_start = math.max(1, math.floor(cy / lh)) + + -- calc if user hit the currently visible area + local hit_visible_area = true + if is_too_large then + + local visible_height = visible_lines_count * line_spacing + local scroll_pos = (visible_lines_start-1) / (line_count - visible_lines_count - 1) + scroll_pos = math.min(1.0, scroll_pos) -- 0..1 + local visible_y = self.position.y + scroll_pos * (minimap_height - visible_height) + + local t = (line_count - visible_lines_start) / visible_lines_count + if t <= 1 then + visible_y = visible_y + visible_height * (1.0 - t) + end + + if y < visible_y or y > visible_y + visible_height then + hit_visible_area = false + end + else + + -- If the click is on the currently visible line numbers, + -- ignore it since then they probably want to initiate a drag instead. + if jump_to_line < visible_lines_start or jump_to_line > visible_lines_start + visible_lines_count then + hit_visible_area = false + end + end + + -- if user didn't click on the visible area (ie not dragging), scroll accordingly + if not hit_visible_area then + self:scroll_to_line(jump_to_line, false, config.minimap_instant_scroll) + return + end + + end + + return prev_on_mouse_pressed(self, button, x, y, clicks) +end + +-- Overloaded with pretty much the same logic as original DocView implementation, +-- with the exception of the dragging scrollbar delta. We want it to behave a bit snappier +-- since the "scrollbar" essentially represents the lines visible in the content view. +local prev_on_mouse_moved = DocView.on_mouse_moved +DocView.on_mouse_moved = function(self, x, y, dx, dy) + if not config.minimap_enabled then return prev_on_mouse_moved(self, x, y, dx, dy) end + + if self.dragging_scrollbar then + local line_count = #self.doc.lines + local lh = self:get_line_height() + local delta = lh / line_spacing * dy + + if is_file_too_large(self) then + local _, sy, _, sh = self:get_scrollbar_rect() + delta = (line_count * lh) / sh * dy + end + + self.scroll.to.y = self.scroll.to.y + delta + end + + -- we need to "hide" that the scrollbar is dragging so that View doesnt does its own scrolling logic + local t = self.dragging_scrollbar + self.dragging_scrollbar = false + local r = prev_on_mouse_moved(self, x, y, dx, dy) + self.dragging_scrollbar = t + return r +end + +-- Overloaded since we want the mouse to interact with the full size of the minimap area, +-- not juse the scrollbar. +local prev_get_scrollbar_rect = DocView.get_scrollbar_rect +DocView.get_scrollbar_rect = function (self) + if not config.minimap_enabled then return prev_get_scrollbar_rect(self) end + + return + self.position.x + self.size.x - config.minimap_width * SCALE, + self.position.y, + config.minimap_width * SCALE, + self.size.y +end + +-- Overloaded so we can render the minimap in the "scrollbar area". +local prev_draw_scrollbar = DocView.draw_scrollbar +DocView.draw_scrollbar = function (self) + if not config.minimap_enabled then return prev_draw_scrollbar(self) end + + local x, y, w, h = self:get_scrollbar_rect() + + local highlight = self.hovered_scrollbar or self.dragging_scrollbar + local visual_color = highlight and style.scrollbar2 or style.scrollbar + + local _, cy, _, cy2 = self:get_content_bounds() + local lh = self:get_line_height() + local visible_lines_count = math.max(1, (cy2 - cy) / lh) + local visible_lines_start = math.max(1, math.floor(cy / lh)) + local scroller_height = visible_lines_count * line_spacing + local line_count = #self.doc.lines + + local visible_y = self.position.y + (visible_lines_start-1) * line_spacing + + + -- check if file is too large to fit inside the minimap area + local max_minmap_lines = math.floor(h / line_spacing) + local minimap_start_line = 1 + if is_file_too_large(self) then + + local scroll_pos = (visible_lines_start-1) / (line_count - visible_lines_count - 1) + scroll_pos = math.min(1.0, scroll_pos) -- 0..1, procent of visual area scrolled + + local scroll_pos_pixels = scroll_pos * (h - scroller_height) + visible_y = self.position.y + scroll_pos_pixels + + -- offset visible area if user is scrolling past end + local t = (line_count - visible_lines_start) / visible_lines_count + if t <= 1 then + visible_y = visible_y + scroller_height * (1.0 - t) + end + + minimap_start_line = visible_lines_start - math.floor(scroll_pos_pixels / line_spacing) + minimap_start_line = math.max(1, math.min(minimap_start_line, line_count - max_minmap_lines)) + end + + if config.minimap_draw_background then + renderer.draw_rect(x, y, w, h, style.minimap_background or style.background) + end + -- draw visual rect + renderer.draw_rect(x, visible_y, w, scroller_height, visual_color) + + -- time to draw the actual code, setup some local vars that are used in both highlighted and plain renderind. + local line_y = y + + -- when not using syntax highlighted rendering, just use the normal color but dim it 50%. + local color = style.syntax["normal"] + color = { color[1],color[2],color[3],color[4] * 0.5 } + + -- we try to "batch" characters so that they can be rendered as just one rectangle instead of one for each. + local batch_width = 0 + local batch_start = x + local minimap_cutoff_x = x + config.minimap_width * SCALE + + -- render lines with syntax highlighting + if config.minimap_syntax_highlight then + + -- keep track of the highlight type, since this needs to break batches as well + local batch_syntax_type = nil + + local function flush_batch(type) + if batch_width > 0 then + -- fetch and dim colors + color = style.syntax[batch_syntax_type] + color = { color[1], color[2], color[3], color[4] * 0.5 } + renderer.draw_rect(batch_start, line_y, batch_width, char_height, color) + end + batch_syntax_type = type + batch_start = batch_start + batch_width + batch_width = 0 + end + + -- per line + local endidx = minimap_start_line + max_minmap_lines + endidx = math.min(endidx, line_count) + for idx=minimap_start_line,endidx do + batch_syntax_type = nil + batch_start = x + batch_width = 0 + + -- per token + for _, type, text in self.doc.highlighter:each_token(idx) do + -- flush prev batch + if not batch_syntax_type then batch_syntax_type = type end + if batch_syntax_type ~= type then + flush_batch(type) + end + + -- per character + for char in common.utf8_chars(text) do + if char == " " or char == "\n" then + flush_batch(type) + batch_start = batch_start + char_spacing + elseif batch_start + batch_width > minimap_cutoff_x then + flush_batch(type) + break + else + batch_width = batch_width + char_spacing + end + + end + end + flush_batch(nil) + line_y = line_y + line_spacing + end + + else -- render lines without syntax highlighting + + local function flush_batch() + if batch_width > 0 then + renderer.draw_rect(batch_start, line_y, batch_width, char_height, color) + end + batch_start = batch_start + batch_width + batch_width = 0 + end + + for idx=1,line_count-1 do + batch_start = x + batch_width = 0 + + for char in common.utf8_chars(self.doc.lines[idx]) do + if char == " " or char == "\n" then + flush_batch() + batch_start = batch_start + char_spacing + elseif batch_start + batch_width > minimap_cutoff_x then + flush_batch() + else + batch_width = batch_width + char_spacing + end + end + flush_batch() + line_y = line_y + line_spacing + end + + end + +end + +command.add(nil, { + ["minimap:toggle-visibility"] = function() + config.minimap_enabled = not config.minimap_enabled + end, + ["minimap:toggle-syntax-highlighting"] = function() + config.minimap_syntax_highlight = not config.minimap_syntax_highlight + end, +}) diff --git a/tools/editor/art/lite/data/plugins/motiontrail.lua b/tools/editor/art/lite/data/plugins/motiontrail.lua new file mode 100644 index 0000000..e688e1b --- /dev/null +++ b/tools/editor/art/lite/data/plugins/motiontrail.lua @@ -0,0 +1,46 @@ +local core = require "core" +local config = require "core.config" +local style = require "core.style" +local DocView = require "core.docview" + +config.motiontrail_steps = 50 + + +local function lerp(a, b, t) + return a + (b - a) * t +end + + +local function get_caret_rect(dv) + local line, col = dv.doc:get_selection() + local x, y = dv:get_line_screen_position(line) + x = x + dv:get_col_x_offset(line, col) + return x, y, style.caret_width, dv:get_line_height() +end + + +local last_x, last_y, last_view + +local draw = DocView.draw + +function DocView:draw(...) + draw(self, ...) + if self ~= core.active_view then return end + + local x, y, w, h = get_caret_rect(self) + + if last_view == self and (x ~= last_x or y ~= last_y) then + local lx = x + for i = 0, 1, 1 / config.motiontrail_steps do + local ix = lerp(x, last_x, i) + local iy = lerp(y, last_y, i) + local iw = math.max(w, math.ceil(math.abs(ix - lx))) + renderer.draw_rect(ix, iy, iw, h, style.caret) + lx = ix + end + core.redraw = true + end + + last_view, last_x, last_y = self, x, y +end + diff --git a/tools/editor/art/lite/data/plugins/projectsearch.lua b/tools/editor/art/lite/data/plugins/projectsearch.lua new file mode 100644 index 0000000..8c8dfd9 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/projectsearch.lua @@ -0,0 +1,399 @@ +-- mod-version:3 +local core = require "core" +local common = require "core.common" +local keymap = require "core.keymap" +local command = require "core.command" +local style = require "core.style" +local View = require "core.view" + +---@class plugins.projectsearch.resultsview : core.view +local ResultsView = View:extend() + +ResultsView.context = "session" + +function ResultsView:new(path, text, fn) + ResultsView.super.new(self) + self.scrollable = true + self.brightness = 0 + self:begin_search(path, text, fn) +end + + +function ResultsView:get_name() + return "Search Results" +end + + +local function find_all_matches_in_file(t, filename, fn) + local fp = io.open(filename) + if not fp then return t end + local n = 1 + for line in fp:lines() do + local s = fn(line) + if s then + -- Insert maximum 256 characters. If we insert more, for compiled files, which can have very long lines + -- things tend to get sluggish. If our line is longer than 80 characters, begin to truncate the thing. + local start_index = math.max(s - 80, 1) + table.insert(t, { file = filename, text = (start_index > 1 and "..." or "") .. line:sub(start_index, 256 + start_index), line = n, col = s }) + core.redraw = true + end + if n % 100 == 0 then coroutine.yield(0) end + n = n + 1 + core.redraw = true + end + fp:close() +end + + +function ResultsView:begin_search(path, text, fn) + self.search_args = { path, text, fn } + self.results = {} + self.last_file_idx = 1 + self.query = text + self.searching = true + self.selected_idx = 0 + + core.add_thread(function() + local i = 1 + for dir_name, file in core.get_project_files() do + if file.type == "file" and (not path or (dir_name .. "/" .. file.filename):find(path, 1, true) == 1) then + local truncated_path = (dir_name == core.project_dir and "" or (dir_name .. PATHSEP)) + find_all_matches_in_file(self.results, truncated_path .. file.filename, fn) + end + self.last_file_idx = i + i = i + 1 + end + self.searching = false + self.brightness = 100 + core.redraw = true + end, self.results) + + self.scroll.to.y = 0 +end + + +function ResultsView:refresh() + self:begin_search(table.unpack(self.search_args)) +end + + +function ResultsView:on_mouse_moved(mx, my, ...) + ResultsView.super.on_mouse_moved(self, mx, my, ...) + self.selected_idx = 0 + for i, item, x,y,w,h in self:each_visible_result() do + if mx >= x and my >= y and mx < x + w and my < y + h then + self.selected_idx = i + break + end + end +end + + +function ResultsView:on_mouse_pressed(...) + local caught = ResultsView.super.on_mouse_pressed(self, ...) + if not caught then + return self:open_selected_result() + end +end + + +function ResultsView:open_selected_result() + local res = self.results[self.selected_idx] + if not res then + return + end + core.try(function() + local dv = core.root_view:open_doc(core.open_doc(res.file)) + core.root_view.root_node:update_layout() + dv.doc:set_selection(res.line, res.col) + dv:scroll_to_line(res.line, false, true) + end) + return true +end + + +function ResultsView:update() + self:move_towards("brightness", 0, 0.1) + ResultsView.super.update(self) +end + + +function ResultsView:get_results_yoffset() + return style.font:get_height() + style.padding.y * 3 +end + + +function ResultsView:get_line_height() + return style.padding.y + style.font:get_height() +end + + +function ResultsView:get_scrollable_size() + return self:get_results_yoffset() + #self.results * self:get_line_height() +end + + +function ResultsView:get_visible_results_range() + local lh = self:get_line_height() + local oy = self:get_results_yoffset() + local min = math.max(1, math.floor((self.scroll.y - oy) / lh)) + return min, min + math.floor(self.size.y / lh) + 1 +end + + +function ResultsView:each_visible_result() + return coroutine.wrap(function() + local lh = self:get_line_height() + local x, y = self:get_content_offset() + local min, max = self:get_visible_results_range() + y = y + self:get_results_yoffset() + lh * (min - 1) + for i = min, max do + local item = self.results[i] + if not item then break end + coroutine.yield(i, item, x, y, self.size.x, lh) + y = y + lh + end + end) +end + + +function ResultsView:scroll_to_make_selected_visible() + local h = self:get_line_height() + local y = self:get_results_yoffset() + h * (self.selected_idx - 1) + self.scroll.to.y = math.min(self.scroll.to.y, y) + self.scroll.to.y = math.max(self.scroll.to.y, y + h - self.size.y) +end + + +function ResultsView:draw() + self:draw_background(style.background) + + -- status + local ox, oy = self:get_content_offset() + local x, y = ox + style.padding.x, oy + style.padding.y + local files_number = core.project_files_number() + local per = common.clamp(files_number and self.last_file_idx / files_number or 1, 0, 1) + local text + if self.searching then + if files_number then + text = string.format("Searching %.f%% (%d of %d files, %d matches) for %q...", + per * 100, self.last_file_idx, files_number, + #self.results, self.query) + else + text = string.format("Searching (%d files, %d matches) for %q...", + self.last_file_idx, #self.results, self.query) + end + else + text = string.format("Found %d matches for %q", + #self.results, self.query) + end + local color = common.lerp(style.text, style.accent, self.brightness / 100) + renderer.draw_text(style.font, text, x, y, color) + + -- horizontal line + local yoffset = self:get_results_yoffset() + local x = ox + style.padding.x + local w = self.size.x - style.padding.x * 2 + local h = style.divider_size + local color = common.lerp(style.dim, style.text, self.brightness / 100) + renderer.draw_rect(x, oy + yoffset - style.padding.y, w, h, color) + if self.searching then + renderer.draw_rect(x, oy + yoffset - style.padding.y, w * per, h, style.text) + end + + -- results + local y1, y2 = self.position.y, self.position.y + self.size.y + for i, item, x,y,w,h in self:each_visible_result() do + local color = style.text + if i == self.selected_idx then + color = style.accent + renderer.draw_rect(x, y, w, h, style.line_highlight) + end + x = x + style.padding.x + local text = string.format("%s at line %d (col %d): ", item.file, item.line, item.col) + x = common.draw_text(style.font, style.dim, text, "left", x, y, w, h) + x = common.draw_text(style.code_font, color, item.text, "left", x, y, w, h) + end + + self:draw_scrollbar() +end + + +---@param path string +---@param text string +---@param fn fun(line_text:string):... +---@return plugins.projectsearch.resultsview? +local function begin_search(path, text, fn) + if text == "" then + core.error("Expected non-empty string") + return + end + local rv = ResultsView(path, text, fn) + core.root_view:get_active_node_default():add_view(rv) + return rv +end + + +local function get_selected_text() + local view = core.active_view + local doc = (view and view.doc) and view.doc or nil + if doc then + return doc:get_text(table.unpack({ doc:get_selection() })) + end +end + + +local function normalize_path(path) + if not path then return nil end + path = common.normalize_path(path) + for i, project_dir in ipairs(core.project_directories) do + if common.path_belongs_to(path, project_dir.name) then + return project_dir.item.filename .. PATHSEP .. common.relative_path(project_dir.name, path) + end + end + return path +end + +---@class plugins.projectsearch +local projectsearch = {} + +---@type plugins.projectsearch.resultsview +projectsearch.ResultsView = ResultsView + +---@param text string +---@param path string +---@param insensitive? boolean +---@return plugins.projectsearch.resultsview? +function projectsearch.search_plain(text, path, insensitive) + if insensitive then text = text:lower() end + return begin_search(path, text, function(line_text) + if insensitive then + return line_text:lower():find(text, nil, true) + else + return line_text:find(text, nil, true) + end + end) +end + +---@param text string +---@param path string +---@param insensitive? boolean +---@return plugins.projectsearch.resultsview? +function projectsearch.search_regex(text, path, insensitive) + local re, errmsg + if insensitive then + re, errmsg = regex.compile(text, "i") + else + re, errmsg = regex.compile(text) + end + if not re then core.log("%s", errmsg) return end + return begin_search(path, text, function(line_text) + return regex.cmatch(re, line_text) + end) +end + +---@param text string +---@param path string +---@param insensitive? boolean +---@return plugins.projectsearch.resultsview? +function projectsearch.search_fuzzy(text, path, insensitive) + if insensitive then text = text:lower() end + return begin_search(path, text, function(line_text) + if insensitive then + return common.fuzzy_match(line_text:lower(), text) and 1 + else + return common.fuzzy_match(line_text, text) and 1 + end + end) +end + + +command.add(nil, { + ["project-search:find"] = function(path) + core.command_view:enter("Find Text In " .. (normalize_path(path) or "Project"), { + text = get_selected_text(), + select_text = true, + submit = function(text) + projectsearch.search_plain(text, path, true) + end + }) + end, + + ["project-search:find-regex"] = function(path) + core.command_view:enter("Find Regex In " .. (normalize_path(path) or "Project"), { + submit = function(text) + projectsearch.search_regex(text, path, true) + end + }) + end, + + ["project-search:fuzzy-find"] = function(path) + core.command_view:enter("Fuzzy Find Text In " .. (normalize_path(path) or "Project"), { + text = get_selected_text(), + select_text = true, + submit = function(text) + projectsearch.search_fuzzy(text, path, true) + end + }) + end, +}) + + +command.add(ResultsView, { + ["project-search:select-previous"] = function() + local view = core.active_view + view.selected_idx = math.max(view.selected_idx - 1, 1) + view:scroll_to_make_selected_visible() + end, + + ["project-search:select-next"] = function() + local view = core.active_view + view.selected_idx = math.min(view.selected_idx + 1, #view.results) + view:scroll_to_make_selected_visible() + end, + + ["project-search:open-selected"] = function() + core.active_view:open_selected_result() + end, + + ["project-search:refresh"] = function() + core.active_view:refresh() + end, + + ["project-search:move-to-previous-page"] = function() + local view = core.active_view + view.scroll.to.y = view.scroll.to.y - view.size.y + end, + + ["project-search:move-to-next-page"] = function() + local view = core.active_view + view.scroll.to.y = view.scroll.to.y + view.size.y + end, + + ["project-search:move-to-start-of-doc"] = function() + local view = core.active_view + view.scroll.to.y = 0 + end, + + ["project-search:move-to-end-of-doc"] = function() + local view = core.active_view + view.scroll.to.y = view:get_scrollable_size() + end +}) + +keymap.add { + ["f5"] = "project-search:refresh", + ["ctrl+shift+f"] = "project-search:find", + ["up"] = "project-search:select-previous", + ["down"] = "project-search:select-next", + ["return"] = "project-search:open-selected", + ["pageup"] = "project-search:move-to-previous-page", + ["pagedown"] = "project-search:move-to-next-page", + ["ctrl+home"] = "project-search:move-to-start-of-doc", + ["ctrl+end"] = "project-search:move-to-end-of-doc", + ["home"] = "project-search:move-to-start-of-doc", + ["end"] = "project-search:move-to-end-of-doc" +} + + +return projectsearch diff --git a/tools/editor/art/lite/data/plugins/quote.lua b/tools/editor/art/lite/data/plugins/quote.lua new file mode 100644 index 0000000..60f0cf1 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/quote.lua @@ -0,0 +1,31 @@ +-- mod-version:3 +local core = require "core" +local command = require "core.command" +local keymap = require "core.keymap" + + +local escapes = { + ["\\"] = "\\\\", + ["\""] = "\\\"", + ["\n"] = "\\n", + ["\r"] = "\\r", + ["\t"] = "\\t", + ["\b"] = "\\b", +} + +local function replace(chr) + return escapes[chr] or string.format("\\x%02x", chr:byte()) +end + + +command.add("core.docview", { + ["quote:quote"] = function(dv) + dv.doc:replace(function(text) + return '"' .. text:gsub("[\0-\31\\\"]", replace) .. '"' + end) + end, +}) + +keymap.add { + ["ctrl+'"] = "quote:quote", +} diff --git a/tools/editor/art/lite/data/plugins/reflow.lua b/tools/editor/art/lite/data/plugins/reflow.lua new file mode 100644 index 0000000..95090a6 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/reflow.lua @@ -0,0 +1,63 @@ +local core = require "core" +local config = require "core.config" +local command = require "core.command" +local keymap = require "core.keymap" + + +local function wordwrap_text(text, limit) + local t = {} + local n = 0 + + for word in text:gmatch("%S+") do + if n + #word > limit then + table.insert(t, "\n") + n = 0 + elseif #t > 0 then + table.insert(t, " ") + end + table.insert(t, word) + n = n + #word + 1 + end + + return table.concat(t) +end + + +command.add("core.docview", { + ["reflow:reflow"] = function() + local doc = core.active_view.doc + doc:replace(function(text) + local prefix_set = "[^%w\n%[%](){}`'\"]*" + + -- get line prefix and trailing whitespace + local prefix1 = text:match("^\n*" .. prefix_set) + local prefix2 = text:match("\n(" .. prefix_set .. ")", #prefix1+1) + local trailing = text:match("%s*$") + if not prefix2 or prefix2 == "" then + prefix2 = prefix1 + end + + -- strip all line prefixes and trailing whitespace + text = text:sub(#prefix1+1, -#trailing - 1):gsub("\n" .. prefix_set, "\n") + + -- split into blocks, wordwrap and join + local line_limit = config.line_limit - #prefix1 + local blocks = {} + text = text:gsub("\n\n", "\0") + for block in text:gmatch("%Z+") do + table.insert(blocks, wordwrap_text(block, line_limit)) + end + text = table.concat(blocks, "\n\n") + + -- add prefix to start of lines + text = prefix1 .. text:gsub("\n", "\n" .. prefix2) .. trailing + + return text + end) + end, +}) + + +keymap.add { + ["ctrl+shift+q"] = "reflow:reflow" +} diff --git a/tools/editor/art/lite/data/plugins/scale.lua b/tools/editor/art/lite/data/plugins/scale.lua new file mode 100644 index 0000000..1761999 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/scale.lua @@ -0,0 +1,110 @@ +local core = require "core" +local common = require "core.common" +local command = require "core.command" +local config = require "core.config" +local keymap = require "core.keymap" +local style = require "core.style" +local RootView = require "core.rootview" +local CommandView = require "core.commandview" + +config.scale_mode = "code" +config.scale_use_mousewheel = true + +local font_cache = setmetatable({}, { __mode = "k" }) + +-- the following should be kept in sync with core.style's default font settings +font_cache[style.font] = { DATADIR .. "/data/fonts/font.ttf", 14 * SCALE } +font_cache[style.big_font] = { DATADIR .. "/data/fonts/font.ttf", 34 * SCALE } +font_cache[style.icon_font] = { DATADIR .. "/data/fonts/icons.ttf", 14 * SCALE } +font_cache[style.code_font] = { DATADIR .. "/data/fonts/monospace.ttf", 13.5 * SCALE } + + +local load_font = renderer.font.load +function renderer.font.load(...) + local res = load_font(...) + font_cache[res] = { ... } + return res +end + + +local function scale_font(font, s) + local fc = font_cache[font] + return renderer.font.load(fc[1], fc[2] * s) +end + + +local current_scale = SCALE +local default = current_scale + + +local function get_scale() return current_scale end + + +local function set_scale(scale) + scale = common.clamp(scale, 0.2, 6) + + -- save scroll positions + local scrolls = {} + for _, view in ipairs(core.root_view.root_node:get_children()) do + local n = view:get_scrollable_size() + if n ~= math.huge and not view:is(CommandView) then + scrolls[view] = view.scroll.y / (n - view.size.y) + end + end + + local s = scale / current_scale + current_scale = scale + + if config.scale_mode == "ui" then + SCALE = current_scale + + style.padding.x = style.padding.x * s + style.padding.y = style.padding.y * s + style.divider_size = style.divider_size * s + style.scrollbar_size = style.scrollbar_size * s + style.caret_width = style.caret_width * s + style.tab_width = style.tab_width * s + + style.big_font = scale_font(style.big_font, s) + style.icon_font = scale_font(style.icon_font, s) + style.font = scale_font(style.font, s) + end + + style.code_font = scale_font(style.code_font, s) + + -- restore scroll positions + for view, n in pairs(scrolls) do + view.scroll.y = n * (view:get_scrollable_size() - view.size.y) + view.scroll.to.y = view.scroll.y + end + + core.redraw = true +end + + +local on_mouse_wheel = RootView.on_mouse_wheel + +function RootView:on_mouse_wheel(d, ...) + if keymap.modkeys["ctrl"] and config.scale_use_mousewheel then + if d < 0 then command.perform "scale:decrease" end + if d > 0 then command.perform "scale:increase" end + else + return on_mouse_wheel(self, d, ...) + end +end + + +command.add(nil, { + ["scale:reset" ] = function() set_scale(default) end, + ["scale:decrease"] = function() set_scale(current_scale * 0.9) end, + ["scale:increase"] = function() set_scale(current_scale * 1.1) end, +}) + +keymap.add { + ["ctrl+0"] = "scale:reset", + ["ctrl+-"] = "scale:decrease", + ["ctrl++"] = "scale:increase", +} + +return { get_scale = get_scale, set_scale = set_scale } + diff --git a/tools/editor/art/lite/data/plugins/selectionhighlight.lua b/tools/editor/art/lite/data/plugins/selectionhighlight.lua new file mode 100644 index 0000000..93dfe17 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/selectionhighlight.lua @@ -0,0 +1,37 @@ +local style = require "core.style" +local DocView = require "core.docview" + +-- originally written by luveti + +local function draw_box(x, y, w, h, color) + local r = renderer.draw_rect + local s = math.ceil(SCALE) + r(x, y, w, s, color) + r(x, y + h - s, w, s, color) + r(x, y + s, s, h - s * 2, color) + r(x + w - s, y + s, s, h - s * 2, color) +end + + +local draw_line_body = DocView.draw_line_body + +function DocView:draw_line_body(idx, x, y) + local line1, col1, line2, col2 = self.doc:get_selection(true) + if line1 == line2 and col1 ~= col2 then + local lh = self:get_line_height() + local selected_text = self.doc.lines[line1]:sub(col1, col2 - 1) + local current_line_text = self.doc.lines[idx] + local last_col = 1 + while true do + local start_col, end_col = current_line_text:find(selected_text, last_col, true) + if start_col == nil then break end + local x1 = x + self:get_col_x_offset(idx, start_col) + local x2 = x + self:get_col_x_offset(idx, end_col + 1) + local color = style.selectionhighlight or style.syntax.comment + draw_box(x1, y, x2 - x1, lh, color) + last_col = end_col + 1 + end + end + draw_line_body(self, idx, x, y) +end + diff --git a/tools/editor/art/lite/data/plugins/tabularize.lua b/tools/editor/art/lite/data/plugins/tabularize.lua new file mode 100644 index 0000000..5185fbf --- /dev/null +++ b/tools/editor/art/lite/data/plugins/tabularize.lua @@ -0,0 +1,63 @@ +-- mod-version:3 +local core = require "core" +local command = require "core.command" +local translate = require "core.doc.translate" + + +local function gmatch_to_array(text, ptn) + local res = {} + for x in text:gmatch(ptn) do + table.insert(res, x) + end + return res +end + + +local function tabularize_lines(lines, delim) + local rows = {} + local cols = {} + + -- split lines at delimiters and get maximum width of columns + local ptn = "[^" .. delim:sub(1,1):gsub("%W", "%%%1") .. "]+" + for i, line in ipairs(lines) do + rows[i] = gmatch_to_array(line, ptn) + for j, col in ipairs(rows[i]) do + cols[j] = math.max(#col, cols[j] or 0) + end + end + + -- pad columns with space + for _, row in ipairs(rows) do + for i = 1, #row - 1 do + row[i] = row[i] .. string.rep(" ", cols[i] - #row[i]) + end + end + + -- write columns back to lines array + for i, line in ipairs(lines) do + lines[i] = table.concat(rows[i], delim) + end +end + + +command.add("core.docview", { + ["tabularize:tabularize"] = function(dv) + core.command_view:enter("Tabularize On Delimiter", { + submit = function(delim) + if delim == "" then delim = " " end + + local doc = dv.doc + local line1, col1, line2, col2, swap = doc:get_selection(true) + line1, col1 = doc:position_offset(line1, col1, translate.start_of_line) + line2, col2 = doc:position_offset(line2, col2, translate.end_of_line) + doc:set_selection(line1, col1, line2, col2, swap) + + doc:replace(function(text) + local lines = gmatch_to_array(text, "[^\n]*\n?") + tabularize_lines(lines, delim) + return table.concat(lines) + end) + end + }) + end, +}) diff --git a/tools/editor/art/lite/data/plugins/treeview.lua b/tools/editor/art/lite/data/plugins/treeview.lua new file mode 100644 index 0000000..701d5d3 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/treeview.lua @@ -0,0 +1,197 @@ +local core = require "core" +local common = require "core.common" +local command = require "core.command" +local config = require "core.config" +local keymap = require "core.keymap" +local style = require "core.style" +local View = require "core.view" + +config.treeview_size = 200 * SCALE + +local function get_depth(filename) + local n = 0 + for sep in filename:gmatch("[\\/]") do + n = n + 1 + end + return n +end + + +local TreeView = View:extend() + +function TreeView:new() + TreeView.super.new(self) + self.scrollable = true + self.visible = true + self.init_size = true + self.cache = {} +end + + +function TreeView:get_cached(item) + local t = self.cache[item.filename] + if not t then + t = {} + t.filename = item.filename + t.abs_filename = system.absolute_path(item.filename) + t.name = t.filename:match("[^\\/]+$") + t.depth = get_depth(t.filename) + t.type = item.type + self.cache[t.filename] = t + end + return t +end + + +function TreeView:get_name() + return "Project" +end + + +function TreeView:get_item_height() + return style.font:get_height() + style.padding.y +end + + +function TreeView:check_cache() + -- invalidate cache's skip values if project_files has changed + if core.project_files ~= self.last_project_files then + for _, v in pairs(self.cache) do + v.skip = nil + end + self.last_project_files = core.project_files + end +end + + +function TreeView:each_item() + return coroutine.wrap(function() + self:check_cache() + local ox, oy = self:get_content_offset() + local y = oy + style.padding.y + local w = self.size.x + local h = self:get_item_height() + + local i = 1 + while i <= #core.project_files do + local item = core.project_files[i] + local cached = self:get_cached(item) + + coroutine.yield(cached, ox, y, w, h) + y = y + h + i = i + 1 + + if not cached.expanded then + if cached.skip then + i = cached.skip + else + local depth = cached.depth + while i <= #core.project_files do + local filename = core.project_files[i].filename + if get_depth(filename) <= depth then break end + i = i + 1 + end + cached.skip = i + end + end + end + end) +end + + +function TreeView:on_mouse_moved(px, py) + self.hovered_item = nil + for item, x,y,w,h in self:each_item() do + if px > x and py > y and px <= x + w and py <= y + h then + self.hovered_item = item + break + end + end +end + + +function TreeView:on_mouse_pressed(button, x, y) + if not self.hovered_item then + return + elseif self.hovered_item.type == "dir" then + self.hovered_item.expanded = not self.hovered_item.expanded + else + core.try(function() + core.root_view:open_doc(core.open_doc(self.hovered_item.filename)) + end) + end +end + + +function TreeView:update() + -- update width + local dest = self.visible and config.treeview_size or 0 + if self.init_size then + self.size.x = dest + self.init_size = false + else + self:move_towards(self.size, "x", dest) + end + + TreeView.super.update(self) +end + + +function TreeView:draw() + self:draw_background(style.background2) + + local icon_width = style.icon_font:get_width("D") + local spacing = style.font:get_width(" ") * 2 + + local doc = core.active_view.doc + local active_filename = doc and system.absolute_path(doc.filename or "") + + for item, x,y,w,h in self:each_item() do + local color = style.text + + -- highlight active_view doc + if item.abs_filename == active_filename then + color = style.accent + end + + -- hovered item background + if item == self.hovered_item then + renderer.draw_rect(x, y, w, h, style.line_highlight) + color = style.accent + end + + -- icons + x = x + item.depth * style.padding.x + style.padding.x + if item.type == "dir" then + local icon1 = item.expanded and "-" or "+" + local icon2 = item.expanded and "D" or "d" + common.draw_text(style.icon_font, color, icon1, nil, x, y, 0, h) + x = x + style.padding.x + common.draw_text(style.icon_font, color, icon2, nil, x, y, 0, h) + x = x + icon_width + else + x = x + style.padding.x + common.draw_text(style.icon_font, color, "f", nil, x, y, 0, h) + x = x + icon_width + end + + -- text + x = x + spacing + x = common.draw_text(style.font, color, item.name, nil, x, y, 0, h) + end +end + + +-- init +local view = TreeView() +local node = core.root_view:get_active_node() +node:split("left", view, true) --< @r-lyeh true > false allows resizable treeview + +-- register commands and keymap +command.add(nil, { + ["treeview:toggle"] = function() + view.visible = not view.visible + end, +}) + +keymap.add { ["ctrl+t"] = "treeview:toggle" } --< @r-lyeh ctrl+// > ctrl+t diff --git a/tools/editor/art/lite/data/plugins/trimwhitespace.lua b/tools/editor/art/lite/data/plugins/trimwhitespace.lua new file mode 100644 index 0000000..d4d25c8 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/trimwhitespace.lua @@ -0,0 +1,36 @@ +local core = require "core" +local command = require "core.command" +local Doc = require "core.doc" + + +local function trim_trailing_whitespace(doc) + local cline, ccol = doc:get_selection() + for i = 1, #doc.lines do + local old_text = doc:get_text(i, 1, i, math.huge) + local new_text = old_text:gsub("%s*$", "") + + -- don't remove whitespace which would cause the caret to reposition + if cline == i and ccol > #new_text then + new_text = old_text:sub(1, ccol - 1) + end + + if old_text ~= new_text then + doc:insert(i, 1, new_text) + doc:remove(i, #new_text + 1, i, math.huge) + end + end +end + + +command.add("core.docview", { + ["trim-whitespace:trim-trailing-whitespace"] = function() + trim_trailing_whitespace(core.active_view.doc) + end, +}) + + +local save = Doc.save +Doc.save = function(self, ...) + trim_trailing_whitespace(self) + save(self, ...) +end diff --git a/tools/editor/art/lite/data/plugins/workspace.lua b/tools/editor/art/lite/data/plugins/workspace.lua new file mode 100644 index 0000000..3b3bd04 --- /dev/null +++ b/tools/editor/art/lite/data/plugins/workspace.lua @@ -0,0 +1,246 @@ +-- mod-version:3 +local core = require "core" +local common = require "core.common" +local DocView = require "core.docview" +local LogView = require "core.logview" + + +local function workspace_files_for(project_dir) + local basename = common.basename(project_dir) + local workspace_dir = USERDIR .. PATHSEP .. "ws" + local info_wsdir = system.get_file_info(workspace_dir) + if not info_wsdir then + local ok, err = system.mkdir(workspace_dir) + if not ok then + error("cannot create workspace directory: \"" .. err .. "\"") + end + end + return coroutine.wrap(function() + local files = system.list_dir(workspace_dir) or {} + local n = #basename + for _, file in ipairs(files) do + if file:sub(1, n) == basename then + local id = tonumber(file:sub(n + 1):match("^-(%d+)$")) + if id then + coroutine.yield(workspace_dir .. PATHSEP .. file, id) + end + end + end + end) +end + + +local function consume_workspace_file(project_dir) + for filename, id in workspace_files_for(project_dir) do + local load_f = loadfile(filename) + local workspace = load_f and load_f() + if workspace and workspace.path == project_dir then + os.remove(filename) + return workspace + end + end +end + + +local function get_workspace_filename(project_dir) + local id_list = {} + for filename, id in workspace_files_for(project_dir) do + id_list[id] = true + end + local id = 1 + while id_list[id] do + id = id + 1 + end + local basename = common.basename(project_dir) + return USERDIR .. PATHSEP .. "ws" .. PATHSEP .. basename .. "-" .. tostring(id) +end + + +local function has_no_locked_children(node) + if node.locked then return false end + if node.type == "leaf" then return true end + return has_no_locked_children(node.a) and has_no_locked_children(node.b) +end + + +local function get_unlocked_root(node) + if node.type == "leaf" then + return not node.locked and node + end + if has_no_locked_children(node) then + return node + end + return get_unlocked_root(node.a) or get_unlocked_root(node.b) +end + + +local function save_view(view) + local mt = getmetatable(view) + if mt == DocView then + return { + type = "doc", + active = (core.active_view == view), + filename = view.doc.filename, + selection = { view.doc:get_selection() }, + scroll = { x = view.scroll.to.x, y = view.scroll.to.y }, + crlf = view.doc.crlf, + text = view.doc.new_file and view.doc:get_text(1, 1, math.huge, math.huge) + } + end + if mt == LogView then return end + for name, mod in pairs(package.loaded) do + if mod == mt then + return { + type = "view", + active = (core.active_view == view), + module = name, + scroll = { x = view.scroll.to.x, y = view.scroll.to.y, to = { x = view.scroll.to.x, y = view.scroll.to.y } }, + } + end + end +end + + +local function load_view(t) + if t.type == "doc" then + local dv + if not t.filename then + -- document not associated to a file + dv = DocView(core.open_doc()) + else + -- we have a filename, try to read the file + local ok, doc = pcall(core.open_doc, t.filename) + if ok then + dv = DocView(doc) + end + end + if dv and dv.doc then + if dv.doc.new_file and t.text then + dv.doc:insert(1, 1, t.text) + dv.doc.crlf = t.crlf + end + dv.doc:set_selection(table.unpack(t.selection)) + dv.last_line1, dv.last_col1, dv.last_line2, dv.last_col2 = dv.doc:get_selection() + dv.scroll.x, dv.scroll.to.x = t.scroll.x, t.scroll.x + dv.scroll.y, dv.scroll.to.y = t.scroll.y, t.scroll.y + end + return dv + end + return require(t.module)() +end + + +local function save_node(node) + local res = {} + res.type = node.type + if node.type == "leaf" then + res.views = {} + for _, view in ipairs(node.views) do + local t = save_view(view) + if t then + table.insert(res.views, t) + if node.active_view == view then + res.active_view = #res.views + end + end + end + else + res.divider = node.divider + res.a = save_node(node.a) + res.b = save_node(node.b) + end + return res +end + + +local function load_node(node, t) + if t.type == "leaf" then + local res + local active_view + for i, v in ipairs(t.views) do + local view = load_view(v) + if view then + if v.active then res = view end + node:add_view(view) + if t.active_view == i then + active_view = view + end + if not view:is(DocView) then + view.scroll = v.scroll + end + end + end + if active_view then + node:set_active_view(active_view) + end + return res + else + node:split(t.type == "hsplit" and "right" or "down") + node.divider = t.divider + local res1 = load_node(node.a, t.a) + local res2 = load_node(node.b, t.b) + return res1 or res2 + end +end + + +local function save_directories() + local project_dir = core.project_dir + local dir_list = {} + for i = 2, #core.project_directories do + dir_list[#dir_list + 1] = common.relative_path(project_dir, core.project_directories[i].name) + end + return dir_list +end + + +local function save_workspace() + local root = get_unlocked_root(core.root_view.root_node) + local workspace_filename = get_workspace_filename(core.project_dir) + local fp = io.open(workspace_filename, "w") + if fp then + local node_text = common.serialize(save_node(root)) + local dir_text = common.serialize(save_directories()) + fp:write(string.format("return { path = %q, documents = %s, directories = %s }\n", core.project_dir, node_text, dir_text)) + fp:close() + end +end + + +local function load_workspace() + local workspace = consume_workspace_file(core.project_dir) + if workspace then + local root = get_unlocked_root(core.root_view.root_node) + local active_view = load_node(root, workspace.documents) + if active_view then + core.set_active_view(active_view) + end + for i, dir_name in ipairs(workspace.directories) do + core.add_project_directory(system.absolute_path(dir_name)) + end + end +end + + +local run = core.run + +function core.run(...) + if #core.docs == 0 then + core.try(load_workspace) + + local on_quit_project = core.on_quit_project + function core.on_quit_project() + core.try(save_workspace) + on_quit_project() + end + + local on_enter_project = core.on_enter_project + function core.on_enter_project(new_dir) + on_enter_project(new_dir) + core.try(load_workspace) + end + end + + core.run = run + return core.run(...) +end diff --git a/tools/editor/art/lite/data/themes/abyss.lua b/tools/editor/art/lite/data/themes/abyss.lua new file mode 100644 index 0000000..b4c147b --- /dev/null +++ b/tools/editor/art/lite/data/themes/abyss.lua @@ -0,0 +1,29 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#02103d" } +style.background2 = { common.color "#02103d" } +style.background3 = { common.color "#02103d" } +style.text = { common.color "#0f6773" } +style.caret = { common.color "#6a8ca8" } +style.accent = { common.color "#6a8ca8" } +style.dim = { common.color "#303030" } +style.divider = { common.color "#151515" } +style.selection = { common.color "#242424" } +style.line_number = { common.color "#252525" } +style.line_number2 = { common.color "#444444" } +style.line_highlight = { common.color "#101010" } +style.scrollbar = { common.color "#252525" } +style.scrollbar2 = { common.color "#444444" } + +style.syntax = {} +style.syntax["normal"] = { common.color "#a0a0a0" } +style.syntax["symbol"] = { common.color "#a0a0a0" } +style.syntax["comment"] = { common.color "#404040" } +style.syntax["keyword"] = { common.color "#dfdfdf" } +style.syntax["keyword2"] = { common.color "#dfdfdf" } +style.syntax["number"] = { common.color "#dfdfdf" } +style.syntax["literal"] = { common.color "#dfdfdf" } +style.syntax["string"] = { common.color "#132a52" } +style.syntax["operator"] = { common.color "#01A870" } +style.syntax["function"] = { common.color "#01A870" } diff --git a/tools/editor/art/lite/data/themes/cold_lime.lua b/tools/editor/art/lite/data/themes/cold_lime.lua new file mode 100644 index 0000000..fd53a30 --- /dev/null +++ b/tools/editor/art/lite/data/themes/cold_lime.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#073642" } +style.background2 = { common.color "#073642" } +style.background3 = { common.color "#073642" } +style.text = { common.color "#00d1d1" } +style.caret = { common.color "#f053f3" } +style.accent = { common.color "#f053f3" } +style.dim = { common.color "#586e75" } +style.divider = { common.color "#6c71c4" } +style.selection = { common.color "#415256" } +style.line_number = { common.color "#586e75" } +style.line_number2 = { common.color "#f053f3" } +style.line_highlight = { common.color "#415256" } +style.scrollbar = { common.color "#6c71c4" } +style.scrollbar2 = { common.color "#6c71c4" } + +style.syntax["normal"] = { common.color "#00d1d1" } +style.syntax["symbol"] = { common.color "#00ff7f" } +style.syntax["comment"] = { common.color "#6c71c4" } +style.syntax["keyword"] = { common.color "#6c71c4" } +style.syntax["keyword2"] = { common.color "#6c71c4" } +style.syntax["number"] = { common.color "#00ff7f" } +style.syntax["literal"] = { common.color "#1586d2" } +style.syntax["string"] = { common.color "#f7f97d" } +style.syntax["operator"] = { common.color "#00ff7f" } +style.syntax["function"] = { common.color "#55ffff" } diff --git a/tools/editor/art/lite/data/themes/dracula.lua b/tools/editor/art/lite/data/themes/dracula.lua new file mode 100644 index 0000000..68ab41c --- /dev/null +++ b/tools/editor/art/lite/data/themes/dracula.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#282a36" } +style.background2 = { common.color "#21222b" } +style.background3 = { common.color "#21222b" } +style.text = { common.color "#7b81a6" } +style.caret = { common.color "#f8f8f0" } +style.accent = { common.color "#8be9fd" } +style.dim = { common.color "#4f5873" } +style.divider = { common.color "#1f2029" } +style.selection = { common.color "#44475a" } +style.line_number = { common.color "#53576e" } +style.line_number2 = { common.color "#f8f8f0" } +style.line_highlight = { common.color "#313442" } +style.scrollbar = { common.color "#44475a" } +style.scrollbar2 = { common.color "#ff79c6" } + +style.syntax["normal"] = { common.color "#f8f8f2" } +style.syntax["symbol"] = { common.color "#f8f8f2" } +style.syntax["comment"] = { common.color "#6272a4" } +style.syntax["keyword"] = { common.color "#ff79c6" } +style.syntax["keyword2"] = { common.color "#ff79c6" } +style.syntax["number"] = { common.color "#bd93f9" } +style.syntax["literal"] = { common.color "#f1fa8c" } +style.syntax["string"] = { common.color "#f1fa8c" } +style.syntax["operator"] = { common.color "#ff79c6" } +style.syntax["function"] = { common.color "#50fa7b" } diff --git a/tools/editor/art/lite/data/themes/duorand.lua b/tools/editor/art/lite/data/themes/duorand.lua new file mode 100644 index 0000000..dabde42 --- /dev/null +++ b/tools/editor/art/lite/data/themes/duorand.lua @@ -0,0 +1,37 @@ +local style = require "core.style" +local common = require "core.common" + +math.randomseed(os.time()) + +local color = { + math.random(90, 255), + math.random(90, 255), + math.random(90, 255) +} + +style.background = { common.color "#151515" } +style.background2 = { common.color "#151515" } +style.background3 = { common.color "#151515" } +style.text = { common.color "#707070" } +style.caret = { common.color "#dfdfdf" } +style.accent = { common.color "#d0d0d0" } +style.dim = { common.color "#303030" } +style.divider = { common.color "#151515" } +style.selection = { common.color "#303030" } +style.line_number = { common.color "#252525" } +style.line_number2 = { common.color "#444444" } +style.line_highlight = { common.color "#101010" } +style.scrollbar = { common.color "#252525" } +style.scrollbar2 = { common.color "#444444" } + +style.syntax = {} +style.syntax["normal"] = { common.color "#a0a0a0" } +style.syntax["symbol"] = { common.color "#a0a0a0" } +style.syntax["comment"] = { common.color "#404040" } +style.syntax["keyword"] = { common.color "#dfdfdf" } +style.syntax["keyword2"] = { common.color "#dfdfdf" } +style.syntax["number"] = { common.color "#dfdfdf" } +style.syntax["literal"] = { common.color "#dfdfdf" } +style.syntax["string"] = { common.color "#dfdfdf" } +style.syntax["operator"] = color +style.syntax["function"] = color diff --git a/tools/editor/art/lite/data/themes/duotone.lua b/tools/editor/art/lite/data/themes/duotone.lua new file mode 100644 index 0000000..d1f0f36 --- /dev/null +++ b/tools/editor/art/lite/data/themes/duotone.lua @@ -0,0 +1,29 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#151515" } +style.background2 = { common.color "#151515" } +style.background3 = { common.color "#151515" } +style.text = { common.color "#707070" } +style.caret = { common.color "#dfdfdf" } +style.accent = { common.color "#d0d0d0" } +style.dim = { common.color "#303030" } +style.divider = { common.color "#151515" } +style.selection = { common.color "#242424" } +style.line_number = { common.color "#252525" } +style.line_number2 = { common.color "#444444" } +style.line_highlight = { common.color "#101010" } +style.scrollbar = { common.color "#252525" } +style.scrollbar2 = { common.color "#444444" } + +style.syntax = {} +style.syntax["normal"] = { common.color "#a0a0a0" } +style.syntax["symbol"] = { common.color "#a0a0a0" } +style.syntax["comment"] = { common.color "#404040" } +style.syntax["keyword"] = { common.color "#dfdfdf" } +style.syntax["keyword2"] = { common.color "#dfdfdf" } +style.syntax["number"] = { common.color "#dfdfdf" } +style.syntax["literal"] = { common.color "#dfdfdf" } +style.syntax["string"] = { common.color "#dfdfdf" } +style.syntax["operator"] = { common.color "#01A870" } +style.syntax["function"] = { common.color "#01A870" } diff --git a/tools/editor/art/lite/data/themes/fall.lua b/tools/editor/art/lite/data/themes/fall.lua new file mode 100644 index 0000000..0cab762 --- /dev/null +++ b/tools/editor/art/lite/data/themes/fall.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#343233" } +style.background2 = { common.color "#2c2a2b" } +style.background3 = { common.color "#2c2a2b" } +style.text = { common.color "#c4b398" } +style.caret = { common.color "#61efce" } +style.accent = { common.color "#ffd152" } +style.dim = { common.color "#615d5f" } +style.divider = { common.color "#242223" } +style.selection = { common.color "#454244" } +style.line_number = { common.color "#454244" } +style.line_number2 = { common.color "#615d5f" } +style.line_highlight = { common.color "#383637" } +style.scrollbar = { common.color "#454344" } +style.scrollbar2 = { common.color "#524F50" } + +style.syntax["normal"] = { common.color "#efdab9" } +style.syntax["symbol"] = { common.color "#efdab9" } +style.syntax["comment"] = { common.color "#615d5f" } +style.syntax["keyword"] = { common.color "#d36e2d" } +style.syntax["keyword2"] = { common.color "#ef6179" } +style.syntax["number"] = { common.color "#ffd152" } +style.syntax["literal"] = { common.color "#ffd152" } +style.syntax["string"] = { common.color "#ffd152" } +style.syntax["operator"] = { common.color "#efdab9" } +style.syntax["function"] = { common.color "#61efce" } diff --git a/tools/editor/art/lite/data/themes/fwk.lua b/tools/editor/art/lite/data/themes/fwk.lua new file mode 100644 index 0000000..e6d5eef --- /dev/null +++ b/tools/editor/art/lite/data/themes/fwk.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#242424" } -- main background +style.background2 = { common.color "#202020" } -- sidebar backgrounds +style.background3 = { common.color "#202020" } -- bottombar background prompts +style.text = { common.color "#9ea191" } +style.caret = { common.color "#F8F8F0" } +style.accent = { common.color "#F8F8F2" } -- selected file (sidebar) +style.dim = { common.color "#5e6052" } -- landing text + sidebar +style.divider = { common.color "#1b1c17" } +style.selection = { common.color "#49483E" } +style.line_number = { common.color "#75715E" } +style.line_number2 = { common.color "#d2d0c6" } +style.line_highlight = { common.color "#36372f" } +style.scrollbar = { common.color "#49483E" } +style.scrollbar2 = { common.color "#636254" } + +style.syntax["normal"] = { common.color "#F8F8F2" } +style.syntax["symbol"] = { common.color "#F8F8F2" } +style.syntax["comment"] = { common.color "#75715E" } +style.syntax["keyword"] = { common.color "#F92672" } +style.syntax["keyword2"] = { common.color "#66DAEF" } +style.syntax["number"] = { common.color "#AE81FF" } +style.syntax["literal"] = { common.color "#AE81FF" } +style.syntax["string"] = { common.color "#E6DB74" } +style.syntax["operator"] = { common.color "#F8F8F2" } +style.syntax["function"] = { common.color "#A6E22E" } diff --git a/tools/editor/art/lite/data/themes/github.lua b/tools/editor/art/lite/data/themes/github.lua new file mode 100644 index 0000000..c2ba66c --- /dev/null +++ b/tools/editor/art/lite/data/themes/github.lua @@ -0,0 +1,31 @@ +local style = require "core.style" +local common = require "core.common" + +-- GitHubs style varies from language to language so its hard to get perfect +-- Originally written by thebirk, 2019 + +style.background = { common.color "#fbfbfb" } +style.background2 = { common.color "#f2f2f2" } +style.background3 = { common.color "#f2f2f2" } +style.text = { common.color "#404040" } +style.caret = { common.color "#181818" } +style.accent = { common.color "#0366d6" } +style.dim = { common.color "#b0b0b0" } +style.divider = { common.color "#e8e8e8" } +style.selection = { common.color "#b7dce8" } +style.line_number = { common.color "#d0d0d0" } +style.line_number2 = { common.color "#808080" } +style.line_highlight = { common.color "#f2f2f2" } +style.scrollbar = { common.color "#e0e0e0" } +style.scrollbar2 = { common.color "#c0c0c0" } + +style.syntax["normal"] = { common.color "#24292e" } +style.syntax["symbol"] = { common.color "#24292e" } +style.syntax["comment"] = { common.color "#6a737d" } +style.syntax["keyword"] = { common.color "#d73a49" } +style.syntax["keyword2"] = { common.color "#d73a49" } +style.syntax["number"] = { common.color "#005cc5" } +style.syntax["literal"] = { common.color "#005cc5" } +style.syntax["string"] = { common.color "#032f62" } +style.syntax["operator"] = { common.color "#d73a49" } +style.syntax["function"] = { common.color "#005cc5" } diff --git a/tools/editor/art/lite/data/themes/gruvbox_dark.lua b/tools/editor/art/lite/data/themes/gruvbox_dark.lua new file mode 100644 index 0000000..ff3e9d8 --- /dev/null +++ b/tools/editor/art/lite/data/themes/gruvbox_dark.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#282828" } +style.background2 = { common.color "#1d2021" } +style.background3 = { common.color "#1d2021" } +style.text = { common.color "#928374" } +style.caret = { common.color "#fbf1c7" } +style.accent = { common.color "#ebdbb2" } +style.dim = { common.color "#928374" } +style.divider = { common.color "#1d2021" } +style.selection = { common.color "#3c3836" } +style.line_number = { common.color "#928374" } +style.line_number2 = { common.color "#ebdbb2" } +style.line_highlight = { common.color "#32302f" } +style.scrollbar = { common.color "#928374" } +style.scrollbar2 = { common.color "#fbf1c7" } + +style.syntax["normal"] = { common.color "#ebdbb2" } +style.syntax["symbol"] = { common.color "#ebdbb2" } +style.syntax["comment"] = { common.color "#928374" } +style.syntax["keyword"] = { common.color "#fb4934" } +style.syntax["keyword2"] = { common.color "#83a598" } +style.syntax["number"] = { common.color "#d3869b" } +style.syntax["literal"] = { common.color "#d3869b" } +style.syntax["string"] = { common.color "#b8bb26" } +style.syntax["operator"] = { common.color "#ebdbb2" } +style.syntax["function"] = { common.color "#8ec07c" } diff --git a/tools/editor/art/lite/data/themes/liqube.lua b/tools/editor/art/lite/data/themes/liqube.lua new file mode 100644 index 0000000..6e7f95c --- /dev/null +++ b/tools/editor/art/lite/data/themes/liqube.lua @@ -0,0 +1,32 @@ +-- Liqube Dark Code for Lite + +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#13171e" } +style.background2 = { common.color "#21252b" } +style.background3 = { common.color "#21252b" } +style.text = { common.color "#abb2bf" } +style.caret = { common.color "#abb2bf" } +style.accent = { common.color "#ffffff" } +style.dim = { common.color "#545e70" } +style.divider = { common.color "#242223" } +style.selection = { common.color "#3e4451" } +style.line_number = { common.color "#323641" } +style.line_number2 = { common.color "#596275" } +style.line_highlight = { common.color "#1c1f25" } +style.scrollbar = { common.color "#3d3f43" } +style.scrollbar2 = { common.color "#595b5f" } +style.guide = { common.color "#1c1f25" } -- indentguide + +style.syntax["normal"] = { common.color "#abb2bf" } +style.syntax["symbol"] = { common.color "#71a9d7" } +style.syntax["comment"] = { common.color "#5c6370" } +style.syntax["keyword"] = { common.color "#98c875" } +style.syntax["keyword2"] = { common.color "#ffffff" } +style.syntax["number"] = { common.color "#ffffff" } +style.syntax["literal"] = { common.color "#ea5964" } +style.syntax["string"] = { common.color "#ea5964" } +style.syntax["operator"] = { common.color "#657085" } +style.syntax["function"] = { common.color "#ffffff" } +style.syntax["preprocessor"] = { common.color "#98c875" } -- thinking ahead diff --git a/tools/editor/art/lite/data/themes/moe.lua b/tools/editor/art/lite/data/themes/moe.lua new file mode 100644 index 0000000..5232aee --- /dev/null +++ b/tools/editor/art/lite/data/themes/moe.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#f7f9f9" } +style.background2 = { common.color "#f7f9f9" } +style.background3 = { common.color "#f7f9f9" } +style.text = { common.color "#404040" } +style.caret = { common.color "#ff5971" } +style.accent = { common.color "#ff5971" } +style.dim = { common.color "#b0b0b0" } +style.divider = { common.color "#e8e8e8" } +style.selection = { common.color "#fde6eb" } +style.line_number = { common.color "#d0d0d0" } +style.line_number2 = { common.color "#808080" } +style.line_highlight = { common.color "#f2f2f2" } +style.scrollbar = { common.color "#e0e0e0" } +style.scrollbar2 = { common.color "#c0c0c0" } + +style.syntax["normal"] = { common.color "#181818" } +style.syntax["symbol"] = { common.color "#181818" } +style.syntax["comment"] = { common.color "#43cdbd" } +style.syntax["keyword"] = { common.color "#5f7dcd" } +style.syntax["keyword2"] = { common.color "#9c53c6" } +style.syntax["number"] = { common.color "#3daee9" } +style.syntax["literal"] = { common.color "#3daee9" } +style.syntax["string"] = { common.color "#3daee9" } +style.syntax["operator"] = { common.color "#5f7dcd" } +style.syntax["function"] = { common.color "#9c53c6" } diff --git a/tools/editor/art/lite/data/themes/monodark.lua b/tools/editor/art/lite/data/themes/monodark.lua new file mode 100644 index 0000000..a61f566 --- /dev/null +++ b/tools/editor/art/lite/data/themes/monodark.lua @@ -0,0 +1,29 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#080808" } +style.background2 = { common.color "#080808" } +style.background3 = { common.color "#101010" } +style.text = { common.color "#707070" } +style.caret = { common.color "#ffffff" } +style.accent = { common.color "#d0d0d0" } +style.dim = { common.color "#303030" } +style.divider = { common.color "#080808" } +style.selection = { common.color "#242424" } +style.line_number = { common.color "#202020" } +style.line_number2 = { common.color "#707070" } +style.line_highlight = { common.color "#101010" } +style.scrollbar = { common.color "#252525" } +style.scrollbar2 = { common.color "#303030" } + +style.syntax = {} +style.syntax["normal"] = { common.color "#a0a0a0" } +style.syntax["symbol"] = { common.color "#a0a0a0" } +style.syntax["comment"] = { common.color "#404040" } +style.syntax["keyword"] = { common.color "#f0f0f0" } +style.syntax["keyword2"] = { common.color "#f0f0f0" } +style.syntax["number"] = { common.color "#f0f0f0" } +style.syntax["literal"] = { common.color "#f0f0f0" } +style.syntax["string"] = { common.color "#f0f0f0" } +style.syntax["operator"] = { common.color "#f0f0f0" } +style.syntax["function"] = { common.color "#a0a0a0" } diff --git a/tools/editor/art/lite/data/themes/monokai.lua b/tools/editor/art/lite/data/themes/monokai.lua new file mode 100644 index 0000000..96446c8 --- /dev/null +++ b/tools/editor/art/lite/data/themes/monokai.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#272822" } +style.background2 = { common.color "#22231C" } +style.background3 = { common.color "#22231C" } +style.text = { common.color "#9ea191" } +style.caret = { common.color "#F8F8F0" } +style.accent = { common.color "#F8F8F2" } +style.dim = { common.color "#5e6052" } +style.divider = { common.color "#1b1c17" } +style.selection = { common.color "#49483E" } +style.line_number = { common.color "#75715E" } +style.line_number2 = { common.color "#d2d0c6" } +style.line_highlight = { common.color "#36372f" } +style.scrollbar = { common.color "#49483E" } +style.scrollbar2 = { common.color "#636254" } + +style.syntax["normal"] = { common.color "#F8F8F2" } +style.syntax["symbol"] = { common.color "#F8F8F2" } +style.syntax["comment"] = { common.color "#75715E" } +style.syntax["keyword"] = { common.color "#F92672" } +style.syntax["keyword2"] = { common.color "#66DAEF" } +style.syntax["number"] = { common.color "#AE81FF" } +style.syntax["literal"] = { common.color "#AE81FF" } +style.syntax["string"] = { common.color "#E6DB74" } +style.syntax["operator"] = { common.color "#F8F8F2" } +style.syntax["function"] = { common.color "#A6E22E" } diff --git a/tools/editor/art/lite/data/themes/nord.lua b/tools/editor/art/lite/data/themes/nord.lua new file mode 100644 index 0000000..4b044d6 --- /dev/null +++ b/tools/editor/art/lite/data/themes/nord.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#2E3440" } +style.background2 = { common.color "#3B4252" } +style.background3 = { common.color "#3B4252" } +style.text = { common.color "#D8DEE9" } +style.caret = { common.color "#D8DEE9" } +style.accent = { common.color "#88C0D0" } +style.dim = { common.color "#5E81AC" } +style.divider = { common.color "#3B4252" } +style.selection = { common.color "#434C5E" } +style.line_number = { common.color "#4C566A" } +style.line_number2 = { common.color "#D8DEE9" } +style.line_highlight = { common.color "#434C5E" } +style.scrollbar = { common.color "#4C566A" } +style.scrollbar2 = { common.color "#D8DEE9" } + +style.syntax["normal"] = { common.color "#ECEFF4" } +style.syntax["symbol"] = { common.color "#D8DEE9" } +style.syntax["comment"] = { common.color "#4C566A" } +style.syntax["keyword"] = { common.color "#81A1C1" } +style.syntax["keyword2"] = { common.color "#81A1C1" } +style.syntax["number"] = { common.color "#B48EAD" } +style.syntax["literal"] = { common.color "#81A1C1" } +style.syntax["string"] = { common.color "#A3BE8C" } +style.syntax["operator"] = { common.color "#81A1C1" } +style.syntax["function"] = { common.color "#88C0D0" } diff --git a/tools/editor/art/lite/data/themes/onedark.lua b/tools/editor/art/lite/data/themes/onedark.lua new file mode 100644 index 0000000..cd43cbd --- /dev/null +++ b/tools/editor/art/lite/data/themes/onedark.lua @@ -0,0 +1,29 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#282c34" } +style.background2 = { common.color "#21252B" } +style.background3 = { common.color "#21252B" } +style.text = { common.color "#abb2bf" } +style.caret = { common.color "#528bff" } +style.accent = { common.color "#ffffff" } +style.dim = { common.color "#4f5873" } +style.divider = { common.color "#181A1F" } +style.selection = { common.color "#383D49" } +style.line_number = { common.color "#53576e" } +style.line_number2 = { common.color "#666B76" } +style.line_highlight = { common.color "#2C333E" } +style.scrollbar = { common.color "#353B45" } +style.scrollbar2 = { common.color "#353B45" } + +style.syntax["normal"] = { common.color "#abb2bf" } +style.syntax["symbol"] = { common.color "#abb2bf" } +style.syntax["comment"] = { common.color "#5f697a" } +style.syntax["keyword"] = { common.color "#cd74e8" } +style.syntax["keyword2"] = { common.color "#eb6772" } +style.syntax["number"] = { common.color "#db9d63" } +style.syntax["literal"] = { common.color "#db9d63" } +style.syntax["string"] = { common.color "#9acc76" } +style.syntax["operator"] = { common.color "#abb2bf" } +style.syntax["function"] = { common.color "#5cb3fa" } + diff --git a/tools/editor/art/lite/data/themes/only_dark.lua b/tools/editor/art/lite/data/themes/only_dark.lua new file mode 100644 index 0000000..2c29e9d --- /dev/null +++ b/tools/editor/art/lite/data/themes/only_dark.lua @@ -0,0 +1,31 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#242424" } +style.background2 = { common.color "#252528" } +style.background3 = { common.color "#44475A" } + +style.text = { common.color "#fffff0" } +style.caret = { common.color "#69FF94" } +style.accent = { common.color "#ff0fff" } + +style.dim = { common.color "#0fffff" } +style.divider = { common.color "#7b7f8b" } +style.selection = { common.color "#48484f" } +style.selectionhighlight = { common.color "#dddeee" } +style.line_number = { common.color "#525259" } +style.line_number2 = { common.color "#f6f6e0" } +style.line_highlight = { common.color "#343438" } +style.scrollbar = { common.color "#414146" } +style.scrollbar2 = { common.color "#4b4bff" } + +style.syntax["normal"] = { common.color "#e1e1e6" } +style.syntax["symbol"] = { common.color "#97e1f1" } +style.syntax["comment"] = { common.color "#676b6f" } +style.syntax["keyword"] = { common.color "#E58AC9" } +style.syntax["keyword2"] = { common.color "#F77483" } +style.syntax["number"] = { common.color "#FFA94D" } +style.syntax["literal"] = { common.color "#ee6666" } +style.syntax["string"] = { common.color "#f7c95c" } +style.syntax["operator"] = { common.color "#93DDFA" } +style.syntax["function"] = { common.color "#bf9eee" } diff --git a/tools/editor/art/lite/data/themes/solarized_light.lua b/tools/editor/art/lite/data/themes/solarized_light.lua new file mode 100644 index 0000000..8f604e4 --- /dev/null +++ b/tools/editor/art/lite/data/themes/solarized_light.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#fdf6e3" } +style.background2 = { common.color "#eee8d5" } +style.background3 = { common.color "#eee8d5" } +style.text = { common.color "#657b83" } +style.caret = { common.color "#657b83" } +style.accent = { common.color "#002b36" } +style.dim = { common.color "#93a1a1" } +style.divider = { common.color "#e0dbc8" } +style.selection = { common.color "#eee8d5" } +style.line_number = { common.color "#93a1a1" } +style.line_number2 = { common.color "#002b36" } +style.line_highlight = { common.color "#eee8d5" } +style.scrollbar = { common.color "#e0dbc8" } +style.scrollbar2 = { common.color "#bfbbaa" } + +style.syntax["normal"] = { common.color "#657b83" } +style.syntax["symbol"] = { common.color "#657b83" } +style.syntax["comment"] = { common.color "#93a1a1" } +style.syntax["keyword"] = { common.color "#859900" } +style.syntax["keyword2"] = { common.color "#268bd2" } +style.syntax["number"] = { common.color "#d33682" } +style.syntax["literal"] = { common.color "#2aa198" } +style.syntax["string"] = { common.color "#2aa198" } +style.syntax["operator"] = { common.color "#859900" } +style.syntax["function"] = { common.color "#268bd2" } diff --git a/tools/editor/art/lite/data/themes/solarobj.lua b/tools/editor/art/lite/data/themes/solarobj.lua new file mode 100644 index 0000000..c9ace55 --- /dev/null +++ b/tools/editor/art/lite/data/themes/solarobj.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#fdf6e3" } +style.background2 = { common.color "#2e2c29" } +style.background3 = { common.color "#3e3c37" } +style.text = { common.color "#b2ada1" } +style.caret = { common.color "#b2ada1" } +style.accent = { common.color "#6c71c4" } +style.dim = { common.color "#b2ada1" } +style.divider = { common.color "#201f1d" } +style.selection = { common.color "#eee8d5" } +style.line_number = { common.color "#93a1a1" } +style.line_number2 = { common.color "#002b36" } +style.line_highlight = { common.color "#fcefcd" } +style.scrollbar = { common.color "#e0dbc8" } +style.scrollbar2 = { common.color "#9d9988" } + +style.syntax["normal"] = { common.color "#3e3c37" } +style.syntax["symbol"] = { common.color "#4c4f82" } +style.syntax["comment"] = { common.color "#93a1a1" } +style.syntax["keyword"] = { common.color "#d33682" } +style.syntax["keyword2"] = { common.color "#6c71c4" } +style.syntax["number"] = { common.color "#859900" } +style.syntax["literal"] = { common.color "#b58900" } +style.syntax["string"] = { common.color "#cb4b16" } +style.syntax["operator"] = { common.color "#859900" } +style.syntax["function"] = { common.color "#268bd2" } diff --git a/tools/editor/art/lite/data/themes/summer.lua b/tools/editor/art/lite/data/themes/summer.lua new file mode 100644 index 0000000..5e48cf7 --- /dev/null +++ b/tools/editor/art/lite/data/themes/summer.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#fbfbfb" } +style.background2 = { common.color "#f2f2f2" } +style.background3 = { common.color "#f2f2f2" } +style.text = { common.color "#404040" } +style.caret = { common.color "#fc1785" } +style.accent = { common.color "#fc1785" } +style.dim = { common.color "#b0b0b0" } +style.divider = { common.color "#e8e8e8" } +style.selection = { common.color "#b7dce8" } +style.line_number = { common.color "#d0d0d0" } +style.line_number2 = { common.color "#808080" } +style.line_highlight = { common.color "#f2f2f2" } +style.scrollbar = { common.color "#e0e0e0" } +style.scrollbar2 = { common.color "#c0c0c0" } + +style.syntax["normal"] = { common.color "#181818" } +style.syntax["symbol"] = { common.color "#181818" } +style.syntax["comment"] = { common.color "#22a21f" } +style.syntax["keyword"] = { common.color "#fb6620" } +style.syntax["keyword2"] = { common.color "#fc1785" } +style.syntax["number"] = { common.color "#1586d2" } +style.syntax["literal"] = { common.color "#1586d2" } +style.syntax["string"] = { common.color "#1586d2" } +style.syntax["operator"] = { common.color "#fb6620" } +style.syntax["function"] = { common.color "#fc1785" } diff --git a/tools/editor/art/lite/data/themes/vscode-dark.lua b/tools/editor/art/lite/data/themes/vscode-dark.lua new file mode 100644 index 0000000..0b8d108 --- /dev/null +++ b/tools/editor/art/lite/data/themes/vscode-dark.lua @@ -0,0 +1,37 @@ +-- Most of the colors are taken from: +-- https://github.com/microsoft/vscode/tree/master/extensions/theme-defaults/themes + +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#1E1E1E" } +style.background2 = { common.color "#252526" } +style.background3 = { common.color "#252526" } +style.text = { common.color "#D4D4D4" } +style.caret = { common.color "#FFFFFF" } +style.accent = { common.color "#76BCFF" } -- Text in autocomplete and command, col(>80) in satusbar +style.dim = { common.color "#7A7A7A" } -- Text of nonactive tabs, prefix in log +style.divider = { common.color "#1E1E1E" } +style.selection = { common.color "#264F78" } +style.line_number = { common.color "#707070" } +style.line_number2 = { common.color "#A0A0A0" } -- Number on line with caret +style.line_highlight = { common.color "#333A40"} +style.scrollbar = { common.color "#404040" } +style.scrollbar2 = { common.color "#707070" } -- Hovered + +style.syntax["normal"] = { common.color "#D4D4D4" } +style.syntax["symbol"] = { common.color "#D4D4D4" } +style.syntax["comment"] = { common.color "#6A9955" } +style.syntax["keyword"] = { common.color "#569CD6" } -- local function end, if case +style.syntax["keyword2"] = { common.color "#C586C0" } -- self, int float +style.syntax["number"] = { common.color "#B5CEA8" } +style.syntax["literal"] = { common.color "#569CD6" } +style.syntax["string"] = { common.color "#CE9178" } +style.syntax["operator"] = { common.color "#8590A5"} -- = + - / < > +style.syntax["function"] = { common.color "#DCDCAA" } + +-- PLUGINS +style.linter_warning = { common.color "#B89500" } -- linter +style.bracketmatch_color = { common.color "#76BCFF" } -- bracketmatch +style.guide = { common.color "#404040" } -- indentguide +style.guide_width = 1 -- indentguide diff --git a/tools/editor/art/lite/data/themes/winter.lua b/tools/editor/art/lite/data/themes/winter.lua new file mode 100644 index 0000000..35fb408 --- /dev/null +++ b/tools/editor/art/lite/data/themes/winter.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#282a36" } +style.background2 = { common.color "#22242e" } +style.background3 = { common.color "#22242e" } +style.text = { common.color "#aab3e6" } +style.caret = { common.color "#f5faff" } +style.accent = { common.color "#ffb86c" } +style.dim = { common.color "#4f526b" } +style.divider = { common.color "#22242e" } +style.selection = { common.color "#4c5163" } +style.line_number = { common.color "#44475a" } +style.line_number2 = { common.color "#717796" } +style.line_highlight = { common.color "#2d303d" } +style.scrollbar = { common.color "#44475a" } +style.scrollbar2 = { common.color "#4c5163" } + +style.syntax["normal"] = { common.color "#f5faff" } +style.syntax["symbol"] = { common.color "#f5faff" } +style.syntax["comment"] = { common.color "#6272a4" } +style.syntax["keyword"] = { common.color "#ff79c6" } +style.syntax["keyword2"] = { common.color "#8be9fd" } +style.syntax["number"] = { common.color "#bd93f9" } +style.syntax["literal"] = { common.color "#bd93f9" } +style.syntax["string"] = { common.color "#f1fa8c" } +style.syntax["operator"] = { common.color "#ff79c6" } +style.syntax["function"] = { common.color "#8be9fd" } diff --git a/tools/editor/art/lite/data/themes/zenburn.lua b/tools/editor/art/lite/data/themes/zenburn.lua new file mode 100644 index 0000000..c69b895 --- /dev/null +++ b/tools/editor/art/lite/data/themes/zenburn.lua @@ -0,0 +1,28 @@ +local style = require "core.style" +local common = require "core.common" + +style.background = { common.color "#404040" } +style.background2 = { common.color "#3d3d3d" } +style.background3 = { common.color "#2b2b2b" } +style.text = { common.color "#dcdccc" } +style.caret = { common.color "#f8f8f0" } +style.accent = { common.color "#dcdccc" } +style.dim = { common.color "#8f8f8f" } +style.divider = { common.color "#383838" } +style.selection = { common.color "#2f2f2f" } +style.line_number = { common.color "#545454" } +style.line_number2 = { common.color "#545454" } +style.line_highlight = { common.color "#383838" } +style.scrollbar = { common.color "#4c4c4c" } +style.scrollbar2 = { common.color "#5e5e5e" } + +style.syntax["normal"] = { common.color "#dcdccc" } +style.syntax["symbol"] = { common.color "#dcdccc" } +style.syntax["comment"] = { common.color "#7f9f7f" } +style.syntax["keyword"] = { common.color "#f0dfaf" } +style.syntax["keyword2"] = { common.color "#dfdfbf" } +style.syntax["number"] = { common.color "#8cd0d3" } +style.syntax["literal"] = { common.color "#dfaf8f" } +style.syntax["string"] = { common.color "#cc9393" } +style.syntax["operator"] = { common.color "#f0efd0" } +style.syntax["function"] = { common.color "#efef8f" } diff --git a/tools/editor/art/lite/data/user/init.lua b/tools/editor/art/lite/data/user/init.lua new file mode 100644 index 0000000..689c60e --- /dev/null +++ b/tools/editor/art/lite/data/user/init.lua @@ -0,0 +1,14 @@ +-- put user settings here +-- this module will be loaded after everything else when the application starts + +local keymap = require "core.keymap" +local config = require "core.config" +local style = require "core.style" + +-- light theme: +-- require "themes.summer" +require "themes.fwk" -- monokai, dracula + +-- key binding: +-- keymap.add { ["ctrl+escape"] = "core:quit" } + diff --git a/tools/editor/art/scripts/inspect.lua b/tools/editor/art/scripts/inspect.lua new file mode 100644 index 0000000..d8a3df4 --- /dev/null +++ b/tools/editor/art/scripts/inspect.lua @@ -0,0 +1,371 @@ +local _tl_compat; if (tonumber((_VERSION or ''):match('[%d.]*$')) or 0) < 5.3 then local p, m = pcall(require, 'compat53.module'); if p then _tl_compat = m end end; local math = _tl_compat and _tl_compat.math or math; local string = _tl_compat and _tl_compat.string or string; local table = _tl_compat and _tl_compat.table or table +local inspect = {Options = {}, } + + + + + + + + + + + + + + + + + +inspect._VERSION = 'inspect.lua 3.1.0' +inspect._URL = 'http://github.com/kikito/inspect.lua' +inspect._DESCRIPTION = 'human-readable representations of tables' +inspect._LICENSE = [[ + MIT LICENSE + + Copyright (c) 2022 Enrique García Cota + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +]] +inspect.KEY = setmetatable({}, { __tostring = function() return 'inspect.KEY' end }) +inspect.METATABLE = setmetatable({}, { __tostring = function() return 'inspect.METATABLE' end }) + +local tostring = tostring +local rep = string.rep +local match = string.match +local char = string.char +local gsub = string.gsub +local fmt = string.format + +local _rawget +if rawget then + _rawget = rawget +else + _rawget = function(t, k) return t[k] end +end + +local function rawpairs(t) + return next, t, nil +end + + + +local function smartQuote(str) + if match(str, '"') and not match(str, "'") then + return "'" .. str .. "'" + end + return '"' .. gsub(str, '"', '\\"') .. '"' +end + + +local shortControlCharEscapes = { + ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", + ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v", ["\127"] = "\\127", +} +local longControlCharEscapes = { ["\127"] = "\127" } +for i = 0, 31 do + local ch = char(i) + if not shortControlCharEscapes[ch] then + shortControlCharEscapes[ch] = "\\" .. i + longControlCharEscapes[ch] = fmt("\\%03d", i) + end +end + +local function escape(str) + return (gsub(gsub(gsub(str, "\\", "\\\\"), + "(%c)%f[0-9]", longControlCharEscapes), + "%c", shortControlCharEscapes)) +end + +local luaKeywords = { + ['and'] = true, + ['break'] = true, + ['do'] = true, + ['else'] = true, + ['elseif'] = true, + ['end'] = true, + ['false'] = true, + ['for'] = true, + ['function'] = true, + ['goto'] = true, + ['if'] = true, + ['in'] = true, + ['local'] = true, + ['nil'] = true, + ['not'] = true, + ['or'] = true, + ['repeat'] = true, + ['return'] = true, + ['then'] = true, + ['true'] = true, + ['until'] = true, + ['while'] = true, +} + +local function isIdentifier(str) + return type(str) == "string" and + not not str:match("^[_%a][_%a%d]*$") and + not luaKeywords[str] +end + +local flr = math.floor +local function isSequenceKey(k, sequenceLength) + return type(k) == "number" and + flr(k) == k and + 1 <= (k) and + k <= sequenceLength +end + +local defaultTypeOrders = { + ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4, + ['function'] = 5, ['userdata'] = 6, ['thread'] = 7, +} + +local function sortKeys(a, b) + local ta, tb = type(a), type(b) + + + if ta == tb and (ta == 'string' or ta == 'number') then + return (a) < (b) + end + + local dta = defaultTypeOrders[ta] or 100 + local dtb = defaultTypeOrders[tb] or 100 + + + return dta == dtb and ta < tb or dta < dtb +end + +local function getKeys(t) + + local seqLen = 1 + while _rawget(t, seqLen) ~= nil do + seqLen = seqLen + 1 + end + seqLen = seqLen - 1 + + local keys, keysLen = {}, 0 + for k in rawpairs(t) do + if not isSequenceKey(k, seqLen) then + keysLen = keysLen + 1 + keys[keysLen] = k + end + end + table.sort(keys, sortKeys) + return keys, keysLen, seqLen +end + +local function countCycles(x, cycles) + if type(x) == "table" then + if cycles[x] then + cycles[x] = cycles[x] + 1 + else + cycles[x] = 1 + for k, v in rawpairs(x) do + countCycles(k, cycles) + countCycles(v, cycles) + end + countCycles(getmetatable(x), cycles) + end + end +end + +local function makePath(path, a, b) + local newPath = {} + local len = #path + for i = 1, len do newPath[i] = path[i] end + + newPath[len + 1] = a + newPath[len + 2] = b + + return newPath +end + + +local function processRecursive(process, + item, + path, + visited) + if item == nil then return nil end + if visited[item] then return visited[item] end + + local processed = process(item, path) + if type(processed) == "table" then + local processedCopy = {} + visited[item] = processedCopy + local processedKey + + for k, v in rawpairs(processed) do + processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited) + if processedKey ~= nil then + processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited) + end + end + + local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited) + if type(mt) ~= 'table' then mt = nil end + setmetatable(processedCopy, mt) + processed = processedCopy + end + return processed +end + +local function puts(buf, str) + buf.n = buf.n + 1 + buf[buf.n] = str +end + + + +local Inspector = {} + + + + + + + + + + +local Inspector_mt = { __index = Inspector } + +local function tabify(inspector) + puts(inspector.buf, inspector.newline .. rep(inspector.indent, inspector.level)) +end + +function Inspector:getId(v) + local id = self.ids[v] + local ids = self.ids + if not id then + local tv = type(v) + id = (ids[tv] or 0) + 1 + ids[v], ids[tv] = id, id + end + return tostring(id) +end + +function Inspector:putValue(v) + local buf = self.buf + local tv = type(v) + if tv == 'string' then + puts(buf, smartQuote(escape(v))) + elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or + tv == 'cdata' or tv == 'ctype' then + puts(buf, tostring(v)) + elseif tv == 'table' and not self.ids[v] then + local t = v + + if t == inspect.KEY or t == inspect.METATABLE then + puts(buf, tostring(t)) + elseif self.level >= self.depth then + puts(buf, '{...}') + else + if self.cycles[t] > 1 then puts(buf, fmt('<%d>', self:getId(t))) end + + local keys, keysLen, seqLen = getKeys(t) + + puts(buf, '{') + self.level = self.level + 1 + + for i = 1, seqLen + keysLen do + if i > 1 then puts(buf, ',') end + if i <= seqLen then + puts(buf, ' ') + self:putValue(t[i]) + else + local k = keys[i - seqLen] + tabify(self) + if isIdentifier(k) then + puts(buf, k) + else + puts(buf, "[") + self:putValue(k) + puts(buf, "]") + end + puts(buf, ' = ') + self:putValue(t[k]) + end + end + + local mt = getmetatable(t) + if type(mt) == 'table' then + if seqLen + keysLen > 0 then puts(buf, ',') end + tabify(self) + puts(buf, ' = ') + self:putValue(mt) + end + + self.level = self.level - 1 + + if keysLen > 0 or type(mt) == 'table' then + tabify(self) + elseif seqLen > 0 then + puts(buf, ' ') + end + + puts(buf, '}') + end + + else + puts(buf, fmt('<%s %d>', tv, self:getId(v))) + end +end + + + + +function inspect.inspect(root, options) + options = options or {} + + local depth = options.depth or (math.huge) + local newline = options.newline or '\n' + local indent = options.indent or ' ' + local process = options.process + + if process then + root = processRecursive(process, root, {}, {}) + end + + local cycles = {} + countCycles(root, cycles) + + local inspector = setmetatable({ + buf = { n = 0 }, + ids = {}, + cycles = cycles, + depth = depth, + level = 0, + newline = newline, + indent = indent, + }, Inspector_mt) + + inspector:putValue(root) + + return table.concat(inspector.buf) +end + +setmetatable(inspect, { + __call = function(_, root, options) + return inspect.inspect(root, options) + end, +}) + +return inspect \ No newline at end of file diff --git a/tools/editor/v4k_editor.h b/tools/editor/v4k_editor.h index a9eaad4..f4e1b6e 100644 --- a/tools/editor/v4k_editor.h +++ b/tools/editor/v4k_editor.h @@ -612,6 +612,7 @@ void editor_frame( void (*game)(unsigned, float, double) ) { UI_MENU_ALIGN_RIGHT(32+32+32+32+32+32+34) \ if(ingame) ui_disable(); \ UI_MENU_ITEM(ICON_MD_FOLDER_SPECIAL, editor_send("browser")) \ + UI_MENU_ITEM(ICON_MDI_SCRIPT_TEXT, editor_send("script")) \ UI_MENU_ITEM(ICON_MDI_CHART_TIMELINE, editor_send("timeline")) \ UI_MENU_ITEM(ICON_MDI_CONSOLE, editor_send("console")) \ UI_MENU_ITEM(ICON_MDI_GRAPH, editor_send("nodes")) \ @@ -722,3 +723,4 @@ void editor_frame( void (*game)(unsigned, float, double) ) { #include "v4k_editor3_timeline.h" #include "v4k_editor4_console.h" #include "v4k_editor5_nodes.h" +#include "v4k_editor6_script.h" diff --git a/tools/editor/v4k_editor6_script.h b/tools/editor/v4k_editor6_script.h new file mode 100644 index 0000000..ca46feb --- /dev/null +++ b/tools/editor/v4k_editor6_script.h @@ -0,0 +1,87 @@ +// lite { +#define f_gc f_gc2 +#define clip clip2 +#define GLEQ_IMPLEMENTATION +#include "3rd_lite_sys_gleq.h" +#include "3rd_lite_sys.h" +#include "3rd_lite.h" +// } + +int ui_texture_fit(texture_t t, struct nk_rect bounds) { + // allocate complete window space + struct nk_rect total_space = nk_window_get_content_region(ui_ctx); + nk_layout_space_begin(ui_ctx, NK_DYNAMIC, total_space.h - 4, 1); // -4 to hide scrollbar Y + nk_layout_space_push(ui_ctx, nk_rect(0,0,1,1)); + + struct nk_command_buffer *canvas = nk_window_get_canvas(ui_ctx); + struct nk_image image = nk_image_id((int)t.id); + nk_draw_image(canvas, bounds, &image, nk_white); + + nk_layout_space_end(ui_ctx); + return 0; +} + +#define LITE_ICON ICON_MDI_SCRIPT_TEXT +#define LITE_TITLE "Script " LITE_ICON + +EDITOR_BIND(script, "held(CTRL)&down(6)", { ui_show(LITE_TITLE, ui_visible(LITE_TITLE) ^ true); }); + +int editor_scripted(int window_mode) { + window_mode = EDITOR_WINDOW; // force mode + + static lua_State *L = 0; + do_once { + L = script_init_env(SCRIPT_LUA|SCRIPT_DEBUGGER); + + const char *platform = "" // "Android" "FreeBSD" "OpenBSD" "NetBSD" + ifdef(ems, "Emscripten") + ifdef(linux, "Linux") + ifdef(osx, "macOS") + ifdef(win32, "Windows") + ; + const char *pathexe = vac("%s%s%s", app_path(), app_name(), ifdef(win32, ".exe", "")); + + gleqInit(); + gleqTrackWindow(window_handle()); + lt_init(L, window_handle(), LT_DATAPATH, __argc, __argv, window_scale(), platform, pathexe); + } + + unsigned lt_none = 0u; + unsigned lt_all = ~0u & ~(GLEQ_WINDOW_MOVED|GLEQ_WINDOW_RESIZED/*|GLEQ_WINDOW_REFRESH*/); + lt_events = lt_none; + + int mouse_in_rect = 0; + if( editor_begin(LITE_TITLE, window_mode) ) { + + lt_events = lt_all; + if( !nk_window_has_focus(ui_ctx) ) lt_events = lt_none; + + struct nk_rect bounds = nk_window_get_content_region(ui_ctx); + + lt_mx = input(MOUSE_X) - bounds.x; + lt_my = input(MOUSE_Y) - bounds.y; + lt_wx = bounds.x; + lt_wy = bounds.y; + lt_ww = bounds.w; + lt_wh = bounds.h; + + if( lt_resizesurface(lt_getsurface(0), lt_ww, lt_wh) ) { + gleq_window_refresh_callback(window_handle()); + } + // fullscreen_quad_rgb( lt_getsurface(0)->t, 1.2f ); + ui_texture_fit(lt_getsurface(0)->t, bounds); + + if( !!nk_input_is_mouse_hovering_rect(&ui_ctx->input, bounds) ) { + lt_events &= ~(1<<31); // dont cursor shape + } + + editor_end(window_mode); + } + + lt_tick(L); + return 0; +} + +AUTORUN { + array_push(editor.subeditors, editor_scripted); +} diff --git a/tools/editor/windows.ini b/tools/editor/windows.ini index f59fa32..83206a2 100644 --- a/tools/editor/windows.ini +++ b/tools/editor/windows.ini @@ -22,3 +22,9 @@ y=0.053746 w=0.999084 h=0.944625 visible=0 +[Script 󰯂] +x=0.212454 +y=0.052117 +w=0.787546 +h=0.946100 +visible=0 diff --git a/tools/editor_rename.bat b/tools/editor_rename.bat index 61838db..d8933a2 100644 --- a/tools/editor_rename.bat +++ b/tools/editor_rename.bat @@ -1,5 +1,5 @@ @echo off - +setlocal enabledelayedexpansion cd %~dp0\.. pushd tools\editor diff --git a/tools/editor_sync.bat b/tools/editor_sync.bat index 6efcdfe..acdfab0 100644 --- a/tools/editor_sync.bat +++ b/tools/editor_sync.bat @@ -1,5 +1,6 @@ @echo off cd %~dp0\.. +setlocal enabledelayedexpansion pushd tools\ rd/q/s editor xcopy/e/y ..\..\fwk-mirror\tools\editor editor\ diff --git a/tools/ninja.lua b/tools/ninja.lua deleted file mode 100644 index f183085..0000000 --- a/tools/ninja.lua +++ /dev/null @@ -1,691 +0,0 @@ --- --- Name: premake-ninja/ninja.lua --- Purpose: Define the ninja action. --- Author: Dmitry Ivanov --- Created: 2015/07/04 --- Copyright: (c) 2015 Dmitry Ivanov --- - -local p = premake -local tree = p.tree -local project = p.project -local config = p.config -local fileconfig = p.fileconfig - --- Some toolset fixes/helper -p.tools.clang.objectextension = ".o" -p.tools.gcc.objectextension = ".o" -p.tools.msc.objectextension = ".obj" - -p.tools.clang.tools.rc = p.tools.clang.tools.rc or "windres" - -p.tools.msc.gettoolname = function(cfg, name) - local map = {cc = "cl", cxx = "cl", ar = "lib", rc = "rc"} - return map[name] -end - --- Ninja module -premake.modules.ninja = {} -local ninja = p.modules.ninja - -local function get_key(cfg) - if cfg.platform then - return cfg.project.name .. "_" .. cfg.buildcfg .. "_" .. cfg.platform - else - return cfg.project.name .. "_" .. cfg.buildcfg - end -end - -local build_cache = {} - -local function add_build(cfg, out, implicit_outputs, command, inputs, implicit_inputs, dependencies, vars) - implicit_outputs = ninja.list(table.translate(implicit_outputs, ninja.esc)) - if #implicit_outputs > 0 then - implicit_outputs = " |" .. implicit_outputs - else - implicit_outputs = "" - end - - inputs = ninja.list(table.translate(inputs, ninja.esc)) - - implicit_inputs = ninja.list(table.translate(implicit_inputs, ninja.esc)) - if #implicit_inputs > 0 then - implicit_inputs = " |" .. implicit_inputs - else - implicit_inputs = "" - end - - dependencies = ninja.list(table.translate(dependencies, ninja.esc)) - if #dependencies > 0 then - dependencies = " ||" .. dependencies - else - dependencies = "" - end - build_line = "build " .. ninja.esc(out) .. implicit_outputs .. ": " .. command .. inputs .. implicit_inputs .. dependencies - - local cached = build_cache[out] - if cached ~= nil then - if build_line == cached.build_line - and table.equals(vars or {}, cached.vars or {}) - then - -- custom_command rule is identical for each configuration (contrary to other rules) - -- So we can compare extra parameter - if string.startswith(cached.command, "custom_command") then - p.outln("# INFO: Rule ignored, same as " .. cached.cfg_key) - else - local cfg_key = get_key(cfg) - p.warn(cached.cfg_key .. " and " .. cfg_key .. " both generate (differently?) " .. out .. ". Ignoring " .. cfg_key) - p.outln("# WARNING: Rule ignored, using the one from " .. cached.cfg_key) - end - else - local cfg_key = get_key(cfg) - p.warn(cached.cfg_key .. " and " .. cfg_key .. " both generate differently " .. out .. ". Ignoring " .. cfg_key) - p.outln("# ERROR: Rule ignored, using the one from " .. cached.cfg_key) - end - p.outln("# " .. build_line) - for i, var in ipairs(vars or {}) do - p.outln("# " .. var) - end - return - end - p.outln(build_line) - for i, var in ipairs(vars or {}) do - p.outln(" " .. var) - end - build_cache[out] = { - cfg_key = get_key(cfg), - build_line = build_line, - vars = vars - } -end - -function ninja.esc(value) - value = value:gsub("%$", "$$") -- TODO maybe there is better way - value = value:gsub(":", "$:") - value = value:gsub("\n", "$\n") - value = value:gsub(" ", "$ ") - return value -end - -function ninja.quote(value) - value = value:gsub("\\", "\\\\") - value = value:gsub("'", "\\'") - value = value:gsub("\"", "\\\"") - - return "\"" .. value .. "\"" -end - --- in some cases we write file names in rule commands directly --- so we need to propely escape them -function ninja.shesc(value) - if type(value) == "table" then - local result = {} - local n = #value - for i = 1, n do - table.insert(result, ninja.shesc(value[i])) - end - return result - end - - if value:find(" ") then - return ninja.quote(value) - end - return value -end - --- generate solution that will call ninja for projects -function ninja.generateWorkspace(wks) - local oldGetDefaultSeparator = path.getDefaultSeparator - path.getDefaultSeparator = function() return "/" end - - p.outln("# solution build file") - p.outln("# generated with premake ninja") - p.outln("") - - p.outln("# build projects") - local cfgs = {} -- key is concatenated name or variant name, value is string of outputs names - local key = "" - local cfg_first = nil - local cfg_first_lib = nil - - for prj in p.workspace.eachproject(wks) do - if p.action.supports(prj.kind) and prj.kind ~= p.NONE then - for cfg in p.project.eachconfig(prj) do - key = get_key(cfg) - - if not cfgs[cfg.buildcfg] then cfgs[cfg.buildcfg] = {} end - table.insert(cfgs[cfg.buildcfg], key) - - -- set first configuration name - if (cfg_first == nil) and (cfg.kind == p.CONSOLEAPP or cfg.kind == p.WINDOWEDAPP) then - cfg_first = key - end - if (cfg_first_lib == nil) and (cfg.kind == p.STATICLIB or cfg.kind == p.SHAREDLIB) then - cfg_first_lib = key - end - if prj.name == wks.startproject then - cfg_first = key - end - - -- include other ninja file - p.outln("subninja " .. ninja.esc(ninja.projectCfgFilename(cfg, true))) - end - end - end - - if cfg_first == nil then cfg_first = cfg_first_lib end - - p.outln("") - - p.outln("# targets") - for cfg, outputs in pairs(cfgs) do - p.outln("build " .. ninja.esc(cfg) .. ": phony" .. ninja.list(table.translate(outputs, ninja.esc))) - end - p.outln("") - - p.outln("# default target") - p.outln("default " .. ninja.esc(cfg_first)) - p.outln("") - - path.getDefaultSeparator = oldGetDefaultSeparator -end - -function ninja.list(value) - if #value > 0 then - return " " .. table.concat(value, " ") - else - return "" - end -end - -local function shouldcompileasc(filecfg) - if filecfg.compileas and filecfg.compileas ~= "Default" then - return p.languages.isc(filecfg.compileas) - end - return path.iscfile(filecfg.abspath) -end - -local function shouldcompileascpp(filecfg) - if filecfg.compileas and filecfg.compileas ~= "Default" then - return p.languages.iscpp(filecfg.compileas) - end - return path.iscppfile(filecfg.abspath) -end - -local function getFileDependencies(cfg) - local dependencies = {} - if #cfg.prebuildcommands > 0 or cfg.prebuildmessage then - dependencies = {"prebuild_" .. get_key(cfg)} - end - for i = 1, #cfg.dependson do - table.insert(dependencies, cfg.dependson[i] .. "_" .. cfg.buildcfg) - end - return dependencies -end - -local function getcflags(toolset, cfg, filecfg) - local buildopt = ninja.list(filecfg.buildoptions) - local cppflags = ninja.list(toolset.getcppflags(filecfg)) - local cflags = ninja.list(toolset.getcflags(filecfg)) - local defines = ninja.list(table.join(toolset.getdefines(filecfg.defines), toolset.getundefines(filecfg.undefines))) - local includes = ninja.list(toolset.getincludedirs(cfg, filecfg.includedirs, filecfg.externalincludedirs, filecfg.frameworkdirs, filecfg.includedirsafter)) - local forceincludes = ninja.list(toolset.getforceincludes(cfg)) - - return buildopt .. cppflags .. cflags .. defines .. includes .. forceincludes -end - -local function getcxxflags(toolset, cfg, filecfg) - local buildopt = ninja.list(filecfg.buildoptions) - local cppflags = ninja.list(toolset.getcppflags(filecfg)) - local cxxflags = ninja.list(toolset.getcxxflags(filecfg)) - local defines = ninja.list(table.join(toolset.getdefines(filecfg.defines), toolset.getundefines(filecfg.undefines))) - local includes = ninja.list(toolset.getincludedirs(cfg, filecfg.includedirs, filecfg.externalincludedirs, filecfg.frameworkdirs, filecfg.includedirsafter)) - local forceincludes = ninja.list(toolset.getforceincludes(cfg)) - return buildopt .. cppflags .. cxxflags .. defines .. includes .. forceincludes -end - -local function getldflags(toolset, cfg) - local ldflags = ninja.list(table.join(toolset.getLibraryDirectories(cfg), toolset.getldflags(cfg), cfg.linkoptions)) - - -- experimental feature, change install_name of shared libs - --if (toolset == p.tools.clang) and (cfg.kind == p.SHAREDLIB) and ninja.endsWith(cfg.buildtarget.name, ".dylib") then - -- ldflags = ldflags .. " -install_name " .. cfg.buildtarget.name - --end - return ldflags -end - -local function getresflags(toolset, cfg, filecfg) - local defines = ninja.list(toolset.getdefines(table.join(filecfg.defines, filecfg.resdefines))) - local includes = ninja.list(toolset.getincludedirs(cfg, table.join(filecfg.externalincludedirs, filecfg.includedirsafter, filecfg.includedirs, filecfg.resincludedirs), {}, {}, {})) - local options = ninja.list(cfg.resoptions) - - return defines .. includes .. options -end - -local function prebuild_rule(cfg) - if #cfg.prebuildcommands > 0 or cfg.prebuildmessage then - local commands = {} - if cfg.prebuildmessage then - commands = {os.translateCommandsAndPaths("{ECHO} " .. cfg.prebuildmessage, cfg.workspace.basedir, cfg.workspace.location)} - end - commands = table.join(commands, os.translateCommandsAndPaths(cfg.prebuildcommands, cfg.workspace.basedir, cfg.workspace.location)) - if (#commands > 1) then - commands = 'sh -c ' .. ninja.quote(table.implode(commands,"","",";")) - else - commands = commands[1] - end - p.outln("rule run_prebuild") - p.outln(" command = " .. commands) - p.outln(" description = prebuild") - p.outln("") - end -end - -local function prelink_rule(cfg) - if #cfg.prelinkcommands > 0 or cfg.prelinkmessage then - local commands = {} - if cfg.prelinkmessage then - commands = {os.translateCommandsAndPaths("{ECHO} " .. cfg.prelinkmessage, cfg.workspace.basedir, cfg.workspace.location)} - end - commands = table.join(commands, os.translateCommandsAndPaths(cfg.prelinkcommands, cfg.workspace.basedir, cfg.workspace.location)) - if (#commands > 1) then - commands = 'sh -c ' .. ninja.quote(table.implode(commands,"","",";")) - else - commands = commands[1] - end - p.outln("rule run_prelink") - p.outln(" command = " .. commands) - p.outln(" description = prelink") - p.outln("") - end -end - -local function postbuild_rule(cfg) - if #cfg.postbuildcommands > 0 or cfg.postbuildmessage then - local commands = {} - if cfg.postbuildmessage then - commands = {os.translateCommandsAndPaths("{ECHO} " .. cfg.postbuildmessage, cfg.workspace.basedir, cfg.workspace.location)} - end - commands = table.join(commands, os.translateCommandsAndPaths(cfg.postbuildcommands, cfg.workspace.basedir, cfg.workspace.location)) - if (#commands > 1) then - commands = 'sh -c ' .. ninja.quote(table.implode(commands,"","",";")) - else - commands = commands[1] - end - p.outln("rule run_postbuild") - p.outln(" command = " .. commands) - p.outln(" description = postbuild") - p.outln("") - end -end - -local function compilation_rules(cfg, toolset, pch) - ---------------------------------------------------- figure out toolset executables - local cc = toolset.gettoolname(cfg, "cc") - local cxx = toolset.gettoolname(cfg, "cxx") - local ar = toolset.gettoolname(cfg, "ar") - local link = toolset.gettoolname(cfg, iif(cfg.language == "C", "cc", "cxx")) - local rc = toolset.gettoolname(cfg, "rc") - - local all_cflags = getcflags(toolset, cfg, cfg) - local all_cxxflags = getcxxflags(toolset, cfg, cfg) - local all_ldflags = getldflags(toolset, cfg) - local all_resflags = getresflags(toolset, cfg, cfg) - - if toolset == p.tools.msc then - p.outln("CFLAGS=" .. all_cflags) - p.outln("rule cc") - p.outln(" command = " .. cc .. " $CFLAGS" .. " /nologo /showIncludes -c /Tc$in /Fo$out") - p.outln(" description = cc $out") - p.outln(" deps = msvc") - p.outln("") - p.outln("CXXFLAGS=" .. all_cxxflags) - p.outln("rule cxx") - p.outln(" command = " .. cxx .. " $CXXFLAGS" .. " /nologo /showIncludes -c /Tp$in /Fo$out") - p.outln(" description = cxx $out") - p.outln(" deps = msvc") - p.outln("") - p.outln("RESFLAGS = " .. all_resflags) - p.outln("rule rc") - p.outln(" command = " .. rc .. " /nologo /fo$out $in $RESFLAGS") - p.outln(" description = rc $out") - p.outln("") - if cfg.kind == p.STATICLIB then - p.outln("rule ar") - p.outln(" command = " .. ar .. " $in /nologo -OUT:$out") - p.outln(" description = ar $out") - p.outln("") - else - p.outln("rule link") - p.outln(" command = " .. link .. " $in" .. ninja.list(ninja.shesc(toolset.getlinks(cfg, true))) .. " /link" .. all_ldflags .. " /nologo /out:$out") - p.outln(" description = link $out") - p.outln("") - end - elseif toolset == p.tools.clang or toolset == p.tools.gcc then - local force_include_pch = "" - if pch then - force_include_pch = " -include " .. ninja.shesc(pch.placeholder) - p.outln("rule build_pch") - p.outln(" command = " .. iif(cfg.language == "C", cc .. all_cflags .. " -x c-header", cxx .. all_cxxflags .. " -x c++-header") .. " -H -MF $out.d -c -o $out $in") - p.outln(" description = build_pch $out") - p.outln(" depfile = $out.d") - p.outln(" deps = gcc") - end - p.outln("CFLAGS=" .. all_cflags) - p.outln("rule cc") - p.outln(" command = " .. cc .. " $CFLAGS" .. force_include_pch .. " -x c -MF $out.d -c -o $out $in") - p.outln(" description = cc $out") - p.outln(" depfile = $out.d") - p.outln(" deps = gcc") - p.outln("") - p.outln("CXXFLAGS=" .. all_cxxflags) - p.outln("rule cxx") - p.outln(" command = " .. cxx .. " $CXXFLAGS" .. force_include_pch .. " -x c++ -MF $out.d -c -o $out $in") - p.outln(" description = cxx $out") - p.outln(" depfile = $out.d") - p.outln(" deps = gcc") - p.outln("") - p.outln("RESFLAGS = " .. all_resflags) - p.outln("rule rc") - p.outln(" command = " .. rc .. " -i $in -o $out $RESFLAGS") - p.outln(" description = rc $out") - p.outln("") - if cfg.kind == p.STATICLIB then - p.outln("rule ar") - p.outln(" command = " .. ar .. " rcs $out $in") - p.outln(" description = ar $out") - p.outln("") - else - local groups = iif(cfg.linkgroups == premake.ON, {"-Wl,--start-group ", " -Wl,--end-group"}, {"", ""}) - p.outln("rule link") - p.outln(" command = " .. link .. " -o $out " .. groups[1] .. "$in" .. ninja.list(ninja.shesc(toolset.getlinks(cfg, true, true))) .. all_ldflags .. groups[2]) - p.outln(" description = link $out") - p.outln("") - end - end -end - -local function custom_command_rule() - p.outln("rule custom_command") - p.outln(" command = $CUSTOM_COMMAND") - p.outln(" description = $CUSTOM_DESCRIPTION") - p.outln("") -end - -local function collect_generated_files(prj, cfg) - local generated_files = {} - tree.traverse(project.getsourcetree(prj), { - onleaf = function(node, depth) - function append_to_generated_files(filecfg) - local outputs = project.getrelative(prj.workspace, filecfg.buildoutputs) - generated_files = table.join(generated_files, outputs) - end - local filecfg = fileconfig.getconfig(node, cfg) - if not filecfg or filecfg.flags.ExcludeFromBuild then - return - end - local rule = p.global.getRuleForFile(node.name, prj.rules) - if fileconfig.hasCustomBuildRule(filecfg) then - append_to_generated_files(filecfg) - elseif rule then - local environ = table.shallowcopy(filecfg.environ) - - if rule.propertydefinition then - p.rule.prepareEnvironment(rule, environ, cfg) - p.rule.prepareEnvironment(rule, environ, filecfg) - end - local rulecfg = p.context.extent(rule, environ) - append_to_generated_files(rulecfg) - end - end, - }, false, 1) - return generated_files -end - -local function pch_build(cfg, pch) - local pch_dependency = {} - if pch then - pch_dependency = { pch.gch } - add_build(cfg, pch.gch, {}, "build_pch", {pch.input}, {}, {}, {}) - end - return pch_dependency -end - -local function custom_command_build(prj, cfg, filecfg, filename, file_dependencies) - local outputs = project.getrelative(prj.workspace, filecfg.buildoutputs) - local output = outputs[1] - table.remove(outputs, 1) - local commands = {} - if filecfg.buildmessage then - commands = {os.translateCommandsAndPaths("{ECHO} " .. filecfg.buildmessage, prj.workspace.basedir, prj.workspace.location)} - end - commands = table.join(commands, os.translateCommandsAndPaths(filecfg.buildcommands, prj.workspace.basedir, prj.workspace.location)) - if (#commands > 1) then - commands = 'sh -c ' .. ninja.quote(table.implode(commands,"","",";")) - else - commands = commands[1] - end - - add_build(cfg, output, outputs, "custom_command", {filename}, filecfg.buildinputs, file_dependencies, - {"CUSTOM_COMMAND = " .. commands, "CUSTOM_DESCRIPTION = custom build " .. ninja.shesc(output)}) -end - -local function compile_file_build(cfg, filecfg, toolset, pch_dependency, regular_file_dependencies, objfiles) - local obj_dir = project.getrelative(cfg.workspace, cfg.objdir) - local filepath = project.getrelative(cfg.workspace, filecfg.abspath) - local has_custom_settings = fileconfig.hasFileSettings(filecfg) - - if shouldcompileasc(filecfg) then - local objfilename = obj_dir .. "/" .. filecfg.objname .. (toolset.objectextension or ".o") - objfiles[#objfiles + 1] = objfilename - local cflags = {} - if has_custom_settings then - cflags = {"CFLAGS = $CFLAGS " .. getcflags(toolset, cfg, filecfg)} - end - add_build(cfg, objfilename, {}, "cc", {filepath}, pch_dependency, regular_file_dependencies, cflags) - elseif shouldcompileascpp(filecfg) then - local objfilename = obj_dir .. "/" .. filecfg.objname .. (toolset.objectextension or ".o") - objfiles[#objfiles + 1] = objfilename - local cxxflags = {} - if has_custom_settings then - cxxflags = {"CXXFLAGS = $CXXFLAGS " .. getcxxflags(toolset, cfg, filecfg)} - end - add_build(cfg, objfilename, {}, "cxx", {filepath}, pch_dependency, regular_file_dependencies, cxxflags) - elseif path.isresourcefile(filecfg.abspath) then - local objfilename = obj_dir .. "/" .. filecfg.name .. ".res" - objfiles[#objfiles + 1] = objfilename - local resflags = {} - if has_custom_settings then - resflags = {"RESFLAGS = $RESFLAGS " .. getresflags(toolset, cfg, filecfg)} - end - add_build(cfg, objfilename, {}, "rc", {filepath}, {}, {}, resflags) - end -end - -local function files_build(prj, cfg, toolset, pch_dependency, regular_file_dependencies, file_dependencies) - local objfiles = {} - tree.traverse(project.getsourcetree(prj), { - onleaf = function(node, depth) - local filecfg = fileconfig.getconfig(node, cfg) - if not filecfg or filecfg.flags.ExcludeFromBuild then - return - end - local rule = p.global.getRuleForFile(node.name, prj.rules) - local filepath = project.getrelative(cfg.workspace, node.abspath) - - if fileconfig.hasCustomBuildRule(filecfg) then - custom_command_build(prj, cfg, filecfg, filepath, file_dependencies) - elseif rule then - local environ = table.shallowcopy(filecfg.environ) - - if rule.propertydefinition then - p.rule.prepareEnvironment(rule, environ, cfg) - p.rule.prepareEnvironment(rule, environ, filecfg) - end - local rulecfg = p.context.extent(rule, environ) - custom_command_build(prj, cfg, rulecfg, filepath, file_dependencies) - else - compile_file_build(cfg, filecfg, toolset, pch_dependency, regular_file_dependencies, objfiles) - end - end, - }, false, 1) - p.outln("") - - return objfiles -end - -local function generated_files_build(cfg, generated_files, key) - local final_dependency = {} - if #generated_files > 0 then - p.outln("# generated files") - add_build(cfg, "generated_files_" .. key, {}, "phony", generated_files, {}, {}, {}) - final_dependency = {"generated_files_" .. key} - end - return final_dependency -end - --- generate project + config build file -function ninja.generateProjectCfg(cfg) - local oldGetDefaultSeparator = path.getDefaultSeparator - path.getDefaultSeparator = function() return "/" end - - local prj = cfg.project - local key = get_key(cfg) - local toolset, toolset_version = p.tools.canonical(cfg.toolset) - - if not toolset then - p.error("Unknown toolset " .. cfg.toolset) - end - - -- Some toolset fixes - cfg.gccprefix = cfg.gccprefix or "" - - p.outln("# project build file") - p.outln("# generated with premake ninja") - p.outln("") - - -- premake-ninja relies on scoped rules - -- and they were added in ninja v1.6 - p.outln("ninja_required_version = 1.6") - p.outln("") - - ---------------------------------------------------- figure out settings - local pch = nil - if toolset ~= p.tools.msc then - pch = p.tools.gcc.getpch(cfg) - if pch then - pch = { - input = pch, - placeholder = project.getrelative(cfg.workspace, path.join(cfg.objdir, path.getname(pch))), - gch = project.getrelative(cfg.workspace, path.join(cfg.objdir, path.getname(pch) .. ".gch")) - } - end - end - - ---------------------------------------------------- write rules - p.outln("# core rules for " .. cfg.name) - prebuild_rule(cfg) - prelink_rule(cfg) - postbuild_rule(cfg) - compilation_rules(cfg, toolset, pch) - custom_command_rule() - - ---------------------------------------------------- build all files - p.outln("# build files") - - local pch_dependency = pch_build(cfg, pch) - - local generated_files = collect_generated_files(prj, cfg) - local file_dependencies = getFileDependencies(cfg) - local regular_file_dependencies = table.join(iif(#generated_files > 0, {"generated_files_" .. key}, {}), file_dependencies) - - local obj_dir = project.getrelative(cfg.workspace, cfg.objdir) - local objfiles = files_build(prj, cfg, toolset, pch_dependency, regular_file_dependencies, file_dependencies) - local final_dependency = generated_files_build(cfg, generated_files, key) - - ---------------------------------------------------- build final target - if #cfg.prebuildcommands > 0 or cfg.prebuildmessage then - p.outln("# prebuild") - add_build(cfg, "prebuild_" .. get_key(cfg), {}, "run_prebuild", {}, {}, {}, {}) - end - local prelink_dependency = {} - if #cfg.prelinkcommands > 0 or cfg.prelinkmessage then - p.outln("# prelink") - add_build(cfg, "prelink_" .. get_key(cfg), {}, "run_prelink", {}, objfiles, final_dependency, {}) - prelink_dependency = { "prelink_" .. get_key(cfg) } - end - if #cfg.postbuildcommands > 0 or cfg.postbuildmessage then - p.outln("# postbuild") - add_build(cfg, "postbuild_" .. get_key(cfg), {}, "run_postbuild", {}, {ninja.outputFilename(cfg)}, {}, {}) - end - - -- we don't pass getlinks(cfg) through dependencies - -- because system libraries are often not in PATH so ninja can't find them - local libs = table.translate(config.getlinks(cfg, "siblings", "fullpath"), function (p) return project.getrelative(cfg.workspace, path.join(cfg.project.location, p)) end) - local cfg_output = ninja.outputFilename(cfg) - local extra_outputs = {} - local command_rule = "" - if cfg.kind == p.STATICLIB then - p.outln("# link static lib") - command_rule = "ar" - elseif cfg.kind == p.SHAREDLIB then - p.outln("# link shared lib") - command_rule = "link" - extra_outputs = iif(os.target() == "windows", {path.replaceextension(cfg_output, ".lib"), path.replaceextension(cfg_output, ".exp")}, {}) - elseif (cfg.kind == p.CONSOLEAPP) or (cfg.kind == p.WINDOWEDAPP) then - p.outln("# link executable") - command_rule = "link" - else - p.error("ninja action doesn't support this kind of target " .. cfg.kind) - end - add_build(cfg, cfg_output, extra_outputs, command_rule, table.join(objfiles, libs), {}, table.join(final_dependency, prelink_dependency), {}) - - p.outln("") - if #cfg.postbuildcommands > 0 or cfg.postbuildmessage then - add_build(cfg, key, {}, "phony", {"postbuild_" .. get_key(cfg)}, {}, {}, {}) - else - add_build(cfg, key, {}, "phony", {cfg_output}, {}, {}, {}) - end - p.outln("") - - path.getDefaultSeparator = oldGetDefaultSeparator -end - --- return name of output binary relative to build folder -function ninja.outputFilename(cfg) - return project.getrelative(cfg.workspace, cfg.buildtarget.directory) .. "/" .. cfg.buildtarget.name -end - --- return name of build file for configuration -function ninja.projectCfgFilename(cfg, relative) - if relative ~= nil then - relative = project.getrelative(cfg.workspace, cfg.location) .. "/" - else - relative = "" - end - return relative .. "build_" .. get_key(cfg) .. ".ninja" -end - --- check if string starts with string -function ninja.startsWith(str, starts) - return str:sub(0, starts:len()) == starts -end - --- check if string ends with string -function ninja.endsWith(str, ends) - return str:sub(-ends:len()) == ends -end - --- generate all build files for every project configuration -function ninja.generateProject(prj) - if not p.action.supports(prj.kind) or prj.kind == p.NONE then - return - end - for cfg in project.eachconfig(prj) do - p.generate(cfg, ninja.projectCfgFilename(cfg), ninja.generateProjectCfg) - end -end - -include("_preload.lua") - -return ninja diff --git a/tools/premake5.lua b/tools/premake5.lua index aadb3db..387e1d7 100644 --- a/tools/premake5.lua +++ b/tools/premake5.lua @@ -3,7 +3,7 @@ require "ninja" -- workspace workspace "project" - configurations { "devel", "debug", "release" } + configurations { "devel", "debug", "release", "retail" } location "../_project" targetdir "../_%{cfg.buildcfg}" configuration "windows" @@ -16,22 +16,38 @@ workspace "project" configuration "linux" links { "pthread", "X11", "m", "dl" } filter "configurations:debug" + debugdir "../" symbols "On" optimize "Off" + kind "consoleApp" -- "WindowedApp" filter "configurations:devel" + debugdir "../" symbols "On" optimize "On" + kind "consoleApp" -- "WindowedApp" filter "configurations:release" + debugdir "../" defines {"NDEBUG"} symbols "Off" optimize "On" + staticruntime "on" + runtime "Release" + kind "consoleApp" -- "WindowedApp" + filter "configurations:retail" + debugdir "../" + defines {"NDEBUG","ENABLE_RETAIL","main=WinMain"} + symbols "Off" + optimize "On" + staticruntime "on" + runtime "Release" + kind "WindowedApp" -- dlls project "engine" language "C" kind "SharedLib" - files {"../engine/v4k.c"} + files {"../engine/fwk.c","../engine/fwk.h"} includedirs {"../engine/"} defines {"API=EXPORT"} @@ -39,7 +55,6 @@ project "engine" project "editor" language "C" - kind "ConsoleApp" -- "WindowedApp" links {"engine"} defines {"API=IMPORT"} files { "../tools/editor/**.", @@ -53,7 +68,6 @@ project "editor" project "editor2" language "C" - kind "ConsoleApp" files { "../tools/editor/**.", "../tools/editor/**.h*", @@ -66,16 +80,14 @@ project "editor2" -- demos -function demos(...) +function demos(static,...) for _, name in ipairs({...}) do project (name) -- defaults() uuid (os.uuid(name)) language "C" - kind "consoleApp" -- "WindowedApp" - includedirs {"../engine/"} - links {"engine"} defines {"API=IMPORT"} -- kind "SharedLib" links {"engine"} includedirs {"../engine/", "../tools/editor/"} + links {"engine"} defines {"API="..static} -- kind "SharedLib" links {"engine"} files { "../demos/*"..name.."*.h*", "../demos/*"..name.."*.c*", @@ -84,9 +96,16 @@ function demos(...) end end -demos( - "00-hello","01-sprite","02-ddraw","03-character","04-control", - "04-scene","05-network","06-pbr" +demos("IMPORT", + "00-loop", "00-script", "01-demo2d", "01-easing", "01-font", "01-ui", + "02-ddraw", "02-frustum", "03-anims", "04-actor", "06-material", "06-scene", + "07-netsync", "07-network", "08-audio", "08-video", "09-cubemap", "09-shadertoy", + "99-bt", "99-compute", "99-controller", "99-demo", "99-geom", "99-lod", + "99-pathfind","99-pbr", "99-spine", "99-sponza", "99-sprite" +) + +demos("STATIC", + "99-nodes" ) -- games @@ -96,10 +115,8 @@ function games(...) project ("game-" .. name) uuid (os.uuid("game-" .. name)) language "C++" - kind "consoleApp" - includedirs {"../engine/"} - links {"engine"} defines {"API=IMPORT"} -- kind "SharedLib" links {"engine"} includedirs {"../engine/", "../tools/editor/"} + links {"engine"} defines {"API=IMPORT"} -- kind "SharedLib" links {"engine"} files { "../games/"..name.."/**.h*", "../games/"..name.."/**.c*", diff --git a/tools/tcc/lib/wininet.def b/tools/tcc/lib/wininet.def new file mode 100644 index 0000000..3d47923 --- /dev/null +++ b/tools/tcc/lib/wininet.def @@ -0,0 +1,9 @@ +LIBRARY wininet.dll + +EXPORTS +InternetOpenA +InternetOpenW +InternetCloseHandle +InternetOpenUrlA +InternetOpenUrlW +InternetReadFile \ No newline at end of file diff --git a/tools/timer.c b/tools/timer.c index 28390f0..92699a6 100644 --- a/tools/timer.c +++ b/tools/timer.c @@ -11,17 +11,32 @@ #include #endif +#ifdef _WIN32 +#include +#else +#include +#endif + int main(int argc, char **argv) { - if( argc <= 1 ) return 0; - char buf[16384] = {0}; // LEAK = calloc(1, 2*1024*1024); - for(int i = 1; i < argc; ++i) { - strcat(buf, argv[i]); - strcat(buf, " "); + if(!_isatty(fileno(stdin))) { + clock_t t1 = clock(); + while(!feof(stdin)) putc(getc(stdin), stdout); + clock_t t2 = clock(); + fprintf(stderr, "%.3fs\n", (t2-t1)*1.0/CLOCKS_PER_SEC); + return 0; } - puts(buf); - clock_t t1 = clock(); - int rc = system(buf); - clock_t t2 = clock(); - fprintf(stderr, "%.3fs - return code: %d\n", (t2-t1)*1.0/CLOCKS_PER_SEC, rc); - return rc; + if( argc > 1 ) { + char buf[16384] = {0}; // LEAK = calloc(1, 2*1024*1024); + for(int i = 1; i < argc; ++i) { + strcat(buf, argv[i]); + strcat(buf, " "); + } + puts(buf); + clock_t t1 = clock(); + int rc = system(buf); + clock_t t2 = clock(); + fprintf(stderr, "%.3fs - return code: %d\n", (t2-t1)*1.0/CLOCKS_PER_SEC, rc); + return rc; + } + return 0; } diff --git a/tools/timer.exe b/tools/timer.exe index 1fd21a8..fb7bbad 100644 Binary files a/tools/timer.exe and b/tools/timer.exe differ