bam-0.4.0/0000755000175000017500000000000011430042046010346 5ustar kmakmabam-0.4.0/tests/0000755000175000017500000000000011430042030011501 5ustar kmakmabam-0.4.0/tests/dot.in.dir/0000755000175000017500000000000011430042030013451 5ustar kmakmabam-0.4.0/tests/dot.in.dir/bam.lua0000644000175000017500000000024411430042030014713 0ustar kmakmasettings = NewSettings() src = Collect("*.cpp") objs = Compile(settings, src) exe = Link(settings, "dot_app", objs) exe2 = Link(settings, "dot_app_d", objs) bam-0.4.0/tests/dot.in.dir/dot_in_dir.cpp0000644000175000017500000000017411430042030016271 0ustar kmakma#include using namespace std; int main() { cout << "Hello world!" << endl; return 0; } bam-0.4.0/tests/include_paths/0000755000175000017500000000000011430042030014323 5ustar kmakmabam-0.4.0/tests/include_paths/local_header.h0000644000175000017500000000000111430042030017065 0ustar kmakma bam-0.4.0/tests/include_paths/bam.lua0000644000175000017500000000014011430042030015560 0ustar kmakmas = NewSettings() s.cc.includes:Add("dir") Link(s, "include_paths", Compile(s, Collect("*.c"))) bam-0.4.0/tests/include_paths/include_paths.c0000644000175000017500000000012111430042030017303 0ustar kmakma#include #include "local_header.h" int main() { return 0; } bam-0.4.0/tests/include_paths/dir/0000755000175000017500000000000011430042030015101 5ustar kmakmabam-0.4.0/tests/include_paths/dir/system_header.h0000644000175000017500000000017511430042030020111 0ustar kmakma/* UGG!!! */ #include "../local_header.h" #if 0 #include "../does_not_existing1.h" #include <../does_not_existing2.h> #endif bam-0.4.0/tests/sharedlib/0000755000175000017500000000000011430042030013436 5ustar kmakmabam-0.4.0/tests/sharedlib/bam.lua0000644000175000017500000000027711430042030014706 0ustar kmakmasettings = NewSettings() if arch == "amd64" then settings.cc.flags:Add("-fPIC") end src = Collect("*.cpp") objs = Compile(settings, src) exe = SharedLibrary(settings, "shared", objs) bam-0.4.0/tests/sharedlib/sharedlib.cpp0000644000175000017500000000020311430042030016072 0ustar kmakma#include using namespace std; int shared_func() { cout << "Hello world!" << endl; return 0; } bam-0.4.0/tests/collect_recurse/0000755000175000017500000000000011430042030014656 5ustar kmakmabam-0.4.0/tests/collect_recurse/extra/0000755000175000017500000000000011430042030016001 5ustar kmakmabam-0.4.0/tests/collect_recurse/extra/recursed.cpp0000644000175000017500000000004411430042030020317 0ustar kmakmaint recurse_test() { return 1337; } bam-0.4.0/tests/collect_recurse/bam.lua0000644000175000017500000000022111430042030016113 0ustar kmakmasettings = NewSettings() src = CollectRecursive("*.cpp") objs = Compile(settings, src) exe = Link(settings, "output/creation/gc_app", objs) bam-0.4.0/tests/collect_recurse/collect_recurse.cpp0000644000175000017500000000025211430042030020536 0ustar kmakma#include using namespace std; extern int recurse_test(); int main() { cout << "Hello world!" << recurse_test() << endl; return 0; } bam-0.4.0/tests/subproject/0000755000175000017500000000000011430042030013661 5ustar kmakmabam-0.4.0/tests/subproject/bam.lua0000644000175000017500000000040611430042030015123 0ustar kmakmamod = Import("mod/mod.bam") test = "ERROR: wrong variable" function get_test() return "ERROR: wrong function" end s = NewSettings() mod.use(s) objs = Compile(s, Collect("*.c")) print("Error test:", mod.get_test()) exe = Link(s, "subproj", objs, mod.output) bam-0.4.0/tests/subproject/mod/0000755000175000017500000000000011430042030014440 5ustar kmakmabam-0.4.0/tests/subproject/mod/mod.c0000644000175000017500000000010211430042030015354 0ustar kmakmaconst char *get_magic_string() { return "magic mod string!!!"; } bam-0.4.0/tests/subproject/mod/mod2/0000755000175000017500000000000011430042030015301 5ustar kmakmabam-0.4.0/tests/subproject/mod/mod2/mod2.c0000644000175000017500000000010211430042030016277 0ustar kmakmaconst char *get_magic_string() { return "magic mod string!!!"; } bam-0.4.0/tests/subproject/mod/mod2/mod2.bam0000644000175000017500000000047211430042030016626 0ustar kmakmas = NewSettings() objs = Compile(s, Collect("*.c")) lib = StaticLibrary(s, "lib", objs) test = "OK: right variable!" print("LIB: ", lib) vpath = Path("") function use(settings) settings.cc.includes:add(vpath) settings.linker.extrafiles:add(lib) print(include_path) end function get_test() return test end bam-0.4.0/tests/subproject/mod/mod2/mod2.h0000644000175000017500000000004711430042030016314 0ustar kmakmaextern const char *get_magic_string(); bam-0.4.0/tests/subproject/mod/mod.bam0000644000175000017500000000047111430042030015702 0ustar kmakmas = NewSettings() objs = Compile(s, Collect("*.c")) lib = StaticLibrary(s, "lib", objs) test = "OK: right variable!" print("LIB: ", lib) vpath = Path("") function use(settings) settings.cc.includes:add(vpath) settings.linker.extrafiles:add(lib) print(include_path) end function get_test() return test end bam-0.4.0/tests/subproject/mod/mod.h0000644000175000017500000000004711430042030015371 0ustar kmakmaextern const char *get_magic_string(); bam-0.4.0/tests/subproject/main.c0000644000175000017500000000015611430042030014753 0ustar kmakma#include #include int main() { printf("The string: %s", get_magic_string()); return 0; } bam-0.4.0/tests/multi_target/0000755000175000017500000000000011430042030014201 5ustar kmakmabam-0.4.0/tests/multi_target/bam.lua0000644000175000017500000000020111430042030015434 0ustar kmakmas = NewSettings() objs = Compile(s, Collect("*.c")) PseudoTarget("CORRECT_ONE", Link(s, "correct", objs)) Link(s, "ERROR", objs) bam-0.4.0/tests/multi_target/multi_target.c0000644000175000017500000000003311430042030017041 0ustar kmakmaint main() { return 0; } bam-0.4.0/tests/collect_wrong/0000755000175000017500000000000011430042030014342 5ustar kmakmabam-0.4.0/tests/collect_wrong/collect_wrong.cpp0000644000175000017500000000017411430042030017711 0ustar kmakma#include using namespace std; int main() { cout << "Hello world!" << endl return 0; } bam-0.4.0/tests/collect_wrong/bam.lua0000644000175000017500000000023111430042030015600 0ustar kmakmasettings = NewSettings() src = Collect("test/*.cpp") -- this path does not exist objs = Compile(settings, src) exe = Link(settings, "gc_app", objs) bam-0.4.0/tests/cyclic/0000755000175000017500000000000011430042030012747 5ustar kmakmabam-0.4.0/tests/cyclic/header2.h0000644000175000017500000000010111430042030014422 0ustar kmakma#ifndef HEADER2_H #define HEADER2_H #include "header1.h" #endif bam-0.4.0/tests/cyclic/bam.lua0000644000175000017500000000010011430042030014200 0ustar kmakmas = NewSettings() Link(s, "cyclic", Compile(s, Collect("*.c"))) bam-0.4.0/tests/cyclic/cyclic.c0000644000175000017500000000010611430042030014356 0ustar kmakma#include "header1.h" #include "header2.h" int main() { return 0; } bam-0.4.0/tests/cyclic/header1.h0000644000175000017500000000010111430042030014421 0ustar kmakma#ifndef HEADER1_H #define HEADER1_H #include "header2.h" #endif bam-0.4.0/tests/deps/0000755000175000017500000000000011430042030012434 5ustar kmakmabam-0.4.0/tests/deps/bam.lua0000644000175000017500000000013711430042030013677 0ustar kmakmas = NewSettings() e = Link(s, "deps", Compile(s, "main.c")) AddDependency(e, "DOES_NOT_EXIST") bam-0.4.0/tests/deps/main.c0000644000175000017500000000003311430042030013520 0ustar kmakmaint main() { return 0; } bam-0.4.0/tests/retval/0000755000175000017500000000000011430042030012776 5ustar kmakmabam-0.4.0/tests/retval/bam.lua0000644000175000017500000000017111430042030014237 0ustar kmakmasettings = NewSettings() src = Collect("*.cpp") objs = Compile(settings, src) exe = Link(settings, "gc_app", objs) bam-0.4.0/tests/retval/retval.cpp0000644000175000017500000000017411430042030015001 0ustar kmakma#include using namespace std; int main() { cout << "Hello world!" << endl return 0; } bam-0.4.0/tests/addorder/0000755000175000017500000000000011430042030013265 5ustar kmakmabam-0.4.0/tests/addorder/bam.lua0000644000175000017500000000034611430042030014532 0ustar kmakmasettings = NewSettings() AddJob("test", "testing", "echo") AddDependency("test", "test2") AddJob("test2", "testing", "echo") --src = Collect("*.cpp") --objs = Compile(settings, src) --exe = Link(settings, "addorder", objs) bam-0.4.0/tests/deadlock/0000755000175000017500000000000011430042030013247 5ustar kmakmabam-0.4.0/tests/deadlock/header2.h0000644000175000017500000000012411430042030014727 0ustar kmakma#ifndef HEADER2 #define HEADER2 #include "header1.h" #include "header_gen.h" #endif bam-0.4.0/tests/deadlock/bam.lua0000644000175000017500000000044511430042030014514 0ustar kmakmasettings = NewSettings() if family == "windows" then AddJob("header_gen.h", "headergen", "echo /**/ > header_gen.h") else AddJob("header_gen.h", "headergen", "echo \"/**/\" > header_gen.h") end src = Collect("*.c") objs = Compile(settings, src) exe = Link(settings, "deadlock", objs) bam-0.4.0/tests/deadlock/test.c0000644000175000017500000000010511430042030014366 0ustar kmakma#include "header1.h" #include "header2.h" int main() { return 0; } bam-0.4.0/tests/deadlock/header1.h0000644000175000017500000000012411430042030014726 0ustar kmakma#ifndef HEADER1 #define HEADER1 #include "header2.h" #include "header_gen.h" #endif bam-0.4.0/tests/cxx_dep/0000755000175000017500000000000011430042030013133 5ustar kmakmabam-0.4.0/tests/cxx_dep/local_header.h0000644000175000017500000000000111430042030015675 0ustar kmakma bam-0.4.0/tests/cxx_dep/lib.c0000644000175000017500000000012011430042030014036 0ustar kmakma#include extern int hello() { printf("hello world\n"); return 0; } bam-0.4.0/tests/cxx_dep/bam.lua0000644000175000017500000000072111430042030014375 0ustar kmakmas = NewSettings() s.cc.includes:Add("dir") s.link.libpath:Add("libs") s.link.libs:Add("hello") -- the look up for this lib should be deferred DefaultTarget(Link(s, "dep_cxx", Compile(s, "main.c"))) if family == "windows" then AddJob("dir/genereted_header.h", "headergen", "echo /**/ > dir/genereted_header.h") else AddJob("dir/genereted_header.h", "headergen", "echo \"/**/\" > dir/genereted_header.h") end StaticLibrary(s, "libs/hello", Compile(s, "lib.c")) bam-0.4.0/tests/cxx_dep/main.c0000644000175000017500000000021211430042030014216 0ustar kmakma#include #include #include "local_header.h" extern int hello(); int main() { return hello(); } bam-0.4.0/tests/cxx_dep/dir/0000755000175000017500000000000011430042030013711 5ustar kmakmabam-0.4.0/tests/cxx_dep/dir/system_header.h0000644000175000017500000000017511430042030016721 0ustar kmakma/* UGG!!! */ #include "../local_header.h" #if 0 #include "../does_not_existing1.h" #include <../does_not_existing2.h> #endif bam-0.4.0/tests/locked/0000755000175000017500000000000011430042030012742 5ustar kmakmabam-0.4.0/tests/locked/locked.cpp0000644000175000017500000000017411430042030014711 0ustar kmakma#include using namespace std; int main() { cout << "Hello world!" << endl; return 0; } bam-0.4.0/tests/locked/bam.lua0000644000175000017500000000027011430042030014203 0ustar kmakmasettings = NewSettings() settings.cc.DOES_NOT_EXIST = 1 settings["DOES_NOT_EXIST"] = 1 src = Collect("*.cpp") objs = Compile(settings, src) exe = Link(settings, "gc_app", objs) bam-0.4.0/make_unix.sh0000755000175000017500000000042311430042030012655 0ustar kmakma#!/bin/sh gcc -Wall -ansi -pedantic src/tools/txt2c.c -o src/tools/txt2c src/tools/txt2c src/base.lua src/tools.lua src/driver_gcc.lua src/driver_cl.lua > src/internal_base.h gcc -Wall -ansi -pedantic src/*.c src/lua/*.c -o bam -I src/lua -lm -lpthread -ldl -O2 -rdynamic $* bam-0.4.0/license.txt0000644000175000017500000000152511430042030012525 0ustar kmakmaCopyright (c) 2009 Magnus Auvinen 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. bam-0.4.0/examples/0000755000175000017500000000000011430042030012155 5ustar kmakmabam-0.4.0/examples/plugin/0000755000175000017500000000000011430042030013453 5ustar kmakmabam-0.4.0/examples/plugin/hello.c0000644000175000017500000000032411430042030014721 0ustar kmakma#include static int lf_helloworld(struct lua_State *L) { lua_pushstring(L, "Hello World!"); return 1; } int plugin_main(lua_State *L) { lua_register(L, "HelloWorld", lf_helloworld); return 0; } bam-0.4.0/make_win32_msvc.bat0000644000175000017500000000251211430042030014016 0ustar kmakma@echo off @REM check if we already have the tools in the environment if exist "%VCINSTALLDIR%" ( goto compile ) @REM Check for Visual Studio if exist "%VS100COMNTOOLS%" ( set VSPATH="%VS100COMNTOOLS%" goto set_env ) if exist "%VS90COMNTOOLS%" ( set VSPATH="%VS90COMNTOOLS%" goto set_env ) if exist "%VS80COMNTOOLS%" ( set VSPATH="%VS80COMNTOOLS%" goto set_env ) echo You need Microsoft Visual Studio 8, 9 or 10 installed pause exit @ setup the environment :set_env call %VSPATH%vsvars32.bat :compile @echo === building bam === @cl /D_CRT_SECURE_NO_DEPRECATE /O2 /nologo src/tools/txt2c.c /Fesrc/tools/txt2c.exe @src\tools\txt2c src/base.lua src/tools.lua src/driver_gcc.lua src/driver_cl.lua > src\internal_base.h @REM /DLUA_BUILD_AS_DLL = export lua functions @REM /W3 = Warning level 3 @REM /Ox = max optimizations @REM /TC = compile as c @REM /Zi = generate debug database @REM /GS- = no stack checks @REM /GL = Whole program optimization (ltcg) @REM /LTCG = link time code generation @cl /D_CRT_SECURE_NO_DEPRECATE /DLUA_BUILD_AS_DLL /W3 /O2 /TC /Zi /GS- /GL /nologo /I src/lua src/*.c src/lua/*.c /Febam.exe /link /LTCG @echo === building example plugin === @cl /nologo /c examples/plugin/hello.c /Isrc @link /nologo /dll hello.obj bam.lib /def:windows_plugin.def @REM clean up @del hello.lib hello.exp bam.exp hello.exp @del *.obj bam-0.4.0/make_beos.sh0000644000175000017500000000040011430042030012612 0ustar kmakma#!/bin/sh gcc -Wall -ansi -pedantic src/tools/txt2c.c -o src/tools/txt2c src/tools/txt2c src/base.lua src/tools.lua src/driver_gcc.lua src/driver_cl.lua > src/internal_base.h gcc -Wall -ansi -pedantic src/lua/*.c src/*.c -o bam -I src/lua -lpthread -O2 $* bam-0.4.0/make_win32_mingw.bat0000644000175000017500000000041711430042030014171 0ustar kmakma@gcc -Wall -ansi -pedantic src/tools/txt2c.c -o src/tools/txt2c @src\tools\txt2c.exe src\base.lua src\tools.lua src\driver_gcc.lua src\driver_cl.lua > src\internal_base.h @gcc -Wall -ansi -pedantic src/lua/src/*.c src/lua/src/lib/*.c src/*.c -o bam -I src/lua/include/ bam-0.4.0/make_winx64_msvc2005.bat0000644000175000017500000000014411430042030014521 0ustar kmakma@cl /D_CRT_SECURE_NO_DEPRECATE /W3 /O2 /nologo src/*.c src/lua/*.c /I src/lua /Febam.exe @del *.obj bam-0.4.0/make_unix_clang.sh0000755000175000017500000000042711430042030014025 0ustar kmakma#!/bin/sh clang -Wall -ansi -pedantic src/tools/txt2c.c -o src/tools/txt2c src/tools/txt2c src/base.lua src/tools.lua src/driver_gcc.lua src/driver_cl.lua > src/internal_base.h clang -Wall -ansi -pedantic src/*.c src/lua/*.c -o bam -I src/lua -lm -lpthread -ldl -O2 -rdynamic $* bam-0.4.0/make_win32_dmc.bat0000644000175000017500000000075211430042030013615 0ustar kmakma@REM --- Batch file that builds bam using Digital Mars C Compiler @dmc -L/NOL -A src\tools\txt2c.c -o src\tools\txt2c.exe @src\tools\txt2c.exe src\base.lua src\tools.lua src\driver_gcc.lua src\driver_cl.lua > src\internal_base.h @REM ------ Generate fileliest @move src\tools\txt2c.c src\tools\txt2c.c.temp > nul @dir /s /b src\*.c > files @move src\tools\txt2c.c.temp src\tools\txt2c.c > nul @dmc -Isrc/lua @files -o bam.exe @REM ------ Restore everything @del *.obj *.map @del files bam-0.4.0/windows_plugin.def0000644000175000017500000000002411430042030014063 0ustar kmakmaEXPORTS plugin_mainbam-0.4.0/src/0000755000175000017500000000000011430042030011126 5ustar kmakmabam-0.4.0/src/tree.h0000644000175000017500000004105711430042030012245 0ustar kmakma/* IMPORTANT!!!! THIS HAS BEEN MODIFIED FROM THE ORIGINAL SOURCE. I've removed the functions that we don't use. IMPORTANT!!!! */ /* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */ /* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */ /* $FreeBSD: src/sys/sys/tree.h,v 1.6.2.1 2008/03/07 22:34:17 jasone Exp $ */ /*- * Copyright 2002 Niels Provos * 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 AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _SYS_TREE_H_ #define _SYS_TREE_H_ /*#include */ /* * This file defines data structures for different types of trees: * red-black trees. * * A red-black tree is a binary search tree with the node color as an * extra attribute. It fulfills a set of conditions: * - every search path from the root to a leaf consists of the * same number of black nodes, * - each red node (except for the root) has a black parent, * - each leaf node is black. * * Every operation on a red-black tree is bounded as O(lg n). * The maximum height of a red-black tree is 2lg (n+1). */ /* Macros that define a red-black tree */ #define RB_HEAD(name, type) \ struct name { \ struct type *rbh_root; /* root of the tree */ \ } #define RB_INITIALIZER(root) \ { NULL } #define RB_INIT(root) do { \ (root)->rbh_root = NULL; \ } while (/*CONSTCOND*/ 0) #define RB_BLACK 0 #define RB_RED 1 #define RB_ENTRY(type) \ struct { \ struct type *rbe_left; /* left element */ \ struct type *rbe_right; /* right element */ \ struct type *rbe_parent; /* parent element */ \ int rbe_color; /* node color */ \ } #define RB_LEFT(elm, field) (elm)->field.rbe_left #define RB_RIGHT(elm, field) (elm)->field.rbe_right #define RB_PARENT(elm, field) (elm)->field.rbe_parent #define RB_COLOR(elm, field) (elm)->field.rbe_color #define RB_ROOT(head) (head)->rbh_root #define RB_EMPTY(head) (RB_ROOT(head) == NULL) #define RB_SET(elm, parent, field) do { \ RB_PARENT(elm, field) = parent; \ RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \ RB_COLOR(elm, field) = RB_RED; \ } while (/*CONSTCOND*/ 0) #define RB_SET_BLACKRED(black, red, field) do { \ RB_COLOR(black, field) = RB_BLACK; \ RB_COLOR(red, field) = RB_RED; \ } while (/*CONSTCOND*/ 0) #ifndef RB_AUGMENT #define RB_AUGMENT(x) do {} while (0) #endif #define RB_ROTATE_LEFT(head, elm, tmp, field) do { \ (tmp) = RB_RIGHT(elm, field); \ if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \ RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \ } \ RB_AUGMENT(elm); \ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ else \ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ } else \ (head)->rbh_root = (tmp); \ RB_LEFT(tmp, field) = (elm); \ RB_PARENT(elm, field) = (tmp); \ RB_AUGMENT(tmp); \ if ((RB_PARENT(tmp, field))) \ RB_AUGMENT(RB_PARENT(tmp, field)); \ } while (/*CONSTCOND*/ 0) #define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \ (tmp) = RB_LEFT(elm, field); \ if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \ RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \ } \ RB_AUGMENT(elm); \ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \ else \ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \ } else \ (head)->rbh_root = (tmp); \ RB_RIGHT(tmp, field) = (elm); \ RB_PARENT(elm, field) = (tmp); \ RB_AUGMENT(tmp); \ if ((RB_PARENT(tmp, field))) \ RB_AUGMENT(RB_PARENT(tmp, field)); \ } while (/*CONSTCOND*/ 0) /* Generates prototypes and inline functions */ #define RB_PROTOTYPE(name, type, field, cmp) \ RB_PROTOTYPE_INTERNAL(name, type, field, cmp,) #define RB_PROTOTYPE_STATIC(name, type, field, cmp) \ RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static) #define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \ attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \ attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\ attr struct type *name##_RB_REMOVE(struct name *, struct type *); \ attr struct type *name##_RB_INSERT(struct name *, struct type *); \ attr struct type *name##_RB_FIND(struct name *, struct type *); \ attr struct type *name##_RB_NFIND(struct name *, struct type *); \ attr struct type *name##_RB_NEXT(struct type *); \ attr struct type *name##_RB_PREV(struct type *); \ attr struct type *name##_RB_MINMAX(struct name *, int); \ \ /* Main rb operation. * Moves node close to the key of elm to top */ #define RB_GENERATE(name, type, field, cmp) \ RB_GENERATE_INTERNAL(name, type, field, cmp,) #define RB_GENERATE_STATIC(name, type, field, cmp) \ RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static) #define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \ attr void \ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \ { \ struct type *parent, *gparent, *tmp; \ while ((parent = RB_PARENT(elm, field)) != NULL && \ RB_COLOR(parent, field) == RB_RED) { \ gparent = RB_PARENT(parent, field); \ if (parent == RB_LEFT(gparent, field)) { \ tmp = RB_RIGHT(gparent, field); \ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ RB_COLOR(tmp, field) = RB_BLACK; \ RB_SET_BLACKRED(parent, gparent, field);\ elm = gparent; \ continue; \ } \ if (RB_RIGHT(parent, field) == elm) { \ RB_ROTATE_LEFT(head, parent, tmp, field);\ tmp = parent; \ parent = elm; \ elm = tmp; \ } \ RB_SET_BLACKRED(parent, gparent, field); \ RB_ROTATE_RIGHT(head, gparent, tmp, field); \ } else { \ tmp = RB_LEFT(gparent, field); \ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \ RB_COLOR(tmp, field) = RB_BLACK; \ RB_SET_BLACKRED(parent, gparent, field);\ elm = gparent; \ continue; \ } \ if (RB_LEFT(parent, field) == elm) { \ RB_ROTATE_RIGHT(head, parent, tmp, field);\ tmp = parent; \ parent = elm; \ elm = tmp; \ } \ RB_SET_BLACKRED(parent, gparent, field); \ RB_ROTATE_LEFT(head, gparent, tmp, field); \ } \ } \ RB_COLOR(head->rbh_root, field) = RB_BLACK; \ } \ \ attr void \ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \ { \ struct type *tmp; \ while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \ elm != RB_ROOT(head)) { \ if (RB_LEFT(parent, field) == elm) { \ tmp = RB_RIGHT(parent, field); \ if (RB_COLOR(tmp, field) == RB_RED) { \ RB_SET_BLACKRED(tmp, parent, field); \ RB_ROTATE_LEFT(head, parent, tmp, field);\ tmp = RB_RIGHT(parent, field); \ } \ if ((RB_LEFT(tmp, field) == NULL || \ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ (RB_RIGHT(tmp, field) == NULL || \ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ RB_COLOR(tmp, field) = RB_RED; \ elm = parent; \ parent = RB_PARENT(elm, field); \ } else { \ if (RB_RIGHT(tmp, field) == NULL || \ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\ struct type *oleft; \ if ((oleft = RB_LEFT(tmp, field)) \ != NULL) \ RB_COLOR(oleft, field) = RB_BLACK;\ RB_COLOR(tmp, field) = RB_RED; \ RB_ROTATE_RIGHT(head, tmp, oleft, field);\ tmp = RB_RIGHT(parent, field); \ } \ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ RB_COLOR(parent, field) = RB_BLACK; \ if (RB_RIGHT(tmp, field)) \ RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\ RB_ROTATE_LEFT(head, parent, tmp, field);\ elm = RB_ROOT(head); \ break; \ } \ } else { \ tmp = RB_LEFT(parent, field); \ if (RB_COLOR(tmp, field) == RB_RED) { \ RB_SET_BLACKRED(tmp, parent, field); \ RB_ROTATE_RIGHT(head, parent, tmp, field);\ tmp = RB_LEFT(parent, field); \ } \ if ((RB_LEFT(tmp, field) == NULL || \ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\ (RB_RIGHT(tmp, field) == NULL || \ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\ RB_COLOR(tmp, field) = RB_RED; \ elm = parent; \ parent = RB_PARENT(elm, field); \ } else { \ if (RB_LEFT(tmp, field) == NULL || \ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\ struct type *oright; \ if ((oright = RB_RIGHT(tmp, field)) \ != NULL) \ RB_COLOR(oright, field) = RB_BLACK;\ RB_COLOR(tmp, field) = RB_RED; \ RB_ROTATE_LEFT(head, tmp, oright, field);\ tmp = RB_LEFT(parent, field); \ } \ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\ RB_COLOR(parent, field) = RB_BLACK; \ if (RB_LEFT(tmp, field)) \ RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\ RB_ROTATE_RIGHT(head, parent, tmp, field);\ elm = RB_ROOT(head); \ break; \ } \ } \ } \ if (elm) \ RB_COLOR(elm, field) = RB_BLACK; \ } \ \ attr struct type * \ name##_RB_REMOVE(struct name *head, struct type *elm) \ { \ struct type *child, *parent, *old = elm; \ int color; \ if (RB_LEFT(elm, field) == NULL) \ child = RB_RIGHT(elm, field); \ else if (RB_RIGHT(elm, field) == NULL) \ child = RB_LEFT(elm, field); \ else { \ struct type *left; \ elm = RB_RIGHT(elm, field); \ while ((left = RB_LEFT(elm, field)) != NULL) \ elm = left; \ child = RB_RIGHT(elm, field); \ parent = RB_PARENT(elm, field); \ color = RB_COLOR(elm, field); \ if (child) \ RB_PARENT(child, field) = parent; \ if (parent) { \ if (RB_LEFT(parent, field) == elm) \ RB_LEFT(parent, field) = child; \ else \ RB_RIGHT(parent, field) = child; \ RB_AUGMENT(parent); \ } else \ RB_ROOT(head) = child; \ if (RB_PARENT(elm, field) == old) \ parent = elm; \ (elm)->field = (old)->field; \ if (RB_PARENT(old, field)) { \ if (RB_LEFT(RB_PARENT(old, field), field) == old)\ RB_LEFT(RB_PARENT(old, field), field) = elm;\ else \ RB_RIGHT(RB_PARENT(old, field), field) = elm;\ RB_AUGMENT(RB_PARENT(old, field)); \ } else \ RB_ROOT(head) = elm; \ RB_PARENT(RB_LEFT(old, field), field) = elm; \ if (RB_RIGHT(old, field)) \ RB_PARENT(RB_RIGHT(old, field), field) = elm; \ if (parent) { \ left = parent; \ do { \ RB_AUGMENT(left); \ } while ((left = RB_PARENT(left, field)) != NULL); \ } \ goto color; \ } \ parent = RB_PARENT(elm, field); \ color = RB_COLOR(elm, field); \ if (child) \ RB_PARENT(child, field) = parent; \ if (parent) { \ if (RB_LEFT(parent, field) == elm) \ RB_LEFT(parent, field) = child; \ else \ RB_RIGHT(parent, field) = child; \ RB_AUGMENT(parent); \ } else \ RB_ROOT(head) = child; \ color: \ if (color == RB_BLACK) \ name##_RB_REMOVE_COLOR(head, parent, child); \ return (old); \ } \ \ /* Inserts a node into the RB tree */ \ attr struct type * \ name##_RB_INSERT(struct name *head, struct type *elm) \ { \ struct type *tmp; \ struct type *parent = NULL; \ int comp = 0; \ tmp = RB_ROOT(head); \ while (tmp) { \ parent = tmp; \ comp = (cmp)(elm, parent); \ if (comp < 0) \ tmp = RB_LEFT(tmp, field); \ else if (comp > 0) \ tmp = RB_RIGHT(tmp, field); \ else \ return (tmp); \ } \ RB_SET(elm, parent, field); \ if (parent != NULL) { \ if (comp < 0) \ RB_LEFT(parent, field) = elm; \ else \ RB_RIGHT(parent, field) = elm; \ RB_AUGMENT(parent); \ } else \ RB_ROOT(head) = elm; \ name##_RB_INSERT_COLOR(head, elm); \ return (NULL); \ } \ \ /* Finds the node with the same key as elm */ \ attr struct type * \ name##_RB_FIND(struct name *head, struct type *elm) \ { \ struct type *tmp = RB_ROOT(head); \ int comp; \ while (tmp) { \ comp = cmp(elm, tmp); \ if (comp < 0) \ tmp = RB_LEFT(tmp, field); \ else if (comp > 0) \ tmp = RB_RIGHT(tmp, field); \ else \ return (tmp); \ } \ return (NULL); \ } \ \ /* Finds the first node greater than or equal to the search key */ \ attr struct type * \ name##_RB_NFIND(struct name *head, struct type *elm) \ { \ struct type *tmp = RB_ROOT(head); \ struct type *res = NULL; \ int comp; \ while (tmp) { \ comp = cmp(elm, tmp); \ if (comp < 0) { \ res = tmp; \ tmp = RB_LEFT(tmp, field); \ } \ else if (comp > 0) \ tmp = RB_RIGHT(tmp, field); \ else \ return (tmp); \ } \ return (res); \ } \ \ /* ARGSUSED */ \ attr struct type * \ name##_RB_NEXT(struct type *elm) \ { \ if (RB_RIGHT(elm, field)) { \ elm = RB_RIGHT(elm, field); \ while (RB_LEFT(elm, field)) \ elm = RB_LEFT(elm, field); \ } else { \ if (RB_PARENT(elm, field) && \ (elm == RB_LEFT(RB_PARENT(elm, field), field))) \ elm = RB_PARENT(elm, field); \ else { \ while (RB_PARENT(elm, field) && \ (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\ elm = RB_PARENT(elm, field); \ elm = RB_PARENT(elm, field); \ } \ } \ return (elm); \ } \ \ /* ARGSUSED */ \ attr struct type * \ name##_RB_PREV(struct type *elm) \ { \ if (RB_LEFT(elm, field)) { \ elm = RB_LEFT(elm, field); \ while (RB_RIGHT(elm, field)) \ elm = RB_RIGHT(elm, field); \ } else { \ if (RB_PARENT(elm, field) && \ (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \ elm = RB_PARENT(elm, field); \ else { \ while (RB_PARENT(elm, field) && \ (elm == RB_LEFT(RB_PARENT(elm, field), field)))\ elm = RB_PARENT(elm, field); \ elm = RB_PARENT(elm, field); \ } \ } \ return (elm); \ } \ \ attr struct type * \ name##_RB_MINMAX(struct name *head, int val) \ { \ struct type *tmp = RB_ROOT(head); \ struct type *parent = NULL; \ while (tmp) { \ parent = tmp; \ if (val < 0) \ tmp = RB_LEFT(tmp, field); \ else \ tmp = RB_RIGHT(tmp, field); \ } \ return (parent); \ } #define RB_NEGINF -1 #define RB_INF 1 #define RB_INSERT(name, x, y) name##_RB_INSERT(x, y) #define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y) #define RB_FIND(name, x, y) name##_RB_FIND(x, y) #define RB_NFIND(name, x, y) name##_RB_NFIND(x, y) #define RB_NEXT(name, x, y) name##_RB_NEXT(y) #define RB_PREV(name, x, y) name##_RB_PREV(y) #define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF) #define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF) #define RB_FOREACH(x, name, head) \ for ((x) = RB_MIN(name, head); \ (x) != NULL; \ (x) = name##_RB_NEXT(x)) #define RB_FOREACH_REVERSE(x, name, head) \ for ((x) = RB_MAX(name, head); \ (x) != NULL; \ (x) = name##_RB_PREV(x)) #endif /* _SYS_TREE_H_ */ bam-0.4.0/src/context.h0000644000175000017500000000235611430042030012771 0ustar kmakma#include struct CONTEXT; struct DEFERRED { struct DEFERRED *next; struct NODE *node; int (*run)(struct CONTEXT *context, struct DEFERRED *info); void *user; }; struct CONTEXT { struct HEAP *luaheap; struct lua_State *lua; const char *filename; const char *filename_short; char script_directory[512]; struct HEAP *graphheap; struct GRAPH *graph; struct CACHE *cache; struct NODE *defaulttarget; struct NODE *target; /* this heap is used for dependency lookups that has to happen after we parsed the whole file */ struct HEAP *deferredheap; struct DEFERRED *firstdeferred; time_t globaltimestamp; time_t buildtime; int exit_on_error; int num_commands; volatile int errorcode; volatile int current_cmd_num; }; const char *context_get_path(struct lua_State *L); struct CONTEXT *context_get_pointer(struct lua_State *L); int context_default_target(struct CONTEXT *context, struct NODE *node); int context_build_prepare(struct CONTEXT *context); int context_build_clean(struct CONTEXT *context); int context_build_make(struct CONTEXT *context); extern const char *CONTEXT_LUA_SCRIPTARGS_TABLE; extern const char *CONTEXT_LUA_TARGETS_TABLE; extern const char *CONTEXT_LUA_PATH; extern const char *CONTEXT_LUA_WORKPATH; bam-0.4.0/src/dep_cpp.c0000644000175000017500000001672411430042030012716 0ustar kmakma#include #include #include #define LUA_CORE /* make sure that we don't try to import these functions */ #include #include #include "path.h" #include "node.h" #include "cache.h" #include "context.h" #include "mem.h" #include "support.h" #include "session.h" #include "luafuncs.h" static int processline(char *line, char **start, char **end, int *systemheader) { const char *include_text = "include"; char *current = line; *start = 0; *end = 0; *systemheader = 0; /* search for # */ while(*current != '#') { if(*current == ' ' || *current == '\t') current++; /* next char */ else return 0; /* this catches \0 aswell */ } current++; /* skip # */ /* search for first character */ while(1) { if(*current == ' ' || *current == '\t') current++; else if(*current == 0) return 0; else break; } /* match "include" */ while(*include_text) { if(*current == *include_text) { current++; include_text++; } else return 0; } /* search for first character */ while(1) { if(*current == ' ' || *current == '\t') current++; else if(*current == 0) return 0; else break; } /* match starting < or " */ *start = current+1; if(*current == '<') *systemheader = 1; else if(*current == '"') *systemheader = 0; else return 0; /* skip < or " */ current++; /* search for < or " to end it */ while(1) { if(*current == '>' || *current == '"') break; else if(*current == 0) return 0; else current++; } *end = current; return 1; } struct CACHERUNINFO { struct CONTEXT *context; int (*callback)(struct NODE *, void *, const char *, int); void *userdata; }; static int dependency_cpp_run(struct CONTEXT *context, struct NODE *node, int (*callback)(struct NODE *, void *, const char *, int), void *userdata); static void cachehit_callback(struct NODE *node, struct CACHENODE *cachenode, void *user) { struct CACHERUNINFO *info = (struct CACHERUNINFO *)user; /* check if the file has been removed */ struct NODE *existing_node = node_find_byhash(node->graph, cachenode->hashid); if(existing_node) { struct NODE *newnode = node_add_dependency_withnode(node, existing_node); dependency_cpp_run(info->context, newnode, info->callback, info->userdata); } else { if(file_timestamp(cachenode->filename) == 0) node->dirty = NODEDIRTY_MISSING; else { struct NODE *newnode = node_add_dependency(node, cachenode->filename); dependency_cpp_run(info->context, newnode, info->callback, info->userdata); } } } /* dependency calculator for c/c++ preprocessor */ static int dependency_cpp_run(struct CONTEXT *context, struct NODE *node, int (*callback)(struct NODE *, void *, const char *, int), void *userdata) { char *linestart; char *includestart; char *includeend; int systemheader; int errorcode = 0; int linecount = 0; /* open file */ long filesize; long readitems; char *filebuf; char *filebufcur; char *filebufend; FILE *file; struct CACHERUNINFO cacheinfo; /* don't run depcheck twice */ if(node->depchecked) return 0; /* mark the node for caching */ node_cached(node); /* check if we have the dependencies in the cache frist */ cacheinfo.context = context; cacheinfo.callback = callback; cacheinfo.userdata = userdata; if(cache_do_dependency(context, node, cachehit_callback, &cacheinfo)) return 0; /* mark the node as checked */ node->depchecked = 1; file = fopen(node->filename, "rb"); if(!file) return 0; /* read the whole file */ fseek(file, 0, SEEK_END); filesize = ftell(file); fseek(file, 0, SEEK_SET); filebuf = malloc(filesize+1); /* +1 for null termination */ if(!filebuf) { printf("cpp-dep: error allocating %ld bytes\n", filesize); fclose(file); return 1; } /* read the file and close it */ readitems = fread(filebuf, 1, filesize, file); fclose(file); if(readitems != filesize) { printf("cpp-dep: error reading the complete file. %ld of %ld bytes read\n", readitems, filesize); free(filebuf); return 1; } filebufcur = filebuf; filebufend = filebuf+filesize; while(filebufcur < filebufend) { /* search for next line */ linestart = filebufcur; while(filebufcur != filebufend && *filebufcur != '\n' && *filebufcur != '\r') filebufcur++; *filebufcur = 0; filebufcur++; linecount++; if(processline(linestart, &includestart, &includeend, &systemheader)) { *includeend = 0; /* run callback */ errorcode = callback(node, userdata, includestart, systemheader); if(errorcode) break; } } /* clean up and return*/ free(filebuf); return errorcode; } struct CPPDEPINFO { struct CONTEXT *context; struct STRINGLIST *paths; }; /* */ static int dependency_cpp_callback(struct NODE *node, void *user, const char *filename, int sys) { struct CPPDEPINFO *depinfo = (struct CPPDEPINFO *)user; struct NODE *depnode; struct CPPDEPINFO recurseinfo; char buf[MAX_PATH_LENGTH]; int check_system = sys; int found = 0; if(!sys) { /* "normal.header" */ int flen = strlen(node->filename)-1; while(flen) { if(node->filename[flen] == '/') break; flen--; } path_join(node->filename, flen, filename, -1, buf, sizeof(buf)); if(file_exist(buf) || node_find(node->graph, buf)) found = 1; else { /* file does not exist */ check_system = 1; } } if(check_system) { /* */ if(path_isabs(filename)) { if(file_exist(filename) || node_find(node->graph, filename)) { strcpy(buf, filename); found = 1; } } else { struct STRINGLIST *cur; int flen = strlen(filename); for(cur = depinfo->paths; cur; cur = cur->next) { path_join(cur->str, cur->len, filename, flen, buf, sizeof(buf)); if(file_exist(buf) || node_find(node->graph, buf)) { found = 1; break; } } } } /* */ if(found) { path_normalize(buf); depnode = node_add_dependency(node, buf); if(!depnode) return 2; /* do the dependency walk */ if(!depnode->depchecked) { recurseinfo.paths = depinfo->paths; recurseinfo.context = depinfo->context; if(dependency_cpp_run(depinfo->context, depnode, dependency_cpp_callback, &recurseinfo) != 0) return 3; } } return 0; } static struct STRINGLIST *current_includepaths = NULL; static int dependency_cpp_do_run(struct CONTEXT *context, struct DEFERRED *info) { struct CPPDEPINFO depinfo; depinfo.context = context; depinfo.paths = (struct STRINGLIST *)info->user; if(dependency_cpp_run(context, info->node, dependency_cpp_callback, &depinfo) != 0) return -1; return 0; } /* */ int lf_add_dependency_cpp_set_paths(lua_State *L) { struct CONTEXT *context; int n = lua_gettop(L); if(n != 1) luaL_error(L, "add_dependency_cpp_set_paths: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TTABLE); context = context_get_pointer(L); current_includepaths = NULL; build_stringlist(L, context->deferredheap, ¤t_includepaths, 1); return 0; } /* */ int lf_add_dependency_cpp(lua_State *L) { struct CONTEXT *context; struct DEFERRED *deferred; int n = lua_gettop(L); if(n != 1) luaL_error(L, "add_dependency_cpp_set: incorrect number of arguments"); luaL_checkstring(L,1); context = context_get_pointer(L); deferred = (struct DEFERRED *)mem_allocate(context->deferredheap, sizeof(struct DEFERRED)); deferred->node = node_find(context->graph, lua_tostring(L,1)); deferred->user = current_includepaths; deferred->run = dependency_cpp_do_run; deferred->next = context->firstdeferred; context->firstdeferred = deferred; return 0; } bam-0.4.0/src/path.h0000644000175000017500000000227611430042030012242 0ustar kmakma/* max path length for bam */ #define MAX_PATH_LENGTH 1024 /* returns a pointer to the filename, /foo/bar.a -> bar.a */ extern const char *path_filename(const char *path); /* /foo/bar.a -> /foo */ extern int path_directory(const char *path, char *directory, int size); /* normalizes a path, rewrites the path */ extern int path_normalize(char *path); /* joins to paths together and normalizes them. returns 0 on success */ extern int path_join(const char *base, int base_len, const char *extend, int extend_len, char *output, int size); /* returns 1 if the path is absolute, else it returns 0 */ extern int path_isabs(const char *path); /* checks so that the path is nice */ /* no /.. /./ or // */ /* must begin with / (absolute) */ /* does not end with / */ extern int path_isnice(const char *path); /* */ struct lua_State; extern int lf_path_isnice(struct lua_State *L); extern int lf_path_isabs(struct lua_State *L); extern int lf_path_join(struct lua_State *L); extern int lf_path_normalize(struct lua_State *L); extern int lf_path_ext(struct lua_State *L); extern int lf_path_dir(struct lua_State *L); extern int lf_path_base(struct lua_State *L); extern int lf_path_filename(struct lua_State *L); bam-0.4.0/src/tools.lua0000644000175000017500000003175011430042030012777 0ustar kmakmafunction SetDefaultDrivers(settings) -- set default drivers if family == "windows" then SetDriversCL(settings) else SetDriversGCC(settings) end end --[[@GROUP Common Settings (settings) @END]]-- function SetCommonSettings(settings) settings.Copy = TableDeepCopy --[[@FUNCTION config_name Name of the settings. TODO: explain when you could use it @END]] settings.config_name = "" --[[@FUNCTION config_ext A short postfix that you can append to files that have been built by this configuration. @END]] settings.config_ext = "" --[[@FUNCTION labelprefix Prefix to use for all jobs that are added. TODO: this option feels a bit strange @END]] settings.labelprefix = "" -- TODO: what todo with these settings.debug = 1 settings.optimize = 0 end ------------------------ COMPILE ACTION ------------------------ --[[@GROUP Compile @END]]-- -- Compiles C, Obj-C and C++ files --[[@UNITTESTS err=1; find="expected a settings object": Compile(nil) err=1; find="compiler returned a nil": s = NewSettings(); s.mappings["c"] = function()end; Compile(s, "test.c") err=0 : s = NewSettings(); Compile(s) @END]]-- --[[@FUNCTION Compile(settings, ...) Compiles a set of files using the supplied settings. It uses ^settings.compile.mappings^ to map the input extension to a compiler function. A compiler functions should look like ^Compiler(settings, input)^ where ^settings^ is the settings object and ^input^ is the filename of the file to compile. The function should return a string that contains the object file that it will generate. {{{{ function MyCompiler(settings, input) \t-- compile stuff \treturn output end settings.compile.mappings[".my"] = MyCompiler objects = Compile(settings, "code.my") -- Invokes the MyCompiler function }}}} @END]]-- function Compile(settings, ...) CheckSettings(settings) local outputs = {} local mappings = settings.compile.mappings local insert = table.insert -- TODO: this here is aware of the different compilers, should be moved somewhere bam_add_dependency_cpp_set_paths(settings.cc.includes) settings.invoke_count = settings.invoke_count + 1 for inname in TableWalk({...}) do -- fetch correct compiler local ext = PathFileExt(inname) local Compiler = mappings[ext] if not Compiler then error("'"..inname.."' has unknown extention '"..ext.."' which there are no compiler for") end insert(outputs, Compiler(settings, inname)) end -- return the output return outputs end function CTestCompile(settings, code, options) return settings.cc.DriverCTest(code, options) end AddTool(function (settings) --[[@FUNCTION Compile Settings (settings.compile)
^mappings^ Table that matches extentions to a compiler function. See the Compile function for a reference how this table is used.
@END]] settings.compile = {} settings.compile.mappings = {} TableLock(settings.compile) end) ------------------------ C/C++ COMPILE ------------------------ --[[@FUNCTION C/C++ Settings (settings.cc) @PAUSE]] function DriverNull() error("no driver set") end function InitCommonCCompiler(settings) if settings.cc then return end settings.cc = {} settings.cc._c_cache = { nr = 0, str = "" } settings.cc._cxx_cache = { nr = 0, str = "" } --[[@RESUME @PAUSE]] settings.cc.defines = NewTable() --[[@RESUME @PAUSE]] settings.cc.DriverCTest = DriverNull --[[@RESUME @PAUSE]] settings.cc.DriverC = DriverNull --[[@RESUME @PAUSE]] settings.cc.DriverCXX = DriverNull --[[@RESUME @PAUSE]] settings.cc.exe_c = "" --[[@RESUME @PAUSE]] settings.cc.exe_cxx = "" --[[@RESUME @PAUSE]] settings.cc.extension = "" --[[@RESUME @PAUSE]] settings.cc.flags = NewFlagTable() --[[@RESUME @PAUSE]] settings.cc.flags_c = NewFlagTable() --[[@RESUME @PAUSE]] settings.cc.flags_cxx = NewFlagTable() --[[@RESUME @PAUSE]] settings.cc.frameworks = NewTable() --[[@RESUME @PAUSE]] settings.cc.includes = NewTable() --[[@RESUME @PAUSE]] settings.cc.Output = Default_Intermediate_Output --[[@RESUME @PAUSE]] settings.cc.systemincludes = NewTable() --[[@RESUME
^defines^ Table of defines that should be set when compiling. {{{{ settings.cc.defines:Add("ANSWER=42") }}}}
^DriverC^ Function that drives the C compiler. Function is responsible for building the command line and adding the job to compile the input file.
^DriverCXX^ Same as DriverC but for the C++ compiler.
^exe_c^Name (and path) of the executable that is the C compiler
^exe_cxx^Same as c_exe but for the C++ compiler
^extension^ Extention that the object files should have. Usally ".o" or ".obj" depending on compiler tool chain.
^flags^ Table of flags that will be appended to the command line to the C/C++ compiler. These flags are used for both the C and C++ compiler. {{{{ settings.cc.flags:Add("-O2", "-g") }}}}
^flags_c^ Same as flags but specific for the C compiler.
^flags_cxx^ Same as flags but specific for the C++ compiler.
^frameworks^ Mac OS X specific. What frameworks to use when compiling.
^includes^ Table of paths where to find headers. {{{{ settings.cc.includes:Add("my/include/directory") }}}}
^Output(settings, path)^ Function that should transform the input path into the output path. The appending of the extension is done automaticly. {{{{ settings.cc.Output = function(settings, input)     return PathBase(input) .. settings.config_ext end }}}}
^systemincludes^ Mac OS X specific. Table of paths where to find system headers.
@END]] TableLock(settings.cc) end function CompileC(settings, input) local cc = settings.cc local outname = cc.Output(settings, input) .. cc.extension cc.DriverC(settings.labelprefix .. "c " .. input, outname, input, settings) AddDependency(outname, input) bam_add_dependency_cpp(input) return outname end function CompileCXX(settings, input) local cc = settings.cc local outname = cc.Output(settings, input) .. cc.extension cc.DriverCXX(settings.labelprefix .. "c++ " .. input, outname, input, settings) AddDependency(outname, input) bam_add_dependency_cpp(input) return outname end AddTool(function (settings) InitCommonCCompiler(settings) settings.compile.mappings["c"] = CompileC settings.compile.mappings["m"] = CompileC end) AddTool(function (settings) InitCommonCCompiler(settings) settings.compile.mappings["cpp"] = CompileCXX settings.compile.mappings["cxx"] = CompileCXX settings.compile.mappings["c++"] = CompileCXX settings.compile.mappings["cc"] = CompileCXX end) --[[@GROUP Other @END]]-- --[[@FUNCTION CopyFile(dst, src) @END]]-- if family == "windows" then function CopyFile(dst, src) AddJob(dst, "copy " .. src .. " -> " .. dst, "copy /b " .. str_replace(src, "/", "\\") .. " " .. str_replace(dst, "/", "\\") .. " >nul 2>&1", src) SetTouch(dst) -- make sure to update timestamp return dst end else function CopyFile(dst, src) AddJob(dst, "copy " .. src .. " -> " .. dst, "cp " .. src .. " " .. dst, src) SetTouch(dst) return dst end end --[[@FUNCTION CopyToDirectory(dst, ...) @END]]-- function CopyToDirectory(dst, ...) for src in TableWalk({...}) do return CopyFile(PathJoin(dst, PathFilename(src)), src) end end ------------------------ LINK ------------------------ --[[@GROUP Link @END]]-- --[[@FUNCTION TODO @END]]-- function Link(settings, output, ...) CheckSettings(settings) local inputs = TableFlatten({...}) output = settings.link.Output(settings, output) .. settings.link.extension settings.link.Driver(settings.labelprefix .. "link " .. output, output, inputs, settings) -- all the files AddDependency(output, inputs) AddDependency(output, settings.link.extrafiles) -- add the libaries local libs = {} local paths = {} for index, inname in ipairs(settings.link.libs) do table.insert(libs, settings.lib.prefix .. inname .. settings.lib.extension) end for index, inname in ipairs(settings.link.libpath) do table.insert(paths, inname) end AddDependencySearch(output, paths, libs) return output end --[[@FUNCTION Settings (settings.link) @PAUSE]] AddTool(function (settings) settings.link = {} --[[@RESUME @PAUSE]] settings.link.Driver = DriverNull --[[@RESUME @PAUSE]] settings.link.exe = "" --[[@RESUME @PAUSE]] settings.link.extension = "" --[[@RESUME @PAUSE]] settings.link.extrafiles = NewTable() --[[@RESUME @PAUSE]] settings.link.flags = NewFlagTable() --[[@RESUME @PAUSE]] settings.link.frameworks = NewTable() --[[@RESUME @PAUSE]] settings.link.frameworkpath = NewTable() --[[@RESUME @PAUSE]] settings.link.libs = NewTable() --[[@RESUME @PAUSE]] settings.link.libpath = NewTable() --[[@RESUME @PAUSE]] settings.link.Output = Default_Intermediate_Output --[[@RESUME @PAUSE]] settings.link.inputflags = "" --[[@RESUME
^Driver^ Function that drives the linker. Function is responsible for building the command line and adding the job to link the input files into an executable.
^exe^ Path to the executable to use as linker.
^extension^ Extention of the executable. Usally "" on most platform but can be ".exe" on platforms like Windows.
^extrafiles^ A table of additional files that should be linked against. These files will be treated as normal objects when linking.
^flags^ Table of raw flags to send to the linker. {{{{ settings.link.flags:Add("-v") }}}}
^frameworks^ Mac OS X specific. A table of frameworks to link against.
^frameworkpath^ Mac OS X specific. A table of paths were to find frameworks.
^libs^ Table of library files to link with. {{{{ settings.link.libs:Add("pthread") }}}}
^libpath^ A table of paths of where to find library files that could be included in the linking process.
^Output^ Function that should transform the input path into the output path. The appending of the extension is done automaticly. {{{{ settings.link.Output = function(settings, input)     return PathBase(input) .. settings.config_ext end }}}}
inputflags (REMOVE?)
@END]] TableLock(settings.link) end) ------------------------ SHARED LIBRARY ACTION ------------------------ --[[@GROUP SharedLibrary @END]]-- AddTool(function (settings) settings.dll = {} settings.dll.Driver = DriverNull settings.dll.prefix = "" settings.dll.extension = "" settings.dll.Output = Default_Intermediate_Output settings.dll.exe = "" settings.dll.inputflags = "" settings.dll.flags = NewFlagTable() settings.dll.libs = NewTable() settings.dll.frameworks = NewTable() settings.dll.frameworkpath = NewTable() settings.dll.libpath = NewTable() settings.dll.extrafiles = NewTable() TableLock(settings.dll) end) --[[@node->hashid; struct NODETREELINK *leaf = NULL; if(linkhash == hashid) return link; leaf = link->leafs[linkhash < hashid]; if(!leaf) return link; link = leaf; } } static void nodelinktree_rotate_parentswap(struct NODETREELINK *link, struct NODETREELINK *child) { child->parent = link->parent; if(link->parent) { if(link->parent->leafs[0] == link) link->parent->leafs[0] = child; else link->parent->leafs[1] = child; } link->parent = child; } static void nodelinktree_rotate_depthcalc(struct NODETREELINK *link, struct NODETREELINK *child) { int depth; link->depth = 1; if(link->leafs[0]) link->depth = link->leafs[0]->depth+1; if(link->leafs[1] && link->depth > link->leafs[1]->depth+1) link->depth = link->leafs[1]->depth+1; depth = child->depth; for(link = child; link; link = link->parent) { link->depth = depth; depth++; } } static struct NODETREELINK *nodelinktree_rotate_right(struct NODETREELINK *link) { struct NODETREELINK *child = link->leafs[0]; nodelinktree_rotate_parentswap(link, child); link->leafs[0] = child->leafs[1]; child->leafs[1] = link; if(link->leafs[0]) link->leafs[0]->parent = link; /* redo depth */ nodelinktree_rotate_depthcalc(link, child); return child; } static struct NODETREELINK *nodelinktree_rotate_left(struct NODETREELINK *link) { struct NODETREELINK *child = link->leafs[1]; nodelinktree_rotate_parentswap(link, child); link->leafs[1] = child->leafs[0]; child->leafs[0] = link; if(link->leafs[1]) link->leafs[1]->parent = link; /* redo depth */ nodelinktree_rotate_depthcalc(link, child); return child; } /* link should be a link at the bottom of the tree */ static struct NODETREELINK *nodelinktree_rebalance(struct NODETREELINK *link) { /* rebalance the tree */ int direction; for(;; link = link->parent) { direction = 0; if(link->leafs[0]) direction += link->leafs[0]->depth; if(link->leafs[1]) direction -= link->leafs[1]->depth; if(direction < -1) link = nodelinktree_rotate_left(link); else if(direction > 1) link = nodelinktree_rotate_right(link); if(link->parent == NULL) return link; } } static void nodelinktree_insert(struct NODETREELINK **root, struct NODETREELINK *parentlink, struct NODE *node) { struct NODETREELINK *newlink = (struct NODETREELINK *)mem_allocate(node->graph->heap, sizeof(struct NODETREELINK)); newlink->node = node; newlink->depth = 1; /* first node special case */ if(!*root) { *root = newlink; newlink->parent = NULL; return; } newlink->parent = parentlink; if(node->hashid > parentlink->node->hashid) parentlink->leafs[1] = newlink; else parentlink->leafs[0] = newlink; /* early exit if we didn't make the tree any deeper */ if(newlink->parent->depth >= 2) return; /* calculate new depth */ { struct NODETREELINK *link; int depth = 2; for(link = newlink->parent; link; link = link->parent) { if(link->depth == depth) break; link->depth = depth; depth++; } } /* rebalance the tree */ *root = nodelinktree_rebalance(newlink); } bam-0.4.0/src/cache.h0000644000175000017500000000075411430042030012350 0ustar kmakmastruct GRAPH; struct CACHE; struct CONTEXT; struct NODE; /* cache */ int cache_save(const char *filename, struct GRAPH *graph); struct CACHE *cache_load(const char *filename); struct CACHENODE *cache_find_byhash(struct CACHE *cache, unsigned hashid); struct CACHENODE *cache_find_byindex(struct CACHE *cache, unsigned index); int cache_do_dependency( struct CONTEXT *context, struct NODE *node, void (*callback)(struct NODE *node, struct CACHENODE *cachenode, void *user), void *user); bam-0.4.0/src/mem.c0000644000175000017500000000476611430042030012065 0ustar kmakma#include #include /* memset */ #include "mem.h" struct CHUNK { char *memory; char *current; char *end; struct CHUNK *next; }; struct HEAP { struct CHUNK *current; }; /* how large each chunk should be */ static const int default_chunksize = 1024*16; /* allocates a new chunk to be used */ static struct CHUNK *mem_newchunk(int chunksize) { struct CHUNK *chunk; char *mem; /* allocate memory */ mem = malloc(sizeof(struct CHUNK)+chunksize); if(!mem) return 0x0; memset(mem, 0, sizeof(struct CHUNK)+chunksize); /* the chunk structure is located in the begining of the chunk */ /* init it and return the chunk */ chunk = (struct CHUNK*)mem; chunk->memory = (char*)(chunk+1); chunk->current = chunk->memory; chunk->end = chunk->memory + chunksize; chunk->next = (struct CHUNK *)0x0; return chunk; } /******************/ static void *mem_allocate_from_chunk(struct CHUNK *chunk, int size) { char *mem; /* check if we need can fit the allocation */ if(chunk->current + size > chunk->end) return (void*)0x0; /* get memory and move the pointer forward */ mem = chunk->current; chunk->current += size; return mem; } /* creates a heap */ struct HEAP *mem_create() { struct CHUNK *chunk; struct HEAP *heap; /* allocate a chunk and allocate the heap structure on that chunk */ chunk = mem_newchunk(default_chunksize); heap = (struct HEAP *)mem_allocate_from_chunk(chunk, sizeof(struct HEAP)); heap->current = chunk; return heap; } /* destroys the heap */ void mem_destroy(struct HEAP *heap) { struct CHUNK *chunk = heap->current; struct CHUNK *next; while(chunk) { next = chunk->next; free(chunk); chunk = next; } } /* */ void *mem_allocate(struct HEAP *heap, int size) { char *mem; /* align the size to the size of a pointer */ size = (size+sizeof(void*)-1)&(~(sizeof(void*)-1)); /* try to allocate from current chunk */ mem = (char *)mem_allocate_from_chunk(heap->current, size); if(!mem) { if(size > default_chunksize/2) { /* this block is kinda big, allocate it's own chunk */ struct CHUNK *chunk = mem_newchunk(size); chunk->next = heap->current->next; heap->current->next = chunk; mem = (char *)mem_allocate_from_chunk(chunk, size); } else { /* allocate new chunk and add it to the heap */ struct CHUNK *chunk = mem_newchunk(default_chunksize); chunk->next = heap->current; heap->current = chunk; /* try to allocate again */ mem = (char *)mem_allocate_from_chunk(heap->current, size); } } return mem; } bam-0.4.0/src/cache.c0000644000175000017500000002073011430042030012337 0ustar kmakma#include /* memset */ #include /* malloc */ #include /* printf */ #include "cache.h" #include "context.h" #include "node.h" #include "platform.h" #include "session.h" #include "support.h" /* buffer sizes */ #define WRITE_BUFFERSIZE (32*1024) #define WRITE_BUFFERNODES (WRITE_BUFFERSIZE/sizeof(struct CACHENODE)) #define WRITE_BUFFERDEPS (WRITE_BUFFERSIZE/sizeof(unsigned)) /* header info */ static char bamheader[8] = { 'B','A','M',0, /* signature */ sizeof(void*), /* pointer size */ 0,0,0 /* version hash */ }; static void cache_setup_header() { /* save a hashed version of the date and time in the header */ unsigned hash = string_hash(__DATE__ __TIME__); bamheader[5] = hash&0xff; bamheader[6] = (hash>>8)&0xff; bamheader[7] = (hash>>16)&0xff; } /* detect if we can use unix styled io. we do this because fwrite can use it's own buffers and bam already to it's buffering nicely so this will reduce the number of syscalls needed. */ #ifdef BAM_FAMILY_UNIX #include #if defined(O_RDONLY) && defined(O_WRONLY) && defined(O_CREAT) && defined(O_TRUNC) #define USE_UNIX_IO #endif #endif /* setup io */ #ifdef USE_UNIX_IO #include #include #include #define IO_HANDLE int #define io_open_read(filename) open(filename, O_RDONLY) #define io_open_write(filename) open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666) #define io_valid(f) ((f) != -1) #define io_close(f) close(f) #define io_read(f, data, size) read(f, data, size) #define io_write(f, data, size) write(f, data, size) size_t io_size(IO_HANDLE f) { struct stat s; if(!fstat(f, &s)) return s.st_size; else { perror("fstat"); return 0; } } #else #include /* FILE, f* */ #define IO_HANDLE FILE* #define io_open_read(filename) fopen(filename, "rb") #define io_open_write(filename) fopen(filename, "wb") #define io_valid(f) (f) #define io_close(f) fclose(f) #define io_read(f, data, size) fread(data, 1, size, f) #define io_write(f, data, size) fwrite(data, 1, size, f) size_t io_size(IO_HANDLE f) { long current, end; current = ftell(f); fseek(f, 0, SEEK_END); end = ftell(f); fseek(f, current, SEEK_SET); return end; } #endif static int cachenode_cmp(struct CACHENODE *a, struct CACHENODE *b) { if(a->hashid > b->hashid) return 1; if(a->hashid < b->hashid) return -1; return 0; } RB_HEAD(CACHENODERB, CACHENODE); RB_GENERATE_INTERNAL(CACHENODERB, CACHENODE, rbentry, cachenode_cmp, static) void CACHENODE_FUNCTIONREMOVER() /* this is just to get it not to complain about unused static functions */ { (void)CACHENODERB_RB_REMOVE; (void)CACHENODERB_RB_NFIND; (void)CACHENODERB_RB_MINMAX; (void)CACHENODERB_RB_NEXT; (void)CACHENODERB_RB_PREV; } struct CACHE { char header[sizeof(bamheader)]; unsigned num_nodes; unsigned num_deps; struct CACHENODERB nodetree; struct CACHENODE *nodes; unsigned *deps; char *strings; }; struct WRITEINFO { IO_HANDLE fp; struct GRAPH *graph; union { struct CACHENODE nodes[WRITE_BUFFERNODES]; unsigned deps[WRITE_BUFFERDEPS]; char strings[WRITE_BUFFERSIZE]; } buffers; /* index into nodes or deps */ unsigned index; }; static int write_header(struct WRITEINFO *info) { /* setup the cache */ struct CACHE cache; memset(&cache, 0, sizeof(struct CACHE)); memcpy(cache.header, bamheader, sizeof(cache.header)); cache.num_nodes = info->graph->num_nodes; cache.num_deps = info->graph->num_deps; if(io_write(info->fp, &cache, sizeof(cache)) != sizeof(cache)) return -1; return 0; } static int write_flush(struct WRITEINFO *info, int elementsize) { int size = elementsize*info->index; if(io_write(info->fp, info->buffers.nodes, size) != size) return -1; info->index = 0; return 0; } static int write_nodes(struct WRITEINFO *info) { unsigned dep_index; unsigned string_index; struct NODE *node; struct GRAPH *graph = info->graph; /* write the cache nodes */ dep_index = 0; string_index = 0; for(node = graph->first; node; node = node->next) { /* fetch cache node */ struct CACHENODE *cachenode = &info->buffers.nodes[info->index++]; /* count dependencies */ struct NODELINK *dep; memset(cachenode, 0, sizeof(struct CACHENODE)); cachenode->deps_num = 0; for(dep = node->firstdep; dep; dep = dep->next) cachenode->deps_num++; cachenode->hashid = node->hashid; cachenode->cmdhash = node->cachehash; cachenode->cached = node->cached; cachenode->timestamp_raw = node->timestamp_raw; cachenode->deps = (unsigned*)((long)dep_index); cachenode->filename = (char*)((long)string_index); string_index += node->filename_len; dep_index += cachenode->deps_num; if(info->index == WRITE_BUFFERNODES && write_flush(info, sizeof(struct CACHENODE))) return -1; } /* flush the remainder */ if(info->index && write_flush(info, sizeof(struct CACHENODE))) return -1; /* write the cache nodes deps */ for(node = graph->first; node; node = node->next) { struct NODELINK *dep; for(dep = node->firstdep; dep; dep = dep->next) { info->buffers.deps[info->index++] = dep->node->id; if(info->index == WRITE_BUFFERDEPS && write_flush(info, sizeof(unsigned))) return -1; } } /* flush the remainder */ if(info->index && write_flush(info, sizeof(unsigned))) return -1; /* write the strings */ for(node = graph->first; node; node = node->next) { if(info->index+node->filename_len > sizeof(info->buffers.strings)) { if(write_flush(info, sizeof(char))) return -1; } memcpy(info->buffers.strings + info->index, node->filename, node->filename_len); info->index += node->filename_len; } /* flush the remainder */ if(info->index && write_flush(info, sizeof(char))) return -1; return 0; } int cache_save(const char *filename, struct GRAPH *graph) { struct WRITEINFO info; info.index = 0; info.graph = graph; info.fp = io_open_write(filename); if(!io_valid(info.fp)) return -1; cache_setup_header(); if(write_header(&info) || write_nodes(&info)) { /* error occured, trunc the cache file so we don't leave a corrupted file */ io_close(info.fp); io_close(io_open_write(filename)); return -1; } /* close up and return */ io_close(info.fp); return 0; } struct CACHE *cache_load(const char *filename) { unsigned long filesize; void *buffer; struct CACHE *cache; unsigned i; size_t bytesread; IO_HANDLE fp; /* open file */ fp = io_open_read(filename); if(!io_valid(fp)) return 0; /* read the whole file */ filesize = io_size(fp); buffer = malloc(filesize); bytesread = io_read(fp, buffer, filesize); io_close(fp); cache_setup_header(); /* verify read and headers */ cache = (struct CACHE *)buffer; if( bytesread != filesize || filesize < sizeof(struct CACHE) || memcmp(cache->header, bamheader, sizeof(bamheader)) != 0 || filesize < sizeof(struct CACHE)+cache->num_nodes*sizeof(struct CACHENODE)) { printf("%s: warning: cache file is invalid, generating new one\n", session.name); free(buffer); return 0; } /* setup pointers */ cache->nodes = (struct CACHENODE *)(cache+1); cache->deps = (unsigned *)(cache->nodes+cache->num_nodes); cache->strings = (char *)(cache->deps+cache->num_deps); /* build node tree and patch pointers */ for(i = 0; i < cache->num_nodes; i++) { cache->nodes[i].filename = cache->strings + (long)cache->nodes[i].filename; cache->nodes[i].deps = cache->deps + (long)cache->nodes[i].deps; RB_INSERT(CACHENODERB, &cache->nodetree, &cache->nodes[i]); } /* done */ return cache; } struct CACHENODE *cache_find_byindex(struct CACHE *cache, unsigned index) { return &cache->nodes[index]; } struct CACHENODE *cache_find_byhash(struct CACHE *cache, unsigned hashid) { struct CACHENODE tempnode; if(!cache) return NULL; tempnode.hashid = hashid; return RB_FIND(CACHENODERB, &cache->nodetree, &tempnode); } int cache_do_dependency( struct CONTEXT *context, struct NODE *node, void (*callback)(struct NODE *node, struct CACHENODE *cachenode, void *user), void *user) { struct CACHENODE *cachenode; struct CACHENODE *depcachenode; int i; /* search the cache */ cachenode = cache_find_byhash(context->cache, node->hashid); if(cachenode && cachenode->cached && cachenode->timestamp_raw == node->timestamp_raw) { if(node->depchecked) return 1; node->depchecked = 1; /* use cached version */ for(i = cachenode->deps_num-1; i >= 0; i--) { depcachenode = cache_find_byindex(context->cache, cachenode->deps[i]); if(depcachenode->cached) callback(node, depcachenode, user); } return 1; } return 0; } bam-0.4.0/src/tools/0000755000175000017500000000000011430042030012266 5ustar kmakmabam-0.4.0/src/tools/txt2c0000755000175000017500000002110611430042030013260 0ustar kmakmaELF>@@x@8 @@@@@@88@8@@@ ``8H @@`@`TT@T@DDPtd, , @, @$$QtdRtd``/lib64/ld-linux-x86-64.so.2GNUGNUyn-% 9P - %F94?__gmon_start__libc.so.6fopenputsputcharprintffeoffgetcfclose__libc_start_mainGLIBC_2.2.5ui X````` `(`0`8` HZH5z %| @%z h%r h%j h%b h%Z h%R h%J h%B hp1I^HHPTIp@H@H@HH HtHÐUHSH= uK0`H H(`HHH9s$fDHH (`H H9r H[fff.UH=o HtHt8`ÐUHH0}HuE` @o @q @x @n @d jE @UHǸ' @EHHHEHHH7HEHEHDEHEHEtHEHE @E= @UHǸEE}u @HǸ눋E;E> @HǸjE,EHHHEH @UHHǸ9EE;E|̿& @3Ðfffff.Hl$Ld$H- L%| Ll$Lt$L|$H\$H8L)AIHIHt1@LLDAHH9rH\$Hl$Ld$Ll$ Lt$(L|$0H8ÐUHSHH Ht`DHHHuH[ÐHHtypedef struct{ const char *filename; const char *content;} INTERNALFILE;const char internal_file_%d[] = {r0};0x%x, INTERNALFILE internal_files[] = {{"%s", internal_file_%d }, {0}};; <D\TtzRx tAC <$TQ_@F X@ H @@o@@@ d `@@ o`@ooL@@`@@@@@@@@GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3.symtab.strtab.shstrtab.interp.note.ABI-tag.note.gnu.build-id.gnu.hash.dynsym.dynstr.gnu.version.gnu.version_r.rela.dyn.rela.plt.init.text.fini.rodata.eh_frame_hdr.eh_frame.ctors.dtors.jcr.dynamic.got.got.plt.data.bss.comment8@8#T@T 1t@t$H@<Do@N @V@d^oL@Lko`@` z@@ X@Xp@p@HH @H X @X , @, $P @P |`(`(8`8@`@``X@`@P`P0P#s8/ f8@T@t@@@@@L@ `@ @ @ X@ p@@H @X @, @P @`(`8`@```@`P`,@`*(`88`EP@[P`jX`x@ ` @8` @```@`  @`+p@;@B Q ewH @}X @@`H`0` @P`);``@TP`[@` X@call_gmon_startcrtstuff.c__CTOR_LIST____DTOR_LIST____JCR_LIST____do_global_dtors_auxcompleted.7382dtor_idx.7384frame_dummy__CTOR_END____FRAME_END____JCR_END____do_global_ctors_auxtxt2c.c_GLOBAL_OFFSET_TABLE___init_array_end__init_array_start_DYNAMICdata_startprintf@@GLIBC_2.2.5__libc_csu_fini_start__gmon_start___Jv_RegisterClassesputs@@GLIBC_2.2.5_finiputchar@@GLIBC_2.2.5fopen@@GLIBC_2.2.5__libc_start_main@@GLIBC_2.2.5_IO_stdin_used__data_startfgetc@@GLIBC_2.2.5__dso_handle__DTOR_END____libc_csu_init__bss_startfeof@@GLIBC_2.2.5_endfclose@@GLIBC_2.2.5_edatamain_initbam-0.4.0/src/tools/txt2c.c0000644000175000017500000000147511430042030013505 0ustar kmakma/* Small utility that reads from stdin and outputs an C table with the data to stdout. */ #include int main(int argc, char **argv) { int c, f; int i = 0; FILE *input; printf("typedef struct\n"); printf("{\n"); printf("\tconst char *filename;\n"); printf("\tconst char *content;\n"); printf("} INTERNALFILE;\n"); printf("\n"); for(f = 1; f < argc; f++) { printf("const char internal_file_%d[] = {", f); input = fopen(argv[f], "r"); while(1) { c = fgetc(input); if(feof(input)) break; printf("0x%x, ", c); i = (i+1)&0xf; if(i == 0) printf("\n\t"); } fclose(input); printf("0};\n"); } printf("INTERNALFILE internal_files[] = {"); for(f = 1; f < argc; f++) { printf("{\"%s\", internal_file_%d },\n", argv[f], f); } printf("{0}};\n"); return 0; } bam-0.4.0/src/tools/txt2c.o0000644000175000017500000001645011430042030013520 0ustar kmakmaELF> @@UHH0}HuE EUHǸEHHHEHHHHEHEHEHEHtHEHE=UHǸEE}uHǸ눋E;E>HǸE,EHHHEHUHHǸEE;E|̿% : ; I$ > $ > $ >   I : ;  : ;I8 : ; : ; I8 I !I/ .? : ; ' I@: ; I 4: ; I 4: ; I \8intii1-o b# # # # # #( #0 #8 #@ #H #P  #X "#` $#h &b#p *b#t ,p#x 0F# 1T# 2# 6# ?{# H# I# J# K# L-# Nb# P#  # # b#v  o  bSbLS@c blf bhi bd YX src/tools/usr/lib/gcc/x86_64-linux-gnu/4.4.3/include/usr/include/bits/usr/includetxt2c.cstddef.htypes.hstdio.hlibio.h vg &y n fgg!r."(Ytypedef struct{ const char *filename; const char *content;} INTERNALFILE;const char internal_file_%d[] = {r0};0x%x, INTERNALFILE internal_files[] = {{"%s", internal_file_%d }, {0}};wwv`main,_IO_buf_end_old_offset_offset_IO_save_endshort intsize_tinput/home/kma/code/bam_IO_write_ptr_flags_IO_buf_base_markers_IO_read_end_locklong int_cur_column_posargv_sbuf_IO_FILEunsigned charargcsigned charunsigned int_IO_marker_shortbuf_IO_write_base_unused2_IO_read_ptrshort unsigned intcharmain_next__pad1__pad2__pad3__pad4__pad5long unsigned int_IO_write_end__off64_t__off_t_chain_IO_backup_base_flags2_mode_IO_read_base_vtable_offset_IO_save_baseGNU C 4.4.3_filenoFILE_IO_lock_tsrc/tools/txt2c.cGCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3zRx AC .symtab.strtab.shstrtab.rela.text.data.bss.debug_abbrev.rela.debug_info.rela.debug_line.rodata.debug_loc.rela.debug_pubnames.rela.debug_aranges.debug_str.comment.note.GNU-stack.rela.eh_frame @(&,1D`?UPaiLyt #000S'0z $  8 @ :    "(.3txt2c.cmainputsputcharprintffopenfgetcfeoffclose ! &+ 05 (:? >DN_ Pqv r t x ! .L _p u    D!) . 7; oB I )P W ^ -l q |  <  e    W   l( 7 F U d ys          L S Z/ a? hO _ p w  F   A   E >   bam-0.4.0/src/node.c0000644000175000017500000003512311430042030012223 0ustar kmakma#include #include #include #include #include "node.h" #include "mem.h" #include "support.h" #include "path.h" #include "context.h" #include "session.h" #include "nodelinktree.inl" /* */ struct GRAPH *node_create_graph(struct HEAP *heap) { /* allocate graph structure */ struct GRAPH *graph = (struct GRAPH*)mem_allocate(heap, sizeof(struct GRAPH)); if(!graph) return (struct GRAPH *)0x0; memset(graph, 0, sizeof(struct GRAPH)); /* init */ graph->heap = heap; return graph; } /* creates a node */ int node_create(struct NODE **nodeptr, struct GRAPH *graph, const char *filename, const char *label, const char *cmdline) { struct NODE *node; struct NODETREELINK *link; int sn; unsigned hashid = string_hash(filename); /* check arguments */ if(!path_isnice(filename)) { printf("%s: error: adding non nice path '%s'. this causes problems with dependency lookups\n", session.name, filename); return NODECREATE_NOTNICE; } if(cmdline && !label) { printf("%s: error: adding job '%s' with command but no label\n", session.name, filename); return NODECREATE_INVALID_ARG; } else if(!cmdline && label) { printf("%s: error: adding job '%s' with label but no command\n", session.name, filename); return NODECREATE_INVALID_ARG; } /* zero out the return pointer */ *nodeptr = (struct NODE *)0x0; /* search for the node */ link = nodelinktree_find_closest(graph->nodehash[hashid&0xffff], hashid); if(link && link->node->hashid == hashid) { /* we are allowed to create a new node from a node that doesn't have a job assigned to it*/ if(link->node->cmdline || cmdline == NULL) return NODECREATE_EXISTS; node = link->node; } else { /* allocate and set pointers */ node = (struct NODE *)mem_allocate(graph->heap, sizeof(struct NODE)); node->graph = graph; node->id = graph->num_nodes++; node->timestamp_raw = file_timestamp(filename); node->timestamp = node->timestamp_raw; if(node->timestamp_raw == 0) node->dirty = NODEDIRTY_MISSING; /* set filename */ node->filename_len = strlen(filename)+1; node->filename = (char *)mem_allocate(graph->heap, node->filename_len); memcpy(node->filename, filename, node->filename_len); node->hashid = string_hash(filename); /* add to hashed tree */ nodelinktree_insert(&graph->nodehash[node->hashid&0xffff], link, node); /* add to list */ if(graph->last) graph->last->next = node; else graph->first = node; graph->last = node; } /* set command and label */ if(cmdline) { sn = strlen(cmdline)+1; node->cmdline = (char *)mem_allocate(graph->heap, sn); memcpy(node->cmdline, cmdline, sn); node->cmdhash = string_hash(cmdline); node->cachehash = node->cmdhash; /* set label */ sn = strlen(label)+1; node->label = (char *)mem_allocate(graph->heap, sn); memcpy(node->label, label, sn); } /* return new node */ *nodeptr = node; return NODECREATE_OK; } /* finds a node based apun the filename */ struct NODE *node_find_byhash(struct GRAPH *graph, unsigned int hashid) { struct NODETREELINK *link; link = nodelinktree_find_closest(graph->nodehash[hashid&0xffff], hashid); if(link && link->node->hashid == hashid) return link->node; return NULL; } struct NODE *node_find(struct GRAPH *graph, const char *filename) { return node_find_byhash(graph, string_hash(filename)); } /* this will return the existing node or create a new one */ struct NODE *node_get(struct GRAPH *graph, const char *filename) { struct NODE *node = node_find(graph, filename); if(!node) { if(node_create(&node, graph, filename, 0, 0) == NODECREATE_OK) return node; } return node; } struct NODE *node_add_dependency_withnode(struct NODE *node, struct NODE *depnode) { struct NODELINK *dep; struct NODELINK *parent; struct NODETREELINK *treelink; /* make sure that the node doesn't try to depend on it self */ if(depnode == node) { if(node->cmdline) { printf("error: node '%s' is depended on itself and is produced by a job\n", node->filename); return (struct NODE*)0x0; } return node; } /* check if we are already dependent on this node */ treelink = nodelinktree_find_closest(node->deproot, depnode->hashid); if(treelink != NULL && treelink->node->hashid == depnode->hashid) return depnode; /* create and add dependency link */ dep = (struct NODELINK *)mem_allocate(node->graph->heap, sizeof(struct NODELINK)); dep->node = depnode; dep->next = node->firstdep; node->firstdep = dep; nodelinktree_insert(&node->deproot, treelink, depnode); /* create and add parent link */ parent = (struct NODELINK *)mem_allocate(node->graph->heap, sizeof(struct NODELINK)); parent->node = node; parent->next = depnode->firstparent; depnode->firstparent = parent; /* increase dep counter */ node->graph->num_deps++; /* return the dependency */ return depnode; } struct NODE *node_add_job_dependency_withnode(struct NODE *node, struct NODE *depnode) { struct NODELINK *dep; struct NODETREELINK *treelink; /* make sure that the node doesn't try to depend on it self */ if(depnode == node) { if(node->cmdline) { printf("error: node '%s' is depended on itself and is produced by a job\n", node->filename); return (struct NODE*)0x0; } return node; } /* check if we are already dependent on this node */ treelink = nodelinktree_find_closest(node->jobdeproot, depnode->hashid); if(treelink != NULL && treelink->node->hashid == depnode->hashid) return depnode; /* create and add job dependency link */ dep = (struct NODELINK *)mem_allocate(node->graph->heap, sizeof(struct NODELINK)); dep->node = depnode; dep->next = node->firstjobdep; node->firstjobdep = dep; nodelinktree_insert(&node->jobdeproot, treelink, depnode); return depnode; } /* adds a dependency to a node */ struct NODE *node_add_dependency(struct NODE *node, const char *filename) { struct NODE *depnode = node_get(node->graph, filename); if(!depnode) return NULL; return node_add_dependency_withnode(node, depnode); } static struct NODE *node_add_constraint(struct NODELINK **first, struct NODE *node, const char *filename) { struct NODE *contraint = node_get(node->graph, filename); struct NODELINK *link = (struct NODELINK *)mem_allocate(node->graph->heap, sizeof(struct NODELINK)); link->node = contraint; link->next = *first; *first = link; return contraint; } struct NODE *node_add_constraint_shared(struct NODE *node, const char *filename) { return node_add_constraint(&node->constraint_shared, node, filename); } struct NODE *node_add_constraint_exclusive(struct NODE *node, const char *filename) { return node_add_constraint(&node->constraint_exclusive, node, filename); } void node_cached(struct NODE *node) { node->cached = 1; } void node_set_pseudo(struct NODE *node) { node->timestamp = 1; node->timestamp_raw = 1; } /* functions to handle with bit array access */ static unsigned char *bitarray_allocate(int size) { return (unsigned char *)malloc((size+7)/8); } static void bitarray_zeroall(unsigned char *a, int size) { memset(a, 0, (size+7)/8); } static void bitarray_free(unsigned char *a) { free(a); } static int bitarray_value(unsigned char *a, int id) { return a[id>>3]&(1<<(id&0x7)); } static void bitarray_set(unsigned char *a, int id) { a[id>>3] |= (1<<(id&0x7)); } static void bitarray_clear(unsigned char *a, int id) { a[id>>3] &= ~(1<<(id&0x7)); } /* ************* */ static int node_walk_r( struct NODEWALK *walk, struct NODE *node) { /* we should detect changes here before we run */ struct NODELINK *dep; struct NODEWALKPATH path; int result = 0; int flags = walk->flags; /* check and set mark */ if(bitarray_value(walk->mark, node->id)) return 0; bitarray_set(walk->mark, node->id); if(flags&NODEWALK_UNDONE) { if(node->workstatus != NODESTATUS_UNDONE) return 0; } if(flags&NODEWALK_TOPDOWN) { walk->node = node; result = walk->callback(walk); } /* push parent */ path.node = node; path.parent = walk->parent; walk->parent = &path; walk->depth++; /* build all dependencies */ dep = node->firstdep; if(flags&NODEWALK_JOBS) dep = node->firstjobdep; for(; dep; dep = dep->next) { result = node_walk_r(walk, dep->node); if(result) break; } /* pop parent */ walk->depth--; walk->parent = walk->parent->parent; /* unmark the node so we can walk this tree again if needed */ if(!(flags&NODEWALK_QUICK)) bitarray_clear(walk->mark, node->id); /* return if we have an error */ if(result) return result; /* check if we need to rebuild this node */ if(!(flags&NODEWALK_FORCE) && !node->dirty) return 0; /* build */ if(flags&NODEWALK_BOTTOMUP) { walk->node = node; result = walk->callback(walk); } return result; } /* walks through all the active nodes that needs a recheck */ static int node_walk_do_revisits(struct NODEWALK *walk) { int result; struct NODE *node; /* no parent or depth info is available */ walk->parent = NULL; walk->depth = 0; walk->revisiting = 1; while(walk->firstrevisit) { /* pop from the list */ node = walk->firstrevisit->node; walk->firstrevisit->node = NULL; walk->firstrevisit = walk->firstrevisit->next; /* issue the call */ walk->node = node; result = walk->callback(walk); if(result) return result; } /* return success */ return 0; } int node_walk( struct NODE *node, int flags, int (*callback)(struct NODEWALK*), void *u) { struct NODEWALK walk; int result; /* set walk parameters */ walk.depth = 0; walk.flags = flags; walk.callback = callback; walk.user = u; walk.parent = 0; walk.revisiting = 0; walk.firstrevisit = NULL; walk.revisits = NULL; /* allocate and clear mark and sweep array */ walk.mark = bitarray_allocate(node->graph->num_nodes); bitarray_zeroall(walk.mark, node->graph->num_nodes); /* allocate memory for activation */ if(flags&NODEWALK_REVISIT) { walk.revisits = malloc(sizeof(struct NODEWALKREVISIT)*node->graph->num_nodes); memset(walk.revisits, 0, sizeof(struct NODEWALKREVISIT)*node->graph->num_nodes); } /* do the walk */ result = node_walk_r(&walk, node); /* do the walk of all active elements, if we don't have an error */ if(flags&NODEWALK_REVISIT && !result) { node_walk_do_revisits(&walk); free(walk.revisits); } /* free the array and return */ bitarray_free(walk.mark); return result; } void node_walk_revisit(struct NODEWALK *walk, struct NODE *node) { struct NODEWALKREVISIT *revisit = &walk->revisits[node->id]; /* check if node already marked for revisit */ if(revisit->node) return; /* no need to revisit the node if there is a visit to be done for it */ /* TODO: the necessarily of this check is unknown. should check some larger builds to see if it helps any substantial amount. */ if(!walk->revisiting && !bitarray_value(walk->mark, node->id)) return; /* insert the node to the nodes to revisit */ revisit->node = node; revisit->next = walk->firstrevisit; walk->firstrevisit = revisit; } void node_debug_dump(struct GRAPH *graph) { struct NODE *node = graph->first; struct NODELINK *link; for(;node;node = node->next) { printf("%s\n", node->filename); for(link = node->firstdep; link; link = link->next) printf(" DEPEND %s\n", link->node->filename); } } /* dumps all nodes to the stdout */ void node_debug_dump_detailed(struct GRAPH *graph) { struct NODE *node = graph->first; struct NODELINK *link; const char *tool; for(;node;node = node->next) { static const char *dirtyflag[] = {"--", "MI", "CH", "DD", "DN", "GS"}; tool = "***"; if(node->cmdline) tool = node->cmdline; printf("%08x %s %s %-15s\n", (unsigned)node->timestamp, dirtyflag[node->dirty], node->filename, tool); for(link = node->firstdep; link; link = link->next) printf("%08x %s DEPEND %s\n", (unsigned)link->node->timestamp, dirtyflag[link->node->dirty], link->node->filename); for(link = node->firstparent; link; link = link->next) printf("%08x %s PARENT %s\n", (unsigned)link->node->timestamp, dirtyflag[link->node->dirty], link->node->filename); for(link = node->constraint_shared; link; link = link->next) printf("%08x %s SHARED %s\n", (unsigned)link->node->timestamp, dirtyflag[link->node->dirty], link->node->filename); for(link = node->constraint_exclusive; link; link = link->next) printf("%08x %s EXCLUS %s\n", (unsigned)link->node->timestamp, dirtyflag[link->node->dirty], link->node->filename); for(link = node->firstjobdep; link; link = link->next) printf("%08x %s JOBDEP %s\n", (unsigned)link->node->timestamp, dirtyflag[link->node->dirty], link->node->filename); } } static int node_debug_dump_dot_callback(struct NODEWALK *walkinfo) { struct NODE *node = walkinfo->node; struct NODELINK *link; /* skip top node, always the build target */ if(node == walkinfo->user) return 0; printf("node%d [label=\"%s\"];\n", node->id, node->filename); for(link = node->firstdep; link; link = link->next) printf("node%d -> node%d;\n", link->node->id, node->id); return 0; } /* dumps all nodes to the stdout */ void node_debug_dump_dot(struct GRAPH *graph, struct NODE *top) { printf("digraph {\n"); printf("graph [rankdir=\"LR\"];\n"); printf("node [shape=box, height=0.25, color=gray, fontsize=8];\n"); node_walk(top, NODEWALK_FORCE|NODEWALK_TOPDOWN|NODEWALK_QUICK, node_debug_dump_dot_callback, top); printf("}\n"); } static int node_debug_dump_jobs_dot_callback(struct NODEWALK *walkinfo) { struct NODE *node = walkinfo->node; struct NODELINK *link; /* skip top node, always the build target */ if(node == walkinfo->user) return 0; printf("node%d [shape=box, label=\"%s\"];\n", node->id, node->filename); for(link = node->firstjobdep; link; link = link->next) printf("node%d -> node%d;\n", link->node->id, node->id); return 0; } void node_debug_dump_jobs_dot(struct GRAPH *graph, struct NODE *top) { printf("digraph {\n"); printf("graph [rankdir=\"LR\"];\n"); printf("node [shape=box, height=0.25, color=gray, fontsize=8];\n"); node_walk(top, NODEWALK_FORCE|NODEWALK_TOPDOWN|NODEWALK_JOBS|NODEWALK_QUICK, node_debug_dump_jobs_dot_callback, top); printf("}\n"); } void node_debug_dump_jobs(struct GRAPH *graph) { struct NODELINK *link; struct NODE *node = graph->first; static const char *dirtyflag[] = {"--", "MI", "CH", "DD", "DN", "GS"}; printf("MI = Missing CH = Command hash dirty, DD = Dependency dirty\n"); printf("DN = Dependency is newer, GS = Global stamp is newer\n"); printf("Dirty Depth %-30s Command\n", "Filename"); for(;node;node = node->next) { if(node->cmdline) { printf(" %s %3d %-30s %s\n", dirtyflag[node->dirty], node->depth, node->filename, node->cmdline); for(link = node->firstjobdep; link; link = link->next) printf(" %s + %-30s\n", dirtyflag[link->node->dirty], link->node->filename); } } } bam-0.4.0/src/path.c0000644000175000017500000002164611430042030012237 0ustar kmakma/* lua includes */ #include #include #include #include #include #include #include "platform.h" #define PATH_SEPARATOR '/' static unsigned path_is_separator(char c) { #if defined(BAM_FAMILY_WINDOWS) return c == '/' || c == '\\'; #else return c == '/'; #endif } /* */ const char *path_filename(const char *path) { const char *ret = path; const char *cur; for(cur = path; *cur; cur++) { if(path_is_separator(*cur)) ret = cur+1; } return ret; } /* */ int path_directory(const char *path, char *directory, int size) { char *dest = directory; char *dest_end = directory+size-1; const char *read = path; const char *cur; for(cur = path; *cur; cur++) { if(path_is_separator(*cur)) { /* ok, copy the directory */ for(; read != cur; read++, dest++) { if(dest == dest_end) { *dest = 0; return 1; } *dest = *read; } } } *dest = 0; if(0) printf("path_directory:\n\tinput:'%s'\n\toutput:'%s'\n", path, directory); return 0; } /* normalizes the path, it rewrites the path */ int path_normalize(char *path) { char *dirs[128]; int depth = 0; char *dstptr = path; char *srcptr = path; /* add the start */ dirs[0] = path; depth++; while(1) { if(srcptr[0] == '.') { if(path_is_separator(srcptr[1])) { /* "./" case, just skip the data */ srcptr += 2; } else if(srcptr[1] == '.') { /* found ".." in path */ if(path_is_separator(srcptr[2])) { /* "../" case */ if(depth == 1) { /* case where we are at the start so append ../ to the start of the string */ dstptr[0] = '.'; dstptr[1] = '.'; dstptr[2] = PATH_SEPARATOR; dstptr += 3; srcptr += 3; dirs[0] = dstptr; } else { /* normal case where we are in the middle like "a/b/../c" */ depth--; dstptr = dirs[depth-1]; srcptr += 3; } } else if(srcptr[2] == 0) { /* ".." case, .. at end of string */ if(depth == 1) { dstptr[0] = '.'; dstptr[1] = '.'; dstptr += 2; srcptr += 2; dirs[0] = dstptr; } else { depth--; dstptr = dirs[depth-1]; srcptr += 2; } } else { /* "..?" case */ return -1; } } } else { /* search for separator */ while(!path_is_separator(srcptr[0]) && srcptr[0]) *dstptr++ = *srcptr++; if(srcptr[0] == 0) { /* end of string, zero terminate and return, strip ending '/' if it exists */ if(dstptr != path && path_is_separator(dstptr[-1])) dstptr[-1] = 0; dstptr[0] = 0; return 0; } else if(path_is_separator(srcptr[0])) { /* store the point of this directory */ *dstptr++ = *srcptr++; dirs[depth] = dstptr; depth++; } else { /* non reachable case */ return -1; } } } return 0; } /* returns true if a path is absolute */ int path_isabs(const char *path) { #if defined(BAM_FAMILY_WINDOWS) if(strlen(path) > 2 && isalpha(path[0]) && path[1] == ':' && path_is_separator(path[2])) return 1; #elif defined(BAM_FAMILY_UNIX) if(path_is_separator(path[0])) return 1; #elif defined(BAM_FAMILY_BEOS) if(path_is_separator(path[0])) return 1; #else #error path_isabs(const char *path) not implemented on this platform #endif return 0; } /* is it absolute and normalized? */ int path_isnice(const char *path) { /* check for initial "../../" */ while(path[0] == '.') { if(path[1] == '.') { if(path_is_separator(path[2])) { /* found "../" case */ path += 3; } else return 0; } else if(path_is_separator(path[1])) return 0; else break; } while(path[0]) { if(path_is_separator(path[0])) { /* check for // */ if(path_is_separator(path[1])) return 0; if(path[1] == '.') { /* check for /.. */ if(path[2] == '.') return 0; /* check for /./ */ if(path_is_separator(path[2])) return 0; } /* check so that the path doesn't end on / */ if(path[1] == 0) return 0; } path++; } return 1; } /* return zero on success */ int path_join(const char *base, int base_len, const char *extend, int extend_len, char *output, int size) { int i; if(extend_len < 0) extend_len = strlen(extend); if(path_isabs(extend)) { /* just copy the extend path */ if(extend_len+1 > size) { fprintf(stderr, "'%s' + '%s' results in a too long path\n", base, extend); return __LINE__; } memcpy(output, extend, extend_len+1); path_normalize(output); return 0; } if(base_len < 0) base_len = strlen(base); /* +2 for separator and null terminator */ if(base_len+extend_len+2 > size) { fprintf(stderr, "'%s' + '%s' results in a too long path\n", base, extend); return __LINE__; } /* no base path, just use extend path then */ if(base_len == 0) { memcpy(output, extend, extend_len+1); path_normalize(output); return 0; } /* copy base path */ memcpy(output, base, base_len); /* append path separator if needed */ if(!path_is_separator(base[base_len-1])) { output[base_len] = PATH_SEPARATOR; base_len++; } /* append the extra path, and null-terminator*/ for(i = 0; i < extend_len+1; i++) output[base_len+i] = extend[i]; /* normalize path and return success */ path_normalize(output); return 0; } /* */ int lf_path_join(lua_State *L) { char buffer[1024*2]; int n = lua_gettop(L); int err; const char *base; const char *extend; size_t base_len, extend_len; if(n != 2) luaL_error(L, "path_join: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TSTRING); luaL_checktype(L, 2, LUA_TSTRING); base = lua_tolstring(L, 1, &base_len); extend = lua_tolstring(L, 2, &extend_len); err = path_join(base, base_len, extend, extend_len, buffer, 2*1024); if(err != 0) { luaL_error(L, "path_join: error %d, couldn't join\n\t'%s'\n and\n\t'%s'", err, lua_tostring(L, 1), lua_tostring(L, 2)); } lua_pushstring(L, buffer); return 1; } /* */ int lf_path_isnice(lua_State *L) { int n = lua_gettop(L); const char *path = 0; if(n != 1) luaL_error(L, "path_isnice: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TSTRING); path = lua_tostring(L, 1); lua_pushnumber(L, path_isnice(path)); return 1; } int lf_path_normalize(lua_State *L) { int n = lua_gettop(L); const char *path = 0; if(n != 1) luaL_error(L, "path_normalize: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TSTRING); path = lua_tostring(L, 1); if(path_isnice(path)) { /* path is ok */ lua_pushstring(L, path); } else { /* normalize and return */ char buffer[2*1024]; strcpy(buffer, path); path_normalize(buffer); lua_pushstring(L, buffer); } return 1; } static const char *path_ext(const char *filename) { const char *cur = filename; const char *ext = 0; for(; *cur; cur++) { if(*cur == '.') ext = cur; if(path_is_separator(*cur)) ext = (const char *)0x0; } if(!ext) return ""; return ext+1; } /* */ int lf_path_ext(lua_State *L) { int n = lua_gettop(L); const char *path = 0; if(n < 1) luaL_error(L, "path_ext: incorrect number of arguments"); path = lua_tostring(L, 1); if(!path) luaL_error(L, "path_ext: argument is not a string"); lua_pushstring(L, path_ext(path)); return 1; } /* */ int lf_path_base(lua_State *L) { int n = lua_gettop(L); size_t org_len; size_t new_len; size_t count = 0; const char *cur = 0; const char *path = 0; if(n < 1) luaL_error(L, "path_base: incorrect number of arguments"); path = lua_tolstring(L, 1, &org_len); if(!path) luaL_error(L, "path_base: argument is not a string"); /* cut off the ext */ new_len = org_len; for(cur = path; *cur; cur++, count++) { if(*cur == '.') new_len = count; else if(path_is_separator(*cur)) new_len = org_len; } lua_pushlstring(L, path, new_len); return 1; } static int path_dir_length(const char *path) { const char *cur = path; int total = 0; int len = -1; for(; *cur; cur++, total++) { if(path_is_separator(*cur)) len = (int)(cur-path); } if(len == -1) return 0; return len; } /* */ int lf_path_dir(lua_State *L) { char buffer[1024]; int n = lua_gettop(L); const char *path = 0; if(n < 1) luaL_error(L, "path_dir: incorrect number of arguments"); path = lua_tostring(L, 1); if(!path) luaL_error(L, "path_dir: argument is not a string"); /* check if we can take the easy way out */ if(path_isnice(path)) { lua_pushlstring(L, path, path_dir_length(path)); return 1; } /* we must normalize the path as well */ strncpy(buffer, path, sizeof(buffer)); path_normalize(buffer); lua_pushlstring(L, buffer, path_dir_length(buffer)); return 1; } /* */ int lf_path_filename(lua_State *L) { int n = lua_gettop(L); const char *path = 0; if(n < 1) luaL_error(L, "path_filename: incorrect number of arguments"); path = lua_tostring(L, 1); if(!path) luaL_error(L, "path_filename: null name"); lua_pushstring(L, path_filename(path)); return 1; } bam-0.4.0/src/support.c0000644000175000017500000003434511430042030013017 0ustar kmakma#include #include #include #include #include #include #include #include "platform.h" #include "path.h" #include "context.h" #include "session.h" #include "support.h" #ifdef BAM_FAMILY_BEOS #include #endif #ifdef BAM_FAMILY_WINDOWS /* windows code */ #define WIN32_LEAN_AND_MEAN #define VC_EXTRALEAN #include #include #include #include #include #include /* _mkdir */ static void list_directory(const char *path, void (*callback)(const char *filename, int dir, void *user), void *user) { WIN32_FIND_DATA finddata; HANDLE handle; char buffer[1024*2]; char *startpoint; if(path[0]) { strcpy(buffer, path); strcat(buffer, "/*"); startpoint = buffer + strlen(path)+1; } else { strcpy(buffer, "*"); startpoint = buffer; } handle = FindFirstFileA(buffer, &finddata); if (handle == INVALID_HANDLE_VALUE) return; /* add all the entries */ do { strcpy(startpoint, finddata.cFileName); if(finddata.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) callback(buffer, 1, user); else callback(buffer, 0, user); } while (FindNextFileA(handle, &finddata)); FindClose(handle); } /* signals. should be moved to platform.c or similar? */ void install_signals(void (*abortsignal)(int)) { signal(SIGINT, abortsignal); signal(SIGBREAK, abortsignal); } static CRITICAL_SECTION criticalsection; void platform_init() { InitializeCriticalSection(&criticalsection); /* this environment variable is set by Microsoft Visual Studio when building. It causes cl.exe to redirect it's output to the specified pipe id. this causes loads of problems with output. */ SetEnvironmentVariable("VS_UNICODE_OUTPUT", NULL); } void platform_shutdown() { DeleteCriticalSection(&criticalsection); } void criticalsection_enter() { EnterCriticalSection(&criticalsection); } void criticalsection_leave() { LeaveCriticalSection(&criticalsection); } void *threads_create(void (*threadfunc)(void *), void *u) { return CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc, u, 0, NULL); } void threads_join(void *thread) { WaitForSingleObject((HANDLE)thread, INFINITE); } void threads_yield() { Sleep(1); } PLUGINFUNC plugin_load(const char *filename) { char buffer[MAX_PATH_LENGTH]; HMODULE handle; FARPROC func; _snprintf(buffer, sizeof(buffer), "%s.dll", filename); handle = LoadLibrary(buffer); if(handle == NULL) { fprintf(stderr, "error loading plugin '%s'\n", buffer); return NULL; } func = GetProcAddress(handle, "plugin_main"); if(func == NULL) { CloseHandle(handle); fprintf(stderr, "error fetching plugin main from '%s'\n", buffer); return NULL; } return (PLUGINFUNC)func; } #else #define D_TYPE_HACK #ifdef D_TYPE_HACK #define __USE_BSD #endif #include #include #include #include #include #include #include #include /* disable D_TYPE_HACK if we don't have support for it */ #if !defined(DT_DIR) || !defined(DT_UNKNOWN) #undef D_TYPE_HACK #endif static void list_directory(const char *path, void (*callback)(const char *filename, int dir, void *user), void *user) { DIR *dir; struct dirent *entry; struct stat info; char buffer[1024]; char *startpoint; if(*path == 0) /* special case for current directory */ { dir = opendir("."); startpoint = buffer; } else { dir = opendir(path); /* get starting point and append a slash */ strcpy(buffer, path); startpoint = buffer + strlen(buffer); *startpoint = '/'; startpoint++; } if(!dir) return; while((entry = readdir(dir)) != NULL) { /* make the path absolute */ strcpy(startpoint, entry->d_name); #ifdef D_TYPE_HACK /* call the callback */ if(entry->d_type == DT_UNKNOWN) { /* do stat to obtain if it's a directory or not */ stat(buffer, &info); if(S_ISDIR(info.st_mode)) callback(buffer, 1, user); else callback(buffer, 0, user); } else if(entry->d_type == DT_DIR) callback(buffer, 1, user); else callback(buffer, 0, user); #else /* do stat to obtain if it's a directory or not */ stat(buffer, &info); if(S_ISDIR(info.st_mode)) callback(buffer, 1, user); else callback(buffer, 0, user); #endif } closedir(dir); } /* signals. should be moved to platform.c or similar? */ void install_signals(void (*abortsignal)(int)) { signal(SIGHUP, abortsignal); signal(SIGINT, abortsignal); signal(SIGKILL, abortsignal); } static pthread_mutex_t lock_mutex = PTHREAD_MUTEX_INITIALIZER; void platform_init() {} void platform_shutdown() {} void criticalsection_enter() { pthread_mutex_lock(&lock_mutex); } void criticalsection_leave() { pthread_mutex_unlock(&lock_mutex); } void *threads_create(void (*threadfunc)(void *), void *u) { pthread_t id; pthread_create(&id, NULL, (void *(*)(void*))threadfunc, u); return (void*)id; } void threads_join(void *thread) { pthread_join((pthread_t)thread, NULL); } void threads_yield() { sched_yield(); } PLUGINFUNC plugin_load(const char *filename) { char buffer[MAX_PATH_LENGTH]; const char *error; void *handle; union { PLUGINFUNC func; void *ptr; } func; if(strlen(filename) > sizeof(buffer) - 10) return (PLUGINFUNC)0; strcpy(buffer, "./"); strcat(buffer, filename); strcpy(buffer, ".so"); handle = dlopen(buffer, RTLD_LAZY); if(!handle) { fputs(dlerror(), stderr); fputs("\n", stderr); return NULL; } func.ptr = dlsym(handle, "plugin_main"); error = dlerror(); if(error) { fputs(error, stderr); fputs("\n", stderr); dlclose(handle); return NULL; } return func.func; } #endif time_t timestamp() { return time(NULL); } time_t file_timestamp(const char *filename) { #ifdef BAM_PLATFORM_MACOSX /* Mac OS X version */ struct stat s; if(stat(filename, &s) == 0) return s.st_mtimespec.tv_sec; return 0; #else /* *NIX version and windows version*/ struct stat s; if(stat(filename, &s) == 0) return s.st_mtime; return 0; #endif } int file_createdir(const char *path) { int r; #ifdef BAM_FAMILY_WINDOWS r = _mkdir(path); #else r = mkdir(path, 0755); #endif if(r == 0 || errno == EEXIST) return 0; return -1; } void file_touch(const char *filename) { #ifdef BAM_FAMILY_WINDOWS _utime(filename, NULL); #else utime(filename, NULL); #endif } #ifdef BAM_FAMILY_WINDOWS static void passthru(FILE *fp) { while(1) { char buffer[1024*4]; size_t num_bytes = fread(buffer, 1, sizeof(buffer), fp); if(num_bytes <= 0) break; criticalsection_enter(); fwrite(buffer, 1, num_bytes, stdout); criticalsection_leave(); } } #endif int run_command(const char *cmd, const char *filter) { int ret; #ifdef BAM_FAMILY_WINDOWS FILE *fp = _popen(cmd, "r"); if(!fp) return -1; if(filter && *filter == 'F') { /* first filter match */ char buffer[1024]; size_t total; size_t matchlen; size_t numread; /* skip first letter */ filter++; matchlen = strlen(filter); total = 0; while(1) { numread = fread(buffer+total, 1, matchlen-total, fp); if(numread <= 0) { /* done or error, flush and exit */ fwrite(buffer, 1, total, stdout); break; } /* accumelate the bytes read */ total += numread; if(total >= matchlen) { /* check if it matched */ if(memcmp(buffer, filter, matchlen) == 0) { /* check for line ending */ char t = fgetc(fp); if(t == '\r') { /* this can be CR or CR/LF */ t = fgetc(fp); if(t != '\n') { /* not a CR/LF */ fputc(t, stdout); } } else if(t == '\n') { /* normal LF line ending */ } else { /* no line ending */ fputc(t, stdout); } } else { fwrite(buffer, 1, total, stdout); } passthru(fp); break; } } } else { /* no filter */ passthru(fp); } ret = _pclose(fp); #else ret = system(cmd); #endif if(session.verbose) printf("%s: ret=%d %s\n", session.name, ret, cmd); return ret; } /* general */ int file_exist(const char *filename) { struct stat s; if(stat(filename, &s) == 0) return 1; return 0; } /* list directory functionallity */ typedef struct { lua_State *lua; int i; } LISTDIR_CALLBACK_INFO; static void listdir_callback(const char *filename, int dir, void *user) { LISTDIR_CALLBACK_INFO *info = (LISTDIR_CALLBACK_INFO *)user; lua_pushstring(info->lua, filename); lua_rawseti(info->lua, -2, info->i++); } int lf_listdir(lua_State *L) { LISTDIR_CALLBACK_INFO info; info.lua = L; info.i = 1; /* create the table */ lua_newtable(L); /* add all the entries */ if(strlen(lua_tostring(L, 1)) < 1) list_directory(context_get_path(L), listdir_callback, &info); else { char buffer[1024]; path_join(context_get_path(L), -1, lua_tostring(L,1), -1, buffer, sizeof(buffer)); list_directory(buffer, listdir_callback, &info); } return 1; } /* collect functionallity */ enum { COLLECTFLAG_FILES=1, COLLECTFLAG_DIRS=2, COLLECTFLAG_HIDDEN=4, COLLECTFLAG_RECURSIVE=8 }; typedef struct { int path_len; const char *start_str; int start_len; const char *end_str; int end_len; lua_State *lua; int i; int flags; } COLLECT_CALLBACK_INFO; static void run_collect(COLLECT_CALLBACK_INFO *info, const char *input); static void collect_callback(const char *filename, int dir, void *user) { COLLECT_CALLBACK_INFO *info = (COLLECT_CALLBACK_INFO *)user; const char *no_pathed = filename + info->path_len; int no_pathed_len = strlen(no_pathed); /* don't process . and .. paths */ if(filename[0] == '.') { if(filename[1] == 0) return; if(filename[1] == '.' && filename[2] == 0) return; } /* don't process hidden stuff if not wanted */ if(no_pathed[0] == '.' && !(info->flags&COLLECTFLAG_HIDDEN)) return; do { /* check end */ if(info->end_len > no_pathed_len || strcmp(no_pathed+no_pathed_len-info->end_len, info->end_str)) break; /* check start */ if(info->start_len && strncmp(no_pathed, info->start_str, info->start_len)) break; /* check dir vs search param */ if(!dir && info->flags&COLLECTFLAG_DIRS) break; if(dir && info->flags&COLLECTFLAG_FILES) break; /* all criterias met, push the result */ lua_pushstring(info->lua, filename); lua_rawseti(info->lua, -2, info->i++); } while(0); /* recurse */ if(dir && info->flags&COLLECTFLAG_RECURSIVE) { char recursepath[1024]; COLLECT_CALLBACK_INFO recurseinfo = *info; strcpy(recursepath, filename); strcat(recursepath, "/"); strcat(recursepath, info->start_str); run_collect(&recurseinfo, recursepath); info->i = recurseinfo.i; } } static void run_collect(COLLECT_CALLBACK_INFO *info, const char *input) { char dir[1024]; int dirlen = 0; /* get the directory */ path_directory(input, dir, sizeof(dir)); dirlen = strlen(dir); info->path_len = dirlen+1; /* set the start string */ if(dirlen) info->start_str = input + dirlen + 1; else info->start_str = input; for(info->start_len = 0; info->start_str[info->start_len]; info->start_len++) { if(info->start_str[info->start_len] == '*') break; } /* set the end string */ if(info->start_str[info->start_len]) info->end_str = info->start_str + info->start_len + 1; else info->end_str = info->start_str + info->start_len; info->end_len = strlen(info->end_str); /* search the path */ list_directory(dir, collect_callback, info); } static int collect(lua_State *L, int flags) { int n = lua_gettop(L); int i; COLLECT_CALLBACK_INFO info; if(n < 1) luaL_error(L, "collect: incorrect number of arguments"); /* create the table */ lua_newtable(L); /* set common info */ info.lua = L; info.i = 1; info.flags = flags; /* start processing the input strings */ for(i = 1; i <= n; i++) { const char *input = lua_tostring(L, i); if(!input) continue; run_collect(&info, input); } return 1; } int lf_collect(lua_State *L) { return collect(L, COLLECTFLAG_FILES); } int lf_collectrecursive(lua_State *L) { return collect(L, COLLECTFLAG_FILES|COLLECTFLAG_RECURSIVE); } int lf_collectdirs(lua_State *L) { return collect(L, COLLECTFLAG_DIRS); } int lf_collectdirsrecursive(lua_State *L) { return collect(L, COLLECTFLAG_DIRS|COLLECTFLAG_RECURSIVE); } /* */ #ifdef BAM_FAMILY_WINDOWS /* on windows, we need to handle that filenames with mixed casing are the same. to solve this we have this table that converts all uppercase letters. in addition to this, we also convert all '\' to '/' to remove that ambiguity */ static const unsigned char tolower_table[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 91, '/', 93, 94, 95, 96, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255}; unsigned int string_hash_add(unsigned int h, const char *str_in) { const unsigned char *str = (const unsigned char *)str_in; for (; *str; str++) h = 31*h + tolower_table[*str]; return h; } #else /* normal unix version */ unsigned int string_hash_add(unsigned int h, const char *str) { for (; *str; str++) h = 31*h + *str; return h; } #endif unsigned int string_hash(const char *str_in) { return string_hash_add(0, str_in); } bam-0.4.0/src/node.h0000644000175000017500000001717111430042030012233 0ustar kmakma#ifndef FILE_NODE_H #define FILE_NODE_H /* **** dependency graph ****** */ #include #include "tree.h" /* */ struct NODELINK { struct NODE *node; struct NODELINK *next; }; struct NODETREELINK { struct NODETREELINK *parent; struct NODETREELINK *leafs[2]; struct NODE *node; int depth; }; struct SCANNER { struct SCANNER *next; int (*scannerfunc)(struct NODE *, struct SCANNER *info); }; #if 0 struct JOB { struct GRAPH *graph; /* graph that the job belongs to */ char *cmdline; char *label; char *filter; unsigned cmdhash; /* hash of the command line for detecting changes */ unsigned cachehash; /* hash that should be written to the cache */ struct NODELINK *firstoutput; struct NODELINK *constraint_exclusive; /* list of exclusive constraints */ struct NODELINK *constraint_shared; /* list of shared constraints */ }; #endif /* a node in the dependency graph NOTE: when adding variables to this structure, they will all be set to zero when created by node_create(). TODO: these should be allocated cache aligned, and padded to 128 byte? */ struct NODE { /* *** */ struct GRAPH *graph; /* graph that the node belongs to */ struct NODE *next; /* next node in the graph */ struct NODELINK *firstparent; /* list of parents */ struct NODELINK *firstdep; /* list of dependencies */ struct NODETREELINK *deproot; /* tree of dependencies */ struct NODELINK *firstjobdep; /* list of job dependencies */ struct NODETREELINK *jobdeproot; /* tree of job dependencies */ struct NODELINK *constraint_exclusive; /* list of exclusive constraints */ struct NODELINK *constraint_shared; /* list of shared constraints */ char *filename; /* this contains the filename with the FULLPATH */ /* either none of these are set or both of em are */ char *cmdline; /* command line that should be executed to build this node */ char *label; /* what to print when we build this node */ char *filter; /* filter string, first character sets the type of filter */ /* filename and the tool to build the resource */ unsigned cmdhash; /* hash of the command line for detecting changes */ unsigned cachehash; /* hash that should be written to the cache */ unsigned constraint_exclusive_count; /* */ unsigned constraint_shared_count; /* */ unsigned hashid; /* hash of the filename/nodename */ /* time stamps, 0 == does not exist. */ time_t timestamp; /* timestamp. this will be updated from the deps of the node */ time_t timestamp_raw; /* raw timestamp. contains the timestamp on the disc */ unsigned id; /* used when doing traversal with marking (bitarray) */ unsigned short filename_len; /* length of filename including zero term */ unsigned short depth; /* depth in the graph. used for priority when buliding */ /* various flags (4 bytes in the end) */ unsigned dirty:8; /* non-zero if the node has to be rebuilt */ unsigned depchecked:1; /* set if a dependency checker have processed the file */ unsigned counted:1; /* set if we have counted this node towards the number of targets to build */ unsigned targeted:1; /* set if this node is targeted for a build */ unsigned touch:1; /* when built, touch the output file as well */ unsigned cached:1; /* set if the node should be considered as cached */ volatile unsigned workstatus:2; /* build status of the node, NODESTATUS_* flags */ }; /* cache node */ struct CACHENODE { RB_ENTRY(CACHENODE) rbentry; unsigned hashid; time_t timestamp_raw; char *filename; unsigned cmdhash; unsigned cached:1; unsigned deps_num; unsigned *deps; /* index id, not hashid */ }; /* */ struct GRAPH { struct NODETREELINK *nodehash[0x10000]; struct NODE *first; struct NODE *last; struct HEAP *heap; /* needed when saving the cache */ int num_nodes; int num_deps; }; struct HEAP; struct CONTEXT; /* node status */ #define NODESTATUS_UNDONE 0 /* node needs build */ #define NODESTATUS_WORKING 1 /* a thread is working on this node */ #define NODESTATUS_DONE 2 /* node built successfully */ #define NODESTATUS_BROKEN 3 /* node tool reported an error or a dependency is broken */ /* node creation error codes */ #define NODECREATE_OK 0 #define NODECREATE_EXISTS 1 /* the node already exists */ #define NODECREATE_NOTNICE 2 /* the path is not normalized */ #define NODECREATE_INVALID_ARG 3 /* invalid arguments */ /* node walk flags */ #define NODEWALK_FORCE 1 /* skips dirty checks and*/ #define NODEWALK_TOPDOWN 2 /* callbacks are done top down */ #define NODEWALK_BOTTOMUP 4 /* callbacks are done bottom up */ #define NODEWALK_UNDONE 8 /* causes checking of the undone flag, does not decend if it's set */ #define NODEWALK_QUICK 16 /* never visit the same node twice */ #define NODEWALK_JOBS 32 /* walk the jobtree instead of the complete tree */ #define NODEWALK_REVISIT (64|NODEWALK_QUICK) /* will do a quick pass and revisits all nodes thats have been marked by node_walk_revisit(). path info won't be available when revisiting nodes */ /* node dirty status */ /* make sure to update node_debug_dump_jobs() when changing these */ #define NODEDIRTY_NOT 0 #define NODEDIRTY_MISSING 1 /* the output file is missing */ #define NODEDIRTY_CMDHASH 2 /* the command doesn't match the one in the cache */ #define NODEDIRTY_DEPDIRTY 3 /* one of the dependencies is dirty */ #define NODEDIRTY_DEPNEWER 4 /* one of the dependencies is newer */ #define NODEDIRTY_GLOBALSTAMP 5 /* the globaltimestamp is newer */ /* you destroy graphs by destroying the heap */ struct GRAPH *node_create_graph(struct HEAP *heap); /* */ int node_create(struct NODE **node, struct GRAPH *graph, const char *filename, const char *label, const char *cmdline); struct NODE *node_find(struct GRAPH *graph, const char *filename); struct NODE *node_find_byhash(struct GRAPH *graph, unsigned int hashid); struct NODE *node_get(struct GRAPH *graph, const char *filename); struct NODE *node_add_dependency(struct NODE *node, const char *filename); struct NODE *node_add_dependency_withnode(struct NODE *node, struct NODE *depnode); struct NODE *node_add_job_dependency_withnode(struct NODE *node, struct NODE *depnode); void node_set_pseudo(struct NODE *node); void node_cached(struct NODE *node); struct NODE *node_add_constraint_shared(struct NODE *node, const char *filename); struct NODE *node_add_constraint_exclusive(struct NODE *node, const char *filename); struct NODEWALKPATH { struct NODEWALKPATH *parent; struct NODE *node; }; struct NODEWALKREVISIT { struct NODE *node; struct NODEWALKREVISIT *next; }; struct NODEWALK { int flags; /* flags for this node walk */ struct NODE *node; /* current visiting node */ /* path that we reached this node by (not available during revisit due to activation) */ struct NODEWALKPATH *parent; unsigned depth; void *user; int (*callback)(struct NODEWALK *); /* function that is called for each visited node */ unsigned char *mark; /* bits for mark and sweep */ int revisiting; /* set to 1 if we are doing revisits */ struct NODEWALKREVISIT *firstrevisit; struct NODEWALKREVISIT *revisits; }; /* walks though the dependency tree with the set options and calling callback() on each node it visites */ int node_walk( struct NODE *node, int flags, int (*callback)(struct NODEWALK *info), void *u); /* marks a node for revisit, only works if NODEWALK_REVISIT flags was specified to node_walk */ void node_walk_revisit(struct NODEWALK *walk, struct NODE *node); /* node debug dump functions */ void node_debug_dump(struct GRAPH *graph); void node_debug_dump_detailed(struct GRAPH *graph); void node_debug_dump_jobs(struct GRAPH *graph); void node_debug_dump_dot(struct GRAPH *graph, struct NODE *top); void node_debug_dump_jobs_dot(struct GRAPH *graph, struct NODE *top); #endif /* FILE_NODE_H */ bam-0.4.0/src/version.h0000644000175000017500000000040111430042030012757 0ustar kmakma#define BAM_VERSION_MAJOR "0" #define BAM_VERSION_MINOR "4" #define BAM_VERSION_PATCH "0" #define BAM_VERSION_STRING BAM_VERSION_MAJOR "." BAM_VERSION_MINOR #define BAM_VERSION_STRING_COMPLETE BAM_VERSION_MAJOR "." BAM_VERSION_MINOR "." BAM_VERSION_PATCH bam-0.4.0/src/luafuncs.c0000644000175000017500000004150111430042030013113 0ustar kmakma#include #include #include /* malloc */ /* lua includes */ #define LUA_CORE /* make sure that we don't try to import these functions */ #include #include #include #include "node.h" #include "context.h" #include "support.h" #include "luafuncs.h" #include "path.h" #include "mem.h" #include "session.h" void build_stringlist(lua_State *L, struct HEAP *heap, struct STRINGLIST **first, int table_index) { struct STRINGLIST *listitem; const char *orgstr; size_t len; int i; for(i = 1;; i++) { /* +1 value */ lua_rawgeti(L, table_index, i); if(lua_type(L, -1) == LUA_TNIL) break; /* allocate and fix copy the string */ orgstr = lua_tolstring(L, -1, &len); listitem = (struct STRINGLIST *)mem_allocate(heap, sizeof(struct STRINGLIST) + len + 1); listitem->str = (const char *)(listitem+1); listitem->len = len; memcpy(listitem+1, orgstr, len+1); /* add it to the list */ listitem->next = *first; *first = listitem; /* pop value */ lua_pop(L, 1); } } /* value for deep walks */ static struct { void (*callback)(lua_State*, void*); void *user; } deepwalkinfo; static void deep_walk_r(lua_State *L, int table_index) { int i; for(i = 1;; i++) { /* +1 value */ lua_rawgeti(L, table_index, i); if(lua_istable(L, -1)) deep_walk_r(L, lua_gettop(L)); else if(lua_type(L, -1) == LUA_TSTRING) deepwalkinfo.callback(L, deepwalkinfo.user); else if(lua_type(L, -1) == LUA_TNIL) break; else { /* other value */ luaL_error(L, "encountered something besides a string or a table"); } /* pop +1 */ lua_pop(L, 1); } } static void deep_walk(lua_State *L, int start, int stop, void (*callback)(lua_State*, void*), void *user) { int i; deepwalkinfo.callback = callback; deepwalkinfo.user = user; for(i = start; i <= stop; i++) { if(lua_istable(L, i)) deep_walk_r(L, i); else if(lua_type(L, i) == LUA_TSTRING) { lua_pushvalue(L, i); deepwalkinfo.callback(L, user); lua_pop(L, 1); } else { luaL_error(L, "encountered something besides a string or a table"); } } } /* add_pseudo(string node) */ int lf_add_pseudo(lua_State *L) { struct NODE *node; struct CONTEXT *context; int i; if(lua_gettop(L) != 1) luaL_error(L, "add_pseudo: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TSTRING); /* fetch contexst from lua */ context = context_get_pointer(L); /* create the node */ i = node_create(&node, context->graph, lua_tostring(L,1), NULL, NULL); if(i == NODECREATE_NOTNICE) luaL_error(L, "add_pseudo: node '%s' is not nice", lua_tostring(L,1)); else if(i == NODECREATE_EXISTS) luaL_error(L, "add_pseudo: node '%s' already exists", lua_tostring(L,1)); else if(i != NODECREATE_OK) luaL_error(L, "add_pseudo: unknown error creating node '%s'", lua_tostring(L,1)); node_set_pseudo(node); return 0; } /* add_output(string output, string other_output) */ int lf_add_output(lua_State *L) { struct NODE *output; struct NODE *other_output; struct CONTEXT *context; if(lua_gettop(L) != 2) luaL_error(L, "add_output: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TSTRING); luaL_checktype(L, 2, LUA_TSTRING); context = context_get_pointer(L); output = node_find(context->graph, lua_tostring(L,1)); if(!output) luaL_error(L, "add_output: couldn't find node with name '%s'", lua_tostring(L,1)); other_output = node_get(context->graph, lua_tostring(L,2)); if(!other_output) luaL_error(L, "add_output: couldn't find node with name '%s'", lua_tostring(L,2)); node_add_dependency_withnode(other_output, output); node_set_pseudo(other_output); return 0; } struct NODEATTRIB_CBINFO { struct NODE *node; struct NODE *(*callback)(struct NODE*, const char *); }; static void callback_node_attrib(lua_State *L, void *user) { struct NODEATTRIB_CBINFO *info = (struct NODEATTRIB_CBINFO *)user; if(!info->callback(info->node, lua_tostring(L, -1))) luaL_error(L, "could not add '%s' to '%s'", lua_tostring(L, -1), lua_tostring(L, 1)); } /* add_dependency(string node, string dependency) */ static int add_node_attribute(lua_State *L, const char *funcname, struct NODE *(*callback)(struct NODE*, const char *)) { struct NODE *node; struct CONTEXT *context; int n = lua_gettop(L); struct NODEATTRIB_CBINFO cbinfo; if(n < 2) luaL_error(L, "%s: to few arguments", funcname); luaL_checktype(L, 1, LUA_TSTRING); context = context_get_pointer(L); node = node_find(context->graph, lua_tostring(L,1)); if(!node) luaL_error(L, "%s: couldn't find node with name '%s'", funcname, lua_tostring(L,1)); /* seek deps */ cbinfo.node = node; cbinfo.callback = callback; deep_walk(L, 2, n, callback_node_attrib, &cbinfo); return 0; } int lf_add_dependency(lua_State *L) { return add_node_attribute(L, "add_dependency", node_add_dependency); } int lf_add_constraint_shared(lua_State *L) { return add_node_attribute(L, "add_constraint_shared", node_add_constraint_shared); } int lf_add_constraint_exclusive(lua_State *L) { return add_node_attribute(L, "add_constraint_exclusive", node_add_constraint_exclusive); } /* add_job(string output, string label, string command, ...) */ int lf_add_job(lua_State *L) { struct NODE *node; struct CONTEXT *context; struct NODEATTRIB_CBINFO cbinfo; int i; if(lua_gettop(L) < 3) luaL_error(L, "add_job: too few arguments"); luaL_checktype(L, 1, LUA_TSTRING); luaL_checktype(L, 2, LUA_TSTRING); luaL_checktype(L, 3, LUA_TSTRING); /* fetch contexst from lua */ context = context_get_pointer(L); /* create the node */ i = node_create(&node, context->graph, lua_tostring(L,1), lua_tostring(L,2), lua_tostring(L,3)); if(i == NODECREATE_NOTNICE) luaL_error(L, "add_job: node '%s' is not nice", lua_tostring(L,1)); else if(i == NODECREATE_EXISTS) luaL_error(L, "add_job: node '%s' already exists", lua_tostring(L,1)); else if(i != NODECREATE_OK) luaL_error(L, "add_job: unknown error creating node '%s'", lua_tostring(L,1)); /* seek deps */ cbinfo.node = node; cbinfo.callback = node_add_dependency; deep_walk(L, 4, lua_gettop(L), callback_node_attrib, &cbinfo); return 0; } int lf_set_touch(struct lua_State *L) { struct NODE *node; if(lua_gettop(L) < 1) luaL_error(L, "set_touch: too few arguments"); luaL_checktype(L, 1, LUA_TSTRING); node = node_find(context_get_pointer(L)->graph, lua_tostring(L,1)); if(!node) luaL_error(L, "set_touch: couldn't find node with name '%s'", lua_tostring(L,1)); node->touch = 1; return 0; } int lf_set_filter(struct lua_State *L) { struct NODE *node; const char *str; size_t len; /* check the arguments */ if(lua_gettop(L) < 2) luaL_error(L, "set_filter: too few arguments"); luaL_checktype(L, 1, LUA_TSTRING); luaL_checktype(L, 2, LUA_TSTRING); /* find the node */ node = node_find(context_get_pointer(L)->graph, lua_tostring(L,1)); if(!node) luaL_error(L, "set_filter: couldn't find node with name '%s'", lua_tostring(L,1)); /* setup the string */ str = lua_tolstring(L, 2, &len); node->filter = (char *)mem_allocate(node->graph->heap, len+1); memcpy(node->filter, str, len+1); return 0; } /* default_target(string filename) */ int lf_default_target(lua_State *L) { struct NODE *node; struct CONTEXT *context; int n = lua_gettop(L); if(n != 1) luaL_error(L, "default_target: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TSTRING); /* fetch context from lua */ context = context_get_pointer(L); /* search for the node */ node = node_find(context->graph, lua_tostring(L,1)); if(!node) luaL_error(L, "default_target: node '%s' not found", lua_tostring(L,1)); /* set target */ context_default_target(context, node); return 0; } /* update_globalstamp(string filename) */ int lf_update_globalstamp(lua_State *L) { struct CONTEXT *context; time_t file_stamp; if(lua_gettop(L) < 1) luaL_error(L, "update_globalstamp: too few arguments"); luaL_checktype(L, 1, LUA_TSTRING); context = context_get_pointer(L); file_stamp = file_timestamp(lua_tostring(L,1)); /* update global timestamp */ if(file_stamp > context->globaltimestamp) context->globaltimestamp = file_stamp; return 0; } /* loadfile(filename) */ int lf_loadfile(lua_State *L) { if(lua_gettop(L) < 1) luaL_error(L, "loadfile: too few arguments"); luaL_checktype(L, 1, LUA_TSTRING); if(session.verbose) printf("%s: reading script from '%s'\n", session.name, lua_tostring(L,1)); if(luaL_loadfile(L, lua_tostring(L,1)) != 0) lua_error(L); return 1; } /* ** */ static void debug_print_lua_value(lua_State *L, int i) { if(lua_type(L,i) == LUA_TNIL) printf("nil"); else if(lua_type(L,i) == LUA_TSTRING) printf("'%s'", lua_tostring(L,i)); else if(lua_type(L,i) == LUA_TNUMBER) printf("%f", lua_tonumber(L,i)); else if(lua_type(L,i) == LUA_TBOOLEAN) { if(lua_toboolean(L,i)) printf("true"); else printf("false"); } else if(lua_type(L,i) == LUA_TTABLE) { printf("{...}"); } else printf("%p (%s (%d))", lua_topointer(L,i), lua_typename(L,lua_type(L,i)), lua_type(L,i)); } /* error function */ int lf_errorfunc(lua_State *L) { int depth = 0; int frameskip = 1; lua_Debug frame; if(session.report_color) printf("\033[01;31m%s\033[00m\n", lua_tostring(L,-1)); else printf("%s\n", lua_tostring(L,-1)); if(session.lua_backtrace) { printf("backtrace:\n"); while(lua_getstack(L, depth, &frame) == 1) { depth++; lua_getinfo(L, "nlSf", &frame); /* check for functions that just report errors. these frames just confuses more then they help */ if(frameskip && strcmp(frame.short_src, "[C]") == 0 && frame.currentline == -1) continue; frameskip = 0; /* print stack frame */ printf(" %s(%d): %s %s\n", frame.short_src, frame.currentline, frame.name, frame.namewhat); /* print all local variables for the frame */ if(session.lua_locals) { int i; const char *name = 0; i = 1; while((name = lua_getlocal(L, &frame, i)) != NULL) { printf(" %s = ", name); debug_print_lua_value(L,-1); printf("\n"); lua_pop(L,1); i++; } i = 1; while((name = lua_getupvalue(L, -1, i)) != NULL) { printf(" upvalue #%d: %s ", i-1, name); debug_print_lua_value(L, -1); lua_pop(L,1); i++; } } } } return 1; } int lf_panicfunc(lua_State *L) { printf("%s: PANIC! I'm gonna segfault now\n", session.name); *(int*)0 = 0; return 0; } int lf_mkdir(struct lua_State *L) { if(lua_gettop(L) < 1) luaL_error(L, "mkdir: too few arguments"); if(!lua_isstring(L,1)) luaL_error(L, "mkdir: expected string"); if(file_createdir(lua_tostring(L,1)) == 0) lua_pushnumber(L, 1); else lua_pushnil(L); return 1; } int lf_fileexist(struct lua_State *L) { if(lua_gettop(L) < 1) luaL_error(L, "fileexist: too few arguments"); if(!lua_isstring(L,1)) luaL_error(L, "fileexist: expected string"); if(file_exist(lua_tostring(L,1))) lua_pushnumber(L, 1); else lua_pushnil(L); return 1; } int lf_istable(lua_State *L) { if(lua_type(L,-1) == LUA_TTABLE) lua_pushnumber(L, 1); else lua_pushnil(L); return 1; } int lf_isstring(lua_State *L) { if(lua_type(L,-1) == LUA_TSTRING) lua_pushnumber(L, 1); else lua_pushnil(L); return 1; } /* TODO: remove this limit */ #define WALK_MAXDEPTH 32 struct WALKDATA { int index[WALK_MAXDEPTH]; int depth; }; static int lf_table_walk_iter(struct lua_State *L) { struct WALKDATA *data; int type; /* 1: walk table 2: last value(ignore) */ lua_rawgeti(L, 1, 1); /* push 3: the walk data */ data = (struct WALKDATA *)lua_touserdata(L, -1); /* 1: walk table 2: last value 3: walk data */ while(1) { data->index[data->depth]++; /* .. 4: current table 5: current value */ lua_rawgeti(L, 1, data->depth+1); /* push 4: fetch table */ lua_rawgeti(L, -1, data->index[data->depth]); /* push 5: value in table */ type = lua_type(L, -1); if(type == LUA_TTABLE) { data->depth++; if(data->depth >= WALK_MAXDEPTH) luaL_error(L, "max table depth exceeded"); data->index[data->depth] = 0; lua_rawseti(L, 1, data->depth+1); lua_pop(L, 1); } else if(type == LUA_TNIL) { /* pop table and nil value */ lua_pop(L, 2); data->depth--; if(data->depth == 0) { lua_pushnil(L); return 1; } } else if(type == LUA_TSTRING) { lua_pushvalue(L, 1); /* push the table stack again */ return 2; } else luaL_error(L, "tablewalk: encountered strange value in tables"); } } /* the walk table looks like this t = { [1] = walk data [2] = table 1 [3] = table 2 [N] = table N } */ int lf_table_walk(struct lua_State *L) { struct WALKDATA *data; if(lua_gettop(L) != 1) luaL_error(L, "table_walk: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TTABLE); /* 1: table to iterate over */ lua_pushcfunction(L, lf_table_walk_iter); /* 2: iterator function */ lua_createtable(L, 4, 0); /* 3: table stack */ data = (struct WALKDATA *)lua_newuserdata(L, sizeof(struct WALKDATA)); data->depth = 1; data->index[data->depth] = 0; lua_rawseti(L, 3, 1); lua_pushvalue(L, 1); lua_rawseti(L, 3, 2); lua_pushnil(L); return 3; } /* does a deep copy of a table */ static int table_deepcopy_r(struct lua_State *L) { size_t s; /* 1: table to copy, 2: new table */ s = lua_objlen(L, -1); lua_createtable(L, 0, s); /* 3: iterator */ lua_pushnil(L); while(lua_next(L, -3)) { /* 4: value */ if(lua_istable(L, -1)) { table_deepcopy_r(L); /* 5: new table */ lua_pushvalue(L, -3); /* 6: key */ lua_pushvalue(L, -2); /* 7: value */ lua_settable(L, -6); /* pops 6 and 7 */ lua_pop(L, 1); /* pops 5 */ } else { lua_pushvalue(L, -2); /* 5: key */ lua_pushvalue(L, -2); /* 6: value */ lua_settable(L, -5); /* pops 5 and 6 */ } /* pops 4 */ lua_pop(L, 1); } /* transfer the meta table */ if(lua_getmetatable(L, -2)) lua_setmetatable(L, -2); return 1; } int lf_table_deepcopy(struct lua_State *L) { if(lua_gettop(L) != 1) luaL_error(L, "table_deepcopy: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TTABLE); return table_deepcopy_r(L); } static int flatten_index; /* flattens a table into a simple table with strings */ static int lf_table_flatten_r(struct lua_State *L, int table_index) { /* +1: iterator */ lua_pushnil(L); while(lua_next(L, table_index)) { /* +2: value */ if(lua_istable(L, -1)) lf_table_flatten_r(L, lua_gettop(L)); else if(lua_type(L, -1) == LUA_TSTRING) { lua_pushnumber(L, flatten_index); /* +3: key */ lua_pushvalue(L, -2); /* +4: value */ lua_settable(L, 2); /* pops +3 and +4 */ flatten_index++; } else { /* other value */ luaL_error(L, "encountered something besides a string or a table"); } /* pops +2 */ lua_pop(L, 1); } return 1; } int lf_table_flatten(struct lua_State *L) { size_t s; if(lua_gettop(L) != 1) luaL_error(L, "table_flatten: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TTABLE); /* 1: table to copy, 2: new table */ s = lua_objlen(L, -1); flatten_index = 1; lua_createtable(L, 0, s); lf_table_flatten_r(L, 1); return 1; } static char string_buffer[1024*4]; int lf_table_tostring(struct lua_State *L) { /* 1: table 2: prefix, 3: postfix */ size_t prefix_len, postfix_len; size_t total_len = 0; size_t item_len = 0; const char *prefix; const char *postfix; char *buffer; char *current; const char *item; if(lua_gettop(L) != 3) luaL_error(L, "table_tostring: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TTABLE); prefix = lua_tolstring(L, 2, &prefix_len); postfix = lua_tolstring(L, 3, &postfix_len); /* first, figure out the total size */ /* 4: iterator */ lua_pushnil(L); while(lua_next(L, 1)) { /* 5: value */ if(lua_type(L, -1) == LUA_TSTRING) { lua_tolstring(L, -1, &item_len); total_len += prefix_len+item_len+postfix_len; } /* pops 5 */ lua_pop(L, 1); } /* now allocate the buffer and start building the complete string */ if(total_len < sizeof(string_buffer)) buffer = string_buffer; else buffer = malloc(total_len); current = buffer; /* 4: iterator */ lua_pushnil(L); while(lua_next(L, 1)) { /* 5: value */ if(lua_type(L, -1) == LUA_TSTRING) { item = lua_tolstring(L, -1, &item_len); memcpy(current, prefix, prefix_len); current += prefix_len; memcpy(current, item, item_len); current += item_len; memcpy(current, postfix, postfix_len); current += postfix_len; } /* pops 5 */ lua_pop(L, 1); } /* push the new string onto the stack and clean up */ lua_pushlstring(L, buffer, total_len); if(buffer != string_buffer) free(buffer); return 1; } int lf_loadplugin(struct lua_State *L) { PLUGINFUNC func; if(lua_gettop(L) != 1) luaL_error(L, "loadplugin: incorrect number of arguments"); luaL_checktype(L, 1, LUA_TSTRING); func = plugin_load(lua_tostring(L, 1)); if(!func) luaL_error(L, "loadplugin: error loading plugin"); lua_settop(L, 0); if((*func)(L) != 0) luaL_error(L, "loadplugin: error initing plugin"); return 0; } bam-0.4.0/src/main.c0000644000175000017500000006257711430042030012237 0ustar kmakma/* some parts written at high altitudes */ /* some parts written at the top of the eiffel tower */ /* system includes */ #include #include #include #include /* lua includes */ #define LUA_CORE /* make sure that we don't try to import these functions */ #include #include /* luaL_openlibs */ #include /* luaL_loadfile */ /* program includes */ #include "mem.h" #include "node.h" #include "path.h" #include "support.h" #include "context.h" #include "cache.h" #include "luafuncs.h" #include "platform.h" #include "session.h" #include "version.h" /* internal base.bam file */ #include "internal_base.h" /* needed for getcwd */ #if defined(BAM_FAMILY_UNIX) || defined(BAM_FAMILY_BEOS) #include #endif #ifdef BAM_FAMILY_WINDOWS #include #define getcwd _getcwd /* stupid msvc is calling getcwd non-ISO-C++ conformant */ #endif #define DEFAULT_REPORT_STYLE "s" /* ** */ #define L_FUNCTION_PREFIX "bam_" struct OPTION { int print; const char **s; int *v; const char *sw; const char *desc; }; /* options passed via the command line */ static int option_clean = 0; static int option_no_cache = 0; static int option_dry = 0; static int option_dependent = 0; static int option_abort_on_error = 0; static int option_debug_nodes = 0; static int option_debug_nodes_detailed = 0; static int option_debug_jobs = 0; static int option_debug_dot = 0; static int option_debug_jobs_dot = 0; static int option_debug_dumpinternal = 0; static int option_debug_nointernal = 0; static int option_debug_trace_vm = 0; static int option_print_help = 0; static const char *option_script = "bam.lua"; /* -f filename */ static const char *option_threads_str = "0"; static const char *option_report_str = DEFAULT_REPORT_STYLE; static const char *option_targets[128] = {0}; static int option_num_targets = 0; static const char *option_scriptargs[128] = {0}; static int option_num_scriptargs = 0; /* filename of the cache, will be filled in at start up, ".bam/xxxxxxxx" = 14 top */ static char cache_filename[16] = {0}; /* session object */ struct SESSION session = { "bam", /* exe */ "bam", /* name */ 1, /* threads */ 0 /* rest */ }; static struct OPTION options[] = { /*@OPTION Targets ( name ) Specify a target to be built. A target can be any output specified to the [AddJob] function. If no targets are specified, the default target will be built If there are no default target and there is only one target specified with the [Target] function, it will be built. Otherwise bam will report an error. There is a special pseudo target named ^all^ that represents all targets specified by the [Target] function. @END*/ /*@OPTION Script Arguments ( name=value ) Sets a script argument. These arguments can be fetched form the build script by accessing the ^ScriptArgs^ table. @END*/ {1, 0, 0 , "\n Execution:", ""}, /*@OPTION Abort on error ( -a ) Setting this will cause bam to abort the build process when an error has occured. Normally it would continue as far as it can. @END*/ {1, 0,&option_abort_on_error , "-a", "abort on error"}, /*@OPTION Clean ( -c ) Cleans the specified targets or the default target. @END*/ {1, 0, &option_clean , "-c", "clean targets"}, /*@OPTION Dependent build ( -d ) Builds all targets that are dependent on the given targets. If no targets are given this option doesn't do anything. @END*/ {1, 0, &option_dependent , "-d", "build targets that is dependent given targets"}, /*@OPTION Dry Run ( --dry ) Does everything that it normally would do but does not execute any commands. @END*/ {1, 0, &option_dry , "--dry", "dry run, don't run any jobs"}, /*@OPTION Threading ( -j N ) Sets the number of threads used when building. A good value for N is the same number as logical cores on the machine. Set to 0 to disable. @END*/ {1, &option_threads_str,0 , "-j", "sets the number of threads to use (default: 0, disabled)"}, /*@OPTION Script File ( -s FILENAME ) Bam file to use. In normal operation, Bam executes ^bam.lua^. This option allows you to specify another bam file. @END*/ {1, &option_script,0 , "-s", "bam file to use (default: bam.lua)"}, {1, 0, 0 , "\n Lua:", ""}, /*@OPTION Script Locals ( -l ) Prints local and up values in the backtrace when there is a script error @END*/ {1, 0, &session.lua_locals , "-l", "print local variables in backtrace"}, /*@OPTION Script Backtrace ( -t ) Prints backtrace when there is a script error @END*/ {1, 0, &session.lua_backtrace , "-t", "print backtrace when an error occurs"}, {1, 0, 0 , "\n Output:", ""}, /*@OPTION Report Format ( -r [b][s][c] ) Sets the format of the progress report when building.
  • b
  • - Use a progress bar showing the percentage.
  • s
  • - Show each step when building. (default)
  • c
  • - Use ANSI colors.
@END*/ {1, &option_report_str,0 , "-r", "build progress report format (default: " DEFAULT_REPORT_STYLE ")\n" " " " b = progress bar\n" " " " c = use ansi colors\n" " " " s = build steps"}, /*@OPTION Verbose ( -v ) Prints all commands that are runned when building. @END*/ {1, 0, &session.verbose , "-v", "be verbose"}, {1, 0, 0 , "\n Other:", ""}, /*@OPTION No cache ( -n ) Do not use cache when building. @END*/ {1, 0, &option_no_cache , "-n", "don't use cache"}, /*@OPTION Help ( -h, --help ) Prints out a short reference of the command line options and quits directly after. @END*/ {1, 0, &option_print_help , "-h, --help", "prints this help"}, {0, 0, &option_print_help , "-h", "prints this help"}, {0, 0, &option_print_help , "--help", "prints this help"}, {1, 0, 0 , "\n Debug:", ""}, /*@OPTION Debug: Dump Nodes ( --debug-nodes ) Dumps all nodes in the dependency graph. @END*/ {1, 0, &option_debug_nodes , "--debug-nodes", "prints all the nodes with dependencies"}, /*@OPTION Debug: Dump Nodes Detailed ( --debug-detail ) Dumps all nodes in the dependency graph, their state and their dependent nodes. This is useful if you are writing your own actions to verify that dependencies are correctly added. @END*/ {1, 0, &option_debug_nodes_detailed , "--debug-detail", "prints all the nodes with dependencies and details"}, /*@OPTION Debug: Dump Jobs ( --debug-jobs ) @END*/ {1, 0, &option_debug_jobs , "--debug-jobs", "prints all the jobs that exist"}, /*@OPTION Debug: Dump Dot ( --debug-dot ) Dumps all nodes in the dependency graph into a dot file that can be rendered with graphviz. @END*/ {1, 0, &option_debug_dot , "--debug-dot", "prints all nodes as a graphviz dot file"}, /*@OPTION Debug: Dump Jobs Dot ( --debug-jobs-dot ) Dumps all jobs and their dependent jobs into a dot file that can be rendered with graphviz. @END*/ {1, 0, &option_debug_jobs_dot , "--debug-jobs-dot", "prints all jobs as a graphviz dot file"}, /*@OPTION Debug: Trace VM ( --debug-trace-vm ) Prints a the function and source line for every instruction that the vm makes. @END*/ {1, 0, &option_debug_trace_vm , "--debug-trace-vm", "prints a line for every instruction the vm makes"}, /*@OPTION Debug: Dump Internal Scripts ( --debug-dump-int ) @END*/ {1, 0, &option_debug_dumpinternal , "--debug-dump-int", "prints the internals scripts to stdout"}, /*@OPTION Debug: No Internal ( --debug-no-int ) Disables all the internal scripts that bam loads on startup. @1, END*/ {1, 0, &option_debug_nointernal , "--debug-no-int", "don't load internal scripts"}, /* terminate list */ {0, 0, 0, (const char*)0, (const char*)0} }; static const char *internal_base_reader(lua_State *L, void *data, size_t *size) { char **p = (char **)data; if(!*p) return 0; *size = strlen(*p); data = *p; *p = 0; return data; } static void lua_setglobalstring(lua_State *L, const char *field, const char *s) { lua_pushstring(L, s); lua_setglobal(L, field); } static void lua_vm_trace_hook(lua_State *L, lua_Debug *ar) { lua_getinfo(L, "nSl", ar); if(ar->name) printf("%s %s %d\n", ar->name, ar->source, ar->currentline); } static void *lua_alloctor_malloc(void *ud, void *ptr, size_t osize, size_t nsize) { if (nsize == 0) { free(ptr); return NULL; } return realloc(ptr, nsize); } /* *** */ int register_lua_globals(struct CONTEXT *context) { int i, error = 0; /* add standard libs */ luaL_openlibs(context->lua); /* add specific functions */ lua_register(context->lua, L_FUNCTION_PREFIX"add_job", lf_add_job); lua_register(context->lua, L_FUNCTION_PREFIX"add_output", lf_add_output); lua_register(context->lua, L_FUNCTION_PREFIX"add_pseudo", lf_add_pseudo); lua_register(context->lua, L_FUNCTION_PREFIX"add_dependency", lf_add_dependency); lua_register(context->lua, L_FUNCTION_PREFIX"add_constraint_shared", lf_add_constraint_shared); lua_register(context->lua, L_FUNCTION_PREFIX"add_constraint_exclusive", lf_add_constraint_exclusive); lua_register(context->lua, L_FUNCTION_PREFIX"default_target", lf_default_target); lua_register(context->lua, L_FUNCTION_PREFIX"set_touch", lf_set_touch); lua_register(context->lua, L_FUNCTION_PREFIX"set_filter", lf_set_filter); /* advanced dependency checkers */ lua_register(context->lua, L_FUNCTION_PREFIX"add_dependency_cpp_set_paths", lf_add_dependency_cpp_set_paths); lua_register(context->lua, L_FUNCTION_PREFIX"add_dependency_cpp", lf_add_dependency_cpp); lua_register(context->lua, L_FUNCTION_PREFIX"add_dependency_search", lf_add_dependency_search); /* path manipulation */ lua_register(context->lua, L_FUNCTION_PREFIX"path_join", lf_path_join); lua_register(context->lua, L_FUNCTION_PREFIX"path_normalize", lf_path_normalize); lua_register(context->lua, L_FUNCTION_PREFIX"path_isnice", lf_path_isnice); lua_register(context->lua, L_FUNCTION_PREFIX"path_ext", lf_path_ext); lua_register(context->lua, L_FUNCTION_PREFIX"path_dir", lf_path_dir); lua_register(context->lua, L_FUNCTION_PREFIX"path_base", lf_path_base); lua_register(context->lua, L_FUNCTION_PREFIX"path_filename", lf_path_filename); /* various support functions */ lua_register(context->lua, L_FUNCTION_PREFIX"collect", lf_collect); lua_register(context->lua, L_FUNCTION_PREFIX"collectrecursive", lf_collectrecursive); lua_register(context->lua, L_FUNCTION_PREFIX"collectdirs", lf_collectdirs); lua_register(context->lua, L_FUNCTION_PREFIX"collectdirsrecursive", lf_collectdirsrecursive); lua_register(context->lua, L_FUNCTION_PREFIX"listdir", lf_listdir); lua_register(context->lua, L_FUNCTION_PREFIX"update_globalstamp", lf_update_globalstamp); lua_register(context->lua, L_FUNCTION_PREFIX"loadfile", lf_loadfile); lua_register(context->lua, L_FUNCTION_PREFIX"load_plugin", lf_loadplugin); lua_register(context->lua, L_FUNCTION_PREFIX"mkdir", lf_mkdir); lua_register(context->lua, L_FUNCTION_PREFIX"fileexist", lf_fileexist); lua_register(context->lua, L_FUNCTION_PREFIX"isstring", lf_isstring); lua_register(context->lua, L_FUNCTION_PREFIX"istable", lf_istable); lua_register(context->lua, L_FUNCTION_PREFIX"table_walk", lf_table_walk); lua_register(context->lua, L_FUNCTION_PREFIX"table_deepcopy", lf_table_deepcopy); lua_register(context->lua, L_FUNCTION_PREFIX"table_tostring", lf_table_tostring); lua_register(context->lua, L_FUNCTION_PREFIX"table_flatten", lf_table_flatten); /* error handling */ lua_register(context->lua, "errorfunc", lf_errorfunc); /* create arguments table */ lua_pushstring(context->lua, CONTEXT_LUA_SCRIPTARGS_TABLE); lua_newtable(context->lua); for(i = 0; i < option_num_scriptargs; i++) { const char *separator = option_scriptargs[i]; while(*separator != '=') separator++; lua_pushlstring(context->lua, option_scriptargs[i], separator-option_scriptargs[i]); lua_pushstring(context->lua, separator+1); lua_settable(context->lua, -3); } lua_settable(context->lua, LUA_GLOBALSINDEX); /* create targets table */ lua_pushstring(context->lua, CONTEXT_LUA_TARGETS_TABLE); lua_newtable(context->lua); for(i = 0; i < option_num_targets; i++) { lua_pushstring(context->lua, option_targets[i]); lua_rawseti(context->lua, -2, i); } lua_settable(context->lua, LUA_GLOBALSINDEX); /* set paths */ { char cwd[MAX_PATH_LENGTH]; if(!getcwd(cwd, sizeof(cwd))) { printf("%s: error: couldn't get current working directory\n", session.name); return -1; } lua_setglobalstring(context->lua, CONTEXT_LUA_PATH, context->script_directory); lua_setglobalstring(context->lua, CONTEXT_LUA_WORKPATH, cwd); } /* set version, family, platform, arch, verbocity */ lua_setglobalstring(context->lua, "_bam_version", BAM_VERSION_STRING); lua_setglobalstring(context->lua, "_bam_version_complete", BAM_VERSION_STRING_COMPLETE); lua_setglobalstring(context->lua, "family", BAM_FAMILY_STRING); lua_setglobalstring(context->lua, "platform", BAM_PLATFORM_STRING); lua_setglobalstring(context->lua, "arch", BAM_ARCH_STRING); lua_setglobalstring(context->lua, "_bam_exe", session.exe); lua_pushnumber(context->lua, session.verbose); lua_setglobal(context->lua, "verbose"); if(option_debug_trace_vm) lua_sethook(context->lua, lua_vm_trace_hook, LUA_MASKCOUNT, 1); /* load base script */ if(!option_debug_nointernal) { int ret; const char *p; int f; for(f = 0; internal_files[f].filename; f++) { p = internal_files[f].content; if(session.verbose) printf("%s: reading internal file '%s'\n", session.name, internal_files[f].filename); lua_getglobal(context->lua, "errorfunc"); /* push error function to stack */ ret = lua_load(context->lua, internal_base_reader, (void *)&p, internal_files[f].filename); if(ret != 0) { lf_errorfunc(context->lua); if(ret == LUA_ERRSYNTAX) { } else if(ret == LUA_ERRMEM) printf("%s: memory allocation error\n", session.name); else printf("%s: unknown error parsing base script\n", session.name); error = 1; } else if(lua_pcall(context->lua, 0, LUA_MULTRET, -2) != 0) error = 1; } } return error; } static int run_deferred_functions(struct CONTEXT *context) { struct DEFERRED *cur; for(cur = context->firstdeferred; cur; cur = cur->next) { if(cur->run(context, cur)) return -1; } return 0; } static int bam_setup(struct CONTEXT *context, const char *scriptfile, const char **targets, int num_targets) { /* */ if(session.verbose) printf("%s: setup started\n", session.name); /* set filename */ context->filename = scriptfile; context->filename_short = path_filename(scriptfile); /* set global timestamp to the script file */ context->globaltimestamp = file_timestamp(scriptfile); /* fetch script directory */ { char cwd[MAX_PATH_LENGTH]; char path[MAX_PATH_LENGTH]; if(!getcwd(cwd, sizeof(cwd))) { printf("%s: error: couldn't get current working directory\n", session.name); return -1; } if(path_directory(context->filename, path, sizeof(path))) { printf("%s: error: path too long '%s'\n", session.name, path); return -1; } if(path_join(cwd, -1, path, -1, context->script_directory, sizeof(context->script_directory))) { printf("%s: error: path too long when joining '%s' and '%s'\n", session.name, cwd, path); return -1; } } /* register all functions */ if(register_lua_globals(context) != 0) { printf("%s: error: registering of lua functions failed\n", session.name); return -1; } /* load script */ if(session.verbose) printf("%s: reading script from '%s'\n", session.name, scriptfile); /* push error function to stack and load the script */ lua_getglobal(context->lua, "errorfunc"); switch(luaL_loadfile(context->lua, scriptfile)) { case 0: break; case LUA_ERRSYNTAX: lf_errorfunc(context->lua); return -1; case LUA_ERRMEM: printf("%s: memory allocation error\n", session.name); return -1; case LUA_ERRFILE: printf("%s: error opening '%s'\n", session.name, scriptfile); return -1; default: printf("%s: unknown error\n", session.name); return -1; } /* call the code chunk */ if(lua_pcall(context->lua, 0, LUA_MULTRET, -2) != 0) { printf("%s: script error (-t for more detail)\n", session.name); return -1; } /* run deferred functions */ if(run_deferred_functions(context) != 0) return -1; /* */ if(session.verbose) printf("%s: making build target\n", session.name); /* make build target */ { struct NODE *node; int all_target = 0; int i; if(node_create(&context->target, context->graph, "_bam_buildtarget", 0, 0)) return -1; node_set_pseudo(context->target); if(num_targets) { /* search for all target */ for(i = 0; i < num_targets; i++) { if(strcmp(targets[i], "all") == 0) { all_target = 1; break; } } } /* default too all if we have no targets or default target */ if(num_targets == 0 && !context->defaulttarget) all_target = 1; if(all_target) { /* build the all target */ for(node = context->graph->first; node; node = node->next) { if(node->firstparent == NULL && node != context->target) { if(!node_add_dependency_withnode(context->target, node)) return -1; } } } else { if(num_targets) { for(i = 0; i < num_targets; i++) { struct NODE *node = node_find(context->graph, targets[i]); if(!node) { printf("%s: target '%s' not found\n", session.name, targets[i]); return -1; } if(option_dependent) { /* TODO: this should perhaps do a reverse walk up in the tree to find all dependent node with commandline */ struct NODELINK *parent; for(parent = node->firstparent; parent; parent = parent->next) { if(!node_add_dependency_withnode(context->target, parent->node)) return -1; } } else { if(!node_add_dependency_withnode(context->target, node)) return -1; } } } else { if(!node_add_dependency_withnode(context->target, context->defaulttarget)) return -1; } } } /* */ if(session.verbose) printf("%s: setup done\n", session.name); /* return success */ return 0; } /* *** */ static int bam(const char *scriptfile, const char **targets, int num_targets) { struct CONTEXT context; int build_error = 0; int setup_error = 0; int report_done = 0; /* build time */ time_t starttime = time(0x0); /* zero out and create memory heap, graph */ memset(&context, 0, sizeof(struct CONTEXT)); context.graphheap = mem_create(); context.deferredheap = mem_create(); context.graph = node_create_graph(context.graphheap); context.exit_on_error = option_abort_on_error; context.buildtime = timestamp(); /* create lua context */ /* HACK: Store the context pointer as the userdata pointer to the allocator to make sure that we have fast access to it. This makes the context_get_pointer call very fast */ context.lua = lua_newstate(lua_alloctor_malloc, &context); /* install panic function */ lua_atpanic(context.lua, lf_panicfunc); /* load cache (thread?) */ if(option_no_cache == 0) { /* create a hash of all the external variables that can cause the script to generate different results */ unsigned int cache_hash = 0; int i; for(i = 0; i < option_num_scriptargs; i++) cache_hash = string_hash_add(cache_hash, option_scriptargs[i]); sprintf(cache_filename, ".bam/%08x", cache_hash); context.cache = cache_load(cache_filename); } /* do the setup */ setup_error = bam_setup(&context, scriptfile, targets, num_targets); /* done with the loopup heap */ mem_destroy(context.deferredheap); /* if we have a separate lua heap, just destroy it */ if(context.luaheap) mem_destroy(context.luaheap); else lua_close(context.lua); /* do actions if we don't have any errors */ if(!setup_error) { build_error = context_build_prepare(&context); if(!build_error) { if(option_debug_nodes) /* debug dump all nodes */ node_debug_dump(context.graph); else if(option_debug_nodes_detailed) /* debug dump all nodes detailed */ node_debug_dump_detailed(context.graph); else if(option_debug_jobs) /* debug dump all jobs */ node_debug_dump_jobs(context.graph); else if(option_debug_dot) /* debug dump all nodes as dot */ node_debug_dump_dot(context.graph, context.target); else if(option_debug_jobs_dot) /* debug dump all jobs as dot */ node_debug_dump_jobs_dot(context.graph, context.target); else if(option_dry) { } else { /* run build or clean */ if(option_clean) build_error = context_build_clean(&context); else { build_error = context_build_make(&context); report_done = 1; } } } } /* save cache (thread?) */ if(option_no_cache == 0 && setup_error == 0) { /* create the cache directory */ file_createdir(".bam"); cache_save(cache_filename, context.graph); } /* clean up */ mem_destroy(context.graphheap); /* print final report and return */ if(setup_error) { /* no error message on setup error, it reports fine itself */ return setup_error; } else if(build_error) printf("%s: error: a build step failed\n", session.name); else if(report_done) { if(context.num_commands == 0) printf("%s: targets are up to date already\n", session.name); else { time_t s = time(0x0) - starttime; if(s <= 1) printf("%s: done\n", session.name); else printf("%s: done (%d:%.2d)\n", session.name, (int)(s/60), (int)(s%60)); } } return build_error; } /* signal handler */ static void abortsignal(int i) { (void)i; printf("%s: signal cought, waiting for jobs to finish\n", session.name); session.abort = 1; } void install_abort_signal() { install_signals(abortsignal); } /* */ static void print_help() { int j; printf("Usage: %s [OPTION]... [VARIABLE=VALUE]... [TARGET]...\n", session.name); printf("Builds applications using the bam build system.\n"); for(j = 0; options[j].sw; j++) { if(options[j].print) printf(" %-20s %s\n", options[j].sw, options[j].desc); } printf("\n"); printf("bam version " BAM_VERSION_STRING_COMPLETE ". built "__DATE__" "__TIME__" using " LUA_VERSION "\n"); printf("by Magnus Auvinen (magnus.auvinen@gmail.com)\n"); printf("\n"); } static int parse_parameters(int num, char **params) { int i, j; /* parse parameters */ for(i = 0; i < num; ++i) { for(j = 0; options[j].sw; j++) { if(strcmp(params[i], options[j].sw) == 0) { if(options[j].s) { if(i+1 >= num) { printf("%s: you must supply a argument with %s\n", session.name, options[j].sw); return -1; } i++; *options[j].s = params[i]; } else *options[j].v = 1; j = -1; break; } } if(j != -1) { /* check if it's an option, and warn if it could not be found */ if(params[i][0] == '-') { printf("%s: unknown switch '%s'\n", session.name, params[i]); return -1; } else { /* check for = because it indicates if it's a target or script argument */ if(strchr(params[i], '=')) option_scriptargs[option_num_scriptargs++] = params[i]; else option_targets[option_num_targets++] = params[i]; } } } return 0; } static int parse_parameters_str(const char *str) { char *ptrs[64]; int num_ptrs = 0; char buffer[1024]; char *start = buffer; char *current = start; char *end = buffer+sizeof(buffer); int string_parse = 0; ptrs[0] = start; while(1) { /* fetch next character */ char c = *str++; if(string_parse) { if(c == '"') string_parse = 0; else if(*str == 0) { printf("%s: error: unterminated \"\n", session.name); return -1; } else *current++ = c; } else { if(c == ' ' || c == '\t' || c == 0) { /* zero term and add this ptr */ *current++ = 0; num_ptrs++; ptrs[num_ptrs] = current; } else if(c == '"') string_parse = 1; else *current++ = c; } if(current == end) { printf("%s: error: argument too long\n", session.name); return -1; } /* break out on zero term */ if(!c) break; } /* parse all the parameters */ return parse_parameters(num_ptrs, ptrs); } /* ********* */ int main(int argc, char **argv) { int i, error; /* init platform */ platform_init(); /* set exe */ session.exe = argv[0]; /* fetch program name, if we can */ for(i = 0; argv[0][i]; ++i) { if(argv[0][i] == '/' || argv[0][i] == '\\') session.name = &argv[0][i+1]; } /* parse environment parameters */ if(getenv("BAM_OPTIONS")) { if(parse_parameters_str(getenv("BAM_OPTIONS"))) return -1; } /* parse commandline parameters */ if(parse_parameters(argc-1, argv+1)) return -1; /* parse the report str */ for(i = 0; option_report_str[i]; i++) { if(option_report_str[i] == 'c') session.report_color = 1; else if(option_report_str[i] == 'b') session.report_bar = 1; else if(option_report_str[i] == 's') session.report_steps = 1; } /* convert the threads string */ session.threads = atoi(option_threads_str); if(session.threads < 0) { printf("%s: invalid number of threads supplied\n", session.name); return 1; } /* check for help argument */ if(option_print_help) { print_help(); return 0; } /* */ if(option_debug_dumpinternal) { int f; for(f = 0; internal_files[f].filename; f++) { printf("%s:\n", internal_files[f].filename); puts(internal_files[f].content); } return 0; } /* init the context */ error = bam(option_script, option_targets, option_num_targets); platform_shutdown(); /* error could be some high value like 256 seams like this could */ /* be clamped down to a unsigned char and not be an error anymore */ if(error) return 1; return 0; } bam-0.4.0/src/luafuncs.h0000644000175000017500000000320711430042030013121 0ustar kmakma /* support functions */ struct STRINGLIST { struct STRINGLIST *next; const char *str; size_t len; }; void build_stringlist(lua_State *L, struct HEAP *heap, struct STRINGLIST **first, int table_index); /* jobs and deps */ int lf_add_job(struct lua_State *L); int lf_add_output(struct lua_State *L); int lf_add_pseudo(struct lua_State *L); int lf_add_dependency(struct lua_State *L); int lf_add_constraint_shared(struct lua_State *L); int lf_add_constraint_exclusive(struct lua_State *L); int lf_set_touch(struct lua_State *L); int lf_set_filter(struct lua_State *L); int lf_default_target(struct lua_State *L); int lf_update_globalstamp(struct lua_State *L); /* dependency */ int lf_add_dependency_cpp_set_paths(lua_State *L); /* dep_cpp.c */ int lf_add_dependency_cpp(lua_State *L); /* dep_cpp.c */ int lf_add_dependency_search(lua_State *L); /* dep_search.c */ /* lua file and directory discovery */ int lf_collect(struct lua_State *L); int lf_collectrecursive(struct lua_State *L); int lf_collectdirs(struct lua_State *L); int lf_collectdirsrecursive(struct lua_State *L); int lf_listdir(struct lua_State *L); /* support, files and dirs */ int lf_mkdir(struct lua_State *L); int lf_fileexist(struct lua_State *L); /* table functions*/ int lf_table_walk(struct lua_State *L); int lf_table_deepcopy(struct lua_State *L); int lf_table_tostring(struct lua_State *L); int lf_table_flatten(struct lua_State *L); /* support, misc */ int lf_istable(struct lua_State *L); int lf_isstring(struct lua_State *L); int lf_loadfile(struct lua_State *L); int lf_errorfunc(struct lua_State *L); int lf_panicfunc(struct lua_State *L); int lf_loadplugin(struct lua_State *L); bam-0.4.0/src/platform.h0000644000175000017500000000543111430042030013126 0ustar kmakma/* platforms */ /* windows family */ #if defined(WIN64) || defined(_WIN64) /* hmm, is this IA64 or x86-64? */ #define BAM_FAMILY_WINDOWS #define BAM_FAMILY_STRING "windows" #define BAM_PLATFORM_WIN64 #define BAM_PLATFORM_STRING "win64" #elif defined(WIN32) || defined(_WIN32) || defined(__MINGW32__) #define BAM_FAMILY_WINDOWS #define BAM_FAMILY_STRING "windows" #define BAM_PLATFORM_WIN32 #define BAM_PLATFORM_STRING "win32" #elif defined(CYGWIN) || defined(__CYGWIN__) || defined(__CYGWIN32__) #define BAM_FAMILY_UNIX #define BAM_FAMILY_STRING "unix" #define BAM_PLATFORM_CYGWIN #define BAM_PLATFORM_STRING "cygwin" #endif /* unix family */ #if defined(__FreeBSD__) #define BAM_FAMILY_UNIX #define BAM_FAMILY_STRING "unix" #define BAM_PLATFORM_FREEBSD #define BAM_PLATFORM_STRING "freebsd" #endif #if defined(__OpenBSD__) #define BAM_FAMILY_UNIX #define BAM_FAMILY_STRING "unix" #define BAM_PLATFORM_OPENBSD #define BAM_PLATFORM_STRING "openbsd" #endif #if defined(__LINUX__) || defined(__linux__) #define BAM_FAMILY_UNIX #define BAM_FAMILY_STRING "unix" #define BAM_PLATFORM_LINUX #define BAM_PLATFORM_STRING "linux" #endif #if defined(__GNU__) || defined(__gnu__) #define BAM_FAMILY_UNIX #define BAM_FAMILY_STRING "unix" #define BAM_PLATFORM_HURD #define BAM_PLATFORM_STRING "gnu" #endif #if defined(MACOSX) || defined(__APPLE__) || defined(__DARWIN__) #define BAM_FAMILY_UNIX #define BAM_FAMILY_STRING "unix" #define BAM_PLATFORM_MACOSX #define BAM_PLATFORM_STRING "macosx" #endif #if defined(__sun) #define BAM_FAMILY_UNIX #define BAM_FAMILY_STRING "unix" #define BAM_PLATFROM_SOLARIS #define BAM_PLATFORM_STRING "solaris" #endif /* beos family */ #if defined(__BeOS) || defined(__BEOS__) #define BAM_FAMILY_BEOS #define BAM_FAMILY_STRING "beos" #define BAM_PLATFORM_BEOS #define BAM_PLATFORM_STRING "beos" #endif #if defined(__HAIKU) || defined(__HAIKU__) #define BAM_FAMILY_BEOS #define BAM_FAMILY_STRING "beos" #define BAM_PLATFORM_BEOS #define BAM_PLATFORM_STRING "haiku" #endif /* architectures */ #if defined(i386) || defined(__i386__) || defined(__x86__) || defined(i386_AT386) || defined(BAM_PLATFORM_WIN32) #define BAM_ARCH_IA32 #define BAM_ARCH_STRING "ia32" #endif #if defined(__ia64__) #define BAM_ARCH_IA64 #define BAM_ARCH_STRING "ia64" #endif #if defined(__amd64__) || defined(__x86_64__) #define BAM_ARCH_AMD64 #define BAM_ARCH_STRING "amd64" #endif #if defined(__powerpc__) || defined(__ppc__) #define BAM_ARCH_PPC #define BAM_ARCH_STRING "ppc" #endif #if defined(__sparc__) #define BAM_ARCH_SPARC #define BAM_ARCH_STRING "sparc" #endif #ifndef BAM_FAMILY_STRING #define BAM_FAMILY_STRING "unknown" #endif #ifndef BAM_PLATFORM_STRING #define BAM_PLATFORM_STRING "unknown" #endif #ifndef BAM_ARCH_STRING #define BAM_ARCH_STRING "unknown" #endif bam-0.4.0/src/support.h0000644000175000017500000000146211430042030013016 0ustar kmakma void install_signals(void (*abortsignal)(int)); int run_command(const char *cmd, const char *filter); void platform_init(); void platform_shutdown(); /* threading */ void *threads_create(void (*threadfunc)(void *), void *u); void threads_join(void *thread); void threads_yield(); void criticalsection_enter(); void criticalsection_leave(); /* filesystem and timestamps */ time_t timestamp(); time_t file_timestamp(const char *filename); int file_exist(const char *filename); int file_createdir(const char *path); void file_touch(const char *filename); /* plugin related */ typedef int (*PLUGINFUNC)(struct lua_State *); PLUGINFUNC plugin_load(const char *filename); /* string hashing function */ unsigned int string_hash(const char *str_in); unsigned int string_hash_add(unsigned int base, const char *str_in); bam-0.4.0/src/context.c0000644000175000017500000003121011430042030012753 0ustar kmakma#define LUA_CORE /* make sure that we don't try to import these functions */ #include #include #include /* system() */ #include "mem.h" #include "context.h" #include "path.h" #include "node.h" #include "cache.h" #include "support.h" #include "session.h" const char *CONTEXT_LUA_SCRIPTARGS_TABLE = "_bam_scriptargs"; const char *CONTEXT_LUA_TARGETS_TABLE = "_bam_targets"; const char *CONTEXT_LUA_PATH = "_bam_path"; const char *CONTEXT_LUA_WORKPATH = "_bam_workpath"; /* */ struct CONTEXT *context_get_pointer(lua_State *L) { /* HACK: we store the context pointer as the user data to to the allocator for fast access to it */ void *context; lua_getallocf(L, &context); return (struct CONTEXT*)context; } /* */ const char *context_get_path(lua_State *L) { const char *path; lua_pushstring(L, CONTEXT_LUA_PATH); lua_gettable(L, LUA_GLOBALSINDEX); path = lua_tostring(L, -1); lua_pop(L, 1); return path; } int context_default_target(struct CONTEXT *context, struct NODE *node) { context->defaulttarget = node; return 0; } static void progressbar_clear() { printf(" \r"); } static void progressbar_draw(struct CONTEXT *context) { const int max = 40; int i; int count = (context->current_cmd_num*max)/context->num_commands; int precent = (context->current_cmd_num*100)/context->num_commands; if(session.report_color) { printf(" %3d%% \033[01;32m[\033[01;33m", precent); for(i = 0; i < count-1; i++) printf("="); printf(">"); for(; i < max; i++) printf(" "); printf("\033[01;32m]\033[00m\r"); } else { printf(" %3d%% [", precent); for(i = 0; i < count-1; i++) printf("="); printf(">"); for(; i < max; i++) printf(" "); printf("]\r"); } } static void constraints_update(struct NODE *node, int direction) { struct NODELINK *link; for(link = node->constraint_shared; link; link = link->next) link->node->constraint_shared_count += direction; for(link = node->constraint_exclusive; link; link = link->next) link->node->constraint_exclusive_count += direction; } /* returns 0 if there are no constraints that are conflicting */ static int constraints_check(struct NODE *node) { struct NODELINK *link; for(link = node->constraint_shared; link; link = link->next) { if(link->node->constraint_exclusive_count) return 1; } for(link = node->constraint_exclusive; link; link = link->next) { if(link->node->constraint_exclusive_count || link->node->constraint_shared_count) return 1; } return 0; } static int create_path(const char *output_name) { char buffer[MAX_PATH_LENGTH]; int i; char t; /* fish out the directory */ if(path_directory(output_name, buffer, sizeof(buffer)) != 0) { fprintf(stderr, "path error: %s\n", buffer); return -1; } /* no directory in path */ if(buffer[0] == 0) return 0; /* check if we need to do a deep walk */ if(file_createdir(buffer) == 0) return 0; /* create dir by doing a deep walk */ i = 0; while(1) { if((buffer[i] == '/') || (buffer[i] == 0)) { /* insert null terminator */ t = buffer[i]; buffer[i] = 0; if(file_createdir(buffer) != 0) { fprintf(stderr, "path error2: %s\n", buffer); return -1; } /* restore the path */ buffer[i] = t; } if(buffer[i] == 0) break; i++; } /* return success */ return 0; } static int run_node(struct CONTEXT *context, struct NODE *node, int thread_id) { static const char *format = 0; int ret; if(node->cmdline) { context->current_cmd_num++; if(!format) { static char buf[64]; int num = 0; int c = context->num_commands; for(; c; c /= 10) num++; if(session.report_color) sprintf(buf, "\033[01;32m[%%%dd/%%%dd] \033[01;36m#%%d\033[00m %%s\n", num, num); else sprintf(buf, "[%%%dd/%%%dd] #%%d %%s\n", num, num); format = buf; } if(session.report_bar) progressbar_clear(); if(session.report_steps) { if(session.simpleoutput) printf("%s", node->label); else printf(format, context->current_cmd_num, context->num_commands, thread_id, node->label); } if(session.report_bar) progressbar_draw(context); } if(session.verbose) { if(session.report_color) printf("\033[01;33m%s\033[00m\n", node->cmdline); else printf("%s\n", node->cmdline); } fflush(stdout); /* create output path */ /* TODO: perhaps we can skip running this if we know that the file exists on disk already */ if(create_path(node->filename) != 0) { if(session.report_color) printf("\033[01;31m"); printf("%s: could not create output directory for '%s'\n", session.name, node->filename); if(session.report_color) printf("\033[00m"); fflush(stdout); return 1; } /* add constraints count */ constraints_update(node, 1); /* execute the command */ criticalsection_leave(); ret = run_command(node->cmdline, node->filter); if(node->touch && ret == 0) file_touch(node->filename); criticalsection_enter(); /* sub constraints count */ constraints_update(node, -1); if(ret) { if(session.report_color) printf("\033[01;31m"); printf("%s: '%s' error %d\n", session.name, node->filename, ret); if(file_timestamp(node->filename) != node->timestamp_raw) { remove(node->filename); printf("%s: '%s' removed because job updated it even it failed.\n", session.name, node->filename); } if(session.report_color) printf("\033[00m"); fflush(stdout); } return ret; } struct THREADINFO { int id; struct CONTEXT *context; int errorcode; }; static int threads_run_callback(struct NODEWALK *walkinfo) { struct NODE *node = walkinfo->node; struct THREADINFO *info = (struct THREADINFO *)walkinfo->user; struct NODELINK *dep; int errorcode = 0; /* check for aborts */ if(session.abort) return -1; /* check global error code so we know if we should exit */ if(info->context->exit_on_error && info->context->errorcode) return info->context->errorcode; /* make sure that all deps are done and propagate broken status */ for(dep = node->firstjobdep; dep; dep = dep->next) { if(dep->node->workstatus == NODESTATUS_BROKEN) { node->workstatus = NODESTATUS_BROKEN; return info->context->errorcode; } if(dep->node->dirty && dep->node->workstatus != NODESTATUS_DONE) return 0; } /* if it doesn't have a tool, just mark it as done and continue the search */ if(!node->cmdline) { node->workstatus = NODESTATUS_DONE; return 0; } /* check if constraints allows it */ if(constraints_check(node)) return 0; /* mark the node as its in the working */ node->workstatus = NODESTATUS_WORKING; /* run the node */ if(node->cmdline) errorcode = run_node(info->context, node, info->id+1); /* this node is done, mark it so and return the error code */ if(errorcode) { node->workstatus = NODESTATUS_BROKEN; /* set global error code */ info->context->errorcode = errorcode; } else { /* node is done, update the cache hash we we don't have to rebuild this one */ node->workstatus = NODESTATUS_DONE; node->cachehash = node->cmdhash; } return errorcode; } static void threads_run(void *u) { struct THREADINFO *info = (struct THREADINFO *)u; struct NODE *target = info->context->target; int flags = NODEWALK_BOTTOMUP|NODEWALK_UNDONE|NODEWALK_QUICK|NODEWALK_JOBS; info->errorcode = 0; /* lock the dependency graph */ criticalsection_enter(); install_abort_signal(); if(target->dirty) { while(1) { info->errorcode = node_walk(target, flags, threads_run_callback, info); if(session.abort) break; /* check if we are done */ if(target->workstatus != NODESTATUS_UNDONE) break; if(info->context->exit_on_error && info->context->errorcode) break; /* let the others have some time */ criticalsection_leave(); threads_yield(); criticalsection_enter(); } } criticalsection_leave(); } int context_build_make(struct CONTEXT *context) { /* multithreaded */ struct THREADINFO info[64]; void *threads[64]; int i; /* clamp number of threads */ if(session.threads > 64) session.threads = 64; else if(session.threads < 1) session.threads = 1; for(i = 0; i < session.threads; i++) { info[i].context = context; info[i].id = i; info[i].errorcode = 0; } if(session.threads <= 1) { /* no threading, use this thread then */ threads_run(&info[0]); if(session.report_bar) progressbar_clear(); return info[0].errorcode; } else { /* start threads */ for(i = 0; i < session.threads; i++) threads[i] = threads_create(threads_run, &info[i]); /* wait for threads */ for(i = 0; i < session.threads; i++) threads_join(threads[i]); if(session.report_bar) progressbar_clear(); /* check for error codes */ for(i = 0; i < session.threads; i++) { if(info[i].errorcode) return info[i].errorcode; } } return 0; } static int build_clean_callback(struct NODEWALK *walkinfo) { struct NODE *node = walkinfo->node; /* no tool, no processing */ if(!node->cmdline) return 0; if(node->timestamp) { if(remove(node->filename) == 0) printf("%s: removed '%s'\n", session.name, node->filename); } return 0; } int context_build_clean(struct CONTEXT *context) { return node_walk(context->target, NODEWALK_BOTTOMUP|NODEWALK_FORCE|NODEWALK_QUICK, build_clean_callback, 0); } static int build_prepare_callback(struct NODEWALK *walkinfo) { struct NODE *node = walkinfo->node; struct CONTEXT *context = (struct CONTEXT *)walkinfo->user; struct CACHENODE *cachenode; struct NODELINK *dep; struct NODELINK *parent; struct NODELINK *jobdep; struct NODEWALKPATH *path; time_t oldtimestamp = node->timestamp; /* to keep track of if this node changes */ int olddirty = node->dirty; struct NODELINK *oldjobdep = node->firstjobdep; if(node->depth < walkinfo->depth) node->depth = walkinfo->depth; /* time sanity check */ if(node->timestamp > context->buildtime) printf("%s: WARNING:'%s' comes from the future\n", session.name, node->filename); if(node->cmdline) { /* dirty checking, check against cmdhash and global timestamp first */ cachenode = cache_find_byhash(context->cache, node->hashid); if(cachenode) { node->cachehash = cachenode->cmdhash; if(node->cachehash != node->cmdhash) node->dirty = NODEDIRTY_CMDHASH; } else if(node->timestamp < context->globaltimestamp) node->dirty = NODEDIRTY_GLOBALSTAMP; } else if(node->timestamp_raw == 0) { printf("%s: error: '%s' does not exist and no way to generate it\n", session.name, node->filename); return 1; } /* check against all the dependencies */ for(dep = node->firstdep; dep; dep = dep->next) { if(dep->node->cmdline) { /* do circular action dependency checking */ for(path = walkinfo->parent; path; path = path->parent) { if(path->node == dep->node) { printf("error: circular dependency found\n"); printf("\t%s\n", dep->node->filename); for(path = walkinfo->parent; path; path = path->parent) printf("\t%s\n", path->node->filename); return -1; } } /* propagate job dependencies */ node_add_job_dependency_withnode(node, dep->node); } else { /* propagate job dependencies */ for(jobdep = dep->node->firstjobdep; jobdep; jobdep = jobdep->next) node_add_job_dependency_withnode(node, jobdep->node); } /* update dirty */ if(!node->dirty) { if(dep->node->dirty) node->dirty = NODEDIRTY_DEPDIRTY; else if(node->timestamp < dep->node->timestamp) { if(node->cmdline) node->dirty = NODEDIRTY_DEPNEWER; else /* no cmdline, just propagate the timestamp */ node->timestamp = dep->node->timestamp; } } } /* mark as targeted */ if(!walkinfo->revisiting) node->targeted = 1; /* invalidate the cache cmd hash if we are dirty because we could be dirty because if a dependency is missing */ if(node->dirty) node->cachehash = 0; /* count commands */ if(node->cmdline && node->dirty && !node->counted && node->targeted) { node->counted = 1; context->num_commands++; } /* check if we should revisit it's parents to propagate the dirty state and timestamp. this can cause us to go outside the targeted nodes and into nodes that are not targeted. be aware */ if(olddirty != node->dirty || oldtimestamp != node->timestamp || oldjobdep != node->firstjobdep) { for(parent = node->firstparent; parent; parent = parent->next) node_walk_revisit(walkinfo, parent->node); } return 0; } /* prepare does time sanity checking, dirty propagation, graph validation and job counting */ int context_build_prepare(struct CONTEXT *context) { /* revisit is used here to solve the problems where we have circular dependencies */ return node_walk(context->target, NODEWALK_BOTTOMUP|NODEWALK_FORCE|NODEWALK_REVISIT, build_prepare_callback, context); } bam-0.4.0/src/dep_search.c0000644000175000017500000000607011430042030013372 0ustar kmakma/*#include #include #include */ #define LUA_CORE /* make sure that we don't try to import these functions */ #include #include #include "path.h" #include "context.h" #include "mem.h" #include "node.h" #include "support.h" #include "luafuncs.h" struct DEPPLAIN { struct STRINGLIST *firstpath; struct STRINGLIST *firstdep; }; /* returns 0 on no find, 1 on find and -1 on error */ static int checkpath(struct CONTEXT *context, struct NODE *node, const char *path) { struct NODE *depnode; /* search up the node and add it if we need */ depnode = node_find(context->graph, path); if(depnode) { if(!node_add_dependency_withnode(node, depnode)) return -1; return 1; } /* check if it exists on the disk */ if(file_exist(path)) { if(!node_add_dependency(node, path)) return -1; return 1; } return 0; } /* this functions takes the whole deferred lookup list and searches for the file */ static int do_run(struct CONTEXT *context, struct DEFERRED *info) { struct STRINGLIST *dep; struct STRINGLIST *path; struct DEPPLAIN *plain = (struct DEPPLAIN *)info->user; char buffer[MAX_PATH_LENGTH]; int result; for(dep = plain->firstdep; dep; dep = dep->next) { /* check the current directory */ result = checkpath(context, info->node, dep->str); if(result == 1) continue; if(result == -1) return -1; /* check all the other directories */ for(path = plain->firstpath; path; path = path->next) { /* build the path, "%s/%s" */ if(path_join(path->str, path->len, dep->str, dep->len, buffer, sizeof(buffer)) != 0) return -1; result = checkpath(context, info->node, buffer); if(result == 1) break; if(result == -1) return -1; } } return 0; } /* add_dependency_search(string node, table paths, table deps) */ int lf_add_dependency_search(lua_State *L) { struct NODE *node; struct CONTEXT *context; struct DEFERRED *deferred; struct DEPPLAIN *plain; if(lua_gettop(L) != 3) luaL_error(L, "add_dep_search: expected 3 arguments"); luaL_checktype(L, 1, LUA_TSTRING); context = context_get_pointer(L); /* check all parameters */ node = node_find(context->graph, lua_tostring(L,1)); if(!node) luaL_error(L, "add_dep_search: couldn't find node with name '%s'", lua_tostring(L,1)); if(lua_type(L,2) != LUA_TTABLE) luaL_error(L, "add_dep_search: expected table as second argument"); if(lua_type(L,3) != LUA_TTABLE) luaL_error(L, "add_dep_search: expected table as third argument"); deferred = (struct DEFERRED *)mem_allocate(context->deferredheap, sizeof(struct DEFERRED)); plain = (struct DEPPLAIN *)mem_allocate(context->deferredheap, sizeof(struct DEPPLAIN)); deferred->node = node; deferred->user = plain; deferred->run = do_run; deferred->next = context->firstdeferred; context->firstdeferred = deferred; /* allocate the lookup */ plain->firstpath = NULL; plain->firstdep = NULL; /* build the string lists */ build_stringlist(L, context->deferredheap, &plain->firstpath, 2); build_stringlist(L, context->deferredheap, &plain->firstdep, 3); return 0; } bam-0.4.0/src/base.lua0000644000175000017500000002763311430042030012556 0ustar kmakma-- just install a better name for the functions and tables ScriptArgs = _bam_scriptargs IsString = bam_isstring IsTable = bam_istable MakeDirectory = bam_mkdir Exist = bam_fileexist SetFilter = bam_set_filter SetTouch = bam_set_touch AddOutput = bam_add_output LoadPlugin = bam_load_plugin --[[@GROUP Common @END]]-- --[[@FUNCTION CheckVersion Tells bam what version this script is written for. It will either make sure that it behaves like that version or print out an error. {{{{ CheckVersion("0.1.0") }}}} @END]]-- function CheckVersion(version) if version == _bam_version then else error("this file for version "..version..".x of bam. you are running ".._bam_version..".x.") end end --[[@FUNCTION Execute(command) Executes the ^command^ in the shell and returns the error code. @END]]-- Execute = os.execute --[[@FUNCTION ExecuteSilent(command) Does the same as ^Execute(command)^ but supresses stdout and stderr of that command. @END]]-- if family == "windows" then ExecuteSilent = function(command) return os.execute(command .. " >nul 2>&1") end else ExecuteSilent = function(command) return os.execute(command .. " >/dev/null 2>/dev/null") end end --[[@GROUP Path Manipulation @END]]-- --[[@UNITTESTS err=1 : Path(nil) err=1 : Path({}) err=1 : Path("asdf", "asdf") catch="" : Path("") catch="" : Path("/") catch="/b.c/file.ext" : Path("/a/../b.c/./file.ext") catch="/b.c" : Path("/a/../b.c/./") catch="/a" : Path("/a/b/..") catch="/a" : Path("/a/b/../") catch="../../b.c" : Path("../../a/../b.c/./") catch="../path/file.name.ext" : Path("../test/../path/file.name.ext") @END]]-- --[[@FUNCTION Path(str) Normalizes the path ^str^ by removing ".." and "." from it. {{{{ Path("test/./path/../file.name.ext") -- Returns "test/file.name.ext" Path("../test/../path/file.name.ext") -- Returns "../path/file.name.ext" }}}} @END]]-- Path = bam_path_normalize --[[@UNITTESTS err=1: PathBase(nil) err=1: PathBase({}) catch="": PathBase("") catch="/": PathBase("/") catch="test/path/file.name": PathBase("test/path/file.name.ext") catch="/a/../b.c/./file": PathBase("/a/../b.c/./file.ext") @END]]-- --[[@FUNCTION PathBase(path) Returns the everthing except the extention in the path. {{{{ PathBase("test/path/file.name.ext") -- Returns "test/path/file.name" PathBase("test/path/file.name") -- Returns "test/path/file" PathBase("test/path/file") -- Returns "test/path/file" }}}} @END]]-- PathBase = bam_path_base --[[@UNITTESTS err=1 : PathFileExt(nil) err=1 : PathFileExt({}) catch="" : PathFileExt("") catch="" : PathFileExt("/") catch="ext" : PathFileExt("/a/../b.c/./file.ext") @END]]-- --[[@FUNCTION PathFileExt(str) Returns the extension of the filename in ^str^. {{{{ PathFileExt("test/path/file.name.ext") -- Returns "ext" }}}} @END]]-- PathFileExt = bam_path_ext --[[@UNITTESTS err=1 : PathFilename(nil) err=1 : PathFilename({}) catch="" : PathFilename("") catch="" : PathFilename("/") catch="file.ext" : PathFilename("/a/../b.c/./file.ext") @END]]-- --[[@FUNCTION PathFilename(str) Returns the filename of the path in ^str^. {{{{ PathFilename("test/path/file.name.ext") -- Returns "file.name.ext" }}}} @END]]-- PathFilename = bam_path_filename --[[@UNITTESTS err=1 : PathJoin(nil) err=1 : PathJoin("asdf", "asdf", "asdf") catch="a/b" : PathJoin("a/b", "") catch="a/b" : PathJoin("a/b/", "") catch="a/b" : PathJoin("a", "b") catch="a" : PathJoin("", "a") catch="a/b" : PathJoin("", "a/b") catch="a" : PathJoin("a/b", "..") catch="a/b" : PathJoin("a/b/", "") catch="a/b" : PathJoin("a/", "b/") @END]]-- --[[@FUNCTION PathJoin(base, add) Joins the two paths ^base^ and ^add^ together and returns a normalized path. This function haldes trailing path separators in the ^base^ argument. {{{{ PathJoin("test/path/", "../filename.ext") -- Returns "test/filename.ext" PathJoin("../test", "path/filename.ext") -- Returns "../test/path/filename.ext" }}}} @END]]-- PathJoin = bam_path_join --[[@UNITTESTS err=1 : PathDir(nil) err=1 : PathDir({}) catch="" : PathDir("") catch="" : PathDir("/") catch="/b.c" : PathDir("/a/../b.c/./file.ext") @END]]-- --[[@FUNCTION PathDir(str) Returns the path of the filename in ^str^. {{{{ PathDir("test/path/file.name.ext") -- Returns "test/path" }}}} @END]]-- PathDir = bam_path_dir --[[@GROUP Tables @END]]-- --[[@UNITTESTS err=1 : TableDeepCopy(nil) err=1 : TableDeepCopy("") err=1 : TableDeepCopy({}, {}) err=0 : TableDeepCopy({{{"a"}, "b"}, "c", "d", {"e", "f"}}) @END]]-- --[[@FUNCTION TableDeepCopy(tbl) Makes a deep copy of the table ^tbl^ resulting in a complete separate table. @END]]-- TableDeepCopy = bam_table_deepcopy --[[@UNITTESTS err=0 : TableFlatten({"", {"", {""}, ""}, "", {}, {""}}) err=1 : TableFlatten({"", {"", {""}, ""}, 1, {""}}) @END]]-- --[[@FUNCTION TableFlatten(tbl) Does a deep walk of the ^tbl^ table for strings and generates a new flat table with the strings. If it occurs anything else then a table or string, it will generate an error. {{{{ -- Returns {"a", "b", "c", "d", "e", "f"} TableFlatten({"a", {"b", {"c"}, "d"}, "e", {}, {"f"}}) }}}} @END]]-- TableFlatten = bam_table_flatten --[[@UNITTESTS err=0 : t = {a = 1}; TableLock(t); t.a = 2 err=1 : t = {a = 1}; TableLock(t); t.b = 2 @END]]-- --[[@FUNCTION TableLock(tbl) Locks the table ^tbl^ so no new keys can be added. Trying to add a new key will result in an error. @END]]-- function TableLock(tbl) local mt = getmetatable(tbl) if not mt then mt = {} end mt.__newindex = function(tbl, key, value) error("trying to create key '" .. key .. "' on a locked table") end setmetatable(tbl, mt) end --[[@UNITTESTS catch="[a][b]" : TableToString({"a", "b"}, "[", "]") @END]]-- --[[@FUNCTION TableToString(tbl, prefix, postfix) Takes every string element in the ^tbl^ table, prepends ^prefix^ and appends ^postfix^ to each element and returns the result. {{{{ TableToString({"a", "b"}, "[", "]") -- Returns "[a][b]" }}}} @END]]-- TableToString = bam_table_tostring --[[@UNITTESTS err=0 : for s in TableWalk({"", {"", {""}, ""}, "", {}, {""}}) do end err=1 : for s in TableWalk({"", {"", {""}, ""}, 1, {""}}) do end @END]]-- --[[@FUNCTION TableWalk(tbl) Returns an iterator that does a deep walk of a table looking for strings. Only checks numeric keys and anything else then table and strings will cause an error. {{{{ for filename in TableWalk({...}) do print(filename) end }}}} @END]]-- TableWalk = bam_table_walk --[[@GROUP Settings @END]]-- _bam_tools = {} --[[@UNITTESTS @END]]-- --[[@FUNCTION Adds a new tool called ^name^ to bam. The ^func^ will be called when ^NewSettings^ function is invoked with the settings object as first parameter. @END]]-- function AddTool(func) table.insert(_bam_tools, func) end --[[@UNITTESTS err=1; find="expected a settings object": CheckSettings(nil) err=1; find="expected a settings object": CheckSettings("") err=1; find="expected a settings object": CheckSettings({}) err=0 : CheckSettings(NewSettings()) @END]]-- function CheckSettings(settings) if not IsTable(settings) or settings._is_settingsobject == nil then error("expected a settings object, got an " .. type(settings) .. " instead") end end --[[@UNITTESTS err=0 : NewSettings() err=1 : t = NewSettings(); t.cc.DOES_NOT_EXIST = 1 err=1 : t = NewSettings():Copy(); t.cc.DOES_NOT_EXIST = 1 @END]]-- --[[@FUNCTION Create a new settings table with the settings for all the registered tools. This table is passed to many of the tools and contains how they should act. @END]]-- function NewSettings() local settings = {} settings._is_settingsobject = true settings.invoke_count = 0 SetCommonSettings(settings) -- add all tools for _, tool in pairs(_bam_tools) do tool(settings) end -- HACK: setup default drivers SetDefaultDrivers(settings) -- lock the table and return TableLock(settings) return settings end --[[@GROUP Files and Directories @END]]-- -- Collects files in a directory. --[[@FUNCTION Collect(...) Gathers a set of files using wildcard. Accepts strings and tables of strings as input and returns a table of all the files that matches A single wildcard * may be used in each string to collect a set of files. Example: {{{{ source_files = Collect("src/*.c", "lib/*.c") }}}} Note. This version collects files, non-recursive. @END]]-- Collect = bam_collect --[[@FUNCTION CollectRecursive(...) Collects files as the [Collect] but does so recursivly. @END]]-- CollectRecursive = bam_collectrecursive --[[@FUNCTION CollectDirs(...) Collects directories in the same fashion as [Collect] but returns directories instead. @END]]-- CollectDirs = bam_collectdirs --[[@FUNCTION CollectDirsRecursive(...) Collects directories in the same fashion as [Collect] but does so recursivly and returns directories instead. @END]]-- CollectDirsRecursive = bam_collectdirsrecursive --[[@GROUP Targets@END]]-- --[[@FUNCTION DefaultTarget(filename) Specifies the default target use build when no targets are specified when bam is invoked. @END]]-- DefaultTarget = bam_default_target --[[@FUNCTION TODO @END]]-- function PseudoTarget(name, ...) local name = Path(name) bam_add_pseudo(name) -- all the files for inname in TableWalk({...}) do AddDependency(name, inname) end return name end --[[@GROUP Modules@END]]-- --[[@FUNCTION TODO @END]]-- function Import(modname) local paths = {""} local chunk = nil s = os.getenv("BAM_PACKAGES") if s then for w in string.gmatch(s, "[^:]*") do if string.len(w) > 0 then table.insert(paths, w) end end end for k,v in pairs(paths) do chunk = bam_loadfile(modname) if chunk then local current = _bam_modulefilename _bam_modulefilename = modname bam_update_globalstamp(_bam_modulefilename) chunk() _bam_modulefilename = current return end end error(modname .. " not found") end --[[@FUNCTION TODO @END]]-- function ModuleFilename() return _bam_modulefilename end --[[@GROUP Job and Dependencies @END]]-- --[[@FUNCTION AddJob(output, label, command, ...) Adds a job to be done. The ^output^ string specifies the file that will be created by the command line specified in ^command^ string. The ^label^ is printed out before ^command^ is runned. You can also add extra parameters, those will become for dependencies for the job. {{{{ AddJob("myapp.o", "compiling myapp.c", "gcc -c myapp.c -o myapp.o") AddDependency("myapp.o", "myapp.c") }}}} This is the same as this: {{{{ AddJob("myapp.o", "compiling myapp.c", "gcc -c myapp.c -o myapp.o", "myapp.c") }}}} You can also add several dependencies at once like this: {{{{ AddJob("myapp", "linking myapp", "gcc myapp1.o myapp2.o myapp3.o -o myapp.o", {"myapp1.o", "myapp2.o"}, "myapp3.o") }}}} @END]]-- AddJob = bam_add_job --[[@FUNCTION AddDependency(filename, ...) Adds dependencies to a job. The files specified in the argument list gets added. Strings and nested tables of strings are accepted. @END]]-- AddDependency = bam_add_dependency --[[@FUNCTION AddDependencySearch(filename, paths, dependencies) @END]]-- AddDependencySearch = bam_add_dependency_search function Default_Intermediate_Output(settings, input) return PathBase(input) .. settings.config_ext end -- [TODO: Should be in C?] function str_replace(s, pattern, what) return string.gsub(s, pattern, function(v) return what end) end function NewTable() local t = {} t.Add = function(self, ...) for i,what in ipairs({...}) do table.insert(self, what) end self.version = self.version + 1 end t.Merge = function(self, source) for k,v in ipairs(source) do table.insert(self, v) end self.version = self.version + 1 end t.version = 0 return t end function NewFlagTable() local t = NewTable() t.ToString = function(self) if self.string_version == self.version then return self.string end local s = TableToString(self, nil, " ") self.string = s self.string_version = self.version return s end t.string_version = 0 t.string = "" return t end AddConstraintShared = bam_add_constraint_shared AddConstraintExclusive = bam_add_constraint_exclusive bam-0.4.0/src/mem.h0000644000175000017500000000065511430042030012063 0ustar kmakma /* Because this application will do lots of smaller allocations and never release them, this basic memory allocator is optimized for it and will chunk memory together so it easily can be released at once when we are done. This also removes almost all overhead per allocation. The memory is initiated to 0. */ struct HEAP *mem_create(); void mem_destroy(struct HEAP *heap); void *mem_allocate(struct HEAP *heap, int size); bam-0.4.0/src/session.h0000644000175000017500000000067711430042030012774 0ustar kmakma/* session - holds all the settings for this bam session */ struct SESSION { const char *exe; const char *name; int threads; int verbose; int simpleoutput; unsigned int cache_hash; int lua_backtrace; int lua_locals; int report_color; int report_bar; int report_steps; volatile int abort; /* raised to 1 when it's time to give up */ }; void install_abort_signal(); /* global session structure */ extern struct SESSION session; bam-0.4.0/src/internal_base.h0000644000175000017500000061364211430042030014121 0ustar kmakmatypedef struct { const char *filename; const char *content; } INTERNALFILE; const char internal_file_1[] = {0x2d, 0x2d, 0x20, 0x6a, 0x75, 0x73, 0x74, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x20, 0x62, 0x65, 0x74, 0x74, 0x65, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0xa, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x72, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x5f, 0x62, 0x61, 0x6d, 0x5f, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x61, 0x72, 0x67, 0x73, 0xa, 0x49, 0x73, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x69, 0x73, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0xa, 0x49, 0x73, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x69, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x65, 0xa, 0x4d, 0x61, 0x6b, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x6d, 0x6b, 0x64, 0x69, 0x72, 0xa, 0x45, 0x78, 0x69, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x65, 0x78, 0x69, 0x73, 0x74, 0xa, 0x53, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0xa, 0x53, 0x65, 0x74, 0x54, 0x6f, 0x75, 0x63, 0x68, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x6f, 0x75, 0x63, 0x68, 0xa, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x4c, 0x6f, 0x61, 0x64, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0xa, 0x9, 0x54, 0x65, 0x6c, 0x6c, 0x73, 0x20, 0x62, 0x61, 0x6d, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x69, 0x73, 0x20, 0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x2e, 0x20, 0x49, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0xa, 0x9, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x62, 0x65, 0x68, 0x61, 0x76, 0x65, 0x73, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0xa, 0x9, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x28, 0x22, 0x30, 0x2e, 0x31, 0x2e, 0x30, 0x22, 0x29, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0xa, 0x9, 0x69, 0x66, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x3d, 0x20, 0x5f, 0x62, 0x61, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x65, 0x6c, 0x73, 0x65, 0xa, 0x9, 0x9, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x22, 0x2e, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x2e, 0x22, 0x2e, 0x78, 0x20, 0x6f, 0x66, 0x20, 0x62, 0x61, 0x6d, 0x2e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x61, 0x72, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x22, 0x2e, 0x2e, 0x5f, 0x62, 0x61, 0x6d, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x2e, 0x22, 0x2e, 0x78, 0x2e, 0x22, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x28, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x29, 0xa, 0x9, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x5e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x6f, 0x73, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x69, 0x6c, 0x65, 0x6e, 0x74, 0x28, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x29, 0xa, 0x9, 0x44, 0x6f, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x5e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x28, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x29, 0x5e, 0x20, 0x62, 0x75, 0x74, 0x20, 0x73, 0x75, 0x70, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20, 0x73, 0x74, 0x64, 0x6f, 0x75, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x20, 0x6f, 0x66, 0xa, 0x9, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x69, 0x66, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x69, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x73, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x28, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x3e, 0x6e, 0x75, 0x6c, 0x20, 0x32, 0x3e, 0x26, 0x31, 0x22, 0x29, 0x20, 0x65, 0x6e, 0x64, 0xa, 0x65, 0x6c, 0x73, 0x65, 0xa, 0x9, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x69, 0x6c, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x73, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x28, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x3e, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x6e, 0x75, 0x6c, 0x6c, 0x20, 0x32, 0x3e, 0x2f, 0x64, 0x65, 0x76, 0x2f, 0x6e, 0x75, 0x6c, 0x6c, 0x22, 0x29, 0x20, 0x65, 0x6e, 0x64, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x50, 0x61, 0x74, 0x68, 0x20, 0x4d, 0x61, 0x6e, 0x69, 0x70, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x6e, 0x69, 0x6c, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x7b, 0x7d, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x22, 0x61, 0x73, 0x64, 0x66, 0x22, 0x2c, 0x20, 0x22, 0x61, 0x73, 0x64, 0x66, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x22, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x22, 0x2f, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x2f, 0x62, 0x2e, 0x63, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x2e, 0x63, 0x2f, 0x2e, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x2f, 0x62, 0x2e, 0x63, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x2e, 0x63, 0x2f, 0x2e, 0x2f, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x2f, 0x61, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x2f, 0x62, 0x2f, 0x2e, 0x2e, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x2f, 0x61, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x22, 0x2f, 0x61, 0x2f, 0x62, 0x2f, 0x2e, 0x2e, 0x2f, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x2e, 0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x2e, 0x63, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x22, 0x2e, 0x2e, 0x2f, 0x2e, 0x2e, 0x2f, 0x61, 0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x2e, 0x63, 0x2f, 0x2e, 0x2f, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x2e, 0x2e, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x22, 0x2e, 0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x2e, 0x2e, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x73, 0x74, 0x72, 0x29, 0xa, 0x9, 0x4e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x5e, 0x73, 0x74, 0x72, 0x5e, 0x20, 0x62, 0x79, 0x20, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x69, 0x6e, 0x67, 0x20, 0x22, 0x2e, 0x2e, 0x22, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x22, 0x2e, 0x22, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x69, 0x74, 0x2e, 0xa, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x50, 0x61, 0x74, 0x68, 0x28, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x2e, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x2e, 0x2e, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0xa, 0x9, 0x50, 0x61, 0x74, 0x68, 0x28, 0x22, 0x2e, 0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x2e, 0x2e, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x22, 0x2e, 0x2e, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x50, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x6e, 0x69, 0x6c, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x7b, 0x7d, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x22, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x22, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x2f, 0x22, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x22, 0x2f, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x2f, 0x61, 0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x2e, 0x63, 0x2f, 0x2e, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x22, 0x2f, 0x61, 0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x2e, 0x63, 0x2f, 0x2e, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x70, 0x61, 0x74, 0x68, 0x29, 0xa, 0x9, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x76, 0x65, 0x72, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x78, 0x63, 0x65, 0x70, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2e, 0xa, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0xa, 0x9, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0xa, 0x9, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x62, 0x61, 0x73, 0x65, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x28, 0x6e, 0x69, 0x6c, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x28, 0x7b, 0x7d, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x28, 0x22, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x28, 0x22, 0x2f, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x65, 0x78, 0x74, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x28, 0x22, 0x2f, 0x61, 0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x2e, 0x63, 0x2f, 0x2e, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x28, 0x73, 0x74, 0x72, 0x29, 0xa, 0x9, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x5e, 0x73, 0x74, 0x72, 0x5e, 0x2e, 0xa, 0x9, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x28, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x22, 0x65, 0x78, 0x74, 0x22, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x65, 0x78, 0x74, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x6e, 0x69, 0x6c, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x7b, 0x7d, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x22, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x22, 0x2f, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x22, 0x2f, 0x61, 0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x2e, 0x63, 0x2f, 0x2e, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x73, 0x74, 0x72, 0x29, 0xa, 0x9, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x69, 0x6e, 0x20, 0x5e, 0x73, 0x74, 0x72, 0x5e, 0x2e, 0xa, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x22, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x6e, 0x69, 0x6c, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x61, 0x73, 0x64, 0x66, 0x22, 0x2c, 0x20, 0x22, 0x61, 0x73, 0x64, 0x66, 0x22, 0x2c, 0x20, 0x22, 0x61, 0x73, 0x64, 0x66, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x61, 0x2f, 0x62, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x61, 0x2f, 0x62, 0x22, 0x2c, 0x20, 0x22, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x61, 0x2f, 0x62, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x61, 0x2f, 0x62, 0x2f, 0x22, 0x2c, 0x20, 0x22, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x61, 0x2f, 0x62, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x61, 0x22, 0x2c, 0x20, 0x22, 0x62, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x61, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x22, 0x2c, 0x20, 0x22, 0x61, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x61, 0x2f, 0x62, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x22, 0x2c, 0x20, 0x22, 0x61, 0x2f, 0x62, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x61, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x61, 0x2f, 0x62, 0x22, 0x2c, 0x20, 0x22, 0x2e, 0x2e, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x61, 0x2f, 0x62, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x61, 0x2f, 0x62, 0x2f, 0x22, 0x2c, 0x20, 0x22, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x61, 0x2f, 0x62, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x61, 0x2f, 0x22, 0x2c, 0x20, 0x22, 0x62, 0x2f, 0x22, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x62, 0x61, 0x73, 0x65, 0x2c, 0x20, 0x61, 0x64, 0x64, 0x29, 0xa, 0x9, 0x4a, 0x6f, 0x69, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x77, 0x6f, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x20, 0x5e, 0x62, 0x61, 0x73, 0x65, 0x5e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x5e, 0x61, 0x64, 0x64, 0x5e, 0x20, 0x74, 0x6f, 0x67, 0x65, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0xa, 0x9, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x68, 0x61, 0x6c, 0x64, 0x65, 0x73, 0x20, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x20, 0x69, 0x6e, 0xa, 0x9, 0x74, 0x68, 0x65, 0x20, 0x5e, 0x62, 0x61, 0x73, 0x65, 0x5e, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0xa, 0x9, 0x9, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x22, 0x2c, 0x20, 0x22, 0x2e, 0x2e, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0xa, 0x9, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x22, 0x2e, 0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x22, 0x2c, 0x20, 0x22, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x22, 0x2e, 0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0x9, 0xa, 0x9, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x44, 0x69, 0x72, 0x28, 0x6e, 0x69, 0x6c, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x44, 0x69, 0x72, 0x28, 0x7b, 0x7d, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x44, 0x69, 0x72, 0x28, 0x22, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x44, 0x69, 0x72, 0x28, 0x22, 0x2f, 0x22, 0x29, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x2f, 0x62, 0x2e, 0x63, 0x22, 0x20, 0x3a, 0x20, 0x50, 0x61, 0x74, 0x68, 0x44, 0x69, 0x72, 0x28, 0x22, 0x2f, 0x61, 0x2f, 0x2e, 0x2e, 0x2f, 0x62, 0x2e, 0x63, 0x2f, 0x2e, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x44, 0x69, 0x72, 0x28, 0x73, 0x74, 0x72, 0x29, 0xa, 0x9, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x74, 0x68, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x5e, 0x73, 0x74, 0x72, 0x5e, 0x2e, 0xa, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x50, 0x61, 0x74, 0x68, 0x44, 0x69, 0x72, 0x28, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x2f, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x65, 0x78, 0x74, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x70, 0x61, 0x74, 0x68, 0x22, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x50, 0x61, 0x74, 0x68, 0x44, 0x69, 0x72, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x64, 0x69, 0x72, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x20, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x65, 0x70, 0x43, 0x6f, 0x70, 0x79, 0x28, 0x6e, 0x69, 0x6c, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x65, 0x70, 0x43, 0x6f, 0x70, 0x79, 0x28, 0x22, 0x22, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x65, 0x70, 0x43, 0x6f, 0x70, 0x79, 0x28, 0x7b, 0x7d, 0x2c, 0x20, 0x7b, 0x7d, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x30, 0x20, 0x3a, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x65, 0x70, 0x43, 0x6f, 0x70, 0x79, 0x28, 0x7b, 0x7b, 0x7b, 0x22, 0x61, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x62, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x63, 0x22, 0x2c, 0x20, 0x22, 0x64, 0x22, 0x2c, 0x20, 0x7b, 0x22, 0x65, 0x22, 0x2c, 0x20, 0x22, 0x66, 0x22, 0x7d, 0x7d, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0x9, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x65, 0x70, 0x43, 0x6f, 0x70, 0x79, 0x28, 0x74, 0x62, 0x6c, 0x29, 0xa, 0x9, 0x4d, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x61, 0x20, 0x64, 0x65, 0x65, 0x70, 0x20, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x5e, 0x74, 0x62, 0x6c, 0x5e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x20, 0x73, 0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0xa, 0x9, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x65, 0x70, 0x43, 0x6f, 0x70, 0x79, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x65, 0x65, 0x70, 0x63, 0x6f, 0x70, 0x79, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x30, 0x20, 0x3a, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x28, 0x7b, 0x22, 0x22, 0x2c, 0x20, 0x7b, 0x22, 0x22, 0x2c, 0x20, 0x7b, 0x22, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x22, 0x2c, 0x20, 0x7b, 0x7d, 0x2c, 0x20, 0x7b, 0x22, 0x22, 0x7d, 0x7d, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x28, 0x7b, 0x22, 0x22, 0x2c, 0x20, 0x7b, 0x22, 0x22, 0x2c, 0x20, 0x7b, 0x22, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x22, 0x7d, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x7b, 0x22, 0x22, 0x7d, 0x7d, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x28, 0x74, 0x62, 0x6c, 0x29, 0xa, 0x9, 0x44, 0x6f, 0x65, 0x73, 0x20, 0x61, 0x20, 0x64, 0x65, 0x65, 0x70, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x5e, 0x74, 0x62, 0x6c, 0x5e, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x77, 0xa, 0x9, 0x66, 0x6c, 0x61, 0x74, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x69, 0x74, 0x20, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x61, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0xa, 0x9, 0x6f, 0x72, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0xa, 0x9, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x7b, 0x22, 0x61, 0x22, 0x2c, 0x20, 0x22, 0x62, 0x22, 0x2c, 0x20, 0x22, 0x63, 0x22, 0x2c, 0x20, 0x22, 0x64, 0x22, 0x2c, 0x20, 0x22, 0x65, 0x22, 0x2c, 0x20, 0x22, 0x66, 0x22, 0x7d, 0xa, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x28, 0x7b, 0x22, 0x61, 0x22, 0x2c, 0x20, 0x7b, 0x22, 0x62, 0x22, 0x2c, 0x20, 0x7b, 0x22, 0x63, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x64, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x65, 0x22, 0x2c, 0x20, 0x7b, 0x7d, 0x2c, 0x20, 0x7b, 0x22, 0x66, 0x22, 0x7d, 0x7d, 0x29, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x66, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x30, 0x20, 0x3a, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x61, 0x20, 0x3d, 0x20, 0x31, 0x7d, 0x3b, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x28, 0x74, 0x29, 0x3b, 0x20, 0x74, 0x2e, 0x61, 0x20, 0x3d, 0x20, 0x32, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x61, 0x20, 0x3d, 0x20, 0x31, 0x7d, 0x3b, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x28, 0x74, 0x29, 0x3b, 0x20, 0x74, 0x2e, 0x62, 0x20, 0x3d, 0x20, 0x32, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x28, 0x74, 0x62, 0x6c, 0x29, 0xa, 0x9, 0x4c, 0x6f, 0x63, 0x6b, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x5e, 0x74, 0x62, 0x6c, 0x5e, 0x20, 0x73, 0x6f, 0x20, 0x6e, 0x6f, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x2e, 0x20, 0x54, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x64, 0x64, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x77, 0xa, 0x9, 0x6b, 0x65, 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x28, 0x74, 0x62, 0x6c, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x74, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x74, 0x62, 0x6c, 0x29, 0xa, 0x9, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6d, 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0x20, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x6d, 0x74, 0x2e, 0x5f, 0x5f, 0x6e, 0x65, 0x77, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x74, 0x62, 0x6c, 0x2c, 0x20, 0x6b, 0x65, 0x79, 0x2c, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x29, 0xa, 0x9, 0x9, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x74, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x27, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6b, 0x65, 0x79, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x27, 0x20, 0x6f, 0x6e, 0x20, 0x61, 0x20, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x73, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x74, 0x62, 0x6c, 0x2c, 0x20, 0x6d, 0x74, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x63, 0x61, 0x74, 0x63, 0x68, 0x3d, 0x22, 0x5b, 0x61, 0x5d, 0x5b, 0x62, 0x5d, 0x22, 0x20, 0x3a, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x7b, 0x22, 0x61, 0x22, 0x2c, 0x20, 0x22, 0x62, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x5b, 0x22, 0x2c, 0x20, 0x22, 0x5d, 0x22, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x74, 0x62, 0x6c, 0x2c, 0x20, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x2c, 0x20, 0x70, 0x6f, 0x73, 0x74, 0x66, 0x69, 0x78, 0x29, 0xa, 0x9, 0x54, 0x61, 0x6b, 0x65, 0x73, 0x20, 0x65, 0x76, 0x65, 0x72, 0x79, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x5e, 0x74, 0x62, 0x6c, 0x5e, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x20, 0x70, 0x72, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x5e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x73, 0x20, 0x5e, 0x70, 0x6f, 0x73, 0x74, 0x66, 0x69, 0x78, 0x5e, 0xa, 0x9, 0x74, 0x6f, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x2e, 0xa, 0x9, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x7b, 0x22, 0x61, 0x22, 0x2c, 0x20, 0x22, 0x62, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x5b, 0x22, 0x2c, 0x20, 0x22, 0x5d, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x22, 0x5b, 0x61, 0x5d, 0x5b, 0x62, 0x5d, 0x22, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x30, 0x20, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x6c, 0x6b, 0x28, 0x7b, 0x22, 0x22, 0x2c, 0x20, 0x7b, 0x22, 0x22, 0x2c, 0x20, 0x7b, 0x22, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x22, 0x2c, 0x20, 0x7b, 0x7d, 0x2c, 0x20, 0x7b, 0x22, 0x22, 0x7d, 0x7d, 0x29, 0x20, 0x64, 0x6f, 0x20, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x6c, 0x6b, 0x28, 0x7b, 0x22, 0x22, 0x2c, 0x20, 0x7b, 0x22, 0x22, 0x2c, 0x20, 0x7b, 0x22, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x22, 0x7d, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x7b, 0x22, 0x22, 0x7d, 0x7d, 0x29, 0x20, 0x64, 0x6f, 0x20, 0x65, 0x6e, 0x64, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x6c, 0x6b, 0x28, 0x74, 0x62, 0x6c, 0x29, 0xa, 0x9, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x61, 0x20, 0x64, 0x65, 0x65, 0x70, 0x20, 0x77, 0x61, 0x6c, 0x6b, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0xa, 0x9, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x20, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x20, 0x6b, 0x65, 0x79, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0xa, 0x9, 0x63, 0x61, 0x75, 0x73, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0xa, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x6c, 0x6b, 0x28, 0x7b, 0x2e, 0x2e, 0x2e, 0x7d, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x6c, 0x6b, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x77, 0x61, 0x6c, 0x6b, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x5f, 0x62, 0x61, 0x6d, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0xa, 0x9, 0x41, 0x64, 0x64, 0x73, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x5e, 0x6e, 0x61, 0x6d, 0x65, 0x5e, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x61, 0x6d, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x5e, 0x66, 0x75, 0x6e, 0x63, 0x5e, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0xa, 0x9, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x5e, 0x4e, 0x65, 0x77, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x5e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x61, 0x73, 0xa, 0x9, 0x66, 0x69, 0x72, 0x73, 0x74, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x2e, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x41, 0x64, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x29, 0xa, 0x9, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x5f, 0x62, 0x61, 0x6d, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x3b, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x3d, 0x22, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x61, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x3a, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x6e, 0x69, 0x6c, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x3b, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x3d, 0x22, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x61, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x3a, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x22, 0x22, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x3b, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x3d, 0x22, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x61, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x3a, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x7b, 0x7d, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x30, 0x20, 0x3a, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x4e, 0x65, 0x77, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x29, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x49, 0x73, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x5f, 0x69, 0x73, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x3d, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x61, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2c, 0x20, 0x67, 0x6f, 0x74, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x22, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x30, 0x20, 0x3a, 0x20, 0x4e, 0x65, 0x77, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x29, 0x3b, 0x20, 0x74, 0x2e, 0x63, 0x63, 0x2e, 0x44, 0x4f, 0x45, 0x53, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x58, 0x49, 0x53, 0x54, 0x20, 0x3d, 0x20, 0x31, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x20, 0x3a, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x29, 0x3a, 0x43, 0x6f, 0x70, 0x79, 0x28, 0x29, 0x3b, 0x20, 0x74, 0x2e, 0x63, 0x63, 0x2e, 0x44, 0x4f, 0x45, 0x53, 0x5f, 0x4e, 0x4f, 0x54, 0x5f, 0x45, 0x58, 0x49, 0x53, 0x54, 0x20, 0x3d, 0x20, 0x31, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0xa, 0x9, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x65, 0x64, 0xa, 0x9, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x61, 0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x6e, 0x79, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x68, 0x6f, 0x77, 0xa, 0x9, 0x74, 0x68, 0x65, 0x79, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x61, 0x63, 0x74, 0x2e, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e, 0x65, 0x77, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x5f, 0x69, 0x73, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x30, 0xa, 0x9, 0xa, 0x9, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x20, 0x61, 0x64, 0x64, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x5f, 0x2c, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x5f, 0x62, 0x61, 0x6d, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x74, 0x6f, 0x6f, 0x6c, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x20, 0x48, 0x41, 0x43, 0x4b, 0x3a, 0x20, 0x73, 0x65, 0x74, 0x75, 0x70, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0xa, 0x9, 0x53, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x20, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0xa, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x9, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x20, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x47, 0x61, 0x74, 0x68, 0x65, 0x72, 0x73, 0x20, 0x61, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x2e, 0x20, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x73, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0xa, 0x9, 0x6f, 0x66, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x61, 0x73, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0xa, 0x9, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x41, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x20, 0x2a, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x62, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x65, 0x61, 0x63, 0x68, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0xa, 0x9, 0x61, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2e, 0xa, 0x9, 0xa, 0x9, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x3a, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x9, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x28, 0x22, 0x73, 0x72, 0x63, 0x2f, 0x2a, 0x2e, 0x63, 0x22, 0x2c, 0x20, 0x22, 0x6c, 0x69, 0x62, 0x2f, 0x2a, 0x2e, 0x63, 0x22, 0x29, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x9, 0xa, 0x9, 0x4e, 0x6f, 0x74, 0x65, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x6e, 0x6f, 0x6e, 0x2d, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x2e, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x52, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x5b, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x5d, 0x20, 0x62, 0x75, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x73, 0x6f, 0x20, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x6c, 0x79, 0x2e, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x52, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x44, 0x69, 0x72, 0x73, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x73, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x61, 0x73, 0x68, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x5b, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x5d, 0x20, 0x62, 0x75, 0x74, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0xa, 0x9, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x2e, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x44, 0x69, 0x72, 0x73, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x64, 0x69, 0x72, 0x73, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x44, 0x69, 0x72, 0x73, 0x52, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x28, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x73, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x61, 0x73, 0x68, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x73, 0x20, 0x5b, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x5d, 0x20, 0x62, 0x75, 0x74, 0x20, 0x64, 0x6f, 0x65, 0x73, 0x20, 0x73, 0x6f, 0xa, 0x9, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x6c, 0x79, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x65, 0x61, 0x64, 0x2e, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x44, 0x69, 0x72, 0x73, 0x52, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x64, 0x69, 0x72, 0x73, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x28, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x20, 0x75, 0x73, 0x65, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6e, 0x6f, 0x20, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0xa, 0x9, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x62, 0x61, 0x6d, 0x20, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x2e, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0xa, 0x9, 0x54, 0x4f, 0x44, 0x4f, 0x9, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x50, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x50, 0x61, 0x74, 0x68, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x62, 0x61, 0x6d, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x70, 0x73, 0x65, 0x75, 0x64, 0x6f, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x6c, 0x6b, 0x28, 0x7b, 0x2e, 0x2e, 0x2e, 0x7d, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0xa, 0x9, 0x54, 0x4f, 0x44, 0x4f, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x28, 0x6d, 0x6f, 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x22, 0x22, 0x7d, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0xa, 0xa, 0x9, 0x73, 0x20, 0x3d, 0x20, 0x6f, 0x73, 0x2e, 0x67, 0x65, 0x74, 0x65, 0x6e, 0x76, 0x28, 0x22, 0x42, 0x41, 0x4d, 0x5f, 0x50, 0x41, 0x43, 0x4b, 0x41, 0x47, 0x45, 0x53, 0x22, 0x29, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x20, 0x69, 0x6e, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x67, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x28, 0x73, 0x2c, 0x20, 0x22, 0x5b, 0x5e, 0x3a, 0x5d, 0x2a, 0x22, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x9, 0x69, 0x66, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x6c, 0x65, 0x6e, 0x28, 0x77, 0x29, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x9, 0x9, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x70, 0x61, 0x74, 0x68, 0x73, 0x2c, 0x20, 0x77, 0x29, 0xa, 0x9, 0x9, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x70, 0x61, 0x74, 0x68, 0x73, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x66, 0x69, 0x6c, 0x65, 0x28, 0x6d, 0x6f, 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x9, 0x69, 0x66, 0x20, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x5f, 0x62, 0x61, 0x6d, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0xa, 0x9, 0x9, 0x9, 0x5f, 0x62, 0x61, 0x6d, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x6d, 0x6f, 0x64, 0x6e, 0x61, 0x6d, 0x65, 0xa, 0x9, 0x9, 0x9, 0x62, 0x61, 0x6d, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x28, 0x5f, 0x62, 0x61, 0x6d, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x9, 0x9, 0x63, 0x68, 0x75, 0x6e, 0x6b, 0x28, 0x29, 0xa, 0x9, 0x9, 0x9, 0x5f, 0x62, 0x61, 0x6d, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0xa, 0x9, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0xa, 0x9, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x9, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x6d, 0x6f, 0x64, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0xa, 0x9, 0x54, 0x4f, 0x44, 0x4f, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x29, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x62, 0x61, 0x6d, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x4a, 0x6f, 0x62, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x20, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x41, 0x64, 0x64, 0x73, 0x20, 0x61, 0x20, 0x6a, 0x6f, 0x62, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x5e, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5e, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0xa, 0x9, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x5e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5e, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0xa, 0x9, 0x54, 0x68, 0x65, 0x20, 0x5e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5e, 0x20, 0x69, 0x73, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x6f, 0x75, 0x74, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x5e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5e, 0x20, 0x69, 0x73, 0x20, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x64, 0x2e, 0x20, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0xa, 0x9, 0x61, 0x64, 0x64, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x63, 0x6f, 0x6d, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6a, 0x6f, 0x62, 0x2e, 0xa, 0x9, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x9, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x22, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x22, 0x2c, 0x20, 0x22, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x22, 0x2c, 0x20, 0x22, 0x67, 0x63, 0x63, 0x20, 0x2d, 0x63, 0x20, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x20, 0x2d, 0x6f, 0x20, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x22, 0x29, 0xa, 0x9, 0x9, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x28, 0x22, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x22, 0x2c, 0x20, 0x22, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x22, 0x29, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x9, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x3a, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x9, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x22, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x22, 0x2c, 0x20, 0x22, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x22, 0x2c, 0x20, 0x22, 0x67, 0x63, 0x63, 0x20, 0x2d, 0x63, 0x20, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x20, 0x2d, 0x6f, 0x20, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x22, 0x2c, 0x20, 0x22, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x22, 0x29, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x9, 0x59, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x61, 0x6c, 0x73, 0x6f, 0x20, 0x61, 0x64, 0x64, 0x20, 0x73, 0x65, 0x76, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x20, 0x61, 0x74, 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68, 0x69, 0x73, 0x3a, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x9, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x22, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x22, 0x2c, 0x20, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x22, 0x2c, 0x20, 0x22, 0x67, 0x63, 0x63, 0x20, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x31, 0x2e, 0x6f, 0x20, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x32, 0x2e, 0x6f, 0x20, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x33, 0x2e, 0x6f, 0x20, 0x2d, 0x6f, 0x20, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x22, 0x2c, 0x20, 0x7b, 0x22, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x31, 0x2e, 0x6f, 0x22, 0x2c, 0x20, 0x22, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x32, 0x2e, 0x6f, 0x22, 0x7d, 0x2c, 0x20, 0x22, 0x6d, 0x79, 0x61, 0x70, 0x70, 0x33, 0x2e, 0x6f, 0x22, 0x29, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x6a, 0x6f, 0x62, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x28, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x41, 0x64, 0x64, 0x73, 0x20, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x6a, 0x6f, 0x62, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x67, 0x65, 0x74, 0x73, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x2e, 0xa, 0x9, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x2e, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x28, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x2c, 0x20, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x65, 0x78, 0x74, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x20, 0x5b, 0x54, 0x4f, 0x44, 0x4f, 0x3a, 0x20, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x43, 0x3f, 0x5d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x72, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x28, 0x73, 0x2c, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x2c, 0x20, 0x77, 0x68, 0x61, 0x74, 0x29, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x67, 0x73, 0x75, 0x62, 0x28, 0x73, 0x2c, 0x20, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x76, 0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x65, 0x6e, 0x64, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0xa, 0x9, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x2c, 0x77, 0x68, 0x61, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x7b, 0x2e, 0x2e, 0x2e, 0x7d, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x9, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x77, 0x68, 0x61, 0x74, 0x29, 0xa, 0x9, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x9, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x2b, 0x20, 0x31, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x9, 0x74, 0x2e, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x29, 0xa, 0x9, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x9, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x76, 0x29, 0xa, 0x9, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x9, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x2b, 0x20, 0x31, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x9, 0x74, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x30, 0xa, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e, 0x65, 0x77, 0x46, 0x6c, 0x61, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0xa, 0x9, 0x74, 0x2e, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x73, 0x65, 0x6c, 0x66, 0x29, 0xa, 0x9, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x3d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0xa, 0x9, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x9, 0xa, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x6c, 0x66, 0x2c, 0x20, 0x6e, 0x69, 0x6c, 0x2c, 0x20, 0x22, 0x20, 0x22, 0x29, 0xa, 0x9, 0x9, 0xa, 0x9, 0x9, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x73, 0xa, 0x9, 0x9, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0xa, 0x9, 0x9, 0xa, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x9, 0x74, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x30, 0xa, 0x9, 0x74, 0x2e, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x41, 0x64, 0x64, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0xa, 0x41, 0x64, 0x64, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0x20, 0x3d, 0x20, 0x62, 0x61, 0x6d, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x73, 0x69, 0x76, 0x65, 0xa, 0xa, 0}; const char internal_file_2[] = {0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x53, 0x65, 0x74, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x2d, 0x2d, 0x20, 0x73, 0x65, 0x74, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0xa, 0x9, 0x69, 0x66, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x53, 0x65, 0x74, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x43, 0x4c, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x65, 0x6c, 0x73, 0x65, 0xa, 0x9, 0x9, 0x53, 0x65, 0x74, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x47, 0x43, 0x43, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x20, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x43, 0x6f, 0x70, 0x79, 0x20, 0x3d, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x65, 0x65, 0x70, 0x43, 0x6f, 0x70, 0x79, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0xa, 0x9, 0x9, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0xa, 0x9, 0x9, 0x54, 0x4f, 0x44, 0x4f, 0x3a, 0x20, 0x65, 0x78, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x75, 0x73, 0x65, 0x20, 0x69, 0x74, 0xa, 0x9, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x65, 0x78, 0x74, 0xa, 0x9, 0x9, 0x41, 0x20, 0x73, 0x68, 0x6f, 0x72, 0x74, 0x20, 0x70, 0x6f, 0x73, 0x74, 0x66, 0x69, 0x78, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x68, 0x61, 0x76, 0x65, 0x20, 0x62, 0x65, 0x65, 0x6e, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x74, 0xa, 0x9, 0x9, 0x62, 0x79, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0xa, 0x9, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x65, 0x78, 0x74, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0xa, 0x9, 0x9, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6a, 0x6f, 0x62, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x2e, 0xa, 0x9, 0x9, 0x54, 0x4f, 0x44, 0x4f, 0x3a, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x65, 0x65, 0x6c, 0x73, 0x20, 0x61, 0x20, 0x62, 0x69, 0x74, 0x20, 0x73, 0x74, 0x72, 0x61, 0x6e, 0x67, 0x65, 0xa, 0x9, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x20, 0x54, 0x4f, 0x44, 0x4f, 0x3a, 0x20, 0x77, 0x68, 0x61, 0x74, 0x20, 0x74, 0x6f, 0x64, 0x6f, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x73, 0x65, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x20, 0x3d, 0x20, 0x31, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x20, 0x3d, 0x20, 0x30, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x43, 0x4f, 0x4d, 0x50, 0x49, 0x4c, 0x45, 0x20, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0xa, 0x9, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x20, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x43, 0x2c, 0x20, 0x4f, 0x62, 0x6a, 0x2d, 0x43, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x55, 0x4e, 0x49, 0x54, 0x54, 0x45, 0x53, 0x54, 0x53, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x3b, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x3d, 0x22, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x20, 0x61, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x3a, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x28, 0x6e, 0x69, 0x6c, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x31, 0x3b, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x3d, 0x22, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x61, 0x20, 0x6e, 0x69, 0x6c, 0x22, 0x3a, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x29, 0x3b, 0x20, 0x73, 0x2e, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x5b, 0x22, 0x63, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x65, 0x6e, 0x64, 0x3b, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x28, 0x73, 0x2c, 0x20, 0x22, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x22, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x3d, 0x30, 0x20, 0x3a, 0x20, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x29, 0x3b, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x28, 0x73, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x65, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x75, 0x70, 0x70, 0x6c, 0x69, 0x65, 0x64, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x20, 0x49, 0x74, 0x20, 0x75, 0x73, 0x65, 0x73, 0xa, 0x9, 0x5e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x5e, 0x20, 0x74, 0x6f, 0x20, 0x6d, 0x61, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0xa, 0x9, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x41, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x5e, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0x5e, 0xa, 0x9, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x5e, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x5e, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x5e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5e, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0xa, 0x9, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x61, 0x74, 0xa, 0x9, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x2e, 0xa, 0xa, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4d, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x5c, 0x74, 0x2d, 0x2d, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x20, 0x73, 0x74, 0x75, 0x66, 0x66, 0xa, 0x9, 0x5c, 0x74, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x5b, 0x22, 0x2e, 0x6d, 0x79, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x4d, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0xa, 0x9, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x22, 0x63, 0x6f, 0x64, 0x65, 0x2e, 0x6d, 0x79, 0x22, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x49, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4d, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0xa, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x9, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x20, 0x3d, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x20, 0x54, 0x4f, 0x44, 0x4f, 0x3a, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x68, 0x65, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x61, 0x77, 0x61, 0x72, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 0x69, 0x66, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x6f, 0x76, 0x65, 0x64, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x77, 0x68, 0x65, 0x72, 0x65, 0xa, 0x9, 0x62, 0x61, 0x6d, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x70, 0x70, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x29, 0xa, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x2b, 0x20, 0x31, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x6c, 0x6b, 0x28, 0x7b, 0x2e, 0x2e, 0x2e, 0x7d, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x2d, 0x2d, 0x20, 0x66, 0x65, 0x74, 0x63, 0x68, 0x20, 0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0xa, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x74, 0x20, 0x3d, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x45, 0x78, 0x74, 0x28, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x5b, 0x65, 0x78, 0x74, 0x5d, 0xa, 0xa, 0x9, 0x9, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x9, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x27, 0x22, 0x2e, 0x2e, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x2e, 0x22, 0x27, 0x20, 0x68, 0x61, 0x73, 0x20, 0x75, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x27, 0x22, 0x2e, 0x2e, 0x65, 0x78, 0x74, 0x2e, 0x2e, 0x22, 0x27, 0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x74, 0x68, 0x65, 0x72, 0x65, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x22, 0x29, 0xa, 0x9, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x9, 0xa, 0x9, 0x9, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x29, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x54, 0x65, 0x73, 0x74, 0x28, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x41, 0x64, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x29, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x53, 0x65, 0x65, 0x20, 0x74, 0x68, 0x65, 0xa, 0x9, 0x9, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x29, 0xa, 0x65, 0x6e, 0x64, 0x29, 0xa, 0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x43, 0x2f, 0x43, 0x2b, 0x2b, 0x20, 0x43, 0x4f, 0x4d, 0x50, 0x49, 0x4c, 0x45, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x43, 0x2f, 0x43, 0x2b, 0x2b, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x29, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4e, 0x75, 0x6c, 0x6c, 0x28, 0x29, 0xa, 0x9, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x22, 0x6e, 0x6f, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x73, 0x65, 0x74, 0x22, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x49, 0x6e, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x43, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x5f, 0x63, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x6e, 0x72, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x20, 0x3d, 0x20, 0x22, 0x22, 0x20, 0x7d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x5f, 0x63, 0x78, 0x78, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x20, 0x3d, 0x20, 0x7b, 0x20, 0x6e, 0x72, 0x20, 0x3d, 0x20, 0x30, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x20, 0x3d, 0x20, 0x22, 0x22, 0x20, 0x7d, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0xa, 0x9, 0x9, 0xa, 0x9, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x3a, 0x41, 0x64, 0x64, 0x28, 0x22, 0x41, 0x4e, 0x53, 0x57, 0x45, 0x52, 0x3d, 0x34, 0x32, 0x22, 0x29, 0xa, 0x9, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x54, 0x65, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4e, 0x75, 0x6c, 0x6c, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2e, 0x20, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0xa, 0x9, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6a, 0x6f, 0x62, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x65, 0xa, 0x9, 0x9, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4e, 0x75, 0x6c, 0x6c, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x58, 0x58, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x53, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x20, 0x62, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x58, 0x58, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4e, 0x75, 0x6c, 0x6c, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x65, 0x78, 0x65, 0x5f, 0x63, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x4e, 0x61, 0x6d, 0x65, 0x20, 0x28, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x61, 0x74, 0x68, 0x29, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x65, 0x78, 0x65, 0x5f, 0x63, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x65, 0x78, 0x65, 0x5f, 0x63, 0x78, 0x78, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x53, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x63, 0x5f, 0x65, 0x78, 0x65, 0x20, 0x62, 0x75, 0x74, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x65, 0x78, 0x65, 0x5f, 0x63, 0x78, 0x78, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x68, 0x61, 0x76, 0x65, 0x2e, 0x20, 0x55, 0x73, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x22, 0x2e, 0x6f, 0x22, 0x20, 0x6f, 0x72, 0x20, 0x22, 0x2e, 0x6f, 0x62, 0x6a, 0x22, 0xa, 0x9, 0x9, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x6f, 0x6c, 0x20, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0xa, 0x9, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0xa, 0x9, 0x9, 0x43, 0x2f, 0x43, 0x2b, 0x2b, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x73, 0x65, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x6f, 0x74, 0x68, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x43, 0x2b, 0x2b, 0xa, 0x9, 0x9, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2e, 0xa, 0x9, 0x9, 0xa, 0x9, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x3a, 0x41, 0x64, 0x64, 0x28, 0x22, 0x2d, 0x4f, 0x32, 0x22, 0x2c, 0x20, 0x22, 0x2d, 0x67, 0x22, 0x29, 0xa, 0x9, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x46, 0x6c, 0x61, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x53, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x46, 0x6c, 0x61, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x78, 0x78, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x53, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x73, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x62, 0x75, 0x74, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x2b, 0x2b, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x78, 0x78, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x46, 0x6c, 0x61, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2e, 0x20, 0x57, 0x68, 0x61, 0x74, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0x9, 0x9, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2e, 0xa, 0x9, 0x9, 0xa, 0x9, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x3a, 0x41, 0x64, 0x64, 0x28, 0x22, 0x6d, 0x79, 0x2f, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x2f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x29, 0xa, 0x9, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0x9, 0x9, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x70, 0x61, 0x74, 0x68, 0x29, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x70, 0x61, 0x74, 0x68, 0xa, 0x9, 0x9, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0xa, 0x9, 0x9, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x79, 0x2e, 0xa, 0x9, 0x9, 0xa, 0x9, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x9, 0x9, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x65, 0x78, 0x74, 0xa, 0x9, 0x9, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0xa, 0x9, 0xa, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x43, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x63, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x75, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x63, 0x63, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0xa, 0x9, 0x63, 0x63, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x63, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x28, 0x6f, 0x75, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x62, 0x61, 0x6d, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x70, 0x70, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x43, 0x58, 0x58, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x63, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x75, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x63, 0x63, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x63, 0x63, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0xa, 0x9, 0x63, 0x63, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x58, 0x58, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x63, 0x2b, 0x2b, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x28, 0x6f, 0x75, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x62, 0x61, 0x6d, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x63, 0x70, 0x70, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0xa, 0x41, 0x64, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x49, 0x6e, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x43, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x5b, 0x22, 0x63, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x43, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x5b, 0x22, 0x6d, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x43, 0xa, 0x65, 0x6e, 0x64, 0x29, 0xa, 0xa, 0x41, 0x64, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x49, 0x6e, 0x69, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x43, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x5b, 0x22, 0x63, 0x70, 0x70, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x43, 0x58, 0x58, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x5b, 0x22, 0x63, 0x78, 0x78, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x43, 0x58, 0x58, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x5b, 0x22, 0x63, 0x2b, 0x2b, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x43, 0x58, 0x58, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x2e, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x73, 0x5b, 0x22, 0x63, 0x63, 0x22, 0x5d, 0x20, 0x3d, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x43, 0x58, 0x58, 0xa, 0x65, 0x6e, 0x64, 0x29, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x4f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x73, 0x72, 0x63, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x69, 0x66, 0x20, 0x66, 0x61, 0x6d, 0x69, 0x6c, 0x79, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x73, 0x72, 0x63, 0x29, 0xa, 0x9, 0x9, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x64, 0x73, 0x74, 0x2c, 0xa, 0x9, 0x9, 0x9, 0x22, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x72, 0x63, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2d, 0x3e, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x64, 0x73, 0x74, 0x2c, 0xa, 0x9, 0x9, 0x9, 0x22, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x2f, 0x62, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x74, 0x72, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x28, 0x73, 0x72, 0x63, 0x2c, 0x20, 0x22, 0x2f, 0x22, 0x2c, 0x20, 0x22, 0x5c, 0x5c, 0x22, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x74, 0x72, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x28, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x22, 0x2f, 0x22, 0x2c, 0x20, 0x22, 0x5c, 0x5c, 0x22, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x3e, 0x6e, 0x75, 0x6c, 0x20, 0x32, 0x3e, 0x26, 0x31, 0x22, 0x2c, 0xa, 0x9, 0x9, 0x9, 0x73, 0x72, 0x63, 0x29, 0xa, 0x9, 0x9, 0x53, 0x65, 0x74, 0x54, 0x6f, 0x75, 0x63, 0x68, 0x28, 0x64, 0x73, 0x74, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x6d, 0x61, 0x6b, 0x65, 0x20, 0x73, 0x75, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0xa, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x73, 0x74, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x65, 0x6c, 0x73, 0x65, 0xa, 0x9, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x73, 0x72, 0x63, 0x29, 0xa, 0x9, 0x9, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x64, 0x73, 0x74, 0x2c, 0xa, 0x9, 0x9, 0x9, 0x22, 0x63, 0x6f, 0x70, 0x79, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x72, 0x63, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2d, 0x3e, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x64, 0x73, 0x74, 0x2c, 0xa, 0x9, 0x9, 0x9, 0x22, 0x63, 0x70, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x72, 0x63, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x64, 0x73, 0x74, 0x2c, 0xa, 0x9, 0x9, 0x9, 0x73, 0x72, 0x63, 0x29, 0xa, 0x9, 0x9, 0x53, 0x65, 0x74, 0x54, 0x6f, 0x75, 0x63, 0x68, 0x28, 0x64, 0x73, 0x74, 0x29, 0xa, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x64, 0x73, 0x74, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x54, 0x6f, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x28, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x54, 0x6f, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x28, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x73, 0x72, 0x63, 0x20, 0x69, 0x6e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x57, 0x61, 0x6c, 0x6b, 0x28, 0x7b, 0x2e, 0x2e, 0x2e, 0x7d, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x28, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x64, 0x73, 0x74, 0x2c, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x73, 0x72, 0x63, 0x29, 0x29, 0x2c, 0x20, 0x73, 0x72, 0x63, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x4c, 0x49, 0x4e, 0x4b, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x20, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0xa, 0x9, 0x54, 0x4f, 0x44, 0x4f, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4c, 0x69, 0x6e, 0x6b, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x28, 0x7b, 0x2e, 0x2e, 0x2e, 0x7d, 0x29, 0xa, 0xa, 0x9, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0xa, 0x9, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x29, 0xa, 0x9, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x29, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x20, 0x61, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x62, 0x61, 0x72, 0x69, 0x65, 0x73, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x62, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0x9, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x6c, 0x69, 0x62, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x6c, 0x69, 0x62, 0x70, 0x61, 0x74, 0x68, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x70, 0x61, 0x74, 0x68, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x2c, 0x20, 0x6c, 0x69, 0x62, 0x73, 0x29, 0xa, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x29, 0xa, 0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0xa, 0xa, 0x41, 0x64, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x2e, 0x20, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0xa, 0x9, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6a, 0x6f, 0x62, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x68, 0x65, 0xa, 0x9, 0x9, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4e, 0x75, 0x6c, 0x6c, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x65, 0x78, 0x65, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x50, 0x61, 0x74, 0x68, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x65, 0x20, 0x61, 0x73, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x20, 0x55, 0x73, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x22, 0x22, 0x20, 0x6f, 0x6e, 0x20, 0x6d, 0x6f, 0x73, 0x74, 0x20, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x62, 0x75, 0x74, 0x20, 0x63, 0x61, 0x6e, 0xa, 0x9, 0x9, 0x62, 0x65, 0x20, 0x22, 0x2e, 0x65, 0x78, 0x65, 0x22, 0x20, 0x6f, 0x6e, 0x20, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x41, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x64, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x73, 0x65, 0xa, 0x9, 0x9, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x74, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20, 0x61, 0x73, 0x20, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x20, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x61, 0x77, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x2e, 0xa, 0x9, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x3a, 0x41, 0x64, 0x64, 0x28, 0x22, 0x2d, 0x76, 0x22, 0x29, 0xa, 0x9, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x46, 0x6c, 0x61, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2e, 0x20, 0x41, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x61, 0x67, 0x61, 0x69, 0x6e, 0x73, 0x74, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x70, 0x61, 0x74, 0x68, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x4d, 0x61, 0x63, 0x20, 0x4f, 0x53, 0x20, 0x58, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x2e, 0x20, 0x41, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x20, 0x77, 0x65, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x6c, 0x69, 0x62, 0x73, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x77, 0x69, 0x74, 0x68, 0x2e, 0xa, 0x9, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x3a, 0x41, 0x64, 0x64, 0x28, 0x22, 0x70, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x22, 0x29, 0xa, 0x9, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x6c, 0x69, 0x62, 0x70, 0x61, 0x74, 0x68, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x41, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x66, 0x20, 0x77, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x6f, 0x20, 0x66, 0x69, 0x6e, 0x64, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x63, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0xa, 0x9, 0x9, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x6e, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x2e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x6c, 0x69, 0x62, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x5e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5e, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x46, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x70, 0x61, 0x74, 0x68, 0xa, 0x9, 0x9, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x70, 0x61, 0x74, 0x68, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x73, 0x20, 0x64, 0x6f, 0x6e, 0x65, 0xa, 0x9, 0x9, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x79, 0x2e, 0xa, 0x9, 0x9, 0xa, 0x9, 0x9, 0x7b, 0x7b, 0x7b, 0x7b, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x9, 0x9, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x26, 0x6e, 0x62, 0x73, 0x70, 0x3b, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x42, 0x61, 0x73, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x65, 0x78, 0x74, 0xa, 0x9, 0x9, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x9, 0x7d, 0x7d, 0x7d, 0x7d, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x9, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x74, 0x72, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x28, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x3f, 0x29, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x74, 0x64, 0x3e, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x72, 0x3e, 0xa, 0x9, 0x40, 0x50, 0x41, 0x55, 0x53, 0x45, 0x5d, 0x5d, 0x9, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x52, 0x45, 0x53, 0x55, 0x4d, 0x45, 0xa, 0x9, 0x9, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e, 0xa, 0x9, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0xa, 0x9, 0x9, 0xa, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x29, 0xa, 0x65, 0x6e, 0x64, 0x29, 0xa, 0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x53, 0x48, 0x41, 0x52, 0x45, 0x44, 0x20, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x20, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x41, 0x64, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4e, 0x75, 0x6c, 0x6c, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x46, 0x6c, 0x61, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x6c, 0x69, 0x62, 0x70, 0x61, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0xa, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x29, 0xa, 0x65, 0x6e, 0x64, 0x29, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x3c, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0xa, 0x9, 0x54, 0x4f, 0x44, 0x4f, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x53, 0x68, 0x61, 0x72, 0x65, 0x64, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x28, 0x7b, 0x2e, 0x2e, 0x2e, 0x7d, 0x29, 0xa, 0xa, 0x9, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x50, 0x61, 0x74, 0x68, 0x44, 0x69, 0x72, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x29, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x2e, 0x2e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x29, 0x29, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x64, 0x6c, 0x6c, 0x20, 0x22, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x9, 0x2d, 0x2d, 0x20, 0x61, 0x64, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x69, 0x62, 0x61, 0x72, 0x69, 0x65, 0x73, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x62, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0x9, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x6c, 0x69, 0x62, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x6c, 0x69, 0x62, 0x70, 0x61, 0x74, 0x68, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x28, 0x70, 0x61, 0x74, 0x68, 0x73, 0x2c, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x70, 0x61, 0x74, 0x68, 0x73, 0x2c, 0x20, 0x6c, 0x69, 0x62, 0x73, 0x29, 0xa, 0x9, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x53, 0x54, 0x41, 0x54, 0x49, 0x43, 0x20, 0x4c, 0x49, 0x42, 0x52, 0x41, 0x52, 0x59, 0x20, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x20, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x20, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0xa, 0x41, 0x64, 0x64, 0x54, 0x6f, 0x6f, 0x6c, 0x28, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x20, 0x3d, 0x20, 0x7b, 0x7d, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x4e, 0x75, 0x6c, 0x6c, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x65, 0x5f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x4e, 0x65, 0x77, 0x46, 0x6c, 0x61, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x29, 0xa, 0x9, 0xa, 0x9, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x29, 0xa, 0x65, 0x6e, 0x64, 0x29, 0xa, 0xa, 0x2d, 0x2d, 0x5b, 0x5b, 0x40, 0x46, 0x55, 0x4e, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0xa, 0x9, 0x54, 0x4f, 0x44, 0x4f, 0xa, 0x40, 0x45, 0x4e, 0x44, 0x5d, 0x5d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x4c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x2e, 0x2e, 0x2e, 0x29, 0xa, 0x9, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x20, 0x3d, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6c, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x28, 0x7b, 0x2e, 0x2e, 0x2e, 0x7d, 0x29, 0xa, 0xa, 0x9, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x50, 0x61, 0x74, 0x68, 0x4a, 0x6f, 0x69, 0x6e, 0x28, 0x50, 0x61, 0x74, 0x68, 0x44, 0x69, 0x72, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x29, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x2e, 0x2e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x29, 0x29, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0xa, 0xa, 0x9, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x6c, 0x69, 0x62, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0x29, 0xa, 0xa, 0x9, 0x66, 0x6f, 0x72, 0x20, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x2c, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x70, 0x61, 0x69, 0x72, 0x73, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x29, 0x20, 0x64, 0x6f, 0xa, 0x9, 0x9, 0x41, 0x64, 0x64, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x65, 0x6e, 0x64, 0xa, 0}; const char internal_file_3[] = {0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x43, 0x2f, 0x43, 0x2b, 0x2b, 0x20, 0x47, 0x43, 0x43, 0x20, 0x44, 0x52, 0x49, 0x56, 0x45, 0x52, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x47, 0x43, 0x43, 0x5f, 0x47, 0x65, 0x74, 0x28, 0x65, 0x78, 0x65, 0x2c, 0x20, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x29, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x61, 0x63, 0x68, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x5b, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5d, 0xa, 0x9, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x7e, 0x3d, 0x20, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x6e, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x9, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x6e, 0x72, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0xa, 0x9, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x63, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0xa, 0x9, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x20, 0x3d, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x63, 0x63, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x2c, 0x20, 0x22, 0x2d, 0x44, 0x22, 0x2c, 0x20, 0x22, 0x20, 0x22, 0x29, 0xa, 0x9, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x63, 0x63, 0x2e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x2c, 0x20, 0x27, 0x2d, 0x49, 0x20, 0x22, 0x27, 0x2c, 0x20, 0x27, 0x22, 0x20, 0x27, 0x29, 0xa, 0x9, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x69, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x63, 0x63, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x2c, 0x20, 0x27, 0x2d, 0x69, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x22, 0x27, 0x2c, 0x20, 0x27, 0x22, 0x20, 0x27, 0x29, 0xa, 0x9, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x20, 0x3d, 0x20, 0x69, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x63, 0x63, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2c, 0x20, 0x27, 0x2d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0xa, 0x9, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x20, 0x3d, 0x20, 0x63, 0x63, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x3a, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0xa, 0x9, 0x9, 0x9, 0x66, 0x20, 0x3d, 0x20, 0x66, 0x20, 0x2e, 0x2e, 0x20, 0x63, 0x63, 0x5b, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5d, 0x3a, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0xa, 0x9, 0x9, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x66, 0x20, 0x3d, 0x20, 0x66, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x2d, 0x67, 0x20, 0x22, 0x20, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x9, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x66, 0x20, 0x3d, 0x20, 0x66, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x2d, 0x4f, 0x32, 0x20, 0x22, 0x20, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x9, 0x9, 0xa, 0x9, 0x9, 0x9, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x73, 0x74, 0x72, 0x20, 0x3d, 0x20, 0x63, 0x63, 0x5b, 0x65, 0x78, 0x65, 0x5d, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x66, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x2d, 0x63, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x64, 0x20, 0x2e, 0x2e, 0x20, 0x69, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2d, 0x6f, 0x20, 0x22, 0xa, 0x9, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x9, 0xa, 0x9, 0x9, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x73, 0x74, 0x72, 0x20, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x47, 0x43, 0x43, 0x5f, 0x43, 0x54, 0x65, 0x73, 0x74, 0x28, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x20, 0x3d, 0x20, 0x69, 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x28, 0x22, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x22, 0x29, 0xa, 0x9, 0x66, 0x3a, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x63, 0x6f, 0x64, 0x65, 0x29, 0xa, 0x9, 0x66, 0x3a, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0xa, 0x9, 0x66, 0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x69, 0x6c, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x67, 0x63, 0x63, 0x20, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x20, 0x2d, 0x6f, 0x20, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x29, 0xa, 0x9, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x28, 0x22, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x22, 0x29, 0xa, 0x9, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x28, 0x22, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x22, 0x29, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x3d, 0x3d, 0x30, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x4c, 0x49, 0x4e, 0x4b, 0x20, 0x47, 0x43, 0x43, 0x20, 0x44, 0x52, 0x49, 0x56, 0x45, 0x52, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x47, 0x43, 0x43, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2d, 0x6f, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x27, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0x20, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x27, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x6c, 0x69, 0x62, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x27, 0x2d, 0x4c, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x2c, 0x20, 0x27, 0x2d, 0x6c, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x27, 0x2d, 0x46, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2c, 0x20, 0x27, 0x2d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x3a, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0xa, 0x9, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x65, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x4c, 0x49, 0x42, 0x20, 0x47, 0x43, 0x43, 0x20, 0x44, 0x52, 0x49, 0x56, 0x45, 0x52, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x47, 0x43, 0x43, 0x5f, 0x4c, 0x69, 0x62, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x72, 0x63, 0x75, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x27, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x3a, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x44, 0x4c, 0x4c, 0x20, 0x47, 0x43, 0x43, 0x20, 0x44, 0x52, 0x49, 0x56, 0x45, 0x52, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x47, 0x43, 0x43, 0x5f, 0x44, 0x4c, 0x4c, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0xa, 0x9, 0x69, 0x66, 0x20, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6d, 0x61, 0x63, 0x6f, 0x73, 0x78, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x22, 0x20, 0x2d, 0x64, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x6c, 0x69, 0x62, 0x22, 0xa, 0x9, 0x65, 0x6c, 0x73, 0x65, 0xa, 0x9, 0x9, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x22, 0x20, 0x2d, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x22, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x5f, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2d, 0x6f, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x27, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0x20, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x27, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x6c, 0x69, 0x62, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x27, 0x2d, 0x4c, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x2c, 0x20, 0x27, 0x2d, 0x6c, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x27, 0x2d, 0x46, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2c, 0x20, 0x27, 0x2d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x27, 0x2c, 0x20, 0x27, 0x20, 0x27, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x20, 0x3d, 0x20, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x3a, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0xa, 0x9, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x65, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x53, 0x65, 0x74, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x47, 0x43, 0x43, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x2e, 0x6f, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x65, 0x78, 0x65, 0x5f, 0x63, 0x20, 0x3d, 0x20, 0x22, 0x67, 0x63, 0x63, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x65, 0x78, 0x65, 0x5f, 0x63, 0x78, 0x78, 0x20, 0x3d, 0x20, 0x22, 0x67, 0x2b, 0x2b, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x54, 0x65, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x47, 0x43, 0x43, 0x5f, 0x43, 0x54, 0x65, 0x73, 0x74, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x47, 0x43, 0x43, 0x5f, 0x47, 0x65, 0x74, 0x28, 0x22, 0x65, 0x78, 0x65, 0x5f, 0x63, 0x22, 0x2c, 0x20, 0x22, 0x5f, 0x63, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x22, 0x2c, 0x20, 0x22, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x22, 0x29, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x58, 0x58, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x47, 0x43, 0x43, 0x5f, 0x47, 0x65, 0x74, 0x28, 0x22, 0x65, 0x78, 0x65, 0x5f, 0x63, 0x78, 0x78, 0x22, 0x2c, 0x20, 0x22, 0x5f, 0x63, 0x78, 0x78, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x22, 0x2c, 0x20, 0x22, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x78, 0x78, 0x22, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x67, 0x2b, 0x2b, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x47, 0x43, 0x43, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x3d, 0x20, 0x22, 0x6c, 0x69, 0x62, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x2e, 0x61, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x61, 0x72, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x47, 0x43, 0x43, 0x5f, 0x4c, 0x69, 0x62, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x69, 0x66, 0x20, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x3d, 0x3d, 0x20, 0x22, 0x6d, 0x61, 0x63, 0x6f, 0x73, 0x78, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x3d, 0x20, 0x22, 0x6c, 0x69, 0x62, 0x22, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x2e, 0x64, 0x79, 0x6c, 0x69, 0x62, 0x22, 0xa, 0x9, 0x9, 0x65, 0x6c, 0x73, 0x65, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x20, 0x3d, 0x20, 0x22, 0x22, 0xa, 0x9, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x2e, 0x73, 0x6f, 0x22, 0xa, 0x9, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x67, 0x2b, 0x2b, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x47, 0x43, 0x43, 0x5f, 0x44, 0x4c, 0x4c, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x65, 0x6e, 0x64, 0xa, 0}; const char internal_file_4[] = {0xa, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x20, 0x63, 0x6c, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x28, 0x63, 0x70, 0x70, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x66, 0x73, 0x20, 0x3d, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x73, 0x2c, 0x20, 0x22, 0x2d, 0x44, 0x22, 0x2c, 0x20, 0x22, 0x20, 0x22, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x63, 0x73, 0x20, 0x3d, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x2c, 0x20, 0x27, 0x2d, 0x49, 0x22, 0x27, 0x2c, 0x20, 0x27, 0x22, 0x20, 0x27, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x63, 0x73, 0x20, 0x3d, 0x20, 0x69, 0x6e, 0x63, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73, 0x2c, 0x20, 0x27, 0x2d, 0x49, 0x22, 0x27, 0x2c, 0x20, 0x27, 0x22, 0x20, 0x27, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x3a, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0xa, 0x9, 0x69, 0x66, 0x20, 0x63, 0x70, 0x70, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x78, 0x78, 0x3a, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0xa, 0x9, 0x65, 0x6c, 0x73, 0x65, 0xa, 0x9, 0x9, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x5f, 0x63, 0x3a, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x65, 0x78, 0x65, 0x5f, 0x63, 0x2c, 0x20, 0x22, 0x2f, 0x22, 0x2c, 0x20, 0x22, 0x5c, 0x5c, 0x22, 0x29, 0xa, 0x9, 0x69, 0x66, 0x20, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x3d, 0x3d, 0x22, 0x77, 0x69, 0x6e, 0x33, 0x32, 0x22, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2f, 0x44, 0x20, 0x5c, 0x22, 0x57, 0x49, 0x4e, 0x33, 0x32, 0x5c, 0x22, 0x20, 0x22, 0xa, 0x9, 0x65, 0x6c, 0x73, 0x65, 0xa, 0x9, 0x9, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2f, 0x44, 0x20, 0x5c, 0x22, 0x57, 0x49, 0x4e, 0x36, 0x34, 0x5c, 0x22, 0x20, 0x22, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x2f, 0x4f, 0x64, 0x20, 0x2f, 0x4d, 0x54, 0x64, 0x20, 0x2f, 0x5a, 0x37, 0x20, 0x2f, 0x44, 0x20, 0x5c, 0x22, 0x5f, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5c, 0x22, 0x20, 0x22, 0x20, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x2f, 0x4f, 0x78, 0x20, 0x2f, 0x4f, 0x74, 0x20, 0x2f, 0x4d, 0x54, 0x20, 0x2f, 0x44, 0x20, 0x5c, 0x22, 0x4e, 0x44, 0x45, 0x42, 0x55, 0x47, 0x5c, 0x22, 0x20, 0x22, 0x20, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x65, 0x63, 0x20, 0x3d, 0x20, 0x65, 0x78, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2f, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x6f, 0x20, 0x2f, 0x44, 0x5f, 0x43, 0x52, 0x54, 0x5f, 0x53, 0x45, 0x43, 0x55, 0x52, 0x45, 0x5f, 0x4e, 0x4f, 0x5f, 0x44, 0x45, 0x50, 0x52, 0x45, 0x43, 0x41, 0x54, 0x45, 0x20, 0x2f, 0x63, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x63, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x64, 0x65, 0x66, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2f, 0x46, 0x6f, 0x22, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x78, 0x65, 0x63, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x43, 0x58, 0x58, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x61, 0x63, 0x68, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x5f, 0x63, 0x78, 0x78, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x7e, 0x3d, 0x20, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x6e, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x6e, 0x72, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0xa, 0x9, 0x9, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x73, 0x74, 0x72, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x28, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x73, 0x74, 0x72, 0x20, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x53, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x22, 0x46, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x43, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x61, 0x63, 0x68, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x5f, 0x63, 0x5f, 0x63, 0x61, 0x63, 0x68, 0x65, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x7e, 0x3d, 0x20, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x6e, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x6e, 0x72, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x69, 0x6e, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0xa, 0x9, 0x9, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x73, 0x74, 0x72, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x28, 0x6e, 0x69, 0x6c, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x73, 0x74, 0x72, 0x20, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x53, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x22, 0x46, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x50, 0x61, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x43, 0x54, 0x65, 0x73, 0x74, 0x28, 0x63, 0x6f, 0x64, 0x65, 0x2c, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x20, 0x3d, 0x20, 0x69, 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x28, 0x22, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x22, 0x2c, 0x20, 0x22, 0x77, 0x22, 0x29, 0xa, 0x9, 0x66, 0x3a, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x63, 0x6f, 0x64, 0x65, 0x29, 0xa, 0x9, 0x66, 0x3a, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x22, 0x5c, 0x6e, 0x22, 0x29, 0xa, 0x9, 0x66, 0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x74, 0x20, 0x3d, 0x20, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x69, 0x6c, 0x65, 0x6e, 0x74, 0x28, 0x22, 0x63, 0x6c, 0x20, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x20, 0x2f, 0x46, 0x65, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x29, 0xa, 0x9, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x28, 0x22, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x63, 0x22, 0x29, 0xa, 0x9, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x28, 0x22, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x65, 0x78, 0x65, 0x22, 0x29, 0xa, 0x9, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x28, 0x22, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6f, 0x62, 0x6a, 0x22, 0x29, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x3d, 0x3d, 0x30, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x65, 0x78, 0x65, 0x63, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x6c, 0x65, 0x6e, 0x28, 0x65, 0x78, 0x65, 0x63, 0x29, 0x20, 0x2b, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x6c, 0x65, 0x6e, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0x20, 0x3c, 0x20, 0x38, 0x30, 0x30, 0x30, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x78, 0x65, 0x63, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0xa, 0x9, 0x65, 0x6c, 0x73, 0x65, 0xa, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x2e, 0x72, 0x65, 0x73, 0x70, 0x22, 0xa, 0x9, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x69, 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x28, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x22, 0x77, 0x22, 0x29, 0xa, 0x9, 0x9, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x77, 0x72, 0x69, 0x74, 0x65, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x9, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x28, 0x29, 0xa, 0x9, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x65, 0x78, 0x65, 0x63, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x40, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x4c, 0x69, 0x62, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x22, 0x22, 0x2c, 0x20, 0x22, 0x20, 0x22, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x78, 0x65, 0x2c, 0x20, 0x22, 0x2f, 0x22, 0x2c, 0x20, 0x22, 0x5c, 0x5c, 0x22, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x65, 0x63, 0x20, 0x3d, 0x20, 0x65, 0x78, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2f, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x6f, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x3a, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2f, 0x4f, 0x55, 0x54, 0x3a, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x9, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x65, 0x78, 0x65, 0x63, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0x5f, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x70, 0x61, 0x72, 0x74, 0x2c, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x3d, 0x20, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x22, 0x22, 0x2c, 0x20, 0x22, 0x20, 0x22, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x70, 0x61, 0x72, 0x74, 0x2e, 0x65, 0x78, 0x74, 0x72, 0x61, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x22, 0x22, 0x2c, 0x20, 0x22, 0x20, 0x22, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x70, 0x61, 0x72, 0x74, 0x2e, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x3a, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x62, 0x73, 0x20, 0x20, 0x3d, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x70, 0x61, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x73, 0x2c, 0x20, 0x22, 0x22, 0x2c, 0x20, 0x22, 0x2e, 0x6c, 0x69, 0x62, 0x20, 0x22, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x62, 0x70, 0x61, 0x74, 0x68, 0x73, 0x20, 0x3d, 0x20, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x6f, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x70, 0x61, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x70, 0x61, 0x74, 0x68, 0x2c, 0x20, 0x22, 0x2f, 0x6c, 0x69, 0x62, 0x70, 0x61, 0x74, 0x68, 0x3a, 0x5c, 0x22, 0x22, 0x2c, 0x20, 0x22, 0x5c, 0x22, 0x20, 0x22, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x5f, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x28, 0x70, 0x61, 0x72, 0x74, 0x2e, 0x65, 0x78, 0x65, 0x2c, 0x20, 0x22, 0x2f, 0x22, 0x2c, 0x20, 0x22, 0x5c, 0x5c, 0x22, 0x29, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x65, 0x62, 0x75, 0x67, 0x20, 0x3e, 0x20, 0x30, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x3d, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x2f, 0x44, 0x45, 0x42, 0x55, 0x47, 0x20, 0x22, 0x20, 0x65, 0x6e, 0x64, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78, 0x65, 0x63, 0x20, 0x3d, 0x20, 0x65, 0x78, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2f, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x6f, 0x20, 0x2f, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x3a, 0x6e, 0x6f, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x65, 0x78, 0x74, 0x72, 0x61, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x66, 0x6c, 0x61, 0x67, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x6c, 0x69, 0x62, 0x70, 0x61, 0x74, 0x68, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x6c, 0x69, 0x62, 0x73, 0x20, 0x2e, 0x2e, 0x20, 0x22, 0x20, 0x2f, 0x4f, 0x55, 0x54, 0x3a, 0x22, 0x20, 0x2e, 0x2e, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0xa, 0x9, 0x65, 0x78, 0x65, 0x63, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x65, 0x78, 0x65, 0x63, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x29, 0xa, 0x9, 0x41, 0x64, 0x64, 0x4a, 0x6f, 0x62, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x65, 0x78, 0x65, 0x63, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x44, 0x4c, 0x4c, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0x5f, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2c, 0x20, 0x22, 0x2f, 0x44, 0x4c, 0x4c, 0x22, 0x29, 0xa, 0x9, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6c, 0x69, 0x62, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x73, 0x75, 0x62, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x6c, 0x65, 0x6e, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x29, 0x20, 0x2d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x6c, 0x65, 0x6e, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x29, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0xa, 0x9, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x28, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x6c, 0x69, 0x62, 0x66, 0x69, 0x6c, 0x65, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0x5f, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x28, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x2c, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x2c, 0x20, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2c, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2c, 0x20, 0x22, 0x22, 0x29, 0xa, 0x65, 0x6e, 0x64, 0xa, 0xa, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x53, 0x65, 0x74, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x43, 0x4c, 0x28, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x29, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x2e, 0x6f, 0x62, 0x6a, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x65, 0x78, 0x65, 0x5f, 0x63, 0x20, 0x3d, 0x20, 0x22, 0x63, 0x6c, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x65, 0x78, 0x65, 0x5f, 0x63, 0x78, 0x78, 0x20, 0x3d, 0x20, 0x22, 0x63, 0x6c, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x54, 0x65, 0x73, 0x74, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x43, 0x54, 0x65, 0x73, 0x74, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x43, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x63, 0x63, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x58, 0x58, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x43, 0x58, 0x58, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x2e, 0x65, 0x78, 0x65, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x4c, 0x69, 0x6e, 0x6b, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x2e, 0x6c, 0x69, 0x62, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x6c, 0x69, 0x62, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x4c, 0x69, 0x62, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x9, 0xa, 0x9, 0x69, 0x66, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x6e, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x22, 0x2e, 0x64, 0x6c, 0x6c, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x65, 0x78, 0x65, 0x20, 0x3d, 0x20, 0x22, 0x6c, 0x69, 0x6e, 0x6b, 0x22, 0xa, 0x9, 0x9, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x64, 0x6c, 0x6c, 0x2e, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x20, 0x3d, 0x20, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x4c, 0x5f, 0x44, 0x4c, 0x4c, 0xa, 0x9, 0x65, 0x6e, 0x64, 0xa, 0x65, 0x6e, 0x64, 0xa, 0}; INTERNALFILE internal_files[] = {{"src/base.lua", internal_file_1 }, {"src/tools.lua", internal_file_2 }, {"src/driver_gcc.lua", internal_file_3 }, {"src/driver_cl.lua", internal_file_4 }, {0}}; bam-0.4.0/src/driver_gcc.lua0000644000175000017500000000727111430042030013747 0ustar kmakma ------------------------ C/C++ GCC DRIVER ------------------------ function DriverGCC_Get(exe, cache_name, flags_name) return function(label, output, input, settings) local cache = settings.cc[cache_name] if settings.invoke_count ~= cache.nr then cache.nr = settings.invoke_count local cc = settings.cc local d = TableToString(cc.defines, "-D", " ") local i = TableToString(cc.includes, '-I "', '" ') local i = i .. TableToString(cc.systemincludes, '-isystem "', '" ') local i = i .. TableToString(cc.frameworks, '-framework ', ' ') local f = cc.flags:ToString() f = f .. cc[flags_name]:ToString() if settings.debug > 0 then f = f .. "-g " end if settings.optimize > 0 then f = f .. "-O2 " end cache.str = cc[exe] .. " " .. f .. "-c " .. d .. i .. " -o " end AddJob(output, label, cache.str .. output .. " " .. input) end end function DriverGCC_CTest(code, options) local f = io.open("_test.c", "w") f:write(code) f:write("\n") f:close() local ret = ExecuteSilent("gcc _test.c -o _test " .. options) os.remove("_test.c") os.remove("_test") return ret==0 end ------------------------ LINK GCC DRIVER ------------------------ function DriverGCC_Link(label, output, inputs, settings) local e = settings.link.exe .. " -o " .. output local e = e .. " " .. settings.link.inputflags .. " " .. TableToString(inputs, '', ' ') local e = e .. TableToString(settings.link.extrafiles, '', ' ') local e = e .. TableToString(settings.link.libpath, '-L', ' ') local e = e .. TableToString(settings.link.libs, '-l', ' ') local e = e .. TableToString(settings.link.frameworkpath, '-F', ' ') local e = e .. TableToString(settings.link.frameworks, '-framework ', ' ') local e = e .. settings.link.flags:ToString() AddJob(output, label, e) end ------------------------ LIB GCC DRIVER ------------------------ function DriverGCC_Lib(output, inputs, settings) local e = settings.lib.exe .. " rcu " .. output local e = e .. " " .. TableToString(inputs, '', ' ') .. settings.lib.flags:ToString() return e end ------------------------ DLL GCC DRIVER ------------------------ function DriverGCC_DLL(label, output, inputs, settings) local shared_flags = "" if platform == "macosx" then shared_flags = " -dynamiclib" else shared_flags = " -shared" end local e = settings.dll.exe .. shared_flags .. " -o " .. output local e = e .. " " .. settings.dll.inputflags .. " " .. TableToString(inputs, '', ' ') local e = e .. TableToString(settings.dll.extrafiles, '', ' ') local e = e .. TableToString(settings.dll.libpath, '-L', ' ') local e = e .. TableToString(settings.dll.libs, '-l', ' ') local e = e .. TableToString(settings.dll.frameworkpath, '-F', ' ') local e = e .. TableToString(settings.dll.frameworks, '-framework ', ' ') local e = e .. settings.dll.flags:ToString() AddJob(output, label, e) end function SetDriversGCC(settings) if settings.cc then settings.cc.extension = ".o" settings.cc.exe_c = "gcc" settings.cc.exe_cxx = "g++" settings.cc.DriverCTest = DriverGCC_CTest settings.cc.DriverC = DriverGCC_Get("exe_c", "_c_cache", "flags_c") settings.cc.DriverCXX = DriverGCC_Get("exe_cxx", "_cxx_cache", "flags_cxx") end if settings.link then settings.link.extension = "" settings.link.exe = "g++" settings.link.Driver = DriverGCC_Link end if settings.lib then settings.lib.prefix = "lib" settings.lib.extension = ".a" settings.lib.exe = "ar" settings.lib.Driver = DriverGCC_Lib end if settings.dll then if platform == "macosx" then settings.dll.prefix = "lib" settings.dll.extension = ".dylib" else settings.dll.prefix = "" settings.dll.extension = ".so" end settings.dll.exe = "g++" settings.dll.Driver = DriverGCC_DLL end end bam-0.4.0/src/driver_cl.lua0000644000175000017500000001012411430042030013600 0ustar kmakma ----- cl compiler ------ function DriverCL_Common(cpp, settings) local defs = TableToString(settings.cc.defines, "-D", " ") .. " " local incs = TableToString(settings.cc.includes, '-I"', '" ') local incs = incs .. TableToString(settings.cc.systemincludes, '-I"', '" ') local flags = settings.cc.flags:ToString() if cpp then flags = flags .. settings.cc.flags_cxx:ToString() else flags = flags .. settings.cc.flags_c:ToString() end local exe = str_replace(settings.cc.exe_c, "/", "\\") if platform =="win32" then flags = flags .. " /D \"WIN32\" " else flags = flags .. " /D \"WIN64\" " end if settings.debug > 0 then flags = flags .. "/Od /MTd /Z7 /D \"_DEBUG\" " end if settings.optimize > 0 then flags = flags .. "/Ox /Ot /MT /D \"NDEBUG\" " end local exec = exe .. " /nologo /D_CRT_SECURE_NO_DEPRECATE /c " .. flags .. " " .. incs .. defs .. " /Fo" return exec end function DriverCL_CXX(label, output,input, settings) local cache = settings.cc._cxx_cache if settings.invoke_count ~= cache.nr then cache.nr = settings.invoke_count cache.str = DriverCL_Common(true, settings) end AddJob(output, label, cache.str .. output .. " " .. input) SetFilter(output, "F" .. PathFilename(input)) end function DriverCL_C(label, output, input, settings) local cache = settings.cc._c_cache if settings.invoke_count ~= cache.nr then cache.nr = settings.invoke_count cache.str = DriverCL_Common(nil, settings) end AddJob(output, label, cache.str .. output .. " " .. input) SetFilter(output, "F" .. PathFilename(input)) end function DriverCL_CTest(code, options) local f = io.open("_test.c", "w") f:write(code) f:write("\n") f:close() local ret = ExecuteSilent("cl _test.c /Fe_test " .. options) os.remove("_test.c") os.remove("_test.exe") os.remove("_test.obj") return ret==0 end function DriverCL_BuildResponse(exec, output, input) if string.len(exec) + string.len(input) < 8000 then return exec .. " " .. input else local response_filename = output .. ".resp" local response_file = io.open(response_filename, "w") response_file:write(input) response_file:close() return exec .. " @" .. response_filename end end function DriverCL_Lib(output, inputs, settings) local input = TableToString(inputs, "", " ") local exe = str_replace(settings.lib.exe, "/", "\\") local exec = exe .. " /nologo " .. settings.lib.flags:ToString() .. " /OUT:" .. output return DriverCL_BuildResponse(exec, output, input) end function DriverCL_Link_Common(label, output, inputs, settings, part, extra) local input = TableToString(inputs, "", " ") .. TableToString(part.extrafiles, "", " ") local flags = part.flags:ToString() local libs = TableToString(part.libs, "", ".lib ") local libpaths = TableToString(part.libpath, "/libpath:\"", "\" ") local exe = str_replace(part.exe, "/", "\\") if settings.debug > 0 then flags = flags .. "/DEBUG " end local exec = exe .. " /nologo /incremental:no " .. extra .. " " .. flags .. libpaths .. libs .. " /OUT:" .. output exec = DriverCL_BuildResponse(exec, output, input) AddJob(output, label, exec) end function DriverCL_DLL(label, output, inputs, settings) DriverCL_Link_Common(label, output, inputs, settings, settings.dll, "/DLL") local libfile = string.sub(output, 0, string.len(output) - string.len(settings.dll.extension)) .. settings.lib.extension AddOutput(output, libfile) end function DriverCL_Link(label, output, inputs, settings) DriverCL_Link_Common(label, output, inputs, settings, settings.link, "") end function SetDriversCL(settings) if settings.cc then settings.cc.extension = ".obj" settings.cc.exe_c = "cl" settings.cc.exe_cxx = "cl" settings.cc.DriverCTest = DriverCL_CTest settings.cc.DriverC = DriverCL_C settings.cc.DriverCXX = DriverCL_CXX end if settings.link then settings.link.extension = ".exe" settings.link.exe = "link" settings.link.Driver = DriverCL_Link end if settings.lib then settings.lib.extension = ".lib" settings.lib.exe = "lib" settings.lib.Driver = DriverCL_Lib end if settings.dll then settings.dll.extension = ".dll" settings.dll.exe = "link" settings.dll.Driver = DriverCL_DLL end end bam-0.4.0/src/lua/0000755000175000017500000000000011430042030011707 5ustar kmakmabam-0.4.0/src/lua/lgc.c0000644000175000017500000004720311430042030012626 0ustar kmakma/* ** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ #include #define lgc_c #define LUA_CORE #include "lua.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" #include "lgc.h" #include "lmem.h" #include "lobject.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" #define GCSTEPSIZE 1024u #define GCSWEEPMAX 40 #define GCSWEEPCOST 10 #define GCFINALIZECOST 100 #define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) #define makewhite(g,x) \ ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) #define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) #define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) #define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) #define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) #define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) #define KEYWEAK bitmask(KEYWEAKBIT) #define VALUEWEAK bitmask(VALUEWEAKBIT) #define markvalue(g,o) { checkconsistency(o); \ if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } #define markobject(g,t) { if (iswhite(obj2gco(t))) \ reallymarkobject(g, obj2gco(t)); } #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) static void removeentry (Node *n) { lua_assert(ttisnil(gval(n))); if (iscollectable(gkey(n))) setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ } static void reallymarkobject (global_State *g, GCObject *o) { lua_assert(iswhite(o) && !isdead(g, o)); white2gray(o); switch (o->gch.tt) { case LUA_TSTRING: { return; } case LUA_TUSERDATA: { Table *mt = gco2u(o)->metatable; gray2black(o); /* udata are never gray */ if (mt) markobject(g, mt); markobject(g, gco2u(o)->env); return; } case LUA_TUPVAL: { UpVal *uv = gco2uv(o); markvalue(g, uv->v); if (uv->v == &uv->u.value) /* closed? */ gray2black(o); /* open upvalues are never black */ return; } case LUA_TFUNCTION: { gco2cl(o)->c.gclist = g->gray; g->gray = o; break; } case LUA_TTABLE: { gco2h(o)->gclist = g->gray; g->gray = o; break; } case LUA_TTHREAD: { gco2th(o)->gclist = g->gray; g->gray = o; break; } case LUA_TPROTO: { gco2p(o)->gclist = g->gray; g->gray = o; break; } default: lua_assert(0); } } static void marktmu (global_State *g) { GCObject *u = g->tmudata; if (u) { do { u = u->gch.next; makewhite(g, u); /* may be marked, if left from previous GC */ reallymarkobject(g, u); } while (u != g->tmudata); } } /* move `dead' udata that need finalization to list `tmudata' */ size_t luaC_separateudata (lua_State *L, int all) { global_State *g = G(L); size_t deadmem = 0; GCObject **p = &g->mainthread->next; GCObject *curr; while ((curr = *p) != NULL) { if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) p = &curr->gch.next; /* don't bother with them */ else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { markfinalized(gco2u(curr)); /* don't need finalization */ p = &curr->gch.next; } else { /* must call its gc method */ deadmem += sizeudata(gco2u(curr)); markfinalized(gco2u(curr)); *p = curr->gch.next; /* link `curr' at the end of `tmudata' list */ if (g->tmudata == NULL) /* list is empty? */ g->tmudata = curr->gch.next = curr; /* creates a circular list */ else { curr->gch.next = g->tmudata->gch.next; g->tmudata->gch.next = curr; g->tmudata = curr; } } } return deadmem; } static int traversetable (global_State *g, Table *h) { int i; int weakkey = 0; int weakvalue = 0; const TValue *mode; if (h->metatable) markobject(g, h->metatable); mode = gfasttm(g, h->metatable, TM_MODE); if (mode && ttisstring(mode)) { /* is there a weak mode? */ weakkey = (strchr(svalue(mode), 'k') != NULL); weakvalue = (strchr(svalue(mode), 'v') != NULL); if (weakkey || weakvalue) { /* is really weak? */ h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ h->marked |= cast_byte((weakkey << KEYWEAKBIT) | (weakvalue << VALUEWEAKBIT)); h->gclist = g->weak; /* must be cleared after GC, ... */ g->weak = obj2gco(h); /* ... so put in the appropriate list */ } } if (weakkey && weakvalue) return 1; if (!weakvalue) { i = h->sizearray; while (i--) markvalue(g, &h->array[i]); } i = sizenode(h); while (i--) { Node *n = gnode(h, i); lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); if (ttisnil(gval(n))) removeentry(n); /* remove empty entries */ else { lua_assert(!ttisnil(gkey(n))); if (!weakkey) markvalue(g, gkey(n)); if (!weakvalue) markvalue(g, gval(n)); } } return weakkey || weakvalue; } /* ** All marks are conditional because a GC may happen while the ** prototype is still being created */ static void traverseproto (global_State *g, Proto *f) { int i; if (f->source) stringmark(f->source); for (i=0; isizek; i++) /* mark literals */ markvalue(g, &f->k[i]); for (i=0; isizeupvalues; i++) { /* mark upvalue names */ if (f->upvalues[i]) stringmark(f->upvalues[i]); } for (i=0; isizep; i++) { /* mark nested protos */ if (f->p[i]) markobject(g, f->p[i]); } for (i=0; isizelocvars; i++) { /* mark local-variable names */ if (f->locvars[i].varname) stringmark(f->locvars[i].varname); } } static void traverseclosure (global_State *g, Closure *cl) { markobject(g, cl->c.env); if (cl->c.isC) { int i; for (i=0; ic.nupvalues; i++) /* mark its upvalues */ markvalue(g, &cl->c.upvalue[i]); } else { int i; lua_assert(cl->l.nupvalues == cl->l.p->nups); markobject(g, cl->l.p); for (i=0; il.nupvalues; i++) /* mark its upvalues */ markobject(g, cl->l.upvals[i]); } } static void checkstacksizes (lua_State *L, StkId max) { int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ int s_used = cast_int(max - L->stack); /* part of stack in use */ if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ return; /* do not touch the stacks */ if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ condhardstacktests(luaD_reallocCI(L, ci_used + 1)); if (4*s_used < L->stacksize && 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ condhardstacktests(luaD_reallocstack(L, s_used)); } static void traversestack (global_State *g, lua_State *l) { StkId o, lim; CallInfo *ci; markvalue(g, gt(l)); lim = l->top; for (ci = l->base_ci; ci <= l->ci; ci++) { lua_assert(ci->top <= l->stack_last); if (lim < ci->top) lim = ci->top; } for (o = l->stack; o < l->top; o++) markvalue(g, o); for (; o <= lim; o++) setnilvalue(o); checkstacksizes(l, lim); } /* ** traverse one gray object, turning it to black. ** Returns `quantity' traversed. */ static l_mem propagatemark (global_State *g) { GCObject *o = g->gray; lua_assert(isgray(o)); gray2black(o); switch (o->gch.tt) { case LUA_TTABLE: { Table *h = gco2h(o); g->gray = h->gclist; if (traversetable(g, h)) /* table is weak? */ black2gray(o); /* keep it gray */ return sizeof(Table) + sizeof(TValue) * h->sizearray + sizeof(Node) * sizenode(h); } case LUA_TFUNCTION: { Closure *cl = gco2cl(o); g->gray = cl->c.gclist; traverseclosure(g, cl); return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : sizeLclosure(cl->l.nupvalues); } case LUA_TTHREAD: { lua_State *th = gco2th(o); g->gray = th->gclist; th->gclist = g->grayagain; g->grayagain = o; black2gray(o); traversestack(g, th); return sizeof(lua_State) + sizeof(TValue) * th->stacksize + sizeof(CallInfo) * th->size_ci; } case LUA_TPROTO: { Proto *p = gco2p(o); g->gray = p->gclist; traverseproto(g, p); return sizeof(Proto) + sizeof(Instruction) * p->sizecode + sizeof(Proto *) * p->sizep + sizeof(TValue) * p->sizek + sizeof(int) * p->sizelineinfo + sizeof(LocVar) * p->sizelocvars + sizeof(TString *) * p->sizeupvalues; } default: lua_assert(0); return 0; } } static size_t propagateall (global_State *g) { size_t m = 0; while (g->gray) m += propagatemark(g); return m; } /* ** The next function tells whether a key or value can be cleared from ** a weak table. Non-collectable objects are never removed from weak ** tables. Strings behave as `values', so are never removed too. for ** other objects: if really collected, cannot keep them; for userdata ** being finalized, keep them in keys, but not in values */ static int iscleared (const TValue *o, int iskey) { if (!iscollectable(o)) return 0; if (ttisstring(o)) { stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ return 0; } return iswhite(gcvalue(o)) || (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); } /* ** clear collected entries from weaktables */ static void cleartable (GCObject *l) { while (l) { Table *h = gco2h(l); int i = h->sizearray; lua_assert(testbit(h->marked, VALUEWEAKBIT) || testbit(h->marked, KEYWEAKBIT)); if (testbit(h->marked, VALUEWEAKBIT)) { while (i--) { TValue *o = &h->array[i]; if (iscleared(o, 0)) /* value was collected? */ setnilvalue(o); /* remove value */ } } i = sizenode(h); while (i--) { Node *n = gnode(h, i); if (!ttisnil(gval(n)) && /* non-empty entry? */ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { setnilvalue(gval(n)); /* remove value ... */ removeentry(n); /* remove entry from table */ } } l = h->gclist; } } static void freeobj (lua_State *L, GCObject *o) { switch (o->gch.tt) { case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; case LUA_TTABLE: luaH_free(L, gco2h(o)); break; case LUA_TTHREAD: { lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); luaE_freethread(L, gco2th(o)); break; } case LUA_TSTRING: { G(L)->strt.nuse--; luaM_freemem(L, o, sizestring(gco2ts(o))); break; } case LUA_TUSERDATA: { luaM_freemem(L, o, sizeudata(gco2u(o))); break; } default: lua_assert(0); } } #define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { GCObject *curr; global_State *g = G(L); int deadmask = otherwhite(g); while ((curr = *p) != NULL && count-- > 0) { if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ sweepwholelist(L, &gco2th(curr)->openupval); if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); makewhite(g, curr); /* make it white (for next cycle) */ p = &curr->gch.next; } else { /* must erase `curr' */ lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); *p = curr->gch.next; if (curr == g->rootgc) /* is the first element of the list? */ g->rootgc = curr->gch.next; /* adjust first */ freeobj(L, curr); } } return p; } static void checkSizes (lua_State *L) { global_State *g = G(L); /* check size of string hash */ if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && g->strt.size > MINSTRTABSIZE*2) luaS_resize(L, g->strt.size/2); /* table is too big */ /* check size of buffer */ if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ size_t newsize = luaZ_sizebuffer(&g->buff) / 2; luaZ_resizebuffer(L, &g->buff, newsize); } } static void GCTM (lua_State *L) { global_State *g = G(L); GCObject *o = g->tmudata->gch.next; /* get first element */ Udata *udata = rawgco2u(o); const TValue *tm; /* remove udata from `tmudata' */ if (o == g->tmudata) /* last element? */ g->tmudata = NULL; else g->tmudata->gch.next = udata->uv.next; udata->uv.next = g->mainthread->next; /* return it to `root' list */ g->mainthread->next = o; makewhite(g, o); tm = fasttm(L, udata->uv.metatable, TM_GC); if (tm != NULL) { lu_byte oldah = L->allowhook; lu_mem oldt = g->GCthreshold; L->allowhook = 0; /* stop debug hooks during GC tag method */ g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ setobj2s(L, L->top, tm); setuvalue(L, L->top+1, udata); L->top += 2; luaD_call(L, L->top - 2, 0); L->allowhook = oldah; /* restore hooks */ g->GCthreshold = oldt; /* restore threshold */ } } /* ** Call all GC tag methods */ void luaC_callGCTM (lua_State *L) { while (G(L)->tmudata) GCTM(L); } void luaC_freeall (lua_State *L) { global_State *g = G(L); int i; g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ sweepwholelist(L, &g->rootgc); for (i = 0; i < g->strt.size; i++) /* free all string lists */ sweepwholelist(L, &g->strt.hash[i]); } static void markmt (global_State *g) { int i; for (i=0; imt[i]) markobject(g, g->mt[i]); } /* mark root set */ static void markroot (lua_State *L) { global_State *g = G(L); g->gray = NULL; g->grayagain = NULL; g->weak = NULL; markobject(g, g->mainthread); /* make global table be traversed before main stack */ markvalue(g, gt(g->mainthread)); markvalue(g, registry(L)); markmt(g); g->gcstate = GCSpropagate; } static void remarkupvals (global_State *g) { UpVal *uv; for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); if (isgray(obj2gco(uv))) markvalue(g, uv->v); } } static void atomic (lua_State *L) { global_State *g = G(L); size_t udsize; /* total size of userdata to be finalized */ /* remark occasional upvalues of (maybe) dead threads */ remarkupvals(g); /* traverse objects cautch by write barrier and by 'remarkupvals' */ propagateall(g); /* remark weak tables */ g->gray = g->weak; g->weak = NULL; lua_assert(!iswhite(obj2gco(g->mainthread))); markobject(g, L); /* mark running thread */ markmt(g); /* mark basic metatables (again) */ propagateall(g); /* remark gray again */ g->gray = g->grayagain; g->grayagain = NULL; propagateall(g); udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ marktmu(g); /* mark `preserved' userdata */ udsize += propagateall(g); /* remark, to propagate `preserveness' */ cleartable(g->weak); /* remove collected objects from weak tables */ /* flip current white */ g->currentwhite = cast_byte(otherwhite(g)); g->sweepstrgc = 0; g->sweepgc = &g->rootgc; g->gcstate = GCSsweepstring; g->estimate = g->totalbytes - udsize; /* first estimate */ } static l_mem singlestep (lua_State *L) { global_State *g = G(L); /*lua_checkmemory(L);*/ switch (g->gcstate) { case GCSpause: { markroot(L); /* start a new collection */ return 0; } case GCSpropagate: { if (g->gray) return propagatemark(g); else { /* no more `gray' objects */ atomic(L); /* finish mark phase */ return 0; } } case GCSsweepstring: { lu_mem old = g->totalbytes; sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ g->gcstate = GCSsweep; /* end sweep-string phase */ lua_assert(old >= g->totalbytes); g->estimate -= old - g->totalbytes; return GCSWEEPCOST; } case GCSsweep: { lu_mem old = g->totalbytes; g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); if (*g->sweepgc == NULL) { /* nothing more to sweep? */ checkSizes(L); g->gcstate = GCSfinalize; /* end sweep phase */ } lua_assert(old >= g->totalbytes); g->estimate -= old - g->totalbytes; return GCSWEEPMAX*GCSWEEPCOST; } case GCSfinalize: { if (g->tmudata) { GCTM(L); if (g->estimate > GCFINALIZECOST) g->estimate -= GCFINALIZECOST; return GCFINALIZECOST; } else { g->gcstate = GCSpause; /* end collection */ g->gcdept = 0; return 0; } } default: lua_assert(0); return 0; } } void luaC_step (lua_State *L) { global_State *g = G(L); l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; if (lim == 0) lim = (MAX_LUMEM-1)/2; /* no limit */ g->gcdept += g->totalbytes - g->GCthreshold; do { lim -= singlestep(L); if (g->gcstate == GCSpause) break; } while (lim > 0); if (g->gcstate != GCSpause) { if (g->gcdept < GCSTEPSIZE) g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ else { g->gcdept -= GCSTEPSIZE; g->GCthreshold = g->totalbytes; } } else { lua_assert(g->totalbytes >= g->estimate); setthreshold(g); } } void luaC_fullgc (lua_State *L) { global_State *g = G(L); if (g->gcstate <= GCSpropagate) { /* reset sweep marks to sweep all elements (returning them to white) */ g->sweepstrgc = 0; g->sweepgc = &g->rootgc; /* reset other collector lists */ g->gray = NULL; g->grayagain = NULL; g->weak = NULL; g->gcstate = GCSsweepstring; } lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); /* finish any pending sweep phase */ while (g->gcstate != GCSfinalize) { lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); singlestep(L); } markroot(L); while (g->gcstate != GCSpause) { singlestep(L); } setthreshold(g); } void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { global_State *g = G(L); lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); lua_assert(ttype(&o->gch) != LUA_TTABLE); /* must keep invariant? */ if (g->gcstate == GCSpropagate) reallymarkobject(g, v); /* restore invariant */ else /* don't mind */ makewhite(g, o); /* mark as white just to avoid other barriers */ } void luaC_barrierback (lua_State *L, Table *t) { global_State *g = G(L); GCObject *o = obj2gco(t); lua_assert(isblack(o) && !isdead(g, o)); lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); black2gray(o); /* make table gray (again) */ t->gclist = g->grayagain; g->grayagain = o; } void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { global_State *g = G(L); o->gch.next = g->rootgc; g->rootgc = o; o->gch.marked = luaC_white(g); o->gch.tt = tt; } void luaC_linkupval (lua_State *L, UpVal *uv) { global_State *g = G(L); GCObject *o = obj2gco(uv); o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ g->rootgc = o; if (isgray(o)) { if (g->gcstate == GCSpropagate) { gray2black(o); /* closed upvalues need barrier */ luaC_barrier(L, uv, uv->v); } else { /* sweep phase: sweep it (turning it into white) */ makewhite(g, o); lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); } } } bam-0.4.0/src/lua/lvm.h0000644000175000017500000000220711430042030012657 0ustar kmakma/* ** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ #ifndef lvm_h #define lvm_h #include "ldo.h" #include "lobject.h" #include "ltm.h" #define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) #define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ (((o) = luaV_tonumber(o,n)) != NULL)) #define equalobj(L,o1,o2) \ (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val); LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val); LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); #endif bam-0.4.0/src/lua/IMPORTANTINFO0000644000175000017500000000017211430042030013663 0ustar kmakmaThis is a slimmed down version of lua 5.1. If you want to use lua for your own project, please obtain a complete version. bam-0.4.0/src/lua/lopcodes.h0000644000175000017500000001762611430042030013704 0ustar kmakma/* ** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ ** Opcodes for Lua virtual machine ** See Copyright Notice in lua.h */ #ifndef lopcodes_h #define lopcodes_h #include "llimits.h" /*=========================================================================== We assume that instructions are unsigned numbers. All instructions have an opcode in the first 6 bits. Instructions can have the following fields: `A' : 8 bits `B' : 9 bits `C' : 9 bits `Bx' : 18 bits (`B' and `C' together) `sBx' : signed Bx A signed argument is represented in excess K; that is, the number value is the unsigned value minus K. K is exactly the maximum value for that argument (so that -max is represented by 0, and +max is represented by 2*max), which is half the maximum for the corresponding unsigned argument. ===========================================================================*/ enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ /* ** size and position of opcode arguments. */ #define SIZE_C 9 #define SIZE_B 9 #define SIZE_Bx (SIZE_C + SIZE_B) #define SIZE_A 8 #define SIZE_OP 6 #define POS_OP 0 #define POS_A (POS_OP + SIZE_OP) #define POS_C (POS_A + SIZE_A) #define POS_B (POS_C + SIZE_C) #define POS_Bx POS_C /* ** limits for opcode arguments. ** we use (signed) int to manipulate most arguments, ** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) */ #if SIZE_Bx < LUAI_BITSINT-1 #define MAXARG_Bx ((1<>1) /* `sBx' is signed */ #else #define MAXARG_Bx MAX_INT #define MAXARG_sBx MAX_INT #endif #define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0))) #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) #define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) #define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) #define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) #define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ ((cast(Instruction, b)< C) then pc++ */ OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ OP_FORLOOP,/* A sBx R(A)+=R(A+2); if R(A) =) R(A)*/ OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ } OpCode; #define NUM_OPCODES (cast(int, OP_VARARG) + 1) /*=========================================================================== Notes: (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, and can be 0: OP_CALL then sets `top' to last_result+1, so next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. (*) In OP_VARARG, if (B == 0) then use actual number of varargs and set top (like in OP_CALL with C == 0). (*) In OP_RETURN, if (B == 0) then return up to `top' (*) In OP_SETLIST, if (B == 0) then B = `top'; if (C == 0) then next `instruction' is real C (*) For comparisons, A specifies what condition the test should accept (true or false). (*) All `skips' (pc++) assume that next instruction is a jump ===========================================================================*/ /* ** masks for instruction properties. The format is: ** bits 0-1: op mode ** bits 2-3: C arg mode ** bits 4-5: B arg mode ** bit 6: instruction set register A ** bit 7: operator is a test */ enum OpArgMask { OpArgN, /* argument is not used */ OpArgU, /* argument is used */ OpArgR, /* argument is a register or a jump offset */ OpArgK /* argument is a constant or register/constant */ }; LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; #define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) #define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) #define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) #define testAMode(m) (luaP_opmodes[m] & (1 << 6)) #define testTMode(m) (luaP_opmodes[m] & (1 << 7)) LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ /* number of list items to accumulate before a SETLIST instruction */ #define LFIELDS_PER_FLUSH 50 #endif bam-0.4.0/src/lua/lmathlib.c0000644000175000017500000001330711430042030013653 0ustar kmakma/* ** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $ ** Standard mathematical library ** See Copyright Notice in lua.h */ #include #include #define lmathlib_c #define LUA_LIB #include "lua.h" #include "lauxlib.h" #include "lualib.h" #undef PI #define PI (3.14159265358979323846) #define RADIANS_PER_DEGREE (PI/180.0) static int math_abs (lua_State *L) { lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); return 1; } static int math_sin (lua_State *L) { lua_pushnumber(L, sin(luaL_checknumber(L, 1))); return 1; } static int math_sinh (lua_State *L) { lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); return 1; } static int math_cos (lua_State *L) { lua_pushnumber(L, cos(luaL_checknumber(L, 1))); return 1; } static int math_cosh (lua_State *L) { lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); return 1; } static int math_tan (lua_State *L) { lua_pushnumber(L, tan(luaL_checknumber(L, 1))); return 1; } static int math_tanh (lua_State *L) { lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); return 1; } static int math_asin (lua_State *L) { lua_pushnumber(L, asin(luaL_checknumber(L, 1))); return 1; } static int math_acos (lua_State *L) { lua_pushnumber(L, acos(luaL_checknumber(L, 1))); return 1; } static int math_atan (lua_State *L) { lua_pushnumber(L, atan(luaL_checknumber(L, 1))); return 1; } static int math_atan2 (lua_State *L) { lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } static int math_ceil (lua_State *L) { lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); return 1; } static int math_floor (lua_State *L) { lua_pushnumber(L, floor(luaL_checknumber(L, 1))); return 1; } static int math_fmod (lua_State *L) { lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } static int math_modf (lua_State *L) { double ip; double fp = modf(luaL_checknumber(L, 1), &ip); lua_pushnumber(L, ip); lua_pushnumber(L, fp); return 2; } static int math_sqrt (lua_State *L) { lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); return 1; } static int math_pow (lua_State *L) { lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); return 1; } static int math_log (lua_State *L) { lua_pushnumber(L, log(luaL_checknumber(L, 1))); return 1; } static int math_log10 (lua_State *L) { lua_pushnumber(L, log10(luaL_checknumber(L, 1))); return 1; } static int math_exp (lua_State *L) { lua_pushnumber(L, exp(luaL_checknumber(L, 1))); return 1; } static int math_deg (lua_State *L) { lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); return 1; } static int math_rad (lua_State *L) { lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); return 1; } static int math_frexp (lua_State *L) { int e; lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); lua_pushinteger(L, e); return 2; } static int math_ldexp (lua_State *L) { lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); return 1; } static int math_min (lua_State *L) { int n = lua_gettop(L); /* number of arguments */ lua_Number dmin = luaL_checknumber(L, 1); int i; for (i=2; i<=n; i++) { lua_Number d = luaL_checknumber(L, i); if (d < dmin) dmin = d; } lua_pushnumber(L, dmin); return 1; } static int math_max (lua_State *L) { int n = lua_gettop(L); /* number of arguments */ lua_Number dmax = luaL_checknumber(L, 1); int i; for (i=2; i<=n; i++) { lua_Number d = luaL_checknumber(L, i); if (d > dmax) dmax = d; } lua_pushnumber(L, dmax); return 1; } static int math_random (lua_State *L) { /* the `%' avoids the (rare) case of r==1, and is needed also because on some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; switch (lua_gettop(L)) { /* check number of arguments */ case 0: { /* no arguments */ lua_pushnumber(L, r); /* Number between 0 and 1 */ break; } case 1: { /* only upper limit */ int u = luaL_checkint(L, 1); luaL_argcheck(L, 1<=u, 1, "interval is empty"); lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ break; } case 2: { /* lower and upper limits */ int l = luaL_checkint(L, 1); int u = luaL_checkint(L, 2); luaL_argcheck(L, l<=u, 2, "interval is empty"); lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ break; } default: return luaL_error(L, "wrong number of arguments"); } return 1; } static int math_randomseed (lua_State *L) { srand(luaL_checkint(L, 1)); return 0; } static const luaL_Reg mathlib[] = { {"abs", math_abs}, {"acos", math_acos}, {"asin", math_asin}, {"atan2", math_atan2}, {"atan", math_atan}, {"ceil", math_ceil}, {"cosh", math_cosh}, {"cos", math_cos}, {"deg", math_deg}, {"exp", math_exp}, {"floor", math_floor}, {"fmod", math_fmod}, {"frexp", math_frexp}, {"ldexp", math_ldexp}, {"log10", math_log10}, {"log", math_log}, {"max", math_max}, {"min", math_min}, {"modf", math_modf}, {"pow", math_pow}, {"rad", math_rad}, {"random", math_random}, {"randomseed", math_randomseed}, {"sinh", math_sinh}, {"sin", math_sin}, {"sqrt", math_sqrt}, {"tanh", math_tanh}, {"tan", math_tan}, {NULL, NULL} }; /* ** Open math library */ LUALIB_API int luaopen_math (lua_State *L) { luaL_register(L, LUA_MATHLIBNAME, mathlib); lua_pushnumber(L, PI); lua_setfield(L, -2, "pi"); lua_pushnumber(L, HUGE_VAL); lua_setfield(L, -2, "huge"); #if defined(LUA_COMPAT_MOD) lua_getfield(L, -1, "fmod"); lua_setfield(L, -2, "mod"); #endif return 1; } bam-0.4.0/src/lua/lzio.c0000644000175000017500000000313411430042030013031 0ustar kmakma/* ** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ ** a generic input stream interface ** See Copyright Notice in lua.h */ #include #define lzio_c #define LUA_CORE #include "lua.h" #include "llimits.h" #include "lmem.h" #include "lstate.h" #include "lzio.h" int luaZ_fill (ZIO *z) { size_t size; lua_State *L = z->L; const char *buff; lua_unlock(L); buff = z->reader(L, z->data, &size); lua_lock(L); if (buff == NULL || size == 0) return EOZ; z->n = size - 1; z->p = buff; return char2int(*(z->p++)); } int luaZ_lookahead (ZIO *z) { if (z->n == 0) { if (luaZ_fill(z) == EOZ) return EOZ; else { z->n++; /* luaZ_fill removed first byte; put back it */ z->p--; } } return char2int(*z->p); } void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { z->L = L; z->reader = reader; z->data = data; z->n = 0; z->p = NULL; } /* --------------------------------------------------------------- read --- */ size_t luaZ_read (ZIO *z, void *b, size_t n) { while (n) { size_t m; if (luaZ_lookahead(z) == EOZ) return n; /* return number of missing bytes */ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ memcpy(b, z->p, m); z->n -= m; z->p += m; b = (char *)b + m; n -= m; } return 0; } /* ------------------------------------------------------------------------ */ char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { if (n > buff->buffsize) { if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; luaZ_resizebuffer(L, buff, n); } return buff->buffer; } bam-0.4.0/src/lua/lmem.c0000644000175000017500000000417411430042030013013 0ustar kmakma/* ** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ #include #define lmem_c #define LUA_CORE #include "lua.h" #include "ldebug.h" #include "ldo.h" #include "lmem.h" #include "lobject.h" #include "lstate.h" /* ** About the realloc function: ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); ** (`osize' is the old size, `nsize' is the new size) ** ** Lua ensures that (ptr == NULL) iff (osize == 0). ** ** * frealloc(ud, NULL, 0, x) creates a new block of size `x' ** ** * frealloc(ud, p, x, 0) frees the block `p' ** (in this specific case, frealloc must return NULL). ** particularly, frealloc(ud, NULL, 0, 0) does nothing ** (which is equivalent to free(NULL) in ANSI C) ** ** frealloc returns NULL if it cannot create or reallocate the area ** (any reallocation to an equal or smaller size cannot fail!) */ #define MINSIZEARRAY 4 void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, int limit, const char *errormsg) { void *newblock; int newsize; if (*size >= limit/2) { /* cannot double it? */ if (*size >= limit) /* cannot grow even a little? */ luaG_runerror(L, errormsg); newsize = limit; /* still have at least one free place */ } else { newsize = (*size)*2; if (newsize < MINSIZEARRAY) newsize = MINSIZEARRAY; /* minimum size */ } newblock = luaM_reallocv(L, block, *size, newsize, size_elems); *size = newsize; /* update only when everything else is OK */ return newblock; } void *luaM_toobig (lua_State *L) { luaG_runerror(L, "memory allocation error: block too big"); return NULL; /* to avoid warnings */ } /* ** generic allocation routine. */ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { global_State *g = G(L); lua_assert((osize == 0) == (block == NULL)); block = (*g->frealloc)(g->ud, block, osize, nsize); if (block == NULL && nsize > 0) luaD_throw(L, LUA_ERRMEM); lua_assert((nsize == 0) == (block == NULL)); g->totalbytes = (g->totalbytes - osize) + nsize; return block; } bam-0.4.0/src/lua/lualib.h0000644000175000017500000000200211430042030013322 0ustar kmakma/* ** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ ** Lua standard libraries ** See Copyright Notice in lua.h */ #ifndef lualib_h #define lualib_h #include "lua.h" /* Key to file-handle type */ #define LUA_FILEHANDLE "FILE*" #define LUA_COLIBNAME "coroutine" LUALIB_API int (luaopen_base) (lua_State *L); #define LUA_TABLIBNAME "table" LUALIB_API int (luaopen_table) (lua_State *L); #define LUA_IOLIBNAME "io" LUALIB_API int (luaopen_io) (lua_State *L); #define LUA_OSLIBNAME "os" LUALIB_API int (luaopen_os) (lua_State *L); #define LUA_STRLIBNAME "string" LUALIB_API int (luaopen_string) (lua_State *L); #define LUA_MATHLIBNAME "math" LUALIB_API int (luaopen_math) (lua_State *L); #define LUA_DBLIBNAME "debug" LUALIB_API int (luaopen_debug) (lua_State *L); #define LUA_LOADLIBNAME "package" LUALIB_API int (luaopen_package) (lua_State *L); /* open all previous libraries */ LUALIB_API void (luaL_openlibs) (lua_State *L); #ifndef lua_assert #define lua_assert(x) ((void)0) #endif #endif bam-0.4.0/src/lua/lua.h0000644000175000017500000002665011430042030012652 0ustar kmakma/* ** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ ** Lua - An Extensible Extension Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file */ #ifndef lua_h #define lua_h #include #include #include "luaconf.h" #define LUA_VERSION "Lua 5.1" #define LUA_RELEASE "Lua 5.1.4" #define LUA_VERSION_NUM 501 #define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" /* mark for precompiled code (`Lua') */ #define LUA_SIGNATURE "\033Lua" /* option for multiple returns in `lua_pcall' and `lua_call' */ #define LUA_MULTRET (-1) /* ** pseudo-indices */ #define LUA_REGISTRYINDEX (-10000) #define LUA_ENVIRONINDEX (-10001) #define LUA_GLOBALSINDEX (-10002) #define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) /* thread status; 0 is OK */ #define LUA_YIELD 1 #define LUA_ERRRUN 2 #define LUA_ERRSYNTAX 3 #define LUA_ERRMEM 4 #define LUA_ERRERR 5 typedef struct lua_State lua_State; typedef int (*lua_CFunction) (lua_State *L); /* ** functions that read/write blocks when loading/dumping Lua chunks */ typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); /* ** prototype for memory-allocation functions */ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); /* ** basic types */ #define LUA_TNONE (-1) #define LUA_TNIL 0 #define LUA_TBOOLEAN 1 #define LUA_TLIGHTUSERDATA 2 #define LUA_TNUMBER 3 #define LUA_TSTRING 4 #define LUA_TTABLE 5 #define LUA_TFUNCTION 6 #define LUA_TUSERDATA 7 #define LUA_TTHREAD 8 /* minimum Lua stack available to a C function */ #define LUA_MINSTACK 20 /* ** generic extra include file */ #if defined(LUA_USER_H) #include LUA_USER_H #endif /* type of numbers in Lua */ typedef LUA_NUMBER lua_Number; /* type for integer functions */ typedef LUA_INTEGER lua_Integer; /* ** state manipulation */ LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); LUA_API void (lua_close) (lua_State *L); LUA_API lua_State *(lua_newthread) (lua_State *L); LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); /* ** basic stack manipulation */ LUA_API int (lua_gettop) (lua_State *L); LUA_API void (lua_settop) (lua_State *L, int idx); LUA_API void (lua_pushvalue) (lua_State *L, int idx); LUA_API void (lua_remove) (lua_State *L, int idx); LUA_API void (lua_insert) (lua_State *L, int idx); LUA_API void (lua_replace) (lua_State *L, int idx); LUA_API int (lua_checkstack) (lua_State *L, int sz); LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); /* ** access functions (stack -> C) */ LUA_API int (lua_isnumber) (lua_State *L, int idx); LUA_API int (lua_isstring) (lua_State *L, int idx); LUA_API int (lua_iscfunction) (lua_State *L, int idx); LUA_API int (lua_isuserdata) (lua_State *L, int idx); LUA_API int (lua_type) (lua_State *L, int idx); LUA_API const char *(lua_typename) (lua_State *L, int tp); LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); LUA_API int (lua_toboolean) (lua_State *L, int idx); LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); LUA_API size_t (lua_objlen) (lua_State *L, int idx); LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); LUA_API void *(lua_touserdata) (lua_State *L, int idx); LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); LUA_API const void *(lua_topointer) (lua_State *L, int idx); /* ** push functions (C -> stack) */ LUA_API void (lua_pushnil) (lua_State *L); LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); LUA_API void (lua_pushstring) (lua_State *L, const char *s); LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, va_list argp); LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); LUA_API void (lua_pushboolean) (lua_State *L, int b); LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); LUA_API int (lua_pushthread) (lua_State *L); /* ** get functions (Lua -> stack) */ LUA_API void (lua_gettable) (lua_State *L, int idx); LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); LUA_API void (lua_rawget) (lua_State *L, int idx); LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); LUA_API int (lua_getmetatable) (lua_State *L, int objindex); LUA_API void (lua_getfenv) (lua_State *L, int idx); /* ** set functions (stack -> Lua) */ LUA_API void (lua_settable) (lua_State *L, int idx); LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); LUA_API void (lua_rawset) (lua_State *L, int idx); LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); LUA_API int (lua_setmetatable) (lua_State *L, int objindex); LUA_API int (lua_setfenv) (lua_State *L, int idx); /* ** `load' and `call' functions (load and run Lua code) */ LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, const char *chunkname); LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); /* ** coroutine functions */ LUA_API int (lua_yield) (lua_State *L, int nresults); LUA_API int (lua_resume) (lua_State *L, int narg); LUA_API int (lua_status) (lua_State *L); /* ** garbage-collection function and options */ #define LUA_GCSTOP 0 #define LUA_GCRESTART 1 #define LUA_GCCOLLECT 2 #define LUA_GCCOUNT 3 #define LUA_GCCOUNTB 4 #define LUA_GCSTEP 5 #define LUA_GCSETPAUSE 6 #define LUA_GCSETSTEPMUL 7 LUA_API int (lua_gc) (lua_State *L, int what, int data); /* ** miscellaneous functions */ LUA_API int (lua_error) (lua_State *L); LUA_API int (lua_next) (lua_State *L, int idx); LUA_API void (lua_concat) (lua_State *L, int n); LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); /* ** =============================================================== ** some useful macros ** =============================================================== */ #define lua_pop(L,n) lua_settop(L, -(n)-1) #define lua_newtable(L) lua_createtable(L, 0, 0) #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) #define lua_strlen(L,i) lua_objlen(L, (i)) #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) #define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) #define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) #define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) #define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) #define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) #define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) #define lua_pushliteral(L, s) \ lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) #define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) #define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) #define lua_tostring(L,i) lua_tolstring(L, (i), NULL) /* ** compatibility macros and functions */ #define lua_open() luaL_newstate() #define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) #define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) #define lua_Chunkreader lua_Reader #define lua_Chunkwriter lua_Writer /* hack */ LUA_API void lua_setlevel (lua_State *from, lua_State *to); /* ** {====================================================================== ** Debug API ** ======================================================================= */ /* ** Event codes */ #define LUA_HOOKCALL 0 #define LUA_HOOKRET 1 #define LUA_HOOKLINE 2 #define LUA_HOOKCOUNT 3 #define LUA_HOOKTAILRET 4 /* ** Event masks */ #define LUA_MASKCALL (1 << LUA_HOOKCALL) #define LUA_MASKRET (1 << LUA_HOOKRET) #define LUA_MASKLINE (1 << LUA_HOOKLINE) #define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) typedef struct lua_Debug lua_Debug; /* activation record */ /* Functions to be called by the debuger in specific events */ typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); LUA_API lua_Hook lua_gethook (lua_State *L); LUA_API int lua_gethookmask (lua_State *L); LUA_API int lua_gethookcount (lua_State *L); struct lua_Debug { int event; const char *name; /* (n) */ const char *namewhat; /* (n) `global', `local', `field', `method' */ const char *what; /* (S) `Lua', `C', `main', `tail' */ const char *source; /* (S) */ int currentline; /* (l) */ int nups; /* (u) number of upvalues */ int linedefined; /* (S) */ int lastlinedefined; /* (S) */ char short_src[LUA_IDSIZE]; /* (S) */ /* private part */ int i_ci; /* active function */ }; /* }====================================================================== */ /****************************************************************************** * Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. * * 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. ******************************************************************************/ #endif bam-0.4.0/src/lua/luaconf.h0000644000175000017500000005346211430042030013521 0ustar kmakma/* ** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ ** Configuration file for Lua ** See Copyright Notice in lua.h */ #ifndef lconfig_h #define lconfig_h #include #include /* ** ================================================================== ** Search for "@@" to find all configurable definitions. ** =================================================================== */ /* @@ LUA_ANSI controls the use of non-ansi features. ** CHANGE it (define it) if you want Lua to avoid the use of any ** non-ansi feature or library. */ #if defined(__STRICT_ANSI__) #define LUA_ANSI #endif #if !defined(LUA_ANSI) && defined(_WIN32) #define LUA_WIN #endif #if defined(LUA_USE_LINUX) #define LUA_USE_POSIX #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ #define LUA_USE_READLINE /* needs some extra libraries */ #endif #if defined(LUA_USE_MACOSX) #define LUA_USE_POSIX #define LUA_DL_DYLD /* does not need extra library */ #endif /* @@ LUA_USE_POSIX includes all functionallity listed as X/Open System @* Interfaces Extension (XSI). ** CHANGE it (define it) if your system is XSI compatible. */ #if defined(LUA_USE_POSIX) #define LUA_USE_MKSTEMP #define LUA_USE_ISATTY #define LUA_USE_POPEN #define LUA_USE_ULONGJMP #endif /* @@ LUA_PATH and LUA_CPATH are the names of the environment variables that @* Lua check to set its paths. @@ LUA_INIT is the name of the environment variable that Lua @* checks for initialization code. ** CHANGE them if you want different names. */ #define LUA_PATH "LUA_PATH" #define LUA_CPATH "LUA_CPATH" #define LUA_INIT "LUA_INIT" /* @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for @* Lua libraries. @@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for @* C libraries. ** CHANGE them if your machine has a non-conventional directory ** hierarchy or if you want to install your libraries in ** non-conventional directories. */ #if defined(_WIN32) /* ** In Windows, any exclamation mark ('!') in the path is replaced by the ** path of the directory of the executable file of the current process. */ #define LUA_LDIR "!\\lua\\" #define LUA_CDIR "!\\" #define LUA_PATH_DEFAULT \ ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" #define LUA_CPATH_DEFAULT \ ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" #else #define LUA_ROOT "/usr/local/" #define LUA_LDIR LUA_ROOT "share/lua/5.1/" #define LUA_CDIR LUA_ROOT "lib/lua/5.1/" #define LUA_PATH_DEFAULT \ "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" #define LUA_CPATH_DEFAULT \ "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" #endif /* @@ LUA_DIRSEP is the directory separator (for submodules). ** CHANGE it if your machine does not use "/" as the directory separator ** and is not Windows. (On Windows Lua automatically uses "\".) */ #if defined(_WIN32) #define LUA_DIRSEP "\\" #else #define LUA_DIRSEP "/" #endif /* @@ LUA_PATHSEP is the character that separates templates in a path. @@ LUA_PATH_MARK is the string that marks the substitution points in a @* template. @@ LUA_EXECDIR in a Windows path is replaced by the executable's @* directory. @@ LUA_IGMARK is a mark to ignore all before it when bulding the @* luaopen_ function name. ** CHANGE them if for some reason your system cannot use those ** characters. (E.g., if one of those characters is a common character ** in file/directory names.) Probably you do not need to change them. */ #define LUA_PATHSEP ";" #define LUA_PATH_MARK "?" #define LUA_EXECDIR "!" #define LUA_IGMARK "-" /* @@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. ** CHANGE that if ptrdiff_t is not adequate on your machine. (On most ** machines, ptrdiff_t gives a good choice between int or long.) */ #define LUA_INTEGER ptrdiff_t /* @@ LUA_API is a mark for all core API functions. @@ LUALIB_API is a mark for all standard library functions. ** CHANGE them if you need to define those functions in some special way. ** For instance, if you want to create one Windows DLL with the core and ** the libraries, you may want to use the following definition (define ** LUA_BUILD_AS_DLL to get it). */ #if defined(LUA_BUILD_AS_DLL) #if defined(LUA_CORE) || defined(LUA_LIB) #define LUA_API __declspec(dllexport) #else #define LUA_API __declspec(dllimport) #endif #else #define LUA_API extern #endif /* more often than not the libs go together with the core */ #define LUALIB_API LUA_API /* @@ LUAI_FUNC is a mark for all extern functions that are not to be @* exported to outside modules. @@ LUAI_DATA is a mark for all extern (const) variables that are not to @* be exported to outside modules. ** CHANGE them if you need to mark them in some special way. Elf/gcc ** (versions 3.2 and later) mark them as "hidden" to optimize access ** when Lua is compiled as a shared library. */ #if defined(luaall_c) #define LUAI_FUNC static #define LUAI_DATA /* empty */ #elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ defined(__ELF__) #define LUAI_FUNC __attribute__((visibility("hidden"))) extern #define LUAI_DATA LUAI_FUNC #else #define LUAI_FUNC extern #define LUAI_DATA extern #endif /* @@ LUA_QL describes how error messages quote program elements. ** CHANGE it if you want a different appearance. */ #define LUA_QL(x) "'" x "'" #define LUA_QS LUA_QL("%s") /* @@ LUA_IDSIZE gives the maximum size for the description of the source @* of a function in debug information. ** CHANGE it if you want a different size. */ #define LUA_IDSIZE 60 /* ** {================================================================== ** Stand-alone configuration ** =================================================================== */ #if defined(lua_c) || defined(luaall_c) /* @@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that @* is, whether we're running lua interactively). ** CHANGE it if you have a better definition for non-POSIX/non-Windows ** systems. */ #if defined(LUA_USE_ISATTY) #include #define lua_stdin_is_tty() isatty(0) #elif defined(LUA_WIN) #include #include #define lua_stdin_is_tty() _isatty(_fileno(stdin)) #else #define lua_stdin_is_tty() 1 /* assume stdin is a tty */ #endif /* @@ LUA_PROMPT is the default prompt used by stand-alone Lua. @@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. ** CHANGE them if you want different prompts. (You can also change the ** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) */ #define LUA_PROMPT "> " #define LUA_PROMPT2 ">> " /* @@ LUA_PROGNAME is the default name for the stand-alone Lua program. ** CHANGE it if your stand-alone interpreter has a different name and ** your system is not able to detect that name automatically. */ #define LUA_PROGNAME "lua" /* @@ LUA_MAXINPUT is the maximum length for an input line in the @* stand-alone interpreter. ** CHANGE it if you need longer lines. */ #define LUA_MAXINPUT 512 /* @@ lua_readline defines how to show a prompt and then read a line from @* the standard input. @@ lua_saveline defines how to "save" a read line in a "history". @@ lua_freeline defines how to free a line read by lua_readline. ** CHANGE them if you want to improve this functionality (e.g., by using ** GNU readline and history facilities). */ #if defined(LUA_USE_READLINE) #include #include #include #define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) #define lua_saveline(L,idx) \ if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ add_history(lua_tostring(L, idx)); /* add it to history */ #define lua_freeline(L,b) ((void)L, free(b)) #else #define lua_readline(L,b,p) \ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ #define lua_saveline(L,idx) { (void)L; (void)idx; } #define lua_freeline(L,b) { (void)L; (void)b; } #endif #endif /* }================================================================== */ /* @@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles @* as a percentage. ** CHANGE it if you want the GC to run faster or slower (higher values ** mean larger pauses which mean slower collection.) You can also change ** this value dynamically. */ #define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ /* @@ LUAI_GCMUL defines the default speed of garbage collection relative to @* memory allocation as a percentage. ** CHANGE it if you want to change the granularity of the garbage ** collection. (Higher values mean coarser collections. 0 represents ** infinity, where each step performs a full collection.) You can also ** change this value dynamically. */ #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ /* @@ LUA_COMPAT_GETN controls compatibility with old getn behavior. ** CHANGE it (define it) if you want exact compatibility with the ** behavior of setn/getn in Lua 5.0. */ #undef LUA_COMPAT_GETN /* @@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. ** CHANGE it to undefined as soon as you do not need a global 'loadlib' ** function (the function is still available as 'package.loadlib'). */ #undef LUA_COMPAT_LOADLIB /* @@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. ** CHANGE it to undefined as soon as your programs use only '...' to ** access vararg parameters (instead of the old 'arg' table). */ #undef LUA_COMPAT_VARARG /* @@ LUA_COMPAT_MOD controls compatibility with old math.mod function. ** CHANGE it to undefined as soon as your programs use 'math.fmod' or ** the new '%' operator instead of 'math.mod'. */ /* #define LUA_COMPAT_MOD */ /* @@ LUA_COMPAT_LSTR controls compatibility with old long string nesting @* facility. ** CHANGE it to 2 if you want the old behaviour, or undefine it to turn ** off the advisory error when nesting [[...]]. */ /* #define LUA_COMPAT_LSTR 1 */ /* @@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. ** CHANGE it to undefined as soon as you rename 'string.gfind' to ** 'string.gmatch'. */ /* #define LUA_COMPAT_GFIND */ /* @@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' @* behavior. ** CHANGE it to undefined as soon as you replace to 'luaL_register' ** your uses of 'luaL_openlib' */ /* #define LUA_COMPAT_OPENLIB */ /* @@ luai_apicheck is the assert macro used by the Lua-C API. ** CHANGE luai_apicheck if you want Lua to perform some checks in the ** parameters it gets from API calls. This may slow down the interpreter ** a bit, but may be quite useful when debugging C code that interfaces ** with Lua. A useful redefinition is to use assert.h. */ #if defined(LUA_USE_APICHECK) #include #define luai_apicheck(L,o) { (void)L; assert(o); } #else #define luai_apicheck(L,o) { (void)L; } #endif /* @@ LUAI_BITSINT defines the number of bits in an int. ** CHANGE here if Lua cannot automatically detect the number of bits of ** your machine. Probably you do not need to change this. */ /* avoid overflows in comparison */ #if INT_MAX-20 < 32760 #define LUAI_BITSINT 16 #elif INT_MAX > 2147483640L /* int has at least 32 bits */ #define LUAI_BITSINT 32 #else #error "you must define LUA_BITSINT with number of bits in an integer" #endif /* @@ LUAI_UINT32 is an unsigned integer with at least 32 bits. @@ LUAI_INT32 is an signed integer with at least 32 bits. @@ LUAI_UMEM is an unsigned integer big enough to count the total @* memory used by Lua. @@ LUAI_MEM is a signed integer big enough to count the total memory @* used by Lua. ** CHANGE here if for some weird reason the default definitions are not ** good enough for your machine. (The definitions in the 'else' ** part always works, but may waste space on machines with 64-bit ** longs.) Probably you do not need to change this. */ #if LUAI_BITSINT >= 32 #define LUAI_UINT32 unsigned int #define LUAI_INT32 int #define LUAI_MAXINT32 INT_MAX #define LUAI_UMEM size_t #define LUAI_MEM ptrdiff_t #else /* 16-bit ints */ #define LUAI_UINT32 unsigned long #define LUAI_INT32 long #define LUAI_MAXINT32 LONG_MAX #define LUAI_UMEM unsigned long #define LUAI_MEM long #endif /* @@ LUAI_MAXCALLS limits the number of nested calls. ** CHANGE it if you need really deep recursive calls. This limit is ** arbitrary; its only purpose is to stop infinite recursion before ** exhausting memory. */ #define LUAI_MAXCALLS 20000 /* @@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function @* can use. ** CHANGE it if you need lots of (Lua) stack space for your C ** functions. This limit is arbitrary; its only purpose is to stop C ** functions to consume unlimited stack space. (must be smaller than ** -LUA_REGISTRYINDEX) */ #define LUAI_MAXCSTACK 8000 /* ** {================================================================== ** CHANGE (to smaller values) the following definitions if your system ** has a small C stack. (Or you may want to change them to larger ** values if your system has a large C stack and these limits are ** too rigid for you.) Some of these constants control the size of ** stack-allocated arrays used by the compiler or the interpreter, while ** others limit the maximum number of recursive calls that the compiler ** or the interpreter can perform. Values too large may cause a C stack ** overflow for some forms of deep constructs. ** =================================================================== */ /* @@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and @* syntactical nested non-terminals in a program. */ #define LUAI_MAXCCALLS 200 /* @@ LUAI_MAXVARS is the maximum number of local variables per function @* (must be smaller than 250). */ #define LUAI_MAXVARS 200 /* @@ LUAI_MAXUPVALUES is the maximum number of upvalues per function @* (must be smaller than 250). */ #define LUAI_MAXUPVALUES 60 /* @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. */ #define LUAL_BUFFERSIZE BUFSIZ /* }================================================================== */ /* ** {================================================================== @@ LUA_NUMBER is the type of numbers in Lua. ** CHANGE the following definitions only if you want to build Lua ** with a number type different from double. You may also need to ** change lua_number2int & lua_number2integer. ** =================================================================== */ #define LUA_NUMBER_DOUBLE #define LUA_NUMBER double /* @@ LUAI_UACNUMBER is the result of an 'usual argument conversion' @* over a number. */ #define LUAI_UACNUMBER double /* @@ LUA_NUMBER_SCAN is the format for reading numbers. @@ LUA_NUMBER_FMT is the format for writing numbers. @@ lua_number2str converts a number to a string. @@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. @@ lua_str2number converts a string to a number. */ #define LUA_NUMBER_SCAN "%lf" #define LUA_NUMBER_FMT "%.14g" #define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) #define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ #define lua_str2number(s,p) strtod((s), (p)) /* @@ The luai_num* macros define the primitive operations over numbers. */ #if defined(LUA_CORE) #include #define luai_numadd(a,b) ((a)+(b)) #define luai_numsub(a,b) ((a)-(b)) #define luai_nummul(a,b) ((a)*(b)) #define luai_numdiv(a,b) ((a)/(b)) #define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) #define luai_numpow(a,b) (pow(a,b)) #define luai_numunm(a) (-(a)) #define luai_numeq(a,b) ((a)==(b)) #define luai_numlt(a,b) ((a)<(b)) #define luai_numle(a,b) ((a)<=(b)) #define luai_numisnan(a) (!luai_numeq((a), (a))) #endif /* @@ lua_number2int is a macro to convert lua_Number to int. @@ lua_number2integer is a macro to convert lua_Number to lua_Integer. ** CHANGE them if you know a faster way to convert a lua_Number to ** int (with any rounding method and without throwing errors) in your ** system. In Pentium machines, a naive typecast from double to int ** in C is extremely slow, so any alternative is worth trying. */ /* On a Pentium, resort to a trick */ #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ (defined(__i386) || defined (_M_IX86) || defined(__i386__)) /* On a Microsoft compiler, use assembler */ #if defined(_MSC_VER) #define lua_number2int(i,d) __asm fld d __asm fistp i #define lua_number2integer(i,n) lua_number2int(i, n) /* the next trick should work on any Pentium, but sometimes clashes with a DirectX idiosyncrasy */ #else union luai_Cast { double l_d; long l_l; }; #define lua_number2int(i,d) \ { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } #define lua_number2integer(i,n) lua_number2int(i, n) #endif /* this option always works, but may be slow */ #else #define lua_number2int(i,d) ((i)=(int)(d)) #define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) #endif /* }================================================================== */ /* @@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. ** CHANGE it if your system requires alignments larger than double. (For ** instance, if your system supports long doubles and they must be ** aligned in 16-byte boundaries, then you should add long double in the ** union.) Probably you do not need to change this. */ #define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } /* @@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. ** CHANGE them if you prefer to use longjmp/setjmp even with C++ ** or if want/don't to use _longjmp/_setjmp instead of regular ** longjmp/setjmp. By default, Lua handles errors with exceptions when ** compiling as C++ code, with _longjmp/_setjmp when asked to use them, ** and with longjmp/setjmp otherwise. */ #if defined(__cplusplus) /* C++ exceptions */ #define LUAI_THROW(L,c) throw(c) #define LUAI_TRY(L,c,a) try { a } catch(...) \ { if ((c)->status == 0) (c)->status = -1; } #define luai_jmpbuf int /* dummy variable */ #elif defined(LUA_USE_ULONGJMP) /* in Unix, try _longjmp/_setjmp (more efficient) */ #define LUAI_THROW(L,c) _longjmp((c)->b, 1) #define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } #define luai_jmpbuf jmp_buf #else /* default handling with long jumps */ #define LUAI_THROW(L,c) longjmp((c)->b, 1) #define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } #define luai_jmpbuf jmp_buf #endif /* @@ LUA_MAXCAPTURES is the maximum number of captures that a pattern @* can do during pattern-matching. ** CHANGE it if you need more captures. This limit is arbitrary. */ #define LUA_MAXCAPTURES 32 /* @@ lua_tmpnam is the function that the OS library uses to create a @* temporary name. @@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. ** CHANGE them if you have an alternative to tmpnam (which is considered ** insecure) or if you want the original tmpnam anyway. By default, Lua ** uses tmpnam except when POSIX is available, where it uses mkstemp. */ #if defined(loslib_c) || defined(luaall_c) #if defined(LUA_USE_MKSTEMP) #include #define LUA_TMPNAMBUFSIZE 32 #define lua_tmpnam(b,e) { \ strcpy(b, "/tmp/lua_XXXXXX"); \ e = mkstemp(b); \ if (e != -1) close(e); \ e = (e == -1); } #else #define LUA_TMPNAMBUFSIZE L_tmpnam #define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } #endif #endif /* @@ lua_popen spawns a new process connected to the current one through @* the file streams. ** CHANGE it if you have a way to implement it in your system. */ #if defined(LUA_USE_POPEN) #define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) #define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) #elif defined(LUA_WIN) #define lua_popen(L,c,m) ((void)L, _popen(c,m)) #define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) #else #define lua_popen(L,c,m) ((void)((void)c, m), \ luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) #define lua_pclose(L,file) ((void)((void)L, file), 0) #endif /* @@ LUA_DL_* define which dynamic-library system Lua should use. ** CHANGE here if Lua has problems choosing the appropriate ** dynamic-library system for your platform (either Windows' DLL, Mac's ** dyld, or Unix's dlopen). If your system is some kind of Unix, there ** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for ** it. To use dlopen you also need to adapt the src/Makefile (probably ** adding -ldl to the linker options), so Lua does not select it ** automatically. (When you change the makefile to add -ldl, you must ** also add -DLUA_USE_DLOPEN.) ** If you do not want any kind of dynamic library, undefine all these ** options. ** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. */ #if defined(LUA_USE_DLOPEN) #define LUA_DL_DLOPEN #endif #if defined(LUA_WIN) #define LUA_DL_DLL #endif /* @@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State @* (the data goes just *before* the lua_State pointer). ** CHANGE (define) this if you really need that. This value must be ** a multiple of the maximum alignment required for your machine. */ #define LUAI_EXTRASPACE 0 /* @@ luai_userstate* allow user-specific actions on threads. ** CHANGE them if you defined LUAI_EXTRASPACE and need to do something ** extra when a thread is created/deleted/resumed/yielded. */ #define luai_userstateopen(L) ((void)L) #define luai_userstateclose(L) ((void)L) #define luai_userstatethread(L,L1) ((void)L) #define luai_userstatefree(L) ((void)L) #define luai_userstateresume(L,n) ((void)L) #define luai_userstateyield(L,n) ((void)L) /* @@ LUA_INTFRMLEN is the length modifier for integer conversions @* in 'string.format'. @@ LUA_INTFRM_T is the integer type correspoding to the previous length @* modifier. ** CHANGE them if your system supports long long or does not support long. */ #if defined(LUA_USELONGLONG) #define LUA_INTFRMLEN "ll" #define LUA_INTFRM_T long long #else #define LUA_INTFRMLEN "l" #define LUA_INTFRM_T long #endif /* =================================================================== */ /* ** Local configuration. You can use this space to add your redefinitions ** without modifying the main part of the file. */ #endif bam-0.4.0/src/lua/linit.c0000644000175000017500000000137511430042030013200 0ustar kmakma/* ** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ ** Initialization of libraries for lua.c ** See Copyright Notice in lua.h */ #define linit_c #define LUA_LIB #include "lua.h" #include "lualib.h" #include "lauxlib.h" static const luaL_Reg lualibs[] = { {"", luaopen_base}, {LUA_LOADLIBNAME, luaopen_package}, {LUA_TABLIBNAME, luaopen_table}, {LUA_IOLIBNAME, luaopen_io}, {LUA_OSLIBNAME, luaopen_os}, {LUA_STRLIBNAME, luaopen_string}, {LUA_MATHLIBNAME, luaopen_math}, {LUA_DBLIBNAME, luaopen_debug}, {NULL, NULL} }; LUALIB_API void luaL_openlibs (lua_State *L) { const luaL_Reg *lib = lualibs; for (; lib->func; lib++) { lua_pushcfunction(L, lib->func); lua_pushstring(L, lib->name); lua_call(L, 1, 0); } } bam-0.4.0/src/lua/ldo.c0000644000175000017500000003500311430042030012632 0ustar kmakma/* ** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ #include #include #include #define ldo_c #define LUA_CORE #include "lua.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" #include "lgc.h" #include "lmem.h" #include "lobject.h" #include "lopcodes.h" #include "lparser.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" #include "lundump.h" #include "lvm.h" #include "lzio.h" /* ** {====================================================== ** Error-recovery functions ** ======================================================= */ /* chain list of long jump buffers */ struct lua_longjmp { struct lua_longjmp *previous; luai_jmpbuf b; volatile int status; /* error code */ }; void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { switch (errcode) { case LUA_ERRMEM: { setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); break; } case LUA_ERRERR: { setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); break; } case LUA_ERRSYNTAX: case LUA_ERRRUN: { setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ break; } } L->top = oldtop + 1; } static void restore_stack_limit (lua_State *L) { lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ int inuse = cast_int(L->ci - L->base_ci); if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ luaD_reallocCI(L, LUAI_MAXCALLS); } } static void resetstack (lua_State *L, int status) { L->ci = L->base_ci; L->base = L->ci->base; luaF_close(L, L->base); /* close eventual pending closures */ luaD_seterrorobj(L, status, L->base); L->nCcalls = L->baseCcalls; L->allowhook = 1; restore_stack_limit(L); L->errfunc = 0; L->errorJmp = NULL; } void luaD_throw (lua_State *L, int errcode) { if (L->errorJmp) { L->errorJmp->status = errcode; LUAI_THROW(L, L->errorJmp); } else { L->status = cast_byte(errcode); if (G(L)->panic) { resetstack(L, errcode); lua_unlock(L); G(L)->panic(L); } exit(EXIT_FAILURE); } } int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { struct lua_longjmp lj; lj.status = 0; lj.previous = L->errorJmp; /* chain new error handler */ L->errorJmp = &lj; LUAI_TRY(L, &lj, (*f)(L, ud); ); L->errorJmp = lj.previous; /* restore old error handler */ return lj.status; } /* }====================================================== */ static void correctstack (lua_State *L, TValue *oldstack) { CallInfo *ci; GCObject *up; L->top = (L->top - oldstack) + L->stack; for (up = L->openupval; up != NULL; up = up->gch.next) gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; for (ci = L->base_ci; ci <= L->ci; ci++) { ci->top = (ci->top - oldstack) + L->stack; ci->base = (ci->base - oldstack) + L->stack; ci->func = (ci->func - oldstack) + L->stack; } L->base = (L->base - oldstack) + L->stack; } void luaD_reallocstack (lua_State *L, int newsize) { TValue *oldstack = L->stack; int realsize = newsize + 1 + EXTRA_STACK; lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); L->stacksize = realsize; L->stack_last = L->stack+newsize; correctstack(L, oldstack); } void luaD_reallocCI (lua_State *L, int newsize) { CallInfo *oldci = L->base_ci; luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); L->size_ci = newsize; L->ci = (L->ci - oldci) + L->base_ci; L->end_ci = L->base_ci + L->size_ci - 1; } void luaD_growstack (lua_State *L, int n) { if (n <= L->stacksize) /* double size is enough? */ luaD_reallocstack(L, 2*L->stacksize); else luaD_reallocstack(L, L->stacksize + n); } static CallInfo *growCI (lua_State *L) { if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ luaD_throw(L, LUA_ERRERR); else { luaD_reallocCI(L, 2*L->size_ci); if (L->size_ci > LUAI_MAXCALLS) luaG_runerror(L, "stack overflow"); } return ++L->ci; } void luaD_callhook (lua_State *L, int event, int line) { lua_Hook hook = L->hook; if (hook && L->allowhook) { ptrdiff_t top = savestack(L, L->top); ptrdiff_t ci_top = savestack(L, L->ci->top); lua_Debug ar; ar.event = event; ar.currentline = line; if (event == LUA_HOOKTAILRET) ar.i_ci = 0; /* tail call; no debug information about it */ else ar.i_ci = cast_int(L->ci - L->base_ci); luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ L->ci->top = L->top + LUA_MINSTACK; lua_assert(L->ci->top <= L->stack_last); L->allowhook = 0; /* cannot call hooks inside a hook */ lua_unlock(L); (*hook)(L, &ar); lua_lock(L); lua_assert(!L->allowhook); L->allowhook = 1; L->ci->top = restorestack(L, ci_top); L->top = restorestack(L, top); } } static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { int i; int nfixargs = p->numparams; Table *htab = NULL; StkId base, fixed; for (; actual < nfixargs; ++actual) setnilvalue(L->top++); #if defined(LUA_COMPAT_VARARG) if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ int nvar = actual - nfixargs; /* number of extra arguments */ lua_assert(p->is_vararg & VARARG_HASARG); luaC_checkGC(L); htab = luaH_new(L, nvar, 1); /* create `arg' table */ for (i=0; itop - nvar + i); /* store counter in field `n' */ setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); } #endif /* move fixed parameters to final position */ fixed = L->top - actual; /* first fixed argument */ base = L->top; /* final position of first argument */ for (i=0; itop++, fixed+i); setnilvalue(fixed+i); } /* add `arg' parameter */ if (htab) { sethvalue(L, L->top++, htab); lua_assert(iswhite(obj2gco(htab))); } return base; } static StkId tryfuncTM (lua_State *L, StkId func) { const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); StkId p; ptrdiff_t funcr = savestack(L, func); if (!ttisfunction(tm)) luaG_typeerror(L, func, "call"); /* Open a hole inside the stack at `func' */ for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); incr_top(L); func = restorestack(L, funcr); /* previous call may change stack */ setobj2s(L, func, tm); /* tag method is the new function to be called */ return func; } #define inc_ci(L) \ ((L->ci == L->end_ci) ? growCI(L) : \ (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) int luaD_precall (lua_State *L, StkId func, int nresults) { LClosure *cl; ptrdiff_t funcr; if (!ttisfunction(func)) /* `func' is not a function? */ func = tryfuncTM(L, func); /* check the `function' tag method */ funcr = savestack(L, func); cl = &clvalue(func)->l; L->ci->savedpc = L->savedpc; if (!cl->isC) { /* Lua function? prepare its call */ CallInfo *ci; StkId st, base; Proto *p = cl->p; luaD_checkstack(L, p->maxstacksize); func = restorestack(L, funcr); if (!p->is_vararg) { /* no varargs? */ base = func + 1; if (L->top > base + p->numparams) L->top = base + p->numparams; } else { /* vararg function */ int nargs = cast_int(L->top - func) - 1; base = adjust_varargs(L, p, nargs); func = restorestack(L, funcr); /* previous call may change the stack */ } ci = inc_ci(L); /* now `enter' new function */ ci->func = func; L->base = ci->base = base; ci->top = L->base + p->maxstacksize; lua_assert(ci->top <= L->stack_last); L->savedpc = p->code; /* starting point */ ci->tailcalls = 0; ci->nresults = nresults; for (st = L->top; st < ci->top; st++) setnilvalue(st); L->top = ci->top; if (L->hookmask & LUA_MASKCALL) { L->savedpc++; /* hooks assume 'pc' is already incremented */ luaD_callhook(L, LUA_HOOKCALL, -1); L->savedpc--; /* correct 'pc' */ } return PCRLUA; } else { /* if is a C function, call it */ CallInfo *ci; int n; luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ ci = inc_ci(L); /* now `enter' new function */ ci->func = restorestack(L, funcr); L->base = ci->base = ci->func + 1; ci->top = L->top + LUA_MINSTACK; lua_assert(ci->top <= L->stack_last); ci->nresults = nresults; if (L->hookmask & LUA_MASKCALL) luaD_callhook(L, LUA_HOOKCALL, -1); lua_unlock(L); n = (*curr_func(L)->c.f)(L); /* do the actual call */ lua_lock(L); if (n < 0) /* yielding? */ return PCRYIELD; else { luaD_poscall(L, L->top - n); return PCRC; } } } static StkId callrethooks (lua_State *L, StkId firstResult) { ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ luaD_callhook(L, LUA_HOOKRET, -1); if (f_isLua(L->ci)) { /* Lua function? */ while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ luaD_callhook(L, LUA_HOOKTAILRET, -1); } return restorestack(L, fr); } int luaD_poscall (lua_State *L, StkId firstResult) { StkId res; int wanted, i; CallInfo *ci; if (L->hookmask & LUA_MASKRET) firstResult = callrethooks(L, firstResult); ci = L->ci--; res = ci->func; /* res == final position of 1st result */ wanted = ci->nresults; L->base = (ci - 1)->base; /* restore base */ L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ /* move results to correct place */ for (i = wanted; i != 0 && firstResult < L->top; i--) setobjs2s(L, res++, firstResult++); while (i-- > 0) setnilvalue(res++); L->top = res; return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ } /* ** Call a function (C or Lua). The function to be called is at *func. ** The arguments are on the stack, right after the function. ** When returns, all the results are on the stack, starting at the original ** function position. */ void luaD_call (lua_State *L, StkId func, int nResults) { if (++L->nCcalls >= LUAI_MAXCCALLS) { if (L->nCcalls == LUAI_MAXCCALLS) luaG_runerror(L, "C stack overflow"); else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ } if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ luaV_execute(L, 1); /* call it */ L->nCcalls--; luaC_checkGC(L); } static void resume (lua_State *L, void *ud) { StkId firstArg = cast(StkId, ud); CallInfo *ci = L->ci; if (L->status == 0) { /* start coroutine? */ lua_assert(ci == L->base_ci && firstArg > L->base); if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) return; } else { /* resuming from previous yield */ lua_assert(L->status == LUA_YIELD); L->status = 0; if (!f_isLua(ci)) { /* `common' yield? */ /* finish interrupted execution of `OP_CALL' */ lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); if (luaD_poscall(L, firstArg)) /* complete it... */ L->top = L->ci->top; /* and correct top if not multiple results */ } else /* yielded inside a hook: just continue its execution */ L->base = L->ci->base; } luaV_execute(L, cast_int(L->ci - L->base_ci)); } static int resume_error (lua_State *L, const char *msg) { L->top = L->ci->base; setsvalue2s(L, L->top, luaS_new(L, msg)); incr_top(L); lua_unlock(L); return LUA_ERRRUN; } LUA_API int lua_resume (lua_State *L, int nargs) { int status; lua_lock(L); if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) return resume_error(L, "cannot resume non-suspended coroutine"); if (L->nCcalls >= LUAI_MAXCCALLS) return resume_error(L, "C stack overflow"); luai_userstateresume(L, nargs); lua_assert(L->errfunc == 0); L->baseCcalls = ++L->nCcalls; status = luaD_rawrunprotected(L, resume, L->top - nargs); if (status != 0) { /* error? */ L->status = cast_byte(status); /* mark thread as `dead' */ luaD_seterrorobj(L, status, L->top); L->ci->top = L->top; } else { lua_assert(L->nCcalls == L->baseCcalls); status = L->status; } --L->nCcalls; lua_unlock(L); return status; } LUA_API int lua_yield (lua_State *L, int nresults) { luai_userstateyield(L, nresults); lua_lock(L); if (L->nCcalls > L->baseCcalls) luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); L->base = L->top - nresults; /* protect stack slots below */ L->status = LUA_YIELD; lua_unlock(L); return -1; } int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t old_top, ptrdiff_t ef) { int status; unsigned short oldnCcalls = L->nCcalls; ptrdiff_t old_ci = saveci(L, L->ci); lu_byte old_allowhooks = L->allowhook; ptrdiff_t old_errfunc = L->errfunc; L->errfunc = ef; status = luaD_rawrunprotected(L, func, u); if (status != 0) { /* an error occurred? */ StkId oldtop = restorestack(L, old_top); luaF_close(L, oldtop); /* close eventual pending closures */ luaD_seterrorobj(L, status, oldtop); L->nCcalls = oldnCcalls; L->ci = restoreci(L, old_ci); L->base = L->ci->base; L->savedpc = L->ci->savedpc; L->allowhook = old_allowhooks; restore_stack_limit(L); } L->errfunc = old_errfunc; return status; } /* ** Execute a protected parser. */ struct SParser { /* data to `f_parser' */ ZIO *z; Mbuffer buff; /* buffer to be used by the scanner */ const char *name; }; static void f_parser (lua_State *L, void *ud) { int i; Proto *tf; Closure *cl; struct SParser *p = cast(struct SParser *, ud); int c = luaZ_lookahead(p->z); luaC_checkGC(L); tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, &p->buff, p->name); cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); cl->l.p = tf; for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ cl->l.upvals[i] = luaF_newupval(L); setclvalue(L, L->top, cl); incr_top(L); } int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { struct SParser p; int status; p.z = z; p.name = name; luaZ_initbuffer(L, &p.buff); status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); luaZ_freebuffer(L, &p.buff); return status; } bam-0.4.0/src/lua/ldblib.c0000644000175000017500000002352511430042030013312 0ustar kmakma/* ** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ #include #include #include #define ldblib_c #define LUA_LIB #include "lua.h" #include "lauxlib.h" #include "lualib.h" static int db_getregistry (lua_State *L) { lua_pushvalue(L, LUA_REGISTRYINDEX); return 1; } static int db_getmetatable (lua_State *L) { luaL_checkany(L, 1); if (!lua_getmetatable(L, 1)) { lua_pushnil(L); /* no metatable */ } return 1; } static int db_setmetatable (lua_State *L) { int t = lua_type(L, 2); luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table expected"); lua_settop(L, 2); lua_pushboolean(L, lua_setmetatable(L, 1)); return 1; } static int db_getfenv (lua_State *L) { lua_getfenv(L, 1); return 1; } static int db_setfenv (lua_State *L) { luaL_checktype(L, 2, LUA_TTABLE); lua_settop(L, 2); if (lua_setfenv(L, 1) == 0) luaL_error(L, LUA_QL("setfenv") " cannot change environment of given object"); return 1; } static void settabss (lua_State *L, const char *i, const char *v) { lua_pushstring(L, v); lua_setfield(L, -2, i); } static void settabsi (lua_State *L, const char *i, int v) { lua_pushinteger(L, v); lua_setfield(L, -2, i); } static lua_State *getthread (lua_State *L, int *arg) { if (lua_isthread(L, 1)) { *arg = 1; return lua_tothread(L, 1); } else { *arg = 0; return L; } } static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { if (L == L1) { lua_pushvalue(L, -2); lua_remove(L, -3); } else lua_xmove(L1, L, 1); lua_setfield(L, -2, fname); } static int db_getinfo (lua_State *L) { lua_Debug ar; int arg; lua_State *L1 = getthread(L, &arg); const char *options = luaL_optstring(L, arg+2, "flnSu"); if (lua_isnumber(L, arg+1)) { if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { lua_pushnil(L); /* level out of range */ return 1; } } else if (lua_isfunction(L, arg+1)) { lua_pushfstring(L, ">%s", options); options = lua_tostring(L, -1); lua_pushvalue(L, arg+1); lua_xmove(L, L1, 1); } else return luaL_argerror(L, arg+1, "function or level expected"); if (!lua_getinfo(L1, options, &ar)) return luaL_argerror(L, arg+2, "invalid option"); lua_createtable(L, 0, 2); if (strchr(options, 'S')) { settabss(L, "source", ar.source); settabss(L, "short_src", ar.short_src); settabsi(L, "linedefined", ar.linedefined); settabsi(L, "lastlinedefined", ar.lastlinedefined); settabss(L, "what", ar.what); } if (strchr(options, 'l')) settabsi(L, "currentline", ar.currentline); if (strchr(options, 'u')) settabsi(L, "nups", ar.nups); if (strchr(options, 'n')) { settabss(L, "name", ar.name); settabss(L, "namewhat", ar.namewhat); } if (strchr(options, 'L')) treatstackoption(L, L1, "activelines"); if (strchr(options, 'f')) treatstackoption(L, L1, "func"); return 1; /* return table */ } static int db_getlocal (lua_State *L) { int arg; lua_State *L1 = getthread(L, &arg); lua_Debug ar; const char *name; if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ return luaL_argerror(L, arg+1, "level out of range"); name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); if (name) { lua_xmove(L1, L, 1); lua_pushstring(L, name); lua_pushvalue(L, -2); return 2; } else { lua_pushnil(L); return 1; } } static int db_setlocal (lua_State *L) { int arg; lua_State *L1 = getthread(L, &arg); lua_Debug ar; if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ return luaL_argerror(L, arg+1, "level out of range"); luaL_checkany(L, arg+3); lua_settop(L, arg+3); lua_xmove(L, L1, 1); lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); return 1; } static int auxupvalue (lua_State *L, int get) { const char *name; int n = luaL_checkint(L, 2); luaL_checktype(L, 1, LUA_TFUNCTION); if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); if (name == NULL) return 0; lua_pushstring(L, name); lua_insert(L, -(get+1)); return get + 1; } static int db_getupvalue (lua_State *L) { return auxupvalue(L, 1); } static int db_setupvalue (lua_State *L) { luaL_checkany(L, 3); return auxupvalue(L, 0); } static const char KEY_HOOK = 'h'; static void hookf (lua_State *L, lua_Debug *ar) { static const char *const hooknames[] = {"call", "return", "line", "count", "tail return"}; lua_pushlightuserdata(L, (void *)&KEY_HOOK); lua_rawget(L, LUA_REGISTRYINDEX); lua_pushlightuserdata(L, L); lua_rawget(L, -2); if (lua_isfunction(L, -1)) { lua_pushstring(L, hooknames[(int)ar->event]); if (ar->currentline >= 0) lua_pushinteger(L, ar->currentline); else lua_pushnil(L); lua_assert(lua_getinfo(L, "lS", ar)); lua_call(L, 2, 0); } } static int makemask (const char *smask, int count) { int mask = 0; if (strchr(smask, 'c')) mask |= LUA_MASKCALL; if (strchr(smask, 'r')) mask |= LUA_MASKRET; if (strchr(smask, 'l')) mask |= LUA_MASKLINE; if (count > 0) mask |= LUA_MASKCOUNT; return mask; } static char *unmakemask (int mask, char *smask) { int i = 0; if (mask & LUA_MASKCALL) smask[i++] = 'c'; if (mask & LUA_MASKRET) smask[i++] = 'r'; if (mask & LUA_MASKLINE) smask[i++] = 'l'; smask[i] = '\0'; return smask; } static void gethooktable (lua_State *L) { lua_pushlightuserdata(L, (void *)&KEY_HOOK); lua_rawget(L, LUA_REGISTRYINDEX); if (!lua_istable(L, -1)) { lua_pop(L, 1); lua_createtable(L, 0, 1); lua_pushlightuserdata(L, (void *)&KEY_HOOK); lua_pushvalue(L, -2); lua_rawset(L, LUA_REGISTRYINDEX); } } static int db_sethook (lua_State *L) { int arg, mask, count; lua_Hook func; lua_State *L1 = getthread(L, &arg); if (lua_isnoneornil(L, arg+1)) { lua_settop(L, arg+1); func = NULL; mask = 0; count = 0; /* turn off hooks */ } else { const char *smask = luaL_checkstring(L, arg+2); luaL_checktype(L, arg+1, LUA_TFUNCTION); count = luaL_optint(L, arg+3, 0); func = hookf; mask = makemask(smask, count); } gethooktable(L); lua_pushlightuserdata(L, L1); lua_pushvalue(L, arg+1); lua_rawset(L, -3); /* set new hook */ lua_pop(L, 1); /* remove hook table */ lua_sethook(L1, func, mask, count); /* set hooks */ return 0; } static int db_gethook (lua_State *L) { int arg; lua_State *L1 = getthread(L, &arg); char buff[5]; int mask = lua_gethookmask(L1); lua_Hook hook = lua_gethook(L1); if (hook != NULL && hook != hookf) /* external hook? */ lua_pushliteral(L, "external hook"); else { gethooktable(L); lua_pushlightuserdata(L, L1); lua_rawget(L, -2); /* get hook */ lua_remove(L, -2); /* remove hook table */ } lua_pushstring(L, unmakemask(mask, buff)); lua_pushinteger(L, lua_gethookcount(L1)); return 3; } static int db_debug (lua_State *L) { for (;;) { char buffer[250]; fputs("lua_debug> ", stderr); if (fgets(buffer, sizeof(buffer), stdin) == 0 || strcmp(buffer, "cont\n") == 0) return 0; if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || lua_pcall(L, 0, 0, 0)) { fputs(lua_tostring(L, -1), stderr); fputs("\n", stderr); } lua_settop(L, 0); /* remove eventual returns */ } } #define LEVELS1 12 /* size of the first part of the stack */ #define LEVELS2 10 /* size of the second part of the stack */ static int db_errorfb (lua_State *L) { int level; int firstpart = 1; /* still before eventual `...' */ int arg; lua_State *L1 = getthread(L, &arg); lua_Debug ar; if (lua_isnumber(L, arg+2)) { level = (int)lua_tointeger(L, arg+2); lua_pop(L, 1); } else level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ if (lua_gettop(L) == arg) lua_pushliteral(L, ""); else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ else lua_pushliteral(L, "\n"); lua_pushliteral(L, "stack traceback:"); while (lua_getstack(L1, level++, &ar)) { if (level > LEVELS1 && firstpart) { /* no more than `LEVELS2' more levels? */ if (!lua_getstack(L1, level+LEVELS2, &ar)) level--; /* keep going */ else { lua_pushliteral(L, "\n\t..."); /* too many levels */ while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ level++; } firstpart = 0; continue; } lua_pushliteral(L, "\n\t"); lua_getinfo(L1, "Snl", &ar); lua_pushfstring(L, "%s:", ar.short_src); if (ar.currentline > 0) lua_pushfstring(L, "%d:", ar.currentline); if (*ar.namewhat != '\0') /* is there a name? */ lua_pushfstring(L, " in function " LUA_QS, ar.name); else { if (*ar.what == 'm') /* main? */ lua_pushfstring(L, " in main chunk"); else if (*ar.what == 'C' || *ar.what == 't') lua_pushliteral(L, " ?"); /* C function or tail call */ else lua_pushfstring(L, " in function <%s:%d>", ar.short_src, ar.linedefined); } lua_concat(L, lua_gettop(L) - arg); } lua_concat(L, lua_gettop(L) - arg); return 1; } static const luaL_Reg dblib[] = { {"debug", db_debug}, {"getfenv", db_getfenv}, {"gethook", db_gethook}, {"getinfo", db_getinfo}, {"getlocal", db_getlocal}, {"getregistry", db_getregistry}, {"getmetatable", db_getmetatable}, {"getupvalue", db_getupvalue}, {"setfenv", db_setfenv}, {"sethook", db_sethook}, {"setlocal", db_setlocal}, {"setmetatable", db_setmetatable}, {"setupvalue", db_setupvalue}, {"traceback", db_errorfb}, {NULL, NULL} }; LUALIB_API int luaopen_debug (lua_State *L) { luaL_register(L, LUA_DBLIBNAME, dblib); return 1; } bam-0.4.0/src/lua/lundump.c0000644000175000017500000001102511430042030013536 0ustar kmakma/* ** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ #include #define lundump_c #define LUA_CORE #include "lua.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" #include "lmem.h" #include "lobject.h" #include "lstring.h" #include "lundump.h" #include "lzio.h" typedef struct { lua_State* L; ZIO* Z; Mbuffer* b; const char* name; } LoadState; #ifdef LUAC_TRUST_BINARIES #define IF(c,s) #define error(S,s) #else #define IF(c,s) if (c) error(S,s) static void error(LoadState* S, const char* why) { luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); luaD_throw(S->L,LUA_ERRSYNTAX); } #endif #define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) #define LoadByte(S) (lu_byte)LoadChar(S) #define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) #define LoadVector(S,b,n,size) LoadMem(S,b,n,size) static void LoadBlock(LoadState* S, void* b, size_t size) { size_t r=luaZ_read(S->Z,b,size); IF (r!=0, "unexpected end"); } static int LoadChar(LoadState* S) { char x; LoadVar(S,x); return x; } static int LoadInt(LoadState* S) { int x; LoadVar(S,x); IF (x<0, "bad integer"); return x; } static lua_Number LoadNumber(LoadState* S) { lua_Number x; LoadVar(S,x); return x; } static TString* LoadString(LoadState* S) { size_t size; LoadVar(S,size); if (size==0) return NULL; else { char* s=luaZ_openspace(S->L,S->b,size); LoadBlock(S,s,size); return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ } } static void LoadCode(LoadState* S, Proto* f) { int n=LoadInt(S); f->code=luaM_newvector(S->L,n,Instruction); f->sizecode=n; LoadVector(S,f->code,n,sizeof(Instruction)); } static Proto* LoadFunction(LoadState* S, TString* p); static void LoadConstants(LoadState* S, Proto* f) { int i,n; n=LoadInt(S); f->k=luaM_newvector(S->L,n,TValue); f->sizek=n; for (i=0; ik[i]); for (i=0; ik[i]; int t=LoadChar(S); switch (t) { case LUA_TNIL: setnilvalue(o); break; case LUA_TBOOLEAN: setbvalue(o,LoadChar(S)!=0); break; case LUA_TNUMBER: setnvalue(o,LoadNumber(S)); break; case LUA_TSTRING: setsvalue2n(S->L,o,LoadString(S)); break; default: error(S,"bad constant"); break; } } n=LoadInt(S); f->p=luaM_newvector(S->L,n,Proto*); f->sizep=n; for (i=0; ip[i]=NULL; for (i=0; ip[i]=LoadFunction(S,f->source); } static void LoadDebug(LoadState* S, Proto* f) { int i,n; n=LoadInt(S); f->lineinfo=luaM_newvector(S->L,n,int); f->sizelineinfo=n; LoadVector(S,f->lineinfo,n,sizeof(int)); n=LoadInt(S); f->locvars=luaM_newvector(S->L,n,LocVar); f->sizelocvars=n; for (i=0; ilocvars[i].varname=NULL; for (i=0; ilocvars[i].varname=LoadString(S); f->locvars[i].startpc=LoadInt(S); f->locvars[i].endpc=LoadInt(S); } n=LoadInt(S); f->upvalues=luaM_newvector(S->L,n,TString*); f->sizeupvalues=n; for (i=0; iupvalues[i]=NULL; for (i=0; iupvalues[i]=LoadString(S); } static Proto* LoadFunction(LoadState* S, TString* p) { Proto* f; if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); f=luaF_newproto(S->L); setptvalue2s(S->L,S->L->top,f); incr_top(S->L); f->source=LoadString(S); if (f->source==NULL) f->source=p; f->linedefined=LoadInt(S); f->lastlinedefined=LoadInt(S); f->nups=LoadByte(S); f->numparams=LoadByte(S); f->is_vararg=LoadByte(S); f->maxstacksize=LoadByte(S); LoadCode(S,f); LoadConstants(S,f); LoadDebug(S,f); IF (!luaG_checkcode(f), "bad code"); S->L->top--; S->L->nCcalls--; return f; } static void LoadHeader(LoadState* S) { char h[LUAC_HEADERSIZE]; char s[LUAC_HEADERSIZE]; luaU_header(h); LoadBlock(S,s,LUAC_HEADERSIZE); IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); } /* ** load precompiled chunk */ Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) { LoadState S; if (*name=='@' || *name=='=') S.name=name+1; else if (*name==LUA_SIGNATURE[0]) S.name="binary string"; else S.name=name; S.L=L; S.Z=Z; S.b=buff; LoadHeader(&S); return LoadFunction(&S,luaS_newliteral(L,"=?")); } /* * make header */ void luaU_header (char* h) { int x=1; memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); h+=sizeof(LUA_SIGNATURE)-1; *h++=(char)LUAC_VERSION; *h++=(char)LUAC_FORMAT; *h++=(char)*(char*)&x; /* endianness */ *h++=(char)sizeof(int); *h++=(char)sizeof(size_t); *h++=(char)sizeof(Instruction); *h++=(char)sizeof(lua_Number); *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ } bam-0.4.0/src/lua/lstring.c0000644000175000017500000000604611430042030013543 0ustar kmakma/* ** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ #include #define lstring_c #define LUA_CORE #include "lua.h" #include "lmem.h" #include "lobject.h" #include "lstate.h" #include "lstring.h" void luaS_resize (lua_State *L, int newsize) { GCObject **newhash; stringtable *tb; int i; if (G(L)->gcstate == GCSsweepstring) return; /* cannot resize during GC traverse */ newhash = luaM_newvector(L, newsize, GCObject *); tb = &G(L)->strt; for (i=0; isize; i++) { GCObject *p = tb->hash[i]; while (p) { /* for each node in the list */ GCObject *next = p->gch.next; /* save next */ unsigned int h = gco2ts(p)->hash; int h1 = lmod(h, newsize); /* new position */ lua_assert(cast_int(h%newsize) == lmod(h, newsize)); p->gch.next = newhash[h1]; /* chain it */ newhash[h1] = p; p = next; } } luaM_freearray(L, tb->hash, tb->size, TString *); tb->size = newsize; tb->hash = newhash; } static TString *newlstr (lua_State *L, const char *str, size_t l, unsigned int h) { TString *ts; stringtable *tb; if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) luaM_toobig(L); ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); ts->tsv.len = l; ts->tsv.hash = h; ts->tsv.marked = luaC_white(G(L)); ts->tsv.tt = LUA_TSTRING; ts->tsv.reserved = 0; memcpy(ts+1, str, l*sizeof(char)); ((char *)(ts+1))[l] = '\0'; /* ending 0 */ tb = &G(L)->strt; h = lmod(h, tb->size); ts->tsv.next = tb->hash[h]; /* chain new entry */ tb->hash[h] = obj2gco(ts); tb->nuse++; if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) luaS_resize(L, tb->size*2); /* too crowded */ return ts; } TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { GCObject *o; unsigned int h = cast(unsigned int, l); /* seed */ size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ size_t l1; for (l1=l; l1>=step; l1-=step) /* compute hash */ h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; o != NULL; o = o->gch.next) { TString *ts = rawgco2ts(o); if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { /* string may be dead */ if (isdead(G(L), o)) changewhite(o); return ts; } } return newlstr(L, str, l, h); /* not found */ } Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { Udata *u; if (s > MAX_SIZET - sizeof(Udata)) luaM_toobig(L); u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); u->uv.marked = luaC_white(G(L)); /* is not finalized */ u->uv.tt = LUA_TUSERDATA; u->uv.len = s; u->uv.metatable = NULL; u->uv.env = e; /* chain it on udata list (after main thread) */ u->uv.next = G(L)->mainthread->next; G(L)->mainthread->next = obj2gco(u); return u; } bam-0.4.0/src/lua/lfunc.h0000644000175000017500000000214511430042030013171 0ustar kmakma/* ** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ #ifndef lfunc_h #define lfunc_h #include "lobject.h" #define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ cast(int, sizeof(TValue)*((n)-1))) #define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ cast(int, sizeof(TValue *)*((n)-1))) LUAI_FUNC Proto *luaF_newproto (lua_State *L); LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); LUAI_FUNC UpVal *luaF_newupval (lua_State *L); LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); LUAI_FUNC void luaF_close (lua_State *L, StkId level); LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, int pc); #endif bam-0.4.0/src/lua/lstate.h0000644000175000017500000001162311430042030013357 0ustar kmakma/* ** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ #ifndef lstate_h #define lstate_h #include "lua.h" #include "lobject.h" #include "ltm.h" #include "lzio.h" struct lua_longjmp; /* defined in ldo.c */ /* table of globals */ #define gt(L) (&L->l_gt) /* registry */ #define registry(L) (&G(L)->l_registry) /* extra stack space to handle TM calls and some other extras */ #define EXTRA_STACK 5 #define BASIC_CI_SIZE 8 #define BASIC_STACK_SIZE (2*LUA_MINSTACK) typedef struct stringtable { GCObject **hash; lu_int32 nuse; /* number of elements */ int size; } stringtable; /* ** informations about a call */ typedef struct CallInfo { StkId base; /* base for this function */ StkId func; /* function index in the stack */ StkId top; /* top for this function */ const Instruction *savedpc; int nresults; /* expected number of results from this function */ int tailcalls; /* number of tail calls lost under this entry */ } CallInfo; #define curr_func(L) (clvalue(L->ci->func)) #define ci_func(ci) (clvalue((ci)->func)) #define f_isLua(ci) (!ci_func(ci)->c.isC) #define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) /* ** `global state', shared by all threads of this state */ typedef struct global_State { stringtable strt; /* hash table for strings */ lua_Alloc frealloc; /* function to reallocate memory */ void *ud; /* auxiliary data to `frealloc' */ lu_byte currentwhite; lu_byte gcstate; /* state of garbage collector */ int sweepstrgc; /* position of sweep in `strt' */ GCObject *rootgc; /* list of all collectable objects */ GCObject **sweepgc; /* position of sweep in `rootgc' */ GCObject *gray; /* list of gray objects */ GCObject *grayagain; /* list of objects to be traversed atomically */ GCObject *weak; /* list of weak tables (to be cleared) */ GCObject *tmudata; /* last element of list of userdata to be GC */ Mbuffer buff; /* temporary buffer for string concatentation */ lu_mem GCthreshold; lu_mem totalbytes; /* number of bytes currently allocated */ lu_mem estimate; /* an estimate of number of bytes actually in use */ lu_mem gcdept; /* how much GC is `behind schedule' */ int gcpause; /* size of pause between successive GCs */ int gcstepmul; /* GC `granularity' */ lua_CFunction panic; /* to be called in unprotected errors */ TValue l_registry; struct lua_State *mainthread; UpVal uvhead; /* head of double-linked list of all open upvalues */ struct Table *mt[NUM_TAGS]; /* metatables for basic types */ TString *tmname[TM_N]; /* array with tag-method names */ } global_State; /* ** `per thread' state */ struct lua_State { CommonHeader; lu_byte status; StkId top; /* first free slot in the stack */ StkId base; /* base of current function */ global_State *l_G; CallInfo *ci; /* call info for current function */ const Instruction *savedpc; /* `savedpc' of current function */ StkId stack_last; /* last free slot in the stack */ StkId stack; /* stack base */ CallInfo *end_ci; /* points after end of ci array*/ CallInfo *base_ci; /* array of CallInfo's */ int stacksize; int size_ci; /* size of array `base_ci' */ unsigned short nCcalls; /* number of nested C calls */ unsigned short baseCcalls; /* nested C calls when resuming coroutine */ lu_byte hookmask; lu_byte allowhook; int basehookcount; int hookcount; lua_Hook hook; TValue l_gt; /* table of globals */ TValue env; /* temporary place for environments */ GCObject *openupval; /* list of open upvalues in this stack */ GCObject *gclist; struct lua_longjmp *errorJmp; /* current error recover point */ ptrdiff_t errfunc; /* current error handling function (stack index) */ }; #define G(L) (L->l_G) /* ** Union of all collectable objects */ union GCObject { GCheader gch; union TString ts; union Udata u; union Closure cl; struct Table h; struct Proto p; struct UpVal uv; struct lua_State th; /* thread */ }; /* macros to convert a GCObject into a specific value */ #define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) #define gco2ts(o) (&rawgco2ts(o)->tsv) #define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) #define gco2u(o) (&rawgco2u(o)->uv) #define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) #define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) #define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) #define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) #define ngcotouv(o) \ check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) #define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) /* macro to convert any Lua object into a GCObject */ #define obj2gco(v) (cast(GCObject *, (v))) LUAI_FUNC lua_State *luaE_newthread (lua_State *L); LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); #endif bam-0.4.0/src/lua/llex.c0000644000175000017500000003027211430042030013023 0ustar kmakma/* ** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ #include #include #include #define llex_c #define LUA_CORE #include "lua.h" #include "ldo.h" #include "llex.h" #include "lobject.h" #include "lparser.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #include "lzio.h" #define next(ls) (ls->current = zgetc(ls->z)) #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') /* ORDER RESERVED */ const char *const luaX_tokens [] = { "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while", "..", "...", "==", ">=", "<=", "~=", "", "", "", "", NULL }; #define save_and_next(ls) (save(ls, ls->current), next(ls)) static void save (LexState *ls, int c) { Mbuffer *b = ls->buff; if (b->n + 1 > b->buffsize) { size_t newsize; if (b->buffsize >= MAX_SIZET/2) luaX_lexerror(ls, "lexical element too long", 0); newsize = b->buffsize * 2; luaZ_resizebuffer(ls->L, b, newsize); } b->buffer[b->n++] = cast(char, c); } void luaX_init (lua_State *L) { int i; for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ } } #define MAXSRC 80 const char *luaX_token2str (LexState *ls, int token) { if (token < FIRST_RESERVED) { lua_assert(token == cast(unsigned char, token)); return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : luaO_pushfstring(ls->L, "%c", token); } else return luaX_tokens[token-FIRST_RESERVED]; } static const char *txtToken (LexState *ls, int token) { switch (token) { case TK_NAME: case TK_STRING: case TK_NUMBER: save(ls, '\0'); return luaZ_buffer(ls->buff); default: return luaX_token2str(ls, token); } } void luaX_lexerror (LexState *ls, const char *msg, int token) { char buff[MAXSRC]; luaO_chunkid(buff, getstr(ls->source), MAXSRC); msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); if (token) luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); luaD_throw(ls->L, LUA_ERRSYNTAX); } void luaX_syntaxerror (LexState *ls, const char *msg) { luaX_lexerror(ls, msg, ls->t.token); } TString *luaX_newstring (LexState *ls, const char *str, size_t l) { lua_State *L = ls->L; TString *ts = luaS_newlstr(L, str, l); TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ if (ttisnil(o)) setbvalue(o, 1); /* make sure `str' will not be collected */ return ts; } static void inclinenumber (LexState *ls) { int old = ls->current; lua_assert(currIsNewline(ls)); next(ls); /* skip `\n' or `\r' */ if (currIsNewline(ls) && ls->current != old) next(ls); /* skip `\n\r' or `\r\n' */ if (++ls->linenumber >= MAX_INT) luaX_syntaxerror(ls, "chunk has too many lines"); } void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { ls->decpoint = '.'; ls->L = L; ls->lookahead.token = TK_EOS; /* no look-ahead token */ ls->z = z; ls->fs = NULL; ls->linenumber = 1; ls->lastline = 1; ls->source = source; luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ next(ls); /* read first char */ } /* ** ======================================================= ** LEXICAL ANALYZER ** ======================================================= */ static int check_next (LexState *ls, const char *set) { if (!strchr(set, ls->current)) return 0; save_and_next(ls); return 1; } static void buffreplace (LexState *ls, char from, char to) { size_t n = luaZ_bufflen(ls->buff); char *p = luaZ_buffer(ls->buff); while (n--) if (p[n] == from) p[n] = to; } static void trydecpoint (LexState *ls, SemInfo *seminfo) { /* format error: try to update decimal point separator */ struct lconv *cv = localeconv(); char old = ls->decpoint; ls->decpoint = (cv ? cv->decimal_point[0] : '.'); buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { /* format error with correct decimal point: no more options */ buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ luaX_lexerror(ls, "malformed number", TK_NUMBER); } } /* LUA_NUMBER */ static void read_numeral (LexState *ls, SemInfo *seminfo) { lua_assert(isdigit(ls->current)); do { save_and_next(ls); } while (isdigit(ls->current) || ls->current == '.'); if (check_next(ls, "Ee")) /* `E'? */ check_next(ls, "+-"); /* optional exponent sign */ while (isalnum(ls->current) || ls->current == '_') save_and_next(ls); save(ls, '\0'); buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ trydecpoint(ls, seminfo); /* try to update decimal point separator */ } static int skip_sep (LexState *ls) { int count = 0; int s = ls->current; lua_assert(s == '[' || s == ']'); save_and_next(ls); while (ls->current == '=') { save_and_next(ls); count++; } return (ls->current == s) ? count : (-count) - 1; } static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { int cont = 0; (void)(cont); /* avoid warnings when `cont' is not used */ save_and_next(ls); /* skip 2nd `[' */ if (currIsNewline(ls)) /* string starts with a newline? */ inclinenumber(ls); /* skip it */ for (;;) { switch (ls->current) { case EOZ: luaX_lexerror(ls, (seminfo) ? "unfinished long string" : "unfinished long comment", TK_EOS); break; /* to avoid warnings */ #if defined(LUA_COMPAT_LSTR) case '[': { if (skip_sep(ls) == sep) { save_and_next(ls); /* skip 2nd `[' */ cont++; #if LUA_COMPAT_LSTR == 1 if (sep == 0) luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); #endif } break; } #endif case ']': { if (skip_sep(ls) == sep) { save_and_next(ls); /* skip 2nd `]' */ #if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 cont--; if (sep == 0 && cont >= 0) break; #endif goto endloop; } break; } case '\n': case '\r': { save(ls, '\n'); inclinenumber(ls); if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ break; } default: { if (seminfo) save_and_next(ls); else next(ls); } } } endloop: if (seminfo) seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), luaZ_bufflen(ls->buff) - 2*(2 + sep)); } static void read_string (LexState *ls, int del, SemInfo *seminfo) { save_and_next(ls); while (ls->current != del) { switch (ls->current) { case EOZ: luaX_lexerror(ls, "unfinished string", TK_EOS); continue; /* to avoid warnings */ case '\n': case '\r': luaX_lexerror(ls, "unfinished string", TK_STRING); continue; /* to avoid warnings */ case '\\': { int c; next(ls); /* do not save the `\' */ switch (ls->current) { case 'a': c = '\a'; break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'v': c = '\v'; break; case '\n': /* go through */ case '\r': save(ls, '\n'); inclinenumber(ls); continue; case EOZ: continue; /* will raise an error next loop */ default: { if (!isdigit(ls->current)) save_and_next(ls); /* handles \\, \", \', and \? */ else { /* \xxx */ int i = 0; c = 0; do { c = 10*c + (ls->current-'0'); next(ls); } while (++i<3 && isdigit(ls->current)); if (c > UCHAR_MAX) luaX_lexerror(ls, "escape sequence too large", TK_STRING); save(ls, c); } continue; } } save(ls, c); next(ls); continue; } default: save_and_next(ls); } } save_and_next(ls); /* skip delimiter */ seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, luaZ_bufflen(ls->buff) - 2); } static int llex (LexState *ls, SemInfo *seminfo) { luaZ_resetbuffer(ls->buff); for (;;) { switch (ls->current) { case '\n': case '\r': { inclinenumber(ls); continue; } case '-': { next(ls); if (ls->current != '-') return '-'; /* else is a comment */ next(ls); if (ls->current == '[') { int sep = skip_sep(ls); luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ if (sep >= 0) { read_long_string(ls, NULL, sep); /* long comment */ luaZ_resetbuffer(ls->buff); continue; } } /* else short comment */ while (!currIsNewline(ls) && ls->current != EOZ) next(ls); continue; } case '[': { int sep = skip_sep(ls); if (sep >= 0) { read_long_string(ls, seminfo, sep); return TK_STRING; } else if (sep == -1) return '['; else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); } case '=': { next(ls); if (ls->current != '=') return '='; else { next(ls); return TK_EQ; } } case '<': { next(ls); if (ls->current != '=') return '<'; else { next(ls); return TK_LE; } } case '>': { next(ls); if (ls->current != '=') return '>'; else { next(ls); return TK_GE; } } case '~': { next(ls); if (ls->current != '=') return '~'; else { next(ls); return TK_NE; } } case '"': case '\'': { read_string(ls, ls->current, seminfo); return TK_STRING; } case '.': { save_and_next(ls); if (check_next(ls, ".")) { if (check_next(ls, ".")) return TK_DOTS; /* ... */ else return TK_CONCAT; /* .. */ } else if (!isdigit(ls->current)) return '.'; else { read_numeral(ls, seminfo); return TK_NUMBER; } } case EOZ: { return TK_EOS; } default: { if (isspace(ls->current)) { lua_assert(!currIsNewline(ls)); next(ls); continue; } else if (isdigit(ls->current)) { read_numeral(ls, seminfo); return TK_NUMBER; } else if (isalpha(ls->current) || ls->current == '_') { /* identifier or reserved word */ TString *ts; do { save_and_next(ls); } while (isalnum(ls->current) || ls->current == '_'); ts = luaX_newstring(ls, luaZ_buffer(ls->buff), luaZ_bufflen(ls->buff)); if (ts->tsv.reserved > 0) /* reserved word? */ return ts->tsv.reserved - 1 + FIRST_RESERVED; else { seminfo->ts = ts; return TK_NAME; } } else { int c = ls->current; next(ls); return c; /* single-char tokens (+ - / ...) */ } } } } } void luaX_next (LexState *ls) { ls->lastline = ls->linenumber; if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ ls->t = ls->lookahead; /* use this one */ ls->lookahead.token = TK_EOS; /* and discharge it */ } else ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ } void luaX_lookahead (LexState *ls) { lua_assert(ls->lookahead.token == TK_EOS); ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); } bam-0.4.0/src/lua/ldebug.c0000644000175000017500000004071011430042030013317 0ustar kmakma/* ** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ ** Debug Interface ** See Copyright Notice in lua.h */ #include #include #include #define ldebug_c #define LUA_CORE #include "lua.h" #include "lapi.h" #include "lcode.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" #include "lobject.h" #include "lopcodes.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" #include "lvm.h" static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); static int currentpc (lua_State *L, CallInfo *ci) { if (!isLua(ci)) return -1; /* function is not a Lua function? */ if (ci == L->ci) ci->savedpc = L->savedpc; return pcRel(ci->savedpc, ci_func(ci)->l.p); } static int currentline (lua_State *L, CallInfo *ci) { int pc = currentpc(L, ci); if (pc < 0) return -1; /* only active lua functions have current-line information */ else return getline(ci_func(ci)->l.p, pc); } /* ** this function can be called asynchronous (e.g. during a signal) */ LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { if (func == NULL || mask == 0) { /* turn off hooks? */ mask = 0; func = NULL; } L->hook = func; L->basehookcount = count; resethookcount(L); L->hookmask = cast_byte(mask); return 1; } LUA_API lua_Hook lua_gethook (lua_State *L) { return L->hook; } LUA_API int lua_gethookmask (lua_State *L) { return L->hookmask; } LUA_API int lua_gethookcount (lua_State *L) { return L->basehookcount; } LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { int status; CallInfo *ci; lua_lock(L); for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { level--; if (f_isLua(ci)) /* Lua function? */ level -= ci->tailcalls; /* skip lost tail calls */ } if (level == 0 && ci > L->base_ci) { /* level found? */ status = 1; ar->i_ci = cast_int(ci - L->base_ci); } else if (level < 0) { /* level is of a lost tail call? */ status = 1; ar->i_ci = 0; } else status = 0; /* no such level */ lua_unlock(L); return status; } static Proto *getluaproto (CallInfo *ci) { return (isLua(ci) ? ci_func(ci)->l.p : NULL); } static const char *findlocal (lua_State *L, CallInfo *ci, int n) { const char *name; Proto *fp = getluaproto(ci); if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) return name; /* is a local variable in a Lua function */ else { StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ return "(*temporary)"; else return NULL; } } LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { CallInfo *ci = L->base_ci + ar->i_ci; const char *name = findlocal(L, ci, n); lua_lock(L); if (name) luaA_pushobject(L, ci->base + (n - 1)); lua_unlock(L); return name; } LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { CallInfo *ci = L->base_ci + ar->i_ci; const char *name = findlocal(L, ci, n); lua_lock(L); if (name) setobjs2s(L, ci->base + (n - 1), L->top - 1); L->top--; /* pop value */ lua_unlock(L); return name; } static void funcinfo (lua_Debug *ar, Closure *cl) { if (cl->c.isC) { ar->source = "=[C]"; ar->linedefined = -1; ar->lastlinedefined = -1; ar->what = "C"; } else { ar->source = getstr(cl->l.p->source); ar->linedefined = cl->l.p->linedefined; ar->lastlinedefined = cl->l.p->lastlinedefined; ar->what = (ar->linedefined == 0) ? "main" : "Lua"; } luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); } static void info_tailcall (lua_Debug *ar) { ar->name = ar->namewhat = ""; ar->what = "tail"; ar->lastlinedefined = ar->linedefined = ar->currentline = -1; ar->source = "=(tail call)"; luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); ar->nups = 0; } static void collectvalidlines (lua_State *L, Closure *f) { if (f == NULL || f->c.isC) { setnilvalue(L->top); } else { Table *t = luaH_new(L, 0, 0); int *lineinfo = f->l.p->lineinfo; int i; for (i=0; il.p->sizelineinfo; i++) setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); sethvalue(L, L->top, t); } incr_top(L); } static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, Closure *f, CallInfo *ci) { int status = 1; if (f == NULL) { info_tailcall(ar); return status; } for (; *what; what++) { switch (*what) { case 'S': { funcinfo(ar, f); break; } case 'l': { ar->currentline = (ci) ? currentline(L, ci) : -1; break; } case 'u': { ar->nups = f->c.nupvalues; break; } case 'n': { ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; if (ar->namewhat == NULL) { ar->namewhat = ""; /* not found */ ar->name = NULL; } break; } case 'L': case 'f': /* handled by lua_getinfo */ break; default: status = 0; /* invalid option */ } } return status; } LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { int status; Closure *f = NULL; CallInfo *ci = NULL; lua_lock(L); if (*what == '>') { StkId func = L->top - 1; luai_apicheck(L, ttisfunction(func)); what++; /* skip the '>' */ f = clvalue(func); L->top--; /* pop function */ } else if (ar->i_ci != 0) { /* no tail call? */ ci = L->base_ci + ar->i_ci; lua_assert(ttisfunction(ci->func)); f = clvalue(ci->func); } status = auxgetinfo(L, what, ar, f, ci); if (strchr(what, 'f')) { if (f == NULL) setnilvalue(L->top); else setclvalue(L, L->top, f); incr_top(L); } if (strchr(what, 'L')) collectvalidlines(L, f); lua_unlock(L); return status; } /* ** {====================================================== ** Symbolic Execution and code checker ** ======================================================= */ #define check(x) if (!(x)) return 0; #define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) #define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) static int precheck (const Proto *pt) { check(pt->maxstacksize <= MAXSTACK); check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); check(!(pt->is_vararg & VARARG_NEEDSARG) || (pt->is_vararg & VARARG_HASARG)); check(pt->sizeupvalues <= pt->nups); check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); return 1; } #define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) int luaG_checkopenop (Instruction i) { switch (GET_OPCODE(i)) { case OP_CALL: case OP_TAILCALL: case OP_RETURN: case OP_SETLIST: { check(GETARG_B(i) == 0); return 1; } default: return 0; /* invalid instruction after an open call */ } } static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { switch (mode) { case OpArgN: check(r == 0); break; case OpArgU: break; case OpArgR: checkreg(pt, r); break; case OpArgK: check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); break; } return 1; } static Instruction symbexec (const Proto *pt, int lastpc, int reg) { int pc; int last; /* stores position of last instruction that changed `reg' */ last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ check(precheck(pt)); for (pc = 0; pc < lastpc; pc++) { Instruction i = pt->code[pc]; OpCode op = GET_OPCODE(i); int a = GETARG_A(i); int b = 0; int c = 0; check(op < NUM_OPCODES); checkreg(pt, a); switch (getOpMode(op)) { case iABC: { b = GETARG_B(i); c = GETARG_C(i); check(checkArgMode(pt, b, getBMode(op))); check(checkArgMode(pt, c, getCMode(op))); break; } case iABx: { b = GETARG_Bx(i); if (getBMode(op) == OpArgK) check(b < pt->sizek); break; } case iAsBx: { b = GETARG_sBx(i); if (getBMode(op) == OpArgR) { int dest = pc+1+b; check(0 <= dest && dest < pt->sizecode); if (dest > 0) { int j; /* check that it does not jump to a setlist count; this is tricky, because the count from a previous setlist may have the same value of an invalid setlist; so, we must go all the way back to the first of them (if any) */ for (j = 0; j < dest; j++) { Instruction d = pt->code[dest-1-j]; if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; } /* if 'j' is even, previous value is not a setlist (even if it looks like one) */ check((j&1) == 0); } } break; } } if (testAMode(op)) { if (a == reg) last = pc; /* change register `a' */ } if (testTMode(op)) { check(pc+2 < pt->sizecode); /* check skip */ check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); } switch (op) { case OP_LOADBOOL: { if (c == 1) { /* does it jump? */ check(pc+2 < pt->sizecode); /* check its jump */ check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || GETARG_C(pt->code[pc+1]) != 0); } break; } case OP_LOADNIL: { if (a <= reg && reg <= b) last = pc; /* set registers from `a' to `b' */ break; } case OP_GETUPVAL: case OP_SETUPVAL: { check(b < pt->nups); break; } case OP_GETGLOBAL: case OP_SETGLOBAL: { check(ttisstring(&pt->k[b])); break; } case OP_SELF: { checkreg(pt, a+1); if (reg == a+1) last = pc; break; } case OP_CONCAT: { check(b < c); /* at least two operands */ break; } case OP_TFORLOOP: { check(c >= 1); /* at least one result (control variable) */ checkreg(pt, a+2+c); /* space for results */ if (reg >= a+2) last = pc; /* affect all regs above its base */ break; } case OP_FORLOOP: case OP_FORPREP: checkreg(pt, a+3); /* go through */ case OP_JMP: { int dest = pc+1+b; /* not full check and jump is forward and do not skip `lastpc'? */ if (reg != NO_REG && pc < dest && dest <= lastpc) pc += b; /* do the jump */ break; } case OP_CALL: case OP_TAILCALL: { if (b != 0) { checkreg(pt, a+b-1); } c--; /* c = num. returns */ if (c == LUA_MULTRET) { check(checkopenop(pt, pc)); } else if (c != 0) checkreg(pt, a+c-1); if (reg >= a) last = pc; /* affect all registers above base */ break; } case OP_RETURN: { b--; /* b = num. returns */ if (b > 0) checkreg(pt, a+b-1); break; } case OP_SETLIST: { if (b > 0) checkreg(pt, a + b); if (c == 0) { pc++; check(pc < pt->sizecode - 1); } break; } case OP_CLOSURE: { int nup, j; check(b < pt->sizep); nup = pt->p[b]->nups; check(pc + nup < pt->sizecode); for (j = 1; j <= nup; j++) { OpCode op1 = GET_OPCODE(pt->code[pc + j]); check(op1 == OP_GETUPVAL || op1 == OP_MOVE); } if (reg != NO_REG) /* tracing? */ pc += nup; /* do not 'execute' these pseudo-instructions */ break; } case OP_VARARG: { check((pt->is_vararg & VARARG_ISVARARG) && !(pt->is_vararg & VARARG_NEEDSARG)); b--; if (b == LUA_MULTRET) check(checkopenop(pt, pc)); checkreg(pt, a+b-1); break; } default: break; } } return pt->code[last]; } #undef check #undef checkjump #undef checkreg /* }====================================================== */ int luaG_checkcode (const Proto *pt) { return (symbexec(pt, pt->sizecode, NO_REG) != 0); } static const char *kname (Proto *p, int c) { if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) return svalue(&p->k[INDEXK(c)]); else return "?"; } static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, const char **name) { if (isLua(ci)) { /* a Lua function? */ Proto *p = ci_func(ci)->l.p; int pc = currentpc(L, ci); Instruction i; *name = luaF_getlocalname(p, stackpos+1, pc); if (*name) /* is a local? */ return "local"; i = symbexec(p, pc, stackpos); /* try symbolic execution */ lua_assert(pc != -1); switch (GET_OPCODE(i)) { case OP_GETGLOBAL: { int g = GETARG_Bx(i); /* global index */ lua_assert(ttisstring(&p->k[g])); *name = svalue(&p->k[g]); return "global"; } case OP_MOVE: { int a = GETARG_A(i); int b = GETARG_B(i); /* move from `b' to `a' */ if (b < a) return getobjname(L, ci, b, name); /* get name for `b' */ break; } case OP_GETTABLE: { int k = GETARG_C(i); /* key index */ *name = kname(p, k); return "field"; } case OP_GETUPVAL: { int u = GETARG_B(i); /* upvalue index */ *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; return "upvalue"; } case OP_SELF: { int k = GETARG_C(i); /* key index */ *name = kname(p, k); return "method"; } default: break; } } return NULL; /* no useful name found */ } static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { Instruction i; if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) return NULL; /* calling function is not Lua (or is unknown) */ ci--; /* calling function */ i = ci_func(ci)->l.p->code[currentpc(L, ci)]; if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || GET_OPCODE(i) == OP_TFORLOOP) return getobjname(L, ci, GETARG_A(i), name); else return NULL; /* no useful name can be found */ } /* only ANSI way to check whether a pointer points to an array */ static int isinstack (CallInfo *ci, const TValue *o) { StkId p; for (p = ci->base; p < ci->top; p++) if (o == p) return 1; return 0; } void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { const char *name = NULL; const char *t = luaT_typenames[ttype(o)]; const char *kind = (isinstack(L->ci, o)) ? getobjname(L, L->ci, cast_int(o - L->base), &name) : NULL; if (kind) luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", op, kind, name, t); else luaG_runerror(L, "attempt to %s a %s value", op, t); } void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; lua_assert(!ttisstring(p1) && !ttisnumber(p1)); luaG_typeerror(L, p1, "concatenate"); } void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { TValue temp; if (luaV_tonumber(p1, &temp) == NULL) p2 = p1; /* first operand is wrong */ luaG_typeerror(L, p2, "perform arithmetic on"); } int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { const char *t1 = luaT_typenames[ttype(p1)]; const char *t2 = luaT_typenames[ttype(p2)]; if (t1[2] == t2[2]) luaG_runerror(L, "attempt to compare two %s values", t1); else luaG_runerror(L, "attempt to compare %s with %s", t1, t2); return 0; } static void addinfo (lua_State *L, const char *msg) { CallInfo *ci = L->ci; if (isLua(ci)) { /* is Lua code? */ char buff[LUA_IDSIZE]; /* add file:line information */ int line = currentline(L, ci); luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); } } void luaG_errormsg (lua_State *L) { if (L->errfunc != 0) { /* is there an error handling function? */ StkId errfunc = restorestack(L, L->errfunc); if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); setobjs2s(L, L->top, L->top - 1); /* move argument */ setobjs2s(L, L->top - 1, errfunc); /* push function */ incr_top(L); luaD_call(L, L->top - 2, 1); /* call it */ } luaD_throw(L, LUA_ERRRUN); } void luaG_runerror (lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); addinfo(L, luaO_pushvfstring(L, fmt, argp)); va_end(argp); luaG_errormsg(L); } bam-0.4.0/src/lua/lcode.h0000644000175000017500000000527611430042030013160 0ustar kmakma/* ** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ #ifndef lcode_h #define lcode_h #include "llex.h" #include "lobject.h" #include "lopcodes.h" #include "lparser.h" /* ** Marks the end of a patch list. It is an invalid value both as an absolute ** address, and as a list link (would link an element to itself). */ #define NO_JUMP (-1) /* ** grep "ORDER OPR" if you change these enums */ typedef enum BinOpr { OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, OPR_CONCAT, OPR_NE, OPR_EQ, OPR_LT, OPR_LE, OPR_GT, OPR_GE, OPR_AND, OPR_OR, OPR_NOBINOPR } BinOpr; typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; #define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) #define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) #define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); LUAI_FUNC void luaK_fixline (FuncState *fs, int line); LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); LUAI_FUNC int luaK_jump (FuncState *fs); LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); LUAI_FUNC int luaK_getlabel (FuncState *fs); LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); #endif bam-0.4.0/src/lua/lauxlib.h0000644000175000017500000001322111430042030013517 0ustar kmakma/* ** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ #ifndef lauxlib_h #define lauxlib_h #include #include #include "lua.h" #if defined(LUA_COMPAT_GETN) LUALIB_API int (luaL_getn) (lua_State *L, int t); LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); #else #define luaL_getn(L,i) ((int)lua_objlen(L, i)) #define luaL_setn(L,i,j) ((void)0) /* no op! */ #endif #if defined(LUA_COMPAT_OPENLIB) #define luaI_openlib luaL_openlib #endif /* extra error code for `luaL_load' */ #define LUA_ERRFILE (LUA_ERRERR+1) typedef struct luaL_Reg { const char *name; lua_CFunction func; } luaL_Reg; LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup); LUALIB_API void (luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l); LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, size_t *l); LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, const char *def, size_t *l); LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, lua_Integer def); LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); LUALIB_API void (luaL_checkany) (lua_State *L, int narg); LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); LUALIB_API void (luaL_where) (lua_State *L, int lvl); LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, const char *const lst[]); LUALIB_API int (luaL_ref) (lua_State *L, int t); LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, const char *name); LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); LUALIB_API lua_State *(luaL_newstate) (void); LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, const char *r); LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, const char *fname, int szhint); /* ** =============================================================== ** some useful macros ** =============================================================== */ #define luaL_argcheck(L, cond,numarg,extramsg) \ ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) #define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) #define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) #define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) #define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) #define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) #define luaL_dofile(L, fn) \ (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) #define luaL_dostring(L, s) \ (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) #define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) /* ** {====================================================== ** Generic Buffer manipulation ** ======================================================= */ typedef struct luaL_Buffer { char *p; /* current position in buffer */ int lvl; /* number of strings in the stack (level) */ lua_State *L; char buffer[LUAL_BUFFERSIZE]; } luaL_Buffer; #define luaL_addchar(B,c) \ ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ (*(B)->p++ = (char)(c))) /* compatibility only */ #define luaL_putchar(B,c) luaL_addchar(B,c) #define luaL_addsize(B,n) ((B)->p += (n)) LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); /* }====================================================== */ /* compatibility with ref system */ /* pre-defined references */ #define LUA_NOREF (-2) #define LUA_REFNIL (-1) #define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) #define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) #define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) #define luaL_reg luaL_Reg #endif bam-0.4.0/src/lua/ltable.c0000644000175000017500000003760711430042030013333 0ustar kmakma/* ** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ /* ** Implementation of tables (aka arrays, objects, or hash tables). ** Tables keep its elements in two parts: an array part and a hash part. ** Non-negative integer keys are all candidates to be kept in the array ** part. The actual size of the array is the largest `n' such that at ** least half the slots between 0 and n are in use. ** Hash uses a mix of chained scatter table with Brent's variation. ** A main invariant of these tables is that, if an element is not ** in its main position (i.e. the `original' position that its hash gives ** to it), then the colliding element is in its own main position. ** Hence even when the load factor reaches 100%, performance remains good. */ #include #include #define ltable_c #define LUA_CORE #include "lua.h" #include "ldebug.h" #include "ldo.h" #include "lgc.h" #include "lmem.h" #include "lobject.h" #include "lstate.h" #include "ltable.h" /* ** max size of array part is 2^MAXBITS */ #if LUAI_BITSINT > 26 #define MAXBITS 26 #else #define MAXBITS (LUAI_BITSINT-2) #endif #define MAXASIZE (1 << MAXBITS) #define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) #define hashstr(t,str) hashpow2(t, (str)->tsv.hash) #define hashboolean(t,p) hashpow2(t, p) /* ** for some types, it is better to avoid modulus by power of 2, as ** they tend to have many 2 factors. */ #define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) #define hashpointer(t,p) hashmod(t, IntPoint(p)) /* ** number of ints inside a lua_Number */ #define numints cast_int(sizeof(lua_Number)/sizeof(int)) #define dummynode (&dummynode_) static const Node dummynode_ = { {{NULL}, LUA_TNIL}, /* value */ {{{NULL}, LUA_TNIL, NULL}} /* key */ }; /* ** hash for lua_Numbers */ static Node *hashnum (const Table *t, lua_Number n) { unsigned int a[numints]; int i; if (luai_numeq(n, 0)) /* avoid problems with -0 */ return gnode(t, 0); memcpy(a, &n, sizeof(a)); for (i = 1; i < numints; i++) a[0] += a[i]; return hashmod(t, a[0]); } /* ** returns the `main' position of an element in a table (that is, the index ** of its hash value) */ static Node *mainposition (const Table *t, const TValue *key) { switch (ttype(key)) { case LUA_TNUMBER: return hashnum(t, nvalue(key)); case LUA_TSTRING: return hashstr(t, rawtsvalue(key)); case LUA_TBOOLEAN: return hashboolean(t, bvalue(key)); case LUA_TLIGHTUSERDATA: return hashpointer(t, pvalue(key)); default: return hashpointer(t, gcvalue(key)); } } /* ** returns the index for `key' if `key' is an appropriate key to live in ** the array part of the table, -1 otherwise. */ static int arrayindex (const TValue *key) { if (ttisnumber(key)) { lua_Number n = nvalue(key); int k; lua_number2int(k, n); if (luai_numeq(cast_num(k), n)) return k; } return -1; /* `key' did not match some condition */ } /* ** returns the index of a `key' for table traversals. First goes all ** elements in the array part, then elements in the hash part. The ** beginning of a traversal is signalled by -1. */ static int findindex (lua_State *L, Table *t, StkId key) { int i; if (ttisnil(key)) return -1; /* first iteration */ i = arrayindex(key); if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ return i-1; /* yes; that's the index (corrected to C) */ else { Node *n = mainposition(t, key); do { /* check whether `key' is somewhere in the chain */ /* key may be dead already, but it is ok to use it in `next' */ if (luaO_rawequalObj(key2tval(n), key) || (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && gcvalue(gkey(n)) == gcvalue(key))) { i = cast_int(n - gnode(t, 0)); /* key index in hash table */ /* hash elements are numbered after array ones */ return i + t->sizearray; } else n = gnext(n); } while (n); luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ return 0; /* to avoid warnings */ } } int luaH_next (lua_State *L, Table *t, StkId key) { int i = findindex(L, t, key); /* find original element */ for (i++; i < t->sizearray; i++) { /* try first array part */ if (!ttisnil(&t->array[i])) { /* a non-nil value? */ setnvalue(key, cast_num(i+1)); setobj2s(L, key+1, &t->array[i]); return 1; } } for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ setobj2s(L, key, key2tval(gnode(t, i))); setobj2s(L, key+1, gval(gnode(t, i))); return 1; } } return 0; /* no more elements */ } /* ** {============================================================= ** Rehash ** ============================================================== */ static int computesizes (int nums[], int *narray) { int i; int twotoi; /* 2^i */ int a = 0; /* number of elements smaller than 2^i */ int na = 0; /* number of elements to go to array part */ int n = 0; /* optimal size for array part */ for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { if (nums[i] > 0) { a += nums[i]; if (a > twotoi/2) { /* more than half elements present? */ n = twotoi; /* optimal size (till now) */ na = a; /* all elements smaller than n will go to array part */ } } if (a == *narray) break; /* all elements already counted */ } *narray = n; lua_assert(*narray/2 <= na && na <= *narray); return na; } static int countint (const TValue *key, int *nums) { int k = arrayindex(key); if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ nums[ceillog2(k)]++; /* count as such */ return 1; } else return 0; } static int numusearray (const Table *t, int *nums) { int lg; int ttlg; /* 2^lg */ int ause = 0; /* summation of `nums' */ int i = 1; /* count to traverse all array keys */ for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ int lc = 0; /* counter */ int lim = ttlg; if (lim > t->sizearray) { lim = t->sizearray; /* adjust upper limit */ if (i > lim) break; /* no more elements to count */ } /* count elements in range (2^(lg-1), 2^lg] */ for (; i <= lim; i++) { if (!ttisnil(&t->array[i-1])) lc++; } nums[lg] += lc; ause += lc; } return ause; } static int numusehash (const Table *t, int *nums, int *pnasize) { int totaluse = 0; /* total number of elements */ int ause = 0; /* summation of `nums' */ int i = sizenode(t); while (i--) { Node *n = &t->node[i]; if (!ttisnil(gval(n))) { ause += countint(key2tval(n), nums); totaluse++; } } *pnasize += ause; return totaluse; } static void setarrayvector (lua_State *L, Table *t, int size) { int i; luaM_reallocvector(L, t->array, t->sizearray, size, TValue); for (i=t->sizearray; iarray[i]); t->sizearray = size; } static void setnodevector (lua_State *L, Table *t, int size) { int lsize; if (size == 0) { /* no elements to hash part? */ t->node = cast(Node *, dummynode); /* use common `dummynode' */ lsize = 0; } else { int i; lsize = ceillog2(size); if (lsize > MAXBITS) luaG_runerror(L, "table overflow"); size = twoto(lsize); t->node = luaM_newvector(L, size, Node); for (i=0; ilsizenode = cast_byte(lsize); t->lastfree = gnode(t, size); /* all positions are free */ } static void resize (lua_State *L, Table *t, int nasize, int nhsize) { int i; int oldasize = t->sizearray; int oldhsize = t->lsizenode; Node *nold = t->node; /* save old hash ... */ if (nasize > oldasize) /* array part must grow? */ setarrayvector(L, t, nasize); /* create new hash part with appropriate size */ setnodevector(L, t, nhsize); if (nasize < oldasize) { /* array part must shrink? */ t->sizearray = nasize; /* re-insert elements from vanishing slice */ for (i=nasize; iarray[i])) setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); } /* shrink array */ luaM_reallocvector(L, t->array, oldasize, nasize, TValue); } /* re-insert elements from hash part */ for (i = twoto(oldhsize) - 1; i >= 0; i--) { Node *old = nold+i; if (!ttisnil(gval(old))) setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); } if (nold != dummynode) luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ } void luaH_resizearray (lua_State *L, Table *t, int nasize) { int nsize = (t->node == dummynode) ? 0 : sizenode(t); resize(L, t, nasize, nsize); } static void rehash (lua_State *L, Table *t, const TValue *ek) { int nasize, na; int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ int i; int totaluse; for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ nasize = numusearray(t, nums); /* count keys in array part */ totaluse = nasize; /* all those keys are integer keys */ totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ /* count extra key */ nasize += countint(ek, nums); totaluse++; /* compute new size for array part */ na = computesizes(nums, &nasize); /* resize the table to new computed sizes */ resize(L, t, nasize, totaluse - na); } /* ** }============================================================= */ Table *luaH_new (lua_State *L, int narray, int nhash) { Table *t = luaM_new(L, Table); luaC_link(L, obj2gco(t), LUA_TTABLE); t->metatable = NULL; t->flags = cast_byte(~0); /* temporary values (kept only if some malloc fails) */ t->array = NULL; t->sizearray = 0; t->lsizenode = 0; t->node = cast(Node *, dummynode); setarrayvector(L, t, narray); setnodevector(L, t, nhash); return t; } void luaH_free (lua_State *L, Table *t) { if (t->node != dummynode) luaM_freearray(L, t->node, sizenode(t), Node); luaM_freearray(L, t->array, t->sizearray, TValue); luaM_free(L, t); } static Node *getfreepos (Table *t) { while (t->lastfree-- > t->node) { if (ttisnil(gkey(t->lastfree))) return t->lastfree; } return NULL; /* could not find a free place */ } /* ** inserts a new key into a hash table; first, check whether key's main ** position is free. If not, check whether colliding node is in its main ** position or not: if it is not, move colliding node to an empty place and ** put new key in its main position; otherwise (colliding node is in its main ** position), new key goes to an empty position. */ static TValue *newkey (lua_State *L, Table *t, const TValue *key) { Node *mp = mainposition(t, key); if (!ttisnil(gval(mp)) || mp == dummynode) { Node *othern; Node *n = getfreepos(t); /* get a free place */ if (n == NULL) { /* cannot find a free place? */ rehash(L, t, key); /* grow table */ return luaH_set(L, t, key); /* re-insert key into grown table */ } lua_assert(n != dummynode); othern = mainposition(t, key2tval(mp)); if (othern != mp) { /* is colliding node out of its main position? */ /* yes; move colliding node into free position */ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ gnext(mp) = NULL; /* now `mp' is free */ setnilvalue(gval(mp)); } else { /* colliding node is in its own main position */ /* new node will go into free position */ gnext(n) = gnext(mp); /* chain new position */ gnext(mp) = n; mp = n; } } gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; luaC_barriert(L, t, key); lua_assert(ttisnil(gval(mp))); return gval(mp); } /* ** search function for integers */ const TValue *luaH_getnum (Table *t, int key) { /* (1 <= key && key <= t->sizearray) */ if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) return &t->array[key-1]; else { lua_Number nk = cast_num(key); Node *n = hashnum(t, nk); do { /* check whether `key' is somewhere in the chain */ if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) return gval(n); /* that's it */ else n = gnext(n); } while (n); return luaO_nilobject; } } /* ** search function for strings */ const TValue *luaH_getstr (Table *t, TString *key) { Node *n = hashstr(t, key); do { /* check whether `key' is somewhere in the chain */ if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) return gval(n); /* that's it */ else n = gnext(n); } while (n); return luaO_nilobject; } /* ** main search function */ const TValue *luaH_get (Table *t, const TValue *key) { switch (ttype(key)) { case LUA_TNIL: return luaO_nilobject; case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); case LUA_TNUMBER: { int k; lua_Number n = nvalue(key); lua_number2int(k, n); if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ return luaH_getnum(t, k); /* use specialized version */ /* else go through */ } default: { Node *n = mainposition(t, key); do { /* check whether `key' is somewhere in the chain */ if (luaO_rawequalObj(key2tval(n), key)) return gval(n); /* that's it */ else n = gnext(n); } while (n); return luaO_nilobject; } } } TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { const TValue *p = luaH_get(t, key); t->flags = 0; if (p != luaO_nilobject) return cast(TValue *, p); else { if (ttisnil(key)) luaG_runerror(L, "table index is nil"); else if (ttisnumber(key) && luai_numisnan(nvalue(key))) luaG_runerror(L, "table index is NaN"); return newkey(L, t, key); } } TValue *luaH_setnum (lua_State *L, Table *t, int key) { const TValue *p = luaH_getnum(t, key); if (p != luaO_nilobject) return cast(TValue *, p); else { TValue k; setnvalue(&k, cast_num(key)); return newkey(L, t, &k); } } TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { const TValue *p = luaH_getstr(t, key); if (p != luaO_nilobject) return cast(TValue *, p); else { TValue k; setsvalue(L, &k, key); return newkey(L, t, &k); } } static int unbound_search (Table *t, unsigned int j) { unsigned int i = j; /* i is zero or a present index */ j++; /* find `i' and `j' such that i is present and j is not */ while (!ttisnil(luaH_getnum(t, j))) { i = j; j *= 2; if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ /* table was built with bad purposes: resort to linear search */ i = 1; while (!ttisnil(luaH_getnum(t, i))) i++; return i - 1; } } /* now do a binary search between them */ while (j - i > 1) { unsigned int m = (i+j)/2; if (ttisnil(luaH_getnum(t, m))) j = m; else i = m; } return i; } /* ** Try to find a boundary in table `t'. A `boundary' is an integer index ** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). */ int luaH_getn (Table *t) { unsigned int j = t->sizearray; if (j > 0 && ttisnil(&t->array[j - 1])) { /* there is a boundary in the array part: (binary) search for it */ unsigned int i = 0; while (j - i > 1) { unsigned int m = (i+j)/2; if (ttisnil(&t->array[m - 1])) j = m; else i = m; } return i; } /* else must find a boundary in hash part */ else if (t->node == dummynode) /* hash part is empty? */ return j; /* that is easy... */ else return unbound_search(t, j); } #if defined(LUA_DEBUG) Node *luaH_mainposition (const Table *t, const TValue *key) { return mainposition(t, key); } int luaH_isdummy (Node *n) { return n == dummynode; } #endif bam-0.4.0/src/lua/lstate.c0000644000175000017500000001305211430042030013350 0ustar kmakma/* ** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ ** Global State ** See Copyright Notice in lua.h */ #include #define lstate_c #define LUA_CORE #include "lua.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" #include "lgc.h" #include "llex.h" #include "lmem.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" #define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) #define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) #define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) /* ** Main thread combines a thread state and the global state */ typedef struct LG { lua_State l; global_State g; } LG; static void stack_init (lua_State *L1, lua_State *L) { /* initialize CallInfo array */ L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); L1->ci = L1->base_ci; L1->size_ci = BASIC_CI_SIZE; L1->end_ci = L1->base_ci + L1->size_ci - 1; /* initialize stack array */ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; L1->top = L1->stack; L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; /* initialize first ci */ L1->ci->func = L1->top; setnilvalue(L1->top++); /* `function' entry for this `ci' */ L1->base = L1->ci->base = L1->top; L1->ci->top = L1->top + LUA_MINSTACK; } static void freestack (lua_State *L, lua_State *L1) { luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); luaM_freearray(L, L1->stack, L1->stacksize, TValue); } /* ** open parts that may cause memory-allocation errors */ static void f_luaopen (lua_State *L, void *ud) { global_State *g = G(L); UNUSED(ud); stack_init(L, L); /* init stack */ sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ luaT_init(L); luaX_init(L); luaS_fix(luaS_newliteral(L, MEMERRMSG)); g->GCthreshold = 4*g->totalbytes; } static void preinit_state (lua_State *L, global_State *g) { G(L) = g; L->stack = NULL; L->stacksize = 0; L->errorJmp = NULL; L->hook = NULL; L->hookmask = 0; L->basehookcount = 0; L->allowhook = 1; resethookcount(L); L->openupval = NULL; L->size_ci = 0; L->nCcalls = L->baseCcalls = 0; L->status = 0; L->base_ci = L->ci = NULL; L->savedpc = NULL; L->errfunc = 0; setnilvalue(gt(L)); } static void close_state (lua_State *L) { global_State *g = G(L); luaF_close(L, L->stack); /* close all upvalues for this thread */ luaC_freeall(L); /* collect all objects */ lua_assert(g->rootgc == obj2gco(L)); lua_assert(g->strt.nuse == 0); luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); luaZ_freebuffer(L, &g->buff); freestack(L, L); lua_assert(g->totalbytes == sizeof(LG)); (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); } lua_State *luaE_newthread (lua_State *L) { lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); luaC_link(L, obj2gco(L1), LUA_TTHREAD); preinit_state(L1, G(L)); stack_init(L1, L); /* init stack */ setobj2n(L, gt(L1), gt(L)); /* share table of globals */ L1->hookmask = L->hookmask; L1->basehookcount = L->basehookcount; L1->hook = L->hook; resethookcount(L1); lua_assert(iswhite(obj2gco(L1))); return L1; } void luaE_freethread (lua_State *L, lua_State *L1) { luaF_close(L1, L1->stack); /* close all upvalues for this thread */ lua_assert(L1->openupval == NULL); luai_userstatefree(L1); freestack(L, L1); luaM_freemem(L, fromstate(L1), state_size(lua_State)); } LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { int i; lua_State *L; global_State *g; void *l = (*f)(ud, NULL, 0, state_size(LG)); if (l == NULL) return NULL; L = tostate(l); g = &((LG *)L)->g; L->next = NULL; L->tt = LUA_TTHREAD; g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); L->marked = luaC_white(g); set2bits(L->marked, FIXEDBIT, SFIXEDBIT); preinit_state(L, g); g->frealloc = f; g->ud = ud; g->mainthread = L; g->uvhead.u.l.prev = &g->uvhead; g->uvhead.u.l.next = &g->uvhead; g->GCthreshold = 0; /* mark it as unfinished state */ g->strt.size = 0; g->strt.nuse = 0; g->strt.hash = NULL; setnilvalue(registry(L)); luaZ_initbuffer(L, &g->buff); g->panic = NULL; g->gcstate = GCSpause; g->rootgc = obj2gco(L); g->sweepstrgc = 0; g->sweepgc = &g->rootgc; g->gray = NULL; g->grayagain = NULL; g->weak = NULL; g->tmudata = NULL; g->totalbytes = sizeof(LG); g->gcpause = LUAI_GCPAUSE; g->gcstepmul = LUAI_GCMUL; g->gcdept = 0; for (i=0; imt[i] = NULL; if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { /* memory allocation error: free partial state */ close_state(L); L = NULL; } else luai_userstateopen(L); return L; } static void callallgcTM (lua_State *L, void *ud) { UNUSED(ud); luaC_callGCTM(L); /* call GC metamethods for all udata */ } LUA_API void lua_close (lua_State *L) { L = G(L)->mainthread; /* only the main thread can be closed */ lua_lock(L); luaF_close(L, L->stack); /* close all upvalues for this thread */ luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ L->errfunc = 0; /* no error function during GC metamethods */ do { /* repeat until no more errors */ L->ci = L->base_ci; L->base = L->top = L->ci->base; L->nCcalls = L->baseCcalls = 0; } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); lua_assert(G(L)->tmudata == NULL); luai_userstateclose(L); close_state(L); } bam-0.4.0/src/lua/print.c0000644000175000017500000001152011430042030013206 0ustar kmakma/* ** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $ ** print bytecodes ** See Copyright Notice in lua.h */ #include #include #define luac_c #define LUA_CORE #include "ldebug.h" #include "lobject.h" #include "lopcodes.h" #include "lundump.h" #define PrintFunction luaU_print #define Sizeof(x) ((int)sizeof(x)) #define VOID(p) ((const void*)(p)) static void PrintString(const TString* ts) { const char* s=getstr(ts); size_t i,n=ts->tsv.len; putchar('"'); for (i=0; ik[i]; switch (ttype(o)) { case LUA_TNIL: printf("nil"); break; case LUA_TBOOLEAN: printf(bvalue(o) ? "true" : "false"); break; case LUA_TNUMBER: printf(LUA_NUMBER_FMT,nvalue(o)); break; case LUA_TSTRING: PrintString(rawtsvalue(o)); break; default: /* cannot happen */ printf("? type=%d",ttype(o)); break; } } static void PrintCode(const Proto* f) { const Instruction* code=f->code; int pc,n=f->sizecode; for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); printf("%-9s\t",luaP_opnames[o]); switch (getOpMode(o)) { case iABC: printf("%d",a); if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b); if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c); break; case iABx: if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx); break; case iAsBx: if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx); break; } switch (o) { case OP_LOADK: printf("\t; "); PrintConstant(f,bx); break; case OP_GETUPVAL: case OP_SETUPVAL: printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-"); break; case OP_GETGLOBAL: case OP_SETGLOBAL: printf("\t; %s",svalue(&f->k[bx])); break; case OP_GETTABLE: case OP_SELF: if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } break; case OP_SETTABLE: case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_POW: case OP_EQ: case OP_LT: case OP_LE: if (ISK(b) || ISK(c)) { printf("\t; "); if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); printf(" "); if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); } break; case OP_JMP: case OP_FORLOOP: case OP_FORPREP: printf("\t; to %d",sbx+pc+2); break; case OP_CLOSURE: printf("\t; %p",VOID(f->p[bx])); break; case OP_SETLIST: if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); break; default: break; } printf("\n"); } } #define SS(x) (x==1)?"":"s" #define S(x) x,SS(x) static void PrintHeader(const Proto* f) { const char* s=getstr(f->source); if (*s=='@' || *s=='=') s++; else if (*s==LUA_SIGNATURE[0]) s="(bstring)"; else s="(string)"; printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n", (f->linedefined==0)?"main":"function",s, f->linedefined,f->lastlinedefined, S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f)); printf("%d%s param%s, %d slot%s, %d upvalue%s, ", f->numparams,f->is_vararg?"+":"",SS(f->numparams), S(f->maxstacksize),S(f->nups)); printf("%d local%s, %d constant%s, %d function%s\n", S(f->sizelocvars),S(f->sizek),S(f->sizep)); } static void PrintConstants(const Proto* f) { int i,n=f->sizek; printf("constants (%d) for %p:\n",n,VOID(f)); for (i=0; isizelocvars; printf("locals (%d) for %p:\n",n,VOID(f)); for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); } } static void PrintUpvalues(const Proto* f) { int i,n=f->sizeupvalues; printf("upvalues (%d) for %p:\n",n,VOID(f)); if (f->upvalues==NULL) return; for (i=0; iupvalues[i])); } } void PrintFunction(const Proto* f, int full) { int i,n=f->sizep; PrintHeader(f); PrintCode(f); if (full) { PrintConstants(f); PrintLocals(f); PrintUpvalues(f); } for (i=0; ip[i],full); } bam-0.4.0/src/lua/lapi.h0000644000175000017500000000040611430042030013005 0ustar kmakma/* ** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ ** Auxiliary functions from Lua API ** See Copyright Notice in lua.h */ #ifndef lapi_h #define lapi_h #include "lobject.h" LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); #endif bam-0.4.0/src/lua/README0000644000175000017500000000254211430042030012572 0ustar kmakmaREADME for Lua 5.1 See INSTALL for installation instructions. See HISTORY for a summary of changes since the last released version. * What is Lua? ------------ Lua is a powerful, light-weight programming language designed for extending applications. Lua is also frequently used as a general-purpose, stand-alone language. Lua is free software. For complete information, visit Lua's web site at http://www.lua.org/ . For an executive summary, see http://www.lua.org/about.html . Lua has been used in many different projects around the world. For a short list, see http://www.lua.org/uses.html . * Availability ------------ Lua is freely available for both academic and commercial purposes. See COPYRIGHT and http://www.lua.org/license.html for details. Lua can be downloaded at http://www.lua.org/download.html . * Installation ------------ Lua is implemented in pure ANSI C, and compiles unmodified in all known platforms that have an ANSI C compiler. In most Unix-like platforms, simply do "make" with a suitable target. See INSTALL for detailed instructions. * Origin ------ Lua is developed at Lua.org, a laboratory of the Department of Computer Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro in Brazil). For more information about the authors, see http://www.lua.org/authors.html . (end of README) bam-0.4.0/src/lua/ltable.h0000644000175000017500000000224011430042030013321 0ustar kmakma/* ** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ #ifndef ltable_h #define ltable_h #include "lobject.h" #define gnode(t,i) (&(t)->node[i]) #define gkey(n) (&(n)->i_key.nk) #define gval(n) (&(n)->i_val) #define gnext(n) ((n)->i_key.nk.next) #define key2tval(n) (&(n)->i_key.tvk) LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); LUAI_FUNC void luaH_free (lua_State *L, Table *t); LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); LUAI_FUNC int luaH_getn (Table *t); #if defined(LUA_DEBUG) LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); LUAI_FUNC int luaH_isdummy (Node *n); #endif #endif bam-0.4.0/src/lua/ltm.c0000644000175000017500000000316211430042030012651 0ustar kmakma/* ** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ #include #define ltm_c #define LUA_CORE #include "lua.h" #include "lobject.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" const char *const luaT_typenames[] = { "nil", "boolean", "userdata", "number", "string", "table", "function", "userdata", "thread", "proto", "upval" }; void luaT_init (lua_State *L) { static const char *const luaT_eventname[] = { /* ORDER TM */ "__index", "__newindex", "__gc", "__mode", "__eq", "__add", "__sub", "__mul", "__div", "__mod", "__pow", "__unm", "__len", "__lt", "__le", "__concat", "__call" }; int i; for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); luaS_fix(G(L)->tmname[i]); /* never collect these names */ } } /* ** function to be used with macro "fasttm": optimized for absence of ** tag methods */ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { const TValue *tm = luaH_getstr(events, ename); lua_assert(event <= TM_EQ); if (ttisnil(tm)) { /* no tag method? */ events->flags |= cast_byte(1u<metatable; break; case LUA_TUSERDATA: mt = uvalue(o)->metatable; break; default: mt = G(L)->mt[ttype(o)]; } return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); } bam-0.4.0/src/lua/lopcodes.c0000644000175000017500000000550411430042030013667 0ustar kmakma/* ** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ ** See Copyright Notice in lua.h */ #define lopcodes_c #define LUA_CORE #include "lopcodes.h" /* ORDER OP */ const char *const luaP_opnames[NUM_OPCODES+1] = { "MOVE", "LOADK", "LOADBOOL", "LOADNIL", "GETUPVAL", "GETGLOBAL", "GETTABLE", "SETGLOBAL", "SETUPVAL", "SETTABLE", "NEWTABLE", "SELF", "ADD", "SUB", "MUL", "DIV", "MOD", "POW", "UNM", "NOT", "LEN", "CONCAT", "JMP", "EQ", "LT", "LE", "TEST", "TESTSET", "CALL", "TAILCALL", "RETURN", "FORLOOP", "FORPREP", "TFORLOOP", "SETLIST", "CLOSE", "CLOSURE", "VARARG", NULL }; #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) const lu_byte luaP_opmodes[NUM_OPCODES] = { /* T A B C mode opcode */ opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ }; bam-0.4.0/src/lua/lvm.c0000644000175000017500000005512611430042030012662 0ustar kmakma/* ** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ #include #include #include #define lvm_c #define LUA_CORE #include "lua.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" #include "lgc.h" #include "lobject.h" #include "lopcodes.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" #include "lvm.h" /* limit for table tag-method chains (to avoid loops) */ #define MAXTAGLOOP 100 const TValue *luaV_tonumber (const TValue *obj, TValue *n) { lua_Number num; if (ttisnumber(obj)) return obj; if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { setnvalue(n, num); return n; } else return NULL; } int luaV_tostring (lua_State *L, StkId obj) { if (!ttisnumber(obj)) return 0; else { char s[LUAI_MAXNUMBER2STR]; lua_Number n = nvalue(obj); lua_number2str(s, n); setsvalue2s(L, obj, luaS_new(L, s)); return 1; } } static void traceexec (lua_State *L, const Instruction *pc) { lu_byte mask = L->hookmask; const Instruction *oldpc = L->savedpc; L->savedpc = pc; if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { resethookcount(L); luaD_callhook(L, LUA_HOOKCOUNT, -1); } if (mask & LUA_MASKLINE) { Proto *p = ci_func(L->ci)->l.p; int npc = pcRel(pc, p); int newline = getline(p, npc); /* call linehook when enter a new function, when jump back (loop), or when enter a new line */ if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) luaD_callhook(L, LUA_HOOKLINE, newline); } } static void callTMres (lua_State *L, StkId res, const TValue *f, const TValue *p1, const TValue *p2) { ptrdiff_t result = savestack(L, res); setobj2s(L, L->top, f); /* push function */ setobj2s(L, L->top+1, p1); /* 1st argument */ setobj2s(L, L->top+2, p2); /* 2nd argument */ luaD_checkstack(L, 3); L->top += 3; luaD_call(L, L->top - 3, 1); res = restorestack(L, result); L->top--; setobjs2s(L, res, L->top); } static void callTM (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, const TValue *p3) { setobj2s(L, L->top, f); /* push function */ setobj2s(L, L->top+1, p1); /* 1st argument */ setobj2s(L, L->top+2, p2); /* 2nd argument */ setobj2s(L, L->top+3, p3); /* 3th argument */ luaD_checkstack(L, 4); L->top += 4; luaD_call(L, L->top - 4, 0); } void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { int loop; for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; if (ttistable(t)) { /* `t' is a table? */ Table *h = hvalue(t); const TValue *res = luaH_get(h, key); /* do a primitive get */ if (!ttisnil(res) || /* result is no nil? */ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ setobj2s(L, val, res); return; } /* else will try the tag method */ } else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) luaG_typeerror(L, t, "index"); if (ttisfunction(tm)) { callTMres(L, val, tm, t, key); return; } t = tm; /* else repeat with `tm' */ } luaG_runerror(L, "loop in gettable"); } void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { int loop; for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; if (ttistable(t)) { /* `t' is a table? */ Table *h = hvalue(t); TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ if (!ttisnil(oldval) || /* result is no nil? */ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ setobj2t(L, oldval, val); luaC_barriert(L, h, val); return; } /* else will try the tag method */ } else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) luaG_typeerror(L, t, "index"); if (ttisfunction(tm)) { callTM(L, tm, t, key, val); return; } t = tm; /* else repeat with `tm' */ } luaG_runerror(L, "loop in settable"); } static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, StkId res, TMS event) { const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ if (ttisnil(tm)) tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ if (ttisnil(tm)) return 0; callTMres(L, res, tm, p1, p2); return 1; } static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, TMS event) { const TValue *tm1 = fasttm(L, mt1, event); const TValue *tm2; if (tm1 == NULL) return NULL; /* no metamethod */ if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ tm2 = fasttm(L, mt2, event); if (tm2 == NULL) return NULL; /* no metamethod */ if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ return tm1; return NULL; } static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, TMS event) { const TValue *tm1 = luaT_gettmbyobj(L, p1, event); const TValue *tm2; if (ttisnil(tm1)) return -1; /* no metamethod? */ tm2 = luaT_gettmbyobj(L, p2, event); if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ return -1; callTMres(L, L->top, tm1, p1, p2); return !l_isfalse(L->top); } static int l_strcmp (const TString *ls, const TString *rs) { const char *l = getstr(ls); size_t ll = ls->tsv.len; const char *r = getstr(rs); size_t lr = rs->tsv.len; for (;;) { int temp = strcoll(l, r); if (temp != 0) return temp; else { /* strings are equal up to a `\0' */ size_t len = strlen(l); /* index of first `\0' in both strings */ if (len == lr) /* r is finished? */ return (len == ll) ? 0 : 1; else if (len == ll) /* l is finished? */ return -1; /* l is smaller than r (because r is not finished) */ /* both strings longer than `len'; go on comparing (after the `\0') */ len++; l += len; ll -= len; r += len; lr -= len; } } } int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { int res; if (ttype(l) != ttype(r)) return luaG_ordererror(L, l, r); else if (ttisnumber(l)) return luai_numlt(nvalue(l), nvalue(r)); else if (ttisstring(l)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) return res; return luaG_ordererror(L, l, r); } static int lessequal (lua_State *L, const TValue *l, const TValue *r) { int res; if (ttype(l) != ttype(r)) return luaG_ordererror(L, l, r); else if (ttisnumber(l)) return luai_numle(nvalue(l), nvalue(r)); else if (ttisstring(l)) return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ return res; else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ return !res; return luaG_ordererror(L, l, r); } int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { const TValue *tm; lua_assert(ttype(t1) == ttype(t2)); switch (ttype(t1)) { case LUA_TNIL: return 1; case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); case LUA_TUSERDATA: { if (uvalue(t1) == uvalue(t2)) return 1; tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ); break; /* will try TM */ } case LUA_TTABLE: { if (hvalue(t1) == hvalue(t2)) return 1; tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); break; /* will try TM */ } default: return gcvalue(t1) == gcvalue(t2); } if (tm == NULL) return 0; /* no TM? */ callTMres(L, L->top, tm, t1, t2); /* call TM */ return !l_isfalse(L->top); } void luaV_concat (lua_State *L, int total, int last) { do { StkId top = L->base + last + 1; int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) luaG_concaterror(L, top-2, top-1); } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ (void)tostring(L, top - 2); /* result is first op (as string) */ else { /* at least two string values; get as many as possible */ size_t tl = tsvalue(top-1)->len; char *buffer; int i; /* collect total length */ for (n = 1; n < total && tostring(L, top-n-1); n++) { size_t l = tsvalue(top-n-1)->len; if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); tl += l; } buffer = luaZ_openspace(L, &G(L)->buff, tl); tl = 0; for (i=n; i>0; i--) { /* concat all strings */ size_t l = tsvalue(top-i)->len; memcpy(buffer+tl, svalue(top-i), l); tl += l; } setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); } total -= n-1; /* got `n' strings to create 1 new */ last -= n-1; } while (total > 1); /* repeat until only 1 result left */ } static void Arith (lua_State *L, StkId ra, const TValue *rb, const TValue *rc, TMS op) { TValue tempb, tempc; const TValue *b, *c; if ((b = luaV_tonumber(rb, &tempb)) != NULL && (c = luaV_tonumber(rc, &tempc)) != NULL) { lua_Number nb = nvalue(b), nc = nvalue(c); switch (op) { case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; default: lua_assert(0); break; } } else if (!call_binTM(L, rb, rc, ra, op)) luaG_aritherror(L, rb, rc); } /* ** some macros for common tasks in `luaV_execute' */ #define runtime_check(L, c) { if (!(c)) break; } #define RA(i) (base+GETARG_A(i)) /* to be used after possible stack reallocation */ #define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) #define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) #define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) #define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) #define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) #define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} #define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } #define arith_op(op,tm) { \ TValue *rb = RKB(i); \ TValue *rc = RKC(i); \ if (ttisnumber(rb) && ttisnumber(rc)) { \ lua_Number nb = nvalue(rb), nc = nvalue(rc); \ setnvalue(ra, op(nb, nc)); \ } \ else \ Protect(Arith(L, ra, rb, rc, tm)); \ } void luaV_execute (lua_State *L, int nexeccalls) { LClosure *cl; StkId base; TValue *k; const Instruction *pc; reentry: /* entry point */ lua_assert(isLua(L->ci)); pc = L->savedpc; cl = &clvalue(L->ci->func)->l; base = L->base; k = cl->p->k; /* main loop of interpreter */ for (;;) { const Instruction i = *pc++; StkId ra; if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { traceexec(L, pc); if (L->status == LUA_YIELD) { /* did hook yield? */ L->savedpc = pc - 1; return; } base = L->base; } /* warning!! several calls may realloc the stack and invalidate `ra' */ ra = RA(i); lua_assert(base == L->base && L->base == L->ci->base); lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); switch (GET_OPCODE(i)) { case OP_MOVE: { setobjs2s(L, ra, RB(i)); continue; } case OP_LOADK: { setobj2s(L, ra, KBx(i)); continue; } case OP_LOADBOOL: { setbvalue(ra, GETARG_B(i)); if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ continue; } case OP_LOADNIL: { TValue *rb = RB(i); do { setnilvalue(rb--); } while (rb >= ra); continue; } case OP_GETUPVAL: { int b = GETARG_B(i); setobj2s(L, ra, cl->upvals[b]->v); continue; } case OP_GETGLOBAL: { TValue g; TValue *rb = KBx(i); sethvalue(L, &g, cl->env); lua_assert(ttisstring(rb)); Protect(luaV_gettable(L, &g, rb, ra)); continue; } case OP_GETTABLE: { Protect(luaV_gettable(L, RB(i), RKC(i), ra)); continue; } case OP_SETGLOBAL: { TValue g; sethvalue(L, &g, cl->env); lua_assert(ttisstring(KBx(i))); Protect(luaV_settable(L, &g, KBx(i), ra)); continue; } case OP_SETUPVAL: { UpVal *uv = cl->upvals[GETARG_B(i)]; setobj(L, uv->v, ra); luaC_barrier(L, uv, ra); continue; } case OP_SETTABLE: { Protect(luaV_settable(L, ra, RKB(i), RKC(i))); continue; } case OP_NEWTABLE: { int b = GETARG_B(i); int c = GETARG_C(i); sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); Protect(luaC_checkGC(L)); continue; } case OP_SELF: { StkId rb = RB(i); setobjs2s(L, ra+1, rb); Protect(luaV_gettable(L, rb, RKC(i), ra)); continue; } case OP_ADD: { arith_op(luai_numadd, TM_ADD); continue; } case OP_SUB: { arith_op(luai_numsub, TM_SUB); continue; } case OP_MUL: { arith_op(luai_nummul, TM_MUL); continue; } case OP_DIV: { arith_op(luai_numdiv, TM_DIV); continue; } case OP_MOD: { arith_op(luai_nummod, TM_MOD); continue; } case OP_POW: { arith_op(luai_numpow, TM_POW); continue; } case OP_UNM: { TValue *rb = RB(i); if (ttisnumber(rb)) { lua_Number nb = nvalue(rb); setnvalue(ra, luai_numunm(nb)); } else { Protect(Arith(L, ra, rb, rb, TM_UNM)); } continue; } case OP_NOT: { int res = l_isfalse(RB(i)); /* next assignment may change this value */ setbvalue(ra, res); continue; } case OP_LEN: { const TValue *rb = RB(i); switch (ttype(rb)) { case LUA_TTABLE: { setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); break; } case LUA_TSTRING: { setnvalue(ra, cast_num(tsvalue(rb)->len)); break; } default: { /* try metamethod */ Protect( if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) luaG_typeerror(L, rb, "get length of"); ) } } continue; } case OP_CONCAT: { int b = GETARG_B(i); int c = GETARG_C(i); Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); setobjs2s(L, RA(i), base+b); continue; } case OP_JMP: { dojump(L, pc, GETARG_sBx(i)); continue; } case OP_EQ: { TValue *rb = RKB(i); TValue *rc = RKC(i); Protect( if (equalobj(L, rb, rc) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; } case OP_LT: { Protect( if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; } case OP_LE: { Protect( if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) dojump(L, pc, GETARG_sBx(*pc)); ) pc++; continue; } case OP_TEST: { if (l_isfalse(ra) != GETARG_C(i)) dojump(L, pc, GETARG_sBx(*pc)); pc++; continue; } case OP_TESTSET: { TValue *rb = RB(i); if (l_isfalse(rb) != GETARG_C(i)) { setobjs2s(L, ra, rb); dojump(L, pc, GETARG_sBx(*pc)); } pc++; continue; } case OP_CALL: { int b = GETARG_B(i); int nresults = GETARG_C(i) - 1; if (b != 0) L->top = ra+b; /* else previous instruction set top */ L->savedpc = pc; switch (luaD_precall(L, ra, nresults)) { case PCRLUA: { nexeccalls++; goto reentry; /* restart luaV_execute over new Lua function */ } case PCRC: { /* it was a C function (`precall' called it); adjust results */ if (nresults >= 0) L->top = L->ci->top; base = L->base; continue; } default: { return; /* yield */ } } } case OP_TAILCALL: { int b = GETARG_B(i); if (b != 0) L->top = ra+b; /* else previous instruction set top */ L->savedpc = pc; lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); switch (luaD_precall(L, ra, LUA_MULTRET)) { case PCRLUA: { /* tail call: put new frame in place of previous one */ CallInfo *ci = L->ci - 1; /* previous frame */ int aux; StkId func = ci->func; StkId pfunc = (ci+1)->func; /* previous function index */ if (L->openupval) luaF_close(L, ci->base); L->base = ci->base = ci->func + ((ci+1)->base - pfunc); for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ setobjs2s(L, func+aux, pfunc+aux); ci->top = L->top = func+aux; /* correct top */ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); ci->savedpc = L->savedpc; ci->tailcalls++; /* one more call lost */ L->ci--; /* remove new frame */ goto reentry; } case PCRC: { /* it was a C function (`precall' called it) */ base = L->base; continue; } default: { return; /* yield */ } } } case OP_RETURN: { int b = GETARG_B(i); if (b != 0) L->top = ra+b-1; if (L->openupval) luaF_close(L, base); L->savedpc = pc; b = luaD_poscall(L, ra); if (--nexeccalls == 0) /* was previous function running `here'? */ return; /* no: return */ else { /* yes: continue its execution */ if (b) L->top = L->ci->top; lua_assert(isLua(L->ci)); lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); goto reentry; } } case OP_FORLOOP: { lua_Number step = nvalue(ra+2); lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ lua_Number limit = nvalue(ra+1); if (luai_numlt(0, step) ? luai_numle(idx, limit) : luai_numle(limit, idx)) { dojump(L, pc, GETARG_sBx(i)); /* jump back */ setnvalue(ra, idx); /* update internal index... */ setnvalue(ra+3, idx); /* ...and external index */ } continue; } case OP_FORPREP: { const TValue *init = ra; const TValue *plimit = ra+1; const TValue *pstep = ra+2; L->savedpc = pc; /* next steps may throw errors */ if (!tonumber(init, ra)) luaG_runerror(L, LUA_QL("for") " initial value must be a number"); else if (!tonumber(plimit, ra+1)) luaG_runerror(L, LUA_QL("for") " limit must be a number"); else if (!tonumber(pstep, ra+2)) luaG_runerror(L, LUA_QL("for") " step must be a number"); setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); dojump(L, pc, GETARG_sBx(i)); continue; } case OP_TFORLOOP: { StkId cb = ra + 3; /* call base */ setobjs2s(L, cb+2, ra+2); setobjs2s(L, cb+1, ra+1); setobjs2s(L, cb, ra); L->top = cb+3; /* func. + 2 args (state and index) */ Protect(luaD_call(L, cb, GETARG_C(i))); L->top = L->ci->top; cb = RA(i) + 3; /* previous call may change the stack */ if (!ttisnil(cb)) { /* continue loop? */ setobjs2s(L, cb-1, cb); /* save control variable */ dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ } pc++; continue; } case OP_SETLIST: { int n = GETARG_B(i); int c = GETARG_C(i); int last; Table *h; if (n == 0) { n = cast_int(L->top - ra) - 1; L->top = L->ci->top; } if (c == 0) c = cast_int(*pc++); runtime_check(L, ttistable(ra)); h = hvalue(ra); last = ((c-1)*LFIELDS_PER_FLUSH) + n; if (last > h->sizearray) /* needs more space? */ luaH_resizearray(L, h, last); /* pre-alloc it at once */ for (; n > 0; n--) { TValue *val = ra+n; setobj2t(L, luaH_setnum(L, h, last--), val); luaC_barriert(L, h, val); } continue; } case OP_CLOSE: { luaF_close(L, ra); continue; } case OP_CLOSURE: { Proto *p; Closure *ncl; int nup, j; p = cl->p->p[GETARG_Bx(i)]; nup = p->nups; ncl = luaF_newLclosure(L, nup, cl->env); ncl->l.p = p; for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; else { lua_assert(GET_OPCODE(*pc) == OP_MOVE); ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); } } setclvalue(L, ra, ncl); Protect(luaC_checkGC(L)); continue; } case OP_VARARG: { int b = GETARG_B(i) - 1; int j; CallInfo *ci = L->ci; int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; if (b == LUA_MULTRET) { Protect(luaD_checkstack(L, n)); ra = RA(i); /* previous call may change the stack */ b = n; L->top = ra + n; } for (j = 0; j < b; j++) { if (j < n) { setobjs2s(L, ra + j, ci->base - n + j); } else { setnilvalue(ra + j); } } continue; } } } } bam-0.4.0/src/lua/COPYRIGHT0000644000175000017500000000277011430042030013210 0ustar kmakmaLua License ----------- Lua is licensed under the terms of the MIT license reproduced below. This means that Lua is free software and can be used for both academic and commercial purposes at absolutely no cost. For details and rationale, see http://www.lua.org/license.html . =============================================================================== Copyright (C) 1994-2008 Lua.org, PUC-Rio. 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. =============================================================================== (end of COPYRIGHT) bam-0.4.0/src/lua/lauxlib.c0000644000175000017500000004201111430042030013511 0ustar kmakma/* ** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ #include #include #include #include #include #include /* This file uses only the official API of Lua. ** Any function declared here could be written as an application function. */ #define lauxlib_c #define LUA_LIB #include "lua.h" #include "lauxlib.h" #define FREELIST_REF 0 /* free list of references */ /* convert a stack index to positive */ #define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ lua_gettop(L) + (i) + 1) /* ** {====================================================== ** Error-report functions ** ======================================================= */ LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { lua_Debug ar; if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); lua_getinfo(L, "n", &ar); if (strcmp(ar.namewhat, "method") == 0) { narg--; /* do not count `self' */ if (narg == 0) /* error is in the self argument itself? */ return luaL_error(L, "calling " LUA_QS " on bad self (%s)", ar.name, extramsg); } if (ar.name == NULL) ar.name = "?"; return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", narg, ar.name, extramsg); } LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { const char *msg = lua_pushfstring(L, "%s expected, got %s", tname, luaL_typename(L, narg)); return luaL_argerror(L, narg, msg); } static void tag_error (lua_State *L, int narg, int tag) { luaL_typerror(L, narg, lua_typename(L, tag)); } LUALIB_API void luaL_where (lua_State *L, int level) { lua_Debug ar; if (lua_getstack(L, level, &ar)) { /* check function at level */ lua_getinfo(L, "Sl", &ar); /* get info about it */ if (ar.currentline > 0) { /* is there info? */ lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); return; } } lua_pushliteral(L, ""); /* else, no information available... */ } LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { va_list argp; va_start(argp, fmt); luaL_where(L, 1); lua_pushvfstring(L, fmt, argp); va_end(argp); lua_concat(L, 2); return lua_error(L); } /* }====================================================== */ LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, const char *const lst[]) { const char *name = (def) ? luaL_optstring(L, narg, def) : luaL_checkstring(L, narg); int i; for (i=0; lst[i]; i++) if (strcmp(lst[i], name) == 0) return i; return luaL_argerror(L, narg, lua_pushfstring(L, "invalid option " LUA_QS, name)); } LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ if (!lua_isnil(L, -1)) /* name already in use? */ return 0; /* leave previous value on top, but return 0 */ lua_pop(L, 1); lua_newtable(L); /* create metatable */ lua_pushvalue(L, -1); lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ return 1; } LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { void *p = lua_touserdata(L, ud); if (p != NULL) { /* value is a userdata? */ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ lua_pop(L, 2); /* remove both metatables */ return p; } } } luaL_typerror(L, ud, tname); /* else error */ return NULL; /* to avoid warnings */ } LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { if (!lua_checkstack(L, space)) luaL_error(L, "stack overflow (%s)", mes); } LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { if (lua_type(L, narg) != t) tag_error(L, narg, t); } LUALIB_API void luaL_checkany (lua_State *L, int narg) { if (lua_type(L, narg) == LUA_TNONE) luaL_argerror(L, narg, "value expected"); } LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { const char *s = lua_tolstring(L, narg, len); if (!s) tag_error(L, narg, LUA_TSTRING); return s; } LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, const char *def, size_t *len) { if (lua_isnoneornil(L, narg)) { if (len) *len = (def ? strlen(def) : 0); return def; } else return luaL_checklstring(L, narg, len); } LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { lua_Number d = lua_tonumber(L, narg); if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ tag_error(L, narg, LUA_TNUMBER); return d; } LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { return luaL_opt(L, luaL_checknumber, narg, def); } LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { lua_Integer d = lua_tointeger(L, narg); if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ tag_error(L, narg, LUA_TNUMBER); return d; } LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, lua_Integer def) { return luaL_opt(L, luaL_checkinteger, narg, def); } LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { if (!lua_getmetatable(L, obj)) /* no metatable? */ return 0; lua_pushstring(L, event); lua_rawget(L, -2); if (lua_isnil(L, -1)) { lua_pop(L, 2); /* remove metatable and metafield */ return 0; } else { lua_remove(L, -2); /* remove only metatable */ return 1; } } LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { obj = abs_index(L, obj); if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ return 0; lua_pushvalue(L, obj); lua_call(L, 1, 1); return 1; } LUALIB_API void (luaL_register) (lua_State *L, const char *libname, const luaL_Reg *l) { luaI_openlib(L, libname, l, 0); } static int libsize (const luaL_Reg *l) { int size = 0; for (; l->name; l++) size++; return size; } LUALIB_API void luaI_openlib (lua_State *L, const char *libname, const luaL_Reg *l, int nup) { if (libname) { int size = libsize(l); /* check whether lib already exists */ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); lua_getfield(L, -1, libname); /* get _LOADED[libname] */ if (!lua_istable(L, -1)) { /* not found? */ lua_pop(L, 1); /* remove previous result */ /* try global variable (and create one if it does not exist) */ if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) luaL_error(L, "name conflict for module " LUA_QS, libname); lua_pushvalue(L, -1); lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ } lua_remove(L, -2); /* remove _LOADED table */ lua_insert(L, -(nup+1)); /* move library table to below upvalues */ } for (; l->name; l++) { int i; for (i=0; ifunc, nup); lua_setfield(L, -(nup+2), l->name); } lua_pop(L, nup); /* remove upvalues */ } /* ** {====================================================== ** getn-setn: size for arrays ** ======================================================= */ #if defined(LUA_COMPAT_GETN) static int checkint (lua_State *L, int topop) { int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; lua_pop(L, topop); return n; } static void getsizes (lua_State *L) { lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); if (lua_isnil(L, -1)) { /* no `size' table? */ lua_pop(L, 1); /* remove nil */ lua_newtable(L); /* create it */ lua_pushvalue(L, -1); /* `size' will be its own metatable */ lua_setmetatable(L, -2); lua_pushliteral(L, "kv"); lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ lua_pushvalue(L, -1); lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ } } LUALIB_API void luaL_setn (lua_State *L, int t, int n) { t = abs_index(L, t); lua_pushliteral(L, "n"); lua_rawget(L, t); if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ lua_pushliteral(L, "n"); /* use it */ lua_pushinteger(L, n); lua_rawset(L, t); } else { /* use `sizes' */ getsizes(L); lua_pushvalue(L, t); lua_pushinteger(L, n); lua_rawset(L, -3); /* sizes[t] = n */ lua_pop(L, 1); /* remove `sizes' */ } } LUALIB_API int luaL_getn (lua_State *L, int t) { int n; t = abs_index(L, t); lua_pushliteral(L, "n"); /* try t.n */ lua_rawget(L, t); if ((n = checkint(L, 1)) >= 0) return n; getsizes(L); /* else try sizes[t] */ lua_pushvalue(L, t); lua_rawget(L, -2); if ((n = checkint(L, 2)) >= 0) return n; return (int)lua_objlen(L, t); } #endif /* }====================================================== */ LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, const char *r) { const char *wild; size_t l = strlen(p); luaL_Buffer b; luaL_buffinit(L, &b); while ((wild = strstr(s, p)) != NULL) { luaL_addlstring(&b, s, wild - s); /* push prefix */ luaL_addstring(&b, r); /* push replacement in place of pattern */ s = wild + l; /* continue after `p' */ } luaL_addstring(&b, s); /* push last suffix */ luaL_pushresult(&b); return lua_tostring(L, -1); } LUALIB_API const char *luaL_findtable (lua_State *L, int idx, const char *fname, int szhint) { const char *e; lua_pushvalue(L, idx); do { e = strchr(fname, '.'); if (e == NULL) e = fname + strlen(fname); lua_pushlstring(L, fname, e - fname); lua_rawget(L, -2); if (lua_isnil(L, -1)) { /* no such field? */ lua_pop(L, 1); /* remove this nil */ lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ lua_pushlstring(L, fname, e - fname); lua_pushvalue(L, -2); lua_settable(L, -4); /* set new table into field */ } else if (!lua_istable(L, -1)) { /* field has a non-table value? */ lua_pop(L, 2); /* remove table and value */ return fname; /* return problematic part of the name */ } lua_remove(L, -2); /* remove previous table */ fname = e + 1; } while (*e == '.'); return NULL; } /* ** {====================================================== ** Generic Buffer manipulation ** ======================================================= */ #define bufflen(B) ((B)->p - (B)->buffer) #define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) #define LIMIT (LUA_MINSTACK/2) static int emptybuffer (luaL_Buffer *B) { size_t l = bufflen(B); if (l == 0) return 0; /* put nothing on stack */ else { lua_pushlstring(B->L, B->buffer, l); B->p = B->buffer; B->lvl++; return 1; } } static void adjuststack (luaL_Buffer *B) { if (B->lvl > 1) { lua_State *L = B->L; int toget = 1; /* number of levels to concat */ size_t toplen = lua_strlen(L, -1); do { size_t l = lua_strlen(L, -(toget+1)); if (B->lvl - toget + 1 >= LIMIT || toplen > l) { toplen += l; toget++; } else break; } while (toget < B->lvl); lua_concat(L, toget); B->lvl = B->lvl - toget + 1; } } LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { if (emptybuffer(B)) adjuststack(B); return B->buffer; } LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { while (l--) luaL_addchar(B, *s++); } LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { luaL_addlstring(B, s, strlen(s)); } LUALIB_API void luaL_pushresult (luaL_Buffer *B) { emptybuffer(B); lua_concat(B->L, B->lvl); B->lvl = 1; } LUALIB_API void luaL_addvalue (luaL_Buffer *B) { lua_State *L = B->L; size_t vl; const char *s = lua_tolstring(L, -1, &vl); if (vl <= bufffree(B)) { /* fit into buffer? */ memcpy(B->p, s, vl); /* put it there */ B->p += vl; lua_pop(L, 1); /* remove from stack */ } else { if (emptybuffer(B)) lua_insert(L, -2); /* put buffer before new value */ B->lvl++; /* add new value into B stack */ adjuststack(B); } } LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { B->L = L; B->p = B->buffer; B->lvl = 0; } /* }====================================================== */ LUALIB_API int luaL_ref (lua_State *L, int t) { int ref; t = abs_index(L, t); if (lua_isnil(L, -1)) { lua_pop(L, 1); /* remove from stack */ return LUA_REFNIL; /* `nil' has a unique fixed reference */ } lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ lua_pop(L, 1); /* remove it from stack */ if (ref != 0) { /* any free element? */ lua_rawgeti(L, t, ref); /* remove it from list */ lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ } else { /* no free elements */ ref = (int)lua_objlen(L, t); ref++; /* create new reference */ } lua_rawseti(L, t, ref); return ref; } LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { if (ref >= 0) { t = abs_index(L, t); lua_rawgeti(L, t, FREELIST_REF); lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ lua_pushinteger(L, ref); lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ } } /* ** {====================================================== ** Load functions ** ======================================================= */ typedef struct LoadF { int extraline; FILE *f; char buff[LUAL_BUFFERSIZE]; } LoadF; static const char *getF (lua_State *L, void *ud, size_t *size) { LoadF *lf = (LoadF *)ud; (void)L; if (lf->extraline) { lf->extraline = 0; *size = 1; return "\n"; } if (feof(lf->f)) return NULL; *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); return (*size > 0) ? lf->buff : NULL; } static int errfile (lua_State *L, const char *what, int fnameindex) { const char *serr = strerror(errno); const char *filename = lua_tostring(L, fnameindex) + 1; lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); lua_remove(L, fnameindex); return LUA_ERRFILE; } LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { LoadF lf; int status, readstatus; int c; int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ lf.extraline = 0; if (filename == NULL) { lua_pushliteral(L, "=stdin"); lf.f = stdin; } else { lua_pushfstring(L, "@%s", filename); lf.f = fopen(filename, "r"); if (lf.f == NULL) return errfile(L, "open", fnameindex); } c = getc(lf.f); if (c == '#') { /* Unix exec. file? */ lf.extraline = 1; while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ if (c == '\n') c = getc(lf.f); } if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ if (lf.f == NULL) return errfile(L, "reopen", fnameindex); /* skip eventual `#!...' */ while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; lf.extraline = 0; } ungetc(c, lf.f); status = lua_load(L, getF, &lf, lua_tostring(L, -1)); readstatus = ferror(lf.f); if (filename) fclose(lf.f); /* close file (even in case of errors) */ if (readstatus) { lua_settop(L, fnameindex); /* ignore results from `lua_load' */ return errfile(L, "read", fnameindex); } lua_remove(L, fnameindex); return status; } typedef struct LoadS { const char *s; size_t size; } LoadS; static const char *getS (lua_State *L, void *ud, size_t *size) { LoadS *ls = (LoadS *)ud; (void)L; if (ls->size == 0) return NULL; *size = ls->size; ls->size = 0; return ls->s; } LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, const char *name) { LoadS ls; ls.s = buff; ls.size = size; return lua_load(L, getS, &ls, name); } LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { return luaL_loadbuffer(L, s, strlen(s), s); } /* }====================================================== */ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { (void)ud; (void)osize; if (nsize == 0) { free(ptr); return NULL; } else return realloc(ptr, nsize); } static int panic (lua_State *L) { (void)L; /* to avoid warnings */ fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1)); return 0; } LUALIB_API lua_State *luaL_newstate (void) { lua_State *L = lua_newstate(l_alloc, NULL); if (L) lua_atpanic(L, &panic); return L; } bam-0.4.0/src/lua/lbaselib.c0000644000175000017500000004122611430042030013635 0ustar kmakma/* ** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ ** Basic library ** See Copyright Notice in lua.h */ #include #include #include #include #define lbaselib_c #define LUA_LIB #include "lua.h" #include "lauxlib.h" #include "lualib.h" /* ** If your system does not support `stdout', you can just remove this function. ** If you need, you can define your own `print' function, following this ** model but changing `fputs' to put the strings at a proper place ** (a console window or a log file, for instance). */ static int luaB_print (lua_State *L) { int n = lua_gettop(L); /* number of arguments */ int i; lua_getglobal(L, "tostring"); for (i=1; i<=n; i++) { const char *s; lua_pushvalue(L, -1); /* function to be called */ lua_pushvalue(L, i); /* value to print */ lua_call(L, 1, 1); s = lua_tostring(L, -1); /* get result */ if (s == NULL) return luaL_error(L, LUA_QL("tostring") " must return a string to " LUA_QL("print")); if (i>1) fputs("\t", stdout); fputs(s, stdout); lua_pop(L, 1); /* pop result */ } fputs("\n", stdout); return 0; } static int luaB_tonumber (lua_State *L) { int base = luaL_optint(L, 2, 10); if (base == 10) { /* standard conversion */ luaL_checkany(L, 1); if (lua_isnumber(L, 1)) { lua_pushnumber(L, lua_tonumber(L, 1)); return 1; } } else { const char *s1 = luaL_checkstring(L, 1); char *s2; unsigned long n; luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); n = strtoul(s1, &s2, base); if (s1 != s2) { /* at least one valid digit? */ while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ if (*s2 == '\0') { /* no invalid trailing characters? */ lua_pushnumber(L, (lua_Number)n); return 1; } } } lua_pushnil(L); /* else not a number */ return 1; } static int luaB_error (lua_State *L) { int level = luaL_optint(L, 2, 1); lua_settop(L, 1); if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ luaL_where(L, level); lua_pushvalue(L, 1); lua_concat(L, 2); } return lua_error(L); } static int luaB_getmetatable (lua_State *L) { luaL_checkany(L, 1); if (!lua_getmetatable(L, 1)) { lua_pushnil(L); return 1; /* no metatable */ } luaL_getmetafield(L, 1, "__metatable"); return 1; /* returns either __metatable field (if present) or metatable */ } static int luaB_setmetatable (lua_State *L) { int t = lua_type(L, 2); luaL_checktype(L, 1, LUA_TTABLE); luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table expected"); if (luaL_getmetafield(L, 1, "__metatable")) luaL_error(L, "cannot change a protected metatable"); lua_settop(L, 2); lua_setmetatable(L, 1); return 1; } static void getfunc (lua_State *L, int opt) { if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); else { lua_Debug ar; int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); if (lua_getstack(L, level, &ar) == 0) luaL_argerror(L, 1, "invalid level"); lua_getinfo(L, "f", &ar); if (lua_isnil(L, -1)) luaL_error(L, "no function environment for tail call at level %d", level); } } static int luaB_getfenv (lua_State *L) { getfunc(L, 1); if (lua_iscfunction(L, -1)) /* is a C function? */ lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ else lua_getfenv(L, -1); return 1; } static int luaB_setfenv (lua_State *L) { luaL_checktype(L, 2, LUA_TTABLE); getfunc(L, 0); lua_pushvalue(L, 2); if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { /* change environment of current thread */ lua_pushthread(L); lua_insert(L, -2); lua_setfenv(L, -2); return 0; } else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) luaL_error(L, LUA_QL("setfenv") " cannot change environment of given object"); return 1; } static int luaB_rawequal (lua_State *L) { luaL_checkany(L, 1); luaL_checkany(L, 2); lua_pushboolean(L, lua_rawequal(L, 1, 2)); return 1; } static int luaB_rawget (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); luaL_checkany(L, 2); lua_settop(L, 2); lua_rawget(L, 1); return 1; } static int luaB_rawset (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); luaL_checkany(L, 2); luaL_checkany(L, 3); lua_settop(L, 3); lua_rawset(L, 1); return 1; } static int luaB_gcinfo (lua_State *L) { lua_pushinteger(L, lua_getgccount(L)); return 1; } static int luaB_collectgarbage (lua_State *L) { static const char *const opts[] = {"stop", "restart", "collect", "count", "step", "setpause", "setstepmul", NULL}; static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; int o = luaL_checkoption(L, 1, "collect", opts); int ex = luaL_optint(L, 2, 0); int res = lua_gc(L, optsnum[o], ex); switch (optsnum[o]) { case LUA_GCCOUNT: { int b = lua_gc(L, LUA_GCCOUNTB, 0); lua_pushnumber(L, res + ((lua_Number)b/1024)); return 1; } case LUA_GCSTEP: { lua_pushboolean(L, res); return 1; } default: { lua_pushnumber(L, res); return 1; } } } static int luaB_type (lua_State *L) { luaL_checkany(L, 1); lua_pushstring(L, luaL_typename(L, 1)); return 1; } static int luaB_next (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 2); /* create a 2nd argument if there isn't one */ if (lua_next(L, 1)) return 2; else { lua_pushnil(L); return 1; } } static int luaB_pairs (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ lua_pushvalue(L, 1); /* state, */ lua_pushnil(L); /* and initial value */ return 3; } static int ipairsaux (lua_State *L) { int i = luaL_checkint(L, 2); luaL_checktype(L, 1, LUA_TTABLE); i++; /* next value */ lua_pushinteger(L, i); lua_rawgeti(L, 1, i); return (lua_isnil(L, -1)) ? 0 : 2; } static int luaB_ipairs (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ lua_pushvalue(L, 1); /* state, */ lua_pushinteger(L, 0); /* and initial value */ return 3; } static int load_aux (lua_State *L, int status) { if (status == 0) /* OK? */ return 1; else { lua_pushnil(L); lua_insert(L, -2); /* put before error message */ return 2; /* return nil plus error message */ } } static int luaB_loadstring (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); const char *chunkname = luaL_optstring(L, 2, s); return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); } static int luaB_loadfile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); return load_aux(L, luaL_loadfile(L, fname)); } /* ** Reader for generic `load' function: `lua_load' uses the ** stack for internal stuff, so the reader cannot change the ** stack top. Instead, it keeps its resulting string in a ** reserved slot inside the stack. */ static const char *generic_reader (lua_State *L, void *ud, size_t *size) { (void)ud; /* to avoid warnings */ luaL_checkstack(L, 2, "too many nested functions"); lua_pushvalue(L, 1); /* get function */ lua_call(L, 0, 1); /* call it */ if (lua_isnil(L, -1)) { *size = 0; return NULL; } else if (lua_isstring(L, -1)) { lua_replace(L, 3); /* save string in a reserved stack slot */ return lua_tolstring(L, 3, size); } else luaL_error(L, "reader function must return a string"); return NULL; /* to avoid warnings */ } static int luaB_load (lua_State *L) { int status; const char *cname = luaL_optstring(L, 2, "=(load)"); luaL_checktype(L, 1, LUA_TFUNCTION); lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ status = lua_load(L, generic_reader, NULL, cname); return load_aux(L, status); } static int luaB_dofile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); int n = lua_gettop(L); if (luaL_loadfile(L, fname) != 0) lua_error(L); lua_call(L, 0, LUA_MULTRET); return lua_gettop(L) - n; } static int luaB_assert (lua_State *L) { luaL_checkany(L, 1); if (!lua_toboolean(L, 1)) return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); return lua_gettop(L); } static int luaB_unpack (lua_State *L) { int i, e, n; luaL_checktype(L, 1, LUA_TTABLE); i = luaL_optint(L, 2, 1); e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); if (i > e) return 0; /* empty range */ n = e - i + 1; /* number of elements */ if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ return luaL_error(L, "too many results to unpack"); lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ while (i++ < e) /* push arg[i + 1...e] */ lua_rawgeti(L, 1, i); return n; } static int luaB_select (lua_State *L) { int n = lua_gettop(L); if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { lua_pushinteger(L, n-1); return 1; } else { int i = luaL_checkint(L, 1); if (i < 0) i = n + i; else if (i > n) i = n; luaL_argcheck(L, 1 <= i, 1, "index out of range"); return n - i; } } static int luaB_pcall (lua_State *L) { int status; luaL_checkany(L, 1); status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); lua_pushboolean(L, (status == 0)); lua_insert(L, 1); return lua_gettop(L); /* return status + all results */ } static int luaB_xpcall (lua_State *L) { int status; luaL_checkany(L, 2); lua_settop(L, 2); lua_insert(L, 1); /* put error function under function to be called */ status = lua_pcall(L, 0, LUA_MULTRET, 1); lua_pushboolean(L, (status == 0)); lua_replace(L, 1); return lua_gettop(L); /* return status + all results */ } static int luaB_tostring (lua_State *L) { luaL_checkany(L, 1); if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ return 1; /* use its value */ switch (lua_type(L, 1)) { case LUA_TNUMBER: lua_pushstring(L, lua_tostring(L, 1)); break; case LUA_TSTRING: lua_pushvalue(L, 1); break; case LUA_TBOOLEAN: lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); break; case LUA_TNIL: lua_pushliteral(L, "nil"); break; default: lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); break; } return 1; } static int luaB_newproxy (lua_State *L) { lua_settop(L, 1); lua_newuserdata(L, 0); /* create proxy */ if (lua_toboolean(L, 1) == 0) return 1; /* no metatable */ else if (lua_isboolean(L, 1)) { lua_newtable(L); /* create a new metatable `m' ... */ lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ lua_pushboolean(L, 1); lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ } else { int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ if (lua_getmetatable(L, 1)) { lua_rawget(L, lua_upvalueindex(1)); validproxy = lua_toboolean(L, -1); lua_pop(L, 1); /* remove value */ } luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); lua_getmetatable(L, 1); /* metatable is valid; get it */ } lua_setmetatable(L, 2); return 1; } static const luaL_Reg base_funcs[] = { {"assert", luaB_assert}, {"collectgarbage", luaB_collectgarbage}, {"dofile", luaB_dofile}, {"error", luaB_error}, {"gcinfo", luaB_gcinfo}, {"getfenv", luaB_getfenv}, {"getmetatable", luaB_getmetatable}, {"loadfile", luaB_loadfile}, {"load", luaB_load}, {"loadstring", luaB_loadstring}, {"next", luaB_next}, {"pcall", luaB_pcall}, {"print", luaB_print}, {"rawequal", luaB_rawequal}, {"rawget", luaB_rawget}, {"rawset", luaB_rawset}, {"select", luaB_select}, {"setfenv", luaB_setfenv}, {"setmetatable", luaB_setmetatable}, {"tonumber", luaB_tonumber}, {"tostring", luaB_tostring}, {"type", luaB_type}, {"unpack", luaB_unpack}, {"xpcall", luaB_xpcall}, {NULL, NULL} }; /* ** {====================================================== ** Coroutine library ** ======================================================= */ #define CO_RUN 0 /* running */ #define CO_SUS 1 /* suspended */ #define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ #define CO_DEAD 3 static const char *const statnames[] = {"running", "suspended", "normal", "dead"}; static int costatus (lua_State *L, lua_State *co) { if (L == co) return CO_RUN; switch (lua_status(co)) { case LUA_YIELD: return CO_SUS; case 0: { lua_Debug ar; if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ return CO_NOR; /* it is running */ else if (lua_gettop(co) == 0) return CO_DEAD; else return CO_SUS; /* initial state */ } default: /* some error occured */ return CO_DEAD; } } static int luaB_costatus (lua_State *L) { lua_State *co = lua_tothread(L, 1); luaL_argcheck(L, co, 1, "coroutine expected"); lua_pushstring(L, statnames[costatus(L, co)]); return 1; } static int auxresume (lua_State *L, lua_State *co, int narg) { int status = costatus(L, co); if (!lua_checkstack(co, narg)) luaL_error(L, "too many arguments to resume"); if (status != CO_SUS) { lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); return -1; /* error flag */ } lua_xmove(L, co, narg); lua_setlevel(L, co); status = lua_resume(co, narg); if (status == 0 || status == LUA_YIELD) { int nres = lua_gettop(co); if (!lua_checkstack(L, nres + 1)) luaL_error(L, "too many results to resume"); lua_xmove(co, L, nres); /* move yielded values */ return nres; } else { lua_xmove(co, L, 1); /* move error message */ return -1; /* error flag */ } } static int luaB_coresume (lua_State *L) { lua_State *co = lua_tothread(L, 1); int r; luaL_argcheck(L, co, 1, "coroutine expected"); r = auxresume(L, co, lua_gettop(L) - 1); if (r < 0) { lua_pushboolean(L, 0); lua_insert(L, -2); return 2; /* return false + error message */ } else { lua_pushboolean(L, 1); lua_insert(L, -(r + 1)); return r + 1; /* return true + `resume' returns */ } } static int luaB_auxwrap (lua_State *L) { lua_State *co = lua_tothread(L, lua_upvalueindex(1)); int r = auxresume(L, co, lua_gettop(L)); if (r < 0) { if (lua_isstring(L, -1)) { /* error object is a string? */ luaL_where(L, 1); /* add extra info */ lua_insert(L, -2); lua_concat(L, 2); } lua_error(L); /* propagate error */ } return r; } static int luaB_cocreate (lua_State *L) { lua_State *NL = lua_newthread(L); luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, "Lua function expected"); lua_pushvalue(L, 1); /* move function to top */ lua_xmove(L, NL, 1); /* move function from L to NL */ return 1; } static int luaB_cowrap (lua_State *L) { luaB_cocreate(L); lua_pushcclosure(L, luaB_auxwrap, 1); return 1; } static int luaB_yield (lua_State *L) { return lua_yield(L, lua_gettop(L)); } static int luaB_corunning (lua_State *L) { if (lua_pushthread(L)) lua_pushnil(L); /* main thread is not a coroutine */ return 1; } static const luaL_Reg co_funcs[] = { {"create", luaB_cocreate}, {"resume", luaB_coresume}, {"running", luaB_corunning}, {"status", luaB_costatus}, {"wrap", luaB_cowrap}, {"yield", luaB_yield}, {NULL, NULL} }; /* }====================================================== */ static void auxopen (lua_State *L, const char *name, lua_CFunction f, lua_CFunction u) { lua_pushcfunction(L, u); lua_pushcclosure(L, f, 1); lua_setfield(L, -2, name); } static void base_open (lua_State *L) { /* set global _G */ lua_pushvalue(L, LUA_GLOBALSINDEX); lua_setglobal(L, "_G"); /* open lib into global table */ luaL_register(L, "_G", base_funcs); lua_pushliteral(L, LUA_VERSION); lua_setglobal(L, "_VERSION"); /* set global _VERSION */ /* `ipairs' and `pairs' need auxliliary functions as upvalues */ auxopen(L, "ipairs", luaB_ipairs, ipairsaux); auxopen(L, "pairs", luaB_pairs, luaB_next); /* `newproxy' needs a weaktable as upvalue */ lua_createtable(L, 0, 1); /* new table `w' */ lua_pushvalue(L, -1); /* `w' will be its own metatable */ lua_setmetatable(L, -2); lua_pushliteral(L, "kv"); lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ lua_pushcclosure(L, luaB_newproxy, 1); lua_setglobal(L, "newproxy"); /* set global `newproxy' */ } LUALIB_API int luaopen_base (lua_State *L) { base_open(L); luaL_register(L, LUA_COLIBNAME, co_funcs); return 2; } bam-0.4.0/src/lua/lstrlib.c0000644000175000017500000005567111430042030013544 0ustar kmakma/* ** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ #include #include #include #include #include #define lstrlib_c #define LUA_LIB #include "lua.h" #include "lauxlib.h" #include "lualib.h" /* macro to `unsign' a character */ #define uchar(c) ((unsigned char)(c)) static int str_len (lua_State *L) { size_t l; luaL_checklstring(L, 1, &l); lua_pushinteger(L, l); return 1; } static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { /* relative string position: negative means back from end */ if (pos < 0) pos += (ptrdiff_t)len + 1; return (pos >= 0) ? pos : 0; } static int str_sub (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); if (start < 1) start = 1; if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; if (start <= end) lua_pushlstring(L, s+start-1, end-start+1); else lua_pushliteral(L, ""); return 1; } static int str_reverse (lua_State *L) { size_t l; luaL_Buffer b; const char *s = luaL_checklstring(L, 1, &l); luaL_buffinit(L, &b); while (l--) luaL_addchar(&b, s[l]); luaL_pushresult(&b); return 1; } static int str_lower (lua_State *L) { size_t l; size_t i; luaL_Buffer b; const char *s = luaL_checklstring(L, 1, &l); luaL_buffinit(L, &b); for (i=0; i 0) luaL_addlstring(&b, s, l); luaL_pushresult(&b); return 1; } static int str_byte (lua_State *L) { size_t l; const char *s = luaL_checklstring(L, 1, &l); ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); int n, i; if (posi <= 0) posi = 1; if ((size_t)pose > l) pose = l; if (posi > pose) return 0; /* empty interval; return no values */ n = (int)(pose - posi + 1); if (posi + n <= pose) /* overflow? */ luaL_error(L, "string slice too long"); luaL_checkstack(L, n, "string slice too long"); for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) return luaL_error(ms->L, "invalid capture index"); return l; } static int capture_to_close (MatchState *ms) { int level = ms->level; for (level--; level>=0; level--) if (ms->capture[level].len == CAP_UNFINISHED) return level; return luaL_error(ms->L, "invalid pattern capture"); } static const char *classend (MatchState *ms, const char *p) { switch (*p++) { case L_ESC: { if (*p == '\0') luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); return p+1; } case '[': { if (*p == '^') p++; do { /* look for a `]' */ if (*p == '\0') luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); if (*(p++) == L_ESC && *p != '\0') p++; /* skip escapes (e.g. `%]') */ } while (*p != ']'); return p+1; } default: { return p; } } } static int match_class (int c, int cl) { int res; switch (tolower(cl)) { case 'a' : res = isalpha(c); break; case 'c' : res = iscntrl(c); break; case 'd' : res = isdigit(c); break; case 'l' : res = islower(c); break; case 'p' : res = ispunct(c); break; case 's' : res = isspace(c); break; case 'u' : res = isupper(c); break; case 'w' : res = isalnum(c); break; case 'x' : res = isxdigit(c); break; case 'z' : res = (c == 0); break; default: return (cl == c); } return (islower(cl) ? res : !res); } static int matchbracketclass (int c, const char *p, const char *ec) { int sig = 1; if (*(p+1) == '^') { sig = 0; p++; /* skip the `^' */ } while (++p < ec) { if (*p == L_ESC) { p++; if (match_class(c, uchar(*p))) return sig; } else if ((*(p+1) == '-') && (p+2 < ec)) { p+=2; if (uchar(*(p-2)) <= c && c <= uchar(*p)) return sig; } else if (uchar(*p) == c) return sig; } return !sig; } static int singlematch (int c, const char *p, const char *ep) { switch (*p) { case '.': return 1; /* matches any char */ case L_ESC: return match_class(c, uchar(*(p+1))); case '[': return matchbracketclass(c, p, ep-1); default: return (uchar(*p) == c); } } static const char *match (MatchState *ms, const char *s, const char *p); static const char *matchbalance (MatchState *ms, const char *s, const char *p) { if (*p == 0 || *(p+1) == 0) luaL_error(ms->L, "unbalanced pattern"); if (*s != *p) return NULL; else { int b = *p; int e = *(p+1); int cont = 1; while (++s < ms->src_end) { if (*s == e) { if (--cont == 0) return s+1; } else if (*s == b) cont++; } } return NULL; /* string ends out of balance */ } static const char *max_expand (MatchState *ms, const char *s, const char *p, const char *ep) { ptrdiff_t i = 0; /* counts maximum expand for item */ while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) i++; /* keeps trying to match with the maximum repetitions */ while (i>=0) { const char *res = match(ms, (s+i), ep+1); if (res) return res; i--; /* else didn't match; reduce 1 repetition to try again */ } return NULL; } static const char *min_expand (MatchState *ms, const char *s, const char *p, const char *ep) { for (;;) { const char *res = match(ms, s, ep+1); if (res != NULL) return res; else if (ssrc_end && singlematch(uchar(*s), p, ep)) s++; /* try with one more repetition */ else return NULL; } } static const char *start_capture (MatchState *ms, const char *s, const char *p, int what) { const char *res; int level = ms->level; if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); ms->capture[level].init = s; ms->capture[level].len = what; ms->level = level+1; if ((res=match(ms, s, p)) == NULL) /* match failed? */ ms->level--; /* undo capture */ return res; } static const char *end_capture (MatchState *ms, const char *s, const char *p) { int l = capture_to_close(ms); const char *res; ms->capture[l].len = s - ms->capture[l].init; /* close capture */ if ((res = match(ms, s, p)) == NULL) /* match failed? */ ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ return res; } static const char *match_capture (MatchState *ms, const char *s, int l) { size_t len; l = check_capture(ms, l); len = ms->capture[l].len; if ((size_t)(ms->src_end-s) >= len && memcmp(ms->capture[l].init, s, len) == 0) return s+len; else return NULL; } static const char *match (MatchState *ms, const char *s, const char *p) { init: /* using goto's to optimize tail recursion */ switch (*p) { case '(': { /* start capture */ if (*(p+1) == ')') /* position capture? */ return start_capture(ms, s, p+2, CAP_POSITION); else return start_capture(ms, s, p+1, CAP_UNFINISHED); } case ')': { /* end capture */ return end_capture(ms, s, p+1); } case L_ESC: { switch (*(p+1)) { case 'b': { /* balanced string? */ s = matchbalance(ms, s, p+2); if (s == NULL) return NULL; p+=4; goto init; /* else return match(ms, s, p+4); */ } case 'f': { /* frontier? */ const char *ep; char previous; p += 2; if (*p != '[') luaL_error(ms->L, "missing " LUA_QL("[") " after " LUA_QL("%%f") " in pattern"); ep = classend(ms, p); /* points to what is next */ previous = (s == ms->src_init) ? '\0' : *(s-1); if (matchbracketclass(uchar(previous), p, ep-1) || !matchbracketclass(uchar(*s), p, ep-1)) return NULL; p=ep; goto init; /* else return match(ms, s, ep); */ } default: { if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ s = match_capture(ms, s, uchar(*(p+1))); if (s == NULL) return NULL; p+=2; goto init; /* else return match(ms, s, p+2) */ } goto dflt; /* case default */ } } } case '\0': { /* end of pattern */ return s; /* match succeeded */ } case '$': { if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ return (s == ms->src_end) ? s : NULL; /* check end of string */ else goto dflt; } default: dflt: { /* it is a pattern item */ const char *ep = classend(ms, p); /* points to what is next */ int m = ssrc_end && singlematch(uchar(*s), p, ep); switch (*ep) { case '?': { /* optional */ const char *res; if (m && ((res=match(ms, s+1, ep+1)) != NULL)) return res; p=ep+1; goto init; /* else return match(ms, s, ep+1); */ } case '*': { /* 0 or more repetitions */ return max_expand(ms, s, p, ep); } case '+': { /* 1 or more repetitions */ return (m ? max_expand(ms, s+1, p, ep) : NULL); } case '-': { /* 0 or more repetitions (minimum) */ return min_expand(ms, s, p, ep); } default: { if (!m) return NULL; s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ } } } } } static const char *lmemfind (const char *s1, size_t l1, const char *s2, size_t l2) { if (l2 == 0) return s1; /* empty strings are everywhere */ else if (l2 > l1) return NULL; /* avoids a negative `l1' */ else { const char *init; /* to search for a `*s2' inside `s1' */ l2--; /* 1st char will be checked by `memchr' */ l1 = l1-l2; /* `s2' cannot be found after that */ while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { init++; /* 1st char is already checked */ if (memcmp(init, s2+1, l2) == 0) return init-1; else { /* correct `l1' and `s1' to try again */ l1 -= init-s1; s1 = init; } } return NULL; /* not found */ } } static void push_onecapture (MatchState *ms, int i, const char *s, const char *e) { if (i >= ms->level) { if (i == 0) /* ms->level == 0, too */ lua_pushlstring(ms->L, s, e - s); /* add whole match */ else luaL_error(ms->L, "invalid capture index"); } else { ptrdiff_t l = ms->capture[i].len; if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); if (l == CAP_POSITION) lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); else lua_pushlstring(ms->L, ms->capture[i].init, l); } } static int push_captures (MatchState *ms, const char *s, const char *e) { int i; int nlevels = (ms->level == 0 && s) ? 1 : ms->level; luaL_checkstack(ms->L, nlevels, "too many captures"); for (i = 0; i < nlevels; i++) push_onecapture(ms, i, s, e); return nlevels; /* number of strings pushed */ } static int str_find_aux (lua_State *L, int find) { size_t l1, l2; const char *s = luaL_checklstring(L, 1, &l1); const char *p = luaL_checklstring(L, 2, &l2); ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; if (init < 0) init = 0; else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; if (find && (lua_toboolean(L, 4) || /* explicit request? */ strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ /* do a plain search */ const char *s2 = lmemfind(s+init, l1-init, p, l2); if (s2) { lua_pushinteger(L, s2-s+1); lua_pushinteger(L, s2-s+l2); return 2; } } else { MatchState ms; int anchor = (*p == '^') ? (p++, 1) : 0; const char *s1=s+init; ms.L = L; ms.src_init = s; ms.src_end = s+l1; do { const char *res; ms.level = 0; if ((res=match(&ms, s1, p)) != NULL) { if (find) { lua_pushinteger(L, s1-s+1); /* start */ lua_pushinteger(L, res-s); /* end */ return push_captures(&ms, NULL, 0) + 2; } else return push_captures(&ms, s1, res); } } while (s1++ < ms.src_end && !anchor); } lua_pushnil(L); /* not found */ return 1; } static int str_find (lua_State *L) { return str_find_aux(L, 1); } static int str_match (lua_State *L) { return str_find_aux(L, 0); } static int gmatch_aux (lua_State *L) { MatchState ms; size_t ls; const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); const char *p = lua_tostring(L, lua_upvalueindex(2)); const char *src; ms.L = L; ms.src_init = s; ms.src_end = s+ls; for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); src <= ms.src_end; src++) { const char *e; ms.level = 0; if ((e = match(&ms, src, p)) != NULL) { lua_Integer newstart = e-s; if (e == src) newstart++; /* empty match? go at least one position */ lua_pushinteger(L, newstart); lua_replace(L, lua_upvalueindex(3)); return push_captures(&ms, src, e); } } return 0; /* not found */ } static int gmatch (lua_State *L) { luaL_checkstring(L, 1); luaL_checkstring(L, 2); lua_settop(L, 2); lua_pushinteger(L, 0); lua_pushcclosure(L, gmatch_aux, 3); return 1; } static int gfind_nodef (lua_State *L) { return luaL_error(L, LUA_QL("string.gfind") " was renamed to " LUA_QL("string.gmatch")); } static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { size_t l, i; const char *news = lua_tolstring(ms->L, 3, &l); for (i = 0; i < l; i++) { if (news[i] != L_ESC) luaL_addchar(b, news[i]); else { i++; /* skip ESC */ if (!isdigit(uchar(news[i]))) luaL_addchar(b, news[i]); else if (news[i] == '0') luaL_addlstring(b, s, e - s); else { push_onecapture(ms, news[i] - '1', s, e); luaL_addvalue(b); /* add capture to accumulated result */ } } } } static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, const char *e) { lua_State *L = ms->L; switch (lua_type(L, 3)) { case LUA_TNUMBER: case LUA_TSTRING: { add_s(ms, b, s, e); return; } case LUA_TFUNCTION: { int n; lua_pushvalue(L, 3); n = push_captures(ms, s, e); lua_call(L, n, 1); break; } case LUA_TTABLE: { push_onecapture(ms, 0, s, e); lua_gettable(L, 3); break; } } if (!lua_toboolean(L, -1)) { /* nil or false? */ lua_pop(L, 1); lua_pushlstring(L, s, e - s); /* keep original text */ } else if (!lua_isstring(L, -1)) luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); luaL_addvalue(b); /* add result to accumulator */ } static int str_gsub (lua_State *L) { size_t srcl; const char *src = luaL_checklstring(L, 1, &srcl); const char *p = luaL_checkstring(L, 2); int tr = lua_type(L, 3); int max_s = luaL_optint(L, 4, srcl+1); int anchor = (*p == '^') ? (p++, 1) : 0; int n = 0; MatchState ms; luaL_Buffer b; luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, "string/function/table expected"); luaL_buffinit(L, &b); ms.L = L; ms.src_init = src; ms.src_end = src+srcl; while (n < max_s) { const char *e; ms.level = 0; e = match(&ms, src, p); if (e) { n++; add_value(&ms, &b, src, e); } if (e && e>src) /* non empty match? */ src = e; /* skip it */ else if (src < ms.src_end) luaL_addchar(&b, *src++); else break; if (anchor) break; } luaL_addlstring(&b, src, ms.src_end-src); luaL_pushresult(&b); lua_pushinteger(L, n); /* number of substitutions */ return 2; } /* }====================================================== */ /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ #define MAX_ITEM 512 /* valid flags in a format specification */ #define FLAGS "-+ #0" /* ** maximum size of each format specification (such as '%-099.99d') ** (+10 accounts for %99.99x plus margin of error) */ #define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { size_t l; const char *s = luaL_checklstring(L, arg, &l); luaL_addchar(b, '"'); while (l--) { switch (*s) { case '"': case '\\': case '\n': { luaL_addchar(b, '\\'); luaL_addchar(b, *s); break; } case '\r': { luaL_addlstring(b, "\\r", 2); break; } case '\0': { luaL_addlstring(b, "\\000", 4); break; } default: { luaL_addchar(b, *s); break; } } s++; } luaL_addchar(b, '"'); } static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { const char *p = strfrmt; while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) luaL_error(L, "invalid format (repeated flags)"); if (isdigit(uchar(*p))) p++; /* skip width */ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ if (*p == '.') { p++; if (isdigit(uchar(*p))) p++; /* skip precision */ if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ } if (isdigit(uchar(*p))) luaL_error(L, "invalid format (width or precision too long)"); *(form++) = '%'; strncpy(form, strfrmt, p - strfrmt + 1); form += p - strfrmt + 1; *form = '\0'; return p; } static void addintlen (char *form) { size_t l = strlen(form); char spec = form[l - 1]; strcpy(form + l - 1, LUA_INTFRMLEN); form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; } static int str_format (lua_State *L) { int arg = 1; size_t sfl; const char *strfrmt = luaL_checklstring(L, arg, &sfl); const char *strfrmt_end = strfrmt+sfl; luaL_Buffer b; luaL_buffinit(L, &b); while (strfrmt < strfrmt_end) { if (*strfrmt != L_ESC) luaL_addchar(&b, *strfrmt++); else if (*++strfrmt == L_ESC) luaL_addchar(&b, *strfrmt++); /* %% */ else { /* format item */ char form[MAX_FORMAT]; /* to store the format (`%...') */ char buff[MAX_ITEM]; /* to store the formatted item */ arg++; strfrmt = scanformat(L, strfrmt, form); switch (*strfrmt++) { case 'c': { sprintf(buff, form, (int)luaL_checknumber(L, arg)); break; } case 'd': case 'i': { addintlen(form); sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); break; } case 'o': case 'u': case 'x': case 'X': { addintlen(form); sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); break; } case 'e': case 'E': case 'f': case 'g': case 'G': { sprintf(buff, form, (double)luaL_checknumber(L, arg)); break; } case 'q': { addquoted(L, &b, arg); continue; /* skip the 'addsize' at the end */ } case 's': { size_t l; const char *s = luaL_checklstring(L, arg, &l); if (!strchr(form, '.') && l >= 100) { /* no precision and string is too long to be formatted; keep original string */ lua_pushvalue(L, arg); luaL_addvalue(&b); continue; /* skip the `addsize' at the end */ } else { sprintf(buff, form, s); break; } } default: { /* also treat cases `pnLlh' */ return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " LUA_QL("format"), *(strfrmt - 1)); } } luaL_addlstring(&b, buff, strlen(buff)); } } luaL_pushresult(&b); return 1; } static const luaL_Reg strlib[] = { {"byte", str_byte}, {"char", str_char}, {"dump", str_dump}, {"find", str_find}, {"format", str_format}, {"gfind", gfind_nodef}, {"gmatch", gmatch}, {"gsub", str_gsub}, {"len", str_len}, {"lower", str_lower}, {"match", str_match}, {"rep", str_rep}, {"reverse", str_reverse}, {"sub", str_sub}, {"upper", str_upper}, {NULL, NULL} }; static void createmetatable (lua_State *L) { lua_createtable(L, 0, 1); /* create metatable for strings */ lua_pushliteral(L, ""); /* dummy string */ lua_pushvalue(L, -2); lua_setmetatable(L, -2); /* set string metatable */ lua_pop(L, 1); /* pop dummy string */ lua_pushvalue(L, -2); /* string library... */ lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ lua_pop(L, 1); /* pop metatable */ } /* ** Open string library */ LUALIB_API int luaopen_string (lua_State *L) { luaL_register(L, LUA_STRLIBNAME, strlib); #if defined(LUA_COMPAT_GFIND) lua_getfield(L, -1, "gmatch"); lua_setfield(L, -2, "gfind"); #endif createmetatable(L); return 1; } bam-0.4.0/src/lua/ldump.c0000644000175000017500000000605211430042030013177 0ustar kmakma/* ** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ ** save precompiled Lua chunks ** See Copyright Notice in lua.h */ #include #define ldump_c #define LUA_CORE #include "lua.h" #include "lobject.h" #include "lstate.h" #include "lundump.h" typedef struct { lua_State* L; lua_Writer writer; void* data; int strip; int status; } DumpState; #define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) #define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) static void DumpBlock(const void* b, size_t size, DumpState* D) { if (D->status==0) { lua_unlock(D->L); D->status=(*D->writer)(D->L,b,size,D->data); lua_lock(D->L); } } static void DumpChar(int y, DumpState* D) { char x=(char)y; DumpVar(x,D); } static void DumpInt(int x, DumpState* D) { DumpVar(x,D); } static void DumpNumber(lua_Number x, DumpState* D) { DumpVar(x,D); } static void DumpVector(const void* b, int n, size_t size, DumpState* D) { DumpInt(n,D); DumpMem(b,n,size,D); } static void DumpString(const TString* s, DumpState* D) { if (s==NULL || getstr(s)==NULL) { size_t size=0; DumpVar(size,D); } else { size_t size=s->tsv.len+1; /* include trailing '\0' */ DumpVar(size,D); DumpBlock(getstr(s),size,D); } } #define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) static void DumpFunction(const Proto* f, const TString* p, DumpState* D); static void DumpConstants(const Proto* f, DumpState* D) { int i,n=f->sizek; DumpInt(n,D); for (i=0; ik[i]; DumpChar(ttype(o),D); switch (ttype(o)) { case LUA_TNIL: break; case LUA_TBOOLEAN: DumpChar(bvalue(o),D); break; case LUA_TNUMBER: DumpNumber(nvalue(o),D); break; case LUA_TSTRING: DumpString(rawtsvalue(o),D); break; default: lua_assert(0); /* cannot happen */ break; } } n=f->sizep; DumpInt(n,D); for (i=0; ip[i],f->source,D); } static void DumpDebug(const Proto* f, DumpState* D) { int i,n; n= (D->strip) ? 0 : f->sizelineinfo; DumpVector(f->lineinfo,n,sizeof(int),D); n= (D->strip) ? 0 : f->sizelocvars; DumpInt(n,D); for (i=0; ilocvars[i].varname,D); DumpInt(f->locvars[i].startpc,D); DumpInt(f->locvars[i].endpc,D); } n= (D->strip) ? 0 : f->sizeupvalues; DumpInt(n,D); for (i=0; iupvalues[i],D); } static void DumpFunction(const Proto* f, const TString* p, DumpState* D) { DumpString((f->source==p || D->strip) ? NULL : f->source,D); DumpInt(f->linedefined,D); DumpInt(f->lastlinedefined,D); DumpChar(f->nups,D); DumpChar(f->numparams,D); DumpChar(f->is_vararg,D); DumpChar(f->maxstacksize,D); DumpCode(f,D); DumpConstants(f,D); DumpDebug(f,D); } static void DumpHeader(DumpState* D) { char h[LUAC_HEADERSIZE]; luaU_header(h); DumpBlock(h,LUAC_HEADERSIZE,D); } /* ** dump Lua function as precompiled chunk */ int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) { DumpState D; D.L=L; D.writer=w; D.data=data; D.strip=strip; D.status=0; DumpHeader(&D); DumpFunction(f,NULL,&D); return D.status; } bam-0.4.0/src/lua/loslib.c0000644000175000017500000001355011430042030013343 0ustar kmakma/* ** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ ** Standard Operating System library ** See Copyright Notice in lua.h */ #include #include #include #include #include #define loslib_c #define LUA_LIB #include "lua.h" #include "lauxlib.h" #include "lualib.h" static int os_pushresult (lua_State *L, int i, const char *filename) { int en = errno; /* calls to Lua API may change this value */ if (i) { lua_pushboolean(L, 1); return 1; } else { lua_pushnil(L); lua_pushfstring(L, "%s: %s", filename, strerror(en)); lua_pushinteger(L, en); return 3; } } static int os_execute (lua_State *L) { lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); return 1; } static int os_remove (lua_State *L) { const char *filename = luaL_checkstring(L, 1); return os_pushresult(L, remove(filename) == 0, filename); } static int os_rename (lua_State *L) { const char *fromname = luaL_checkstring(L, 1); const char *toname = luaL_checkstring(L, 2); return os_pushresult(L, rename(fromname, toname) == 0, fromname); } static int os_tmpname (lua_State *L) { char buff[LUA_TMPNAMBUFSIZE]; int err; lua_tmpnam(buff, err); if (err) return luaL_error(L, "unable to generate a unique filename"); lua_pushstring(L, buff); return 1; } static int os_getenv (lua_State *L) { lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ return 1; } static int os_clock (lua_State *L) { lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); return 1; } /* ** {====================================================== ** Time/Date operations ** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, ** wday=%w+1, yday=%j, isdst=? } ** ======================================================= */ static void setfield (lua_State *L, const char *key, int value) { lua_pushinteger(L, value); lua_setfield(L, -2, key); } static void setboolfield (lua_State *L, const char *key, int value) { if (value < 0) /* undefined? */ return; /* does not set field */ lua_pushboolean(L, value); lua_setfield(L, -2, key); } static int getboolfield (lua_State *L, const char *key) { int res; lua_getfield(L, -1, key); res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); lua_pop(L, 1); return res; } static int getfield (lua_State *L, const char *key, int d) { int res; lua_getfield(L, -1, key); if (lua_isnumber(L, -1)) res = (int)lua_tointeger(L, -1); else { if (d < 0) return luaL_error(L, "field " LUA_QS " missing in date table", key); res = d; } lua_pop(L, 1); return res; } static int os_date (lua_State *L) { const char *s = luaL_optstring(L, 1, "%c"); time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); struct tm *stm; if (*s == '!') { /* UTC? */ stm = gmtime(&t); s++; /* skip `!' */ } else stm = localtime(&t); if (stm == NULL) /* invalid date? */ lua_pushnil(L); else if (strcmp(s, "*t") == 0) { lua_createtable(L, 0, 9); /* 9 = number of fields */ setfield(L, "sec", stm->tm_sec); setfield(L, "min", stm->tm_min); setfield(L, "hour", stm->tm_hour); setfield(L, "day", stm->tm_mday); setfield(L, "month", stm->tm_mon+1); setfield(L, "year", stm->tm_year+1900); setfield(L, "wday", stm->tm_wday+1); setfield(L, "yday", stm->tm_yday+1); setboolfield(L, "isdst", stm->tm_isdst); } else { char cc[3]; luaL_Buffer b; cc[0] = '%'; cc[2] = '\0'; luaL_buffinit(L, &b); for (; *s; s++) { if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ luaL_addchar(&b, *s); else { size_t reslen; char buff[200]; /* should be big enough for any conversion result */ cc[1] = *(++s); reslen = strftime(buff, sizeof(buff), cc, stm); luaL_addlstring(&b, buff, reslen); } } luaL_pushresult(&b); } return 1; } static int os_time (lua_State *L) { time_t t; if (lua_isnoneornil(L, 1)) /* called without args? */ t = time(NULL); /* get current time */ else { struct tm ts; luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 1); /* make sure table is at the top */ ts.tm_sec = getfield(L, "sec", 0); ts.tm_min = getfield(L, "min", 0); ts.tm_hour = getfield(L, "hour", 12); ts.tm_mday = getfield(L, "day", -1); ts.tm_mon = getfield(L, "month", -1) - 1; ts.tm_year = getfield(L, "year", -1) - 1900; ts.tm_isdst = getboolfield(L, "isdst"); t = mktime(&ts); } if (t == (time_t)(-1)) lua_pushnil(L); else lua_pushnumber(L, (lua_Number)t); return 1; } static int os_difftime (lua_State *L) { lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), (time_t)(luaL_optnumber(L, 2, 0)))); return 1; } /* }====================================================== */ static int os_setlocale (lua_State *L) { static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME}; static const char *const catnames[] = {"all", "collate", "ctype", "monetary", "numeric", "time", NULL}; const char *l = luaL_optstring(L, 1, NULL); int op = luaL_checkoption(L, 2, "all", catnames); lua_pushstring(L, setlocale(cat[op], l)); return 1; } static int os_exit (lua_State *L) { exit(luaL_optint(L, 1, EXIT_SUCCESS)); } static const luaL_Reg syslib[] = { {"clock", os_clock}, {"date", os_date}, {"difftime", os_difftime}, {"execute", os_execute}, {"exit", os_exit}, {"getenv", os_getenv}, {"remove", os_remove}, {"rename", os_rename}, {"setlocale", os_setlocale}, {"time", os_time}, {"tmpname", os_tmpname}, {NULL, NULL} }; /* }====================================================== */ LUALIB_API int luaopen_os (lua_State *L) { luaL_register(L, LUA_OSLIBNAME, syslib); return 1; } bam-0.4.0/src/lua/loadlib.c0000644000175000017500000004542011430042030013466 0ustar kmakma/* ** $Id: loadlib.c,v 1.52.1.3 2008/08/06 13:29:28 roberto Exp $ ** Dynamic library loader for Lua ** See Copyright Notice in lua.h ** ** This module contains an implementation of loadlib for Unix systems ** that have dlfcn, an implementation for Darwin (Mac OS X), an ** implementation for Windows, and a stub for other systems. */ #include #include #define loadlib_c #define LUA_LIB #include "lua.h" #include "lauxlib.h" #include "lualib.h" /* prefix for open functions in C libraries */ #define LUA_POF "luaopen_" /* separator for open functions in C libraries */ #define LUA_OFSEP "_" #define LIBPREFIX "LOADLIB: " #define POF LUA_POF #define LIB_FAIL "open" /* error codes for ll_loadfunc */ #define ERRLIB 1 #define ERRFUNC 2 #define setprogdir(L) ((void)0) static void ll_unloadlib (void *lib); static void *ll_load (lua_State *L, const char *path); static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); #if defined(LUA_DL_DLOPEN) /* ** {======================================================================== ** This is an implementation of loadlib based on the dlfcn interface. ** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, ** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least ** as an emulation layer on top of native functions. ** ========================================================================= */ #include static void ll_unloadlib (void *lib) { dlclose(lib); } static void *ll_load (lua_State *L, const char *path) { void *lib = dlopen(path, RTLD_NOW); if (lib == NULL) lua_pushstring(L, dlerror()); return lib; } static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { lua_CFunction f = (lua_CFunction)dlsym(lib, sym); if (f == NULL) lua_pushstring(L, dlerror()); return f; } /* }====================================================== */ #elif defined(LUA_DL_DLL) /* ** {====================================================================== ** This is an implementation of loadlib for Windows using native functions. ** ======================================================================= */ #include #undef setprogdir static void setprogdir (lua_State *L) { char buff[MAX_PATH + 1]; char *lb; DWORD nsize = sizeof(buff)/sizeof(char); DWORD n = GetModuleFileNameA(NULL, buff, nsize); if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) luaL_error(L, "unable to get ModuleFileName"); else { *lb = '\0'; luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); lua_remove(L, -2); /* remove original string */ } } static void pusherror (lua_State *L) { int error = GetLastError(); char buffer[128]; if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, buffer, sizeof(buffer), NULL)) lua_pushstring(L, buffer); else lua_pushfstring(L, "system error %d\n", error); } static void ll_unloadlib (void *lib) { FreeLibrary((HINSTANCE)lib); } static void *ll_load (lua_State *L, const char *path) { HINSTANCE lib = LoadLibraryA(path); if (lib == NULL) pusherror(L); return lib; } static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym); if (f == NULL) pusherror(L); return f; } /* }====================================================== */ #elif defined(LUA_DL_DYLD) /* ** {====================================================================== ** Native Mac OS X / Darwin Implementation ** ======================================================================= */ #include /* Mac appends a `_' before C function names */ #undef POF #define POF "_" LUA_POF static void pusherror (lua_State *L) { const char *err_str; const char *err_file; NSLinkEditErrors err; int err_num; NSLinkEditError(&err, &err_num, &err_file, &err_str); lua_pushstring(L, err_str); } static const char *errorfromcode (NSObjectFileImageReturnCode ret) { switch (ret) { case NSObjectFileImageInappropriateFile: return "file is not a bundle"; case NSObjectFileImageArch: return "library is for wrong CPU type"; case NSObjectFileImageFormat: return "bad format"; case NSObjectFileImageAccess: return "cannot access file"; case NSObjectFileImageFailure: default: return "unable to load library"; } } static void ll_unloadlib (void *lib) { NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); } static void *ll_load (lua_State *L, const char *path) { NSObjectFileImage img; NSObjectFileImageReturnCode ret; /* this would be a rare case, but prevents crashing if it happens */ if(!_dyld_present()) { lua_pushliteral(L, "dyld not present"); return NULL; } ret = NSCreateObjectFileImageFromFile(path, &img); if (ret == NSObjectFileImageSuccess) { NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE | NSLINKMODULE_OPTION_RETURN_ON_ERROR); NSDestroyObjectFileImage(img); if (mod == NULL) pusherror(L); return mod; } lua_pushstring(L, errorfromcode(ret)); return NULL; } static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym); if (nss == NULL) { lua_pushfstring(L, "symbol " LUA_QS " not found", sym); return NULL; } return (lua_CFunction)NSAddressOfSymbol(nss); } /* }====================================================== */ #else /* ** {====================================================== ** Fallback for other systems ** ======================================================= */ #undef LIB_FAIL #define LIB_FAIL "absent" #define DLMSG "dynamic libraries not enabled; check your Lua installation" static void ll_unloadlib (void *lib) { (void)lib; /* to avoid warnings */ } static void *ll_load (lua_State *L, const char *path) { (void)path; /* to avoid warnings */ lua_pushliteral(L, DLMSG); return NULL; } static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { (void)lib; (void)sym; /* to avoid warnings */ lua_pushliteral(L, DLMSG); return NULL; } /* }====================================================== */ #endif static void **ll_register (lua_State *L, const char *path) { void **plib; lua_pushfstring(L, "%s%s", LIBPREFIX, path); lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ if (!lua_isnil(L, -1)) /* is there an entry? */ plib = (void **)lua_touserdata(L, -1); else { /* no entry yet; create one */ lua_pop(L, 1); plib = (void **)lua_newuserdata(L, sizeof(const void *)); *plib = NULL; luaL_getmetatable(L, "_LOADLIB"); lua_setmetatable(L, -2); lua_pushfstring(L, "%s%s", LIBPREFIX, path); lua_pushvalue(L, -2); lua_settable(L, LUA_REGISTRYINDEX); } return plib; } /* ** __gc tag method: calls library's `ll_unloadlib' function with the lib ** handle */ static int gctm (lua_State *L) { void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); if (*lib) ll_unloadlib(*lib); *lib = NULL; /* mark library as closed */ return 0; } static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { void **reg = ll_register(L, path); if (*reg == NULL) *reg = ll_load(L, path); if (*reg == NULL) return ERRLIB; /* unable to load library */ else { lua_CFunction f = ll_sym(L, *reg, sym); if (f == NULL) return ERRFUNC; /* unable to find function */ lua_pushcfunction(L, f); return 0; /* return function */ } } static int ll_loadlib (lua_State *L) { const char *path = luaL_checkstring(L, 1); const char *init = luaL_checkstring(L, 2); int stat = ll_loadfunc(L, path, init); if (stat == 0) /* no errors? */ return 1; /* return the loaded function */ else { /* error; error message is on stack top */ lua_pushnil(L); lua_insert(L, -2); lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); return 3; /* return nil, error message, and where */ } } /* ** {====================================================== ** 'require' function ** ======================================================= */ static int readable (const char *filename) { FILE *f = fopen(filename, "r"); /* try to open file */ if (f == NULL) return 0; /* open failed */ fclose(f); return 1; } static const char *pushnexttemplate (lua_State *L, const char *path) { const char *l; while (*path == *LUA_PATHSEP) path++; /* skip separators */ if (*path == '\0') return NULL; /* no more templates */ l = strchr(path, *LUA_PATHSEP); /* find next separator */ if (l == NULL) l = path + strlen(path); lua_pushlstring(L, path, l - path); /* template */ return l; } static const char *findfile (lua_State *L, const char *name, const char *pname) { const char *path; name = luaL_gsub(L, name, ".", LUA_DIRSEP); lua_getfield(L, LUA_ENVIRONINDEX, pname); path = lua_tostring(L, -1); if (path == NULL) luaL_error(L, LUA_QL("package.%s") " must be a string", pname); lua_pushliteral(L, ""); /* error accumulator */ while ((path = pushnexttemplate(L, path)) != NULL) { const char *filename; filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); lua_remove(L, -2); /* remove path template */ if (readable(filename)) /* does file exist and is readable? */ return filename; /* return that file name */ lua_pushfstring(L, "\n\tno file " LUA_QS, filename); lua_remove(L, -2); /* remove file name */ lua_concat(L, 2); /* add entry to possible error message */ } return NULL; /* not found */ } static void loaderror (lua_State *L, const char *filename) { luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", lua_tostring(L, 1), filename, lua_tostring(L, -1)); } static int loader_Lua (lua_State *L) { const char *filename; const char *name = luaL_checkstring(L, 1); filename = findfile(L, name, "path"); if (filename == NULL) return 1; /* library not found in this path */ if (luaL_loadfile(L, filename) != 0) loaderror(L, filename); return 1; /* library loaded successfully */ } static const char *mkfuncname (lua_State *L, const char *modname) { const char *funcname; const char *mark = strchr(modname, *LUA_IGMARK); if (mark) modname = mark + 1; funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); funcname = lua_pushfstring(L, POF"%s", funcname); lua_remove(L, -2); /* remove 'gsub' result */ return funcname; } static int loader_C (lua_State *L) { const char *funcname; const char *name = luaL_checkstring(L, 1); const char *filename = findfile(L, name, "cpath"); if (filename == NULL) return 1; /* library not found in this path */ funcname = mkfuncname(L, name); if (ll_loadfunc(L, filename, funcname) != 0) loaderror(L, filename); return 1; /* library loaded successfully */ } static int loader_Croot (lua_State *L) { const char *funcname; const char *filename; const char *name = luaL_checkstring(L, 1); const char *p = strchr(name, '.'); int stat; if (p == NULL) return 0; /* is root */ lua_pushlstring(L, name, p - name); filename = findfile(L, lua_tostring(L, -1), "cpath"); if (filename == NULL) return 1; /* root not found */ funcname = mkfuncname(L, name); if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { if (stat != ERRFUNC) loaderror(L, filename); /* real error */ lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, name, filename); return 1; /* function not found */ } return 1; } static int loader_preload (lua_State *L) { const char *name = luaL_checkstring(L, 1); lua_getfield(L, LUA_ENVIRONINDEX, "preload"); if (!lua_istable(L, -1)) luaL_error(L, LUA_QL("package.preload") " must be a table"); lua_getfield(L, -1, name); if (lua_isnil(L, -1)) /* not found? */ lua_pushfstring(L, "\n\tno field package.preload['%s']", name); return 1; } static const int sentinel_ = 0; #define sentinel ((void *)&sentinel_) static int ll_require (lua_State *L) { const char *name = luaL_checkstring(L, 1); int i; lua_settop(L, 1); /* _LOADED table will be at index 2 */ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, 2, name); if (lua_toboolean(L, -1)) { /* is it there? */ if (lua_touserdata(L, -1) == sentinel) /* check loops */ luaL_error(L, "loop or previous error loading module " LUA_QS, name); return 1; /* package is already loaded */ } /* else must load it; iterate over available loaders */ lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); if (!lua_istable(L, -1)) luaL_error(L, LUA_QL("package.loaders") " must be a table"); lua_pushliteral(L, ""); /* error message accumulator */ for (i=1; ; i++) { lua_rawgeti(L, -2, i); /* get a loader */ if (lua_isnil(L, -1)) luaL_error(L, "module " LUA_QS " not found:%s", name, lua_tostring(L, -2)); lua_pushstring(L, name); lua_call(L, 1, 1); /* call it */ if (lua_isfunction(L, -1)) /* did it find module? */ break; /* module loaded successfully */ else if (lua_isstring(L, -1)) /* loader returned error message? */ lua_concat(L, 2); /* accumulate it */ else lua_pop(L, 1); } lua_pushlightuserdata(L, sentinel); lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ lua_pushstring(L, name); /* pass name as argument to module */ lua_call(L, 1, 1); /* run loaded module */ if (!lua_isnil(L, -1)) /* non-nil return? */ lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ lua_getfield(L, 2, name); if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ lua_pushboolean(L, 1); /* use true as result */ lua_pushvalue(L, -1); /* extra copy to be returned */ lua_setfield(L, 2, name); /* _LOADED[name] = true */ } return 1; } /* }====================================================== */ /* ** {====================================================== ** 'module' function ** ======================================================= */ static void setfenv (lua_State *L) { lua_Debug ar; if (lua_getstack(L, 1, &ar) == 0 || lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ lua_iscfunction(L, -1)) luaL_error(L, LUA_QL("module") " not called from a Lua function"); lua_pushvalue(L, -2); lua_setfenv(L, -2); lua_pop(L, 1); } static void dooptions (lua_State *L, int n) { int i; for (i = 2; i <= n; i++) { lua_pushvalue(L, i); /* get option (a function) */ lua_pushvalue(L, -2); /* module */ lua_call(L, 1, 0); } } static void modinit (lua_State *L, const char *modname) { const char *dot; lua_pushvalue(L, -1); lua_setfield(L, -2, "_M"); /* module._M = module */ lua_pushstring(L, modname); lua_setfield(L, -2, "_NAME"); dot = strrchr(modname, '.'); /* look for last dot in module name */ if (dot == NULL) dot = modname; else dot++; /* set _PACKAGE as package name (full module name minus last part) */ lua_pushlstring(L, modname, dot - modname); lua_setfield(L, -2, "_PACKAGE"); } static int ll_module (lua_State *L) { const char *modname = luaL_checkstring(L, 1); int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ if (!lua_istable(L, -1)) { /* not found? */ lua_pop(L, 1); /* remove previous result */ /* try global variable (and create one if it does not exist) */ if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL) return luaL_error(L, "name conflict for module " LUA_QS, modname); lua_pushvalue(L, -1); lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ } /* check whether table already has a _NAME field */ lua_getfield(L, -1, "_NAME"); if (!lua_isnil(L, -1)) /* is table an initialized module? */ lua_pop(L, 1); else { /* no; initialize it */ lua_pop(L, 1); modinit(L, modname); } lua_pushvalue(L, -1); setfenv(L); dooptions(L, loaded - 1); return 0; } static int ll_seeall (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); if (!lua_getmetatable(L, 1)) { lua_createtable(L, 0, 1); /* create new metatable */ lua_pushvalue(L, -1); lua_setmetatable(L, 1); } lua_pushvalue(L, LUA_GLOBALSINDEX); lua_setfield(L, -2, "__index"); /* mt.__index = _G */ return 0; } /* }====================================================== */ /* auxiliary mark (for internal use) */ #define AUXMARK "\1" static void setpath (lua_State *L, const char *fieldname, const char *envname, const char *def) { const char *path = getenv(envname); if (path == NULL) /* no environment variable? */ lua_pushstring(L, def); /* use default */ else { /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, LUA_PATHSEP AUXMARK LUA_PATHSEP); luaL_gsub(L, path, AUXMARK, def); lua_remove(L, -2); } setprogdir(L); lua_setfield(L, -2, fieldname); } static const luaL_Reg pk_funcs[] = { {"loadlib", ll_loadlib}, {"seeall", ll_seeall}, {NULL, NULL} }; static const luaL_Reg ll_funcs[] = { {"module", ll_module}, {"require", ll_require}, {NULL, NULL} }; static const lua_CFunction loaders[] = {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; LUALIB_API int luaopen_package (lua_State *L) { int i; /* create new type _LOADLIB */ luaL_newmetatable(L, "_LOADLIB"); lua_pushcfunction(L, gctm); lua_setfield(L, -2, "__gc"); /* create `package' table */ luaL_register(L, LUA_LOADLIBNAME, pk_funcs); #if defined(LUA_COMPAT_LOADLIB) lua_getfield(L, -1, "loadlib"); lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); #endif lua_pushvalue(L, -1); lua_replace(L, LUA_ENVIRONINDEX); /* create `loaders' table */ lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1); /* fill it with pre-defined loaders */ for (i=0; loaders[i] != NULL; i++) { lua_pushcfunction(L, loaders[i]); lua_rawseti(L, -2, i+1); } lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ /* store config information */ lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" LUA_EXECDIR "\n" LUA_IGMARK); lua_setfield(L, -2, "config"); /* set field `loaded' */ luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); lua_setfield(L, -2, "loaded"); /* set field `preload' */ lua_newtable(L); lua_setfield(L, -2, "preload"); lua_pushvalue(L, LUA_GLOBALSINDEX); luaL_register(L, NULL, ll_funcs); /* open lib into global table */ lua_pop(L, 1); return 1; /* return 'package' table */ } bam-0.4.0/src/lua/ltm.h0000644000175000017500000000177211430042030012663 0ustar kmakma/* ** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ ** Tag methods ** See Copyright Notice in lua.h */ #ifndef ltm_h #define ltm_h #include "lobject.h" /* * WARNING: if you change the order of this enumeration, * grep "ORDER TM" */ typedef enum { TM_INDEX, TM_NEWINDEX, TM_GC, TM_MODE, TM_EQ, /* last tag method with `fast' access */ TM_ADD, TM_SUB, TM_MUL, TM_DIV, TM_MOD, TM_POW, TM_UNM, TM_LEN, TM_LT, TM_LE, TM_CONCAT, TM_CALL, TM_N /* number of elements in the enum */ } TMS; #define gfasttm(g,et,e) ((et) == NULL ? NULL : \ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) #define fasttm(l,et,e) gfasttm(G(l), et, e) LUAI_DATA const char *const luaT_typenames[]; LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event); LUAI_FUNC void luaT_init (lua_State *L); #endif bam-0.4.0/src/lua/lzio.h0000644000175000017500000000302411430042030013034 0ustar kmakma/* ** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ ** Buffered streams ** See Copyright Notice in lua.h */ #ifndef lzio_h #define lzio_h #include "lua.h" #include "lmem.h" #define EOZ (-1) /* end of stream */ typedef struct Zio ZIO; #define char2int(c) cast(int, cast(unsigned char, (c))) #define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) typedef struct Mbuffer { char *buffer; size_t n; size_t buffsize; } Mbuffer; #define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) #define luaZ_buffer(buff) ((buff)->buffer) #define luaZ_sizebuffer(buff) ((buff)->buffsize) #define luaZ_bufflen(buff) ((buff)->n) #define luaZ_resetbuffer(buff) ((buff)->n = 0) #define luaZ_resizebuffer(L, buff, size) \ (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ (buff)->buffsize = size) #define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data); LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ LUAI_FUNC int luaZ_lookahead (ZIO *z); /* --------- Private Part ------------------ */ struct Zio { size_t n; /* bytes still unread */ const char *p; /* current position in buffer */ lua_Reader reader; void* data; /* additional data */ lua_State *L; /* Lua state (for reader) */ }; LUAI_FUNC int luaZ_fill (ZIO *z); #endif bam-0.4.0/src/lua/lobject.h0000644000175000017500000002046611430042030013512 0ustar kmakma/* ** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ #ifndef lobject_h #define lobject_h #include #include "llimits.h" #include "lua.h" /* tags for values visible from Lua */ #define LAST_TAG LUA_TTHREAD #define NUM_TAGS (LAST_TAG+1) /* ** Extra tags for non-values */ #define LUA_TPROTO (LAST_TAG+1) #define LUA_TUPVAL (LAST_TAG+2) #define LUA_TDEADKEY (LAST_TAG+3) /* ** Union of all collectable objects */ typedef union GCObject GCObject; /* ** Common Header for all collectable objects (in macro form, to be ** included in other objects) */ #define CommonHeader GCObject *next; lu_byte tt; lu_byte marked /* ** Common header in struct form */ typedef struct GCheader { CommonHeader; } GCheader; /* ** Union of all Lua values */ typedef union { GCObject *gc; void *p; lua_Number n; int b; } Value; /* ** Tagged Values */ #define TValuefields Value value; int tt typedef struct lua_TValue { TValuefields; } TValue; /* Macros to test type */ #define ttisnil(o) (ttype(o) == LUA_TNIL) #define ttisnumber(o) (ttype(o) == LUA_TNUMBER) #define ttisstring(o) (ttype(o) == LUA_TSTRING) #define ttistable(o) (ttype(o) == LUA_TTABLE) #define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) #define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) #define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) #define ttisthread(o) (ttype(o) == LUA_TTHREAD) #define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) /* Macros to access values */ #define ttype(o) ((o)->tt) #define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) #define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) #define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) #define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) #define tsvalue(o) (&rawtsvalue(o)->tsv) #define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) #define uvalue(o) (&rawuvalue(o)->uv) #define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) #define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) #define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) #define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) #define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) /* ** for internal debug only */ #define checkconsistency(obj) \ lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) #define checkliveness(g,obj) \ lua_assert(!iscollectable(obj) || \ ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) /* Macros to set values */ #define setnilvalue(obj) ((obj)->tt=LUA_TNIL) #define setnvalue(obj,x) \ { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } #define setpvalue(obj,x) \ { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } #define setbvalue(obj,x) \ { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } #define setsvalue(L,obj,x) \ { TValue *i_o=(obj); \ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ checkliveness(G(L),i_o); } #define setuvalue(L,obj,x) \ { TValue *i_o=(obj); \ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ checkliveness(G(L),i_o); } #define setthvalue(L,obj,x) \ { TValue *i_o=(obj); \ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ checkliveness(G(L),i_o); } #define setclvalue(L,obj,x) \ { TValue *i_o=(obj); \ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ checkliveness(G(L),i_o); } #define sethvalue(L,obj,x) \ { TValue *i_o=(obj); \ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ checkliveness(G(L),i_o); } #define setptvalue(L,obj,x) \ { TValue *i_o=(obj); \ i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ checkliveness(G(L),i_o); } #define setobj(L,obj1,obj2) \ { const TValue *o2=(obj2); TValue *o1=(obj1); \ o1->value = o2->value; o1->tt=o2->tt; \ checkliveness(G(L),o1); } /* ** different types of sets, according to destination */ /* from stack to (same) stack */ #define setobjs2s setobj /* to stack (not from same stack) */ #define setobj2s setobj #define setsvalue2s setsvalue #define sethvalue2s sethvalue #define setptvalue2s setptvalue /* from table to same table */ #define setobjt2t setobj /* to table */ #define setobj2t setobj /* to new object */ #define setobj2n setobj #define setsvalue2n setsvalue #define setttype(obj, tt) (ttype(obj) = (tt)) #define iscollectable(o) (ttype(o) >= LUA_TSTRING) typedef TValue *StkId; /* index to stack elements */ /* ** String headers for string table */ typedef union TString { L_Umaxalign dummy; /* ensures maximum alignment for strings */ struct { CommonHeader; lu_byte reserved; unsigned int hash; size_t len; } tsv; } TString; #define getstr(ts) cast(const char *, (ts) + 1) #define svalue(o) getstr(rawtsvalue(o)) typedef union Udata { L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ struct { CommonHeader; struct Table *metatable; struct Table *env; size_t len; } uv; } Udata; /* ** Function Prototypes */ typedef struct Proto { CommonHeader; TValue *k; /* constants used by the function */ Instruction *code; struct Proto **p; /* functions defined inside the function */ int *lineinfo; /* map from opcodes to source lines */ struct LocVar *locvars; /* information about local variables */ TString **upvalues; /* upvalue names */ TString *source; int sizeupvalues; int sizek; /* size of `k' */ int sizecode; int sizelineinfo; int sizep; /* size of `p' */ int sizelocvars; int linedefined; int lastlinedefined; GCObject *gclist; lu_byte nups; /* number of upvalues */ lu_byte numparams; lu_byte is_vararg; lu_byte maxstacksize; } Proto; /* masks for new-style vararg */ #define VARARG_HASARG 1 #define VARARG_ISVARARG 2 #define VARARG_NEEDSARG 4 typedef struct LocVar { TString *varname; int startpc; /* first point where variable is active */ int endpc; /* first point where variable is dead */ } LocVar; /* ** Upvalues */ typedef struct UpVal { CommonHeader; TValue *v; /* points to stack or to its own value */ union { TValue value; /* the value (when closed) */ struct { /* double linked list (when open) */ struct UpVal *prev; struct UpVal *next; } l; } u; } UpVal; /* ** Closures */ #define ClosureHeader \ CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ struct Table *env typedef struct CClosure { ClosureHeader; lua_CFunction f; TValue upvalue[1]; } CClosure; typedef struct LClosure { ClosureHeader; struct Proto *p; UpVal *upvals[1]; } LClosure; typedef union Closure { CClosure c; LClosure l; } Closure; #define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) #define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) /* ** Tables */ typedef union TKey { struct { TValuefields; struct Node *next; /* for chaining */ } nk; TValue tvk; } TKey; typedef struct Node { TValue i_val; TKey i_key; } Node; typedef struct Table { CommonHeader; lu_byte flags; /* 1<

lsizenode)) #define luaO_nilobject (&luaO_nilobject_) LUAI_DATA const TValue luaO_nilobject_; #define ceillog2(x) (luaO_log2((x)-1) + 1) LUAI_FUNC int luaO_log2 (unsigned int x); LUAI_FUNC int luaO_int2fb (unsigned int x); LUAI_FUNC int luaO_fb2int (int x); LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp); LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); #endif bam-0.4.0/src/lua/lobject.c0000644000175000017500000001257211430042030013504 0ustar kmakma/* ** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ #include #include #include #include #include #define lobject_c #define LUA_CORE #include "lua.h" #include "ldo.h" #include "lmem.h" #include "lobject.h" #include "lstate.h" #include "lstring.h" #include "lvm.h" const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; /* ** converts an integer to a "floating point byte", represented as ** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if ** eeeee != 0 and (xxx) otherwise. */ int luaO_int2fb (unsigned int x) { int e = 0; /* expoent */ while (x >= 16) { x = (x+1) >> 1; e++; } if (x < 8) return x; else return ((e+1) << 3) | (cast_int(x) - 8); } /* converts back */ int luaO_fb2int (int x) { int e = (x >> 3) & 31; if (e == 0) return x; else return ((x & 7)+8) << (e - 1); } int luaO_log2 (unsigned int x) { static const lu_byte log_2[256] = { 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 }; int l = -1; while (x >= 256) { l += 8; x >>= 8; } return l + log_2[x]; } int luaO_rawequalObj (const TValue *t1, const TValue *t2) { if (ttype(t1) != ttype(t2)) return 0; else switch (ttype(t1)) { case LUA_TNIL: return 1; case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); default: lua_assert(iscollectable(t1)); return gcvalue(t1) == gcvalue(t2); } } int luaO_str2d (const char *s, lua_Number *result) { char *endptr; *result = lua_str2number(s, &endptr); if (endptr == s) return 0; /* conversion failed */ if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ *result = cast_num(strtoul(s, &endptr, 16)); if (*endptr == '\0') return 1; /* most common case */ while (isspace(cast(unsigned char, *endptr))) endptr++; if (*endptr != '\0') return 0; /* invalid trailing characters? */ return 1; } static void pushstr (lua_State *L, const char *str) { setsvalue2s(L, L->top, luaS_new(L, str)); incr_top(L); } /* this function handles only `%d', `%c', %f, %p, and `%s' formats */ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { int n = 1; pushstr(L, ""); for (;;) { const char *e = strchr(fmt, '%'); if (e == NULL) break; setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); incr_top(L); switch (*(e+1)) { case 's': { const char *s = va_arg(argp, char *); if (s == NULL) s = "(null)"; pushstr(L, s); break; } case 'c': { char buff[2]; buff[0] = cast(char, va_arg(argp, int)); buff[1] = '\0'; pushstr(L, buff); break; } case 'd': { setnvalue(L->top, cast_num(va_arg(argp, int))); incr_top(L); break; } case 'f': { setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); incr_top(L); break; } case 'p': { char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ sprintf(buff, "%p", va_arg(argp, void *)); pushstr(L, buff); break; } case '%': { pushstr(L, "%"); break; } default: { char buff[3]; buff[0] = '%'; buff[1] = *(e+1); buff[2] = '\0'; pushstr(L, buff); break; } } n += 2; fmt = e+2; } pushstr(L, fmt); luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); L->top -= n; return svalue(L->top - 1); } const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { const char *msg; va_list argp; va_start(argp, fmt); msg = luaO_pushvfstring(L, fmt, argp); va_end(argp); return msg; } void luaO_chunkid (char *out, const char *source, size_t bufflen) { if (*source == '=') { strncpy(out, source+1, bufflen); /* remove first char */ out[bufflen-1] = '\0'; /* ensures null termination */ } else { /* out = "source", or "...source" */ if (*source == '@') { size_t l; source++; /* skip the `@' */ bufflen -= sizeof(" '...' "); l = strlen(source); strcpy(out, ""); if (l > bufflen) { source += (l-bufflen); /* get last part of file name */ strcat(out, "..."); } strcat(out, source); } else { /* out = [string "string"] */ size_t len = strcspn(source, "\n\r"); /* stop at first newline */ bufflen -= sizeof(" [string \"...\"] "); if (len > bufflen) len = bufflen; strcpy(out, "[string \""); if (source[len] != '\0') { /* must truncate? */ strncat(out, source, len); strcat(out, "..."); } else strcat(out, source); strcat(out, "\"]"); } } } bam-0.4.0/src/lua/ltablib.c0000644000175000017500000001625711430042030013477 0ustar kmakma/* ** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ ** Library for Table Manipulation ** See Copyright Notice in lua.h */ #include #define ltablib_c #define LUA_LIB #include "lua.h" #include "lauxlib.h" #include "lualib.h" #define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) static int foreachi (lua_State *L) { int i; int n = aux_getn(L, 1); luaL_checktype(L, 2, LUA_TFUNCTION); for (i=1; i <= n; i++) { lua_pushvalue(L, 2); /* function */ lua_pushinteger(L, i); /* 1st argument */ lua_rawgeti(L, 1, i); /* 2nd argument */ lua_call(L, 2, 1); if (!lua_isnil(L, -1)) return 1; lua_pop(L, 1); /* remove nil result */ } return 0; } static int foreach (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); luaL_checktype(L, 2, LUA_TFUNCTION); lua_pushnil(L); /* first key */ while (lua_next(L, 1)) { lua_pushvalue(L, 2); /* function */ lua_pushvalue(L, -3); /* key */ lua_pushvalue(L, -3); /* value */ lua_call(L, 2, 1); if (!lua_isnil(L, -1)) return 1; lua_pop(L, 2); /* remove value and result */ } return 0; } static int maxn (lua_State *L) { lua_Number max = 0; luaL_checktype(L, 1, LUA_TTABLE); lua_pushnil(L); /* first key */ while (lua_next(L, 1)) { lua_pop(L, 1); /* remove value */ if (lua_type(L, -1) == LUA_TNUMBER) { lua_Number v = lua_tonumber(L, -1); if (v > max) max = v; } } lua_pushnumber(L, max); return 1; } static int getn (lua_State *L) { lua_pushinteger(L, aux_getn(L, 1)); return 1; } static int setn (lua_State *L) { luaL_checktype(L, 1, LUA_TTABLE); #ifndef luaL_setn luaL_setn(L, 1, luaL_checkint(L, 2)); #else luaL_error(L, LUA_QL("setn") " is obsolete"); #endif lua_pushvalue(L, 1); return 1; } static int tinsert (lua_State *L) { int e = aux_getn(L, 1) + 1; /* first empty element */ int pos; /* where to insert new element */ switch (lua_gettop(L)) { case 2: { /* called with only 2 arguments */ pos = e; /* insert new element at the end */ break; } case 3: { int i; pos = luaL_checkint(L, 2); /* 2nd argument is the position */ if (pos > e) e = pos; /* `grow' array if necessary */ for (i = e; i > pos; i--) { /* move up elements */ lua_rawgeti(L, 1, i-1); lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ } break; } default: { return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); } } luaL_setn(L, 1, e); /* new size */ lua_rawseti(L, 1, pos); /* t[pos] = v */ return 0; } static int tremove (lua_State *L) { int e = aux_getn(L, 1); int pos = luaL_optint(L, 2, e); if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ return 0; /* nothing to remove */ luaL_setn(L, 1, e - 1); /* t.n = n-1 */ lua_rawgeti(L, 1, pos); /* result = t[pos] */ for ( ;pos= P */ while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { if (i>u) luaL_error(L, "invalid order function for sorting"); lua_pop(L, 1); /* remove a[i] */ } /* repeat --j until a[j] <= P */ while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { if (j #include #include "lua.h" typedef LUAI_UINT32 lu_int32; typedef LUAI_UMEM lu_mem; typedef LUAI_MEM l_mem; /* chars used as small naturals (so that `char' is reserved for characters) */ typedef unsigned char lu_byte; #define MAX_SIZET ((size_t)(~(size_t)0)-2) #define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) #define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ /* ** conversion of pointer to integer ** this is for hashing only; there is no problem if the integer ** cannot hold the whole pointer value */ #define IntPoint(p) ((unsigned int)(lu_mem)(p)) /* type to ensure maximum alignment */ typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; /* result of a `usual argument conversion' over lua_Number */ typedef LUAI_UACNUMBER l_uacNumber; /* internal assertions for in-house debugging */ #ifdef lua_assert #define check_exp(c,e) (lua_assert(c), (e)) #define api_check(l,e) lua_assert(e) #else #define lua_assert(c) ((void)0) #define check_exp(c,e) (e) #define api_check luai_apicheck #endif #ifndef UNUSED #define UNUSED(x) ((void)(x)) /* to avoid warnings */ #endif #ifndef cast #define cast(t, exp) ((t)(exp)) #endif #define cast_byte(i) cast(lu_byte, (i)) #define cast_num(i) cast(lua_Number, (i)) #define cast_int(i) cast(int, (i)) /* ** type for virtual-machine instructions ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) */ typedef lu_int32 Instruction; /* maximum stack for a Lua function */ #define MAXSTACK 250 /* minimum size for the string table (must be power of 2) */ #ifndef MINSTRTABSIZE #define MINSTRTABSIZE 32 #endif /* minimum size for string buffer */ #ifndef LUA_MINBUFFER #define LUA_MINBUFFER 32 #endif #ifndef lua_lock #define lua_lock(L) ((void) 0) #define lua_unlock(L) ((void) 0) #endif #ifndef luai_threadyield #define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} #endif /* ** macro to control inclusion of some hard tests on stack reallocation */ #ifndef HARDSTACKTESTS #define condhardstacktests(x) ((void)0) #else #define condhardstacktests(x) x #endif #endif bam-0.4.0/src/lua/lgc.h0000644000175000017500000000612711430042030012633 0ustar kmakma/* ** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ #ifndef lgc_h #define lgc_h #include "lobject.h" /* ** Possible states of the Garbage Collector */ #define GCSpause 0 #define GCSpropagate 1 #define GCSsweepstring 2 #define GCSsweep 3 #define GCSfinalize 4 /* ** some userful bit tricks */ #define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) #define setbits(x,m) ((x) |= (m)) #define testbits(x,m) ((x) & (m)) #define bitmask(b) (1<<(b)) #define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) #define l_setbit(x,b) setbits(x, bitmask(b)) #define resetbit(x,b) resetbits(x, bitmask(b)) #define testbit(x,b) testbits(x, bitmask(b)) #define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) #define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) #define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) /* ** Layout for bit use in `marked' field: ** bit 0 - object is white (type 0) ** bit 1 - object is white (type 1) ** bit 2 - object is black ** bit 3 - for userdata: has been finalized ** bit 3 - for tables: has weak keys ** bit 4 - for tables: has weak values ** bit 5 - object is fixed (should not be collected) ** bit 6 - object is "super" fixed (only the main thread) */ #define WHITE0BIT 0 #define WHITE1BIT 1 #define BLACKBIT 2 #define FINALIZEDBIT 3 #define KEYWEAKBIT 3 #define VALUEWEAKBIT 4 #define FIXEDBIT 5 #define SFIXEDBIT 6 #define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) #define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) #define isblack(x) testbit((x)->gch.marked, BLACKBIT) #define isgray(x) (!isblack(x) && !iswhite(x)) #define otherwhite(g) (g->currentwhite ^ WHITEBITS) #define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) #define changewhite(x) ((x)->gch.marked ^= WHITEBITS) #define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) #define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) #define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) #define luaC_checkGC(L) { \ condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ if (G(L)->totalbytes >= G(L)->GCthreshold) \ luaC_step(L); } #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ luaC_barrierf(L,obj2gco(p),gcvalue(v)); } #define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ luaC_barrierback(L,t); } #define luaC_objbarrier(L,p,o) \ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ luaC_barrierf(L,obj2gco(p),obj2gco(o)); } #define luaC_objbarriert(L,t,o) \ { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); LUAI_FUNC void luaC_callGCTM (lua_State *L); LUAI_FUNC void luaC_freeall (lua_State *L); LUAI_FUNC void luaC_step (lua_State *L); LUAI_FUNC void luaC_fullgc (lua_State *L); LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); #endif bam-0.4.0/src/lua/lapi.c0000644000175000017500000005426411430042030013013 0ustar kmakma/* ** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ ** Lua API ** See Copyright Notice in lua.h */ #include #include #include #include #define lapi_c #define LUA_CORE #include "lua.h" #include "lapi.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" #include "lgc.h" #include "lmem.h" #include "lobject.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #include "ltm.h" #include "lundump.h" #include "lvm.h" const char lua_ident[] = "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" "$Authors: " LUA_AUTHORS " $\n" "$URL: www.lua.org $\n"; #define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) #define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) #define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} static TValue *index2adr (lua_State *L, int idx) { if (idx > 0) { TValue *o = L->base + (idx - 1); api_check(L, idx <= L->ci->top - L->base); if (o >= L->top) return cast(TValue *, luaO_nilobject); else return o; } else if (idx > LUA_REGISTRYINDEX) { api_check(L, idx != 0 && -idx <= L->top - L->base); return L->top + idx; } else switch (idx) { /* pseudo-indices */ case LUA_REGISTRYINDEX: return registry(L); case LUA_ENVIRONINDEX: { Closure *func = curr_func(L); sethvalue(L, &L->env, func->c.env); return &L->env; } case LUA_GLOBALSINDEX: return gt(L); default: { Closure *func = curr_func(L); idx = LUA_GLOBALSINDEX - idx; return (idx <= func->c.nupvalues) ? &func->c.upvalue[idx-1] : cast(TValue *, luaO_nilobject); } } } static Table *getcurrenv (lua_State *L) { if (L->ci == L->base_ci) /* no enclosing function? */ return hvalue(gt(L)); /* use global table as environment */ else { Closure *func = curr_func(L); return func->c.env; } } void luaA_pushobject (lua_State *L, const TValue *o) { setobj2s(L, L->top, o); api_incr_top(L); } LUA_API int lua_checkstack (lua_State *L, int size) { int res = 1; lua_lock(L); if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) res = 0; /* stack overflow */ else if (size > 0) { luaD_checkstack(L, size); if (L->ci->top < L->top + size) L->ci->top = L->top + size; } lua_unlock(L); return res; } LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { int i; if (from == to) return; lua_lock(to); api_checknelems(from, n); api_check(from, G(from) == G(to)); api_check(from, to->ci->top - to->top >= n); from->top -= n; for (i = 0; i < n; i++) { setobj2s(to, to->top++, from->top + i); } lua_unlock(to); } LUA_API void lua_setlevel (lua_State *from, lua_State *to) { to->nCcalls = from->nCcalls; } LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { lua_CFunction old; lua_lock(L); old = G(L)->panic; G(L)->panic = panicf; lua_unlock(L); return old; } LUA_API lua_State *lua_newthread (lua_State *L) { lua_State *L1; lua_lock(L); luaC_checkGC(L); L1 = luaE_newthread(L); setthvalue(L, L->top, L1); api_incr_top(L); lua_unlock(L); luai_userstatethread(L, L1); return L1; } /* ** basic stack manipulation */ LUA_API int lua_gettop (lua_State *L) { return cast_int(L->top - L->base); } LUA_API void lua_settop (lua_State *L, int idx) { lua_lock(L); if (idx >= 0) { api_check(L, idx <= L->stack_last - L->base); while (L->top < L->base + idx) setnilvalue(L->top++); L->top = L->base + idx; } else { api_check(L, -(idx+1) <= (L->top - L->base)); L->top += idx+1; /* `subtract' index (index is negative) */ } lua_unlock(L); } LUA_API void lua_remove (lua_State *L, int idx) { StkId p; lua_lock(L); p = index2adr(L, idx); api_checkvalidindex(L, p); while (++p < L->top) setobjs2s(L, p-1, p); L->top--; lua_unlock(L); } LUA_API void lua_insert (lua_State *L, int idx) { StkId p; StkId q; lua_lock(L); p = index2adr(L, idx); api_checkvalidindex(L, p); for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); setobjs2s(L, p, L->top); lua_unlock(L); } LUA_API void lua_replace (lua_State *L, int idx) { StkId o; lua_lock(L); /* explicit test for incompatible code */ if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) luaG_runerror(L, "no calling environment"); api_checknelems(L, 1); o = index2adr(L, idx); api_checkvalidindex(L, o); if (idx == LUA_ENVIRONINDEX) { Closure *func = curr_func(L); api_check(L, ttistable(L->top - 1)); func->c.env = hvalue(L->top - 1); luaC_barrier(L, func, L->top - 1); } else { setobj(L, o, L->top - 1); if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ luaC_barrier(L, curr_func(L), L->top - 1); } L->top--; lua_unlock(L); } LUA_API void lua_pushvalue (lua_State *L, int idx) { lua_lock(L); setobj2s(L, L->top, index2adr(L, idx)); api_incr_top(L); lua_unlock(L); } /* ** access functions (stack -> C) */ LUA_API int lua_type (lua_State *L, int idx) { StkId o = index2adr(L, idx); return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); } LUA_API const char *lua_typename (lua_State *L, int t) { UNUSED(L); return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; } LUA_API int lua_iscfunction (lua_State *L, int idx) { StkId o = index2adr(L, idx); return iscfunction(o); } LUA_API int lua_isnumber (lua_State *L, int idx) { TValue n; const TValue *o = index2adr(L, idx); return tonumber(o, &n); } LUA_API int lua_isstring (lua_State *L, int idx) { int t = lua_type(L, idx); return (t == LUA_TSTRING || t == LUA_TNUMBER); } LUA_API int lua_isuserdata (lua_State *L, int idx) { const TValue *o = index2adr(L, idx); return (ttisuserdata(o) || ttislightuserdata(o)); } LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { StkId o1 = index2adr(L, index1); StkId o2 = index2adr(L, index2); return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : luaO_rawequalObj(o1, o2); } LUA_API int lua_equal (lua_State *L, int index1, int index2) { StkId o1, o2; int i; lua_lock(L); /* may call tag method */ o1 = index2adr(L, index1); o2 = index2adr(L, index2); i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); lua_unlock(L); return i; } LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { StkId o1, o2; int i; lua_lock(L); /* may call tag method */ o1 = index2adr(L, index1); o2 = index2adr(L, index2); i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : luaV_lessthan(L, o1, o2); lua_unlock(L); return i; } LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { TValue n; const TValue *o = index2adr(L, idx); if (tonumber(o, &n)) return nvalue(o); else return 0; } LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { TValue n; const TValue *o = index2adr(L, idx); if (tonumber(o, &n)) { lua_Integer res; lua_Number num = nvalue(o); lua_number2integer(res, num); return res; } else return 0; } LUA_API int lua_toboolean (lua_State *L, int idx) { const TValue *o = index2adr(L, idx); return !l_isfalse(o); } LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { StkId o = index2adr(L, idx); if (!ttisstring(o)) { lua_lock(L); /* `luaV_tostring' may create a new string */ if (!luaV_tostring(L, o)) { /* conversion failed? */ if (len != NULL) *len = 0; lua_unlock(L); return NULL; } luaC_checkGC(L); o = index2adr(L, idx); /* previous call may reallocate the stack */ lua_unlock(L); } if (len != NULL) *len = tsvalue(o)->len; return svalue(o); } LUA_API size_t lua_objlen (lua_State *L, int idx) { StkId o = index2adr(L, idx); switch (ttype(o)) { case LUA_TSTRING: return tsvalue(o)->len; case LUA_TUSERDATA: return uvalue(o)->len; case LUA_TTABLE: return luaH_getn(hvalue(o)); case LUA_TNUMBER: { size_t l; lua_lock(L); /* `luaV_tostring' may create a new string */ l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); lua_unlock(L); return l; } default: return 0; } } LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { StkId o = index2adr(L, idx); return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; } LUA_API void *lua_touserdata (lua_State *L, int idx) { StkId o = index2adr(L, idx); switch (ttype(o)) { case LUA_TUSERDATA: return (rawuvalue(o) + 1); case LUA_TLIGHTUSERDATA: return pvalue(o); default: return NULL; } } LUA_API lua_State *lua_tothread (lua_State *L, int idx) { StkId o = index2adr(L, idx); return (!ttisthread(o)) ? NULL : thvalue(o); } LUA_API const void *lua_topointer (lua_State *L, int idx) { StkId o = index2adr(L, idx); switch (ttype(o)) { case LUA_TTABLE: return hvalue(o); case LUA_TFUNCTION: return clvalue(o); case LUA_TTHREAD: return thvalue(o); case LUA_TUSERDATA: case LUA_TLIGHTUSERDATA: return lua_touserdata(L, idx); default: return NULL; } } /* ** push functions (C -> stack) */ LUA_API void lua_pushnil (lua_State *L) { lua_lock(L); setnilvalue(L->top); api_incr_top(L); lua_unlock(L); } LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { lua_lock(L); setnvalue(L->top, n); api_incr_top(L); lua_unlock(L); } LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { lua_lock(L); setnvalue(L->top, cast_num(n)); api_incr_top(L); lua_unlock(L); } LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { lua_lock(L); luaC_checkGC(L); setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); api_incr_top(L); lua_unlock(L); } LUA_API void lua_pushstring (lua_State *L, const char *s) { if (s == NULL) lua_pushnil(L); else lua_pushlstring(L, s, strlen(s)); } LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, va_list argp) { const char *ret; lua_lock(L); luaC_checkGC(L); ret = luaO_pushvfstring(L, fmt, argp); lua_unlock(L); return ret; } LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { const char *ret; va_list argp; lua_lock(L); luaC_checkGC(L); va_start(argp, fmt); ret = luaO_pushvfstring(L, fmt, argp); va_end(argp); lua_unlock(L); return ret; } LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { Closure *cl; lua_lock(L); luaC_checkGC(L); api_checknelems(L, n); cl = luaF_newCclosure(L, n, getcurrenv(L)); cl->c.f = fn; L->top -= n; while (n--) setobj2n(L, &cl->c.upvalue[n], L->top+n); setclvalue(L, L->top, cl); lua_assert(iswhite(obj2gco(cl))); api_incr_top(L); lua_unlock(L); } LUA_API void lua_pushboolean (lua_State *L, int b) { lua_lock(L); setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ api_incr_top(L); lua_unlock(L); } LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { lua_lock(L); setpvalue(L->top, p); api_incr_top(L); lua_unlock(L); } LUA_API int lua_pushthread (lua_State *L) { lua_lock(L); setthvalue(L, L->top, L); api_incr_top(L); lua_unlock(L); return (G(L)->mainthread == L); } /* ** get functions (Lua -> stack) */ LUA_API void lua_gettable (lua_State *L, int idx) { StkId t; lua_lock(L); t = index2adr(L, idx); api_checkvalidindex(L, t); luaV_gettable(L, t, L->top - 1, L->top - 1); lua_unlock(L); } LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { StkId t; TValue key; lua_lock(L); t = index2adr(L, idx); api_checkvalidindex(L, t); setsvalue(L, &key, luaS_new(L, k)); luaV_gettable(L, t, &key, L->top); api_incr_top(L); lua_unlock(L); } LUA_API void lua_rawget (lua_State *L, int idx) { StkId t; lua_lock(L); t = index2adr(L, idx); api_check(L, ttistable(t)); setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); lua_unlock(L); } LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { StkId o; lua_lock(L); o = index2adr(L, idx); api_check(L, ttistable(o)); setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); api_incr_top(L); lua_unlock(L); } LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { lua_lock(L); luaC_checkGC(L); sethvalue(L, L->top, luaH_new(L, narray, nrec)); api_incr_top(L); lua_unlock(L); } LUA_API int lua_getmetatable (lua_State *L, int objindex) { const TValue *obj; Table *mt = NULL; int res; lua_lock(L); obj = index2adr(L, objindex); switch (ttype(obj)) { case LUA_TTABLE: mt = hvalue(obj)->metatable; break; case LUA_TUSERDATA: mt = uvalue(obj)->metatable; break; default: mt = G(L)->mt[ttype(obj)]; break; } if (mt == NULL) res = 0; else { sethvalue(L, L->top, mt); api_incr_top(L); res = 1; } lua_unlock(L); return res; } LUA_API void lua_getfenv (lua_State *L, int idx) { StkId o; lua_lock(L); o = index2adr(L, idx); api_checkvalidindex(L, o); switch (ttype(o)) { case LUA_TFUNCTION: sethvalue(L, L->top, clvalue(o)->c.env); break; case LUA_TUSERDATA: sethvalue(L, L->top, uvalue(o)->env); break; case LUA_TTHREAD: setobj2s(L, L->top, gt(thvalue(o))); break; default: setnilvalue(L->top); break; } api_incr_top(L); lua_unlock(L); } /* ** set functions (stack -> Lua) */ LUA_API void lua_settable (lua_State *L, int idx) { StkId t; lua_lock(L); api_checknelems(L, 2); t = index2adr(L, idx); api_checkvalidindex(L, t); luaV_settable(L, t, L->top - 2, L->top - 1); L->top -= 2; /* pop index and value */ lua_unlock(L); } LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { StkId t; TValue key; lua_lock(L); api_checknelems(L, 1); t = index2adr(L, idx); api_checkvalidindex(L, t); setsvalue(L, &key, luaS_new(L, k)); luaV_settable(L, t, &key, L->top - 1); L->top--; /* pop value */ lua_unlock(L); } LUA_API void lua_rawset (lua_State *L, int idx) { StkId t; lua_lock(L); api_checknelems(L, 2); t = index2adr(L, idx); api_check(L, ttistable(t)); setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); luaC_barriert(L, hvalue(t), L->top-1); L->top -= 2; lua_unlock(L); } LUA_API void lua_rawseti (lua_State *L, int idx, int n) { StkId o; lua_lock(L); api_checknelems(L, 1); o = index2adr(L, idx); api_check(L, ttistable(o)); setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); luaC_barriert(L, hvalue(o), L->top-1); L->top--; lua_unlock(L); } LUA_API int lua_setmetatable (lua_State *L, int objindex) { TValue *obj; Table *mt; lua_lock(L); api_checknelems(L, 1); obj = index2adr(L, objindex); api_checkvalidindex(L, obj); if (ttisnil(L->top - 1)) mt = NULL; else { api_check(L, ttistable(L->top - 1)); mt = hvalue(L->top - 1); } switch (ttype(obj)) { case LUA_TTABLE: { hvalue(obj)->metatable = mt; if (mt) luaC_objbarriert(L, hvalue(obj), mt); break; } case LUA_TUSERDATA: { uvalue(obj)->metatable = mt; if (mt) luaC_objbarrier(L, rawuvalue(obj), mt); break; } default: { G(L)->mt[ttype(obj)] = mt; break; } } L->top--; lua_unlock(L); return 1; } LUA_API int lua_setfenv (lua_State *L, int idx) { StkId o; int res = 1; lua_lock(L); api_checknelems(L, 1); o = index2adr(L, idx); api_checkvalidindex(L, o); api_check(L, ttistable(L->top - 1)); switch (ttype(o)) { case LUA_TFUNCTION: clvalue(o)->c.env = hvalue(L->top - 1); break; case LUA_TUSERDATA: uvalue(o)->env = hvalue(L->top - 1); break; case LUA_TTHREAD: sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); break; default: res = 0; break; } if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); L->top--; lua_unlock(L); return res; } /* ** `load' and `call' functions (run Lua code) */ #define adjustresults(L,nres) \ { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } #define checkresults(L,na,nr) \ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) LUA_API void lua_call (lua_State *L, int nargs, int nresults) { StkId func; lua_lock(L); api_checknelems(L, nargs+1); checkresults(L, nargs, nresults); func = L->top - (nargs+1); luaD_call(L, func, nresults); adjustresults(L, nresults); lua_unlock(L); } /* ** Execute a protected call. */ struct CallS { /* data to `f_call' */ StkId func; int nresults; }; static void f_call (lua_State *L, void *ud) { struct CallS *c = cast(struct CallS *, ud); luaD_call(L, c->func, c->nresults); } LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { struct CallS c; int status; ptrdiff_t func; lua_lock(L); api_checknelems(L, nargs+1); checkresults(L, nargs, nresults); if (errfunc == 0) func = 0; else { StkId o = index2adr(L, errfunc); api_checkvalidindex(L, o); func = savestack(L, o); } c.func = L->top - (nargs+1); /* function to be called */ c.nresults = nresults; status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); adjustresults(L, nresults); lua_unlock(L); return status; } /* ** Execute a protected C call. */ struct CCallS { /* data to `f_Ccall' */ lua_CFunction func; void *ud; }; static void f_Ccall (lua_State *L, void *ud) { struct CCallS *c = cast(struct CCallS *, ud); Closure *cl; cl = luaF_newCclosure(L, 0, getcurrenv(L)); cl->c.f = c->func; setclvalue(L, L->top, cl); /* push function */ api_incr_top(L); setpvalue(L->top, c->ud); /* push only argument */ api_incr_top(L); luaD_call(L, L->top - 2, 0); } LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { struct CCallS c; int status; lua_lock(L); c.func = func; c.ud = ud; status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); lua_unlock(L); return status; } LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *chunkname) { ZIO z; int status; lua_lock(L); if (!chunkname) chunkname = "?"; luaZ_init(L, &z, reader, data); status = luaD_protectedparser(L, &z, chunkname); lua_unlock(L); return status; } LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { int status; TValue *o; lua_lock(L); api_checknelems(L, 1); o = L->top - 1; if (isLfunction(o)) status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); else status = 1; lua_unlock(L); return status; } LUA_API int lua_status (lua_State *L) { return L->status; } /* ** Garbage-collection function */ LUA_API int lua_gc (lua_State *L, int what, int data) { int res = 0; global_State *g; lua_lock(L); g = G(L); switch (what) { case LUA_GCSTOP: { g->GCthreshold = MAX_LUMEM; break; } case LUA_GCRESTART: { g->GCthreshold = g->totalbytes; break; } case LUA_GCCOLLECT: { luaC_fullgc(L); break; } case LUA_GCCOUNT: { /* GC values are expressed in Kbytes: #bytes/2^10 */ res = cast_int(g->totalbytes >> 10); break; } case LUA_GCCOUNTB: { res = cast_int(g->totalbytes & 0x3ff); break; } case LUA_GCSTEP: { lu_mem a = (cast(lu_mem, data) << 10); if (a <= g->totalbytes) g->GCthreshold = g->totalbytes - a; else g->GCthreshold = 0; while (g->GCthreshold <= g->totalbytes) { luaC_step(L); if (g->gcstate == GCSpause) { /* end of cycle? */ res = 1; /* signal it */ break; } } break; } case LUA_GCSETPAUSE: { res = g->gcpause; g->gcpause = data; break; } case LUA_GCSETSTEPMUL: { res = g->gcstepmul; g->gcstepmul = data; break; } default: res = -1; /* invalid option */ } lua_unlock(L); return res; } /* ** miscellaneous functions */ LUA_API int lua_error (lua_State *L) { lua_lock(L); api_checknelems(L, 1); luaG_errormsg(L); lua_unlock(L); return 0; /* to avoid warnings */ } LUA_API int lua_next (lua_State *L, int idx) { StkId t; int more; lua_lock(L); t = index2adr(L, idx); api_check(L, ttistable(t)); more = luaH_next(L, hvalue(t), L->top - 1); if (more) { api_incr_top(L); } else /* no more elements */ L->top -= 1; /* remove key */ lua_unlock(L); return more; } LUA_API void lua_concat (lua_State *L, int n) { lua_lock(L); api_checknelems(L, n); if (n >= 2) { luaC_checkGC(L); luaV_concat(L, n, cast_int(L->top - L->base) - 1); L->top -= (n-1); } else if (n == 0) { /* push empty string */ setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); api_incr_top(L); } /* else n == 1; nothing to do */ lua_unlock(L); } LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { lua_Alloc f; lua_lock(L); if (ud) *ud = G(L)->ud; f = G(L)->frealloc; lua_unlock(L); return f; } LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { lua_lock(L); G(L)->ud = ud; G(L)->frealloc = f; lua_unlock(L); } LUA_API void *lua_newuserdata (lua_State *L, size_t size) { Udata *u; lua_lock(L); luaC_checkGC(L); u = luaS_newudata(L, size, getcurrenv(L)); setuvalue(L, L->top, u); api_incr_top(L); lua_unlock(L); return u + 1; } static const char *aux_upvalue (StkId fi, int n, TValue **val) { Closure *f; if (!ttisfunction(fi)) return NULL; f = clvalue(fi); if (f->c.isC) { if (!(1 <= n && n <= f->c.nupvalues)) return NULL; *val = &f->c.upvalue[n-1]; return ""; } else { Proto *p = f->l.p; if (!(1 <= n && n <= p->sizeupvalues)) return NULL; *val = f->l.upvals[n-1]->v; return getstr(p->upvalues[n-1]); } } LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { const char *name; TValue *val; lua_lock(L); name = aux_upvalue(index2adr(L, funcindex), n, &val); if (name) { setobj2s(L, L->top, val); api_incr_top(L); } lua_unlock(L); return name; } LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { const char *name; TValue *val; StkId fi; lua_lock(L); fi = index2adr(L, funcindex); api_checknelems(L, 1); name = aux_upvalue(fi, n, &val); if (name) { L->top--; setobj(L, val, L->top); luaC_barrier(L, clvalue(fi), L->top); } lua_unlock(L); return name; } bam-0.4.0/src/lua/lcode.c0000644000175000017500000005152711430042030013153 0ustar kmakma/* ** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ #include #define lcode_c #define LUA_CORE #include "lua.h" #include "lcode.h" #include "ldebug.h" #include "ldo.h" #include "lgc.h" #include "llex.h" #include "lmem.h" #include "lobject.h" #include "lopcodes.h" #include "lparser.h" #include "ltable.h" #define hasjumps(e) ((e)->t != (e)->f) static int isnumeral(expdesc *e) { return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); } void luaK_nil (FuncState *fs, int from, int n) { Instruction *previous; if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ if (fs->pc == 0) { /* function start? */ if (from >= fs->nactvar) return; /* positions are already clean */ } else { previous = &fs->f->code[fs->pc-1]; if (GET_OPCODE(*previous) == OP_LOADNIL) { int pfrom = GETARG_A(*previous); int pto = GETARG_B(*previous); if (pfrom <= from && from <= pto+1) { /* can connect both? */ if (from+n-1 > pto) SETARG_B(*previous, from+n-1); return; } } } } luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ } int luaK_jump (FuncState *fs) { int jpc = fs->jpc; /* save list of jumps to here */ int j; fs->jpc = NO_JUMP; j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); luaK_concat(fs, &j, jpc); /* keep them on hold */ return j; } void luaK_ret (FuncState *fs, int first, int nret) { luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); } static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { luaK_codeABC(fs, op, A, B, C); return luaK_jump(fs); } static void fixjump (FuncState *fs, int pc, int dest) { Instruction *jmp = &fs->f->code[pc]; int offset = dest-(pc+1); lua_assert(dest != NO_JUMP); if (abs(offset) > MAXARG_sBx) luaX_syntaxerror(fs->ls, "control structure too long"); SETARG_sBx(*jmp, offset); } /* ** returns current `pc' and marks it as a jump target (to avoid wrong ** optimizations with consecutive instructions not in the same basic block). */ int luaK_getlabel (FuncState *fs) { fs->lasttarget = fs->pc; return fs->pc; } static int getjump (FuncState *fs, int pc) { int offset = GETARG_sBx(fs->f->code[pc]); if (offset == NO_JUMP) /* point to itself represents end of list */ return NO_JUMP; /* end of list */ else return (pc+1)+offset; /* turn offset into absolute position */ } static Instruction *getjumpcontrol (FuncState *fs, int pc) { Instruction *pi = &fs->f->code[pc]; if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) return pi-1; else return pi; } /* ** check whether list has any jump that do not produce a value ** (or produce an inverted value) */ static int need_value (FuncState *fs, int list) { for (; list != NO_JUMP; list = getjump(fs, list)) { Instruction i = *getjumpcontrol(fs, list); if (GET_OPCODE(i) != OP_TESTSET) return 1; } return 0; /* not found */ } static int patchtestreg (FuncState *fs, int node, int reg) { Instruction *i = getjumpcontrol(fs, node); if (GET_OPCODE(*i) != OP_TESTSET) return 0; /* cannot patch other instructions */ if (reg != NO_REG && reg != GETARG_B(*i)) SETARG_A(*i, reg); else /* no register to put value or register already has the value */ *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); return 1; } static void removevalues (FuncState *fs, int list) { for (; list != NO_JUMP; list = getjump(fs, list)) patchtestreg(fs, list, NO_REG); } static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, int dtarget) { while (list != NO_JUMP) { int next = getjump(fs, list); if (patchtestreg(fs, list, reg)) fixjump(fs, list, vtarget); else fixjump(fs, list, dtarget); /* jump to default target */ list = next; } } static void dischargejpc (FuncState *fs) { patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); fs->jpc = NO_JUMP; } void luaK_patchlist (FuncState *fs, int list, int target) { if (target == fs->pc) luaK_patchtohere(fs, list); else { lua_assert(target < fs->pc); patchlistaux(fs, list, target, NO_REG, target); } } void luaK_patchtohere (FuncState *fs, int list) { luaK_getlabel(fs); luaK_concat(fs, &fs->jpc, list); } void luaK_concat (FuncState *fs, int *l1, int l2) { if (l2 == NO_JUMP) return; else if (*l1 == NO_JUMP) *l1 = l2; else { int list = *l1; int next; while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ list = next; fixjump(fs, list, l2); } } void luaK_checkstack (FuncState *fs, int n) { int newstack = fs->freereg + n; if (newstack > fs->f->maxstacksize) { if (newstack >= MAXSTACK) luaX_syntaxerror(fs->ls, "function or expression too complex"); fs->f->maxstacksize = cast_byte(newstack); } } void luaK_reserveregs (FuncState *fs, int n) { luaK_checkstack(fs, n); fs->freereg += n; } static void freereg (FuncState *fs, int reg) { if (!ISK(reg) && reg >= fs->nactvar) { fs->freereg--; lua_assert(reg == fs->freereg); } } static void freeexp (FuncState *fs, expdesc *e) { if (e->k == VNONRELOC) freereg(fs, e->u.s.info); } static int addk (FuncState *fs, TValue *k, TValue *v) { lua_State *L = fs->L; TValue *idx = luaH_set(L, fs->h, k); Proto *f = fs->f; int oldsize = f->sizek; if (ttisnumber(idx)) { lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); return cast_int(nvalue(idx)); } else { /* constant not found; create a new entry */ setnvalue(idx, cast_num(fs->nk)); luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, MAXARG_Bx, "constant table overflow"); while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); setobj(L, &f->k[fs->nk], v); luaC_barrier(L, f, v); return fs->nk++; } } int luaK_stringK (FuncState *fs, TString *s) { TValue o; setsvalue(fs->L, &o, s); return addk(fs, &o, &o); } int luaK_numberK (FuncState *fs, lua_Number r) { TValue o; setnvalue(&o, r); return addk(fs, &o, &o); } static int boolK (FuncState *fs, int b) { TValue o; setbvalue(&o, b); return addk(fs, &o, &o); } static int nilK (FuncState *fs) { TValue k, v; setnilvalue(&v); /* cannot use nil as key; instead use table itself to represent nil */ sethvalue(fs->L, &k, fs->h); return addk(fs, &k, &v); } void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { if (e->k == VCALL) { /* expression is an open function call? */ SETARG_C(getcode(fs, e), nresults+1); } else if (e->k == VVARARG) { SETARG_B(getcode(fs, e), nresults+1); SETARG_A(getcode(fs, e), fs->freereg); luaK_reserveregs(fs, 1); } } void luaK_setoneret (FuncState *fs, expdesc *e) { if (e->k == VCALL) { /* expression is an open function call? */ e->k = VNONRELOC; e->u.s.info = GETARG_A(getcode(fs, e)); } else if (e->k == VVARARG) { SETARG_B(getcode(fs, e), 2); e->k = VRELOCABLE; /* can relocate its simple result */ } } void luaK_dischargevars (FuncState *fs, expdesc *e) { switch (e->k) { case VLOCAL: { e->k = VNONRELOC; break; } case VUPVAL: { e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); e->k = VRELOCABLE; break; } case VGLOBAL: { e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); e->k = VRELOCABLE; break; } case VINDEXED: { freereg(fs, e->u.s.aux); freereg(fs, e->u.s.info); e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); e->k = VRELOCABLE; break; } case VVARARG: case VCALL: { luaK_setoneret(fs, e); break; } default: break; /* there is one value available (somewhere) */ } } static int code_label (FuncState *fs, int A, int b, int jump) { luaK_getlabel(fs); /* those instructions may be jump targets */ return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); } static void discharge2reg (FuncState *fs, expdesc *e, int reg) { luaK_dischargevars(fs, e); switch (e->k) { case VNIL: { luaK_nil(fs, reg, 1); break; } case VFALSE: case VTRUE: { luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); break; } case VK: { luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); break; } case VKNUM: { luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); break; } case VRELOCABLE: { Instruction *pc = &getcode(fs, e); SETARG_A(*pc, reg); break; } case VNONRELOC: { if (reg != e->u.s.info) luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); break; } default: { lua_assert(e->k == VVOID || e->k == VJMP); return; /* nothing to do... */ } } e->u.s.info = reg; e->k = VNONRELOC; } static void discharge2anyreg (FuncState *fs, expdesc *e) { if (e->k != VNONRELOC) { luaK_reserveregs(fs, 1); discharge2reg(fs, e, fs->freereg-1); } } static void exp2reg (FuncState *fs, expdesc *e, int reg) { discharge2reg(fs, e, reg); if (e->k == VJMP) luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ if (hasjumps(e)) { int final; /* position after whole expression */ int p_f = NO_JUMP; /* position of an eventual LOAD false */ int p_t = NO_JUMP; /* position of an eventual LOAD true */ if (need_value(fs, e->t) || need_value(fs, e->f)) { int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); p_f = code_label(fs, reg, 0, 1); p_t = code_label(fs, reg, 1, 0); luaK_patchtohere(fs, fj); } final = luaK_getlabel(fs); patchlistaux(fs, e->f, final, reg, p_f); patchlistaux(fs, e->t, final, reg, p_t); } e->f = e->t = NO_JUMP; e->u.s.info = reg; e->k = VNONRELOC; } void luaK_exp2nextreg (FuncState *fs, expdesc *e) { luaK_dischargevars(fs, e); freeexp(fs, e); luaK_reserveregs(fs, 1); exp2reg(fs, e, fs->freereg - 1); } int luaK_exp2anyreg (FuncState *fs, expdesc *e) { luaK_dischargevars(fs, e); if (e->k == VNONRELOC) { if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ exp2reg(fs, e, e->u.s.info); /* put value on it */ return e->u.s.info; } } luaK_exp2nextreg(fs, e); /* default */ return e->u.s.info; } void luaK_exp2val (FuncState *fs, expdesc *e) { if (hasjumps(e)) luaK_exp2anyreg(fs, e); else luaK_dischargevars(fs, e); } int luaK_exp2RK (FuncState *fs, expdesc *e) { luaK_exp2val(fs, e); switch (e->k) { case VKNUM: case VTRUE: case VFALSE: case VNIL: { if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ e->u.s.info = (e->k == VNIL) ? nilK(fs) : (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : boolK(fs, (e->k == VTRUE)); e->k = VK; return RKASK(e->u.s.info); } else break; } case VK: { if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ return RKASK(e->u.s.info); else break; } default: break; } /* not a constant in the right range: put it in a register */ return luaK_exp2anyreg(fs, e); } void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { switch (var->k) { case VLOCAL: { freeexp(fs, ex); exp2reg(fs, ex, var->u.s.info); return; } case VUPVAL: { int e = luaK_exp2anyreg(fs, ex); luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); break; } case VGLOBAL: { int e = luaK_exp2anyreg(fs, ex); luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); break; } case VINDEXED: { int e = luaK_exp2RK(fs, ex); luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); break; } default: { lua_assert(0); /* invalid var kind to store */ break; } } freeexp(fs, ex); } void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { int func; luaK_exp2anyreg(fs, e); freeexp(fs, e); func = fs->freereg; luaK_reserveregs(fs, 2); luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); freeexp(fs, key); e->u.s.info = func; e->k = VNONRELOC; } static void invertjump (FuncState *fs, expdesc *e) { Instruction *pc = getjumpcontrol(fs, e->u.s.info); lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && GET_OPCODE(*pc) != OP_TEST); SETARG_A(*pc, !(GETARG_A(*pc))); } static int jumponcond (FuncState *fs, expdesc *e, int cond) { if (e->k == VRELOCABLE) { Instruction ie = getcode(fs, e); if (GET_OPCODE(ie) == OP_NOT) { fs->pc--; /* remove previous OP_NOT */ return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); } /* else go through */ } discharge2anyreg(fs, e); freeexp(fs, e); return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); } void luaK_goiftrue (FuncState *fs, expdesc *e) { int pc; /* pc of last jump */ luaK_dischargevars(fs, e); switch (e->k) { case VK: case VKNUM: case VTRUE: { pc = NO_JUMP; /* always true; do nothing */ break; } case VFALSE: { pc = luaK_jump(fs); /* always jump */ break; } case VJMP: { invertjump(fs, e); pc = e->u.s.info; break; } default: { pc = jumponcond(fs, e, 0); break; } } luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ luaK_patchtohere(fs, e->t); e->t = NO_JUMP; } static void luaK_goiffalse (FuncState *fs, expdesc *e) { int pc; /* pc of last jump */ luaK_dischargevars(fs, e); switch (e->k) { case VNIL: case VFALSE: { pc = NO_JUMP; /* always false; do nothing */ break; } case VTRUE: { pc = luaK_jump(fs); /* always jump */ break; } case VJMP: { pc = e->u.s.info; break; } default: { pc = jumponcond(fs, e, 1); break; } } luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ luaK_patchtohere(fs, e->f); e->f = NO_JUMP; } static void codenot (FuncState *fs, expdesc *e) { luaK_dischargevars(fs, e); switch (e->k) { case VNIL: case VFALSE: { e->k = VTRUE; break; } case VK: case VKNUM: case VTRUE: { e->k = VFALSE; break; } case VJMP: { invertjump(fs, e); break; } case VRELOCABLE: case VNONRELOC: { discharge2anyreg(fs, e); freeexp(fs, e); e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); e->k = VRELOCABLE; break; } default: { lua_assert(0); /* cannot happen */ break; } } /* interchange true and false lists */ { int temp = e->f; e->f = e->t; e->t = temp; } removevalues(fs, e->f); removevalues(fs, e->t); } void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { t->u.s.aux = luaK_exp2RK(fs, k); t->k = VINDEXED; } static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { lua_Number v1, v2, r; if (!isnumeral(e1) || !isnumeral(e2)) return 0; v1 = e1->u.nval; v2 = e2->u.nval; switch (op) { case OP_ADD: r = luai_numadd(v1, v2); break; case OP_SUB: r = luai_numsub(v1, v2); break; case OP_MUL: r = luai_nummul(v1, v2); break; case OP_DIV: if (v2 == 0) return 0; /* do not attempt to divide by 0 */ r = luai_numdiv(v1, v2); break; case OP_MOD: if (v2 == 0) return 0; /* do not attempt to divide by 0 */ r = luai_nummod(v1, v2); break; case OP_POW: r = luai_numpow(v1, v2); break; case OP_UNM: r = luai_numunm(v1); break; case OP_LEN: return 0; /* no constant folding for 'len' */ default: lua_assert(0); r = 0; break; } if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ e1->u.nval = r; return 1; } static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { if (constfolding(op, e1, e2)) return; else { int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; int o1 = luaK_exp2RK(fs, e1); if (o1 > o2) { freeexp(fs, e1); freeexp(fs, e2); } else { freeexp(fs, e2); freeexp(fs, e1); } e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); e1->k = VRELOCABLE; } } static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, expdesc *e2) { int o1 = luaK_exp2RK(fs, e1); int o2 = luaK_exp2RK(fs, e2); freeexp(fs, e2); freeexp(fs, e1); if (cond == 0 && op != OP_EQ) { int temp; /* exchange args to replace by `<' or `<=' */ temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ cond = 1; } e1->u.s.info = condjump(fs, op, cond, o1, o2); e1->k = VJMP; } void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { expdesc e2; e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; switch (op) { case OPR_MINUS: { if (!isnumeral(e)) luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ codearith(fs, OP_UNM, e, &e2); break; } case OPR_NOT: codenot(fs, e); break; case OPR_LEN: { luaK_exp2anyreg(fs, e); /* cannot operate on constants */ codearith(fs, OP_LEN, e, &e2); break; } default: lua_assert(0); } } void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { switch (op) { case OPR_AND: { luaK_goiftrue(fs, v); break; } case OPR_OR: { luaK_goiffalse(fs, v); break; } case OPR_CONCAT: { luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ break; } case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: case OPR_MOD: case OPR_POW: { if (!isnumeral(v)) luaK_exp2RK(fs, v); break; } default: { luaK_exp2RK(fs, v); break; } } } void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { switch (op) { case OPR_AND: { lua_assert(e1->t == NO_JUMP); /* list must be closed */ luaK_dischargevars(fs, e2); luaK_concat(fs, &e2->f, e1->f); *e1 = *e2; break; } case OPR_OR: { lua_assert(e1->f == NO_JUMP); /* list must be closed */ luaK_dischargevars(fs, e2); luaK_concat(fs, &e2->t, e1->t); *e1 = *e2; break; } case OPR_CONCAT: { luaK_exp2val(fs, e2); if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); freeexp(fs, e1); SETARG_B(getcode(fs, e2), e1->u.s.info); e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; } else { luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ codearith(fs, OP_CONCAT, e1, e2); } break; } case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; case OPR_POW: codearith(fs, OP_POW, e1, e2); break; case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; default: lua_assert(0); } } void luaK_fixline (FuncState *fs, int line) { fs->f->lineinfo[fs->pc - 1] = line; } static int luaK_code (FuncState *fs, Instruction i, int line) { Proto *f = fs->f; dischargejpc(fs); /* `pc' will change */ /* put new instruction in code array */ luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, MAX_INT, "code size overflow"); f->code[fs->pc] = i; /* save corresponding line information */ luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, MAX_INT, "code size overflow"); f->lineinfo[fs->pc] = line; return fs->pc++; } int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { lua_assert(getOpMode(o) == iABC); lua_assert(getBMode(o) != OpArgN || b == 0); lua_assert(getCMode(o) != OpArgN || c == 0); return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); } int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); lua_assert(getCMode(o) == OpArgN); return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); } void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; int b = (tostore == LUA_MULTRET) ? 0 : tostore; lua_assert(tostore != 0); if (c <= MAXARG_C) luaK_codeABC(fs, OP_SETLIST, base, b, c); else { luaK_codeABC(fs, OP_SETLIST, base, b, 0); luaK_code(fs, cast(Instruction, c), fs->ls->lastline); } fs->freereg = base + 1; /* free registers with list values */ } bam-0.4.0/src/lua/lfunc.c0000644000175000017500000001101211430042030013155 0ustar kmakma/* ** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ #include #define lfunc_c #define LUA_CORE #include "lua.h" #include "lfunc.h" #include "lgc.h" #include "lmem.h" #include "lobject.h" #include "lstate.h" Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); luaC_link(L, obj2gco(c), LUA_TFUNCTION); c->c.isC = 1; c->c.env = e; c->c.nupvalues = cast_byte(nelems); return c; } Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); luaC_link(L, obj2gco(c), LUA_TFUNCTION); c->l.isC = 0; c->l.env = e; c->l.nupvalues = cast_byte(nelems); while (nelems--) c->l.upvals[nelems] = NULL; return c; } UpVal *luaF_newupval (lua_State *L) { UpVal *uv = luaM_new(L, UpVal); luaC_link(L, obj2gco(uv), LUA_TUPVAL); uv->v = &uv->u.value; setnilvalue(uv->v); return uv; } UpVal *luaF_findupval (lua_State *L, StkId level) { global_State *g = G(L); GCObject **pp = &L->openupval; UpVal *p; UpVal *uv; while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { lua_assert(p->v != &p->u.value); if (p->v == level) { /* found a corresponding upvalue? */ if (isdead(g, obj2gco(p))) /* is it dead? */ changewhite(obj2gco(p)); /* ressurect it */ return p; } pp = &p->next; } uv = luaM_new(L, UpVal); /* not found: create a new one */ uv->tt = LUA_TUPVAL; uv->marked = luaC_white(g); uv->v = level; /* current value lives in the stack */ uv->next = *pp; /* chain it in the proper position */ *pp = obj2gco(uv); uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ uv->u.l.next = g->uvhead.u.l.next; uv->u.l.next->u.l.prev = uv; g->uvhead.u.l.next = uv; lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); return uv; } static void unlinkupval (UpVal *uv) { lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ uv->u.l.prev->u.l.next = uv->u.l.next; } void luaF_freeupval (lua_State *L, UpVal *uv) { if (uv->v != &uv->u.value) /* is it open? */ unlinkupval(uv); /* remove from open list */ luaM_free(L, uv); /* free upvalue */ } void luaF_close (lua_State *L, StkId level) { UpVal *uv; global_State *g = G(L); while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { GCObject *o = obj2gco(uv); lua_assert(!isblack(o) && uv->v != &uv->u.value); L->openupval = uv->next; /* remove from `open' list */ if (isdead(g, o)) luaF_freeupval(L, uv); /* free upvalue */ else { unlinkupval(uv); setobj(L, &uv->u.value, uv->v); uv->v = &uv->u.value; /* now current value lives here */ luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ } } } Proto *luaF_newproto (lua_State *L) { Proto *f = luaM_new(L, Proto); luaC_link(L, obj2gco(f), LUA_TPROTO); f->k = NULL; f->sizek = 0; f->p = NULL; f->sizep = 0; f->code = NULL; f->sizecode = 0; f->sizelineinfo = 0; f->sizeupvalues = 0; f->nups = 0; f->upvalues = NULL; f->numparams = 0; f->is_vararg = 0; f->maxstacksize = 0; f->lineinfo = NULL; f->sizelocvars = 0; f->locvars = NULL; f->linedefined = 0; f->lastlinedefined = 0; f->source = NULL; return f; } void luaF_freeproto (lua_State *L, Proto *f) { luaM_freearray(L, f->code, f->sizecode, Instruction); luaM_freearray(L, f->p, f->sizep, Proto *); luaM_freearray(L, f->k, f->sizek, TValue); luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); luaM_free(L, f); } void luaF_freeclosure (lua_State *L, Closure *c) { int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : sizeLclosure(c->l.nupvalues); luaM_freemem(L, c, size); } /* ** Look for n-th local variable at line `line' in function `func'. ** Returns NULL if not found. */ const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { int i; for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { if (pc < f->locvars[i].endpc) { /* is variable active? */ local_number--; if (local_number == 0) return getstr(f->locvars[i].varname); } } return NULL; /* not found */ } bam-0.4.0/src/lua/llex.h0000644000175000017500000000420111430042030013021 0ustar kmakma/* ** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ #ifndef llex_h #define llex_h #include "lobject.h" #include "lzio.h" #define FIRST_RESERVED 257 /* maximum length of a reserved word */ #define TOKEN_LEN (sizeof("function")/sizeof(char)) /* * WARNING: if you change the order of this enumeration, * grep "ORDER RESERVED" */ enum RESERVED { /* terminal symbols denoted by reserved words */ TK_AND = FIRST_RESERVED, TK_BREAK, TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, /* other terminal symbols */ TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, TK_NAME, TK_STRING, TK_EOS }; /* number of reserved words */ #define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) /* array with token `names' */ LUAI_DATA const char *const luaX_tokens []; typedef union { lua_Number r; TString *ts; } SemInfo; /* semantics information */ typedef struct Token { int token; SemInfo seminfo; } Token; typedef struct LexState { int current; /* current character (charint) */ int linenumber; /* input line counter */ int lastline; /* line of last token `consumed' */ Token t; /* current token */ Token lookahead; /* look ahead token */ struct FuncState *fs; /* `FuncState' is private to the parser */ struct lua_State *L; ZIO *z; /* input stream */ Mbuffer *buff; /* buffer for tokens */ TString *source; /* current source name */ char decpoint; /* locale decimal point */ } LexState; LUAI_FUNC void luaX_init (lua_State *L); LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source); LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); LUAI_FUNC void luaX_next (LexState *ls); LUAI_FUNC void luaX_lookahead (LexState *ls); LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); #endif bam-0.4.0/src/lua/ldo.h0000644000175000017500000000355111430042030012642 0ustar kmakma/* ** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ #ifndef ldo_h #define ldo_h #include "lobject.h" #include "lstate.h" #include "lzio.h" #define luaD_checkstack(L,n) \ if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ luaD_growstack(L, n); \ else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); #define incr_top(L) {luaD_checkstack(L,1); L->top++;} #define savestack(L,p) ((char *)(p) - (char *)L->stack) #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) #define saveci(L,p) ((char *)(p) - (char *)L->base_ci) #define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) /* results from luaD_precall */ #define PCRLUA 0 /* initiated a call to a Lua function */ #define PCRC 1 /* did a call to a C function */ #define PCRYIELD 2 /* C funtion yielded */ /* type of protected functions, to be ran by `runprotected' */ typedef void (*Pfunc) (lua_State *L, void *ud); LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t oldtop, ptrdiff_t ef); LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); LUAI_FUNC void luaD_growstack (lua_State *L, int n); LUAI_FUNC void luaD_throw (lua_State *L, int errcode); LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); #endif bam-0.4.0/src/lua/lmem.h0000644000175000017500000000272611430042030013021 0ustar kmakma/* ** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ #ifndef lmem_h #define lmem_h #include #include "llimits.h" #include "lua.h" #define MEMERRMSG "not enough memory" #define luaM_reallocv(L,b,on,n,e) \ ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ luaM_toobig(L)) #define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) #define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) #define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) #define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) #define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) #define luaM_newvector(L,n,t) \ cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) #define luaM_growvector(L,v,nelems,size,t,limit,e) \ if ((nelems)+1 > (size)) \ ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) #define luaM_reallocvector(L, v,oldn,n,t) \ ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, size_t size); LUAI_FUNC void *luaM_toobig (lua_State *L); LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elem, int limit, const char *errormsg); #endif bam-0.4.0/src/lua/lstring.h0000644000175000017500000000145611430042030013550 0ustar kmakma/* ** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ ** String table (keep all strings handled by Lua) ** See Copyright Notice in lua.h */ #ifndef lstring_h #define lstring_h #include "lgc.h" #include "lobject.h" #include "lstate.h" #define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) #define sizeudata(u) (sizeof(union Udata)+(u)->len) #define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ (sizeof(s)/sizeof(char))-1)) #define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) LUAI_FUNC void luaS_resize (lua_State *L, int newsize); LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); #endif bam-0.4.0/src/lua/lparser.c0000644000175000017500000010753011430042030013531 0ustar kmakma/* ** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ #include #define lparser_c #define LUA_CORE #include "lua.h" #include "lcode.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" #include "llex.h" #include "lmem.h" #include "lobject.h" #include "lopcodes.h" #include "lparser.h" #include "lstate.h" #include "lstring.h" #include "ltable.h" #define hasmultret(k) ((k) == VCALL || (k) == VVARARG) #define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) #define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) /* ** nodes for block list (list of active blocks) */ typedef struct BlockCnt { struct BlockCnt *previous; /* chain */ int breaklist; /* list of jumps out of this loop */ lu_byte nactvar; /* # active locals outside the breakable structure */ lu_byte upval; /* true if some variable in the block is an upvalue */ lu_byte isbreakable; /* true if `block' is a loop */ } BlockCnt; /* ** prototypes for recursive non-terminal functions */ static void chunk (LexState *ls); static void expr (LexState *ls, expdesc *v); static void anchor_token (LexState *ls) { if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { TString *ts = ls->t.seminfo.ts; luaX_newstring(ls, getstr(ts), ts->tsv.len); } } static void error_expected (LexState *ls, int token) { luaX_syntaxerror(ls, luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); } static void errorlimit (FuncState *fs, int limit, const char *what) { const char *msg = (fs->f->linedefined == 0) ? luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : luaO_pushfstring(fs->L, "function at line %d has more than %d %s", fs->f->linedefined, limit, what); luaX_lexerror(fs->ls, msg, 0); } static int testnext (LexState *ls, int c) { if (ls->t.token == c) { luaX_next(ls); return 1; } else return 0; } static void check (LexState *ls, int c) { if (ls->t.token != c) error_expected(ls, c); } static void checknext (LexState *ls, int c) { check(ls, c); luaX_next(ls); } #define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } static void check_match (LexState *ls, int what, int who, int where) { if (!testnext(ls, what)) { if (where == ls->linenumber) error_expected(ls, what); else { luaX_syntaxerror(ls, luaO_pushfstring(ls->L, LUA_QS " expected (to close " LUA_QS " at line %d)", luaX_token2str(ls, what), luaX_token2str(ls, who), where)); } } } static TString *str_checkname (LexState *ls) { TString *ts; check(ls, TK_NAME); ts = ls->t.seminfo.ts; luaX_next(ls); return ts; } static void init_exp (expdesc *e, expkind k, int i) { e->f = e->t = NO_JUMP; e->k = k; e->u.s.info = i; } static void codestring (LexState *ls, expdesc *e, TString *s) { init_exp(e, VK, luaK_stringK(ls->fs, s)); } static void checkname(LexState *ls, expdesc *e) { codestring(ls, e, str_checkname(ls)); } static int registerlocalvar (LexState *ls, TString *varname) { FuncState *fs = ls->fs; Proto *f = fs->f; int oldsize = f->sizelocvars; luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, LocVar, SHRT_MAX, "too many local variables"); while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; f->locvars[fs->nlocvars].varname = varname; luaC_objbarrier(ls->L, f, varname); return fs->nlocvars++; } #define new_localvarliteral(ls,v,n) \ new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) static void new_localvar (LexState *ls, TString *name, int n) { FuncState *fs = ls->fs; luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); } static void adjustlocalvars (LexState *ls, int nvars) { FuncState *fs = ls->fs; fs->nactvar = cast_byte(fs->nactvar + nvars); for (; nvars; nvars--) { getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; } } static void removevars (LexState *ls, int tolevel) { FuncState *fs = ls->fs; while (fs->nactvar > tolevel) getlocvar(fs, --fs->nactvar).endpc = fs->pc; } static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { int i; Proto *f = fs->f; int oldsize = f->sizeupvalues; for (i=0; inups; i++) { if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { lua_assert(f->upvalues[i] == name); return i; } } /* new one */ luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, TString *, MAX_INT, ""); while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; f->upvalues[f->nups] = name; luaC_objbarrier(fs->L, f, name); lua_assert(v->k == VLOCAL || v->k == VUPVAL); fs->upvalues[f->nups].k = cast_byte(v->k); fs->upvalues[f->nups].info = cast_byte(v->u.s.info); return f->nups++; } static int searchvar (FuncState *fs, TString *n) { int i; for (i=fs->nactvar-1; i >= 0; i--) { if (n == getlocvar(fs, i).varname) return i; } return -1; /* not found */ } static void markupval (FuncState *fs, int level) { BlockCnt *bl = fs->bl; while (bl && bl->nactvar > level) bl = bl->previous; if (bl) bl->upval = 1; } static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { if (fs == NULL) { /* no more levels? */ init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ return VGLOBAL; } else { int v = searchvar(fs, n); /* look up at current level */ if (v >= 0) { init_exp(var, VLOCAL, v); if (!base) markupval(fs, v); /* local will be used as an upval */ return VLOCAL; } else { /* not found at current level; try upper one */ if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) return VGLOBAL; var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ var->k = VUPVAL; /* upvalue in this level */ return VUPVAL; } } } static void singlevar (LexState *ls, expdesc *var) { TString *varname = str_checkname(ls); FuncState *fs = ls->fs; if (singlevaraux(fs, varname, var, 1) == VGLOBAL) var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ } static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { FuncState *fs = ls->fs; int extra = nvars - nexps; if (hasmultret(e->k)) { extra++; /* includes call itself */ if (extra < 0) extra = 0; luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ if (extra > 1) luaK_reserveregs(fs, extra-1); } else { if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ if (extra > 0) { int reg = fs->freereg; luaK_reserveregs(fs, extra); luaK_nil(fs, reg, extra); } } } static void enterlevel (LexState *ls) { if (++ls->L->nCcalls > LUAI_MAXCCALLS) luaX_lexerror(ls, "chunk has too many syntax levels", 0); } #define leavelevel(ls) ((ls)->L->nCcalls--) static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { bl->breaklist = NO_JUMP; bl->isbreakable = isbreakable; bl->nactvar = fs->nactvar; bl->upval = 0; bl->previous = fs->bl; fs->bl = bl; lua_assert(fs->freereg == fs->nactvar); } static void leaveblock (FuncState *fs) { BlockCnt *bl = fs->bl; fs->bl = bl->previous; removevars(fs->ls, bl->nactvar); if (bl->upval) luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); /* a block either controls scope or breaks (never both) */ lua_assert(!bl->isbreakable || !bl->upval); lua_assert(bl->nactvar == fs->nactvar); fs->freereg = fs->nactvar; /* free registers */ luaK_patchtohere(fs, bl->breaklist); } static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { FuncState *fs = ls->fs; Proto *f = fs->f; int oldsize = f->sizep; int i; luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "constant table overflow"); while (oldsize < f->sizep) f->p[oldsize++] = NULL; f->p[fs->np++] = func->f; luaC_objbarrier(ls->L, f, func->f); init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); for (i=0; if->nups; i++) { OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); } } static void open_func (LexState *ls, FuncState *fs) { lua_State *L = ls->L; Proto *f = luaF_newproto(L); fs->f = f; fs->prev = ls->fs; /* linked list of funcstates */ fs->ls = ls; fs->L = L; ls->fs = fs; fs->pc = 0; fs->lasttarget = -1; fs->jpc = NO_JUMP; fs->freereg = 0; fs->nk = 0; fs->np = 0; fs->nlocvars = 0; fs->nactvar = 0; fs->bl = NULL; f->source = ls->source; f->maxstacksize = 2; /* registers 0/1 are always valid */ fs->h = luaH_new(L, 0, 0); /* anchor table of constants and prototype (to avoid being collected) */ sethvalue2s(L, L->top, fs->h); incr_top(L); setptvalue2s(L, L->top, f); incr_top(L); } static void close_func (LexState *ls) { lua_State *L = ls->L; FuncState *fs = ls->fs; Proto *f = fs->f; removevars(ls, 0); luaK_ret(fs, 0, 0); /* final return */ luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); f->sizecode = fs->pc; luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); f->sizelineinfo = fs->pc; luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); f->sizek = fs->nk; luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); f->sizep = fs->np; luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); f->sizelocvars = fs->nlocvars; luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); f->sizeupvalues = f->nups; lua_assert(luaG_checkcode(f)); lua_assert(fs->bl == NULL); ls->fs = fs->prev; L->top -= 2; /* remove table and prototype from the stack */ /* last token read was anchored in defunct function; must reanchor it */ if (fs) anchor_token(ls); } Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { struct LexState lexstate; struct FuncState funcstate; lexstate.buff = buff; luaX_setinput(L, &lexstate, z, luaS_new(L, name)); open_func(&lexstate, &funcstate); funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ luaX_next(&lexstate); /* read first token */ chunk(&lexstate); check(&lexstate, TK_EOS); close_func(&lexstate); lua_assert(funcstate.prev == NULL); lua_assert(funcstate.f->nups == 0); lua_assert(lexstate.fs == NULL); return funcstate.f; } /*============================================================*/ /* GRAMMAR RULES */ /*============================================================*/ static void field (LexState *ls, expdesc *v) { /* field -> ['.' | ':'] NAME */ FuncState *fs = ls->fs; expdesc key; luaK_exp2anyreg(fs, v); luaX_next(ls); /* skip the dot or colon */ checkname(ls, &key); luaK_indexed(fs, v, &key); } static void yindex (LexState *ls, expdesc *v) { /* index -> '[' expr ']' */ luaX_next(ls); /* skip the '[' */ expr(ls, v); luaK_exp2val(ls->fs, v); checknext(ls, ']'); } /* ** {====================================================================== ** Rules for Constructors ** ======================================================================= */ struct ConsControl { expdesc v; /* last list item read */ expdesc *t; /* table descriptor */ int nh; /* total number of `record' elements */ int na; /* total number of array elements */ int tostore; /* number of array elements pending to be stored */ }; static void recfield (LexState *ls, struct ConsControl *cc) { /* recfield -> (NAME | `['exp1`]') = exp1 */ FuncState *fs = ls->fs; int reg = ls->fs->freereg; expdesc key, val; int rkkey; if (ls->t.token == TK_NAME) { luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); checkname(ls, &key); } else /* ls->t.token == '[' */ yindex(ls, &key); cc->nh++; checknext(ls, '='); rkkey = luaK_exp2RK(fs, &key); expr(ls, &val); luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); fs->freereg = reg; /* free registers */ } static void closelistfield (FuncState *fs, struct ConsControl *cc) { if (cc->v.k == VVOID) return; /* there is no list item */ luaK_exp2nextreg(fs, &cc->v); cc->v.k = VVOID; if (cc->tostore == LFIELDS_PER_FLUSH) { luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ cc->tostore = 0; /* no more items pending */ } } static void lastlistfield (FuncState *fs, struct ConsControl *cc) { if (cc->tostore == 0) return; if (hasmultret(cc->v.k)) { luaK_setmultret(fs, &cc->v); luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); cc->na--; /* do not count last expression (unknown number of elements) */ } else { if (cc->v.k != VVOID) luaK_exp2nextreg(fs, &cc->v); luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); } } static void listfield (LexState *ls, struct ConsControl *cc) { expr(ls, &cc->v); luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); cc->na++; cc->tostore++; } static void constructor (LexState *ls, expdesc *t) { /* constructor -> ?? */ FuncState *fs = ls->fs; int line = ls->linenumber; int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); struct ConsControl cc; cc.na = cc.nh = cc.tostore = 0; cc.t = t; init_exp(t, VRELOCABLE, pc); init_exp(&cc.v, VVOID, 0); /* no value (yet) */ luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ checknext(ls, '{'); do { lua_assert(cc.v.k == VVOID || cc.tostore > 0); if (ls->t.token == '}') break; closelistfield(fs, &cc); switch(ls->t.token) { case TK_NAME: { /* may be listfields or recfields */ luaX_lookahead(ls); if (ls->lookahead.token != '=') /* expression? */ listfield(ls, &cc); else recfield(ls, &cc); break; } case '[': { /* constructor_item -> recfield */ recfield(ls, &cc); break; } default: { /* constructor_part -> listfield */ listfield(ls, &cc); break; } } } while (testnext(ls, ',') || testnext(ls, ';')); check_match(ls, '}', '{', line); lastlistfield(fs, &cc); SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ } /* }====================================================================== */ static void parlist (LexState *ls) { /* parlist -> [ param { `,' param } ] */ FuncState *fs = ls->fs; Proto *f = fs->f; int nparams = 0; f->is_vararg = 0; if (ls->t.token != ')') { /* is `parlist' not empty? */ do { switch (ls->t.token) { case TK_NAME: { /* param -> NAME */ new_localvar(ls, str_checkname(ls), nparams++); break; } case TK_DOTS: { /* param -> `...' */ luaX_next(ls); #if defined(LUA_COMPAT_VARARG) /* use `arg' as default name */ new_localvarliteral(ls, "arg", nparams++); f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; #endif f->is_vararg |= VARARG_ISVARARG; break; } default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); } } while (!f->is_vararg && testnext(ls, ',')); } adjustlocalvars(ls, nparams); f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ } static void body (LexState *ls, expdesc *e, int needself, int line) { /* body -> `(' parlist `)' chunk END */ FuncState new_fs; open_func(ls, &new_fs); new_fs.f->linedefined = line; checknext(ls, '('); if (needself) { new_localvarliteral(ls, "self", 0); adjustlocalvars(ls, 1); } parlist(ls); checknext(ls, ')'); chunk(ls); new_fs.f->lastlinedefined = ls->linenumber; check_match(ls, TK_END, TK_FUNCTION, line); close_func(ls); pushclosure(ls, &new_fs, e); } static int explist1 (LexState *ls, expdesc *v) { /* explist1 -> expr { `,' expr } */ int n = 1; /* at least one expression */ expr(ls, v); while (testnext(ls, ',')) { luaK_exp2nextreg(ls->fs, v); expr(ls, v); n++; } return n; } static void funcargs (LexState *ls, expdesc *f) { FuncState *fs = ls->fs; expdesc args; int base, nparams; int line = ls->linenumber; switch (ls->t.token) { case '(': { /* funcargs -> `(' [ explist1 ] `)' */ if (line != ls->lastline) luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); luaX_next(ls); if (ls->t.token == ')') /* arg list is empty? */ args.k = VVOID; else { explist1(ls, &args); luaK_setmultret(fs, &args); } check_match(ls, ')', '(', line); break; } case '{': { /* funcargs -> constructor */ constructor(ls, &args); break; } case TK_STRING: { /* funcargs -> STRING */ codestring(ls, &args, ls->t.seminfo.ts); luaX_next(ls); /* must use `seminfo' before `next' */ break; } default: { luaX_syntaxerror(ls, "function arguments expected"); return; } } lua_assert(f->k == VNONRELOC); base = f->u.s.info; /* base register for call */ if (hasmultret(args.k)) nparams = LUA_MULTRET; /* open call */ else { if (args.k != VVOID) luaK_exp2nextreg(fs, &args); /* close last argument */ nparams = fs->freereg - (base+1); } init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); luaK_fixline(fs, line); fs->freereg = base+1; /* call remove function and arguments and leaves (unless changed) one result */ } /* ** {====================================================================== ** Expression parsing ** ======================================================================= */ static void prefixexp (LexState *ls, expdesc *v) { /* prefixexp -> NAME | '(' expr ')' */ switch (ls->t.token) { case '(': { int line = ls->linenumber; luaX_next(ls); expr(ls, v); check_match(ls, ')', '(', line); luaK_dischargevars(ls->fs, v); return; } case TK_NAME: { singlevar(ls, v); return; } default: { luaX_syntaxerror(ls, "unexpected symbol"); return; } } } static void primaryexp (LexState *ls, expdesc *v) { /* primaryexp -> prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ FuncState *fs = ls->fs; prefixexp(ls, v); for (;;) { switch (ls->t.token) { case '.': { /* field */ field(ls, v); break; } case '[': { /* `[' exp1 `]' */ expdesc key; luaK_exp2anyreg(fs, v); yindex(ls, &key); luaK_indexed(fs, v, &key); break; } case ':': { /* `:' NAME funcargs */ expdesc key; luaX_next(ls); checkname(ls, &key); luaK_self(fs, v, &key); funcargs(ls, v); break; } case '(': case TK_STRING: case '{': { /* funcargs */ luaK_exp2nextreg(fs, v); funcargs(ls, v); break; } default: return; } } } static void simpleexp (LexState *ls, expdesc *v) { /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | constructor | FUNCTION body | primaryexp */ switch (ls->t.token) { case TK_NUMBER: { init_exp(v, VKNUM, 0); v->u.nval = ls->t.seminfo.r; break; } case TK_STRING: { codestring(ls, v, ls->t.seminfo.ts); break; } case TK_NIL: { init_exp(v, VNIL, 0); break; } case TK_TRUE: { init_exp(v, VTRUE, 0); break; } case TK_FALSE: { init_exp(v, VFALSE, 0); break; } case TK_DOTS: { /* vararg */ FuncState *fs = ls->fs; check_condition(ls, fs->f->is_vararg, "cannot use " LUA_QL("...") " outside a vararg function"); fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); break; } case '{': { /* constructor */ constructor(ls, v); return; } case TK_FUNCTION: { luaX_next(ls); body(ls, v, 0, ls->linenumber); return; } default: { primaryexp(ls, v); return; } } luaX_next(ls); } static UnOpr getunopr (int op) { switch (op) { case TK_NOT: return OPR_NOT; case '-': return OPR_MINUS; case '#': return OPR_LEN; default: return OPR_NOUNOPR; } } static BinOpr getbinopr (int op) { switch (op) { case '+': return OPR_ADD; case '-': return OPR_SUB; case '*': return OPR_MUL; case '/': return OPR_DIV; case '%': return OPR_MOD; case '^': return OPR_POW; case TK_CONCAT: return OPR_CONCAT; case TK_NE: return OPR_NE; case TK_EQ: return OPR_EQ; case '<': return OPR_LT; case TK_LE: return OPR_LE; case '>': return OPR_GT; case TK_GE: return OPR_GE; case TK_AND: return OPR_AND; case TK_OR: return OPR_OR; default: return OPR_NOBINOPR; } } static const struct { lu_byte left; /* left priority for each binary operator */ lu_byte right; /* right priority */ } priority[] = { /* ORDER OPR */ {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ {10, 9}, {5, 4}, /* power and concat (right associative) */ {3, 3}, {3, 3}, /* equality and inequality */ {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ {2, 2}, {1, 1} /* logical (and/or) */ }; #define UNARY_PRIORITY 8 /* priority for unary operators */ /* ** subexpr -> (simpleexp | unop subexpr) { binop subexpr } ** where `binop' is any binary operator with a priority higher than `limit' */ static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { BinOpr op; UnOpr uop; enterlevel(ls); uop = getunopr(ls->t.token); if (uop != OPR_NOUNOPR) { luaX_next(ls); subexpr(ls, v, UNARY_PRIORITY); luaK_prefix(ls->fs, uop, v); } else simpleexp(ls, v); /* expand while operators have priorities higher than `limit' */ op = getbinopr(ls->t.token); while (op != OPR_NOBINOPR && priority[op].left > limit) { expdesc v2; BinOpr nextop; luaX_next(ls); luaK_infix(ls->fs, op, v); /* read sub-expression with higher priority */ nextop = subexpr(ls, &v2, priority[op].right); luaK_posfix(ls->fs, op, v, &v2); op = nextop; } leavelevel(ls); return op; /* return first untreated operator */ } static void expr (LexState *ls, expdesc *v) { subexpr(ls, v, 0); } /* }==================================================================== */ /* ** {====================================================================== ** Rules for Statements ** ======================================================================= */ static int block_follow (int token) { switch (token) { case TK_ELSE: case TK_ELSEIF: case TK_END: case TK_UNTIL: case TK_EOS: return 1; default: return 0; } } static void block (LexState *ls) { /* block -> chunk */ FuncState *fs = ls->fs; BlockCnt bl; enterblock(fs, &bl, 0); chunk(ls); lua_assert(bl.breaklist == NO_JUMP); leaveblock(fs); } /* ** structure to chain all variables in the left-hand side of an ** assignment */ struct LHS_assign { struct LHS_assign *prev; expdesc v; /* variable (global, local, upvalue, or indexed) */ }; /* ** check whether, in an assignment to a local variable, the local variable ** is needed in a previous assignment (to a table). If so, save original ** local value in a safe place and use this safe copy in the previous ** assignment. */ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { FuncState *fs = ls->fs; int extra = fs->freereg; /* eventual position to save local variable */ int conflict = 0; for (; lh; lh = lh->prev) { if (lh->v.k == VINDEXED) { if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ conflict = 1; lh->v.u.s.info = extra; /* previous assignment will use safe copy */ } if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ conflict = 1; lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ } } } if (conflict) { luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ luaK_reserveregs(fs, 1); } } static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { expdesc e; check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, "syntax error"); if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ struct LHS_assign nv; nv.prev = lh; primaryexp(ls, &nv.v); if (nv.v.k == VLOCAL) check_conflict(ls, lh, &nv.v); luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, "variables in assignment"); assignment(ls, &nv, nvars+1); } else { /* assignment -> `=' explist1 */ int nexps; checknext(ls, '='); nexps = explist1(ls, &e); if (nexps != nvars) { adjust_assign(ls, nvars, nexps, &e); if (nexps > nvars) ls->fs->freereg -= nexps - nvars; /* remove extra values */ } else { luaK_setoneret(ls->fs, &e); /* close last expression */ luaK_storevar(ls->fs, &lh->v, &e); return; /* avoid default */ } } init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ luaK_storevar(ls->fs, &lh->v, &e); } static int cond (LexState *ls) { /* cond -> exp */ expdesc v; expr(ls, &v); /* read condition */ if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ luaK_goiftrue(ls->fs, &v); return v.f; } static void breakstat (LexState *ls) { FuncState *fs = ls->fs; BlockCnt *bl = fs->bl; int upval = 0; while (bl && !bl->isbreakable) { upval |= bl->upval; bl = bl->previous; } if (!bl) luaX_syntaxerror(ls, "no loop to break"); if (upval) luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); } static void whilestat (LexState *ls, int line) { /* whilestat -> WHILE cond DO block END */ FuncState *fs = ls->fs; int whileinit; int condexit; BlockCnt bl; luaX_next(ls); /* skip WHILE */ whileinit = luaK_getlabel(fs); condexit = cond(ls); enterblock(fs, &bl, 1); checknext(ls, TK_DO); block(ls); luaK_patchlist(fs, luaK_jump(fs), whileinit); check_match(ls, TK_END, TK_WHILE, line); leaveblock(fs); luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ } static void repeatstat (LexState *ls, int line) { /* repeatstat -> REPEAT block UNTIL cond */ int condexit; FuncState *fs = ls->fs; int repeat_init = luaK_getlabel(fs); BlockCnt bl1, bl2; enterblock(fs, &bl1, 1); /* loop block */ enterblock(fs, &bl2, 0); /* scope block */ luaX_next(ls); /* skip REPEAT */ chunk(ls); check_match(ls, TK_UNTIL, TK_REPEAT, line); condexit = cond(ls); /* read condition (inside scope block) */ if (!bl2.upval) { /* no upvalues? */ leaveblock(fs); /* finish scope */ luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ } else { /* complete semantics when there are upvalues */ breakstat(ls); /* if condition then break */ luaK_patchtohere(ls->fs, condexit); /* else... */ leaveblock(fs); /* finish scope... */ luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ } leaveblock(fs); /* finish loop */ } static int exp1 (LexState *ls) { expdesc e; int k; expr(ls, &e); k = e.k; luaK_exp2nextreg(ls->fs, &e); return k; } static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { /* forbody -> DO block */ BlockCnt bl; FuncState *fs = ls->fs; int prep, endfor; adjustlocalvars(ls, 3); /* control variables */ checknext(ls, TK_DO); prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); enterblock(fs, &bl, 0); /* scope for declared variables */ adjustlocalvars(ls, nvars); luaK_reserveregs(fs, nvars); block(ls); leaveblock(fs); /* end of scope for declared variables */ luaK_patchtohere(fs, prep); endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); } static void fornum (LexState *ls, TString *varname, int line) { /* fornum -> NAME = exp1,exp1[,exp1] forbody */ FuncState *fs = ls->fs; int base = fs->freereg; new_localvarliteral(ls, "(for index)", 0); new_localvarliteral(ls, "(for limit)", 1); new_localvarliteral(ls, "(for step)", 2); new_localvar(ls, varname, 3); checknext(ls, '='); exp1(ls); /* initial value */ checknext(ls, ','); exp1(ls); /* limit */ if (testnext(ls, ',')) exp1(ls); /* optional step */ else { /* default step = 1 */ luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); luaK_reserveregs(fs, 1); } forbody(ls, base, line, 1, 1); } static void forlist (LexState *ls, TString *indexname) { /* forlist -> NAME {,NAME} IN explist1 forbody */ FuncState *fs = ls->fs; expdesc e; int nvars = 0; int line; int base = fs->freereg; /* create control variables */ new_localvarliteral(ls, "(for generator)", nvars++); new_localvarliteral(ls, "(for state)", nvars++); new_localvarliteral(ls, "(for control)", nvars++); /* create declared variables */ new_localvar(ls, indexname, nvars++); while (testnext(ls, ',')) new_localvar(ls, str_checkname(ls), nvars++); checknext(ls, TK_IN); line = ls->linenumber; adjust_assign(ls, 3, explist1(ls, &e), &e); luaK_checkstack(fs, 3); /* extra space to call generator */ forbody(ls, base, line, nvars - 3, 0); } static void forstat (LexState *ls, int line) { /* forstat -> FOR (fornum | forlist) END */ FuncState *fs = ls->fs; TString *varname; BlockCnt bl; enterblock(fs, &bl, 1); /* scope for loop and control variables */ luaX_next(ls); /* skip `for' */ varname = str_checkname(ls); /* first variable name */ switch (ls->t.token) { case '=': fornum(ls, varname, line); break; case ',': case TK_IN: forlist(ls, varname); break; default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); } check_match(ls, TK_END, TK_FOR, line); leaveblock(fs); /* loop scope (`break' jumps to this point) */ } static int test_then_block (LexState *ls) { /* test_then_block -> [IF | ELSEIF] cond THEN block */ int condexit; luaX_next(ls); /* skip IF or ELSEIF */ condexit = cond(ls); checknext(ls, TK_THEN); block(ls); /* `then' part */ return condexit; } static void ifstat (LexState *ls, int line) { /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ FuncState *fs = ls->fs; int flist; int escapelist = NO_JUMP; flist = test_then_block(ls); /* IF cond THEN block */ while (ls->t.token == TK_ELSEIF) { luaK_concat(fs, &escapelist, luaK_jump(fs)); luaK_patchtohere(fs, flist); flist = test_then_block(ls); /* ELSEIF cond THEN block */ } if (ls->t.token == TK_ELSE) { luaK_concat(fs, &escapelist, luaK_jump(fs)); luaK_patchtohere(fs, flist); luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ block(ls); /* `else' part */ } else luaK_concat(fs, &escapelist, flist); luaK_patchtohere(fs, escapelist); check_match(ls, TK_END, TK_IF, line); } static void localfunc (LexState *ls) { expdesc v, b; FuncState *fs = ls->fs; new_localvar(ls, str_checkname(ls), 0); init_exp(&v, VLOCAL, fs->freereg); luaK_reserveregs(fs, 1); adjustlocalvars(ls, 1); body(ls, &b, 0, ls->linenumber); luaK_storevar(fs, &v, &b); /* debug information will only see the variable after this point! */ getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; } static void localstat (LexState *ls) { /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ int nvars = 0; int nexps; expdesc e; do { new_localvar(ls, str_checkname(ls), nvars++); } while (testnext(ls, ',')); if (testnext(ls, '=')) nexps = explist1(ls, &e); else { e.k = VVOID; nexps = 0; } adjust_assign(ls, nvars, nexps, &e); adjustlocalvars(ls, nvars); } static int funcname (LexState *ls, expdesc *v) { /* funcname -> NAME {field} [`:' NAME] */ int needself = 0; singlevar(ls, v); while (ls->t.token == '.') field(ls, v); if (ls->t.token == ':') { needself = 1; field(ls, v); } return needself; } static void funcstat (LexState *ls, int line) { /* funcstat -> FUNCTION funcname body */ int needself; expdesc v, b; luaX_next(ls); /* skip FUNCTION */ needself = funcname(ls, &v); body(ls, &b, needself, line); luaK_storevar(ls->fs, &v, &b); luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ } static void exprstat (LexState *ls) { /* stat -> func | assignment */ FuncState *fs = ls->fs; struct LHS_assign v; primaryexp(ls, &v.v); if (v.v.k == VCALL) /* stat -> func */ SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ else { /* stat -> assignment */ v.prev = NULL; assignment(ls, &v, 1); } } static void retstat (LexState *ls) { /* stat -> RETURN explist */ FuncState *fs = ls->fs; expdesc e; int first, nret; /* registers with returned values */ luaX_next(ls); /* skip RETURN */ if (block_follow(ls->t.token) || ls->t.token == ';') first = nret = 0; /* return no values */ else { nret = explist1(ls, &e); /* optional return values */ if (hasmultret(e.k)) { luaK_setmultret(fs, &e); if (e.k == VCALL && nret == 1) { /* tail call? */ SET_OPCODE(getcode(fs,&e), OP_TAILCALL); lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); } first = fs->nactvar; nret = LUA_MULTRET; /* return all values */ } else { if (nret == 1) /* only one single value? */ first = luaK_exp2anyreg(fs, &e); else { luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ first = fs->nactvar; /* return all `active' values */ lua_assert(nret == fs->freereg - first); } } } luaK_ret(fs, first, nret); } static int statement (LexState *ls) { int line = ls->linenumber; /* may be needed for error messages */ switch (ls->t.token) { case TK_IF: { /* stat -> ifstat */ ifstat(ls, line); return 0; } case TK_WHILE: { /* stat -> whilestat */ whilestat(ls, line); return 0; } case TK_DO: { /* stat -> DO block END */ luaX_next(ls); /* skip DO */ block(ls); check_match(ls, TK_END, TK_DO, line); return 0; } case TK_FOR: { /* stat -> forstat */ forstat(ls, line); return 0; } case TK_REPEAT: { /* stat -> repeatstat */ repeatstat(ls, line); return 0; } case TK_FUNCTION: { funcstat(ls, line); /* stat -> funcstat */ return 0; } case TK_LOCAL: { /* stat -> localstat */ luaX_next(ls); /* skip LOCAL */ if (testnext(ls, TK_FUNCTION)) /* local function? */ localfunc(ls); else localstat(ls); return 0; } case TK_RETURN: { /* stat -> retstat */ retstat(ls); return 1; /* must be last statement */ } case TK_BREAK: { /* stat -> breakstat */ luaX_next(ls); /* skip BREAK */ breakstat(ls); return 1; /* must be last statement */ } default: { exprstat(ls); return 0; /* to avoid warnings */ } } } static void chunk (LexState *ls) { /* chunk -> { stat [`;'] } */ int islast = 0; enterlevel(ls); while (!islast && !block_follow(ls->t.token)) { islast = statement(ls); testnext(ls, ';'); lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && ls->fs->freereg >= ls->fs->nactvar); ls->fs->freereg = ls->fs->nactvar; /* free registers */ } leavelevel(ls); } /* }====================================================================== */ bam-0.4.0/src/lua/lparser.h0000644000175000017500000000432511430042030013534 0ustar kmakma/* ** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ #ifndef lparser_h #define lparser_h #include "llimits.h" #include "lobject.h" #include "lzio.h" /* ** Expression descriptor */ typedef enum { VVOID, /* no value */ VNIL, VTRUE, VFALSE, VK, /* info = index of constant in `k' */ VKNUM, /* nval = numerical value */ VLOCAL, /* info = local register */ VUPVAL, /* info = index of upvalue in `upvalues' */ VGLOBAL, /* info = index of table; aux = index of global name in `k' */ VINDEXED, /* info = table register; aux = index register (or `k') */ VJMP, /* info = instruction pc */ VRELOCABLE, /* info = instruction pc */ VNONRELOC, /* info = result register */ VCALL, /* info = instruction pc */ VVARARG /* info = instruction pc */ } expkind; typedef struct expdesc { expkind k; union { struct { int info, aux; } s; lua_Number nval; } u; int t; /* patch list of `exit when true' */ int f; /* patch list of `exit when false' */ } expdesc; typedef struct upvaldesc { lu_byte k; lu_byte info; } upvaldesc; struct BlockCnt; /* defined in lparser.c */ /* state needed to generate code for a given function */ typedef struct FuncState { Proto *f; /* current function header */ Table *h; /* table to find (and reuse) elements in `k' */ struct FuncState *prev; /* enclosing function */ struct LexState *ls; /* lexical state */ struct lua_State *L; /* copy of the Lua state */ struct BlockCnt *bl; /* chain of current blocks */ int pc; /* next position to code (equivalent to `ncode') */ int lasttarget; /* `pc' of last `jump target' */ int jpc; /* list of pending jumps to `pc' */ int freereg; /* first free register */ int nk; /* number of elements in `k' */ int np; /* number of elements in `p' */ short nlocvars; /* number of elements in `locvars' */ lu_byte nactvar; /* number of active local variables */ upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ } FuncState; LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name); #endif bam-0.4.0/src/lua/lundump.h0000644000175000017500000000157211430042030013551 0ustar kmakma/* ** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ #ifndef lundump_h #define lundump_h #include "lobject.h" #include "lzio.h" /* load one chunk; from lundump.c */ LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); /* make header; from lundump.c */ LUAI_FUNC void luaU_header (char* h); /* dump one chunk; from ldump.c */ LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); #ifdef luac_c /* print one chunk; from print.c */ LUAI_FUNC void luaU_print (const Proto* f, int full); #endif /* for header of binary files -- this is Lua 5.1 */ #define LUAC_VERSION 0x51 /* for header of binary files -- this is the official format */ #define LUAC_FORMAT 0 /* size of header of binary files */ #define LUAC_HEADERSIZE 12 #endif bam-0.4.0/src/lua/ldebug.h0000644000175000017500000000204511430042030013323 0ustar kmakma/* ** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ ** Auxiliary functions from Debug Interface module ** See Copyright Notice in lua.h */ #ifndef ldebug_h #define ldebug_h #include "lstate.h" #define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) #define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) #define resethookcount(L) (L->hookcount = L->basehookcount) LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, const char *opname); LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2); LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2); LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); LUAI_FUNC void luaG_errormsg (lua_State *L); LUAI_FUNC int luaG_checkcode (const Proto *pt); LUAI_FUNC int luaG_checkopenop (Instruction i); #endif bam-0.4.0/src/lua/liolib.c0000644000175000017500000003213611430042030013332 0ustar kmakma/* ** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ #include #include #include #include #define liolib_c #define LUA_LIB #include "lua.h" #include "lauxlib.h" #include "lualib.h" #define IO_INPUT 1 #define IO_OUTPUT 2 static const char *const fnames[] = {"input", "output"}; static int pushresult (lua_State *L, int i, const char *filename) { int en = errno; /* calls to Lua API may change this value */ if (i) { lua_pushboolean(L, 1); return 1; } else { lua_pushnil(L); if (filename) lua_pushfstring(L, "%s: %s", filename, strerror(en)); else lua_pushfstring(L, "%s", strerror(en)); lua_pushinteger(L, en); return 3; } } static void fileerror (lua_State *L, int arg, const char *filename) { lua_pushfstring(L, "%s: %s", filename, strerror(errno)); luaL_argerror(L, arg, lua_tostring(L, -1)); } #define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) static int io_type (lua_State *L) { void *ud; luaL_checkany(L, 1); ud = lua_touserdata(L, 1); lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) lua_pushnil(L); /* not a file */ else if (*((FILE **)ud) == NULL) lua_pushliteral(L, "closed file"); else lua_pushliteral(L, "file"); return 1; } static FILE *tofile (lua_State *L) { FILE **f = tofilep(L); if (*f == NULL) luaL_error(L, "attempt to use a closed file"); return *f; } /* ** When creating file handles, always creates a `closed' file handle ** before opening the actual file; so, if there is a memory error, the ** file is not left opened. */ static FILE **newfile (lua_State *L) { FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); *pf = NULL; /* file handle is currently `closed' */ luaL_getmetatable(L, LUA_FILEHANDLE); lua_setmetatable(L, -2); return pf; } /* ** function to (not) close the standard files stdin, stdout, and stderr */ static int io_noclose (lua_State *L) { lua_pushnil(L); lua_pushliteral(L, "cannot close standard file"); return 2; } /* ** function to close 'popen' files */ static int io_pclose (lua_State *L) { FILE **p = tofilep(L); int ok = lua_pclose(L, *p); *p = NULL; return pushresult(L, ok, NULL); } /* ** function to close regular files */ static int io_fclose (lua_State *L) { FILE **p = tofilep(L); int ok = (fclose(*p) == 0); *p = NULL; return pushresult(L, ok, NULL); } static int aux_close (lua_State *L) { lua_getfenv(L, 1); lua_getfield(L, -1, "__close"); return (lua_tocfunction(L, -1))(L); } static int io_close (lua_State *L) { if (lua_isnone(L, 1)) lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); tofile(L); /* make sure argument is a file */ return aux_close(L); } static int io_gc (lua_State *L) { FILE *f = *tofilep(L); /* ignore closed files */ if (f != NULL) aux_close(L); return 0; } static int io_tostring (lua_State *L) { FILE *f = *tofilep(L); if (f == NULL) lua_pushliteral(L, "file (closed)"); else lua_pushfstring(L, "file (%p)", f); return 1; } static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); FILE **pf = newfile(L); *pf = fopen(filename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1; } /* ** this function has a separated environment, which defines the ** correct __close for 'popen' files */ static int io_popen (lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); FILE **pf = newfile(L); *pf = lua_popen(L, filename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1; } static int io_tmpfile (lua_State *L) { FILE **pf = newfile(L); *pf = tmpfile(); return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; } static FILE *getiofile (lua_State *L, int findex) { FILE *f; lua_rawgeti(L, LUA_ENVIRONINDEX, findex); f = *(FILE **)lua_touserdata(L, -1); if (f == NULL) luaL_error(L, "standard %s file is closed", fnames[findex - 1]); return f; } static int g_iofile (lua_State *L, int f, const char *mode) { if (!lua_isnoneornil(L, 1)) { const char *filename = lua_tostring(L, 1); if (filename) { FILE **pf = newfile(L); *pf = fopen(filename, mode); if (*pf == NULL) fileerror(L, 1, filename); } else { tofile(L); /* check that it's a valid file handle */ lua_pushvalue(L, 1); } lua_rawseti(L, LUA_ENVIRONINDEX, f); } /* return current value */ lua_rawgeti(L, LUA_ENVIRONINDEX, f); return 1; } static int io_input (lua_State *L) { return g_iofile(L, IO_INPUT, "r"); } static int io_output (lua_State *L) { return g_iofile(L, IO_OUTPUT, "w"); } static int io_readline (lua_State *L); static void aux_lines (lua_State *L, int idx, int toclose) { lua_pushvalue(L, idx); lua_pushboolean(L, toclose); /* close/not close file when finished */ lua_pushcclosure(L, io_readline, 2); } static int f_lines (lua_State *L) { tofile(L); /* check that it's a valid file handle */ aux_lines(L, 1, 0); return 1; } static int io_lines (lua_State *L) { if (lua_isnoneornil(L, 1)) { /* no arguments? */ /* will iterate over default input */ lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); return f_lines(L); } else { const char *filename = luaL_checkstring(L, 1); FILE **pf = newfile(L); *pf = fopen(filename, "r"); if (*pf == NULL) fileerror(L, 1, filename); aux_lines(L, lua_gettop(L), 1); return 1; } } /* ** {====================================================== ** READ ** ======================================================= */ static int read_number (lua_State *L, FILE *f) { lua_Number d; if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { lua_pushnumber(L, d); return 1; } else return 0; /* read fails */ } static int test_eof (lua_State *L, FILE *f) { int c = getc(f); ungetc(c, f); lua_pushlstring(L, NULL, 0); return (c != EOF); } static int read_line (lua_State *L, FILE *f) { luaL_Buffer b; luaL_buffinit(L, &b); for (;;) { size_t l; char *p = luaL_prepbuffer(&b); if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ luaL_pushresult(&b); /* close buffer */ return (lua_objlen(L, -1) > 0); /* check whether read something */ } l = strlen(p); if (l == 0 || p[l-1] != '\n') luaL_addsize(&b, l); else { luaL_addsize(&b, l - 1); /* do not include `eol' */ luaL_pushresult(&b); /* close buffer */ return 1; /* read at least an `eol' */ } } } static int read_chars (lua_State *L, FILE *f, size_t n) { size_t rlen; /* how much to read */ size_t nr; /* number of chars actually read */ luaL_Buffer b; luaL_buffinit(L, &b); rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ do { char *p = luaL_prepbuffer(&b); if (rlen > n) rlen = n; /* cannot read more than asked */ nr = fread(p, sizeof(char), rlen, f); luaL_addsize(&b, nr); n -= nr; /* still have to read `n' chars */ } while (n > 0 && nr == rlen); /* until end of count or eof */ luaL_pushresult(&b); /* close buffer */ return (n == 0 || lua_objlen(L, -1) > 0); } static int g_read (lua_State *L, FILE *f, int first) { int nargs = lua_gettop(L) - 1; int success; int n; clearerr(f); if (nargs == 0) { /* no arguments? */ success = read_line(L, f); n = first+1; /* to return 1 result */ } else { /* ensure stack space for all results and for auxlib's buffer */ luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); success = 1; for (n = first; nargs-- && success; n++) { if (lua_type(L, n) == LUA_TNUMBER) { size_t l = (size_t)lua_tointeger(L, n); success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); } else { const char *p = lua_tostring(L, n); luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); switch (p[1]) { case 'n': /* number */ success = read_number(L, f); break; case 'l': /* line */ success = read_line(L, f); break; case 'a': /* file */ read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ success = 1; /* always success */ break; default: return luaL_argerror(L, n, "invalid format"); } } } } if (ferror(f)) return pushresult(L, 0, NULL); if (!success) { lua_pop(L, 1); /* remove last result */ lua_pushnil(L); /* push nil instead */ } return n - first; } static int io_read (lua_State *L) { return g_read(L, getiofile(L, IO_INPUT), 1); } static int f_read (lua_State *L) { return g_read(L, tofile(L), 2); } static int io_readline (lua_State *L) { FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); int sucess; if (f == NULL) /* file is already closed? */ luaL_error(L, "file is already closed"); sucess = read_line(L, f); if (ferror(f)) return luaL_error(L, "%s", strerror(errno)); if (sucess) return 1; else { /* EOF */ if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ lua_settop(L, 0); lua_pushvalue(L, lua_upvalueindex(1)); aux_close(L); /* close it */ } return 0; } } /* }====================================================== */ static int g_write (lua_State *L, FILE *f, int arg) { int nargs = lua_gettop(L) - 1; int status = 1; for (; nargs--; arg++) { if (lua_type(L, arg) == LUA_TNUMBER) { /* optimization: could be done exactly as for strings */ status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; } else { size_t l; const char *s = luaL_checklstring(L, arg, &l); status = status && (fwrite(s, sizeof(char), l, f) == l); } } return pushresult(L, status, NULL); } static int io_write (lua_State *L) { return g_write(L, getiofile(L, IO_OUTPUT), 1); } static int f_write (lua_State *L) { return g_write(L, tofile(L), 2); } static int f_seek (lua_State *L) { static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; static const char *const modenames[] = {"set", "cur", "end", NULL}; FILE *f = tofile(L); int op = luaL_checkoption(L, 2, "cur", modenames); long offset = luaL_optlong(L, 3, 0); op = fseek(f, offset, mode[op]); if (op) return pushresult(L, 0, NULL); /* error */ else { lua_pushinteger(L, ftell(f)); return 1; } } static int f_setvbuf (lua_State *L) { static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; static const char *const modenames[] = {"no", "full", "line", NULL}; FILE *f = tofile(L); int op = luaL_checkoption(L, 2, NULL, modenames); lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); int res = setvbuf(f, NULL, mode[op], sz); return pushresult(L, res == 0, NULL); } static int io_flush (lua_State *L) { return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); } static int f_flush (lua_State *L) { return pushresult(L, fflush(tofile(L)) == 0, NULL); } static const luaL_Reg iolib[] = { {"close", io_close}, {"flush", io_flush}, {"input", io_input}, {"lines", io_lines}, {"open", io_open}, {"output", io_output}, {"popen", io_popen}, {"read", io_read}, {"tmpfile", io_tmpfile}, {"type", io_type}, {"write", io_write}, {NULL, NULL} }; static const luaL_Reg flib[] = { {"close", io_close}, {"flush", f_flush}, {"lines", f_lines}, {"read", f_read}, {"seek", f_seek}, {"setvbuf", f_setvbuf}, {"write", f_write}, {"__gc", io_gc}, {"__tostring", io_tostring}, {NULL, NULL} }; static void createmeta (lua_State *L) { luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ lua_pushvalue(L, -1); /* push metatable */ lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ luaL_register(L, NULL, flib); /* file methods */ } static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { *newfile(L) = f; if (k > 0) { lua_pushvalue(L, -1); lua_rawseti(L, LUA_ENVIRONINDEX, k); } lua_pushvalue(L, -2); /* copy environment */ lua_setfenv(L, -2); /* set it */ lua_setfield(L, -3, fname); } static void newfenv (lua_State *L, lua_CFunction cls) { lua_createtable(L, 0, 1); lua_pushcfunction(L, cls); lua_setfield(L, -2, "__close"); } LUALIB_API int luaopen_io (lua_State *L) { createmeta(L); /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ newfenv(L, io_fclose); lua_replace(L, LUA_ENVIRONINDEX); /* open library */ luaL_register(L, LUA_IOLIBNAME, iolib); /* create (and set) default files */ newfenv(L, io_noclose); /* close function for default files */ createstdfile(L, stdin, IO_INPUT, "stdin"); createstdfile(L, stdout, IO_OUTPUT, "stdout"); createstdfile(L, stderr, 0, "stderr"); lua_pop(L, 1); /* pop environment for default files */ lua_getfield(L, -1, "popen"); newfenv(L, io_pclose); /* create environment for 'popen' */ lua_setfenv(L, -2); /* set fenv for 'popen' */ lua_pop(L, 1); /* pop 'popen' */ return 1; } bam-0.4.0/scripts/0000755000175000017500000000000011430042056012036 5ustar kmakmabam-0.4.0/scripts/test.py0000755000175000017500000001251211430042030013363 0ustar kmakma#!/usr/bin/env python import os, sys, shutil, subprocess extra_bam_flags = "" src_path = "tests" output_path = "test_output" failed_tests = [] tests = [] verbose = False for v in sys.argv: if v == "-v": verbose = True bam = "../../bam" if os.name == 'nt': bam = "..\\..\\bam" if len(sys.argv) > 1: tests = sys.argv[1:] def copytree(src, dst): names = os.listdir(src) os.mkdir(dst) for name in names: if name[0] == '.': continue srcname = os.path.join(src, name) dstname = os.path.join(dst, name) try: if os.path.isdir(srcname): copytree(srcname, dstname) else: shutil.copy2(srcname, dstname) except (IOError, os.error), why: print "Can't copy %s to %s: %s" % (`srcname`, `dstname`, str(why)) def run_bam(testname, flags): global output_path olddir = os.getcwd() os.chdir(output_path+"/"+testname) p = subprocess.Popen(bam+" "+flags, stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT) report = p.stdout.readlines() p.wait() ret = p.returncode os.chdir(olddir) return (ret, report) def test(name, moreflags="", should_fail=0): global output_path, failed_tests, tests if len(tests) and not name in tests: return olddir = os.getcwd() os.chdir(output_path+"/"+name) cmdline = bam+" -t -v "+extra_bam_flags+" " + moreflags print name + ":", p = subprocess.Popen(cmdline, stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT) report = p.stdout.readlines() p.wait() ret = p.returncode os.chdir(olddir) if (should_fail and not ret) or (not should_fail and ret): print " FAILED!" for l in report: print "\t", l, failed_tests += [name + "(returned %d)" % ret] else: print " ok" def difftest(name, flags1, flags2): global failed_tests if len(tests) and not name in tests: return testname = "difftest: %s '%s' vs '%s': "%(name, flags1, flags2) print testname, ret1, report1 = run_bam(name, flags1) ret2, report2 = run_bam(name, flags2) if ret1: print "FAILED! '%s' returned %d" %(flags1, ret1) failed_tests += [testname] return if ret2: print "FAILED! '%s' returned %d" %(flags2, ret2) failed_tests += [testname] return if len(report1) != len(report2): print "FAILED! %d lines vs %d lines" % (len(report1), len(report2)) failed_tests += [testname] return failed = 0 for i in xrange(0, len(report1)): if report1[i] != report2[i]: if not failed: print "FAILED!" print "1:", report1[i].strip() print "2:", report2[i].strip() failed += 1 if failed: failed_tests += [testname] else: print "ok" def unittests(): global failed_tests class Test: def __init__(self): self.line = "" self.catch = None self.find = None self.err = 0 # expect 0 per default tests = [] state = 0 for line in file('src/base.lua'): if state == 0: if "@UNITTESTS" in line: state = 1 else: if "@END" in line: state = 0 else: test = Test() (args, cmdline) = line.split(":", 1) test.line = cmdline.strip() args = args.split(";") for arg in args: arg,value = arg.split("=") arg = arg.strip() value = value.strip() if arg.lower() == "err": test.err = int(value) elif arg.lower() == "catch": test.catch = value[1:-1] elif arg.lower() == "find": test.find = value[1:-1] tests += [test] olddir = os.getcwd() os.chdir(output_path+"/unit") for test in tests: f = file("bam.lua", "w") if test.catch != None: print >>f, "print(\"CATCH:\", %s)"%(test.line) else: print >>f, test.line print >>f, 'DefaultTarget(PseudoTarget("Test"))' f.close() print "%s:"%(test.line), p = subprocess.Popen(bam + " --dry", stdout=subprocess.PIPE, shell=True, stderr=subprocess.STDOUT) report = p.stdout.readlines() p.wait() ret = p.returncode failed = False if ret != test.err: failed = True print "FAILED! error %d != %d" % (test.err, ret) if test.catch != None: found = False for l in report: l = l.split("CATCH:", 1) if len(l) == 2: catched = l[1].strip() if catched == test.catch: found = True else: print "FAILED! catch '%s' != '%s'" % (test.catch, catched) if not found: failed = True if test.find != None: found = False for l in report: if test.find in l: found = True if not found: failed = True print "FAILED! could not find '%s' in output" % (test.find) if failed or verbose: if failed: failed_tests += [test.line] else: print "", for l in report: print "\t", l.rstrip() else: print "ok" os.chdir(olddir) # clean shutil.rmtree(output_path, True) # copy tree copytree("tests", output_path) os.mkdir(os.path.join(output_path, "unit")) # run smaller unit tests if len(tests) == 0: unittests() # run bigger test cases test("cyclic") difftest("cyclic", "--debug-nodes", "--debug-nodes -n") test("include_paths") difftest("include_paths", "--debug-nodes", "--debug-nodes -n") test("dot.in.dir") difftest("dot.in.dir", "--debug-nodes", "--debug-nodes -n") test("retval", "", 1) test("multi_target", "SHOULD_NOT_EXIST", 1) test("multi_target", "CORRECT_ONE") test("collect_wrong", "", 1) test("locked", "", 1) test("cxx_dep") test("deps", "", 1) test("collect_recurse") test("sharedlib") test("deadlock") test("addorder") if len(failed_tests): print "FAILED TESTS:" for t in failed_tests: print "\t"+t else: print "ALL TESTS PASSED!" bam-0.4.0/scripts/todo.sh0000755000175000017500000000005211430042030013327 0ustar kmakma#!/bin/sh fgrep -n TODO src/*.c src/*.lua bam-0.4.0/scripts/tinydoc.py0000644000175000017500000001374411430042030014062 0ustar kmakma import re, time class Node: def __init__(self, name): self.name = name self.body = "" self.index = "" self.indexname = "" self.tag = "" self.nodes = [] def Sorted(self): names = [] for n in self.nodes: names += [n.name] names.sort() new_list = [] for name in names: for n in self.nodes: if n.name == name: new_list += [n] break self.nodes = new_list return self # tags group_tag = "@GROUP" function_tag = "@FUNCTION" option_tag = "@OPTION" body_tag = "@BODY" tags = [function_tag, option_tag, body_tag] end_tag = "@END" class DocInfo: def __init__(self): self.name = "" self.copyright = "" self.logo = "" class Output: def __init__(self, filename, docinfo): self.filename = filename self.docinfo = docinfo def output_name(self): return self.filename def render_node_index(self, cur): if len(cur.index): print >>self.file, self.index_node_begin(cur) for node in cur.nodes: self.render_node_index(node) if len(cur.index): print >>self.file, self.index_node_end(cur) def render_node(self, cur): if len(cur.index): print >>self.file, self.format_header(cur) print >>self.file, self.format_body(cur) for node in cur.nodes: self.render_node(node) def index_nodes(self, cur, index=""): for i in xrange(0, len(cur.nodes)): if len(index): cur.nodes[i].index = index + "." + str(i+1) else: cur.nodes[i].index = str(i+1) cur.nodes[i].indexname = cur.nodes[i].name if cur.nodes[i].tag == function_tag: cur.nodes[i].indexname = cur.nodes[i].indexname.split("(")[0].strip() self.index_nodes(cur.nodes[i], cur.nodes[i].index) def render(self, rootnode): self.index_nodes(rootnode) print >>self.file, self.render_begin() print >>self.file, self.index_begin() self.render_node_index(rootnode) print >>self.file, self.index_end() self.render_node(rootnode) print >>self.file, self.render_end() class HTMLOutput(Output): def render_begin(self): img = "" if len(self.docinfo.logo): img = ''%self.docinfo.logo # large part of the style sheet is stolen from luas documentation return ''' Bam Manual


%s

%s

%s
%s ''' %(img, self.docinfo.name, self.docinfo.note, self.docinfo.copyright) def render_end(self): return '''
Generated at %s. ''' % (time.asctime()) def index_begin(self): return '

Contents

    ' def index_end(self): return '

' def index_node_begin(self, node): return '
  • %s - %s
    • '%(node.index,node.index,node.indexname) def index_node_end(self, node): if len(node.index) == 1: return '

    ' return '' def format_header(self, node): i = (len(node.index)-1)/2 + 1 header = '%s - %s'%(i,node.indexname,node.index,node.index,node.name,node.name,i) if node.tag == function_tag: header = '
    ' + header return header def format_body(self, node): body = node.body body = re.sub('\^(?P[^\^]+)\^', '\g', body) body = re.sub('\[(?P[^\]]+)\]', '\g', body) body = re.sub('{{{{', '
    ', body)
    		body = re.sub('}}}}', '
    ', body) body = re.sub('!IMG (?P.+)', '', body) body = re.sub('\\\\t', '    ', body) body = re.sub('\n\n', '

    ', body) body = '

    ' + body + '

    \n' body += '\n\n' % (node.indexname) return body def ParseTextFile(rootnode, filename, addbr=False): group = rootnode for line in file(filename): if group_tag in line: group_name = line.split(group_tag)[-1].split(end_tag)[0].strip() group = Node(group_name) rootnode.nodes += [group] else: if addbr: group.body += line.strip() + "
    \n" else: group.body += line.strip() + "\n" return rootnode def ParseFile(rootnode, filename): # 0 = scaning for start tag # 1 = scaning for end tag, # 2 = outputting function decl state = 0 group = rootnode for line in file(filename): if state == 0: if group_tag in line: group_name = line.split(group_tag)[-1].split(end_tag)[0].strip() group = Node(group_name) rootnode.nodes += [group] else: for t in tags: if t in line: title = line.split(t)[-1].strip() tag = t body = "" state = 1 break elif state == 1: if end_tag in line: state = 3 elif "@PAUSE" in line: state = 2 else: body += line.strip() + "\n" elif state == 2: if "@RESUME" in line: state = 1 else: if tag == function_tag: if len(title) == 0: title = line.replace("function", "").strip() title = title.replace("(", " (") node = Node(title) node.body = body node.tag = tag group.nodes += [node] state = 0 return rootnode bam-0.4.0/scripts/gendocs.py0000644000175000017500000000233011430042030014020 0ustar kmakma#!/usr/bin/env python from tinydoc import * import os #os.system("dot -Tpng docs/depgraph.dot > docs/depgraph.png") info = DocInfo() info.name = "Bam Manual" info.logo = "bam_logo.png" info.note = "This manual is a work in progress and is not complete." info.copyright = "Copyright © 2010 Magnus Auvinen. Freely available under the terms of the zlib/libpng license." outputs = [HTMLOutput("docs/bam.html", info)] group = 0 root = Node("root") root.nodes += [ParseTextFile(Node("Introduction"), "docs/introduction.txt")] root.nodes += [ParseTextFile(Node("Building Bam"), "docs/building.txt")] root.nodes += [ParseTextFile(Node("Quick Start"), "docs/quickstart.txt")] root.nodes += [ParseTextFile(Node("Custom Actions"), "docs/actions.txt")] root.nodes += [ParseFile(Node("Command Line Reference"), "src/main.c")] root.nodes += [ParseFile(Node("Function Reference"), "src/base.lua").Sorted()] root.nodes += [ParseFile(Node("Tool Reference"), "src/tools.lua").Sorted()] root.nodes += [ParseTextFile(Node("License"), "license.txt", True)] #notes.nodes +=[Node("C/C++ Dependency Checker")] #notes.nodes +=[Node("Spaces in Paths")] # render files for o in outputs: o.file = file(o.output_name(), "w") o.render(root) o.file.close() bam-0.4.0/docs/0000755000175000017500000000000011430042100011265 5ustar kmakmabam-0.4.0/docs/depgraph.dot0000644000175000017500000000075011430042030013573 0ustar kmakmadigraph { size ="6,6"; app [label="app\n< gcc obj1.o obj2.o -o app >"] obj1o [label="src1.o\n< gcc -c src1.c -o obj1.o >"]; obj2o [label="src2.o\n< gcc -c src2.c -o obj2.o >"]; src1c [label="src1.c"]; src2c [label="src2.c"]; header1h [label="header1.h"]; header2h [label="header2.h"]; sharedh [label="shared.h"]; obj1o -> app; obj2o -> app; src1c -> obj1o; src2c -> obj2o; header1h -> src1c; header2h -> src1c; header2h -> sharedh; sharedh -> src1c; sharedh -> src2c; } bam-0.4.0/docs/bam_logo.png0000644000175000017500000000255111430042030013557 0ustar kmakmaPNG  IHDRK@tEXtSoftwareAdobe ImageReadyqe< IDATx1OAgBe%%$&6~+ 4T$4[:z"gbL,lLL΂N,,7;%OD;f64s D (!GeﱍZSPwEː9/l|1_ /m|)dr > +5t]ghd?l< l6ƤaNA@Ʒs%?m<jg6~IPƷ|M*2+66wm2E3flH#O0mgly<ƋgO pRx`SV+JzZWfcGS.I=-@Q:nM4zh|3C=-@(>m˅)K? u޺HZA{_%EΎ^K)n0p+Ƣ{?Q`&E zZDo ߲Nl1PYUMX}<.txiJM߷7C͸rb)!S*RO S6w+[nbgT  1%VO (˶V R^恭=JnsQ 3p= MaǼ=(k|v ۯ );S[IRGЕkz!BsXHQ\侸'Oے4sȆ.k޷rt6=PLQ}*9L⨐T!cW:遲C? 4U}H)US8e}FRѵ~ ET%RwJWeKNK6S&q Nig-dW+@D)Q'g+03Sz=-@TLl:ǹorԠr&\Jz,-<XI>ӕ:UinueAj?n2"%dt+F]'@Sl]J8%NS8;Fw׹oI,^DID*-2MquEW PiSդ+hPython to be installed. This test suite is used during the development of Bam to verify that nothing breaks between releases. You can run the test suite by typing this: {{{{python scripts/test.py}}}} It will either print out that all tests where successfull or what tests it didn't pass. bam-0.4.0/docs/introduction.txt0000644000175000017500000000052111430042030014547 0ustar kmakmaBam is a build system with the focus on being having fast build times and flexiable build scripts. Instead of having a custom language it uses Lua to describe the build steps. It's written in clean C and is distrubuted under the liberal zlib licence. Available on many platforms including but not limited to Linux, Mac OS X and Windows.