From 93a2c6678de8215f9ff89e3a4a3009d86ef56725 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 17 Dec 2013 22:16:27 -0500 Subject: [PATCH] Initial work. Goes far enough to decrypt and correctly verify the master key. --- .hgignore | 3 + 1pass.c | 323 ++++++++++ 1pass.lua | 104 +++ CMakeLists.txt | 118 ++++ JSON.lua | 884 ++++++++++++++++++++++++++ aes.c | 401 ++++++++++++ aes.h | 18 + base64.c | 197 ++++++ base64.h | 46 ++ lua/Makefile | 187 ++++++ lua/lapi.c | 1284 +++++++++++++++++++++++++++++++++++++ lua/lapi.h | 24 + lua/lauxlib.c | 959 ++++++++++++++++++++++++++++ lua/lauxlib.h | 212 +++++++ lua/lbaselib.c | 458 ++++++++++++++ lua/lbitlib.c | 212 +++++++ lua/lcode.c | 881 ++++++++++++++++++++++++++ lua/lcode.h | 83 +++ lua/lcorolib.c | 155 +++++ lua/lctype.c | 52 ++ lua/lctype.h | 95 +++ lua/ldblib.c | 398 ++++++++++++ lua/ldebug.c | 593 ++++++++++++++++++ lua/ldebug.h | 34 + lua/ldo.c | 681 ++++++++++++++++++++ lua/ldo.h | 46 ++ lua/ldump.c | 173 +++++ lua/lfunc.c | 161 +++++ lua/lfunc.h | 33 + lua/lgc.c | 1220 ++++++++++++++++++++++++++++++++++++ lua/lgc.h | 157 +++++ lua/liblua.a | Bin 0 -> 329392 bytes lua/linit.c | 67 ++ lua/liolib.c | 666 ++++++++++++++++++++ lua/llex.c | 530 ++++++++++++++++ lua/llex.h | 78 +++ lua/llimits.h | 309 +++++++++ lua/lmathlib.c | 279 +++++++++ lua/lmem.c | 99 +++ lua/lmem.h | 57 ++ lua/loadlib.c | 725 +++++++++++++++++++++ lua/lobject.c | 287 +++++++++ lua/lobject.h | 607 ++++++++++++++++++ lua/lopcodes.c | 107 ++++ lua/lopcodes.h | 288 +++++++++ lua/loslib.c | 323 ++++++++++ lua/lparser.c | 1638 ++++++++++++++++++++++++++++++++++++++++++++++++ lua/lparser.h | 119 ++++ lua/lstate.c | 323 ++++++++++ lua/lstate.h | 228 +++++++ lua/lstring.c | 185 ++++++ lua/lstring.h | 46 ++ lua/lstrlib.c | 1019 ++++++++++++++++++++++++++++++ lua/ltable.c | 588 +++++++++++++++++ lua/ltable.h | 45 ++ lua/ltablib.c | 283 +++++++++ lua/ltm.c | 77 +++ lua/ltm.h | 57 ++ lua/lua | Bin 0 -> 191568 bytes lua/lua.c | 497 +++++++++++++++ lua/lua.h | 444 +++++++++++++ lua/lua.hpp | 9 + lua/luac | Bin 0 -> 133648 bytes lua/luac.c | 432 +++++++++++++ lua/luaconf.h | 551 ++++++++++++++++ lua/lualib.h | 55 ++ lua/lundump.c | 258 ++++++++ lua/lundump.h | 28 + lua/lvm.c | 867 +++++++++++++++++++++++++ lua/lvm.h | 44 ++ lua/lzio.c | 76 +++ lua/lzio.h | 65 ++ md5.c | 394 ++++++++++++ md5.h | 19 + pkcs5_pbkdf2.c | 122 ++++ pkcs5_pbkdf2.h | 11 + sha1.c | 179 ++++++ sha1.h | 28 + 78 files changed, 23301 insertions(+) create mode 100644 .hgignore create mode 100644 1pass.c create mode 100644 1pass.lua create mode 100644 CMakeLists.txt create mode 100644 JSON.lua create mode 100644 aes.c create mode 100644 aes.h create mode 100644 base64.c create mode 100644 base64.h create mode 100644 lua/Makefile create mode 100644 lua/lapi.c create mode 100644 lua/lapi.h create mode 100644 lua/lauxlib.c create mode 100644 lua/lauxlib.h create mode 100644 lua/lbaselib.c create mode 100644 lua/lbitlib.c create mode 100644 lua/lcode.c create mode 100644 lua/lcode.h create mode 100644 lua/lcorolib.c create mode 100644 lua/lctype.c create mode 100644 lua/lctype.h create mode 100644 lua/ldblib.c create mode 100644 lua/ldebug.c create mode 100644 lua/ldebug.h create mode 100644 lua/ldo.c create mode 100644 lua/ldo.h create mode 100644 lua/ldump.c create mode 100644 lua/lfunc.c create mode 100644 lua/lfunc.h create mode 100644 lua/lgc.c create mode 100644 lua/lgc.h create mode 100644 lua/liblua.a create mode 100644 lua/linit.c create mode 100644 lua/liolib.c create mode 100644 lua/llex.c create mode 100644 lua/llex.h create mode 100644 lua/llimits.h create mode 100644 lua/lmathlib.c create mode 100644 lua/lmem.c create mode 100644 lua/lmem.h create mode 100644 lua/loadlib.c create mode 100644 lua/lobject.c create mode 100644 lua/lobject.h create mode 100644 lua/lopcodes.c create mode 100644 lua/lopcodes.h create mode 100644 lua/loslib.c create mode 100644 lua/lparser.c create mode 100644 lua/lparser.h create mode 100644 lua/lstate.c create mode 100644 lua/lstate.h create mode 100644 lua/lstring.c create mode 100644 lua/lstring.h create mode 100644 lua/lstrlib.c create mode 100644 lua/ltable.c create mode 100644 lua/ltable.h create mode 100644 lua/ltablib.c create mode 100644 lua/ltm.c create mode 100644 lua/ltm.h create mode 100755 lua/lua create mode 100644 lua/lua.c create mode 100644 lua/lua.h create mode 100644 lua/lua.hpp create mode 100755 lua/luac create mode 100644 lua/luac.c create mode 100644 lua/luaconf.h create mode 100644 lua/lualib.h create mode 100644 lua/lundump.c create mode 100644 lua/lundump.h create mode 100644 lua/lvm.c create mode 100644 lua/lvm.h create mode 100644 lua/lzio.c create mode 100644 lua/lzio.h create mode 100644 md5.c create mode 100644 md5.h create mode 100644 pkcs5_pbkdf2.c create mode 100644 pkcs5_pbkdf2.h create mode 100644 sha1.c create mode 100644 sha1.h diff --git a/.hgignore b/.hgignore new file mode 100644 index 0000000..e90b1b0 --- /dev/null +++ b/.hgignore @@ -0,0 +1,3 @@ +syntax:glob +cmake-build +1Password diff --git a/1pass.c b/1pass.c new file mode 100644 index 0000000..0e96ffc --- /dev/null +++ b/1pass.c @@ -0,0 +1,323 @@ +#include +#include +#include +#include +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "pkcs5_pbkdf2.h" +#include "aes.h" +#include "base64.h" +#include "md5.h" + +#define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) ) + +static lua_State *luaState = NULL; +static const uint8_t zero16[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; +static const char saltprefix[] = { 'S', 'a', 'l', 't', 'e', 'd', '_', '_' }; + + +static inline int retvalString(lua_State *L, const char *str) +{ + if (str != NULL) + lua_pushstring(L, str); + else + lua_pushnil(L); + return 1; +} // retvalString + + +static inline int retvalStringBytes(lua_State *L, const uint8_t *str, size_t len) +{ +//size_t i; printf("{\n"); for (i = 0; i < len; i++) { printf(" 0x%X\n", (unsigned int) str[i]); } printf(" }\n\n"); + + if (str != NULL) + lua_pushlstring(L, (const char *) str, len); + else + lua_pushnil(L); + return 1; +} // retvalStringBytes + +static inline void xorBlock(uint8_t *dst, const uint8_t *src) +{ + int i; + for (i = 0; i < 16; i++, dst++, src++) + *dst ^= *src; +} // xorBlock + +static int decryptUsingKeyAndIvec(uint8_t *data, size_t *datalen, const uint8_t *key, const uint8_t *iv) +{ + const size_t blocks = *datalen / 16; + uint8_t *block = data + ((blocks-1) * 16); // start at final block, work backwards + const uint8_t *padding = &block[15]; + uint8_t expkey[aesExpandedKeySize]; + size_t i; + + if (blocks == 0) + return 1; // nothing to do. + + aesExpandKey(key, expkey); + + for (i = 0; i < blocks-1; i++) + { + aesDecrypt(block, expkey, block); // decrypt in place. + xorBlock(block, block-16); + block -= 16; + } + aesDecrypt(block, expkey, block); // decrypt in place. + xorBlock(block, iv); // xor against initial vector for final block. + + if (*padding > 16) + return 0; // bad data? + + *datalen -= *padding; + + return 1; +} // decryptBinaryUsingKeyAndIvec + + +static inline int isSalted(const uint8_t *data, const size_t datalen) +{ + return ( (datalen > sizeof (saltprefix)) && + (memcmp(data, saltprefix, sizeof (saltprefix)) == 0) ); +} // isSalted + + +static int decryptUsingPBKDF2(lua_State *L) +{ + const char *base64 = luaL_checkstring(L, 1); + const char *password = luaL_checkstring(L, 2); + const int iterations = luaL_checkinteger(L, 3); + size_t datalen = strlen(base64); + uint8_t *dataptr = (uint8_t *) malloc(datalen); + uint8_t *data = dataptr; + base64_decodestate base64state; + + base64_init_decodestate(&base64state); + datalen = base64_decode_block(base64, (int) datalen, data, &base64state); + + const uint8_t *salt = zero16; + int saltlen = sizeof (zero16); + if (isSalted(data, datalen)) + { + salt = data + 8; + saltlen = 8; + data += 16; + datalen -= 16; + } // if + + uint8_t output[32]; + pkcs5_pbkdf2(password, strlen(password), salt, saltlen, output, sizeof (output), (unsigned int) iterations); + + const uint8_t *aeskey = &output[0]; + const uint8_t *aesiv = &output[16]; + if (decryptUsingKeyAndIvec(data, &datalen, aeskey, aesiv)) + retvalStringBytes(L, data, datalen); + else + lua_pushnil(L); + + free(dataptr); + return 1; +} // decryptUsingPBKDF2 + + +static int decryptBase64UsingKey(lua_State *L) +{ + size_t keylen = 0; + const char *base64 = luaL_checkstring(L, 1); + const uint8_t *key = (const uint8_t *) luaL_checklstring(L, 2, &keylen); + size_t datalen = strlen(base64); + uint8_t *dataptr = (uint8_t *) malloc(datalen); + uint8_t *data = dataptr; + base64_decodestate base64state; + + base64_init_decodestate(&base64state); + datalen = base64_decode_block(base64, (int) datalen, data, &base64state); + + uint8_t aeskey[16]; + uint8_t aesiv[16]; + MD5_CTX md5; + + if (isSalted(data, datalen)) + { + const uint8_t *salt = data + 8; + const size_t saltlen = 8; + data += 16; + datalen -= 16; + + assert(aesNr == 10); // AES-256 needs more rounds. + assert(aesNk == 4); // hashing size is hardcoded later. + uint8_t hashing[32]; + + MD5_init(&md5); + MD5_append(&md5, key, keylen); + MD5_append(&md5, salt, saltlen); + MD5_finish(&md5, hashing); + + MD5_init(&md5); + MD5_append(&md5, hashing, 16); + MD5_append(&md5, key, keylen); + MD5_append(&md5, salt, saltlen); + MD5_finish(&md5, &hashing[16]); + + memcpy(aeskey, hashing, 4 * aesNk); + memcpy(aesiv, &hashing[4 * aesNk], 16); + } // if + else + { + MD5_init(&md5); + MD5_append(&md5, key, keylen); + MD5_finish(&md5, aeskey); + memset(aesiv, '\0', sizeof (aesiv)); + } // else + + if (decryptUsingKeyAndIvec(data, &datalen, aeskey, aesiv)) + retvalStringBytes(L, data, datalen); + else + lua_pushnil(L); + + free(dataptr); + return 1; +} // decryptBase64UsingKey + + +static void registerLuaLibs(lua_State *L) +{ + // We always need the string and base libraries (although base has a + // few we could trim). The rest you can compile in if you want/need them. + int i; + static const luaL_Reg lualibs[] = { + {"_G", luaopen_base}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_DBLIBNAME, luaopen_debug}, + {LUA_BITLIBNAME, luaopen_bit32}, + {LUA_COLIBNAME, luaopen_coroutine}, + }; + + for (i = 0; i < STATICARRAYLEN(lualibs); i++) + { + luaL_requiref(L, lualibs[i].name, lualibs[i].func, 1); + lua_pop(L, 1); // remove lib + } // for +} // registerLuaLibs + + +static void *luaAlloc(void *ud, void *ptr, size_t osize, size_t nsize) +{ + if (nsize == 0) + { + free(ptr); + return NULL; + } // if + return realloc(ptr, nsize); +} // luaAlloc + + +static inline void luaSetCFunc(lua_State *L, lua_CFunction f, const char *sym) +{ + lua_pushcfunction(L, f); + lua_setglobal(luaState, sym); +} // luaSetCFunc + + +static int luaFatal(lua_State *L) +{ + const char *errstr = lua_tostring(L, -1); + fprintf(stderr, "Lua panic: %s\n", errstr ? errstr : "(?)"); + fflush(stderr); + exit(1); +} // luaFatal + + +static int initLua(void) +{ + assert(luaState == NULL); + luaState = lua_newstate(luaAlloc, NULL); + + lua_atpanic(luaState, luaFatal); + assert(lua_checkstack(luaState, 20)); // Just in case. + registerLuaLibs(luaState); + + // Set up initial C functions, etc we want to expose to Lua code... + luaSetCFunc(luaState, decryptUsingPBKDF2, "decryptUsingPBKDF2"); + luaSetCFunc(luaState, decryptBase64UsingKey, "decryptBase64UsingKey"); + + // Transfer control to Lua to setup some APIs and state... + if (luaL_dofile(luaState, "1pass.lua") != 0) + { + const char *msg = lua_tostring(luaState, -1); + fprintf(stderr, "1pass.lua didn't run: %s\n", msg); + lua_pop(luaState, 1); + return 0; + } // if + + return 1; +} // initLua + + +void deinitLua(void) +{ + if (luaState != NULL) + { + lua_close(luaState); + luaState = NULL; + } // if +} // deinitLua + + + +static char *loadKey(const char *baseDir, const char *level, const char *password) +{ + char *retval = NULL; + lua_getglobal(luaState, "loadKey"); + lua_pushstring(luaState, baseDir); + lua_pushstring(luaState, level); + lua_pushstring(luaState, password); + lua_call(luaState, 3, 1); + const char *str = lua_tostring(luaState, -1); + if (str) + retval = strdup(str); + lua_pop(luaState, 1); + return retval; +} // luafunc_loadKey + + +static char *sl5 = NULL; + +int main(int argc, char **argv) +{ + const char *basedir = "1Password/1Password.agilekeychain/data/default"; // !!! FIXME + + char *password = NULL; + size_t pwlen = 0; + printf("password: "); fflush(stdout); + const ssize_t rc = getline(&password, &pwlen, stdin); + if (rc == -1) + return 1; + else if (password[rc-1] == '\n') + password[rc-1] = 0; + + if (!initLua()) + { + fprintf(stderr, "uhoh\n"); + return 1; + } // if + + sl5 = loadKey(basedir, "SL5", password); + if (!sl5) + { + fprintf(stderr, "wrong password?\n"); + return 1; + } // if + + free(sl5); + return 0; +} // main + +// end of 1pass.c ... + diff --git a/1pass.lua b/1pass.lua new file mode 100644 index 0000000..5731a45 --- /dev/null +++ b/1pass.lua @@ -0,0 +1,104 @@ +JSON = (loadfile "JSON.lua")() + +local function dumptable(tabname, tab, depth) + if depth == nil then -- first call, before any recursion? + depth = 1 + end + + if tabname ~= nil then + if tab == nil then + print(tabname .. " = nil") + return + else + print(tabname .. " = {") + end + end + + local depthstr = "" + for i=1,(depth*4) do + depthstr = depthstr .. " " + end + + if tab.DUMPTABLE_ITERATED then + print(depthstr .. "(...circular reference...)") + else + tab.DUMPTABLE_ITERATED = true + for k,v in pairs(tab) do + if type(v) == "table" then + print(depthstr .. tostring(k) .. " = {") + dumptable(nil, v, depth + 1) + print(depthstr .. "}") + else + if k ~= "DUMPTABLE_ITERATED" then + print(depthstr .. tostring(k) .. " = " .. tostring(v)) + end + end + end + tab.DUMPTABLE_ITERATED = nil + end + + if tabname ~= nil then + print("}") + end +end + +local function load_json(fname) + local f = io.open(fname, "rb") + if (f == nil) then + return nil + end + + local str = f:read("*all") + f:close() + + local retval = JSON:decode(str) + dumptable("JSON " .. fname, retval) + return retval +end + + +function loadKey(basedir, level, password) + local keysjson = load_json(basedir .. "/encryptionKeys.js"); + if (keysjson == nil) or (keysjson[level] == nil) then + return nil + end + + local identifier = keysjson[level] + for i,v in ipairs(keysjson.list) do + if v.identifier == identifier then + local iterations = v.iterations + if (iterations == nil) or (iterations < 1000) then + iterations = 1000 + end + + local decrypted = decryptUsingPBKDF2(v.data, password, iterations) + if decrypted == nil then + return nil + end + + local validate = decryptBase64UsingKey(v.validation, decrypted) + if validate ~= decrypted then + return nil + end + + return decrypted + end + end + + return nil +end + +function showHint(basedir) + local f = io.open(basedir .. "/.password.hint", "r") + if (f == nil) then + return + end + + local str = f:read("*all") + f:close() + + print("(hint is '" .. str .. "').") +end + +-- end of 1pass.lua ... + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b64efc7 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,118 @@ +cmake_minimum_required(VERSION 2.8.10) +project(1pass) + +# Set up some sanity stuff... +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + SET(LINUX TRUE) +endif() +if(APPLE) + SET(MACOSX TRUE) +endif() +if(MSVC) + SET(WINDOWS TRUE) +endif() + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Debug CACHE STRING "None Debug Release RelWithDebInfo MinSizeRel" FORCE) +endif() +SET(DEBUG FALSE) +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + SET(DEBUG TRUE) +endif() + + +add_definitions(-D_REENTRANT=1) + +if(DEBUG) + add_definitions(-DDEBUG=1) + add_definitions(-D_DEBUG=1) +else() + add_definitions(-DNDEBUG=1) + add_definitions(-D_NDEBUG=1) +endif() + +if(WINDOWS) + add_definitions(-DWIN32=1) + add_definitions(-DOS_WIN32=1) + add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE=1) +endif() + +if(LINUX) + set(CMAKE_SKIP_RPATH ON CACHE BOOL "Skip RPATH" FORCE) + add_definitions(-D_FILE_OFFSET_BITS=64) + add_definitions(-D_LARGEFILE_SOURCE=1) +endif() + +if(LINUX OR MACOSX) + if(DEBUG) + add_definitions(-O0 -ggdb3) + endif(DEBUG) + add_definitions(-pipe -fsigned-char) + set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}" CACHE STRING "compile flags" FORCE) + + add_definitions(-DLUA_USE_MKSTEMP=1) # as opposed to tmpnam(), yuck! + add_definitions(-DLUA_USE_ULONGJMP=1) +endif() + + +include(TestBigEndian) +test_big_endian(ONEPASS_IS_BIGENDIAN) +if(ONEPASS_IS_BIGENDIAN) + add_definitions(-DPLATFORM_BIGENDIAN=1) +else() + add_definitions(-DPLATFORM_LITTLEENDIAN=1) +endif() + + +include_directories("lua") + +add_executable(1pass + 1pass.c + pkcs5_pbkdf2.c + aes.c + md5.c + sha1.c + base64.c + lua/lapi.c + lua/ldebug.c + lua/ldo.c + lua/ldump.c + lua/lfunc.c + lua/lgc.c + lua/lmem.c + lua/lobject.c + lua/lopcodes.c + lua/lstate.c + lua/lstring.c + lua/ltable.c + lua/ltm.c + lua/lundump.c + lua/lvm.c + lua/lzio.c + lua/lauxlib.c + lua/lbaselib.c + lua/lstrlib.c + lua/ltablib.c + lua/lctype.c + lua/lparser.c + lua/llex.c + lua/lcode.c + lua/linit.c + lua/lctype.c + lua/ldblib.c + lua/liolib.c + lua/lmathlib.c + lua/loslib.c + lua/lbitlib.c + lua/lcorolib.c + lua/loadlib.c +) + +if(LINUX) + set_target_properties(odin PROPERTIES LINK_FLAGS "-Wl,-rpath,$ORIGIN") + # !!! FIXME: other stuff. +endif() + +# end of CMakeLists.txt ... + diff --git a/JSON.lua b/JSON.lua new file mode 100644 index 0000000..b3d8ae6 --- /dev/null +++ b/JSON.lua @@ -0,0 +1,884 @@ +-- -*- coding: utf-8 -*- +-- +-- Simple JSON encoding and decoding in pure Lua. +-- +-- Copyright 2010-2013 Jeffrey Friedl +-- http://regex.info/blog/ +-- +-- Latest version: http://regex.info/blog/lua/json +-- +-- This code is released under a Creative Commons CC-BY "Attribution" License: +-- http://creativecommons.org/licenses/by/3.0/deed.en_US +-- +-- It can be used for any purpose so long as the copyright notice and +-- web-page links above are maintained. Enjoy. +-- +local VERSION = 20131118.9 -- version history at end of file +local OBJDEF = { VERSION = VERSION } + + +-- +-- Simple JSON encoding and decoding in pure Lua. +-- http://www.json.org/ +-- +-- +-- JSON = (loadfile "JSON.lua")() -- one-time load of the routines +-- +-- local lua_value = JSON:decode(raw_json_text) +-- +-- local raw_json_text = JSON:encode(lua_table_or_value) +-- local pretty_json_text = JSON:encode_pretty(lua_table_or_value) -- "pretty printed" version for human readability +-- +-- +-- DECODING +-- +-- JSON = (loadfile "JSON.lua")() -- one-time load of the routines +-- +-- local lua_value = JSON:decode(raw_json_text) +-- +-- If the JSON text is for an object or an array, e.g. +-- { "what": "books", "count": 3 } +-- or +-- [ "Larry", "Curly", "Moe" ] +-- +-- the result is a Lua table, e.g. +-- { what = "books", count = 3 } +-- or +-- { "Larry", "Curly", "Moe" } +-- +-- +-- The encode and decode routines accept an optional second argument, "etc", which is not used +-- during encoding or decoding, but upon error is passed along to error handlers. It can be of any +-- type (including nil). +-- +-- With most errors during decoding, this code calls +-- +-- JSON:onDecodeError(message, text, location, etc) +-- +-- with a message about the error, and if known, the JSON text being parsed and the byte count +-- where the problem was discovered. You can replace the default JSON:onDecodeError() with your +-- own function. +-- +-- The default onDecodeError() merely augments the message with data about the text and the +-- location if known (and if a second 'etc' argument had been provided to decode(), its value is +-- tacked onto the message as well), and then calls JSON.assert(), which itself defaults to Lua's +-- built-in assert(), and can also be overridden. +-- +-- For example, in an Adobe Lightroom plugin, you might use something like +-- +-- function JSON:onDecodeError(message, text, location, etc) +-- LrErrors.throwUserError("Internal Error: invalid JSON data") +-- end +-- +-- or even just +-- +-- function JSON.assert(message) +-- LrErrors.throwUserError("Internal Error: " .. message) +-- end +-- +-- If JSON:decode() is passed a nil, this is called instead: +-- +-- JSON:onDecodeOfNilError(message, nil, nil, etc) +-- +-- and if JSON:decode() is passed HTML instead of JSON, this is called: +-- +-- JSON:onDecodeOfHTMLError(message, text, nil, etc) +-- +-- The use of the fourth 'etc' argument allows stronger coordination between decoding and error +-- reporting, especially when you provide your own error-handling routines. Continuing with the +-- the Adobe Lightroom plugin example: +-- +-- function JSON:onDecodeError(message, text, location, etc) +-- local note = "Internal Error: invalid JSON data" +-- if type(etc) = 'table' and etc.photo then +-- note = note .. " while processing for " .. etc.photo:getFormattedMetadata('fileName') +-- end +-- LrErrors.throwUserError(note) +-- end +-- +-- : +-- : +-- +-- for i, photo in ipairs(photosToProcess) do +-- : +-- : +-- local data = JSON:decode(someJsonText, { photo = photo }) +-- : +-- : +-- end +-- +-- +-- +-- + +-- DECODING AND STRICT TYPES +-- +-- Because both JSON objects and JSON arrays are converted to Lua tables, it's not normally +-- possible to tell which a JSON type a particular Lua table was derived from, or guarantee +-- decode-encode round-trip equivalency. +-- +-- However, if you enable strictTypes, e.g. +-- +-- JSON = (loadfile "JSON.lua")() --load the routines +-- JSON.strictTypes = true +-- +-- then the Lua table resulting from the decoding of a JSON object or JSON array is marked via Lua +-- metatable, so that when re-encoded with JSON:encode() it ends up as the appropriate JSON type. +-- +-- (This is not the default because other routines may not work well with tables that have a +-- metatable set, for example, Lightroom API calls.) +-- +-- +-- ENCODING +-- +-- JSON = (loadfile "JSON.lua")() -- one-time load of the routines +-- +-- local raw_json_text = JSON:encode(lua_table_or_value) +-- local pretty_json_text = JSON:encode_pretty(lua_table_or_value) -- "pretty printed" version for human readability + +-- On error during encoding, this code calls: +-- +-- JSON:onEncodeError(message, etc) +-- +-- which you can override in your local JSON object. +-- +-- If the Lua table contains both string and numeric keys, it fits neither JSON's +-- idea of an object, nor its idea of an array. To get around this, when any string +-- key exists (or when non-positive numeric keys exist), numeric keys are converted +-- to strings. +-- +-- For example, +-- JSON:encode({ "one", "two", "three", SOMESTRING = "some string" })) +-- produces the JSON object +-- {"1":"one","2":"two","3":"three","SOMESTRING":"some string"} +-- +-- To prohibit this conversion and instead make it an error condition, set +-- JSON.noKeyConversion = true + + +-- +-- SUMMARY OF METHODS YOU CAN OVERRIDE IN YOUR LOCAL LUA JSON OBJECT +-- +-- assert +-- onDecodeError +-- onDecodeOfNilError +-- onDecodeOfHTMLError +-- onEncodeError +-- +-- If you want to create a separate Lua JSON object with its own error handlers, +-- you can reload JSON.lua or use the :new() method. +-- +--------------------------------------------------------------------------- + + +local author = "-[ JSON.lua package by Jeffrey Friedl (http://regex.info/blog/lua/json), version " .. tostring(VERSION) .. " ]-" +local isArray = { __tostring = function() return "JSON array" end } isArray.__index = isArray +local isObject = { __tostring = function() return "JSON object" end } isObject.__index = isObject + + +function OBJDEF:newArray(tbl) + return setmetatable(tbl or {}, isArray) +end + +function OBJDEF:newObject(tbl) + return setmetatable(tbl or {}, isObject) +end + +local function unicode_codepoint_as_utf8(codepoint) + -- + -- codepoint is a number + -- + if codepoint <= 127 then + return string.char(codepoint) + + elseif codepoint <= 2047 then + -- + -- 110yyyxx 10xxxxxx <-- useful notation from http://en.wikipedia.org/wiki/Utf8 + -- + local highpart = math.floor(codepoint / 0x40) + local lowpart = codepoint - (0x40 * highpart) + return string.char(0xC0 + highpart, + 0x80 + lowpart) + + elseif codepoint <= 65535 then + -- + -- 1110yyyy 10yyyyxx 10xxxxxx + -- + local highpart = math.floor(codepoint / 0x1000) + local remainder = codepoint - 0x1000 * highpart + local midpart = math.floor(remainder / 0x40) + local lowpart = remainder - 0x40 * midpart + + highpart = 0xE0 + highpart + midpart = 0x80 + midpart + lowpart = 0x80 + lowpart + + -- + -- Check for an invalid character (thanks Andy R. at Adobe). + -- See table 3.7, page 93, in http://www.unicode.org/versions/Unicode5.2.0/ch03.pdf#G28070 + -- + if ( highpart == 0xE0 and midpart < 0xA0 ) or + ( highpart == 0xED and midpart > 0x9F ) or + ( highpart == 0xF0 and midpart < 0x90 ) or + ( highpart == 0xF4 and midpart > 0x8F ) + then + return "?" + else + return string.char(highpart, + midpart, + lowpart) + end + + else + -- + -- 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx + -- + local highpart = math.floor(codepoint / 0x40000) + local remainder = codepoint - 0x40000 * highpart + local midA = math.floor(remainder / 0x1000) + remainder = remainder - 0x1000 * midA + local midB = math.floor(remainder / 0x40) + local lowpart = remainder - 0x40 * midB + + return string.char(0xF0 + highpart, + 0x80 + midA, + 0x80 + midB, + 0x80 + lowpart) + end +end + +function OBJDEF:onDecodeError(message, text, location, etc) + if text then + if location then + message = string.format("%s at char %d of: %s", message, location, text) + else + message = string.format("%s: %s", message, text) + end + end + if etc ~= nil then + message = message .. " (" .. OBJDEF:encode(etc) .. ")" + end + + if self.assert then + self.assert(false, message) + else + assert(false, message) + end +end + +OBJDEF.onDecodeOfNilError = OBJDEF.onDecodeError +OBJDEF.onDecodeOfHTMLError = OBJDEF.onDecodeError + +function OBJDEF:onEncodeError(message, etc) + if etc ~= nil then + message = message .. " (" .. OBJDEF:encode(etc) .. ")" + end + + if self.assert then + self.assert(false, message) + else + assert(false, message) + end +end + +local function grok_number(self, text, start, etc) + -- + -- Grab the integer part + -- + local integer_part = text:match('^-?[1-9]%d*', start) + or text:match("^-?0", start) + + if not integer_part then + self:onDecodeError("expected number", text, start, etc) + end + + local i = start + integer_part:len() + + -- + -- Grab an optional decimal part + -- + local decimal_part = text:match('^%.%d+', i) or "" + + i = i + decimal_part:len() + + -- + -- Grab an optional exponential part + -- + local exponent_part = text:match('^[eE][-+]?%d+', i) or "" + + i = i + exponent_part:len() + + local full_number_text = integer_part .. decimal_part .. exponent_part + local as_number = tonumber(full_number_text) + + if not as_number then + self:onDecodeError("bad number", text, start, etc) + end + + return as_number, i +end + + +local function grok_string(self, text, start, etc) + + if text:sub(start,start) ~= '"' then + self:onDecodeError("expected string's opening quote", text, start, etc) + end + + local i = start + 1 -- +1 to bypass the initial quote + local text_len = text:len() + local VALUE = "" + while i <= text_len do + local c = text:sub(i,i) + if c == '"' then + return VALUE, i + 1 + end + if c ~= '\\' then + VALUE = VALUE .. c + i = i + 1 + elseif text:match('^\\b', i) then + VALUE = VALUE .. "\b" + i = i + 2 + elseif text:match('^\\f', i) then + VALUE = VALUE .. "\f" + i = i + 2 + elseif text:match('^\\n', i) then + VALUE = VALUE .. "\n" + i = i + 2 + elseif text:match('^\\r', i) then + VALUE = VALUE .. "\r" + i = i + 2 + elseif text:match('^\\t', i) then + VALUE = VALUE .. "\t" + i = i + 2 + else + local hex = text:match('^\\u([0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i) + if hex then + i = i + 6 -- bypass what we just read + + -- We have a Unicode codepoint. It could be standalone, or if in the proper range and + -- followed by another in a specific range, it'll be a two-code surrogate pair. + local codepoint = tonumber(hex, 16) + if codepoint >= 0xD800 and codepoint <= 0xDBFF then + -- it's a hi surrogate... see whether we have a following low + local lo_surrogate = text:match('^\\u([dD][cdefCDEF][0123456789aAbBcCdDeEfF][0123456789aAbBcCdDeEfF])', i) + if lo_surrogate then + i = i + 6 -- bypass the low surrogate we just read + codepoint = 0x2400 + (codepoint - 0xD800) * 0x400 + tonumber(lo_surrogate, 16) + else + -- not a proper low, so we'll just leave the first codepoint as is and spit it out. + end + end + VALUE = VALUE .. unicode_codepoint_as_utf8(codepoint) + + else + + -- just pass through what's escaped + VALUE = VALUE .. text:match('^\\(.)', i) + i = i + 2 + end + end + end + + self:onDecodeError("unclosed string", text, start, etc) +end + +local function skip_whitespace(text, start) + + local match_start, match_end = text:find("^[ \n\r\t]+", start) -- [http://www.ietf.org/rfc/rfc4627.txt] Section 2 + if match_end then + return match_end + 1 + else + return start + end +end + +local grok_one -- assigned later + +local function grok_object(self, text, start, etc) + if not text:sub(start,start) == '{' then + self:onDecodeError("expected '{'", text, start, etc) + end + + local i = skip_whitespace(text, start + 1) -- +1 to skip the '{' + + local VALUE = self.strictTypes and self:newObject { } or { } + + if text:sub(i,i) == '}' then + return VALUE, i + 1 + end + local text_len = text:len() + while i <= text_len do + local key, new_i = grok_string(self, text, i, etc) + + i = skip_whitespace(text, new_i) + + if text:sub(i, i) ~= ':' then + self:onDecodeError("expected colon", text, i, etc) + end + + i = skip_whitespace(text, i + 1) + + local val, new_i = grok_one(self, text, i) + + VALUE[key] = val + + -- + -- Expect now either '}' to end things, or a ',' to allow us to continue. + -- + i = skip_whitespace(text, new_i) + + local c = text:sub(i,i) + + if c == '}' then + return VALUE, i + 1 + end + + if text:sub(i, i) ~= ',' then + self:onDecodeError("expected comma or '}'", text, i, etc) + end + + i = skip_whitespace(text, i + 1) + end + + self:onDecodeError("unclosed '{'", text, start, etc) +end + +local function grok_array(self, text, start, etc) + if not text:sub(start,start) == '[' then + self:onDecodeError("expected '['", text, start, etc) + end + + local i = skip_whitespace(text, start + 1) -- +1 to skip the '[' + local VALUE = self.strictTypes and self:newArray { } or { } + if text:sub(i,i) == ']' then + return VALUE, i + 1 + end + + local text_len = text:len() + while i <= text_len do + local val, new_i = grok_one(self, text, i) + + table.insert(VALUE, val) + + i = skip_whitespace(text, new_i) + + -- + -- Expect now either ']' to end things, or a ',' to allow us to continue. + -- + local c = text:sub(i,i) + if c == ']' then + return VALUE, i + 1 + end + if text:sub(i, i) ~= ',' then + self:onDecodeError("expected comma or '['", text, i, etc) + end + i = skip_whitespace(text, i + 1) + end + self:onDecodeError("unclosed '['", text, start, etc) +end + + +grok_one = function(self, text, start, etc) + -- Skip any whitespace + start = skip_whitespace(text, start) + + if start > text:len() then + self:onDecodeError("unexpected end of string", text, nil, etc) + end + + if text:find('^"', start) then + return grok_string(self, text, start, etc) + + elseif text:find('^[-0123456789 ]', start) then + return grok_number(self, text, start, etc) + + elseif text:find('^%{', start) then + return grok_object(self, text, start, etc) + + elseif text:find('^%[', start) then + return grok_array(self, text, start, etc) + + elseif text:find('^true', start) then + return true, start + 4 + + elseif text:find('^false', start) then + return false, start + 5 + + elseif text:find('^null', start) then + return nil, start + 4 + + else + self:onDecodeError("can't parse JSON", text, start, etc) + end +end + +function OBJDEF:decode(text, etc) + if type(self) ~= 'table' or self.__index ~= OBJDEF then + OBJDEF:onDecodeError("JSON:decode must be called in method format", nil, nil, etc) + end + + if text == nil then + self:onDecodeOfNilError(string.format("nil passed to JSON:decode()"), nil, nil, etc) + elseif type(text) ~= 'string' then + self:onDecodeError(string.format("expected string argument to JSON:decode(), got %s", type(text)), nil, nil, etc) + end + + if text:match('^%s*$') then + return nil + end + + if text:match('^%s*<') then + -- Can't be JSON... we'll assume it's HTML + self:onDecodeOfHTMLError(string.format("html passed to JSON:decode()"), text, nil, etc) + end + + -- + -- Ensure that it's not UTF-32 or UTF-16. + -- Those are perfectly valid encodings for JSON (as per RFC 4627 section 3), + -- but this package can't handle them. + -- + if text:sub(1,1):byte() == 0 or (text:len() >= 2 and text:sub(2,2):byte() == 0) then + self:onDecodeError("JSON package groks only UTF-8, sorry", text, nil, etc) + end + + local success, value = pcall(grok_one, self, text, 1, etc) + if success then + return value + else + -- should never get here... JSON parse errors should have been caught earlier + assert(false, value) + return nil + end +end + +local function backslash_replacement_function(c) + if c == "\n" then + return "\\n" + elseif c == "\r" then + return "\\r" + elseif c == "\t" then + return "\\t" + elseif c == "\b" then + return "\\b" + elseif c == "\f" then + return "\\f" + elseif c == '"' then + return '\\"' + elseif c == '\\' then + return '\\\\' + else + return string.format("\\u%04x", c:byte()) + end +end + +local chars_to_be_escaped_in_JSON_string + = '[' + .. '"' -- class sub-pattern to match a double quote + .. '%\\' -- class sub-pattern to match a backslash + .. '%z' -- class sub-pattern to match a null + .. '\001' .. '-' .. '\031' -- class sub-pattern to match control characters + .. ']' + +local function json_string_literal(value) + local newval = value:gsub(chars_to_be_escaped_in_JSON_string, backslash_replacement_function) + return '"' .. newval .. '"' +end + +local function object_or_array(self, T, etc) + -- + -- We need to inspect all the keys... if there are any strings, we'll convert to a JSON + -- object. If there are only numbers, it's a JSON array. + -- + -- If we'll be converting to a JSON object, we'll want to sort the keys so that the + -- end result is deterministic. + -- + local string_keys = { } + local number_keys = { } + local number_keys_must_be_strings = false + local maximum_number_key + + for key in pairs(T) do + if type(key) == 'string' then + table.insert(string_keys, key) + elseif type(key) == 'number' then + table.insert(number_keys, key) + if key <= 0 or key >= math.huge then + number_keys_must_be_strings = true + elseif not maximum_number_key or key > maximum_number_key then + maximum_number_key = key + end + else + self:onEncodeError("can't encode table with a key of type " .. type(key), etc) + end + end + + if #string_keys == 0 and not number_keys_must_be_strings then + -- + -- An empty table, or a numeric-only array + -- + if #number_keys > 0 then + return nil, maximum_number_key -- an array + elseif tostring(T) == "JSON array" then + return nil + elseif tostring(T) == "JSON object" then + return { } + else + -- have to guess, so we'll pick array, since empty arrays are likely more common than empty objects + return nil + end + end + + table.sort(string_keys) + + local map + if #number_keys > 0 then + -- + -- If we're here then we have either mixed string/number keys, or numbers inappropriate for a JSON array + -- It's not ideal, but we'll turn the numbers into strings so that we can at least create a JSON object. + -- + + if JSON.noKeyConversion then + self:onEncodeError("a table with both numeric and string keys could be an object or array; aborting", etc) + end + + -- + -- Have to make a shallow copy of the source table so we can remap the numeric keys to be strings + -- + map = { } + for key, val in pairs(T) do + map[key] = val + end + + table.sort(number_keys) + + -- + -- Throw numeric keys in there as strings + -- + for _, number_key in ipairs(number_keys) do + local string_key = tostring(number_key) + if map[string_key] == nil then + table.insert(string_keys , string_key) + map[string_key] = T[number_key] + else + self:onEncodeError("conflict converting table with mixed-type keys into a JSON object: key " .. number_key .. " exists both as a string and a number.", etc) + end + end + end + + return string_keys, nil, map +end + +-- +-- Encode +-- +local encode_value -- must predeclare because it calls itself +function encode_value(self, value, parents, etc, indent) -- non-nil indent means pretty-printing + + if value == nil then + return 'null' + + elseif type(value) == 'string' then + return json_string_literal(value) + + elseif type(value) == 'number' then + if value ~= value then + -- + -- NaN (Not a Number). + -- JSON has no NaN, so we have to fudge the best we can. This should really be a package option. + -- + return "null" + elseif value >= math.huge then + -- + -- Positive infinity. JSON has no INF, so we have to fudge the best we can. This should + -- really be a package option. Note: at least with some implementations, positive infinity + -- is both ">= math.huge" and "<= -math.huge", which makes no sense but that's how it is. + -- Negative infinity is properly "<= -math.huge". So, we must be sure to check the ">=" + -- case first. + -- + return "1e+9999" + elseif value <= -math.huge then + -- + -- Negative infinity. + -- JSON has no INF, so we have to fudge the best we can. This should really be a package option. + -- + return "-1e+9999" + else + return tostring(value) + end + + elseif type(value) == 'boolean' then + return tostring(value) + + elseif type(value) ~= 'table' then + self:onEncodeError("can't convert " .. type(value) .. " to JSON", etc) + + else + -- + -- A table to be converted to either a JSON object or array. + -- + local T = value + + if parents[T] then + self:onEncodeError("table " .. tostring(T) .. " is a child of itself", etc) + else + parents[T] = true + end + + local result_value + + local object_keys, maximum_number_key, map = object_or_array(self, T, etc) + if maximum_number_key then + -- + -- An array... + -- + local ITEMS = { } + for i = 1, maximum_number_key do + table.insert(ITEMS, encode_value(self, T[i], parents, etc, indent)) + end + + if indent then + result_value = "[ " .. table.concat(ITEMS, ", ") .. " ]" + else + result_value = "[" .. table.concat(ITEMS, ",") .. "]" + end + + elseif object_keys then + -- + -- An object + -- + local TT = map or T + + if indent then + + local KEYS = { } + local max_key_length = 0 + for _, key in ipairs(object_keys) do + local encoded = encode_value(self, tostring(key), parents, etc, "") + max_key_length = math.max(max_key_length, #encoded) + table.insert(KEYS, encoded) + end + local key_indent = indent .. " " + local subtable_indent = indent .. string.rep(" ", max_key_length + 2 + 4) + local FORMAT = "%s%" .. string.format("%d", max_key_length) .. "s: %s" + + local COMBINED_PARTS = { } + for i, key in ipairs(object_keys) do + local encoded_val = encode_value(self, TT[key], parents, etc, subtable_indent) + table.insert(COMBINED_PARTS, string.format(FORMAT, key_indent, KEYS[i], encoded_val)) + end + result_value = "{\n" .. table.concat(COMBINED_PARTS, ",\n") .. "\n" .. indent .. "}" + + else + + local PARTS = { } + for _, key in ipairs(object_keys) do + local encoded_val = encode_value(self, TT[key], parents, etc, indent) + local encoded_key = encode_value(self, tostring(key), parents, etc, indent) + table.insert(PARTS, string.format("%s:%s", encoded_key, encoded_val)) + end + result_value = "{" .. table.concat(PARTS, ",") .. "}" + + end + else + -- + -- An empty array/object... we'll treat it as an array, though it should really be an option + -- + result_value = "[]" + end + + parents[T] = false + return result_value + end +end + + +function OBJDEF:encode(value, etc) + if type(self) ~= 'table' or self.__index ~= OBJDEF then + OBJDEF:onEncodeError("JSON:encode must be called in method format", etc) + end + return encode_value(self, value, {}, etc, nil) +end + +function OBJDEF:encode_pretty(value, etc) + if type(self) ~= 'table' or self.__index ~= OBJDEF then + OBJDEF:onEncodeError("JSON:encode_pretty must be called in method format", etc) + end + return encode_value(self, value, {}, etc, "") +end + +function OBJDEF.__tostring() + return "JSON encode/decode package" +end + +OBJDEF.__index = OBJDEF + +function OBJDEF:new(args) + local new = { } + + if args then + for key, val in pairs(args) do + new[key] = val + end + end + + return setmetatable(new, OBJDEF) +end + +return OBJDEF:new() + +-- +-- Version history: +-- +-- 20131118.9 Update for Lua 5.3... it seems that tostring(2/1) produces "2.0" instead of "2", +-- and this caused some problems. +-- +-- 20131031.8 Unified the code for encode() and encode_pretty(); they had been stupidly separate, +-- and had of course diverged (encode_pretty didn't get the fixes that encode got, so +-- sometimes produced incorrect results; thanks to Mattie for the heads up). +-- +-- Handle encoding tables with non-positive numeric keys (unlikely, but possible). +-- +-- If a table has both numeric and string keys, or its numeric keys are inappropriate +-- (such as being non-positive or infinite), the numeric keys are turned into +-- string keys appropriate for a JSON object. So, as before, +-- JSON:encode({ "one", "two", "three" }) +-- produces the array +-- ["one","two","three"] +-- but now something with mixed key types like +-- JSON:encode({ "one", "two", "three", SOMESTRING = "some string" })) +-- instead of throwing an error produces an object: +-- {"1":"one","2":"two","3":"three","SOMESTRING":"some string"} +-- +-- To maintain the prior throw-an-error semantics, set +-- JSON.noKeyConversion = true +-- +-- 20131004.7 Release under a Creative Commons CC-BY license, which I should have done from day one, sorry. +-- +-- 20130120.6 Comment update: added a link to the specific page on my blog where this code can +-- be found, so that folks who come across the code outside of my blog can find updates +-- more easily. +-- +-- 20111207.5 Added support for the 'etc' arguments, for better error reporting. +-- +-- 20110731.4 More feedback from David Kolf on how to make the tests for Nan/Infinity system independent. +-- +-- 20110730.3 Incorporated feedback from David Kolf at http://lua-users.org/wiki/JsonModules: +-- +-- * When encoding lua for JSON, Sparse numeric arrays are now handled by +-- spitting out full arrays, such that +-- JSON:encode({"one", "two", [10] = "ten"}) +-- returns +-- ["one","two",null,null,null,null,null,null,null,"ten"] +-- +-- In 20100810.2 and earlier, only up to the first non-null value would have been retained. +-- +-- * When encoding lua for JSON, numeric value NaN gets spit out as null, and infinity as "1+e9999". +-- Version 20100810.2 and earlier created invalid JSON in both cases. +-- +-- * Unicode surrogate pairs are now detected when decoding JSON. +-- +-- 20100810.2 added some checking to ensure that an invalid Unicode character couldn't leak in to the UTF-8 encoding +-- +-- 20100731.1 initial public release +-- diff --git a/aes.c b/aes.c new file mode 100644 index 0000000..1a7654d --- /dev/null +++ b/aes.c @@ -0,0 +1,401 @@ +// advanced encryption standard +// author: karl malbrain, malbrain@yahoo.com +/* +This work, including the source code, documentation +and related data, is placed into the public domain. + +The orginal author is Karl Malbrain. + +THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY +OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF +MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, +ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE +RESULTING FROM THE USE, MODIFICATION, OR +REDISTRIBUTION OF THIS SOFTWARE. +*/ + +#include +#include +#include + +#include "aes.h" + +#define Nb aesNb +#define Nk aesNk +#define Nr aesNr + +static const uint8_t Sbox[256] = { // forward s-box +0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, +0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, +0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, +0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, +0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, +0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, +0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, +0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, +0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, +0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, +0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, +0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, +0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, +0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, +0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, +0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16}; + +static const uint8_t InvSbox[256] = { // inverse s-box +0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, +0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, +0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, +0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, +0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, +0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, +0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, +0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, +0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, +0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, +0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, +0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, +0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, +0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, +0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, +0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d}; + +// combined Xtimes2[Sbox[]] +static const uint8_t Xtime2Sbox[256] = { +0xc6, 0xf8, 0xee, 0xf6, 0xff, 0xd6, 0xde, 0x91, 0x60, 0x02, 0xce, 0x56, 0xe7, 0xb5, 0x4d, 0xec, +0x8f, 0x1f, 0x89, 0xfa, 0xef, 0xb2, 0x8e, 0xfb, 0x41, 0xb3, 0x5f, 0x45, 0x23, 0x53, 0xe4, 0x9b, +0x75, 0xe1, 0x3d, 0x4c, 0x6c, 0x7e, 0xf5, 0x83, 0x68, 0x51, 0xd1, 0xf9, 0xe2, 0xab, 0x62, 0x2a, +0x08, 0x95, 0x46, 0x9d, 0x30, 0x37, 0x0a, 0x2f, 0x0e, 0x24, 0x1b, 0xdf, 0xcd, 0x4e, 0x7f, 0xea, +0x12, 0x1d, 0x58, 0x34, 0x36, 0xdc, 0xb4, 0x5b, 0xa4, 0x76, 0xb7, 0x7d, 0x52, 0xdd, 0x5e, 0x13, +0xa6, 0xb9, 0x00, 0xc1, 0x40, 0xe3, 0x79, 0xb6, 0xd4, 0x8d, 0x67, 0x72, 0x94, 0x98, 0xb0, 0x85, +0xbb, 0xc5, 0x4f, 0xed, 0x86, 0x9a, 0x66, 0x11, 0x8a, 0xe9, 0x04, 0xfe, 0xa0, 0x78, 0x25, 0x4b, +0xa2, 0x5d, 0x80, 0x05, 0x3f, 0x21, 0x70, 0xf1, 0x63, 0x77, 0xaf, 0x42, 0x20, 0xe5, 0xfd, 0xbf, +0x81, 0x18, 0x26, 0xc3, 0xbe, 0x35, 0x88, 0x2e, 0x93, 0x55, 0xfc, 0x7a, 0xc8, 0xba, 0x32, 0xe6, +0xc0, 0x19, 0x9e, 0xa3, 0x44, 0x54, 0x3b, 0x0b, 0x8c, 0xc7, 0x6b, 0x28, 0xa7, 0xbc, 0x16, 0xad, +0xdb, 0x64, 0x74, 0x14, 0x92, 0x0c, 0x48, 0xb8, 0x9f, 0xbd, 0x43, 0xc4, 0x39, 0x31, 0xd3, 0xf2, +0xd5, 0x8b, 0x6e, 0xda, 0x01, 0xb1, 0x9c, 0x49, 0xd8, 0xac, 0xf3, 0xcf, 0xca, 0xf4, 0x47, 0x10, +0x6f, 0xf0, 0x4a, 0x5c, 0x38, 0x57, 0x73, 0x97, 0xcb, 0xa1, 0xe8, 0x3e, 0x96, 0x61, 0x0d, 0x0f, +0xe0, 0x7c, 0x71, 0xcc, 0x90, 0x06, 0xf7, 0x1c, 0xc2, 0x6a, 0xae, 0x69, 0x17, 0x99, 0x3a, 0x27, +0xd9, 0xeb, 0x2b, 0x22, 0xd2, 0xa9, 0x07, 0x33, 0x2d, 0x3c, 0x15, 0xc9, 0x87, 0xaa, 0x50, 0xa5, +0x03, 0x59, 0x09, 0x1a, 0x65, 0xd7, 0x84, 0xd0, 0x82, 0x29, 0x5a, 0x1e, 0x7b, 0xa8, 0x6d, 0x2c +}; + +// combined Xtimes3[Sbox[]] +static const uint8_t Xtime3Sbox[256] = { +0xa5, 0x84, 0x99, 0x8d, 0x0d, 0xbd, 0xb1, 0x54, 0x50, 0x03, 0xa9, 0x7d, 0x19, 0x62, 0xe6, 0x9a, +0x45, 0x9d, 0x40, 0x87, 0x15, 0xeb, 0xc9, 0x0b, 0xec, 0x67, 0xfd, 0xea, 0xbf, 0xf7, 0x96, 0x5b, +0xc2, 0x1c, 0xae, 0x6a, 0x5a, 0x41, 0x02, 0x4f, 0x5c, 0xf4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3f, +0x0c, 0x52, 0x65, 0x5e, 0x28, 0xa1, 0x0f, 0xb5, 0x09, 0x36, 0x9b, 0x3d, 0x26, 0x69, 0xcd, 0x9f, +0x1b, 0x9e, 0x74, 0x2e, 0x2d, 0xb2, 0xee, 0xfb, 0xf6, 0x4d, 0x61, 0xce, 0x7b, 0x3e, 0x71, 0x97, +0xf5, 0x68, 0x00, 0x2c, 0x60, 0x1f, 0xc8, 0xed, 0xbe, 0x46, 0xd9, 0x4b, 0xde, 0xd4, 0xe8, 0x4a, +0x6b, 0x2a, 0xe5, 0x16, 0xc5, 0xd7, 0x55, 0x94, 0xcf, 0x10, 0x06, 0x81, 0xf0, 0x44, 0xba, 0xe3, +0xf3, 0xfe, 0xc0, 0x8a, 0xad, 0xbc, 0x48, 0x04, 0xdf, 0xc1, 0x75, 0x63, 0x30, 0x1a, 0x0e, 0x6d, +0x4c, 0x14, 0x35, 0x2f, 0xe1, 0xa2, 0xcc, 0x39, 0x57, 0xf2, 0x82, 0x47, 0xac, 0xe7, 0x2b, 0x95, +0xa0, 0x98, 0xd1, 0x7f, 0x66, 0x7e, 0xab, 0x83, 0xca, 0x29, 0xd3, 0x3c, 0x79, 0xe2, 0x1d, 0x76, +0x3b, 0x56, 0x4e, 0x1e, 0xdb, 0x0a, 0x6c, 0xe4, 0x5d, 0x6e, 0xef, 0xa6, 0xa8, 0xa4, 0x37, 0x8b, +0x32, 0x43, 0x59, 0xb7, 0x8c, 0x64, 0xd2, 0xe0, 0xb4, 0xfa, 0x07, 0x25, 0xaf, 0x8e, 0xe9, 0x18, +0xd5, 0x88, 0x6f, 0x72, 0x24, 0xf1, 0xc7, 0x51, 0x23, 0x7c, 0x9c, 0x21, 0xdd, 0xdc, 0x86, 0x85, +0x90, 0x42, 0xc4, 0xaa, 0xd8, 0x05, 0x01, 0x12, 0xa3, 0x5f, 0xf9, 0xd0, 0x91, 0x58, 0x27, 0xb9, +0x38, 0x13, 0xb3, 0x33, 0xbb, 0x70, 0x89, 0xa7, 0xb6, 0x22, 0x92, 0x20, 0x49, 0xff, 0x78, 0x7a, +0x8f, 0xf8, 0x80, 0x17, 0xda, 0x31, 0xc6, 0xb8, 0xc3, 0xb0, 0x77, 0x11, 0xcb, 0xfc, 0xd6, 0x3a +}; + +// modular multiplication tables +// based on: + +// Xtime2[x] = (x & 0x80 ? 0x1b : 0) ^ (x + x) +// Xtime3[x] = x^Xtime2[x]; + +static const uint8_t Xtime2[256] = { +0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, +0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, +0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, +0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, +0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, +0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, +0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, +0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, +0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, +0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, +0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, +0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, +0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, +0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, +0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, +0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5}; + +static const uint8_t Xtime9[256] = { +0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, +0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, +0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, +0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, +0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, +0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, +0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, +0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, +0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, +0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, +0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, +0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, +0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, +0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, +0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, +0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46}; + +static const uint8_t XtimeB[256] = { +0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, +0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, +0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, +0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, +0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, +0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, +0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, +0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, +0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, +0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, +0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, +0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, +0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, +0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, +0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, +0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3}; + +static const uint8_t XtimeD[256] = { +0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, +0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, +0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, +0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, +0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, +0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, +0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, +0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, +0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, +0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, +0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, +0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, +0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, +0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, +0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, +0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97}; + +static const uint8_t XtimeE[256] = { +0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, +0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, +0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, +0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, +0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, +0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, +0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, +0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, +0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, +0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, +0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, +0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, +0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, +0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, +0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, +0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d}; + +// exchanges columns in each of 4 rows +// row0 - unchanged, row1- shifted left 1, +// row2 - shifted left 2 and row3 - shifted left 3 +static void ShiftRows (uint8_t *state) +{ +uint8_t tmp; + + // just substitute row 0 + state[0] = Sbox[state[0]], state[4] = Sbox[state[4]]; + state[8] = Sbox[state[8]], state[12] = Sbox[state[12]]; + + // rotate row 1 + tmp = Sbox[state[1]], state[1] = Sbox[state[5]]; + state[5] = Sbox[state[9]], state[9] = Sbox[state[13]], state[13] = tmp; + + // rotate row 2 + tmp = Sbox[state[2]], state[2] = Sbox[state[10]], state[10] = tmp; + tmp = Sbox[state[6]], state[6] = Sbox[state[14]], state[14] = tmp; + + // rotate row 3 + tmp = Sbox[state[15]], state[15] = Sbox[state[11]]; + state[11] = Sbox[state[7]], state[7] = Sbox[state[3]], state[3] = tmp; +} + +// restores columns in each of 4 rows +// row0 - unchanged, row1- shifted right 1, +// row2 - shifted right 2 and row3 - shifted right 3 +static void InvShiftRows (uint8_t *state) +{ +uint8_t tmp; + + // restore row 0 + state[0] = InvSbox[state[0]], state[4] = InvSbox[state[4]]; + state[8] = InvSbox[state[8]], state[12] = InvSbox[state[12]]; + + // restore row 1 + tmp = InvSbox[state[13]], state[13] = InvSbox[state[9]]; + state[9] = InvSbox[state[5]], state[5] = InvSbox[state[1]], state[1] = tmp; + + // restore row 2 + tmp = InvSbox[state[2]], state[2] = InvSbox[state[10]], state[10] = tmp; + tmp = InvSbox[state[6]], state[6] = InvSbox[state[14]], state[14] = tmp; + + // restore row 3 + tmp = InvSbox[state[3]], state[3] = InvSbox[state[7]]; + state[7] = InvSbox[state[11]], state[11] = InvSbox[state[15]], state[15] = tmp; +} + +// recombine and mix each row in a column +static void MixSubColumns (uint8_t *state) +{ +uint8_t tmp[4 * Nb]; + + // mixing column 0 + tmp[0] = Xtime2Sbox[state[0]] ^ Xtime3Sbox[state[5]] ^ Sbox[state[10]] ^ Sbox[state[15]]; + tmp[1] = Sbox[state[0]] ^ Xtime2Sbox[state[5]] ^ Xtime3Sbox[state[10]] ^ Sbox[state[15]]; + tmp[2] = Sbox[state[0]] ^ Sbox[state[5]] ^ Xtime2Sbox[state[10]] ^ Xtime3Sbox[state[15]]; + tmp[3] = Xtime3Sbox[state[0]] ^ Sbox[state[5]] ^ Sbox[state[10]] ^ Xtime2Sbox[state[15]]; + + // mixing column 1 + tmp[4] = Xtime2Sbox[state[4]] ^ Xtime3Sbox[state[9]] ^ Sbox[state[14]] ^ Sbox[state[3]]; + tmp[5] = Sbox[state[4]] ^ Xtime2Sbox[state[9]] ^ Xtime3Sbox[state[14]] ^ Sbox[state[3]]; + tmp[6] = Sbox[state[4]] ^ Sbox[state[9]] ^ Xtime2Sbox[state[14]] ^ Xtime3Sbox[state[3]]; + tmp[7] = Xtime3Sbox[state[4]] ^ Sbox[state[9]] ^ Sbox[state[14]] ^ Xtime2Sbox[state[3]]; + + // mixing column 2 + tmp[8] = Xtime2Sbox[state[8]] ^ Xtime3Sbox[state[13]] ^ Sbox[state[2]] ^ Sbox[state[7]]; + tmp[9] = Sbox[state[8]] ^ Xtime2Sbox[state[13]] ^ Xtime3Sbox[state[2]] ^ Sbox[state[7]]; + tmp[10] = Sbox[state[8]] ^ Sbox[state[13]] ^ Xtime2Sbox[state[2]] ^ Xtime3Sbox[state[7]]; + tmp[11] = Xtime3Sbox[state[8]] ^ Sbox[state[13]] ^ Sbox[state[2]] ^ Xtime2Sbox[state[7]]; + + // mixing column 3 + tmp[12] = Xtime2Sbox[state[12]] ^ Xtime3Sbox[state[1]] ^ Sbox[state[6]] ^ Sbox[state[11]]; + tmp[13] = Sbox[state[12]] ^ Xtime2Sbox[state[1]] ^ Xtime3Sbox[state[6]] ^ Sbox[state[11]]; + tmp[14] = Sbox[state[12]] ^ Sbox[state[1]] ^ Xtime2Sbox[state[6]] ^ Xtime3Sbox[state[11]]; + tmp[15] = Xtime3Sbox[state[12]] ^ Sbox[state[1]] ^ Sbox[state[6]] ^ Xtime2Sbox[state[11]]; + + memcpy (state, tmp, sizeof(tmp)); +} + +// restore and un-mix each row in a column +void InvMixSubColumns (uint8_t *state) +{ +uint8_t tmp[4 * Nb]; +int i; + + // restore column 0 + tmp[0] = XtimeE[state[0]] ^ XtimeB[state[1]] ^ XtimeD[state[2]] ^ Xtime9[state[3]]; + tmp[5] = Xtime9[state[0]] ^ XtimeE[state[1]] ^ XtimeB[state[2]] ^ XtimeD[state[3]]; + tmp[10] = XtimeD[state[0]] ^ Xtime9[state[1]] ^ XtimeE[state[2]] ^ XtimeB[state[3]]; + tmp[15] = XtimeB[state[0]] ^ XtimeD[state[1]] ^ Xtime9[state[2]] ^ XtimeE[state[3]]; + + // restore column 1 + tmp[4] = XtimeE[state[4]] ^ XtimeB[state[5]] ^ XtimeD[state[6]] ^ Xtime9[state[7]]; + tmp[9] = Xtime9[state[4]] ^ XtimeE[state[5]] ^ XtimeB[state[6]] ^ XtimeD[state[7]]; + tmp[14] = XtimeD[state[4]] ^ Xtime9[state[5]] ^ XtimeE[state[6]] ^ XtimeB[state[7]]; + tmp[3] = XtimeB[state[4]] ^ XtimeD[state[5]] ^ Xtime9[state[6]] ^ XtimeE[state[7]]; + + // restore column 2 + tmp[8] = XtimeE[state[8]] ^ XtimeB[state[9]] ^ XtimeD[state[10]] ^ Xtime9[state[11]]; + tmp[13] = Xtime9[state[8]] ^ XtimeE[state[9]] ^ XtimeB[state[10]] ^ XtimeD[state[11]]; + tmp[2] = XtimeD[state[8]] ^ Xtime9[state[9]] ^ XtimeE[state[10]] ^ XtimeB[state[11]]; + tmp[7] = XtimeB[state[8]] ^ XtimeD[state[9]] ^ Xtime9[state[10]] ^ XtimeE[state[11]]; + + // restore column 3 + tmp[12] = XtimeE[state[12]] ^ XtimeB[state[13]] ^ XtimeD[state[14]] ^ Xtime9[state[15]]; + tmp[1] = Xtime9[state[12]] ^ XtimeE[state[13]] ^ XtimeB[state[14]] ^ XtimeD[state[15]]; + tmp[6] = XtimeD[state[12]] ^ Xtime9[state[13]] ^ XtimeE[state[14]] ^ XtimeB[state[15]]; + tmp[11] = XtimeB[state[12]] ^ XtimeD[state[13]] ^ Xtime9[state[14]] ^ XtimeE[state[15]]; + + for( i=0; i < 4 * Nb; i++ ) + state[i] = InvSbox[tmp[i]]; +} + +// encrypt/decrypt columns of the key +// n.b. you can replace this with +// byte-wise xor if you wish. + +static void AddRoundKey (unsigned *state, unsigned *key) +{ +int idx; + + for( idx = 0; idx < 4; idx++ ) + state[idx] ^= key[idx]; +} + +uint8_t Rcon[11] = { +0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; + +// produce Nb bytes for each round +void aesExpandKey(const uint8_t *key, uint8_t *expkey) +{ +uint8_t tmp0, tmp1, tmp2, tmp3, tmp4; +unsigned idx; + + memcpy (expkey, key, Nk * 4); + + for( idx = Nk; idx < Nb * (Nr + 1); idx++ ) { + tmp0 = expkey[4*idx - 4]; + tmp1 = expkey[4*idx - 3]; + tmp2 = expkey[4*idx - 2]; + tmp3 = expkey[4*idx - 1]; + if( !(idx % Nk) ) { + tmp4 = tmp3; + tmp3 = Sbox[tmp0]; + tmp0 = Sbox[tmp1] ^ Rcon[idx/Nk]; + tmp1 = Sbox[tmp2]; + tmp2 = Sbox[tmp4]; + } else if( Nk > 6 && idx % Nk == 4 ) { + tmp0 = Sbox[tmp0]; + tmp1 = Sbox[tmp1]; + tmp2 = Sbox[tmp2]; + tmp3 = Sbox[tmp3]; + } + + expkey[4*idx+0] = expkey[4*idx - 4*Nk + 0] ^ tmp0; + expkey[4*idx+1] = expkey[4*idx - 4*Nk + 1] ^ tmp1; + expkey[4*idx+2] = expkey[4*idx - 4*Nk + 2] ^ tmp2; + expkey[4*idx+3] = expkey[4*idx - 4*Nk + 3] ^ tmp3; + } +} + +// encrypt one 128 bit block +void aesEncrypt (uint8_t *in, uint8_t *expkey, uint8_t *out) +{ +uint8_t state[Nb * 4]; +unsigned round; + + memcpy (state, in, Nb * 4); + AddRoundKey ((unsigned *)state, (unsigned *)expkey); + + for( round = 1; round < Nr + 1; round++ ) { + if( round < Nr ) + MixSubColumns (state); + else + ShiftRows (state); + + AddRoundKey ((unsigned *)state, (unsigned *)expkey + round * Nb); + } + + memcpy (out, state, sizeof(state)); +} + +void aesDecrypt (uint8_t *in, uint8_t *expkey, uint8_t *out) +{ +uint8_t state[Nb * 4]; +unsigned round; + + memcpy (state, in, sizeof(state)); + + AddRoundKey ((unsigned *)state, (unsigned *)expkey + Nr * Nb); + InvShiftRows(state); + + for( round = Nr; round--; ) + { + AddRoundKey ((unsigned *)state, (unsigned *)expkey + round * Nb); + if( round ) + InvMixSubColumns (state); + } + + memcpy (out, state, sizeof(state)); +} + diff --git a/aes.h b/aes.h new file mode 100644 index 0000000..89760b1 --- /dev/null +++ b/aes.h @@ -0,0 +1,18 @@ +#ifndef _INCL_AES_H_ +#define _INCL_AES_H_ + +#include + +// AES-128 only supports Nb=4 +#define aesNb 4 // number of columns in the state & expanded key +#define aesNk 4 // number of columns in a key +#define aesNr 10 // number of rounds in encryption + +#define aesExpandedKeySize (4 * aesNb * (aesNr + 1)) +void aesExpandKey(const uint8_t *key, uint8_t *expkey); + +// these do one 128-bit block at a time. +void aesEncrypt (uint8_t *in, uint8_t *expkey, uint8_t *out); +void aesDecrypt (uint8_t *in, uint8_t *expkey, uint8_t *out); + +#endif diff --git a/base64.c b/base64.c new file mode 100644 index 0000000..3b62099 --- /dev/null +++ b/base64.c @@ -0,0 +1,197 @@ +/* +cdecoder.c - c source to a base64 decoding algorithm implementation + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#include "base64.h" + +int base64_decode_value(char value_in) +{ + static const char decoding[] = {62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-2,-1,-1,-1,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,-1,-1,-1,-1,-1,-1,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}; + static const char decoding_size = sizeof(decoding); + value_in -= 43; + if (value_in < 0 || value_in > decoding_size) return -1; + return decoding[(int)value_in]; +} + +void base64_init_decodestate(base64_decodestate* state_in) +{ + state_in->step = step_a; + state_in->plainchar = 0; +} + +int base64_decode_block(const char* code_in, const int length_in, uint8_t* plaintext_out, base64_decodestate* state_in) +{ + const char* codechar = code_in; + uint8_t* plainchar = plaintext_out; + char fragment; + + *plainchar = state_in->plainchar; + + switch (state_in->step) + { + while (1) + { + case step_a: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_a; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar = (fragment & 0x03f) << 2; + case step_b: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_b; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x030) >> 4; + *plainchar = (fragment & 0x00f) << 4; + case step_c: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_c; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03c) >> 2; + *plainchar = (fragment & 0x003) << 6; + case step_d: + do { + if (codechar == code_in+length_in) + { + state_in->step = step_d; + state_in->plainchar = *plainchar; + return plainchar - plaintext_out; + } + fragment = (char)base64_decode_value(*codechar++); + } while (fragment < 0); + *plainchar++ |= (fragment & 0x03f); + } + } + /* control should not reach here */ + return plainchar - plaintext_out; +} + +/* +cencoder.c - c source to a base64 encoding algorithm implementation + +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +const int CHARS_PER_LINE = 72; + +void base64_init_encodestate(base64_encodestate* state_in) +{ + state_in->step = step_A; + state_in->result = 0; + state_in->stepcount = 0; +} + +char base64_encode_value(char value_in) +{ + static const char* encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + if (value_in > 63) return '='; + return encoding[(int)value_in]; +} + +int base64_encode_block(const uint8_t* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in) +{ + const uint8_t* plainchar = plaintext_in; + const uint8_t* const plaintextend = plaintext_in + length_in; + char* codechar = code_out; + char result; + uint8_t fragment; + + result = state_in->result; + + switch (state_in->step) + { + while (1) + { + case step_A: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_A; + return codechar - code_out; + } + fragment = *plainchar++; + result = (fragment & 0x0fc) >> 2; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x003) << 4; + case step_B: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_B; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0f0) >> 4; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x00f) << 2; + case step_C: + if (plainchar == plaintextend) + { + state_in->result = result; + state_in->step = step_C; + return codechar - code_out; + } + fragment = *plainchar++; + result |= (fragment & 0x0c0) >> 6; + *codechar++ = base64_encode_value(result); + result = (fragment & 0x03f) >> 0; + *codechar++ = base64_encode_value(result); + + ++(state_in->stepcount); + if (state_in->stepcount == CHARS_PER_LINE/4) + { + *codechar++ = '\n'; + state_in->stepcount = 0; + } + } + } + /* control should not reach here */ + return codechar - code_out; +} + +int base64_encode_blockend(char* code_out, base64_encodestate* state_in) +{ + char* codechar = code_out; + + switch (state_in->step) + { + case step_B: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + *codechar++ = '='; + break; + case step_C: + *codechar++ = base64_encode_value(state_in->result); + *codechar++ = '='; + break; + case step_A: + break; + } + *codechar++ = '\n'; + + return codechar - code_out; +} + +// end of base64.c ... + diff --git a/base64.h b/base64.h new file mode 100644 index 0000000..dc6f9a1 --- /dev/null +++ b/base64.h @@ -0,0 +1,46 @@ +/* +cdecode.h - c header for a base64 decoding algorithm +This is part of the libb64 project, and has been placed in the public domain. +For details, see http://sourceforge.net/projects/libb64 +*/ + +#ifndef _INCL_BASE64_H_ +#define _INCL_BASE64_H_ + +#include + +typedef enum +{ + step_a, step_b, step_c, step_d +} base64_decodestep; + +typedef struct +{ + base64_decodestep step; + char plainchar; +} base64_decodestate; + +void base64_init_decodestate(base64_decodestate* state_in); +int base64_decode_value(char value_in); +int base64_decode_block(const char* code_in, const int length_in, uint8_t* plaintext_out, base64_decodestate* state_in); + + +typedef enum +{ + step_A, step_B, step_C +} base64_encodestep; + +typedef struct +{ + base64_encodestep step; + char result; + int stepcount; +} base64_encodestate; + +void base64_init_encodestate(base64_encodestate* state_in); +char base64_encode_value(char value_in); +int base64_encode_block(const uint8_t* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in); +int base64_encode_blockend(char* code_out, base64_encodestate* state_in); + +#endif + diff --git a/lua/Makefile b/lua/Makefile new file mode 100644 index 0000000..7b4b2b7 --- /dev/null +++ b/lua/Makefile @@ -0,0 +1,187 @@ +# Makefile for building Lua +# See ../doc/readme.html for installation and customization instructions. + +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= + +# Your platform. See PLATS for possible values. +PLAT= none + +CC= gcc +CFLAGS= -O2 -Wall -DLUA_COMPAT_ALL $(SYSCFLAGS) $(MYCFLAGS) +LDFLAGS= $(SYSLDFLAGS) $(MYLDFLAGS) +LIBS= -lm $(SYSLIBS) $(MYLIBS) + +AR= ar rcu +RANLIB= ranlib +RM= rm -f + +SYSCFLAGS= +SYSLDFLAGS= +SYSLIBS= + +MYCFLAGS= +MYLDFLAGS= +MYLIBS= +MYOBJS= + +# == END OF USER SETTINGS -- NO NEED TO CHANGE ANYTHING BELOW THIS LINE ======= + +PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris + +LUA_A= liblua.a +CORE_O= lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o \ + lmem.o lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o \ + ltm.o lundump.o lvm.o lzio.o +LIB_O= lauxlib.o lbaselib.o lbitlib.o lcorolib.o ldblib.o liolib.o \ + lmathlib.o loslib.o lstrlib.o ltablib.o loadlib.o linit.o +BASE_O= $(CORE_O) $(LIB_O) $(MYOBJS) + +LUA_T= lua +LUA_O= lua.o + +LUAC_T= luac +LUAC_O= luac.o + +ALL_O= $(BASE_O) $(LUA_O) $(LUAC_O) +ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) +ALL_A= $(LUA_A) + +# Targets start here. +default: $(PLAT) + +all: $(ALL_T) + +o: $(ALL_O) + +a: $(ALL_A) + +$(LUA_A): $(BASE_O) + $(AR) $@ $(BASE_O) + $(RANLIB) $@ + +$(LUA_T): $(LUA_O) $(LUA_A) + $(CC) -o $@ $(LDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) + +$(LUAC_T): $(LUAC_O) $(LUA_A) + $(CC) -o $@ $(LDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) + +clean: + $(RM) $(ALL_T) $(ALL_O) + +depend: + @$(CC) $(CFLAGS) -MM l*.c + +echo: + @echo "PLAT= $(PLAT)" + @echo "CC= $(CC)" + @echo "CFLAGS= $(CFLAGS)" + @echo "LDFLAGS= $(SYSLDFLAGS)" + @echo "LIBS= $(LIBS)" + @echo "AR= $(AR)" + @echo "RANLIB= $(RANLIB)" + @echo "RM= $(RM)" + +# Convenience targets for popular platforms +ALL= all + +none: + @echo "Please do 'make PLATFORM' where PLATFORM is one of these:" + @echo " $(PLATS)" + +aix: + $(MAKE) $(ALL) CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" SYSLDFLAGS="-brtl -bexpall" + +ansi: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_ANSI" + +bsd: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-Wl,-E" + +freebsd: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -lreadline" + +generic: $(ALL) + +linux: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_LINUX" SYSLIBS="-Wl,-E -ldl -lreadline" + +macosx: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_MACOSX" SYSLIBS="-lreadline" CC=cc + +mingw: + $(MAKE) "LUA_A=lua52.dll" "LUA_T=lua.exe" \ + "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ + "SYSCFLAGS=-DLUA_BUILD_AS_DLL" "SYSLIBS=" "SYSLDFLAGS=-s" lua.exe + $(MAKE) "LUAC_T=luac.exe" luac.exe + +posix: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX" + +solaris: + $(MAKE) $(ALL) SYSCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" SYSLIBS="-ldl" + +# list targets that do not create files (but not all makes understand .PHONY) +.PHONY: all $(PLATS) default o a clean depend echo none + +# DO NOT DELETE + +lapi.o: lapi.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h ltm.h \ + lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lstring.h ltable.h lundump.h \ + lvm.h +lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h +lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h +lbitlib.o: lbitlib.c lua.h luaconf.h lauxlib.h lualib.h +lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ + lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \ + lstring.h ltable.h lvm.h +lcorolib.o: lcorolib.c lua.h luaconf.h lauxlib.h lualib.h +lctype.o: lctype.c lctype.h lua.h luaconf.h llimits.h +ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h +ldebug.o: ldebug.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h \ + ltm.h lzio.h lmem.h lcode.h llex.h lopcodes.h lparser.h ldebug.h ldo.h \ + lfunc.h lstring.h lgc.h ltable.h lvm.h +ldo.o: ldo.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h ltm.h \ + lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h \ + lstring.h ltable.h lundump.h lvm.h +ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \ + lzio.h lmem.h lundump.h +lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h \ + lstate.h ltm.h lzio.h lmem.h +lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h +linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h +liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h +llex.o: llex.c lua.h luaconf.h lctype.h llimits.h ldo.h lobject.h \ + lstate.h ltm.h lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h +lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h +lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h lgc.h +loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h +lobject.o: lobject.c lua.h luaconf.h lctype.h llimits.h ldebug.h lstate.h \ + lobject.h ltm.h lzio.h lmem.h ldo.h lstring.h lgc.h lvm.h +lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h +loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h +lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ + lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lfunc.h \ + lstring.h lgc.h ltable.h +lstate.o: lstate.c lua.h luaconf.h lapi.h llimits.h lstate.h lobject.h \ + ltm.h lzio.h lmem.h ldebug.h ldo.h lfunc.h lgc.h llex.h lstring.h \ + ltable.h +lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \ + ltm.h lzio.h lstring.h lgc.h +lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h +ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h lgc.h lstring.h ltable.h lvm.h +ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h +ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \ + lmem.h lstring.h lgc.h ltable.h +lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h +luac.o: luac.c lua.h luaconf.h lauxlib.h lobject.h llimits.h lstate.h \ + ltm.h lzio.h lmem.h lundump.h ldebug.h lopcodes.h +lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h +lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h +lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \ + lzio.h + diff --git a/lua/lapi.c b/lua/lapi.c new file mode 100644 index 0000000..d011431 --- /dev/null +++ b/lua/lapi.c @@ -0,0 +1,1284 @@ +/* +** $Id: lapi.c,v 2.171.1.1 2013/04/12 18:48:47 roberto Exp $ +** Lua API +** See Copyright Notice in lua.h +*/ + + +#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[] = + "$LuaVersion: " LUA_COPYRIGHT " $" + "$LuaAuthors: " LUA_AUTHORS " $"; + + +/* value at a non-valid index */ +#define NONVALIDVALUE cast(TValue *, luaO_nilobject) + +/* corresponding test */ +#define isvalid(o) ((o) != luaO_nilobject) + +/* test for pseudo index */ +#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) + +/* test for valid but not pseudo index */ +#define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) + +#define api_checkvalidindex(L, o) api_check(L, isvalid(o), "invalid index") + +#define api_checkstackindex(L, i, o) \ + api_check(L, isstackindex(i, o), "index not in the stack") + + +static TValue *index2addr (lua_State *L, int idx) { + CallInfo *ci = L->ci; + if (idx > 0) { + TValue *o = ci->func + idx; + api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); + if (o >= L->top) return NONVALIDVALUE; + else return o; + } + else if (!ispseudo(idx)) { /* negative index */ + api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + return L->top + idx; + } + else if (idx == LUA_REGISTRYINDEX) + return &G(L)->l_registry; + else { /* upvalues */ + idx = LUA_REGISTRYINDEX - idx; + api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); + if (ttislcf(ci->func)) /* light C function? */ + return NONVALIDVALUE; /* it has no upvalues */ + else { + CClosure *func = clCvalue(ci->func); + return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; + } + } +} + + +/* +** to be called by 'lua_checkstack' in protected mode, to grow stack +** capturing memory errors +*/ +static void growstack (lua_State *L, void *ud) { + int size = *(int *)ud; + luaD_growstack(L, size); +} + + +LUA_API int lua_checkstack (lua_State *L, int size) { + int res; + CallInfo *ci = L->ci; + lua_lock(L); + if (L->stack_last - L->top > size) /* stack large enough? */ + res = 1; /* yes; check is OK */ + else { /* no; need to grow stack */ + int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; + if (inuse > LUAI_MAXSTACK - size) /* can grow without overflow? */ + res = 0; /* no */ + else /* try to grow stack */ + res = (luaD_rawrunprotected(L, &growstack, &size) == LUA_OK); + } + if (res && ci->top < L->top + size) + ci->top = L->top + size; /* adjust frame top */ + 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), "moving among independent states"); + api_check(from, to->ci->top - to->top >= n, "not enough elements to move"); + from->top -= n; + for (i = 0; i < n; i++) { + setobj2s(to, to->top++, from->top + i); + } + lua_unlock(to); +} + + +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 const lua_Number *lua_version (lua_State *L) { + static const lua_Number version = LUA_VERSION_NUM; + if (L == NULL) return &version; + else return G(L)->version; +} + + + +/* +** basic stack manipulation +*/ + + +/* +** convert an acceptable stack index into an absolute index +*/ +LUA_API int lua_absindex (lua_State *L, int idx) { + return (idx > 0 || ispseudo(idx)) + ? idx + : cast_int(L->top - L->ci->func + idx); +} + + +LUA_API int lua_gettop (lua_State *L) { + return cast_int(L->top - (L->ci->func + 1)); +} + + +LUA_API void lua_settop (lua_State *L, int idx) { + StkId func = L->ci->func; + lua_lock(L); + if (idx >= 0) { + api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); + while (L->top < (func + 1) + idx) + setnilvalue(L->top++); + L->top = (func + 1) + idx; + } + else { + api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); + 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 = index2addr(L, idx); + api_checkstackindex(L, idx, 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 = index2addr(L, idx); + api_checkstackindex(L, idx, p); + for (q = L->top; q > p; q--) /* use L->top as a temporary */ + setobjs2s(L, q, q - 1); + setobjs2s(L, p, L->top); + lua_unlock(L); +} + + +static void moveto (lua_State *L, TValue *fr, int idx) { + TValue *to = index2addr(L, idx); + api_checkvalidindex(L, to); + setobj(L, to, fr); + if (idx < LUA_REGISTRYINDEX) /* function upvalue? */ + luaC_barrier(L, clCvalue(L->ci->func), fr); + /* LUA_REGISTRYINDEX does not need gc barrier + (collector revisits it before finishing collection) */ +} + + +LUA_API void lua_replace (lua_State *L, int idx) { + lua_lock(L); + api_checknelems(L, 1); + moveto(L, L->top - 1, idx); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { + TValue *fr; + lua_lock(L); + fr = index2addr(L, fromidx); + moveto(L, fr, toidx); + lua_unlock(L); +} + + +LUA_API void lua_pushvalue (lua_State *L, int idx) { + lua_lock(L); + setobj2s(L, L->top, index2addr(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 = index2addr(L, idx); + return (isvalid(o) ? ttypenv(o) : LUA_TNONE); +} + + +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + return ttypename(t); +} + + +LUA_API int lua_iscfunction (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + return (ttislcf(o) || (ttisCclosure(o))); +} + + +LUA_API int lua_isnumber (lua_State *L, int idx) { + TValue n; + const TValue *o = index2addr(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 = index2addr(L, idx); + return (ttisuserdata(o) || ttislightuserdata(o)); +} + + +LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { + StkId o1 = index2addr(L, index1); + StkId o2 = index2addr(L, index2); + return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; +} + + +LUA_API void lua_arith (lua_State *L, int op) { + StkId o1; /* 1st operand */ + StkId o2; /* 2nd operand */ + lua_lock(L); + if (op != LUA_OPUNM) /* all other operations expect two operands */ + api_checknelems(L, 2); + else { /* for unary minus, add fake 2nd operand */ + api_checknelems(L, 1); + setobjs2s(L, L->top, L->top - 1); + L->top++; + } + o1 = L->top - 2; + o2 = L->top - 1; + if (ttisnumber(o1) && ttisnumber(o2)) { + setnvalue(o1, luaO_arith(op, nvalue(o1), nvalue(o2))); + } + else + luaV_arith(L, o1, o1, o2, cast(TMS, op - LUA_OPADD + TM_ADD)); + L->top--; + lua_unlock(L); +} + + +LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { + StkId o1, o2; + int i = 0; + lua_lock(L); /* may call tag method */ + o1 = index2addr(L, index1); + o2 = index2addr(L, index2); + if (isvalid(o1) && isvalid(o2)) { + switch (op) { + case LUA_OPEQ: i = equalobj(L, o1, o2); break; + case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; + case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; + default: api_check(L, 0, "invalid option"); + } + } + lua_unlock(L); + return i; +} + + +LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *isnum) { + TValue n; + const TValue *o = index2addr(L, idx); + if (tonumber(o, &n)) { + if (isnum) *isnum = 1; + return nvalue(o); + } + else { + if (isnum) *isnum = 0; + return 0; + } +} + + +LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *isnum) { + TValue n; + const TValue *o = index2addr(L, idx); + if (tonumber(o, &n)) { + lua_Integer res; + lua_Number num = nvalue(o); + lua_number2integer(res, num); + if (isnum) *isnum = 1; + return res; + } + else { + if (isnum) *isnum = 0; + return 0; + } +} + + +LUA_API lua_Unsigned lua_tounsignedx (lua_State *L, int idx, int *isnum) { + TValue n; + const TValue *o = index2addr(L, idx); + if (tonumber(o, &n)) { + lua_Unsigned res; + lua_Number num = nvalue(o); + lua_number2unsigned(res, num); + if (isnum) *isnum = 1; + return res; + } + else { + if (isnum) *isnum = 0; + return 0; + } +} + + +LUA_API int lua_toboolean (lua_State *L, int idx) { + const TValue *o = index2addr(L, idx); + return !l_isfalse(o); +} + + +LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { + StkId o = index2addr(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 = index2addr(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_rawlen (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + switch (ttypenv(o)) { + case LUA_TSTRING: return tsvalue(o)->len; + case LUA_TUSERDATA: return uvalue(o)->len; + case LUA_TTABLE: return luaH_getn(hvalue(o)); + default: return 0; + } +} + + +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + if (ttislcf(o)) return fvalue(o); + else if (ttisCclosure(o)) + return clCvalue(o)->f; + else return NULL; /* not a C function */ +} + + +LUA_API void *lua_touserdata (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + switch (ttypenv(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 = index2addr(L, idx); + return (!ttisthread(o)) ? NULL : thvalue(o); +} + + +LUA_API const void *lua_topointer (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + switch (ttype(o)) { + case LUA_TTABLE: return hvalue(o); + case LUA_TLCL: return clLvalue(o); + case LUA_TCCL: return clCvalue(o); + case LUA_TLCF: return cast(void *, cast(size_t, fvalue(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); + luai_checknum(L, L->top, + luaG_runerror(L, "C API - attempt to push a signaling NaN")); + 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_pushunsigned (lua_State *L, lua_Unsigned u) { + lua_Number n; + lua_lock(L); + n = lua_unsigned2number(u); + setnvalue(L->top, n); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { + TString *ts; + lua_lock(L); + luaC_checkGC(L); + ts = luaS_newlstr(L, s, len); + setsvalue2s(L, L->top, ts); + api_incr_top(L); + lua_unlock(L); + return getstr(ts); +} + + +LUA_API const char *lua_pushstring (lua_State *L, const char *s) { + if (s == NULL) { + lua_pushnil(L); + return NULL; + } + else { + TString *ts; + lua_lock(L); + luaC_checkGC(L); + ts = luaS_new(L, s); + setsvalue2s(L, L->top, ts); + api_incr_top(L); + lua_unlock(L); + return getstr(ts); + } +} + + +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) { + lua_lock(L); + if (n == 0) { + setfvalue(L->top, fn); + } + else { + Closure *cl; + api_checknelems(L, n); + api_check(L, n <= MAXUPVAL, "upvalue index too large"); + luaC_checkGC(L); + cl = luaF_newCclosure(L, n); + cl->c.f = fn; + L->top -= n; + while (n--) + setobj2n(L, &cl->c.upvalue[n], L->top + n); + setclCvalue(L, L->top, 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_getglobal (lua_State *L, const char *var) { + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt; /* global table */ + lua_lock(L); + gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + setsvalue2s(L, L->top++, luaS_new(L, var)); + luaV_gettable(L, gt, L->top - 1, L->top - 1); + lua_unlock(L); +} + + +LUA_API void lua_gettable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + 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; + lua_lock(L); + t = index2addr(L, idx); + setsvalue2s(L, L->top, luaS_new(L, k)); + api_incr_top(L); + luaV_gettable(L, t, L->top - 1, L->top - 1); + lua_unlock(L); +} + + +LUA_API void lua_rawget (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + 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 t; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2s(L, L->top, luaH_getint(hvalue(t), n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_rawgetp (lua_State *L, int idx, const void *p) { + StkId t; + TValue k; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setpvalue(&k, cast(void *, p)); + setobj2s(L, L->top, luaH_get(hvalue(t), &k)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { + Table *t; + lua_lock(L); + luaC_checkGC(L); + t = luaH_new(L); + sethvalue(L, L->top, t); + api_incr_top(L); + if (narray > 0 || nrec > 0) + luaH_resize(L, t, narray, nrec); + 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 = index2addr(L, objindex); + switch (ttypenv(obj)) { + case LUA_TTABLE: + mt = hvalue(obj)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(obj)->metatable; + break; + default: + mt = G(L)->mt[ttypenv(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_getuservalue (lua_State *L, int idx) { + StkId o; + lua_lock(L); + o = index2addr(L, idx); + api_check(L, ttisuserdata(o), "userdata expected"); + if (uvalue(o)->env) { + sethvalue(L, L->top, uvalue(o)->env); + } else + setnilvalue(L->top); + api_incr_top(L); + lua_unlock(L); +} + + +/* +** set functions (stack -> Lua) +*/ + + +LUA_API void lua_setglobal (lua_State *L, const char *var) { + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt; /* global table */ + lua_lock(L); + api_checknelems(L, 1); + gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + setsvalue2s(L, L->top++, luaS_new(L, var)); + luaV_settable(L, gt, L->top - 1, L->top - 2); + L->top -= 2; /* pop value and key */ + lua_unlock(L); +} + + +LUA_API void lua_settable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2addr(L, idx); + 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; + lua_lock(L); + api_checknelems(L, 1); + t = index2addr(L, idx); + setsvalue2s(L, L->top++, luaS_new(L, k)); + luaV_settable(L, t, L->top - 1, L->top - 2); + L->top -= 2; /* pop value and key */ + lua_unlock(L); +} + + +LUA_API void lua_rawset (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); + invalidateTMcache(hvalue(t)); + luaC_barrierback(L, gcvalue(t), L->top-1); + L->top -= 2; + lua_unlock(L); +} + + +LUA_API void lua_rawseti (lua_State *L, int idx, int n) { + StkId t; + lua_lock(L); + api_checknelems(L, 1); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + luaH_setint(L, hvalue(t), n, L->top - 1); + luaC_barrierback(L, gcvalue(t), L->top-1); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { + StkId t; + TValue k; + lua_lock(L); + api_checknelems(L, 1); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setpvalue(&k, cast(void *, p)); + setobj2t(L, luaH_set(L, hvalue(t), &k), L->top - 1); + luaC_barrierback(L, gcvalue(t), 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 = index2addr(L, objindex); + if (ttisnil(L->top - 1)) + mt = NULL; + else { + api_check(L, ttistable(L->top - 1), "table expected"); + mt = hvalue(L->top - 1); + } + switch (ttypenv(obj)) { + case LUA_TTABLE: { + hvalue(obj)->metatable = mt; + if (mt) { + luaC_objbarrierback(L, gcvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } + break; + } + case LUA_TUSERDATA: { + uvalue(obj)->metatable = mt; + if (mt) { + luaC_objbarrier(L, rawuvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } + break; + } + default: { + G(L)->mt[ttypenv(obj)] = mt; + break; + } + } + L->top--; + lua_unlock(L); + return 1; +} + + +LUA_API void lua_setuservalue (lua_State *L, int idx) { + StkId o; + lua_lock(L); + api_checknelems(L, 1); + o = index2addr(L, idx); + api_check(L, ttisuserdata(o), "userdata expected"); + if (ttisnil(L->top - 1)) + uvalue(o)->env = NULL; + else { + api_check(L, ttistable(L->top - 1), "table expected"); + uvalue(o)->env = hvalue(L->top - 1); + luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); + } + L->top--; + lua_unlock(L); +} + + +/* +** `load' and `call' functions (run Lua code) +*/ + + +#define checkresults(L,na,nr) \ + api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ + "results from function overflow current stack size") + + +LUA_API int lua_getctx (lua_State *L, int *ctx) { + if (L->ci->callstatus & CIST_YIELDED) { + if (ctx) *ctx = L->ci->u.c.ctx; + return L->ci->u.c.status; + } + else return LUA_OK; +} + + +LUA_API void lua_callk (lua_State *L, int nargs, int nresults, int ctx, + lua_CFunction k) { + StkId func; + lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); + api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); + func = L->top - (nargs+1); + if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ + L->ci->u.c.k = k; /* save continuation */ + L->ci->u.c.ctx = ctx; /* save context */ + luaD_call(L, func, nresults, 1); /* do the call */ + } + else /* no continuation or no yieldable */ + luaD_call(L, func, nresults, 0); /* just do the call */ + 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, 0); +} + + + +LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, + int ctx, lua_CFunction k) { + struct CallS c; + int status; + ptrdiff_t func; + lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); + api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); + if (errfunc == 0) + func = 0; + else { + StkId o = index2addr(L, errfunc); + api_checkstackindex(L, errfunc, o); + func = savestack(L, o); + } + c.func = L->top - (nargs+1); /* function to be called */ + if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ + c.nresults = nresults; /* do a 'conventional' protected call */ + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + } + else { /* prepare continuation (call is already protected by 'resume') */ + CallInfo *ci = L->ci; + ci->u.c.k = k; /* save continuation */ + ci->u.c.ctx = ctx; /* save context */ + /* save information for error recovery */ + ci->extra = savestack(L, c.func); + ci->u.c.old_allowhook = L->allowhook; + ci->u.c.old_errfunc = L->errfunc; + L->errfunc = func; + /* mark that function may do error recovery */ + ci->callstatus |= CIST_YPCALL; + luaD_call(L, c.func, nresults, 1); /* do the call */ + ci->callstatus &= ~CIST_YPCALL; + L->errfunc = ci->u.c.old_errfunc; + status = LUA_OK; /* if it is here, there were no errors */ + } + adjustresults(L, nresults); + lua_unlock(L); + return status; +} + + +LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, + const char *chunkname, const char *mode) { + ZIO z; + int status; + lua_lock(L); + if (!chunkname) chunkname = "?"; + luaZ_init(L, &z, reader, data); + status = luaD_protectedparser(L, &z, chunkname, mode); + if (status == LUA_OK) { /* no errors? */ + LClosure *f = clLvalue(L->top - 1); /* get newly created function */ + if (f->nupvalues == 1) { /* does it have one upvalue? */ + /* get global table from registry */ + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ + setobj(L, f->upvals[0]->v, gt); + luaC_barrier(L, f->upvals[0], gt); + } + } + 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, getproto(o), 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->gcrunning = 0; + break; + } + case LUA_GCRESTART: { + luaE_setdebt(g, 0); + g->gcrunning = 1; + break; + } + case LUA_GCCOLLECT: { + luaC_fullgc(L, 0); + break; + } + case LUA_GCCOUNT: { + /* GC values are expressed in Kbytes: #bytes/2^10 */ + res = cast_int(gettotalbytes(g) >> 10); + break; + } + case LUA_GCCOUNTB: { + res = cast_int(gettotalbytes(g) & 0x3ff); + break; + } + case LUA_GCSTEP: { + if (g->gckind == KGC_GEN) { /* generational mode? */ + res = (g->GCestimate == 0); /* true if it will do major collection */ + luaC_forcestep(L); /* do a single step */ + } + else { + lu_mem debt = cast(lu_mem, data) * 1024 - GCSTEPSIZE; + if (g->gcrunning) + debt += g->GCdebt; /* include current debt */ + luaE_setdebt(g, debt); + luaC_forcestep(L); + if (g->gcstate == GCSpause) /* end of cycle? */ + res = 1; /* signal it */ + } + break; + } + case LUA_GCSETPAUSE: { + res = g->gcpause; + g->gcpause = data; + break; + } + case LUA_GCSETMAJORINC: { + res = g->gcmajorinc; + g->gcmajorinc = data; + break; + } + case LUA_GCSETSTEPMUL: { + res = g->gcstepmul; + g->gcstepmul = data; + break; + } + case LUA_GCISRUNNING: { + res = g->gcrunning; + break; + } + case LUA_GCGEN: { /* change collector to generational mode */ + luaC_changemode(L, KGC_GEN); + break; + } + case LUA_GCINC: { /* change collector to incremental mode */ + luaC_changemode(L, KGC_NORMAL); + 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); + /* code unreachable; will unlock when control actually leaves the kernel */ + return 0; /* to avoid warnings */ +} + + +LUA_API int lua_next (lua_State *L, int idx) { + StkId t; + int more; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + 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); + } + 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 void lua_len (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + luaV_objlen(L, L->top, t); + api_incr_top(L); + 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, NULL); + 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, + GCObject **owner) { + switch (ttype(fi)) { + case LUA_TCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + if (!(1 <= n && n <= f->nupvalues)) return NULL; + *val = &f->upvalue[n-1]; + if (owner) *owner = obj2gco(f); + return ""; + } + case LUA_TLCL: { /* Lua closure */ + LClosure *f = clLvalue(fi); + TString *name; + Proto *p = f->p; + if (!(1 <= n && n <= p->sizeupvalues)) return NULL; + *val = f->upvals[n-1]->v; + if (owner) *owner = obj2gco(f->upvals[n - 1]); + name = p->upvalues[n-1].name; + return (name == NULL) ? "" : getstr(name); + } + default: return NULL; /* not a closure */ + } +} + + +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val = NULL; /* to avoid warnings */ + lua_lock(L); + name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL); + 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 = NULL; /* to avoid warnings */ + GCObject *owner = NULL; /* to avoid warnings */ + StkId fi; + lua_lock(L); + fi = index2addr(L, funcindex); + api_checknelems(L, 1); + name = aux_upvalue(fi, n, &val, &owner); + if (name) { + L->top--; + setobj(L, val, L->top); + luaC_barrier(L, owner, L->top); + } + lua_unlock(L); + return name; +} + + +static UpVal **getupvalref (lua_State *L, int fidx, int n, LClosure **pf) { + LClosure *f; + StkId fi = index2addr(L, fidx); + api_check(L, ttisLclosure(fi), "Lua function expected"); + f = clLvalue(fi); + api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); + if (pf) *pf = f; + return &f->upvals[n - 1]; /* get its upvalue pointer */ +} + + +LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { + StkId fi = index2addr(L, fidx); + switch (ttype(fi)) { + case LUA_TLCL: { /* lua closure */ + return *getupvalref(L, fidx, n, NULL); + } + case LUA_TCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); + return &f->upvalue[n - 1]; + } + default: { + api_check(L, 0, "closure expected"); + return NULL; + } + } +} + + +LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, + int fidx2, int n2) { + LClosure *f1; + UpVal **up1 = getupvalref(L, fidx1, n1, &f1); + UpVal **up2 = getupvalref(L, fidx2, n2, NULL); + *up1 = *up2; + luaC_objbarrier(L, f1, *up2); +} + diff --git a/lua/lapi.h b/lua/lapi.h new file mode 100644 index 0000000..c7d34ad --- /dev/null +++ b/lua/lapi.h @@ -0,0 +1,24 @@ +/* +** $Id: lapi.h,v 2.7.1.1 2013/04/12 18:48:47 roberto Exp $ +** Auxiliary functions from Lua API +** See Copyright Notice in lua.h +*/ + +#ifndef lapi_h +#define lapi_h + + +#include "llimits.h" +#include "lstate.h" + +#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ + "stack overflow");} + +#define adjustresults(L,nres) \ + { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } + +#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ + "not enough elements in the stack") + + +#endif diff --git a/lua/lauxlib.c b/lua/lauxlib.c new file mode 100644 index 0000000..b00f8c7 --- /dev/null +++ b/lua/lauxlib.c @@ -0,0 +1,959 @@ +/* +** $Id: lauxlib.c,v 1.248.1.1 2013/04/12 18:48:47 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#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" + + +/* +** {====================================================== +** Traceback +** ======================================================= +*/ + + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + + + +/* +** search for 'objidx' in table at index -1. +** return 1 + string at top if find a good name. +*/ +static int findfield (lua_State *L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + + +static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_pushglobaltable(L); + if (findfield(L, top + 1, 2)) { + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + + +static void pushfuncname (lua_State *L, lua_Debug *ar) { + if (*ar->namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, "function " LUA_QS, ar->name); + else if (*ar->what == 'm') /* main? */ + lua_pushliteral(L, "main chunk"); + else if (*ar->what == 'C') { + if (pushglobalfuncname(L, ar)) { + lua_pushfstring(L, "function " LUA_QS, lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else + lua_pushliteral(L, "?"); + } + else + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); +} + + +static int countlevels (lua_State *L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } + /* do a binary search */ + while (li < le) { + int m = (li + le)/2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; +} + + +LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, + const char *msg, int level) { + lua_Debug ar; + int top = lua_gettop(L); + int numlevels = countlevels(L1); + int mark = (numlevels > LEVELS1 + LEVELS2) ? LEVELS1 : 0; + if (msg) lua_pushfstring(L, "%s\n", msg); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level == mark) { /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = numlevels - LEVELS2; /* and skip to last ones */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + pushfuncname(L, &ar); + if (ar.istailcall) + lua_pushliteral(L, "\n\t(...tail calls...)"); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** 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 = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; + return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", + narg, ar.name, extramsg); +} + + +static int typeerror (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) { + typeerror(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_fileresult (lua_State *L, int stat, const char *fname) { + int en = errno; /* calls to Lua API may change this value */ + if (stat) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (fname) + lua_pushfstring(L, "%s: %s", fname, strerror(en)); + else + lua_pushstring(L, strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +#if !defined(inspectstat) /* { */ + +#if defined(LUA_USE_POSIX) + +#include + +/* +** use appropriate macros to interpret 'pclose' return status +*/ +#define inspectstat(stat,what) \ + if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ + else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } + +#else + +#define inspectstat(stat,what) /* no op */ + +#endif + +#endif /* } */ + + +LUALIB_API int luaL_execresult (lua_State *L, int stat) { + const char *what = "exit"; /* type of termination */ + if (stat == -1) /* error? */ + return luaL_fileresult(L, 0, NULL); + else { + inspectstat(stat, what); /* interpret result */ + if (*what == 'e' && stat == 0) /* successful termination? */ + lua_pushboolean(L, 1); + else + lua_pushnil(L); + lua_pushstring(L, what); + lua_pushinteger(L, stat); + return 3; /* return true/nil,what,code */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Userdata's metatable manipulation +** ======================================================= +*/ + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + luaL_getmetatable(L, tname); /* try to get metatable */ + 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_setmetatable (lua_State *L, const char *tname) { + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + + +LUALIB_API void *luaL_testudata (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? */ + luaL_getmetatable(L, tname); /* get correct metatable */ + if (!lua_rawequal(L, -1, -2)) /* not the same? */ + p = NULL; /* value is a userdata with wrong metatable */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + return NULL; /* value is not a userdata with a metatable */ +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + void *p = luaL_testudata(L, ud, tname); + if (p == NULL) typeerror(L, ud, tname); + return p; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Argument check functions +** ======================================================= +*/ + +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 void luaL_checkstack (lua_State *L, int space, const char *msg) { + /* keep some extra space to run error routines, if needed */ + const int extra = LUA_MINSTACK; + if (!lua_checkstack(L, space + extra)) { + if (msg) + luaL_error(L, "stack overflow (%s)", msg); + else + luaL_error(L, "stack overflow"); + } +} + + +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) { + int isnum; + lua_Number d = lua_tonumberx(L, narg, &isnum); + if (!isnum) + 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) { + int isnum; + lua_Integer d = lua_tointegerx(L, narg, &isnum); + if (!isnum) + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Unsigned luaL_checkunsigned (lua_State *L, int narg) { + int isnum; + lua_Unsigned d = lua_tounsignedx(L, narg, &isnum); + if (!isnum) + 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 lua_Unsigned luaL_optunsigned (lua_State *L, int narg, + lua_Unsigned def) { + return luaL_opt(L, luaL_checkunsigned, narg, def); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +/* +** check whether buffer is using a userdata on the stack as a temporary +** buffer +*/ +#define buffonstack(B) ((B)->b != (B)->initb) + + +/* +** returns a pointer to a free area with at least 'sz' bytes +*/ +LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { + lua_State *L = B->L; + if (B->size - B->n < sz) { /* not enough space? */ + char *newbuff; + size_t newsize = B->size * 2; /* double buffer size */ + if (newsize - B->n < sz) /* not big enough? */ + newsize = B->n + sz; + if (newsize < B->n || newsize - B->n < sz) + luaL_error(L, "buffer too large"); + /* create larger buffer */ + newbuff = (char *)lua_newuserdata(L, newsize * sizeof(char)); + /* move content to new buffer */ + memcpy(newbuff, B->b, B->n * sizeof(char)); + if (buffonstack(B)) + lua_remove(L, -2); /* remove old buffer */ + B->b = newbuff; + B->size = newsize; + } + return &B->b[B->n]; +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + char *b = luaL_prepbuffsize(B, l); + memcpy(b, s, l * sizeof(char)); + luaL_addsize(B, l); +} + + +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) { + lua_State *L = B->L; + lua_pushlstring(L, B->b, B->n); + if (buffonstack(B)) + lua_remove(L, -2); /* remove old buffer */ +} + + +LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { + luaL_addsize(B, sz); + luaL_pushresult(B); +} + + +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t l; + const char *s = lua_tolstring(L, -1, &l); + if (buffonstack(B)) + lua_insert(L, -2); /* put value below buffer */ + luaL_addlstring(B, s, l); + lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->b = B->initb; + B->n = 0; + B->size = LUAL_BUFFERSIZE; +} + + +LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { + luaL_buffinit(L, B); + return luaL_prepbuffsize(B, sz); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Reference system +** ======================================================= +*/ + +/* index of free-list header */ +#define freelist 0 + + +LUALIB_API int luaL_ref (lua_State *L, int t) { + int ref; + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* remove from stack */ + return LUA_REFNIL; /* `nil' has a unique fixed reference */ + } + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); /* get first free element */ + ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ + 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); /* (t[freelist] = t[ref]) */ + } + else /* no free elements */ + ref = (int)lua_rawlen(L, t) + 1; /* get a 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 = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); + lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ + lua_pushinteger(L, ref); + lua_rawseti(L, t, freelist); /* t[freelist] = ref */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + int n; /* number of pre-read characters */ + FILE *f; /* file being read */ + char buff[LUAL_BUFFERSIZE]; /* area for reading file */ +} LoadF; + + +static const char *getF (lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; /* not used */ + if (lf->n > 0) { /* are there pre-read characters to be read? */ + *size = lf->n; /* return them (chars already in buffer) */ + lf->n = 0; /* no more pre-read characters */ + } + else { /* read a block from file */ + /* 'fread' can return > 0 *and* set the EOF flag. If next call to + 'getF' called 'fread', it might still wait for user input. + The next check avoids this problem. */ + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ + } + return lf->buff; +} + + +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; +} + + +static int skipBOM (LoadF *lf) { + const char *p = "\xEF\xBB\xBF"; /* Utf8 BOM mark */ + int c; + lf->n = 0; + do { + c = getc(lf->f); + if (c == EOF || c != *(const unsigned char *)p++) return c; + lf->buff[lf->n++] = c; /* to be read by the parser */ + } while (*p != '\0'); + lf->n = 0; /* prefix matched; discard it */ + return getc(lf->f); /* return next character */ +} + + +/* +** reads the first character of file 'f' and skips an optional BOM mark +** in its beginning plus its first line if it starts with '#'. Returns +** true if it skipped the first line. In any case, '*cp' has the +** first "valid" character of the file (after the optional BOM and +** a first-line comment). +*/ +static int skipcomment (LoadF *lf, int *cp) { + int c = *cp = skipBOM(lf); + if (c == '#') { /* first line is a comment (Unix exec. file)? */ + do { /* skip first line */ + c = getc(lf->f); + } while (c != EOF && c != '\n') ; + *cp = getc(lf->f); /* skip end-of-line, if present */ + return 1; /* there was a comment */ + } + else return 0; /* no comment */ +} + + +LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, + const char *mode) { + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + 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); + } + if (skipcomment(&lf, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ + 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); + skipcomment(&lf, &c); /* re-read initial portion */ + } + if (c != EOF) + lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ + status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); + 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; /* not used */ + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, + const char *name, const char *mode) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name, mode); +} + + +LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { + return luaL_loadbuffer(L, s, strlen(s), s); +} + +/* }====================================================== */ + + + +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 = lua_absindex(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 int luaL_len (lua_State *L, int idx) { + int l; + int isnum; + lua_len(L, idx); + l = (int)lua_tointegerx(L, -1, &isnum); + if (!isnum) + luaL_error(L, "object length is not a number"); + lua_pop(L, 1); /* remove object */ + return l; +} + + +LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { + if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */ + switch (lua_type(L, idx)) { + case LUA_TNUMBER: + case LUA_TSTRING: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: + lua_pushfstring(L, "%s: %p", luaL_typename(L, idx), + lua_topointer(L, idx)); + break; + } + } + return lua_tolstring(L, -1, len); +} + + +/* +** {====================================================== +** Compatibility with 5.1 module functions +** ======================================================= +*/ +#if defined(LUA_COMPAT_MODULE) + +static const char *luaL_findtable (lua_State *L, int idx, + const char *fname, int szhint) { + const char *e; + if (idx) 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; +} + + +/* +** Count number of elements in a luaL_Reg list. +*/ +static int libsize (const luaL_Reg *l) { + int size = 0; + for (; l && l->name; l++) size++; + return size; +} + + +/* +** Find or create a module table with a given name. The function +** first looks at the _LOADED table and, if that fails, try a +** global variable with that name. In any case, leaves on the stack +** the module table. +*/ +LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, + int sizehint) { + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); /* get _LOADED table */ + lua_getfield(L, -1, 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) */ + lua_pushglobaltable(L); + if (luaL_findtable(L, 0, modname, sizehint) != NULL) + luaL_error(L, "name conflict for module " LUA_QS, modname); + lua_pushvalue(L, -1); + lua_setfield(L, -3, modname); /* _LOADED[modname] = new table */ + } + lua_remove(L, -2); /* remove _LOADED table */ +} + + +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, + const luaL_Reg *l, int nup) { + luaL_checkversion(L); + if (libname) { + luaL_pushmodule(L, libname, libsize(l)); /* get/create library table */ + lua_insert(L, -(nup + 1)); /* move library table to below upvalues */ + } + if (l) + luaL_setfuncs(L, l, nup); + else + lua_pop(L, nup); /* remove upvalues */ +} + +#endif +/* }====================================================== */ + +/* +** set functions from list 'l' into table at top - 'nup'; each +** function gets the 'nup' elements at the top as upvalues. +** Returns with only the table at the stack. +*/ +LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkversion(L); + luaL_checkstack(L, nup, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -nup); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_setfield(L, -(nup + 2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + + +/* +** ensure that stack[idx][fname] has a table and push that table +** into the stack +*/ +LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { + lua_getfield(L, idx, fname); + if (lua_istable(L, -1)) return 1; /* table already there */ + else { + lua_pop(L, 1); /* remove previous result */ + idx = lua_absindex(L, idx); + lua_newtable(L); + lua_pushvalue(L, -1); /* copy to be left at top */ + lua_setfield(L, idx, fname); /* assign new table to field */ + return 0; /* false, because did not find table there */ + } +} + + +/* +** stripped-down 'require'. Calls 'openf' to open a module, +** registers the result in 'package.loaded' table and, if 'glb' +** is true, also registers the result in the global table. +** Leaves resulting module on the top. +*/ +LUALIB_API void luaL_requiref (lua_State *L, const char *modname, + lua_CFunction openf, int glb) { + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); /* argument to open function */ + lua_call(L, 1, 1); /* open module */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_pushvalue(L, -2); /* make copy of module (call result) */ + lua_setfield(L, -2, modname); /* _LOADED[modname] = module */ + lua_pop(L, 1); /* remove _LOADED table */ + if (glb) { + lua_pushvalue(L, -1); /* copy of 'mod' */ + lua_setglobal(L, modname); /* _G[modname] = module */ + } +} + + +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); +} + + +static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { + (void)ud; (void)osize; /* not used */ + if (nsize == 0) { + free(ptr); + return NULL; + } + else + return realloc(ptr, nsize); +} + + +static int panic (lua_State *L) { + luai_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; /* return to Lua to abort */ +} + + +LUALIB_API lua_State *luaL_newstate (void) { + lua_State *L = lua_newstate(l_alloc, NULL); + if (L) lua_atpanic(L, &panic); + return L; +} + + +LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver) { + const lua_Number *v = lua_version(L); + if (v != lua_version(NULL)) + luaL_error(L, "multiple Lua VMs detected"); + else if (*v != ver) + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", + ver, *v); + /* check conversions number -> integer types */ + lua_pushnumber(L, -(lua_Number)0x1234); + if (lua_tointeger(L, -1) != -0x1234 || + lua_tounsigned(L, -1) != (lua_Unsigned)-0x1234) + luaL_error(L, "bad conversion number->int;" + " must recompile Lua with proper settings"); + lua_pop(L, 1); +} + diff --git a/lua/lauxlib.h b/lua/lauxlib.h new file mode 100644 index 0000000..0fb023b --- /dev/null +++ b/lua/lauxlib.h @@ -0,0 +1,212 @@ +/* +** $Id: lauxlib.h,v 1.120.1.1 2013/04/12 18:48:47 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" + + + +/* 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 (luaL_checkversion_) (lua_State *L, lua_Number ver); +#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) + +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 const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); +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 lua_Unsigned (luaL_checkunsigned) (lua_State *L, int numArg); +LUALIB_API lua_Unsigned (luaL_optunsigned) (lua_State *L, int numArg, + lua_Unsigned 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_setmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, 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_fileresult) (lua_State *L, int stat, const char *fname); +LUALIB_API int (luaL_execresult) (lua_State *L, int stat); + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +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_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + +LUALIB_API int (luaL_len) (lua_State *L, int idx); + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); + +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); + +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); + +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#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))) + +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +typedef struct luaL_Buffer { + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ + lua_State *L; + char initb[LUAL_BUFFERSIZE]; /* initial buffer */ +} luaL_Buffer; + + +#define luaL_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) + +#define luaL_addsize(B,s) ((B)->n += (s)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); +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); +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); +LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); + +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +/* }====================================================== */ + + + +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + + + +/* compatibility with old module system */ +#if defined(LUA_COMPAT_MODULE) + +LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, + int sizehint); +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); + +#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) + +#endif + + +#endif + + diff --git a/lua/lbaselib.c b/lua/lbaselib.c new file mode 100644 index 0000000..5255b3c --- /dev/null +++ b/lua/lbaselib.c @@ -0,0 +1,458 @@ +/* +** $Id: lbaselib.c,v 1.276.1.1 2013/04/12 18:48:47 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" + + +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; + size_t l; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + s = lua_tolstring(L, -1, &l); /* get result */ + if (s == NULL) + return luaL_error(L, + LUA_QL("tostring") " must return a string to " LUA_QL("print")); + if (i>1) luai_writestring("\t", 1); + luai_writestring(s, l); + lua_pop(L, 1); /* pop result */ + } + luai_writeline(); + return 0; +} + + +#define SPACECHARS " \f\n\r\t\v" + +static int luaB_tonumber (lua_State *L) { + if (lua_isnoneornil(L, 2)) { /* standard conversion */ + int isnum; + lua_Number n = lua_tonumberx(L, 1, &isnum); + if (isnum) { + lua_pushnumber(L, n); + return 1; + } /* else not a number; must be something */ + luaL_checkany(L, 1); + } + else { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + const char *e = s + l; /* end point for 's' */ + int base = luaL_checkint(L, 2); + int neg = 0; + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + s += strspn(s, SPACECHARS); /* skip initial spaces */ + if (*s == '-') { s++; neg = 1; } /* handle signal */ + else if (*s == '+') s++; + if (isalnum((unsigned char)*s)) { + lua_Number n = 0; + do { + int digit = (isdigit((unsigned char)*s)) ? *s - '0' + : toupper((unsigned char)*s) - 'A' + 10; + if (digit >= base) break; /* invalid numeral; force a fail */ + n = n * (lua_Number)base + (lua_Number)digit; + s++; + } while (isalnum((unsigned char)*s)); + s += strspn(s, SPACECHARS); /* skip trailing spaces */ + if (s == e) { /* no invalid trailing characters? */ + lua_pushnumber(L, (neg) ? -n : n); + return 1; + } /* else not a number */ + } /* else not a number */ + } + lua_pushnil(L); /* 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")) + return luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + 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_rawlen (lua_State *L) { + int t = lua_type(L, 1); + luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, + "table or string expected"); + lua_pushinteger(L, lua_rawlen(L, 1)); + 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_collectgarbage (lua_State *L) { + static const char *const opts[] = {"stop", "restart", "collect", + "count", "step", "setpause", "setstepmul", + "setmajorinc", "isrunning", "generational", "incremental", NULL}; + static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, + LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; + int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; + int ex = luaL_optint(L, 2, 0); + int res = lua_gc(L, o, ex); + switch (o) { + case LUA_GCCOUNT: { + int b = lua_gc(L, LUA_GCCOUNTB, 0); + lua_pushnumber(L, res + ((lua_Number)b/1024)); + lua_pushinteger(L, b); + return 2; + } + case LUA_GCSTEP: case LUA_GCISRUNNING: { + lua_pushboolean(L, res); + return 1; + } + default: { + lua_pushinteger(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 pairsmeta (lua_State *L, const char *method, int iszero, + lua_CFunction iter) { + if (!luaL_getmetafield(L, 1, method)) { /* no metamethod? */ + luaL_checktype(L, 1, LUA_TTABLE); /* argument must be a table */ + lua_pushcfunction(L, iter); /* will return generator, */ + lua_pushvalue(L, 1); /* state, */ + if (iszero) lua_pushinteger(L, 0); /* and initial value */ + else lua_pushnil(L); + } + else { + lua_pushvalue(L, 1); /* argument 'self' to metamethod */ + lua_call(L, 1, 3); /* get 3 values from metamethod */ + } + return 3; +} + + +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) { + return pairsmeta(L, "__pairs", 0, luaB_next); +} + + +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)) ? 1 : 2; +} + + +static int luaB_ipairs (lua_State *L) { + return pairsmeta(L, "__ipairs", 1, ipairsaux); +} + + +static int load_aux (lua_State *L, int status, int envidx) { + if (status == LUA_OK) { + if (envidx != 0) { /* 'env' parameter? */ + lua_pushvalue(L, envidx); /* environment for loaded function */ + if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ + lua_pop(L, 1); /* remove 'env' if not used by previous call */ + } + return 1; + } + else { /* error (message is on top of the stack) */ + lua_pushnil(L); + lua_insert(L, -2); /* put before error message */ + return 2; /* return nil plus error message */ + } +} + + +static int luaB_loadfile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + const char *mode = luaL_optstring(L, 2, NULL); + int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ + int status = luaL_loadfilex(L, fname, mode); + return load_aux(L, status, env); +} + + +/* +** {====================================================== +** Generic Read function +** ======================================================= +*/ + + +/* +** reserved slot, above all arguments, to hold a copy of the returned +** string to avoid it being collected while parsed. 'load' has four +** optional arguments (chunk, source name, mode, and environment). +*/ +#define RESERVEDSLOT 5 + + +/* +** 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); /* not used */ + 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)) { + lua_pop(L, 1); /* pop result */ + *size = 0; + return NULL; + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "reader function must return a string"); + lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ + return lua_tolstring(L, RESERVEDSLOT, size); +} + + +static int luaB_load (lua_State *L) { + int status; + size_t l; + const char *s = lua_tolstring(L, 1, &l); + const char *mode = luaL_optstring(L, 3, "bt"); + int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ + if (s != NULL) { /* loading a string? */ + const char *chunkname = luaL_optstring(L, 2, s); + status = luaL_loadbufferx(L, s, l, chunkname, mode); + } + else { /* loading from a reader function */ + const char *chunkname = luaL_optstring(L, 2, "=(load)"); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, RESERVEDSLOT); /* create reserved slot */ + status = lua_load(L, generic_reader, NULL, chunkname, mode); + } + return load_aux(L, status, env); +} + +/* }====================================================== */ + + +static int dofilecont (lua_State *L) { + return lua_gettop(L) - 1; +} + + +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + lua_settop(L, 1); + if (luaL_loadfile(L, fname) != LUA_OK) + return lua_error(L); + lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); + return dofilecont(L); +} + + +static int luaB_assert (lua_State *L) { + if (!lua_toboolean(L, 1)) + return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); + return lua_gettop(L); +} + + +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 finishpcall (lua_State *L, int status) { + if (!lua_checkstack(L, 1)) { /* no space for extra boolean? */ + lua_settop(L, 0); /* create space for return values */ + lua_pushboolean(L, 0); + lua_pushstring(L, "stack overflow"); + return 2; /* return false, msg */ + } + lua_pushboolean(L, status); /* first result (status) */ + lua_replace(L, 1); /* put first result in first slot */ + return lua_gettop(L); +} + + +static int pcallcont (lua_State *L) { + int status = lua_getctx(L, NULL); + return finishpcall(L, (status == LUA_YIELD)); +} + + +static int luaB_pcall (lua_State *L) { + int status; + luaL_checkany(L, 1); + lua_pushnil(L); + lua_insert(L, 1); /* create space for status result */ + status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, pcallcont); + return finishpcall(L, (status == LUA_OK)); +} + + +static int luaB_xpcall (lua_State *L) { + int status; + int n = lua_gettop(L); + luaL_argcheck(L, n >= 2, 2, "value expected"); + lua_pushvalue(L, 1); /* exchange function... */ + lua_copy(L, 2, 1); /* ...and error handler */ + lua_replace(L, 2); + status = lua_pcallk(L, n - 2, LUA_MULTRET, 1, 0, pcallcont); + return finishpcall(L, (status == LUA_OK)); +} + + +static int luaB_tostring (lua_State *L) { + luaL_checkany(L, 1); + luaL_tolstring(L, 1, NULL); + return 1; +} + + +static const luaL_Reg base_funcs[] = { + {"assert", luaB_assert}, + {"collectgarbage", luaB_collectgarbage}, + {"dofile", luaB_dofile}, + {"error", luaB_error}, + {"getmetatable", luaB_getmetatable}, + {"ipairs", luaB_ipairs}, + {"loadfile", luaB_loadfile}, + {"load", luaB_load}, +#if defined(LUA_COMPAT_LOADSTRING) + {"loadstring", luaB_load}, +#endif + {"next", luaB_next}, + {"pairs", luaB_pairs}, + {"pcall", luaB_pcall}, + {"print", luaB_print}, + {"rawequal", luaB_rawequal}, + {"rawlen", luaB_rawlen}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"select", luaB_select}, + {"setmetatable", luaB_setmetatable}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"xpcall", luaB_xpcall}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_base (lua_State *L) { + /* set global _G */ + lua_pushglobaltable(L); + lua_pushglobaltable(L); + lua_setfield(L, -2, "_G"); + /* open lib into global table */ + luaL_setfuncs(L, base_funcs, 0); + lua_pushliteral(L, LUA_VERSION); + lua_setfield(L, -2, "_VERSION"); /* set global _VERSION */ + return 1; +} + diff --git a/lua/lbitlib.c b/lua/lbitlib.c new file mode 100644 index 0000000..31c7b66 --- /dev/null +++ b/lua/lbitlib.c @@ -0,0 +1,212 @@ +/* +** $Id: lbitlib.c,v 1.18.1.2 2013/07/09 18:01:41 roberto Exp $ +** Standard library for bitwise operations +** See Copyright Notice in lua.h +*/ + +#define lbitlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* number of bits to consider in a number */ +#if !defined(LUA_NBITS) +#define LUA_NBITS 32 +#endif + + +#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) + +/* macro to trim extra bits */ +#define trim(x) ((x) & ALLONES) + + +/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ +#define mask(n) (~((ALLONES << 1) << ((n) - 1))) + + +typedef lua_Unsigned b_uint; + + + +static b_uint andaux (lua_State *L) { + int i, n = lua_gettop(L); + b_uint r = ~(b_uint)0; + for (i = 1; i <= n; i++) + r &= luaL_checkunsigned(L, i); + return trim(r); +} + + +static int b_and (lua_State *L) { + b_uint r = andaux(L); + lua_pushunsigned(L, r); + return 1; +} + + +static int b_test (lua_State *L) { + b_uint r = andaux(L); + lua_pushboolean(L, r != 0); + return 1; +} + + +static int b_or (lua_State *L) { + int i, n = lua_gettop(L); + b_uint r = 0; + for (i = 1; i <= n; i++) + r |= luaL_checkunsigned(L, i); + lua_pushunsigned(L, trim(r)); + return 1; +} + + +static int b_xor (lua_State *L) { + int i, n = lua_gettop(L); + b_uint r = 0; + for (i = 1; i <= n; i++) + r ^= luaL_checkunsigned(L, i); + lua_pushunsigned(L, trim(r)); + return 1; +} + + +static int b_not (lua_State *L) { + b_uint r = ~luaL_checkunsigned(L, 1); + lua_pushunsigned(L, trim(r)); + return 1; +} + + +static int b_shift (lua_State *L, b_uint r, int i) { + if (i < 0) { /* shift right? */ + i = -i; + r = trim(r); + if (i >= LUA_NBITS) r = 0; + else r >>= i; + } + else { /* shift left */ + if (i >= LUA_NBITS) r = 0; + else r <<= i; + r = trim(r); + } + lua_pushunsigned(L, r); + return 1; +} + + +static int b_lshift (lua_State *L) { + return b_shift(L, luaL_checkunsigned(L, 1), luaL_checkint(L, 2)); +} + + +static int b_rshift (lua_State *L) { + return b_shift(L, luaL_checkunsigned(L, 1), -luaL_checkint(L, 2)); +} + + +static int b_arshift (lua_State *L) { + b_uint r = luaL_checkunsigned(L, 1); + int i = luaL_checkint(L, 2); + if (i < 0 || !(r & ((b_uint)1 << (LUA_NBITS - 1)))) + return b_shift(L, r, -i); + else { /* arithmetic shift for 'negative' number */ + if (i >= LUA_NBITS) r = ALLONES; + else + r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */ + lua_pushunsigned(L, r); + return 1; + } +} + + +static int b_rot (lua_State *L, int i) { + b_uint r = luaL_checkunsigned(L, 1); + i &= (LUA_NBITS - 1); /* i = i % NBITS */ + r = trim(r); + if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */ + r = (r << i) | (r >> (LUA_NBITS - i)); + lua_pushunsigned(L, trim(r)); + return 1; +} + + +static int b_lrot (lua_State *L) { + return b_rot(L, luaL_checkint(L, 2)); +} + + +static int b_rrot (lua_State *L) { + return b_rot(L, -luaL_checkint(L, 2)); +} + + +/* +** get field and width arguments for field-manipulation functions, +** checking whether they are valid. +** ('luaL_error' called without 'return' to avoid later warnings about +** 'width' being used uninitialized.) +*/ +static int fieldargs (lua_State *L, int farg, int *width) { + int f = luaL_checkint(L, farg); + int w = luaL_optint(L, farg + 1, 1); + luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); + luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); + if (f + w > LUA_NBITS) + luaL_error(L, "trying to access non-existent bits"); + *width = w; + return f; +} + + +static int b_extract (lua_State *L) { + int w; + b_uint r = luaL_checkunsigned(L, 1); + int f = fieldargs(L, 2, &w); + r = (r >> f) & mask(w); + lua_pushunsigned(L, r); + return 1; +} + + +static int b_replace (lua_State *L) { + int w; + b_uint r = luaL_checkunsigned(L, 1); + b_uint v = luaL_checkunsigned(L, 2); + int f = fieldargs(L, 3, &w); + int m = mask(w); + v &= m; /* erase bits outside given width */ + r = (r & ~(m << f)) | (v << f); + lua_pushunsigned(L, r); + return 1; +} + + +static const luaL_Reg bitlib[] = { + {"arshift", b_arshift}, + {"band", b_and}, + {"bnot", b_not}, + {"bor", b_or}, + {"bxor", b_xor}, + {"btest", b_test}, + {"extract", b_extract}, + {"lrotate", b_lrot}, + {"lshift", b_lshift}, + {"replace", b_replace}, + {"rrotate", b_rrot}, + {"rshift", b_rshift}, + {NULL, NULL} +}; + + + +LUAMOD_API int luaopen_bit32 (lua_State *L) { + luaL_newlib(L, bitlib); + return 1; +} + diff --git a/lua/lcode.c b/lua/lcode.c new file mode 100644 index 0000000..820b95c --- /dev/null +++ b/lua/lcode.c @@ -0,0 +1,881 @@ +/* +** $Id: lcode.c,v 2.62.1.1 2013/04/12 18:48:47 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 "lstring.h" +#include "ltable.h" +#include "lvm.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; + int l = from + n - 1; /* last register to set nil */ + if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ + previous = &fs->f->code[fs->pc-1]; + if (GET_OPCODE(*previous) == OP_LOADNIL) { + int pfrom = GETARG_A(*previous); + int pl = pfrom + GETARG_B(*previous); + if ((pfrom <= from && from <= pl + 1) || + (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ + if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ + if (pl > l) l = pl; /* l = max(l, pl) */ + SETARG_A(*previous, from); + SETARG_B(*previous, l - from); + return; + } + } /* else go through */ + } + luaK_codeABC(fs, OP_LOADNIL, 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); + } +} + + +LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level) { + level++; /* argument is +1 to reserve 0 as non-op */ + while (list != NO_JUMP) { + int next = getjump(fs, list); + lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && + (GETARG_A(fs->f->code[list]) == 0 || + GETARG_A(fs->f->code[list]) >= level)); + SETARG_A(fs->f->code[list], level); + list = next; + } +} + + +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); + } +} + + +static int luaK_code (FuncState *fs, Instruction i) { + Proto *f = fs->f; + dischargejpc(fs); /* `pc' will change */ + /* put new instruction in code array */ + luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "opcodes"); + f->code[fs->pc] = i; + /* save corresponding line information */ + luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "opcodes"); + f->lineinfo[fs->pc] = fs->ls->lastline; + 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); + lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); + return luaK_code(fs, CREATE_ABC(o, a, b, c)); +} + + +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); + lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); + return luaK_code(fs, CREATE_ABx(o, a, bc)); +} + + +static int codeextraarg (FuncState *fs, int a) { + lua_assert(a <= MAXARG_Ax); + return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); +} + + +int luaK_codek (FuncState *fs, int reg, int k) { + if (k <= MAXARG_Bx) + return luaK_codeABx(fs, OP_LOADK, reg, k); + else { + int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); + codeextraarg(fs, k); + return p; + } +} + + +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.info); +} + + +static int addk (FuncState *fs, TValue *key, TValue *v) { + lua_State *L = fs->ls->L; + TValue *idx = luaH_set(L, fs->h, key); + Proto *f = fs->f; + int k, oldsize; + if (ttisnumber(idx)) { + lua_Number n = nvalue(idx); + lua_number2int(k, n); + if (luaV_rawequalobj(&f->k[k], v)) + return k; + /* else may be a collision (e.g., between 0.0 and "\0\0\0\0\0\0\0\0"); + go through and create a new entry for this value */ + } + /* constant not found; create a new entry */ + oldsize = f->sizek; + k = fs->nk; + /* numerical value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setnvalue(idx, cast_num(k)); + luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[k], v); + fs->nk++; + luaC_barrier(L, f, v); + return k; +} + + +int luaK_stringK (FuncState *fs, TString *s) { + TValue o; + setsvalue(fs->ls->L, &o, s); + return addk(fs, &o, &o); +} + + +int luaK_numberK (FuncState *fs, lua_Number r) { + int n; + lua_State *L = fs->ls->L; + TValue o; + setnvalue(&o, r); + if (r == 0 || luai_numisnan(NULL, r)) { /* handle -0 and NaN */ + /* use raw representation as key to avoid numeric problems */ + setsvalue(L, L->top++, luaS_newlstr(L, (char *)&r, sizeof(r))); + n = addk(fs, L->top - 1, &o); + L->top--; + } + else + n = addk(fs, &o, &o); /* regular case */ + return n; +} + + +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->ls->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.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.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); + e->k = VRELOCABLE; + break; + } + case VINDEXED: { + OpCode op = OP_GETTABUP; /* assume 't' is in an upvalue */ + freereg(fs, e->u.ind.idx); + if (e->u.ind.vt == VLOCAL) { /* 't' is in a register? */ + freereg(fs, e->u.ind.t); + op = OP_GETTABLE; + } + e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); + 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_codek(fs, reg, e->u.info); + break; + } + case VKNUM: { + luaK_codek(fs, 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.info) + luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); + break; + } + default: { + lua_assert(e->k == VVOID || e->k == VJMP); + return; /* nothing to do... */ + } + } + e->u.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.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.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.info; /* exp is already in a register */ + if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ + exp2reg(fs, e, e->u.info); /* put value on it */ + return e->u.info; + } + } + luaK_exp2nextreg(fs, e); /* default */ + return e->u.info; +} + + +void luaK_exp2anyregup (FuncState *fs, expdesc *e) { + if (e->k != VUPVAL || hasjumps(e)) + luaK_exp2anyreg(fs, e); +} + + +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 VTRUE: + case VFALSE: + case VNIL: { + if (fs->nk <= MAXINDEXRK) { /* constant fits in RK operand? */ + e->u.info = (e->k == VNIL) ? nilK(fs) : boolK(fs, (e->k == VTRUE)); + e->k = VK; + return RKASK(e->u.info); + } + else break; + } + case VKNUM: { + e->u.info = luaK_numberK(fs, e->u.nval); + e->k = VK; + /* go through */ + } + case VK: { + if (e->u.info <= MAXINDEXRK) /* constant fits in argC? */ + return RKASK(e->u.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.info); + return; + } + case VUPVAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); + break; + } + case VINDEXED: { + OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; + int e = luaK_exp2RK(fs, ex); + luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, 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 ereg; + luaK_exp2anyreg(fs, e); + ereg = e->u.info; /* register where 'e' was placed */ + freeexp(fs, e); + e->u.info = fs->freereg; /* base register for op_self */ + e->k = VNONRELOC; + luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ + luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); + freeexp(fs, key); +} + + +static void invertjump (FuncState *fs, expdesc *e) { + Instruction *pc = getjumpcontrol(fs, e->u.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.info, cond); +} + + +void luaK_goiftrue (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VJMP: { + invertjump(fs, e); + pc = e->u.info; + break; + } + case VK: case VKNUM: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + 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; +} + + +void luaK_goiffalse (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VJMP: { + pc = e->u.info; + break; + } + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ + 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.info = luaK_codeABC(fs, OP_NOT, 0, e->u.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) { + lua_assert(!hasjumps(t)); + t->u.ind.t = t->u.info; + t->u.ind.idx = luaK_exp2RK(fs, k); + t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL + : check_exp(vkisinreg(t->k), VLOCAL); + t->k = VINDEXED; +} + + +static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { + lua_Number r; + if (!isnumeral(e1) || !isnumeral(e2)) return 0; + if ((op == OP_DIV || op == OP_MOD) && e2->u.nval == 0) + return 0; /* do not attempt to divide by 0 */ + r = luaO_arith(op - OP_ADD + LUA_OPADD, e1->u.nval, e2->u.nval); + e1->u.nval = r; + return 1; +} + + +static void codearith (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int line) { + 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.info = luaK_codeABC(fs, op, 0, o1, o2); + e1->k = VRELOCABLE; + luaK_fixline(fs, line); + } +} + + +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.info = condjump(fs, op, cond, o1, o2); + e1->k = VJMP; +} + + +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { + expdesc e2; + e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; + switch (op) { + case OPR_MINUS: { + if (isnumeral(e)) /* minus constant? */ + e->u.nval = luai_numunm(NULL, e->u.nval); /* fold it */ + else { + luaK_exp2anyreg(fs, e); + codearith(fs, OP_UNM, e, &e2, line); + } + 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, line); + 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, int line) { + 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.info == GETARG_B(getcode(fs, e2))-1); + freeexp(fs, e1); + SETARG_B(getcode(fs, e2), e1->u.info); + e1->k = VRELOCABLE; e1->u.info = e2->u.info; + } + else { + luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ + codearith(fs, OP_CONCAT, e1, e2, line); + } + break; + } + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_MOD: case OPR_POW: { + codearith(fs, cast(OpCode, op - OPR_ADD + OP_ADD), e1, e2, line); + break; + } + case OPR_EQ: case OPR_LT: case OPR_LE: { + codecomp(fs, cast(OpCode, op - OPR_EQ + OP_EQ), 1, e1, e2); + break; + } + case OPR_NE: case OPR_GT: case OPR_GE: { + codecomp(fs, cast(OpCode, op - OPR_NE + OP_EQ), 0, e1, e2); + break; + } + default: lua_assert(0); + } +} + + +void luaK_fixline (FuncState *fs, int line) { + fs->f->lineinfo[fs->pc - 1] = line; +} + + +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 if (c <= MAXARG_Ax) { + luaK_codeABC(fs, OP_SETLIST, base, b, 0); + codeextraarg(fs, c); + } + else + luaX_syntaxerror(fs->ls, "constructor too long"); + fs->freereg = base + 1; /* free registers with list values */ +} + diff --git a/lua/lcode.h b/lua/lcode.h new file mode 100644 index 0000000..6a1424c --- /dev/null +++ b/lua/lcode.h @@ -0,0 +1,83 @@ +/* +** $Id: lcode.h,v 1.58.1.1 2013/04/12 18:48:47 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 (ORDER OP) +*/ +typedef enum BinOpr { + OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, + OPR_CONCAT, + OPR_EQ, OPR_LT, OPR_LE, + OPR_NE, 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.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) + +#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) + +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 int luaK_codek (FuncState *fs, int reg, int k); +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_exp2anyregup (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_goiffalse (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_patchclose (FuncState *fs, int list, int level); +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, int line); +LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); +LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, + expdesc *v2, int line); +LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); + + +#endif diff --git a/lua/lcorolib.c b/lua/lcorolib.c new file mode 100644 index 0000000..ce4f6ad --- /dev/null +++ b/lua/lcorolib.c @@ -0,0 +1,155 @@ +/* +** $Id: lcorolib.c,v 1.5.1.1 2013/04/12 18:48:47 roberto Exp $ +** Coroutine Library +** See Copyright Notice in lua.h +*/ + + +#include + + +#define lcorolib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status; + if (!lua_checkstack(co, narg)) { + lua_pushliteral(L, "too many arguments to resume"); + return -1; /* error flag */ + } + if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { + lua_pushliteral(L, "cannot resume dead coroutine"); + return -1; /* error flag */ + } + lua_xmove(L, co, narg); + status = lua_resume(co, L, narg); + if (status == LUA_OK || status == LUA_YIELD) { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres + 1)) { + lua_pop(co, nres); /* remove results anyway */ + lua_pushliteral(L, "too many results to resume"); + return -1; /* error flag */ + } + 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); + } + return lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL; + luaL_checktype(L, 1, LUA_TFUNCTION); + NL = lua_newthread(L); + 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_costatus (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + if (L == co) lua_pushliteral(L, "running"); + else { + switch (lua_status(co)) { + case LUA_YIELD: + lua_pushliteral(L, "suspended"); + break; + case LUA_OK: { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ + lua_pushliteral(L, "normal"); /* it is running */ + else if (lua_gettop(co) == 0) + lua_pushliteral(L, "dead"); + else + lua_pushliteral(L, "suspended"); /* initial state */ + break; + } + default: /* some error occurred */ + lua_pushliteral(L, "dead"); + break; + } + } + return 1; +} + + +static int luaB_corunning (lua_State *L) { + int ismain = lua_pushthread(L); + lua_pushboolean(L, ismain); + return 2; +} + + +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} +}; + + + +LUAMOD_API int luaopen_coroutine (lua_State *L) { + luaL_newlib(L, co_funcs); + return 1; +} + diff --git a/lua/lctype.c b/lua/lctype.c new file mode 100644 index 0000000..93f8cad --- /dev/null +++ b/lua/lctype.c @@ -0,0 +1,52 @@ +/* +** $Id: lctype.c,v 1.11.1.1 2013/04/12 18:48:47 roberto Exp $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#define lctype_c +#define LUA_CORE + +#include "lctype.h" + +#if !LUA_USE_CTYPE /* { */ + +#include + +LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { + 0x00, /* EOZ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ + 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +#endif /* } */ diff --git a/lua/lctype.h b/lua/lctype.h new file mode 100644 index 0000000..b09b21a --- /dev/null +++ b/lua/lctype.h @@ -0,0 +1,95 @@ +/* +** $Id: lctype.h,v 1.12.1.1 2013/04/12 18:48:47 roberto Exp $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lctype_h +#define lctype_h + +#include "lua.h" + + +/* +** WARNING: the functions defined here do not necessarily correspond +** to the similar functions in the standard C ctype.h. They are +** optimized for the specific needs of Lua +*/ + +#if !defined(LUA_USE_CTYPE) + +#if 'A' == 65 && '0' == 48 +/* ASCII case: can use its own tables; faster and fixed */ +#define LUA_USE_CTYPE 0 +#else +/* must use standard C ctype */ +#define LUA_USE_CTYPE 1 +#endif + +#endif + + +#if !LUA_USE_CTYPE /* { */ + +#include + +#include "llimits.h" + + +#define ALPHABIT 0 +#define DIGITBIT 1 +#define PRINTBIT 2 +#define SPACEBIT 3 +#define XDIGITBIT 4 + + +#define MASK(B) (1 << (B)) + + +/* +** add 1 to char to allow index -1 (EOZ) +*/ +#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) + +/* +** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' +*/ +#define lislalpha(c) testprop(c, MASK(ALPHABIT)) +#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) +#define lisdigit(c) testprop(c, MASK(DIGITBIT)) +#define lisspace(c) testprop(c, MASK(SPACEBIT)) +#define lisprint(c) testprop(c, MASK(PRINTBIT)) +#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) + +/* +** this 'ltolower' only works for alphabetic characters +*/ +#define ltolower(c) ((c) | ('A' ^ 'a')) + + +/* two more entries for 0 and -1 (EOZ) */ +LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; + + +#else /* }{ */ + +/* +** use standard C ctypes +*/ + +#include + + +#define lislalpha(c) (isalpha(c) || (c) == '_') +#define lislalnum(c) (isalnum(c) || (c) == '_') +#define lisdigit(c) (isdigit(c)) +#define lisspace(c) (isspace(c)) +#define lisprint(c) (isprint(c)) +#define lisxdigit(c) (isxdigit(c)) + +#define ltolower(c) (tolower(c)) + +#endif /* } */ + +#endif + diff --git a/lua/ldblib.c b/lua/ldblib.c new file mode 100644 index 0000000..84fe3c7 --- /dev/null +++ b/lua/ldblib.c @@ -0,0 +1,398 @@ +/* +** $Id: ldblib.c,v 1.132.1.1 2013/04/12 18:48:47 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" + + +#define HOOKKEY "_HKEY" + + + +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_setmetatable(L, 1); + return 1; /* return 1st argument */ +} + + +static int db_getuservalue (lua_State *L) { + if (lua_type(L, 1) != LUA_TUSERDATA) + lua_pushnil(L); + else + lua_getuservalue(L, 1); + return 1; +} + + +static int db_setuservalue (lua_State *L) { + if (lua_type(L, 1) == LUA_TLIGHTUSERDATA) + luaL_argerror(L, 1, "full userdata expected, got light userdata"); + luaL_checktype(L, 1, LUA_TUSERDATA); + if (!lua_isnoneornil(L, 2)) + luaL_checktype(L, 2, LUA_TTABLE); + lua_settop(L, 2); + lua_setuservalue(L, 1); + 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 void settabsb (lua_State *L, const char *i, int v) { + lua_pushboolean(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, "flnStu"); + 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); + settabsi(L, "nparams", ar.nparams); + settabsb(L, "isvararg", ar.isvararg); + } + if (strchr(options, 'n')) { + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + } + if (strchr(options, 't')) + settabsb(L, "istailcall", ar.istailcall); + 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; + int nvar = luaL_checkint(L, arg+2); /* local-variable index */ + if (lua_isfunction(L, arg + 1)) { /* function argument? */ + lua_pushvalue(L, arg + 1); /* push function */ + lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ + return 1; + } + else { /* stack-level argument */ + 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, nvar); + if (name) { + lua_xmove(L1, L, 1); /* push local value */ + lua_pushstring(L, name); /* push name */ + lua_pushvalue(L, -2); /* re-order */ + return 2; + } + else { + lua_pushnil(L); /* no name (nor value) */ + 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); + 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 int checkupval (lua_State *L, int argf, int argnup) { + lua_Debug ar; + int nup = luaL_checkint(L, argnup); + luaL_checktype(L, argf, LUA_TFUNCTION); + lua_pushvalue(L, argf); + lua_getinfo(L, ">u", &ar); + luaL_argcheck(L, 1 <= nup && nup <= ar.nups, argnup, "invalid upvalue index"); + return nup; +} + + +static int db_upvalueid (lua_State *L) { + int n = checkupval(L, 1, 2); + lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); + return 1; +} + + +static int db_upvaluejoin (lua_State *L) { + int n1 = checkupval(L, 1, 2); + int n2 = checkupval(L, 3, 4); + luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); + luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); + lua_upvaluejoin(L, 1, n1, 3, n2); + return 0; +} + + +#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY) + + +static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail call"}; + gethooktable(L); + lua_pushthread(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 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); + } + if (gethooktable(L) == 0) { /* creating hook table? */ + lua_pushstring(L, "k"); + lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ + lua_pushvalue(L, -1); + lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ + } + lua_pushthread(L1); lua_xmove(L1, L, 1); + lua_pushvalue(L, arg+1); + lua_rawset(L, -3); /* set new hook */ + 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_pushthread(L1); lua_xmove(L1, L, 1); + 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]; + luai_writestringerror("%s", "lua_debug> "); + 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)) + luai_writestringerror("%s\n", lua_tostring(L, -1)); + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +static int db_traceback (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + const char *msg = lua_tostring(L, arg + 1); + if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ + lua_pushvalue(L, arg + 1); /* return it untouched */ + else { + int level = luaL_optint(L, arg + 2, (L == L1) ? 1 : 0); + luaL_traceback(L, L1, msg, level); + } + return 1; +} + + +static const luaL_Reg dblib[] = { + {"debug", db_debug}, + {"getuservalue", db_getuservalue}, + {"gethook", db_gethook}, + {"getinfo", db_getinfo}, + {"getlocal", db_getlocal}, + {"getregistry", db_getregistry}, + {"getmetatable", db_getmetatable}, + {"getupvalue", db_getupvalue}, + {"upvaluejoin", db_upvaluejoin}, + {"upvalueid", db_upvalueid}, + {"setuservalue", db_setuservalue}, + {"sethook", db_sethook}, + {"setlocal", db_setlocal}, + {"setmetatable", db_setmetatable}, + {"setupvalue", db_setupvalue}, + {"traceback", db_traceback}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_debug (lua_State *L) { + luaL_newlib(L, dblib); + return 1; +} + diff --git a/lua/ldebug.c b/lua/ldebug.c new file mode 100644 index 0000000..20d663e --- /dev/null +++ b/lua/ldebug.c @@ -0,0 +1,593 @@ +/* +** $Id: ldebug.c,v 2.90.1.3 2013/05/16 16:04:15 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" + + + +#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); + + +static int currentpc (CallInfo *ci) { + lua_assert(isLua(ci)); + return pcRel(ci->u.l.savedpc, ci_func(ci)->p); +} + + +static int currentline (CallInfo *ci) { + return getfuncline(ci_func(ci)->p, currentpc(ci)); +} + + +/* +** 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; + } + if (isLua(L->ci)) + L->oldpc = L->ci->u.l.savedpc; + 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; + if (level < 0) return 0; /* invalid (negative) level */ + lua_lock(L); + for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) + level--; + if (level == 0 && ci != &L->base_ci) { /* level found? */ + status = 1; + ar->i_ci = ci; + } + else status = 0; /* no such level */ + lua_unlock(L); + return status; +} + + +static const char *upvalname (Proto *p, int uv) { + TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); + if (s == NULL) return "?"; + else return getstr(s); +} + + +static const char *findvararg (CallInfo *ci, int n, StkId *pos) { + int nparams = clLvalue(ci->func)->p->numparams; + if (n >= ci->u.l.base - ci->func - nparams) + return NULL; /* no such vararg */ + else { + *pos = ci->func + nparams + n; + return "(*vararg)"; /* generic name for any vararg */ + } +} + + +static const char *findlocal (lua_State *L, CallInfo *ci, int n, + StkId *pos) { + const char *name = NULL; + StkId base; + if (isLua(ci)) { + if (n < 0) /* access to vararg values? */ + return findvararg(ci, -n, pos); + else { + base = ci->u.l.base; + name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); + } + } + else + base = ci->func + 1; + if (name == NULL) { /* no 'standard' name? */ + StkId limit = (ci == L->ci) ? L->top : ci->next->func; + if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ + name = "(*temporary)"; /* generic name for any valid slot */ + else + return NULL; /* no name */ + } + *pos = base + (n - 1); + return name; +} + + +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { + const char *name; + lua_lock(L); + if (ar == NULL) { /* information about non-active function? */ + if (!isLfunction(L->top - 1)) /* not a Lua function? */ + name = NULL; + else /* consider live variables at function start (parameters) */ + name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); + } + else { /* active function; get information through 'ar' */ + StkId pos = 0; /* to avoid warnings */ + name = findlocal(L, ar->i_ci, n, &pos); + if (name) { + setobj2s(L, L->top, pos); + api_incr_top(L); + } + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + StkId pos = 0; /* to avoid warnings */ + const char *name = findlocal(L, ar->i_ci, n, &pos); + lua_lock(L); + if (name) + setobjs2s(L, pos, L->top - 1); + L->top--; /* pop value */ + lua_unlock(L); + return name; +} + + +static void funcinfo (lua_Debug *ar, Closure *cl) { + if (noLuaClosure(cl)) { + ar->source = "=[C]"; + ar->linedefined = -1; + ar->lastlinedefined = -1; + ar->what = "C"; + } + else { + Proto *p = cl->l.p; + ar->source = p->source ? getstr(p->source) : "=?"; + ar->linedefined = p->linedefined; + ar->lastlinedefined = p->lastlinedefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); +} + + +static void collectvalidlines (lua_State *L, Closure *f) { + if (noLuaClosure(f)) { + setnilvalue(L->top); + api_incr_top(L); + } + else { + int i; + TValue v; + int *lineinfo = f->l.p->lineinfo; + Table *t = luaH_new(L); /* new table to store active lines */ + sethvalue(L, L->top, t); /* push it on stack */ + api_incr_top(L); + setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ + for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ + luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ + } +} + + +static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, + Closure *f, CallInfo *ci) { + int status = 1; + for (; *what; what++) { + switch (*what) { + case 'S': { + funcinfo(ar, f); + break; + } + case 'l': { + ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; + break; + } + case 'u': { + ar->nups = (f == NULL) ? 0 : f->c.nupvalues; + if (noLuaClosure(f)) { + ar->isvararg = 1; + ar->nparams = 0; + } + else { + ar->isvararg = f->l.p->is_vararg; + ar->nparams = f->l.p->numparams; + } + break; + } + case 't': { + ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; + break; + } + case 'n': { + /* calling function is a known Lua function? */ + if (ci && !(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) + ar->namewhat = getfuncname(L, ci->previous, &ar->name); + else + ar->namewhat = 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 *cl; + CallInfo *ci; + StkId func; + lua_lock(L); + if (*what == '>') { + ci = NULL; + func = L->top - 1; + api_check(L, ttisfunction(func), "function expected"); + what++; /* skip the '>' */ + L->top--; /* pop function */ + } + else { + ci = ar->i_ci; + func = ci->func; + lua_assert(ttisfunction(ci->func)); + } + cl = ttisclosure(func) ? clvalue(func) : NULL; + status = auxgetinfo(L, what, ar, cl, ci); + if (strchr(what, 'f')) { + setobjs2s(L, L->top, func); + api_incr_top(L); + } + if (strchr(what, 'L')) + collectvalidlines(L, cl); + lua_unlock(L); + return status; +} + + +/* +** {====================================================== +** Symbolic Execution +** ======================================================= +*/ + +static const char *getobjname (Proto *p, int lastpc, int reg, + const char **name); + + +/* +** find a "name" for the RK value 'c' +*/ +static void kname (Proto *p, int pc, int c, const char **name) { + if (ISK(c)) { /* is 'c' a constant? */ + TValue *kvalue = &p->k[INDEXK(c)]; + if (ttisstring(kvalue)) { /* literal constant? */ + *name = svalue(kvalue); /* it is its own name */ + return; + } + /* else no reasonable name found */ + } + else { /* 'c' is a register */ + const char *what = getobjname(p, pc, c, name); /* search for 'c' */ + if (what && *what == 'c') { /* found a constant name? */ + return; /* 'name' already filled */ + } + /* else no reasonable name found */ + } + *name = "?"; /* no reasonable name found */ +} + + +static int filterpc (int pc, int jmptarget) { + if (pc < jmptarget) /* is code conditional (inside a jump)? */ + return -1; /* cannot know who sets that register */ + else return pc; /* current position sets that register */ +} + + +/* +** try to find last instruction before 'lastpc' that modified register 'reg' +*/ +static int findsetreg (Proto *p, int lastpc, int reg) { + int pc; + int setreg = -1; /* keep last instruction that changed 'reg' */ + int jmptarget = 0; /* any code before this address is conditional */ + for (pc = 0; pc < lastpc; pc++) { + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + int a = GETARG_A(i); + switch (op) { + case OP_LOADNIL: { + int b = GETARG_B(i); + if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ + setreg = filterpc(pc, jmptarget); + break; + } + case OP_TFORCALL: { + if (reg >= a + 2) /* affect all regs above its base */ + setreg = filterpc(pc, jmptarget); + break; + } + case OP_CALL: + case OP_TAILCALL: { + if (reg >= a) /* affect all registers above base */ + setreg = filterpc(pc, jmptarget); + break; + } + case OP_JMP: { + int b = GETARG_sBx(i); + int dest = pc + 1 + b; + /* jump is forward and do not skip `lastpc'? */ + if (pc < dest && dest <= lastpc) { + if (dest > jmptarget) + jmptarget = dest; /* update 'jmptarget' */ + } + break; + } + case OP_TEST: { + if (reg == a) /* jumped code can change 'a' */ + setreg = filterpc(pc, jmptarget); + break; + } + default: + if (testAMode(op) && reg == a) /* any instruction that set A */ + setreg = filterpc(pc, jmptarget); + break; + } + } + return setreg; +} + + +static const char *getobjname (Proto *p, int lastpc, int reg, + const char **name) { + int pc; + *name = luaF_getlocalname(p, reg + 1, lastpc); + if (*name) /* is a local? */ + return "local"; + /* else try symbolic execution */ + pc = findsetreg(p, lastpc, reg); + if (pc != -1) { /* could find instruction? */ + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + switch (op) { + case OP_MOVE: { + int b = GETARG_B(i); /* move from 'b' to 'a' */ + if (b < GETARG_A(i)) + return getobjname(p, pc, b, name); /* get name for 'b' */ + break; + } + case OP_GETTABUP: + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + int t = GETARG_B(i); /* table index */ + const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ + ? luaF_getlocalname(p, t + 1, pc) + : upvalname(p, t); + kname(p, pc, k, name); + return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; + } + case OP_GETUPVAL: { + *name = upvalname(p, GETARG_B(i)); + return "upvalue"; + } + case OP_LOADK: + case OP_LOADKX: { + int b = (op == OP_LOADK) ? GETARG_Bx(i) + : GETARG_Ax(p->code[pc + 1]); + if (ttisstring(&p->k[b])) { + *name = svalue(&p->k[b]); + return "constant"; + } + break; + } + case OP_SELF: { + int k = GETARG_C(i); /* key index */ + kname(p, pc, k, name); + return "method"; + } + default: break; /* go through to return NULL */ + } + } + return NULL; /* could not find reasonable name */ +} + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { + TMS tm; + Proto *p = ci_func(ci)->p; /* calling function */ + int pc = currentpc(ci); /* calling instruction index */ + Instruction i = p->code[pc]; /* calling instruction */ + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: /* get function name */ + return getobjname(p, pc, GETARG_A(i), name); + case OP_TFORCALL: { /* for iterator */ + *name = "for iterator"; + return "for iterator"; + } + /* all other instructions can call only through metamethods */ + case OP_SELF: + case OP_GETTABUP: + case OP_GETTABLE: tm = TM_INDEX; break; + case OP_SETTABUP: + case OP_SETTABLE: tm = TM_NEWINDEX; break; + case OP_EQ: tm = TM_EQ; break; + case OP_ADD: tm = TM_ADD; break; + case OP_SUB: tm = TM_SUB; break; + case OP_MUL: tm = TM_MUL; break; + case OP_DIV: tm = TM_DIV; break; + case OP_MOD: tm = TM_MOD; break; + case OP_POW: tm = TM_POW; break; + case OP_UNM: tm = TM_UNM; break; + case OP_LEN: tm = TM_LEN; break; + case OP_LT: tm = TM_LT; break; + case OP_LE: tm = TM_LE; break; + case OP_CONCAT: tm = TM_CONCAT; break; + default: + return NULL; /* else no useful name can be found */ + } + *name = getstr(G(L)->tmname[tm]); + return "metamethod"; +} + +/* }====================================================== */ + + + +/* +** only ANSI way to check whether a pointer points to an array +** (used only for error messages, so efficiency is not a big concern) +*/ +static int isinstack (CallInfo *ci, const TValue *o) { + StkId p; + for (p = ci->u.l.base; p < ci->top; p++) + if (o == p) return 1; + return 0; +} + + +static const char *getupvalname (CallInfo *ci, const TValue *o, + const char **name) { + LClosure *c = ci_func(ci); + int i; + for (i = 0; i < c->nupvalues; i++) { + if (c->upvals[i]->v == o) { + *name = upvalname(c->p, i); + return "upvalue"; + } + } + return NULL; +} + + +l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + CallInfo *ci = L->ci; + const char *name = NULL; + const char *t = objtypename(o); + const char *kind = NULL; + if (isLua(ci)) { + kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ + if (!kind && isinstack(ci, o)) /* no? try a register */ + kind = getobjname(ci_func(ci)->p, currentpc(ci), + cast_int(o - ci->u.l.base), &name); + } + 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); +} + + +l_noret 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"); +} + + +l_noret 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"); +} + + +l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { + const char *t1 = objtypename(p1); + const char *t2 = objtypename(p2); + if (t1 == t2) + luaG_runerror(L, "attempt to compare two %s values", t1); + else + luaG_runerror(L, "attempt to compare %s with %s", t1, t2); +} + + +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(ci); + TString *src = ci_func(ci)->p->source; + if (src) + luaO_chunkid(buff, getstr(src), LUA_IDSIZE); + else { /* no source available; use "?" instead */ + buff[0] = '?'; buff[1] = '\0'; + } + luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); + } +} + + +l_noret 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 */ + L->top++; + luaD_call(L, L->top - 2, 1, 0); /* call it */ + } + luaD_throw(L, LUA_ERRRUN); +} + + +l_noret 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); +} + diff --git a/lua/ldebug.h b/lua/ldebug.h new file mode 100644 index 0000000..6445c76 --- /dev/null +++ b/lua/ldebug.h @@ -0,0 +1,34 @@ +/* +** $Id: ldebug.h,v 2.7.1.1 2013/04/12 18:48:47 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 getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) + +#define resethookcount(L) (L->hookcount = L->basehookcount) + +/* Active Lua function (given call info) */ +#define ci_func(ci) (clLvalue((ci)->func)) + + +LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, + const char *opname); +LUAI_FUNC l_noret luaG_concaterror (lua_State *L, StkId p1, StkId p2); +LUAI_FUNC l_noret luaG_aritherror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC l_noret luaG_errormsg (lua_State *L); + +#endif diff --git a/lua/ldo.c b/lua/ldo.c new file mode 100644 index 0000000..e9dd5fa --- /dev/null +++ b/lua/ldo.c @@ -0,0 +1,681 @@ +/* +** $Id: ldo.c,v 2.108.1.3 2013/11/08 18:22:50 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 "lapi.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 +** ======================================================= +*/ + +/* +** LUAI_THROW/LUAI_TRY define how Lua does exception handling. 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(LUAI_THROW) + +#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) +/* 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 + +#endif + + + +/* chain list of long jump buffers */ +struct lua_longjmp { + struct lua_longjmp *previous; + luai_jmpbuf b; + volatile int status; /* error code */ +}; + + +static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { + switch (errcode) { + case LUA_ERRMEM: { /* memory error? */ + setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ + break; + } + case LUA_ERRERR: { + setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); + break; + } + default: { + setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + break; + } + } + L->top = oldtop + 1; +} + + +l_noret luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { /* thread has an error handler? */ + L->errorJmp->status = errcode; /* set status */ + LUAI_THROW(L, L->errorJmp); /* jump to it */ + } + else { /* thread has no error handler */ + L->status = cast_byte(errcode); /* mark it as dead */ + if (G(L)->mainthread->errorJmp) { /* main thread has a handler? */ + setobjs2s(L, G(L)->mainthread->top++, L->top - 1); /* copy error obj. */ + luaD_throw(G(L)->mainthread, errcode); /* re-throw in main thread */ + } + else { /* no handler at all; abort */ + if (G(L)->panic) { /* panic function? */ + lua_unlock(L); + G(L)->panic(L); /* call it (last chance to jump out) */ + } + abort(); + } + } +} + + +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + unsigned short oldnCcalls = L->nCcalls; + struct lua_longjmp lj; + lj.status = LUA_OK; + 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 */ + L->nCcalls = oldnCcalls; + 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->ci; ci != NULL; ci = ci->previous) { + ci->top = (ci->top - oldstack) + L->stack; + ci->func = (ci->func - oldstack) + L->stack; + if (isLua(ci)) + ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; + } +} + + +/* some space for error handling */ +#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) + + +void luaD_reallocstack (lua_State *L, int newsize) { + TValue *oldstack = L->stack; + int lim = L->stacksize; + lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); + luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); + for (; lim < newsize; lim++) + setnilvalue(L->stack + lim); /* erase new segment */ + L->stacksize = newsize; + L->stack_last = L->stack + newsize - EXTRA_STACK; + correctstack(L, oldstack); +} + + +void luaD_growstack (lua_State *L, int n) { + int size = L->stacksize; + if (size > LUAI_MAXSTACK) /* error after extra size? */ + luaD_throw(L, LUA_ERRERR); + else { + int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; + int newsize = 2 * size; + if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; + if (newsize < needed) newsize = needed; + if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ + luaD_reallocstack(L, ERRORSTACKSIZE); + luaG_runerror(L, "stack overflow"); + } + else + luaD_reallocstack(L, newsize); + } +} + + +static int stackinuse (lua_State *L) { + CallInfo *ci; + StkId lim = L->top; + for (ci = L->ci; ci != NULL; ci = ci->previous) { + lua_assert(ci->top <= L->stack_last); + if (lim < ci->top) lim = ci->top; + } + return cast_int(lim - L->stack) + 1; /* part of stack in use */ +} + + +void luaD_shrinkstack (lua_State *L) { + int inuse = stackinuse(L); + int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; + if (goodsize > LUAI_MAXSTACK) goodsize = LUAI_MAXSTACK; + if (inuse > LUAI_MAXSTACK || /* handling stack overflow? */ + goodsize >= L->stacksize) /* would grow instead of shrink? */ + condmovestack(L); /* don't change stack (change only for debugging) */ + else + luaD_reallocstack(L, goodsize); /* shrink it */ +} + + +void luaD_hook (lua_State *L, int event, int line) { + lua_Hook hook = L->hook; + if (hook && L->allowhook) { + CallInfo *ci = L->ci; + ptrdiff_t top = savestack(L, L->top); + ptrdiff_t ci_top = savestack(L, ci->top); + lua_Debug ar; + ar.event = event; + ar.currentline = line; + ar.i_ci = ci; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + L->allowhook = 0; /* cannot call hooks inside a hook */ + ci->callstatus |= CIST_HOOKED; + lua_unlock(L); + (*hook)(L, &ar); + lua_lock(L); + lua_assert(!L->allowhook); + L->allowhook = 1; + ci->top = restorestack(L, ci_top); + L->top = restorestack(L, top); + ci->callstatus &= ~CIST_HOOKED; + } +} + + +static void callhook (lua_State *L, CallInfo *ci) { + int hook = LUA_HOOKCALL; + ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ + if (isLua(ci->previous) && + GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { + ci->callstatus |= CIST_TAIL; + hook = LUA_HOOKTAILCALL; + } + luaD_hook(L, hook, -1); + ci->u.l.savedpc--; /* correct 'pc' */ +} + + +static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { + int i; + int nfixargs = p->numparams; + StkId base, fixed; + lua_assert(actual >= nfixargs); + /* move fixed parameters to final position */ + luaD_checkstack(L, p->maxstacksize); /* check again for new 'base' */ + fixed = L->top - actual; /* first fixed argument */ + base = L->top; /* final position of first argument */ + for (i=0; itop++, fixed + i); + setnilvalue(fixed + i); + } + 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 next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) + + +/* +** returns true if function has been executed (C function) +*/ +int luaD_precall (lua_State *L, StkId func, int nresults) { + lua_CFunction f; + CallInfo *ci; + int n; /* number of arguments (Lua) or returns (C) */ + ptrdiff_t funcr = savestack(L, func); + switch (ttype(func)) { + case LUA_TLCF: /* light C function */ + f = fvalue(func); + goto Cfunc; + case LUA_TCCL: { /* C closure */ + f = clCvalue(func)->f; + Cfunc: + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = restorestack(L, funcr); + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->callstatus = 0; + luaC_checkGC(L); /* stack grow uses memory */ + if (L->hookmask & LUA_MASKCALL) + luaD_hook(L, LUA_HOOKCALL, -1); + lua_unlock(L); + n = (*f)(L); /* do the actual call */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, L->top - n); + return 1; + } + case LUA_TLCL: { /* Lua function: prepare its call */ + StkId base; + Proto *p = clLvalue(func)->p; + n = cast_int(L->top - func) - 1; /* number of real arguments */ + luaD_checkstack(L, p->maxstacksize); + for (; n < p->numparams; n++) + setnilvalue(L->top++); /* complete missing arguments */ + if (!p->is_vararg) { + func = restorestack(L, funcr); + base = func + 1; + } + else { + base = adjust_varargs(L, p, n); + func = restorestack(L, funcr); /* previous call can change stack */ + } + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = func; + ci->u.l.base = base; + ci->top = base + p->maxstacksize; + lua_assert(ci->top <= L->stack_last); + ci->u.l.savedpc = p->code; /* starting point */ + ci->callstatus = CIST_LUA; + L->top = ci->top; + luaC_checkGC(L); /* stack grow uses memory */ + if (L->hookmask & LUA_MASKCALL) + callhook(L, ci); + return 0; + } + default: { /* not a function */ + func = tryfuncTM(L, func); /* retry with 'function' tag method */ + return luaD_precall(L, func, nresults); /* now it must be a function */ + } + } +} + + +int luaD_poscall (lua_State *L, StkId firstResult) { + StkId res; + int wanted, i; + CallInfo *ci = L->ci; + if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { + if (L->hookmask & LUA_MASKRET) { + ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ + luaD_hook(L, LUA_HOOKRET, -1); + firstResult = restorestack(L, fr); + } + L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ + } + res = ci->func; /* res == final position of 1st result */ + wanted = ci->nresults; + L->ci = ci = ci->previous; /* back to caller */ + /* 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, int allowyield) { + 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 (!allowyield) L->nny++; + if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ + luaV_execute(L); /* call it */ + if (!allowyield) L->nny--; + L->nCcalls--; +} + + +static void finishCcall (lua_State *L) { + CallInfo *ci = L->ci; + int n; + lua_assert(ci->u.c.k != NULL); /* must have a continuation */ + lua_assert(L->nny == 0); + if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ + ci->callstatus &= ~CIST_YPCALL; /* finish 'lua_pcall' */ + L->errfunc = ci->u.c.old_errfunc; + } + /* finish 'lua_callk'/'lua_pcall' */ + adjustresults(L, ci->nresults); + /* call continuation function */ + if (!(ci->callstatus & CIST_STAT)) /* no call status? */ + ci->u.c.status = LUA_YIELD; /* 'default' status */ + lua_assert(ci->u.c.status != LUA_OK); + ci->callstatus = (ci->callstatus & ~(CIST_YPCALL | CIST_STAT)) | CIST_YIELDED; + lua_unlock(L); + n = (*ci->u.c.k)(L); + lua_lock(L); + api_checknelems(L, n); + /* finish 'luaD_precall' */ + luaD_poscall(L, L->top - n); +} + + +static void unroll (lua_State *L, void *ud) { + UNUSED(ud); + for (;;) { + if (L->ci == &L->base_ci) /* stack is empty? */ + return; /* coroutine finished normally */ + if (!isLua(L->ci)) /* C function? */ + finishCcall(L); + else { /* Lua function */ + luaV_finishOp(L); /* finish interrupted instruction */ + luaV_execute(L); /* execute down to higher C 'boundary' */ + } + } +} + + +/* +** check whether thread has a suspended protected call +*/ +static CallInfo *findpcall (lua_State *L) { + CallInfo *ci; + for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ + if (ci->callstatus & CIST_YPCALL) + return ci; + } + return NULL; /* no pending pcall */ +} + + +static int recover (lua_State *L, int status) { + StkId oldtop; + CallInfo *ci = findpcall(L); + if (ci == NULL) return 0; /* no recovery point */ + /* "finish" luaD_pcall */ + oldtop = restorestack(L, ci->extra); + luaF_close(L, oldtop); + seterrorobj(L, status, oldtop); + L->ci = ci; + L->allowhook = ci->u.c.old_allowhook; + L->nny = 0; /* should be zero to be yieldable */ + luaD_shrinkstack(L); + L->errfunc = ci->u.c.old_errfunc; + ci->callstatus |= CIST_STAT; /* call has error status */ + ci->u.c.status = status; /* (here it is) */ + return 1; /* continue running the coroutine */ +} + + +/* +** signal an error in the call to 'resume', not in the execution of the +** coroutine itself. (Such errors should not be handled by any coroutine +** error handler and should not kill the coroutine.) +*/ +static l_noret resume_error (lua_State *L, const char *msg, StkId firstArg) { + L->top = firstArg; /* remove args from the stack */ + setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ + api_incr_top(L); + luaD_throw(L, -1); /* jump back to 'lua_resume' */ +} + + +/* +** do the work for 'lua_resume' in protected mode +*/ +static void resume (lua_State *L, void *ud) { + int nCcalls = L->nCcalls; + StkId firstArg = cast(StkId, ud); + CallInfo *ci = L->ci; + if (nCcalls >= LUAI_MAXCCALLS) + resume_error(L, "C stack overflow", firstArg); + if (L->status == LUA_OK) { /* may be starting a coroutine */ + if (ci != &L->base_ci) /* not in base level? */ + resume_error(L, "cannot resume non-suspended coroutine", firstArg); + /* coroutine is in base level; start running it */ + if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ + luaV_execute(L); /* call it */ + } + else if (L->status != LUA_YIELD) + resume_error(L, "cannot resume dead coroutine", firstArg); + else { /* resuming from previous yield */ + L->status = LUA_OK; + ci->func = restorestack(L, ci->extra); + if (isLua(ci)) /* yielded inside a hook? */ + luaV_execute(L); /* just continue running Lua code */ + else { /* 'common' yield */ + if (ci->u.c.k != NULL) { /* does it have a continuation? */ + int n; + ci->u.c.status = LUA_YIELD; /* 'default' status */ + ci->callstatus |= CIST_YIELDED; + lua_unlock(L); + n = (*ci->u.c.k)(L); /* call continuation */ + lua_lock(L); + api_checknelems(L, n); + firstArg = L->top - n; /* yield results come from continuation */ + } + luaD_poscall(L, firstArg); /* finish 'luaD_precall' */ + } + unroll(L, NULL); + } + lua_assert(nCcalls == L->nCcalls); +} + + +LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { + int status; + int oldnny = L->nny; /* save 'nny' */ + lua_lock(L); + luai_userstateresume(L, nargs); + L->nCcalls = (from) ? from->nCcalls + 1 : 1; + L->nny = 0; /* allow yields */ + api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); + status = luaD_rawrunprotected(L, resume, L->top - nargs); + if (status == -1) /* error calling 'lua_resume'? */ + status = LUA_ERRRUN; + else { /* yield or regular error */ + while (status != LUA_OK && status != LUA_YIELD) { /* error? */ + if (recover(L, status)) /* recover point? */ + status = luaD_rawrunprotected(L, unroll, NULL); /* run continuation */ + else { /* unrecoverable error */ + L->status = cast_byte(status); /* mark thread as `dead' */ + seterrorobj(L, status, L->top); + L->ci->top = L->top; + break; + } + } + lua_assert(status == L->status); + } + L->nny = oldnny; /* restore 'nny' */ + L->nCcalls--; + lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); + lua_unlock(L); + return status; +} + + +LUA_API int lua_yieldk (lua_State *L, int nresults, int ctx, lua_CFunction k) { + CallInfo *ci = L->ci; + luai_userstateyield(L, nresults); + lua_lock(L); + api_checknelems(L, nresults); + if (L->nny > 0) { + if (L != G(L)->mainthread) + luaG_runerror(L, "attempt to yield across a C-call boundary"); + else + luaG_runerror(L, "attempt to yield from outside a coroutine"); + } + L->status = LUA_YIELD; + ci->extra = savestack(L, ci->func); /* save current 'func' */ + if (isLua(ci)) { /* inside a hook? */ + api_check(L, k == NULL, "hooks cannot continue after yielding"); + } + else { + if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ + ci->u.c.ctx = ctx; /* save context */ + ci->func = L->top - nresults - 1; /* protect stack below results */ + luaD_throw(L, LUA_YIELD); + } + lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ + lua_unlock(L); + return 0; /* return to 'luaD_hook' */ +} + + +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t old_top, ptrdiff_t ef) { + int status; + CallInfo *old_ci = L->ci; + lu_byte old_allowhooks = L->allowhook; + unsigned short old_nny = L->nny; + ptrdiff_t old_errfunc = L->errfunc; + L->errfunc = ef; + status = luaD_rawrunprotected(L, func, u); + if (status != LUA_OK) { /* an error occurred? */ + StkId oldtop = restorestack(L, old_top); + luaF_close(L, oldtop); /* close possible pending closures */ + seterrorobj(L, status, oldtop); + L->ci = old_ci; + L->allowhook = old_allowhooks; + L->nny = old_nny; + luaD_shrinkstack(L); + } + L->errfunc = old_errfunc; + return status; +} + + + +/* +** Execute a protected parser. +*/ +struct SParser { /* data to `f_parser' */ + ZIO *z; + Mbuffer buff; /* dynamic structure used by the scanner */ + Dyndata dyd; /* dynamic structures used by the parser */ + const char *mode; + const char *name; +}; + + +static void checkmode (lua_State *L, const char *mode, const char *x) { + if (mode && strchr(mode, x[0]) == NULL) { + luaO_pushfstring(L, + "attempt to load a %s chunk (mode is " LUA_QS ")", x, mode); + luaD_throw(L, LUA_ERRSYNTAX); + } +} + + +static void f_parser (lua_State *L, void *ud) { + int i; + Closure *cl; + struct SParser *p = cast(struct SParser *, ud); + int c = zgetc(p->z); /* read first character */ + if (c == LUA_SIGNATURE[0]) { + checkmode(L, p->mode, "binary"); + cl = luaU_undump(L, p->z, &p->buff, p->name); + } + else { + checkmode(L, p->mode, "text"); + cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); + } + lua_assert(cl->l.nupvalues == cl->l.p->sizeupvalues); + for (i = 0; i < cl->l.nupvalues; i++) { /* initialize upvalues */ + UpVal *up = luaF_newupval(L); + cl->l.upvals[i] = up; + luaC_objbarrier(L, cl, up); + } +} + + +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode) { + struct SParser p; + int status; + L->nny++; /* cannot yield during parsing */ + p.z = z; p.name = name; p.mode = mode; + p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; + p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; + p.dyd.label.arr = NULL; p.dyd.label.size = 0; + luaZ_initbuffer(L, &p.buff); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + luaZ_freebuffer(L, &p.buff); + luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); + luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); + luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); + L->nny--; + return status; +} + + diff --git a/lua/ldo.h b/lua/ldo.h new file mode 100644 index 0000000..d3d3082 --- /dev/null +++ b/lua/ldo.h @@ -0,0 +1,46 @@ +/* +** $Id: ldo.h,v 2.20.1.1 2013/04/12 18:48:47 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 (L->stack_last - L->top <= (n)) \ + luaD_growstack(L, n); else condmovestack(L); + + +#define incr_top(L) {L->top++; luaD_checkstack(L,0);} + +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) + + +/* 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, + const char *mode); +LUAI_FUNC void luaD_hook (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, + int allowyield); +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_reallocstack (lua_State *L, int newsize); +LUAI_FUNC void luaD_growstack (lua_State *L, int n); +LUAI_FUNC void luaD_shrinkstack (lua_State *L); + +LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); +LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); + +#endif + diff --git a/lua/ldump.c b/lua/ldump.c new file mode 100644 index 0000000..61fa2cd --- /dev/null +++ b/lua/ldump.c @@ -0,0 +1,173 @@ +/* +** $Id: ldump.c,v 2.17.1.1 2013/04/12 18:48:47 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) + { + 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*sizeof(char),D); + } +} + +#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) + +static void DumpFunction(const Proto* f, DumpState* D); + +static void DumpConstants(const Proto* f, DumpState* D) +{ + int i,n=f->sizek; + DumpInt(n,D); + for (i=0; ik[i]; + DumpChar(ttypenv(o),D); + switch (ttypenv(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); + } + } + n=f->sizep; + DumpInt(n,D); + for (i=0; ip[i],D); +} + +static void DumpUpvalues(const Proto* f, DumpState* D) +{ + int i,n=f->sizeupvalues; + DumpInt(n,D); + for (i=0; iupvalues[i].instack,D); + DumpChar(f->upvalues[i].idx,D); + } +} + +static void DumpDebug(const Proto* f, DumpState* D) +{ + int i,n; + DumpString((D->strip) ? NULL : f->source,D); + 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].name,D); +} + +static void DumpFunction(const Proto* f, DumpState* D) +{ + DumpInt(f->linedefined,D); + DumpInt(f->lastlinedefined,D); + DumpChar(f->numparams,D); + DumpChar(f->is_vararg,D); + DumpChar(f->maxstacksize,D); + DumpCode(f,D); + DumpConstants(f,D); + DumpUpvalues(f,D); + DumpDebug(f,D); +} + +static void DumpHeader(DumpState* D) +{ + lu_byte 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,&D); + return D.status; +} diff --git a/lua/lfunc.c b/lua/lfunc.c new file mode 100644 index 0000000..e90e152 --- /dev/null +++ b/lua/lfunc.c @@ -0,0 +1,161 @@ +/* +** $Id: lfunc.c,v 2.30.1.1 2013/04/12 18:48:47 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 n) { + Closure *c = &luaC_newobj(L, LUA_TCCL, sizeCclosure(n), NULL, 0)->cl; + c->c.nupvalues = cast_byte(n); + return c; +} + + +Closure *luaF_newLclosure (lua_State *L, int n) { + Closure *c = &luaC_newobj(L, LUA_TLCL, sizeLclosure(n), NULL, 0)->cl; + c->l.p = NULL; + c->l.nupvalues = cast_byte(n); + while (n--) c->l.upvals[n] = NULL; + return c; +} + + +UpVal *luaF_newupval (lua_State *L) { + UpVal *uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), NULL, 0)->uv; + 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 = gco2uv(*pp))->v >= level) { + GCObject *o = obj2gco(p); + lua_assert(p->v != &p->u.value); + lua_assert(!isold(o) || isold(obj2gco(L))); + if (p->v == level) { /* found a corresponding upvalue? */ + if (isdead(g, o)) /* is it dead? */ + changewhite(o); /* resurrect it */ + return p; + } + pp = &p->next; + } + /* not found: create a new one */ + uv = &luaC_newobj(L, LUA_TUPVAL, sizeof(UpVal), pp, 0)->uv; + uv->v = level; /* current value lives in the stack */ + 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 = gco2uv(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); /* remove upvalue from 'uvhead' list */ + setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ + uv->v = &uv->u.value; /* now current value lives here */ + gch(o)->next = g->allgc; /* link upvalue into 'allgc' list */ + g->allgc = o; + luaC_checkupvalcolor(g, uv); + } + } +} + + +Proto *luaF_newproto (lua_State *L) { + Proto *f = &luaC_newobj(L, LUA_TPROTO, sizeof(Proto), NULL, 0)->p; + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->cache = NULL; + f->sizecode = 0; + f->lineinfo = NULL; + f->sizelineinfo = 0; + f->upvalues = NULL; + f->sizeupvalues = 0; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->locvars = NULL; + f->sizelocvars = 0; + 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); + luaM_freearray(L, f->p, f->sizep); + luaM_freearray(L, f->k, f->sizek); + luaM_freearray(L, f->lineinfo, f->sizelineinfo); + luaM_freearray(L, f->locvars, f->sizelocvars); + luaM_freearray(L, f->upvalues, f->sizeupvalues); + luaM_free(L, f); +} + + +/* +** 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 */ +} + diff --git a/lua/lfunc.h b/lua/lfunc.h new file mode 100644 index 0000000..ca0d3a3 --- /dev/null +++ b/lua/lfunc.h @@ -0,0 +1,33 @@ +/* +** $Id: lfunc.h,v 2.8.1.1 2013/04/12 18:48:47 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); +LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems); +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_freeupval (lua_State *L, UpVal *uv); +LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, + int pc); + + +#endif diff --git a/lua/lgc.c b/lua/lgc.c new file mode 100644 index 0000000..52460dc --- /dev/null +++ b/lua/lgc.c @@ -0,0 +1,1220 @@ +/* +** $Id: lgc.c,v 2.140.1.2 2013/04/26 18:22:05 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" + + + +/* +** cost of sweeping one element (the size of a small object divided +** by some adjust for the sweep speed) +*/ +#define GCSWEEPCOST ((sizeof(TString) + 4) / 4) + +/* maximum number of elements to sweep in each single step */ +#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) + +/* maximum number of finalizers to call in each GC step */ +#define GCFINALIZENUM 4 + + +/* +** macro to adjust 'stepmul': 'stepmul' is actually used like +** 'stepmul / STEPMULADJ' (value chosen by tests) +*/ +#define STEPMULADJ 200 + + +/* +** macro to adjust 'pause': 'pause' is actually used like +** 'pause / PAUSEADJ' (value chosen by tests) +*/ +#define PAUSEADJ 100 + + +/* +** 'makewhite' erases all color bits plus the old bit and then +** sets only the current white bit +*/ +#define maskcolors (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS)) +#define makewhite(g,x) \ + (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) + +#define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) +#define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) + + +#define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) + +#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) + + +#define checkconsistency(obj) \ + lua_longassert(!iscollectable(obj) || righttt(obj)) + + +#define markvalue(g,o) { checkconsistency(o); \ + if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } + +#define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ + reallymarkobject(g, obj2gco(t)); } + +static void reallymarkobject (global_State *g, GCObject *o); + + +/* +** {====================================================== +** Generic functions +** ======================================================= +*/ + + +/* +** one after last element in a hash array +*/ +#define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) + + +/* +** link table 'h' into list pointed by 'p' +*/ +#define linktable(h,p) ((h)->gclist = *(p), *(p) = obj2gco(h)) + + +/* +** if key is not marked, mark its entry as dead (therefore removing it +** from the table) +*/ +static void removeentry (Node *n) { + lua_assert(ttisnil(gval(n))); + if (valiswhite(gkey(n))) + setdeadvalue(gkey(n)); /* unused and unmarked key; remove it */ +} + + +/* +** 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 objects +** being finalized, keep them in keys, but not in values +*/ +static int iscleared (global_State *g, const TValue *o) { + if (!iscollectable(o)) return 0; + else if (ttisstring(o)) { + markobject(g, rawtsvalue(o)); /* strings are `values', so are never weak */ + return 0; + } + else return iswhite(gcvalue(o)); +} + + +/* +** barrier that moves collector forward, that is, mark the white object +** being pointed by a black object. +*/ +void luaC_barrier_ (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 != GCSpause); + lua_assert(gch(o)->tt != LUA_TTABLE); + if (keepinvariantout(g)) /* must keep invariant? */ + reallymarkobject(g, v); /* restore invariant */ + else { /* sweep phase */ + lua_assert(issweepphase(g)); + makewhite(g, o); /* mark main obj. as white to avoid other barriers */ + } +} + + +/* +** barrier that moves collector backward, that is, mark the black object +** pointing to a white object as gray again. (Current implementation +** only works for tables; access to 'gclist' is not uniform across +** different types.) +*/ +void luaC_barrierback_ (lua_State *L, GCObject *o) { + global_State *g = G(L); + lua_assert(isblack(o) && !isdead(g, o) && gch(o)->tt == LUA_TTABLE); + black2gray(o); /* make object gray (again) */ + gco2t(o)->gclist = g->grayagain; + g->grayagain = o; +} + + +/* +** barrier for prototypes. When creating first closure (cache is +** NULL), use a forward barrier; this may be the only closure of the +** prototype (if it is a "regular" function, with a single instance) +** and the prototype may be big, so it is better to avoid traversing +** it again. Otherwise, use a backward barrier, to avoid marking all +** possible instances. +*/ +LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c) { + global_State *g = G(L); + lua_assert(isblack(obj2gco(p))); + if (p->cache == NULL) { /* first time? */ + luaC_objbarrier(L, p, c); + } + else { /* use a backward barrier */ + black2gray(obj2gco(p)); /* make prototype gray (again) */ + p->gclist = g->grayagain; + g->grayagain = obj2gco(p); + } +} + + +/* +** check color (and invariants) for an upvalue that was closed, +** i.e., moved into the 'allgc' list +*/ +void luaC_checkupvalcolor (global_State *g, UpVal *uv) { + GCObject *o = obj2gco(uv); + lua_assert(!isblack(o)); /* open upvalues are never black */ + if (isgray(o)) { + if (keepinvariant(g)) { + resetoldbit(o); /* see MOVE OLD rule */ + gray2black(o); /* it is being visited now */ + markvalue(g, uv->v); + } + else { + lua_assert(issweepphase(g)); + makewhite(g, o); + } + } +} + + +/* +** create a new collectable object (with given type and size) and link +** it to '*list'. 'offset' tells how many bytes to allocate before the +** object itself (used only by states). +*/ +GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, GCObject **list, + int offset) { + global_State *g = G(L); + char *raw = cast(char *, luaM_newobject(L, novariant(tt), sz)); + GCObject *o = obj2gco(raw + offset); + if (list == NULL) + list = &g->allgc; /* standard list for collectable objects */ + gch(o)->marked = luaC_white(g); + gch(o)->tt = tt; + gch(o)->next = *list; + *list = o; + return o; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Mark functions +** ======================================================= +*/ + + +/* +** mark an object. Userdata, strings, and closed upvalues are visited +** and turned black here. Other objects are marked gray and added +** to appropriate list to be visited (and turned black) later. (Open +** upvalues are already linked in 'headuv' list.) +*/ +static void reallymarkobject (global_State *g, GCObject *o) { + lu_mem size; + white2gray(o); + switch (gch(o)->tt) { + case LUA_TSHRSTR: + case LUA_TLNGSTR: { + size = sizestring(gco2ts(o)); + break; /* nothing else to mark; make it black */ + } + case LUA_TUSERDATA: { + Table *mt = gco2u(o)->metatable; + markobject(g, mt); + markobject(g, gco2u(o)->env); + size = sizeudata(gco2u(o)); + break; + } + case LUA_TUPVAL: { + UpVal *uv = gco2uv(o); + markvalue(g, uv->v); + if (uv->v != &uv->u.value) /* open? */ + return; /* open upvalues remain gray */ + size = sizeof(UpVal); + break; + } + case LUA_TLCL: { + gco2lcl(o)->gclist = g->gray; + g->gray = o; + return; + } + case LUA_TCCL: { + gco2ccl(o)->gclist = g->gray; + g->gray = o; + return; + } + case LUA_TTABLE: { + linktable(gco2t(o), &g->gray); + return; + } + case LUA_TTHREAD: { + gco2th(o)->gclist = g->gray; + g->gray = o; + return; + } + case LUA_TPROTO: { + gco2p(o)->gclist = g->gray; + g->gray = o; + return; + } + default: lua_assert(0); return; + } + gray2black(o); + g->GCmemtrav += size; +} + + +/* +** mark metamethods for basic types +*/ +static void markmt (global_State *g) { + int i; + for (i=0; i < LUA_NUMTAGS; i++) + markobject(g, g->mt[i]); +} + + +/* +** mark all objects in list of being-finalized +*/ +static void markbeingfnz (global_State *g) { + GCObject *o; + for (o = g->tobefnz; o != NULL; o = gch(o)->next) { + makewhite(g, o); + reallymarkobject(g, o); + } +} + + +/* +** mark all values stored in marked open upvalues. (See comment in +** 'lstate.h'.) +*/ +static void remarkupvals (global_State *g) { + UpVal *uv; + for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { + if (isgray(obj2gco(uv))) + markvalue(g, uv->v); + } +} + + +/* +** mark root set and reset all gray lists, to start a new +** incremental (or full) collection +*/ +static void restartcollection (global_State *g) { + g->gray = g->grayagain = NULL; + g->weak = g->allweak = g->ephemeron = NULL; + markobject(g, g->mainthread); + markvalue(g, &g->l_registry); + markmt(g); + markbeingfnz(g); /* mark any finalizing object left from previous cycle */ +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Traverse functions +** ======================================================= +*/ + +static void traverseweakvalue (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + /* if there is array part, assume it may have white values (do not + traverse it just to check) */ + int hasclears = (h->sizearray > 0); + for (n = gnode(h, 0); n < limit; n++) { + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else { + lua_assert(!ttisnil(gkey(n))); + markvalue(g, gkey(n)); /* mark key */ + if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ + hasclears = 1; /* table will have to be cleared */ + } + } + if (hasclears) + linktable(h, &g->weak); /* has to be cleared later */ + else /* no white values */ + linktable(h, &g->grayagain); /* no need to clean */ +} + + +static int traverseephemeron (global_State *g, Table *h) { + int marked = 0; /* true if an object is marked in this traversal */ + int hasclears = 0; /* true if table has white keys */ + int prop = 0; /* true if table has entry "white-key -> white-value" */ + Node *n, *limit = gnodelast(h); + int i; + /* traverse array part (numeric keys are 'strong') */ + for (i = 0; i < h->sizearray; i++) { + if (valiswhite(&h->array[i])) { + marked = 1; + reallymarkobject(g, gcvalue(&h->array[i])); + } + } + /* traverse hash part */ + for (n = gnode(h, 0); n < limit; n++) { + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */ + hasclears = 1; /* table must be cleared */ + if (valiswhite(gval(n))) /* value not marked yet? */ + prop = 1; /* must propagate again */ + } + else if (valiswhite(gval(n))) { /* value not marked yet? */ + marked = 1; + reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ + } + } + if (prop) + linktable(h, &g->ephemeron); /* have to propagate again */ + else if (hasclears) /* does table have white keys? */ + linktable(h, &g->allweak); /* may have to clean white keys */ + else /* no white keys */ + linktable(h, &g->grayagain); /* no need to clean */ + return marked; +} + + +static void traversestrongtable (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + int i; + for (i = 0; i < h->sizearray; i++) /* traverse array part */ + markvalue(g, &h->array[i]); + for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else { + lua_assert(!ttisnil(gkey(n))); + markvalue(g, gkey(n)); /* mark key */ + markvalue(g, gval(n)); /* mark value */ + } + } +} + + +static lu_mem traversetable (global_State *g, Table *h) { + const char *weakkey, *weakvalue; + const TValue *mode = gfasttm(g, h->metatable, TM_MODE); + markobject(g, h->metatable); + if (mode && ttisstring(mode) && /* is there a weak mode? */ + ((weakkey = strchr(svalue(mode), 'k')), + (weakvalue = strchr(svalue(mode), 'v')), + (weakkey || weakvalue))) { /* is really weak? */ + black2gray(obj2gco(h)); /* keep table gray */ + if (!weakkey) /* strong keys? */ + traverseweakvalue(g, h); + else if (!weakvalue) /* strong values? */ + traverseephemeron(g, h); + else /* all weak */ + linktable(h, &g->allweak); /* nothing to traverse now */ + } + else /* not weak */ + traversestrongtable(g, h); + return sizeof(Table) + sizeof(TValue) * h->sizearray + + sizeof(Node) * cast(size_t, sizenode(h)); +} + + +static int traverseproto (global_State *g, Proto *f) { + int i; + if (f->cache && iswhite(obj2gco(f->cache))) + f->cache = NULL; /* allow cache to be collected */ + markobject(g, f->source); + for (i = 0; i < f->sizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ + markobject(g, f->upvalues[i].name); + for (i = 0; i < f->sizep; i++) /* mark nested protos */ + markobject(g, f->p[i]); + for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ + markobject(g, f->locvars[i].varname); + return sizeof(Proto) + sizeof(Instruction) * f->sizecode + + sizeof(Proto *) * f->sizep + + sizeof(TValue) * f->sizek + + sizeof(int) * f->sizelineinfo + + sizeof(LocVar) * f->sizelocvars + + sizeof(Upvaldesc) * f->sizeupvalues; +} + + +static lu_mem traverseCclosure (global_State *g, CClosure *cl) { + int i; + for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ + markvalue(g, &cl->upvalue[i]); + return sizeCclosure(cl->nupvalues); +} + +static lu_mem traverseLclosure (global_State *g, LClosure *cl) { + int i; + markobject(g, cl->p); /* mark its prototype */ + for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ + markobject(g, cl->upvals[i]); + return sizeLclosure(cl->nupvalues); +} + + +static lu_mem traversestack (global_State *g, lua_State *th) { + int n = 0; + StkId o = th->stack; + if (o == NULL) + return 1; /* stack not completely built yet */ + for (; o < th->top; o++) /* mark live elements in the stack */ + markvalue(g, o); + if (g->gcstate == GCSatomic) { /* final traversal? */ + StkId lim = th->stack + th->stacksize; /* real end of stack */ + for (; o < lim; o++) /* clear not-marked stack slice */ + setnilvalue(o); + } + else { /* count call infos to compute size */ + CallInfo *ci; + for (ci = &th->base_ci; ci != th->ci; ci = ci->next) + n++; + } + return sizeof(lua_State) + sizeof(TValue) * th->stacksize + + sizeof(CallInfo) * n; +} + + +/* +** traverse one gray object, turning it to black (except for threads, +** which are always gray). +*/ +static void propagatemark (global_State *g) { + lu_mem size; + GCObject *o = g->gray; + lua_assert(isgray(o)); + gray2black(o); + switch (gch(o)->tt) { + case LUA_TTABLE: { + Table *h = gco2t(o); + g->gray = h->gclist; /* remove from 'gray' list */ + size = traversetable(g, h); + break; + } + case LUA_TLCL: { + LClosure *cl = gco2lcl(o); + g->gray = cl->gclist; /* remove from 'gray' list */ + size = traverseLclosure(g, cl); + break; + } + case LUA_TCCL: { + CClosure *cl = gco2ccl(o); + g->gray = cl->gclist; /* remove from 'gray' list */ + size = traverseCclosure(g, cl); + break; + } + case LUA_TTHREAD: { + lua_State *th = gco2th(o); + g->gray = th->gclist; /* remove from 'gray' list */ + th->gclist = g->grayagain; + g->grayagain = o; /* insert into 'grayagain' list */ + black2gray(o); + size = traversestack(g, th); + break; + } + case LUA_TPROTO: { + Proto *p = gco2p(o); + g->gray = p->gclist; /* remove from 'gray' list */ + size = traverseproto(g, p); + break; + } + default: lua_assert(0); return; + } + g->GCmemtrav += size; +} + + +static void propagateall (global_State *g) { + while (g->gray) propagatemark(g); +} + + +static void propagatelist (global_State *g, GCObject *l) { + lua_assert(g->gray == NULL); /* no grays left */ + g->gray = l; + propagateall(g); /* traverse all elements from 'l' */ +} + +/* +** retraverse all gray lists. Because tables may be reinserted in other +** lists when traversed, traverse the original lists to avoid traversing +** twice the same table (which is not wrong, but inefficient) +*/ +static void retraversegrays (global_State *g) { + GCObject *weak = g->weak; /* save original lists */ + GCObject *grayagain = g->grayagain; + GCObject *ephemeron = g->ephemeron; + g->weak = g->grayagain = g->ephemeron = NULL; + propagateall(g); /* traverse main gray list */ + propagatelist(g, grayagain); + propagatelist(g, weak); + propagatelist(g, ephemeron); +} + + +static void convergeephemerons (global_State *g) { + int changed; + do { + GCObject *w; + GCObject *next = g->ephemeron; /* get ephemeron list */ + g->ephemeron = NULL; /* tables will return to this list when traversed */ + changed = 0; + while ((w = next) != NULL) { + next = gco2t(w)->gclist; + if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */ + propagateall(g); /* propagate changes */ + changed = 1; /* will have to revisit all ephemeron tables */ + } + } + } while (changed); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Sweep Functions +** ======================================================= +*/ + + +/* +** clear entries with unmarked keys from all weaktables in list 'l' up +** to element 'f' +*/ +static void clearkeys (global_State *g, GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* and remove entry from table */ + } + } + } +} + + +/* +** clear entries with unmarked values from all weaktables in list 'l' up +** to element 'f' +*/ +static void clearvalues (global_State *g, GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + int i; + for (i = 0; i < h->sizearray; i++) { + TValue *o = &h->array[i]; + if (iscleared(g, o)) /* value was collected? */ + setnilvalue(o); /* remove value */ + } + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && iscleared(g, gval(n))) { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* and remove entry from table */ + } + } + } +} + + +static void freeobj (lua_State *L, GCObject *o) { + switch (gch(o)->tt) { + case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; + case LUA_TLCL: { + luaM_freemem(L, o, sizeLclosure(gco2lcl(o)->nupvalues)); + break; + } + case LUA_TCCL: { + luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); + break; + } + case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; + case LUA_TTABLE: luaH_free(L, gco2t(o)); break; + case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; + case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; + case LUA_TSHRSTR: + G(L)->strt.nuse--; + /* go through */ + case LUA_TLNGSTR: { + luaM_freemem(L, o, sizestring(gco2ts(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); + + +/* +** sweep the (open) upvalues of a thread and resize its stack and +** list of call-info structures. +*/ +static void sweepthread (lua_State *L, lua_State *L1) { + if (L1->stack == NULL) return; /* stack not completely built yet */ + sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ + luaE_freeCI(L1); /* free extra CallInfo slots */ + /* should not change the stack during an emergency gc cycle */ + if (G(L)->gckind != KGC_EMERGENCY) + luaD_shrinkstack(L1); +} + + +/* +** sweep at most 'count' elements from a list of GCObjects erasing dead +** objects, where a dead (not alive) object is one marked with the "old" +** (non current) white and not fixed. +** In non-generational mode, change all non-dead objects back to white, +** preparing for next collection cycle. +** In generational mode, keep black objects black, and also mark them as +** old; stop when hitting an old object, as all objects after that +** one will be old too. +** When object is a thread, sweep its list of open upvalues too. +*/ +static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { + global_State *g = G(L); + int ow = otherwhite(g); + int toclear, toset; /* bits to clear and to set in all live objects */ + int tostop; /* stop sweep when this is true */ + if (isgenerational(g)) { /* generational mode? */ + toclear = ~0; /* clear nothing */ + toset = bitmask(OLDBIT); /* set the old bit of all surviving objects */ + tostop = bitmask(OLDBIT); /* do not sweep old generation */ + } + else { /* normal mode */ + toclear = maskcolors; /* clear all color bits + old bit */ + toset = luaC_white(g); /* make object white */ + tostop = 0; /* do not stop */ + } + while (*p != NULL && count-- > 0) { + GCObject *curr = *p; + int marked = gch(curr)->marked; + if (isdeadm(ow, marked)) { /* is 'curr' dead? */ + *p = gch(curr)->next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + else { + if (testbits(marked, tostop)) + return NULL; /* stop sweeping this list */ + if (gch(curr)->tt == LUA_TTHREAD) + sweepthread(L, gco2th(curr)); /* sweep thread's upvalues */ + /* update marks */ + gch(curr)->marked = cast_byte((marked & toclear) | toset); + p = &gch(curr)->next; /* go to next element */ + } + } + return (*p == NULL) ? NULL : p; +} + + +/* +** sweep a list until a live object (or end of list) +*/ +static GCObject **sweeptolive (lua_State *L, GCObject **p, int *n) { + GCObject ** old = p; + int i = 0; + do { + i++; + p = sweeplist(L, p, 1); + } while (p == old); + if (n) *n += i; + return p; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Finalization +** ======================================================= +*/ + +static void checkSizes (lua_State *L) { + global_State *g = G(L); + if (g->gckind != KGC_EMERGENCY) { /* do not change sizes in emergency */ + int hs = g->strt.size / 2; /* half the size of the string table */ + if (g->strt.nuse < cast(lu_int32, hs)) /* using less than that half? */ + luaS_resize(L, hs); /* halve its size */ + luaZ_freebuffer(L, &g->buff); /* free concatenation buffer */ + } +} + + +static GCObject *udata2finalize (global_State *g) { + GCObject *o = g->tobefnz; /* get first element */ + lua_assert(isfinalized(o)); + g->tobefnz = gch(o)->next; /* remove it from 'tobefnz' list */ + gch(o)->next = g->allgc; /* return it to 'allgc' list */ + g->allgc = o; + resetbit(gch(o)->marked, SEPARATED); /* mark that it is not in 'tobefnz' */ + lua_assert(!isold(o)); /* see MOVE OLD rule */ + if (!keepinvariantout(g)) /* not keeping invariant? */ + makewhite(g, o); /* "sweep" object */ + return o; +} + + +static void dothecall (lua_State *L, void *ud) { + UNUSED(ud); + luaD_call(L, L->top - 2, 0, 0); +} + + +static void GCTM (lua_State *L, int propagateerrors) { + global_State *g = G(L); + const TValue *tm; + TValue v; + setgcovalue(L, &v, udata2finalize(g)); + tm = luaT_gettmbyobj(L, &v, TM_GC); + if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ + int status; + lu_byte oldah = L->allowhook; + int running = g->gcrunning; + L->allowhook = 0; /* stop debug hooks during GC metamethod */ + g->gcrunning = 0; /* avoid GC steps */ + setobj2s(L, L->top, tm); /* push finalizer... */ + setobj2s(L, L->top + 1, &v); /* ... and its argument */ + L->top += 2; /* and (next line) call the finalizer */ + status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); + L->allowhook = oldah; /* restore hooks */ + g->gcrunning = running; /* restore state */ + if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ + if (status == LUA_ERRRUN) { /* is there an error object? */ + const char *msg = (ttisstring(L->top - 1)) + ? svalue(L->top - 1) + : "no message"; + luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); + status = LUA_ERRGCMM; /* error in __gc metamethod */ + } + luaD_throw(L, status); /* re-throw error */ + } + } +} + + +/* +** move all unreachable objects (or 'all' objects) that need +** finalization from list 'finobj' to list 'tobefnz' (to be finalized) +*/ +static void separatetobefnz (lua_State *L, int all) { + global_State *g = G(L); + GCObject **p = &g->finobj; + GCObject *curr; + GCObject **lastnext = &g->tobefnz; + /* find last 'next' field in 'tobefnz' list (to add elements in its end) */ + while (*lastnext != NULL) + lastnext = &gch(*lastnext)->next; + while ((curr = *p) != NULL) { /* traverse all finalizable objects */ + lua_assert(!isfinalized(curr)); + lua_assert(testbit(gch(curr)->marked, SEPARATED)); + if (!(iswhite(curr) || all)) /* not being collected? */ + p = &gch(curr)->next; /* don't bother with it */ + else { + l_setbit(gch(curr)->marked, FINALIZEDBIT); /* won't be finalized again */ + *p = gch(curr)->next; /* remove 'curr' from 'finobj' list */ + gch(curr)->next = *lastnext; /* link at the end of 'tobefnz' list */ + *lastnext = curr; + lastnext = &gch(curr)->next; + } + } +} + + +/* +** if object 'o' has a finalizer, remove it from 'allgc' list (must +** search the list to find it) and link it in 'finobj' list. +*/ +void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { + global_State *g = G(L); + if (testbit(gch(o)->marked, SEPARATED) || /* obj. is already separated... */ + isfinalized(o) || /* ... or is finalized... */ + gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ + return; /* nothing to be done */ + else { /* move 'o' to 'finobj' list */ + GCObject **p; + GCheader *ho = gch(o); + if (g->sweepgc == &ho->next) { /* avoid removing current sweep object */ + lua_assert(issweepphase(g)); + g->sweepgc = sweeptolive(L, g->sweepgc, NULL); + } + /* search for pointer pointing to 'o' */ + for (p = &g->allgc; *p != o; p = &gch(*p)->next) { /* empty */ } + *p = ho->next; /* remove 'o' from root list */ + ho->next = g->finobj; /* link it in list 'finobj' */ + g->finobj = o; + l_setbit(ho->marked, SEPARATED); /* mark it as such */ + if (!keepinvariantout(g)) /* not keeping invariant? */ + makewhite(g, o); /* "sweep" object */ + else + resetoldbit(o); /* see MOVE OLD rule */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** GC control +** ======================================================= +*/ + + +/* +** set a reasonable "time" to wait before starting a new GC cycle; +** cycle will start when memory use hits threshold +*/ +static void setpause (global_State *g, l_mem estimate) { + l_mem debt, threshold; + estimate = estimate / PAUSEADJ; /* adjust 'estimate' */ + threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ + ? estimate * g->gcpause /* no overflow */ + : MAX_LMEM; /* overflow; truncate to maximum */ + debt = -cast(l_mem, threshold - gettotalbytes(g)); + luaE_setdebt(g, debt); +} + + +#define sweepphases \ + (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) + + +/* +** enter first sweep phase (strings) and prepare pointers for other +** sweep phases. The calls to 'sweeptolive' make pointers point to an +** object inside the list (instead of to the header), so that the real +** sweep do not need to skip objects created between "now" and the start +** of the real sweep. +** Returns how many objects it swept. +*/ +static int entersweep (lua_State *L) { + global_State *g = G(L); + int n = 0; + g->gcstate = GCSsweepstring; + lua_assert(g->sweepgc == NULL && g->sweepfin == NULL); + /* prepare to sweep strings, finalizable objects, and regular objects */ + g->sweepstrgc = 0; + g->sweepfin = sweeptolive(L, &g->finobj, &n); + g->sweepgc = sweeptolive(L, &g->allgc, &n); + return n; +} + + +/* +** change GC mode +*/ +void luaC_changemode (lua_State *L, int mode) { + global_State *g = G(L); + if (mode == g->gckind) return; /* nothing to change */ + if (mode == KGC_GEN) { /* change to generational mode */ + /* make sure gray lists are consistent */ + luaC_runtilstate(L, bitmask(GCSpropagate)); + g->GCestimate = gettotalbytes(g); + g->gckind = KGC_GEN; + } + else { /* change to incremental mode */ + /* sweep all objects to turn them back to white + (as white has not changed, nothing extra will be collected) */ + g->gckind = KGC_NORMAL; + entersweep(L); + luaC_runtilstate(L, ~sweepphases); + } +} + + +/* +** call all pending finalizers +*/ +static void callallpendingfinalizers (lua_State *L, int propagateerrors) { + global_State *g = G(L); + while (g->tobefnz) { + resetoldbit(g->tobefnz); + GCTM(L, propagateerrors); + } +} + + +void luaC_freeallobjects (lua_State *L) { + global_State *g = G(L); + int i; + separatetobefnz(L, 1); /* separate all objects with finalizers */ + lua_assert(g->finobj == NULL); + callallpendingfinalizers(L, 0); + g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ + g->gckind = KGC_NORMAL; + sweepwholelist(L, &g->finobj); /* finalizers can create objs. in 'finobj' */ + sweepwholelist(L, &g->allgc); + for (i = 0; i < g->strt.size; i++) /* free all string lists */ + sweepwholelist(L, &g->strt.hash[i]); + lua_assert(g->strt.nuse == 0); +} + + +static l_mem atomic (lua_State *L) { + global_State *g = G(L); + l_mem work = -cast(l_mem, g->GCmemtrav); /* start counting work */ + GCObject *origweak, *origall; + lua_assert(!iswhite(obj2gco(g->mainthread))); + markobject(g, L); /* mark running thread */ + /* registry and global metatables may be changed by API */ + markvalue(g, &g->l_registry); + markmt(g); /* mark basic metatables */ + /* remark occasional upvalues of (maybe) dead threads */ + remarkupvals(g); + propagateall(g); /* propagate changes */ + work += g->GCmemtrav; /* stop counting (do not (re)count grays) */ + /* traverse objects caught by write barrier and by 'remarkupvals' */ + retraversegrays(g); + work -= g->GCmemtrav; /* restart counting */ + convergeephemerons(g); + /* at this point, all strongly accessible objects are marked. */ + /* clear values from weak tables, before checking finalizers */ + clearvalues(g, g->weak, NULL); + clearvalues(g, g->allweak, NULL); + origweak = g->weak; origall = g->allweak; + work += g->GCmemtrav; /* stop counting (objects being finalized) */ + separatetobefnz(L, 0); /* separate objects to be finalized */ + markbeingfnz(g); /* mark objects that will be finalized */ + propagateall(g); /* remark, to propagate `preserveness' */ + work -= g->GCmemtrav; /* restart counting */ + convergeephemerons(g); + /* at this point, all resurrected objects are marked. */ + /* remove dead objects from weak tables */ + clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */ + clearkeys(g, g->allweak, NULL); /* clear keys from all allweak tables */ + /* clear values from resurrected weak tables */ + clearvalues(g, g->weak, origweak); + clearvalues(g, g->allweak, origall); + g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ + work += g->GCmemtrav; /* complete counting */ + return work; /* estimate of memory marked by 'atomic' */ +} + + +static lu_mem singlestep (lua_State *L) { + global_State *g = G(L); + switch (g->gcstate) { + case GCSpause: { + /* start to count memory traversed */ + g->GCmemtrav = g->strt.size * sizeof(GCObject*); + lua_assert(!isgenerational(g)); + restartcollection(g); + g->gcstate = GCSpropagate; + return g->GCmemtrav; + } + case GCSpropagate: { + if (g->gray) { + lu_mem oldtrav = g->GCmemtrav; + propagatemark(g); + return g->GCmemtrav - oldtrav; /* memory traversed in this step */ + } + else { /* no more `gray' objects */ + lu_mem work; + int sw; + g->gcstate = GCSatomic; /* finish mark phase */ + g->GCestimate = g->GCmemtrav; /* save what was counted */; + work = atomic(L); /* add what was traversed by 'atomic' */ + g->GCestimate += work; /* estimate of total memory traversed */ + sw = entersweep(L); + return work + sw * GCSWEEPCOST; + } + } + case GCSsweepstring: { + int i; + for (i = 0; i < GCSWEEPMAX && g->sweepstrgc + i < g->strt.size; i++) + sweepwholelist(L, &g->strt.hash[g->sweepstrgc + i]); + g->sweepstrgc += i; + if (g->sweepstrgc >= g->strt.size) /* no more strings to sweep? */ + g->gcstate = GCSsweepudata; + return i * GCSWEEPCOST; + } + case GCSsweepudata: { + if (g->sweepfin) { + g->sweepfin = sweeplist(L, g->sweepfin, GCSWEEPMAX); + return GCSWEEPMAX*GCSWEEPCOST; + } + else { + g->gcstate = GCSsweep; + return 0; + } + } + case GCSsweep: { + if (g->sweepgc) { + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); + return GCSWEEPMAX*GCSWEEPCOST; + } + else { + /* sweep main thread */ + GCObject *mt = obj2gco(g->mainthread); + sweeplist(L, &mt, 1); + checkSizes(L); + g->gcstate = GCSpause; /* finish collection */ + return GCSWEEPCOST; + } + } + default: lua_assert(0); return 0; + } +} + + +/* +** advances the garbage collector until it reaches a state allowed +** by 'statemask' +*/ +void luaC_runtilstate (lua_State *L, int statesmask) { + global_State *g = G(L); + while (!testbit(statesmask, g->gcstate)) + singlestep(L); +} + + +static void generationalcollection (lua_State *L) { + global_State *g = G(L); + lua_assert(g->gcstate == GCSpropagate); + if (g->GCestimate == 0) { /* signal for another major collection? */ + luaC_fullgc(L, 0); /* perform a full regular collection */ + g->GCestimate = gettotalbytes(g); /* update control */ + } + else { + lu_mem estimate = g->GCestimate; + luaC_runtilstate(L, bitmask(GCSpause)); /* run complete (minor) cycle */ + g->gcstate = GCSpropagate; /* skip restart */ + if (gettotalbytes(g) > (estimate / 100) * g->gcmajorinc) + g->GCestimate = 0; /* signal for a major collection */ + else + g->GCestimate = estimate; /* keep estimate from last major coll. */ + + } + setpause(g, gettotalbytes(g)); + lua_assert(g->gcstate == GCSpropagate); +} + + +static void incstep (lua_State *L) { + global_State *g = G(L); + l_mem debt = g->GCdebt; + int stepmul = g->gcstepmul; + if (stepmul < 40) stepmul = 40; /* avoid ridiculous low values (and 0) */ + /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */ + debt = (debt / STEPMULADJ) + 1; + debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; + do { /* always perform at least one single step */ + lu_mem work = singlestep(L); /* do some work */ + debt -= work; + } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); + if (g->gcstate == GCSpause) + setpause(g, g->GCestimate); /* pause until next cycle */ + else { + debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */ + luaE_setdebt(g, debt); + } +} + + +/* +** performs a basic GC step +*/ +void luaC_forcestep (lua_State *L) { + global_State *g = G(L); + int i; + if (isgenerational(g)) generationalcollection(L); + else incstep(L); + /* run a few finalizers (or all of them at the end of a collect cycle) */ + for (i = 0; g->tobefnz && (i < GCFINALIZENUM || g->gcstate == GCSpause); i++) + GCTM(L, 1); /* call one finalizer */ +} + + +/* +** performs a basic GC step only if collector is running +*/ +void luaC_step (lua_State *L) { + global_State *g = G(L); + if (g->gcrunning) luaC_forcestep(L); + else luaE_setdebt(g, -GCSTEPSIZE); /* avoid being called too often */ +} + + + +/* +** performs a full GC cycle; if "isemergency", does not call +** finalizers (which could change stack positions) +*/ +void luaC_fullgc (lua_State *L, int isemergency) { + global_State *g = G(L); + int origkind = g->gckind; + lua_assert(origkind != KGC_EMERGENCY); + if (isemergency) /* do not run finalizers during emergency GC */ + g->gckind = KGC_EMERGENCY; + else { + g->gckind = KGC_NORMAL; + callallpendingfinalizers(L, 1); + } + if (keepinvariant(g)) { /* may there be some black objects? */ + /* must sweep all objects to turn them back to white + (as white has not changed, nothing will be collected) */ + entersweep(L); + } + /* finish any pending sweep phase to start a new cycle */ + luaC_runtilstate(L, bitmask(GCSpause)); + luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ + luaC_runtilstate(L, bitmask(GCSpause)); /* run entire collection */ + if (origkind == KGC_GEN) { /* generational mode? */ + /* generational mode must be kept in propagate phase */ + luaC_runtilstate(L, bitmask(GCSpropagate)); + } + g->gckind = origkind; + setpause(g, gettotalbytes(g)); + if (!isemergency) /* do not run finalizers during emergency GC */ + callallpendingfinalizers(L, 1); +} + +/* }====================================================== */ + + diff --git a/lua/lgc.h b/lua/lgc.h new file mode 100644 index 0000000..84bb1cd --- /dev/null +++ b/lua/lgc.h @@ -0,0 +1,157 @@ +/* +** $Id: lgc.h,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#ifndef lgc_h +#define lgc_h + + +#include "lobject.h" +#include "lstate.h" + +/* +** Collectable objects may have one of three colors: white, which +** means the object is not marked; gray, which means the +** object is marked, but its references may be not marked; and +** black, which means that the object and all its references are marked. +** The main invariant of the garbage collector, while marking objects, +** is that a black object can never point to a white one. Moreover, +** any gray object must be in a "gray list" (gray, grayagain, weak, +** allweak, ephemeron) so that it can be visited again before finishing +** the collection cycle. These lists have no meaning when the invariant +** is not being enforced (e.g., sweep phase). +*/ + + + +/* how much to allocate before next GC step */ +#if !defined(GCSTEPSIZE) +/* ~100 small strings */ +#define GCSTEPSIZE (cast_int(100 * sizeof(TString))) +#endif + + +/* +** Possible states of the Garbage Collector +*/ +#define GCSpropagate 0 +#define GCSatomic 1 +#define GCSsweepstring 2 +#define GCSsweepudata 3 +#define GCSsweep 4 +#define GCSpause 5 + + +#define issweepphase(g) \ + (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) + +#define isgenerational(g) ((g)->gckind == KGC_GEN) + +/* +** macros to tell when main invariant (white objects cannot point to black +** ones) must be kept. During a non-generational collection, the sweep +** phase may break the invariant, as objects turned white may point to +** still-black objects. The invariant is restored when sweep ends and +** all objects are white again. During a generational collection, the +** invariant must be kept all times. +*/ + +#define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic) + + +/* +** Outside the collector, the state in generational mode is kept in +** 'propagate', so 'keepinvariant' is always true. +*/ +#define keepinvariantout(g) \ + check_exp(g->gcstate == GCSpropagate || !isgenerational(g), \ + g->gcstate <= GCSatomic) + + +/* +** some useful 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)) + + +/* Layout for bit use in `marked' field: */ +#define WHITE0BIT 0 /* object is white (type 0) */ +#define WHITE1BIT 1 /* object is white (type 1) */ +#define BLACKBIT 2 /* object is black */ +#define FINALIZEDBIT 3 /* object has been separated for finalization */ +#define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ +#define FIXEDBIT 5 /* object is fixed (should not be collected) */ +#define OLDBIT 6 /* object is old (only in generational mode) */ +/* bit 7 is currently used by tests (luaL_checkmemory) */ + +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) + + +#define iswhite(x) testbits((x)->gch.marked, WHITEBITS) +#define isblack(x) testbit((x)->gch.marked, BLACKBIT) +#define isgray(x) /* neither white nor black */ \ + (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) + +#define isold(x) testbit((x)->gch.marked, OLDBIT) + +/* MOVE OLD rule: whenever an object is moved to the beginning of + a GC list, its old bit must be cleared */ +#define resetoldbit(o) resetbit((o)->gch.marked, OLDBIT) + +#define otherwhite(g) (g->currentwhite ^ WHITEBITS) +#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) +#define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) + +#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_condGC(L,c) \ + {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);} +#define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);) + + +#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ + luaC_barrier_(L,obj2gco(p),gcvalue(v)); } + +#define luaC_barrierback(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ + luaC_barrierback_(L,p); } + +#define luaC_objbarrier(L,p,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ + luaC_barrier_(L,obj2gco(p),obj2gco(o)); } + +#define luaC_objbarrierback(L,p,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); } + +#define luaC_barrierproto(L,p,c) \ + { if (isblack(obj2gco(p))) luaC_barrierproto_(L,p,c); } + +LUAI_FUNC void luaC_freeallobjects (lua_State *L); +LUAI_FUNC void luaC_step (lua_State *L); +LUAI_FUNC void luaC_forcestep (lua_State *L); +LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); +LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); +LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz, + GCObject **list, int offset); +LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); +LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); +LUAI_FUNC void luaC_barrierproto_ (lua_State *L, Proto *p, Closure *c); +LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); +LUAI_FUNC void luaC_checkupvalcolor (global_State *g, UpVal *uv); +LUAI_FUNC void luaC_changemode (lua_State *L, int mode); + +#endif diff --git a/lua/liblua.a b/lua/liblua.a new file mode 100644 index 0000000000000000000000000000000000000000..308fae6610bdef5982bf741111e798c53671ee2d GIT binary patch literal 329392 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 L7wYjYM)$69zD{3T4wALXNxuR-S z&O3G|_L^B=4r6M1U0o+Ooo~>yZ0dq?XX{E;7paQh+Ii;pzZgnvJiGJEVPJTQNP8se zj^AK9DR;)_sd}z{vz=W{o-kLz%>KUDo@#B!2;^RR}j zpeUEd*8fGMQ=g=2PTfycF17s8`uy4%KWeC7Uq&gJq6QDDu{X2TtUNeZ9c8p(rNmdH zmBV>{{ib|`;f`N#IIzX27|z!3MKK6Rkpzn2*P<9sg5Y@iw!G3ePz*1q!52gjs6{A- zY7yybigf3hS5au23s1O*-JuyoIqUFB#^b-8J}ON+darH zb{08xUg+Xqh?E?w)N?(eMjb;^_Nl=b)u_tuB{o;rOH_}KtFd>o{aHoog7pYj)rDk= zf1&d<*W=ShJzkIe+lz47iJG-ugsXT^0oj=)+!rf#1>w5$An!!D`zQVhg~>s+pK@tJAmdpZ1+^>n=Hq{_K7fk#~+YH27(_t+x? zjyrav{R={5gZ;eF&K}0pt7OxBhkM{hQ~PmNoJC&+lux@+EZ!)qTfQj zh^PhorTFsNUGbm&KULmiM0uBwUf$Y}kdRT5R6|xtg&tQ*s#~uUf@;!rBjuEEV8|&U zA4kfmn3Rv65ppV*<>N~MGCo1G}aa3I(Vj1$N z3xvZ^iGGv4D7xTAdw4=|LR285{=}#Gb$fACwC1yAH}t9)4cwep`s$`J7?q$S>XqXG zNbmUfsXe1V)P_Wlc&9TmoD)7DV@UK*XkKJ64RXnL!0K$v2?;2L7SsrIy!c zSMT&{d(pnGmqKSfWs97)g>xb$isS3Df3wWLITX@344}{} zOvJ1aaZOoHNUskW$FIm?InT;4(Bknca+oJ(Rh+}s=0q!HzH5wB#C(@WDgos1&GyI< zN96Rl(AkmGW5bvblnTkI2BUHGayC_WyYASH{_=EoI9Hl6{7RRnG>wq+1CERwfB!ed z|MY4jYWeXA6xH*>V-Zz~reivBsq7=ti1$ix_8;KTD6ymri zBEQ7?6vfAwFZ05VF)j-l0@)dq=@nTSBnYLmyV;94Wv}x;- zT$g^MJ@V!ah}Nl@>oF`icfC6jI}->x zDq;*EBd5lN(elTj)uVv7-+@Wx-}(1fApOXW&{$7H`*B*=$*@F5b+-daHR`Vu-Hies z8Ulz_DCSAhRmbP{W@Mu7HC5hV{VwM?*yH20A#~B7i&6wKyOrZlu^x;5z)u6!53v+$ z$X;V%6&TRY1hnH)dSHoF)ohsC*(3YiV%@3CN$YA>F=$DjSZ_K3pGj(7Gn)4&KEdz! zxp0}9k7a0ZVkIaw{bv96$>~YTZL#9JI+-78=U)$_F#H-td`mPm+cB%lO@%tEyIR24 zYXv;oBA~v*F>CF1$EINl>PcRRm1QiLuPk( zIR(3~U+wlGr+t0BzCA^VOs_BMqzcl#G%89&W|?1is0%6w!V}fbJrreL))v{BOi#7; zGO`1+9E{IaVQtMQVq;kisJ$-S1T;+Zg9pS?lfDeg!~6Z(GAEa(s)zD0HwxLE`jWh1 zZHXQJ#D=hr=u8|4A5pb2y$kKD5sCOjT3-xkC8*Tr!Az@ms3K-BX{=wed~|l55CfHc znjH>kfShavBkDI*XH_c#Bkfx7nvtcxNjinB8gy9YtED^1XUvwd(11S9l!sJbJWH@9 zYSw;kOM*&}^!kLE3aU|Ebr?m`BE1r_JT zFL-Vjn+z%Y3D|w06}RMkT+J#LD~GklSZ4Vs^Kl5Xu1S!m#zZf<@DhV~%CPW) z5f=nG$L~cstFqJ&xg^XT{p)J%Eer+o{R{3CL&0gt3}xiPJm$tI|J`CmNI3Cl-Dw#L z3Rfdmgs`N-%cx>GQ|-Rp?yA%`p|T+V4{^SZGqbfEGjPH)k` z{{NT9mwGs{)Rnp#pVGteB8b=&DdB8ajhLFtu|lq+(WdlQJRe0z@n4t4pEAnY(xbh; zA<_Kx5}Id=YBO5=#VkA7-^%{MqaE@jTfCfWpxsK343s@xugC5ak_6e|>q=}M>%++8 zLNKe^UaxlAs~tEQw>8cC5_rB*C0vJ^3@-KfvYzrNNy~3oMAQ%_u8uE5ygaK!OWh6iBp{ zXUe<(DtV7~-Hjc%NNhmLd|7=WWzGRZ^otshvOlo68a)7wv(S9fI)OH4>*$?88{`u< zkCL50n~+bRz7r6U9-xlftnd_LmP;f0TVp&$TZW%u|KRT~Pj&&B`-z*((vbaxC=D8V z$h3{J-~Zp7z7abj=>Jsx3hDy=-OC3Ma~W;D3dMsJ_o`v+;HrAoUU!~CgDSC6IvwqH z=!6Fwr5F}pA$CY7Bwga{K_ogr{iQ_`nf;Bq|N9vgCL)ZTWJE1CWR3Danyw*A7jFQI z`H?6;TJ!x(hcK$P^l-0lfchjVN+c5F^ux&nT1)fO6r)HkiZP$Z_0&8w&v*Wt+GnQv zO9}E7CnD{`N+>&^w-4!Ma&2#1cowQIrWDRfoMKt&IZ=)(dxKGBuR`_&w9}%#$7e-` z$A+KBkdM|N2Ky*}=s-K!)|K;PYPkRWZ!Wr3s zjG8URD}J={8`0ZBDB~=L*toyQIP`F?A)m1$hHkFcO-HoQos~J!<%nUKoIh2$ilZky zGwh*>DyGKelvf(fJyExjEWRE{X0} zb%*2W4SA)fv7VE11jv7Rd5Ir`1KPxw3q!MBRJF>(m57vmwI{L}S>f_(;Q{~URTx={ zok!V_6Mo*li{I?mYmh+|C0-4u*7VB5f>*03^lYp0Z>><_f4izxxN+93y`y3VvMCHf zkU;JxGqE_@5uEWpG7wx5U>wF}bs}dsBYv%aG!$iucJWT;}}7_y##% zRH^M%wF9cwuWHAT^?~mCodN9~Rl_;9m?%rNTP%fPmqT^y{x^Z^f1#McY>#l?hLdM$_b>u@up|*qUB2QYlAz%0U=W?*I3Bb2HWq$ zw)iz<6Wb4d6&5rLrirf_i{}k?z`_Fy4=g(0N?<`R-s0)lv}{cH9)Dz0A(kI@8#@|~ zr(cUN@#xq*+maXSu+stzwI7Hp(Q9ofH<{G??- zw9+y6&&af7N22ot$v?3eL9M1RKx+UjKeRWBUlIZPNiOqx(IT{NOem$)wB{e@R~Zk_ zc=;NKCl-tK3(;UluEijYm>=vC^8NQSG<#pM90Lo+=#W9B{UXA#El6s#gOyG zlt0wRpg*GXs90jta^x!}hROXHv{l-v0*h8e6ULPJkGUS4IVZ7l# zg>h}6$T3U(LO7gNDf?46hbQ;fMx6h{1RPm~bBs8Lm)u{QAHZolN)exA#L0<^#R-L3 zL-HIRGHVFkNgsEg{_cR{(!Xeryh9rrXL7<<;xJ%4PMfIu7xPP(Ro~wvdmcRyL!SB} zLYLtPGmawb*<)z7T8y;h$LB@PTpC^om)9GoRuA2Og{8~FsWU$98z09ns$MJ>^0aw$ zx|2Eyaca&iAJm`!!WsFk$Pl@h^dXLRiIXI=J}~0?0rKO38Wg8UR61cxC(y9L^BVSa z!q;`ZRDDUG>qc$KAw&spV(c?PR5kPLEvkR= zDJd%mgzJ_`RRq_#@b0>D?!38IxLjq;EgM=%|AnitY?iCIv~>QQc}2xn5X;==)-|(T z)l19f+|t*U4gkSb*^hwy=zh9ns7b7 z##+@p+qHbItE?VhE4m7jalu>dX7>##7K-vUnCoof$WjWWhfNbC(%c~B*}i7+Z2vM?_m1WQRqEPA1!{y*ET;J#eJ0K`FLoUh-XCn zI>ccvMR^{?iF#X|C z=pFR&7oNu?jBsCMmxOPOLhon#X#Th4N{24#^9cX9^LJ3B+bUE3IqAbBJc~wgU&|G9 zH+XD{ZG`_tVrZZ!qtS(uF1USZ6!!z9#0$^2B#iLC13KI2SqVy}_A}&^^rt0^aKB@c zBs@9_z4~lP=oy7R#B_ZWddE4EP$fei5&qC*NvH1z@rFhD_)ZpFmk6$r`6E|q zR&Zi{NtmzujYz#DN>%%f9{$4;XYIRt7ppaT@ps* zUklSI|1-sJi0LmMcj>e({< z@zUi8_qB5*{W?%GrLTttE03c_xbOeGbYDD*|1AC$+r76awsxn@IbocAJ9w#DQqwNk zgGC=aUz6To0c)c3OJmB;%2^Z{`%v~*vWU-%-wx*E?l{TE?ud_M+#}3K@?JcKe{3W^ z8cXyuAB)F~{{0eseay$rJR{$q!53vdu5KCmCLrC0e=OEA^34aI;orxlgY;hxbGSc4 z9K@3$y<5Py{Wmh7cYX}tli(}dEBT&J=PQe3Ka?fQ?G^C#GarvTGp6Gs@Ez@y{(U{& zKQ>c&6krTo+b8*W9GcO;0QmZtkGtKBd?D~fnUBg^JQ?!kpTSqMPln6m(~SP@A^(`~ z8z1A}U&+7y(!Y-jcQW#E2lKg*N2A5>TJSx7K>A1H*AzZWd8`7T^1S5ZacstPJP5wR z-%7sS?48-(d=c_Rw9B92t^Xh3`y=?;4@&=D`WXL6A864FlJ8sTd~BwAFdKZ2Garq2 z#bcD4MII~x-%!8w?`dW;)4^u)?|$%YeNpo9_%~y|`~ZB)OOmgL-DmRedGNI}pZ+m? ze*@nD^YOSiW4KetqC8%a;hz67{&~UYVm|ICGWyp9zI^7J@iG2AZ1Io9dq)3$X^Gzm zIbl8ebRZ7&yw!@!B_IC^zX;%d<&E9{RiNSGT##)!}mP+ z)Wg!hU!?O{jmEc^YJ)7nO^3j{3bpB z4S$gS(Rf}wMz|UB`=7zTlllKOo!^o_d%)*@P5MjYeDN6mTGI1Z@C`Fx{A2hgW3U_=qyc$JS4Pc{Z6)ZvuY|{0b0ta84cY3E<6)b|BFY6r!B~ z{{u*T<-p$n#{wz6{g)}q&w-Bvp8|djh+*Qi2Z8-C-vs<0z_EE0iS@8V`2pKr%`#>t^TY(r8&zS}! zckg0-jqqDQ^7k$_&u4re>vzQe43PM?FfIY^gZ&I3#p}KEC4DEO4kY?gHebv*j0rW_ z?+22*p8_e|?@dt@%u(lj9Z2!K8~7No3K#`WXZx|he?vUJeV(*`07(2(f#lyLHb)_d zcESAbK%#G*EaT^8{M|Xy{5?h=ql57=bTE|OX2!9MFHDm54*++AF zx5rBQPZ>7@seNC>=6AE%U&dy}>w&~ab5zQ&A4;q|m(6dW5XgQh<8(&9jn=`GX^$(4 z@>96K75MMKN+6zT14u9EIZ?(Q#tz0>MmM92QDGcFehBxBJ&YZUwTx~?7o);BfP53~ z8G9Hz7;72bj4nonaRB)$+%xttb}-g5x*1)J3gZCsUASlLVeDY6Wpp#T7!}3=l#6iB z*u&VtSj*^UbTKN711LY?p0S6qgRz#;&FErO7za?!!aZXTV+Ug`qnpvis4xz|v2f4W z!`Q)C%jjlwF)EA$s6=?pi8A&ub}-g5x*1)J0O4*H+WACy&_fn@=93v|d!$&J{Y*F3 z-ESr{^3KpRxq{8#XMWn>oQSeD^gQ0h=A#Rwf9-7U_et~Z00+W1_RTLty>h_))@vob z4K$(~`>q$F-V%M_dP!f%?w#PFXB@jPVfP-?6LN3tJ6r_$MD9B{d~!x~<9P=(qDMKt z-vEv1#=h<>4&Q!*bTOCsK{wXzx3T|2izK}lKy+hYeGA90{W?j%6nRN>V_(V(xk%wZ zQYPu&=J*@?7ApH+$o?moZtOcWGrfoDbf+5mZ|qyFVtPB%??6~YH}(x4W4gOshJPiy zH}-WLOkd%XbkZtB?zf}AribQc6#ro=7(72U=;*iUc@uJr=siroiPLZFyRBgNQBMCK z*uAl@_yN1`XZLr(PmzC!13e|2zdN}6zr*P>_AUOz@!!emtL5;GeZ93D{!tG9HFA$Q z7HoJlz4_(R+|1=^?32-5XrjEhJnv)o#y-$Krf+BW=QG{d z$J)sBzD3gilxjc=1>K-o7LN3q6OgHwqb*3v!pT=}!pL{*j4|`rZ>Saq7Pgy=|AWC z-@xtXyBxl;&;J;Q-@xIwGTk^w@Bq`DO#g`K#ybRH;t>we`6ngDZ8&;B>9hn zCh`aK6M9;?d>`lX^>Fzc=Zqd>y2~xtl^5B)aZaj&=_}a1jolmPoVGB%pXs~Uy>Sk! zl<7rGZ!z3sUPsTLnEr@c7!|sUkK%8fV|t$HElhut{Ws2O-O2P0_Wu@kZ=91NCCya- zRCYgrV90;t9NoWi`Sfx9`U}&ea6``yrVlawSuQ_gpPlZqB>#oV3GnY{y0OoGF4K!t z;hjf4=3S_-R{DFW zKUVX^H1q3e<`>h ze6LR9za-5+Pa1t^n)yhYc@rXIjn6}A>B&or&wFX{=}$91m=>SmH2;2(mOtCl!l%1= zt?|LNrYYtFY4Q2@H2S}$nXA+M>r6|3VH&?PEj=63;wvt2NWW{%Ta)=lsniRsYLd6L z)zn!peoVR2E%mNQxAA!BQC0`!DVr&H|V9@)R=ZV47e@#PQa9UAs({OdIwGFeKwYR zZ>)DLS?|M<7ZtS1TPsG~VUv2rjd^X2yvhVdzK6s#8@G&@7HKyJTCXWdyY{9GcQ5g6 zS5z;I8&xdV4w#G$cY`D8-O}MTV_xxC`R@Ygtz)ZPo zbL3@b!snD?puk7DY}1;3XhfF#B}F+PheTeaU4@i-F%p@Q7w1q}!a_I`e#p#}w#myd z!NQke;%1(d8(FRQOyTkwP1AbIf{ zB@bko5S2VJ@`x#%DiBg*oAEL@a-Wt2B+9&F7Ps2*RkxN4|Kz29@`@bm4S(V$B9Q>g zEmB}GuJ5zlV3xdk&vFYNRYCI#&^7V`+|=94((a#2zp*au_B+cBOy%<3xM9(HW0-k) zSn4%hmdiGA?N){xwy5yM^>TbQFEY|<#C=LBl0vl3>R2z`rE;*E*)Zz$qLwRp zlNXB4t>^oSMGt10xDzwY+>e=NqboBlkTi%g(}=iPjj~TOsj?R{jogu$<{&yR(_r>r zrVVvrDF(V<&9t!eTNXPhMlBXn3R*0TtT(ODXhcV4T8K+IO_R7gr!^U_aa&ru$&u`N zELMiNwz9F{vv9EpH*F9X)F{(v>0>N*BT``WG!`E2Y)l*OZ&JG?%Irt}pl+_Jkctx!>Ak72bDmt~OcM!K(;&sEX|&dV#7YWIlZwcv z*;u5h$pv>TBuy(ywG^VJl_^KlZRnYz74qIT+`~pUL(gr-%nW@jsTAM)G!e9}E^#{LE` zJL2G^jGxsH>-#6&!&b}btY=3~_-B1MJ58%kx`(Zg{ZqzDC++Z$(%VxaqDq!2UVhR& zY<-`T{yfeF*ghvU|FCS=AUWiJ@|?DC21*s>PGA)4S?!1m_{@9Qa8yE}-$MMB;b+J1 z(?0aw_F}!fa6$R(P34Kc05k&W;{v*xU#?H?^lJT)fg2*j+2PsV?%U@tSLAdeRI5*noJxeVwe#q1B9w?bU!+$%7ziFL)3di~vDo0m&X|bsDT;7l zqK#a&znh+jlF~PQB-sHmTB|1lDC^vB53BPrTmoKLy?2i z)AAeDMJu08Y7*oh{LB}yUnY87>iHr+)c^zNOe6QCPHIT3oo)&cF*62FZ^eEbnmv0 zRBg8!dFuvG$F=#&hO_KFOkI1SKBOKG0%NMiDtRHSE@6oo_0rW3i)?W&)Jl zzDVDNT9(MPp_7LlfxTGR9iuq9e@-<=&+%T|XUVwutdWeg!sqFHHzkX`xo14uRi4O) zs5!4Yx-LU~jNi${n5w4Bg=Cm2547J?c^=^MoG#1rE#!|V&)ptv z>UK-bOE1{;`X$Scs`*{AjKX74K4v{j(R-sopThpk^(~L%_mb_n_9De^e`f5d|ZSu#}H;Rb|xkKtZ(KaHx+?_{AB5-}s=Wo?c#@?UU*-N#d^PL-_P~L2K0pap>bDo9 z)<)T0)nLCzpZYcJ_hxJJ{EEa2YBp8JCcDkweeKtvp5#)G9{L)pBUHe?N!8J=Y&gf? zz2s}6Iws>o_y3&Mj&XJLXdiUGC930llOP4DKE56~c%e4$WWU$euf-@=`(&;5&4;~BZ-xHIo`=3V-oWr$t16UL{dUhC zQje!UO^&71U+Ukad?LN)XQ;RNFad2`n=gpHHIXvg2K86TwlheHjT{_f=*049y|K4) zA_p#m1*=7eL`m`sy(iE!=Cut8O>;NjTiU-V@4D0QW#ibbo_j}1S<(EH^?~B&c)H5l zon0Kz$3e46HTf`6`Y_3})qU@_D%@Zivkh%6_m1>U=&^-@Hz;Zf4?#N)X&~2p!*rpV zsNPB_LF;RG`#1l&IRqK2_T#`YotE_vnjo8{&cpuDfy{ z_c)xmRba)~ylL`soPMuf-;cXsoc`b*Qfs6Ka_pW3mGvE^vL~1c!Qg{x?VuG z1hlnLpWeL0s|V-f#v^$5xjpzdDF+?5xb~p3dp(q)RW0#A&$_L&Z`0?pCj=Qd^mXLxvPw8(r&h`g?%a=^r?IOcXy;G1Oc%byj=}G*?w_xu5 z@A-qzLoXkOJ?9B0+GIQQ>OrBsJyACQ#3CpQnhKK8;BpS>q0A0JNixMkYJT@>q*4|- zInC;r8lGAIWL}>U*9k#OCbD@&2^so(eTQjax!SRO-)hI)n7A&gpDHDnU)+m(aiI~G zv@k={Vt1G{3_oLs6HYtS9xd%RwTYFZ5T(*_qYfKtBCU!;&HSMF={b?%v%)I_!JAOZ zA!|1)3opsmjB%WjyKA8~SyO|H?9Y(=y<~Ey<8vd!6QBkZexR+;5bU|c4IPO~=6A+KSK)@#IzqxQ z_c+=+U7C{Kk+EJe8Q%hnN6%1v5vR`m2-ODHy*V^cju%jf(|dDh&~0JYvpZu)F@lZa z&P;L5O=^22y=x!nS&`@|+ydwLGLDbps)e%z1hYGFgK%P?H;cR+{3ibCZT8qZQz8e) z#yyT-m)TG3v4zJYKNjNBldLmU-krqQao_lHVdu80g*#~ucTGj!dLlWVuE?WdZOrj& z@&n^RQKDLzJ-$E&pa#o~yh_Fyn~mALr8RD`GM_oWOqQ}a7T9(lCiAu{NtjmYGM@1e+`rw*<4K%p+W{&0>5 zs(<5m(v26WMrd(neTF*i;LG~_uUbY7G*-y%zJGy@T)uJgW!qt`_v9Onz;I_m4)wl) z&aLwuF@Q6A)*&tXs|XcR<)+C2E!;j6*nuEeIZ z_0TgI3w&S>P202d`OiQ>T;$ADN7vV=)?E9HIi!&h^p@D*d-%CtpZIi=#`5DmzeF)5 z2FoF|=$;V08e-#0xQ4Va?)?qMpgVk$e)|Im?+rEb?hPH+UaugysSjXS9Qkl+xKPi2 zAa-=(STR$e;m%j!zB^zOqqiuB@HXtkFxwL;%?srjsvx!9)a`mO+V^SidC=OS-LUgu zmYc*l7m&8cVDW&WbPxqxvL^dp!4TM>hjS?F;u}5s<{~PJvprf(k+8Z;#v;B_B+`un zO_t{w%n0Maw*ByZm1bfE6wqAzC|O@0Ba6Bep2Z&Bu3;s>2< z9{t*fFtRYFk8-wxA#FCM%$TfXKZMB&MmFAuP(piER050+iKnSuQ@6Wk?cf*bGC zZ8Qlqb7EKg^Oo{I`BK)>S2Qbs#fYraCV3(sp-~)hbe+X{*XyRMeG7Pyx8 z%!vM$?m2oz-UQ{*$3=#7LklCr_HYQEL-n)Bd{5-sf}HS09(_px6jZ12Ixe&R<5z9BRR4e{9ZYkT=Ou znx50GeuTU691pyT6i~I@f{(`Vk{2%WV_IPhUeFWf%T+tk5vuYEw2o`9R@$ei-4nLy zwm61clp@yri;-@3VB1I9u1>5Bqu+ZXdV_2cREPRCn=vvBVq`d(1{E|ioE*nYP>u|@ z|DTKpzmKSoIv%XTaHwiFjYjV_1~LeL9d=b_|6BUJGNfcVE zafi6$>0>k{*^A|<_}bA&{!JN2{<3HCL~h6lUx4AC-5=={ZF&->JT#lgJyYSOb)H^3 z29*;%`qdBw-dqeV|A;Y)sdJjfv&KbnqP3?_BX~YY?UnSpTk9i9^DQLJv1sAgA_aCH zY6paR98!|1*fS(gMa!YmtV^9++`^^#>C4a2J$n7YwCXdfKVqbj%+QaiKVts7t<1i) zEYG-zZ8gNx4m-vNp)otgZ7mz$n}zQfj5%f|`5^BdaCx*BL^pG$*C!Napl=o99$y~~ z4b@&>KLEP|V?x(P&e+2DrO5N_f-yc+8ysxbri^kx^(y2;?%C`PL@ z(P_=F_E$d!o9x8okj2qWYxWj5gBr}J^<4)M5cNZ2!0PISsG2LXR72Y8T>h%-Qs-jr@>%ZyM3c?ViY<54_sDqHa)I zE4L3mhaB}4|0m{B=Y%HX|GBv3Ml3VQ(U0~UVUk^sxAZ7xjMV>-$hFh33yX4#7eZ%u z7Wy7B9J&UJJ9b>8!RuW&W#AgseeCUtzTCHC1L(DmB3NxN#{m)V9VeFG^ek*=73vj* ziG6BtpN>i5=o`hbv%;hKCJ#O{f>X+Z?@LaxbV;1fK{|qC@e{Al(FcNqeQ0(cKk~T3T*-`M zlT3^_Km8bGV`+vlreF6t=}I*q#A&77uVLVhTRp@W%qYDP!v@r~Nr-f&UmfhPu>9P3 zH-2y7ofbn<>sO`L3vuGnUeUs@K%AH}o0PWw3C$V}eq>YjYH!Bg%+WW#5=rE{9S`F^ zqdz;ozRPVt?$zFN_=Y?V-*29AqW~Pf7jsXeS?BhP!LMZ~$_;!G8h8%Pa?`TKSdXRj z$gS)`4E03Y7l$pZbU9wdrK4EFN$jV491;#+jBa;m+&8@|ely)~6#L5!YV1@&_wAEx z*sw(7+I%ia8?2MPnUfo%y~_iU0|oH{+RaR4Z7vZ++TNrQJ7$Hl8&2Q5^dx$HTQ_-S z+<6v}+9jCfv4rjl6YB#X$)xM!#F`0)W3)Vi`=b6t5S*}0wY`{l6L+5?X2ycW5KZh4 zMh<4h?+9q`VmUZD)*htgXV@UB9=*mMKTpbgu!&%_-IB(;v^N^Nv~d*cdb_vuMCcaW z7=_uNSUP~K_;oa;q3vRt(-@mm?1?y7BzCCc7m8h78HkZB@AB-}r>!TsO|x&auSC7} zA#3T*Bl_Kj-)j6G!jEL6_4h-V;S^5^NpE^O#DAdiIghKk)m7i#g6|aC8k^U-Le0%C zI?UWu->%@yB~C1cgCVexeN*$gHPW(fU8qfIZlU9aZDbQ_ZEkW&-f(Mul9>Y|_%41K z^#C&u)CSRm3YGdq+4v)1COy zbj)w*89|RSy>Jxz5YtJoYNq(r=1PaOx0ES<3dt-yKansZ{2feRItty;$3gS8O!Z6Q zf}`)9GwIRpVESCl`!dDf`2Lvm^kj0coGl|(HwwLl>35GpA7DD&{GQ4GA)1finFe|$ zJ?4gffwMu+6#pXXzVUn;^i28RKSk326Of4>rNf?hM$^OYyg<@%d^cnMS2O)5Xa||% zUv!al9~dS69n&R!wDNbkB>iHv!%XS#m?7zXfJ}7b`*}_#Vv+i^Tq4aqfK2)0ERb~4 z_mL@mESE;rQ=ZRyVM#uU$Iz$fN$OGcg0P+WSWaPt$NJ3K8AYQBzpczi@=`nopGAM< z!yq_W&#Mu?O#b~6e0Jtz`I#}?KZCE9`93awq^EoZ^KrAw=pX4RcQYT!Rqr#II5j-WV=e1UH zC;heLcQ)!~3-hrYPV%uk@^3cywlW{f{QF`tN-{Z_j@>x7aK30xQ z&y(Ok`Wglect~ES@LTk$z5>2lv22z|u-qOIKBea)@{jqr{buB&^)lC=WVmA8jRH2} zY1LB-zN5@X@?1OyAL{|7bceua=&dEWp2C+Q-9I4yw`BMv=TrDC`bD1yUjy^ieGK2< zz_)|>NbZX#EuNG=Q?sETiTOzWr|^|az4(+KI^Z#2=u;iZm!j`kq#ykKtlyOSg%p1? z)ML_99(_lqpZbXueoH+jJ>?}wB_H({qw$fRa%E8RjnK<$@lWU}|BK|K{zE)QK5@B= z^rH;j%t!r53SXLDUXgzA5B;a~m->|y{!Hlyzw>>`KUzH{f1d~6R_3Gr=HvV&{*S=F z^O*FP`XBKa>B|t0*%-^MI4=3QKT5U(c3uEn0={bI>tTDdy>R|g`1gaakNK#75|0sn zn%-*LOhKJxL-yZbyaY(`$^lY7*nl<~ z-kmSLlbQ1(3ZD3X0VMj*fE3RsfRwM_1X6rf04Y9uF@7Vy7?Aw=4#sD{pkg|U|$EMbW{T=U4=k$cSH^l=IjNM{j-d#f#gmFlDm8$@gK%` zRqz3`Vg4qN=xsovmjkZ>9>=(s%J)?u@%I6V?>j)^+s=3g({Ez>#cY2J3R%eA5g@sH z4oL2P1f+C62BiF`amswS*dg)Oi89^SGF||@3jF_ZmZUFa{LTcKzpX&>Z!M7WZ6%Px zod~4xzJf-8XU-F-q{R0FAo0C{N<``Z74Qqd@3NV6uP=i+hC*5a{1FghVp=`$c9^dL zjzRso2)G>P*HOsi&$B@C|7jrkzn0AnY@Q3GcwETnWPAaUC3mFnhw`HnNa21Fh;XJ| z!RAZY>_lX!-mFKU|m^AbThgb6~+PN1735Yj6IAUjJ1qzMi(PMxFdaHq`z|j zNY4{w#_vZ`t}9Qm`TK094=0Fje4iL4Gu#{V`Mpekg!vCL-Iy=G%4TE!^A4Mh`Q&jn z8}qxr8}4Vw_>Dt7qwpi_zk|%EgU0uW=d-zGw&cHz&7{|yo+37vpfjN7S~hS0yfjxB zbaWE*+{)%Cn^&{hT`cK)0i@5$E!&OIeMqQqYa{wx>A#{hakW4p?m2$wo`wHWAU$D@UlGR--V3@Q;@@(n4}4DAP}L8fhrbneL^swO4>8@v?&p#jbeD@~LQahmx&q{m9XH;qn5yRCFvnzx!DT4eLU6 z?LwDA3aiv`Rbf?AQvtPMQe{vDDU@ldTUl>--%=L}LXSq9Bv;oox2zSb{WVSDx{4Y> z4K+8^vl=e82{tviNxfW^LaRYtxLv9sqfl4XOO-!(Z>SI6E%Zfk1hM;2-wK5Z^=sPL zMyd&^5GJ9dNW3kpN!1o+sy8x1k(ynkvs7(Y6{M*MsSUTTGsCEdnid3V7=Vu9Th3cyHbeUsGx zg92!7T#fA(nSau_x~_@yvjWQAR@JxHL$8)BfY$oejj}|odeVr^ut%9RwRml3s=-Cp?gAj%@r$YL3Jx>l4Mg0h*6)C49L)=!KhV98?$1iS;^XzW+^IE(oR$& zi_xq{NjpnbN?LMlN?LF|Nm?W;M~a=SA4#i}Dw4Fe)RI(7Sy3|Cg)Ldi)g_hfmWrg= zs5BNE)SINqs5+@OqV^=MxB?|Du<3_Nku-~{lQhcOlQeS$N?LFoN?K6yu!58Mj8`x! zHFc|2-OYx1ifAFC37I)MPZ+7LHLt^#A}Tt0C)6y-SK5|j4^q^pn3YyUgn|(-l&SDi zyeEAXM$=={M1BiHN_5EP)9PQj>guap@*({zLOWG6M0rO2E7jBixQHt6VLmEfGybRk zfgWRgX_%?Iq93{&@%*FuSD4-O&oBc!Ebma`C$@o2tD2f6z7d(?;G zNlO@XmnJ1?3(yH1k6$%@)`#evY^(LBe7Dmx(#?eI)aN|&Vf%B%Gd9CR3}drDo<1_b z|9%_FJBLv*D0u2S8f!$Ytby_WM88nUl_f=H{a#hSGQ37A7|NtyXow=bLA2Bs=PRYW+6+naXjWj&&vL zW6fT&|0MlAMO4}8VTW$4XJM$R97UsGQi_+Kq`#*K?&;ZS_=kKX|BMIis=;_CBsOY) z4JeRu;NfYQ)53wZ{b5~;*0#hw%GUtT!tc{QbY7?HB@Yhlt6e7m(c-Aj-lsaedsThC z>%^iNwh#`x-GeXs*B7c<`3kKnpjA~DMLj2?w(yv({aee`os{KJn_+%Gpz7r-tY&^iaeSomx; z@_vU}dMcEwYB#nUK_}0*k*Y7o=kfD&w_RIkrw`s?>WfcSKjj*MbgG~6DC z;-1U>k>5D|r8TaQ4X)8Us z@kZ5lT8$ma#`!A0Hc{=yN($zy^YPULj_5f8vj%ZMEZZM^g}7h5e=1_O2_Ml2E>Gfl zQfm-|_$=p(llh&N)kY#h=TauB`WKOTOHlyxbpNn+qsZf-WDbt_KFH87 z(SYOs9oJtUo{Z|@gxUr808H$~LEd<7rQTG~j-!V7|x;Nm>y0-Vzmg@B`QsMGMgi> za0P@xW!DLOQ?S=tFkgvZ;qS#Map7DR7im**lBJz22MfXP*|sQ;T+jD(Y_eY(K5MlH z-9bLOXM6QL#iyUxtJxd|UT=(Przl-vVPUa=J&a2wN!Pmfp)616n z9T~oR{rJf6YR8tBK#R9Tq7UO+$Mp^HiI(!r&q+upLV`-}I;t+V5c1WBgyE0AxxcYc ziW?VfOVrC3qOA{Hq|#cWB4S|cS7XC2d{9LnB^1W*N~Q-jlDOi_shm_@RUx%lD_Ce8 z+Cx5~?bkvDE?sS)&l+ay?k4i2h}cA1Hfox~8xvZ0pnc@=XRd{xqHsOi#`zPyXc=AK z$B9~1zoQ2-^10OpnTj1!F#L#0O3#*}m=;1Z+HpcwQ_+SOlAL_wxqyWo0u{~dORz!a z`?cQCI9UVFCFLr;Zc#(kNE9c9%boPW{vv#H(NKs3%py8a$3=XqmJe1RJn=`$oz7lg zAMzR>*7g&Sn@IcZ%BBKe@t@1|C6CcbXnf^BUxo-z{E0op<6TgD`~7d|zF$JjG$hZD z@7}%yDSZ;ZOYyA&Vfyb;*#8W_27I$Xzq|4NE&L25yYujyhF<}Gm*Y1Nzf%0%_z`b8 z@Fsp=3cMY^Ae)JPf`9aG{Gebdd7gO*eRGUl!Wr6Qe(j@5d>Gb@UUBetz_nvmC-4$chL~o!} zb%x(X$)bL_O9Hz0u(J}KPl%gfyxHHq0X@bF9FkRwP~B46hg$l2+ZAeLuM<5^__%-8 zK7VWwebT*900rrI`FhlJArreR4?`fzGKS}cT!(Q0R~+*{RTPy)7m4D-ao=I1x5^Ia zWVn)2EqT#(S84{k)bD5Zx5zOJQY!n<=X$jNg-)U0^BlD=Pj{#Qa(ZLGmz4=Y;`FJS z4Yk|RManTS=z+9@NL!ha^fv~ ze&gwW@QN{{udeif+wsqPy`_VW@9uWHKJb>l==k2QEr0OhaC!U&;ayTbs5&-)73DXL?LzC>0cN~#3*^VyStyJ~wNf0Ecw6ZKY>WE z#;0!4&`rc1uR=ihs3UY6Bo%R?p&X!*jt-Sgkt2@C>FjVFTtK>k8A|u0S8D7X)Ww3L z%C0|$Zij-g{P-P)d`%7i01^o0X(ASs$TNsNIF2qxscydlw}I}N z_^(h5XO14j%gh+!*t!S?Ra=A;hd>!E9E$v9$<`#YUyGqCQivQS^cxQEt~iuJ$=(CH z)U2{|1(LDd@_Urue+ZiD zpmzQ>ADIfpK3k%p6347A>Ny>=y6LlK$E>fr1UyPr+A-@fw}78i3;3V40)Ev32x#5I z2qB<#4FOcG`>24g4-j;B^$U}4yV~tTALQHG>)TRhR&~Fj3H=*bRA>%-_gg^YI;?RB{1j6^G5aQdiXP@V&u~@nwjirof!<={KhI zMyfuc4=T{mmJ+*EeR98Ax<8BxFJw4JKGl?7-g5q?m$g$pUX1BOiP<)D!qsA`rne5! zRHAiQYsENxK7>2X-&%)suMIP}VWGmTdl9Ul@hq|zyl;pvNQ(D~#M77sQcaG4$bbz_ zX{ZZ@>ese}@M(l=W*hxoHnZ(AS79B!Vy7TnKTAnvNmA$oiy$tTScjj|Qs0VO3)Z^C zx+v6kHwInJ>#R;`C9{sc!B{Us5`MR3VnD#_8$%6;A141CAxj}G_kX_U|2*G*7}mS?UVH8PeeJcITh`b#j+s68Jn{2*7y{+(KW*WX00Dw~9O06ENfa2bDE0a++|Q`;fS|0j9fWP$@oMhI=|WbA4{> zp1^+(>kUi;7B%Vo_i!T&hUbRqfK^RtNzLMpDp9&t8Ez_xf!|Br)KwnO95OVdS}}$ z@|;pXFjpNf|IV-v37yoFv~(Ll*Y^?VZU@~ip_6)(mLFGAJwhk-CoSFIK(|NeSdWy^ z>9EMVQcgbib@u9GW2{d}bZO*9dG48CQ? zgY_dew4u(6gt*hWi&s@*ORdOfUt^=qka><0f;@* zq9EXffHwi24Y{{A!Pf&~>otD`U^(RHt^h=uiY^7jzHI(^fQVDk+h~up{|Dfiu-^+f z1Nd(Noq+!Vh%N2>Zv&ziE}94E0z4P(9HVjm$pWVUqHX1WfUT1yaQ`PDL@@JT0)$ik z?E;n{w;v`%fA+73{!L(ApY`S zLp{V_{x|TC>Et`Sgl{S`ThU?DeM+CeUV%Y@bpo9N9Rh6v4}%Xrr}PQz6&Ms)C(tR- zArL_M3nP+T)#&ktb@UYcEd{^+(1^D1n0Q{`RVcFfVdwO_lE?} z5Pp;^Vt7*oe?jnU!H)=@EBG6NpCtIZg1;jCGf@cSH%IW31bD>0{48$-y!b56?Z)!`K0DA=^H93;#CYco|ccFzh<{oy=j>cgB$m# z<JriWzz%!CbMFgZz#>tGDdT>kWtCyT0Uq# zUR8p0-|Ek+Y9((jU7=k|^+%a}%qi9%bM!}vrqQ9qE%b*F#JOs(B|17f7#&K94n;>( z`_LYAQ1h*?L&cM=G9i&FqA(v;qrh^999COpxw1bX{mhoH(^jc^zDWwFhwKo~aBy#{Pl(1<@oI$prL z2(GawjYyoP$sKN367f81>^MN~7X2zgpr-y|txt?^BtR_=q(AV;##o=ddnTgli?o*_ zCeDh6*YI}4ptt{J2t7PvzSV&91*HK@KQe*+!cy*{yUUKl5l3GGT=Sn(TUz zgGiSb$BRRTeenax)xc}UB})QN@6E2FQE6oO?i_YuXVGuAw6UstgQd7}|bF#0&HF%5H zX75yV&_C^qG&m@Rf=Dha4gZ!W4&iTf;J+{2ILJeSSr2<>p$Je-X7w98j;%m_+I}kY zfh}LK@Z!xW z=4I%Z-Tu`ImD6J-rUv8TPXn!pw4mQwiYkA^JL@@b|9|8B?ueoPqPI{s8K&e}iDdO{fZuNWNms zhaM{Ukc|p`M2AB)$|@YXbv|S741yV6nDOF(g6tt_#&>UU4sOiCfyo?i_;S2jOeg67F@G?l;SPKL)C8eCN|8>n z|89wn)<8M(2yafXBB?V+wAlDCW_Bj(WKk)2{F&+(q11d4J|Jx4fNaW;3vYNtJVW~Y z)fXvMBg^?9;Tuh;a5HlK!xfRWg%A%dT^9Av#1Ler+7&uJC2$5X3G!afO3*X{!?Ob7W zFY`936#Bx)^!plV$6w5nlE+^?^!g{AwBtC(-aTpnUZDrzlNYo*Z;clj+L{yLcDRBo zW;i_ETfB)hiEJ%$2`S33-^LU9SR>F_ox8hz8lSR~Y=~$3xNN}7I`M4qhNtRGI0?ay z0Ea^HQD|JJQgNo7d4qnUBRhg350|TIG`^+k^5T4f=hJVZo;2;aWyzq;9=Z#~Kqfnv zO$#2&2wZTmd>U}fjxr61BW3S2W*qI$zzc;^jIrj<2kl)^dI~>ngoYu`JZSIwGV#y@ z=$l?Z<4Uw*G*QExPVH9$r>Kzm2c6!G;Dg!S#tcwnwrqBsx;`ofs#?IcJdN7vH1{H5lI+1b6%q<)7uQhWa@WRplT>mM-7yrS?M+{Vh zWgShS4hNp|QIpEZN{3N)Rd#z8#JkO$a|E(fdS4t!B)PIQo@TsN2EkjMwLPi>u*8Su z)fC$9wgt|^;>K}sDISEuqz*GkZ`fI=gy#I`m-O+iFpO1YYH<^|JXt=$8#YQgozHTG zD~loBYrONQ>eevQdBc{~Q?f6!KTV!rDj5rCH2(l{pdFl9HbG0QyD98>81lZ}ZqGyB z$PJE)u&2Z9O2W`Hdeq+e9I8e|q!FFLyoJ8-KTJ2XFEGmtmg5=$Ms!c2FUVS`TY(++ z(iKc!X!ZmP*%MrZv`~NR4UU}^54pN4yiJjchnrmC3U};mOMaq|Fmzsr`8X~KEXJjQ zX9BNzFM&{Na({4w`S>ZW1p)L2Ix*}J5qih?W*2|2CiGezTbvpL0zF2!`UpBxysdH{ z@`ifg`xKNa9Ifsd@cc4@+F?6ag1DG~CmFC7f@FNQ{qDTjRF#78eoPZ8L+_mvn2Q0%e+K3j z`&J{Z$`StTo!rv)Mj)uXyv7?kh{B*KrgDyPOftRrle}zvqUVIS zH(cSTl}|qQ7{uA5e?iGJYCZsGad1EHIO@#F^ncQIbO~NTgvw@k#H(@UE0LVfOf$yz zm+jyBr}!FQ53Q!$QcMdG#YK_8Kudyx+dix;^bjBKk5vBgeL6hE0)4>kxe^=5FFN_y zB{ek5eUBIR#pk1H&(+a_tIkauu%}xNrK$A|>k}3h8K9fiHEvkrsBdU%X>WJbJIae1 z@TR?EHMZ5)Kz_z5(PL6JwY6+?v;_R^>((@azM-WJ$hu99w$;& zYs_%Qh3{mc!^H4Q$Gfk=NlaRXX>+Y}0=mKsvpjP8?>_@cb>E|5k4J z!EgncE`6=jm9y=K0O|NUa0pLxvkAtfzgOHpGeQ0ymh;0m;6EMz!*c#PAO6#opF{R{ zFQ33acQI%tk_W1zQg|4tKjY*SZ7*G#^w zS4s3~(txJc-_-pOJbqcZ(bo>w5}aQaw}Y2YsK&6|w#&(M!6nM*Ap)+{qk3%E6o} zcoyJ7;O}4~3{5b91aLawtAJ>-`G*BR05}(PKLES}FalT(*a+wW{4AgoaE{=g1at%6 zi*|b@;P(ZF1vU#@35aurqFg|9LHYfN1kzM=3gD*!GXS$-Px&RJt>_To48U&!mI8hi zkn%d+fJ|SV*nbX?@;lQ2&xQSWkSG`6?SP8`*8pOvU35Jly3YJ+!7BjK)#fh|{L_HQ z-ux>7>3&f1%OQNnShMXaYUNoQBI2Cp9z=;_yi(f2KXRg2I#&INc$SV zd4MMaLc+P|IV7I(e*lo~KL@1yW}?h)8A{d#`MJGS(1Nci+dcWtOQk?valid%Yg*Ym%hiF=`>pYla?cc7o7 zxmVnGiTm$i2j{rim4Y*xR(JFvNjTYB-8oiU@l<)E*HY-cDfADe;9FDZPfu~LOmVMG z!Knuhe{u6c3SOOpKa=ABt`zsnQt*Zpye|dsO~JVri@$`SEKyu$r+#%y8`MkH^68Av zi%5~Xwyk~(1Z7&=TKtU-eyVh$e3iwy5i7lxhJ?&i1=MsYD^tx?MJ-A zx)$qdtwZf|&~FweUQ)ZMaf`bDqWq?)95dy^tioU_o{Cgzfs)%%l_I6wEe@6vPuQ-7 z*q17!gq5W*6P8v9uy|=DoTU^J7R()uNp8ncGaof7S!qF&bCV9HaFv#p(!xj8|fi>t^}Zs(l6RO-n{;Q7J7E1x-;+x-d*eTHI>Bc)i>zD`m1)(KSO;pPGY0 ztfAB59Gq*5F6^Y=MMbZLQC(0+N4u!pAB2AxG(lU)! zen3BxiSLJ2n=gbKUU?xDJBcY$8%Fqs9!O!_;S1l|i}So)zUao?@f~N1{k(oJCwJIG zbd5cM8;?C<&(HP4S8dhcaHyTXqdOfLYodkQ&gD0KG_spN z0vYy@^Sli=)`V}^h4>)}iDc|bNd~u+sr}az*;eHa--@gb1U(R%`ARV&=-S6hfj6;m z5+5`opUYhwnLfAskHMGh-PKGv4y6;EdzDB-B1xn*ud@1!aj`XU-J6T?mg?NmH|?i- z_8{1De=f{%< zxxJK9QFeX(kg+s|R5`GrmeZ1Zm9`Qw53!%Xz ze8ZP@J6;s`3#MOA$uaQGPq;Tc4hfw}IN?Z?uzGxyDXa(|4`iVr)}SDIQVXIdg{{&| z@hal(fs6*qcX{zuk#oy<@b)Q7s@5bzW)H*qA6uf@8^jUgIcUkDv^jWQf=eO?6A578 ziz8KK+2M4JHn~?bX?+UA^`8)GWGvTo$35`Hsq> z|K{nL<-C%$5cxIh|4x2EbC+t;n~^SzA2pWoBazene?>JpZiN4m$Y|Y%vakBhyL{3! z(L3%=N&N8FL4dTI<|_c{&LP<2(cFgpr*!VJEFQOye<}Q6Kg-rF`=;ctjNac(*^ec? z55FTq&+wF)fPN<&F=!Nh9uTC98cgbu4Sz5 z@dcadSxt7`n4c~QY-;f1X-Dfk*=kQhn2$RTo?B8}8lMOAG0Fc!^I)X~4Dr$PV2v|7 z`9sz!^HJx)r?dBfAwPb0pa;X&^~awF3m=CR-XT;j#$^QjFg2z5So7dg_@@a9zfsgc zoi^G}G!HICVBG4t1M}dm@N1n1lNEoQee#-vl^@WLWH=9ooc3GcLy$xZ^*M}&p?w#^ zXUT(}lD;Ek(Oomm6!wYB*^xe)^_&BaBxhSnkQ)O|&fn<`Bk%b}160)c2J`eh#fXcK zj*k6T0K)DEvaf?Ab<#QeKBU!lZ(%aqsDV+~fDEkz_D~aP(fg?6h~6@yE9!iaEqTfP zHWlkZxZzVqSxs(RK9oKM{@Z@HkrR3&6Osa}szPsOc0C$c*lpy*u1Ex{lWv4-a=p>7 z>_&hH8w37VhRja~MDU^INIq%Fo!QZ!mZx?)pGj#*r4tW;$KoV%7uk(z*%L2Is#NKC*gpzh5#s|P3RD) z>fV6!dO=GG2b`4z2b~@G-GtxG^iga&tuaBf2{sVG(I7;R|GWhLts( zk!e|;NITlh$~stOV$qkd&4q0hg{zZn3t@Y`Iia)ALKtl2nsKy{O@oAB5(n_YR8+Ex z6>pgFw9Zplf83F!Yp98=Z`&+f%_)Y&?evldrM;A0^Zxcvl%2UPYwThF$&|$%>vxy+ zZ#|*}*WRYCsvGu`r#9wzmcec&$*A0e%_{uT$s_a#^(+&P^WP`#w*jV;C(!rZai&Q# z&Odd9(7c9UI{hR;>7Bo)sK)zuNN4#2xTgz$NZj2M_@8K=QviC-b9P}eMZ^44M$cO; z=iTJJTj-dN%A}!Vr92{ZlAl-!kJpECJLpD)j`^yLrn8)%-v@^pzSj*S`J0yC-$2(Y zbj)XEG(XF`e$-!53Uy&LlHY0h%>&(Tq5DB9KTG_sCqJw?X_!aK=x_z?L;2u{rRb*u zZx^^tV6(uh1uhgw{Rt?$qB=l~nMJvPYNCE zXqJk5v-tlk?C7rB)hEP#MEw6++;zRbR@{5UKhUIk?*ZZnt5Wk&y>q{K6dx@S%z}< zS)Efh|CjL8VNK#N0C-ztV**b(sIeYjl$)=fDB6aW4RYyR@#hhRdBNS}XT@>aqV7D$ zug51PK~3_pB1npOlBEhSVH1zO#Y(3jVU_giMk0y{0;XEUGGS$nC~Z9k@&H)f~CY9rB}YBxcKsU*kLc3JFjdGY#k2lv#-^wi~s$5%6D97))=;P8jW*p z!Cw|FVLs~m;tyQF!H^&Q?!pA5jTRsCp0ehn`}03vKqd(z(T!W2=$`V3#H&wxoMEm9 zN-+S*QL%PWJWsT5zZ?E(j!1vfSCG8Em}tFn1mS%K{tlrcurIN$S9s*kALnS0J)u6K zk8RZaIDY1RjrzXcm|-nZY4n}?$_ zx6BIly&oFQwco}m6m%QEO3;wC!^jvMJFNB#L;YtBvzz1H#IF7L@J7BABo%JDc*Ec0 z=kU+*FJWD*t-nFC2(A?1mc=O$Q_l25Ec%@zEf~<$95UIuMp@%pPpH2zR-ItiEbL<5 zgk7t)n~#Y$bckm=sTjRjg@Fr#?;JTvF~cpL=*ql%I6KCT*Fbh~Sx%NWW4S{uR%U>N zQ}I&#n(+G`e*cNzLHsz}pXf*bN$VY4c?dS;;Mk1OwF+4b`Y(}3XQLE%W%)mWNvm1DC&kP6hW+D;w-fx$du{YKHBc7ZzG{+ximDin zg5OWi>RytA)r*-&2;9u0Pnh*3g@ncU5+dyL(MG1i<&#QCqd$^SlxHgb_YH8@0&@XT}B5E$2Lx!+(b- zJV%%23OIqkRbg&TQTc6JsNW2`g6PbujvE$Ys7ZHG58$vR|AQ0xM}0zusAI6`S9c*o`d*wW4_-(AC-VRo zDw}~+gx~jnJKQMCq9S&Z$yEgvG-gOiX!CSJkvA+_!rPSufU9Waz;j20eGm*844G<(13C!@L2+chaU0&`P z8y|O1+xVEfdwq^K{6g$9)tnOP!Qc}($A0(9Y1{}vj2sLi{JiWl@Epg?oWQD>3O)S1 zD$m%fNb)q?9r}X<@r?Zu>A~>wKw+%U^luV9U`2jwMRw`#en`fD`4h^3Ma@1v- z_G_Z1^^l4(e7wmz9RD)ugK> zUBl9ayzj+}^4@{ldYMQVeBNPx@l&sx@Y$WP4eHOx@021J>%7Cv8(vIz`cFfgoqC>P zIwUgh&RyUVn`w?OJIgWA!X00kX)VhEoxW>sM9$&y*t5(LOuTWVmvKJJeB_^FxfwXY2Mep1(}skW>ECn;=+X zCdU$f_(wr7W9FoF_g%7aP${4>b8%O4efCD~Rjm^F=ll>wvq^ zBfRcE;<^uw2Crn8xj?Hw>+x7+w{{7<9=prhe(>5)Ac8=d9bhTfu3^!eVxfw>7gTmfk_Ml9e36ZP>Y8b^XBVuj{4vIH`0IKs@K0P@#@Kk&zYx2W&6ork;gOv+IY;+r z`ey|HE4#Y}v%O*{^EUWm4?b{@v7ZXnG4vgZVbCmwU+UHP5rc?bBIB=XC#oN7^m0A7 z@f9Gq;&rhiQc!@R2s{-#d4l}FrPD#<63;Fp)6>gZEwy`B`jWtu>-nVgAwkf=bEBm^ zK#^J=w3@Iye!(*M7YR-mYoY|q;)|CMUSE;tc;aOQt38TJCk0i;72I5v>CIf?@MbK9 z@WR20$gSgNY>kxHXLA&2`w72TiHcq#Ws5*x2awV z_n9FUF~qKul~NLLJ%-R*Fob#{<)x8j3&RihzkYtk!;c;>8)@gAQ%S&Ghghc~UndG% zy&oSADf@wtB7+-)oVq#rm|dm z*t^2uhHuo$Va`r4ZnMv5w`#8O)F2M>`nWZP6AKwz|umv+lD6*X}E0^->$v1 zGD4$;K6}Lxbn|(}JtsZ&{nka(p87r-knzqiTiEYqS9ZIxM}L((=6&Y_BjXLcEQPQ? zgEzi#S=e`KhEdjk>r}7(R}bL@n2PAyYSsOW?@x_c`&~P;3XC1^{X1@8ZJn}ka^P>V z?1huErs-dZz8RO#yfwW!l(&Okk9c zz%%9&Q6yz_?D5(AZ_jw?Kz3hp#=C?)rg?nge`k6xyo!dKdf6{;AI0@Mq*6c1WjQ|d~Qmh!LxJiHSV43 zy-LZ{!KK$ARGj=lL@0bJ-oBIj)?pXAUFr*|05c;uQZa->R7DkaIk=0$Yw`%DfO}Y`VQB<$ool>h%27 zv$JItqBs>TcvVJhApxp6IxQm-QpJKCys)XqT%Wy~DEEYO;IAkeY+;~!aC7TMHCJ*S zT*6iIk{ZU`8@;i4TzlhkAkk0CdVdM}-y6;Ka(Z{Hml3z!ld&$I>~|#cL-(Y#$2&|U z+F4$0zkATN?*(*;SRy~%X4SK$=@aW;?PuX+e=g@YX3uQ$a|J(`6gXQ^#K+UPJJ#o( z?v_<-$6RF_(S>uZeZ;8rRT;;ueMF*zKx?;jUg`S?^bbbH^SX(KZhZo34b9jt1(QeEQhJ-NQ9@#2>Z$Q7)}$-I2=?^); zB-Vv+n&W9VXW?N_b4B=<-HddwG3PxhjYC7b0h(2?L-1MDQO0e!g+pM((;D~eadN-x z6s0;M+dJTK!W$?8M!L91JXJV7cOuJvpA9lge?gJmqgiJ;{ZJ0%KPxpC;ZJhWRW`8o zaVTY}1fR>n2ZMl`Kf*sY7v`OnE(<_y@%?94q@oULvF0X?A4rn}{tu<~Ur{Idhk(~0 zV3!%NwZB97#S@3WCN+Flr22YSW_1k&9-`C#=*sj|;a3S!p=f7z5IJKs3=Tg>@nF;) zqilbB{?T&mNJFpVTvfbB64OynZtO2m=~0~#Sms~!$LG2|=vEnzC4rT=wR75V~n_cMC z_N}*gC%#$Z@T6YBg~;WfVFw*eoeu%Jc2=C^x}TNR_4un)&x30P*iG=1qMWXT$nbrt zqV*tsd5e!`U4RO9Rm6Y6_zH#`JCLjNn>;}--i85{Pzm~7}jv)LX$>%;E~9I*KD)8hyAfZ_1u zu3fB|iJnw%6~blrgf7h6^nUs#bQzq`WoSZ|Lle3jp3vopxSX!C{}iN0jUqC=G9~|# z#z*Sig-WJDb@ye=TlR##^Ahl|_Fp`OILXxI=z9DWj@@QMg2aERZQB~vT|+)Tz8|hO zbR*OAj`lnKbJ1nz>3QQB%(V+t%+Aphg4n4&%3|6;Rvv2=#!GfYuCYIO7HlXe-TI#@ zJa5CnM3bA>AIr7I&#X>wwXa2GL{%LL_oMashZ7Z2_54q(U>?`usz&&rvb$e8z@z1P zPXB+#>;EoY|L;th|5ZfR6cqawG(z*+i`=D6o;0U9Z-O#hYkVspAjXEg4SRaJq3UYP zEmSnhnB6k|Npoo*U?cUvfd-5Ah8F|dbEUy0r_bz2(xs1wqW`H=^^^Fa!MOV1<*~~L z*q_m{Q(G)Ivef%0y#KTnO-Xr-6F|Hg!0F@JZol7Ov<3FWYYq<)c1gdn8`J%pR6cG_#K_;R)V7 zh=wjWd*{!9Niv7;#CJ;hbv@?4ROOy}VlQxEQg>y>5bG!YI2&~NIpdk%!5=2Xp3SX9P>8wTxP27w4Pqy8+VW?_qJDD1Rk-Vi=RU? zgNfJm6gfxIx$!F%I@WV#G@V6maswP%pEvnAOe#!I(#wf93!T*av~-jc?G-wy|KsQ` z1w^cFeP4WO$$Y|^p4q@!be zZwFno(6QYp^C9s)0Q%AwO};GWB>FV>mfj{kr4V4)u1-W>fV#hH*raDWOQKKF)5Z8# zfo4?noUz>{(Wk_R`PT{hJkc{I?J#XQQm>Um=-3{U_@=~ze4i!FKg@Vb`%KF>3w@k^ zhmh@58J*v0_|60U5qVcI-s5U|k)LKhTo1ZF(HF+{o5VLIA4vaY(2rnCkB0488O=9M zJ-rX~t)dU?MCD#&%HI|JgMz}48};;1>j5BXE(x zPYKKs_z$yRE4mpFSz6>2{1XC$R6qdxW`XbKnfUhrKMnh@2wW%jD*zY5{w`B5PSG_2 z&lLESS-?f#5?C+riBFn*e<*OJ!2dwU2N}Pjjey9;BEDBPAMgnX?xNZh{YK#J0@ny! z2#BIAI#=LB7$4}r9gzN;06zuz8NfM!d}r-SzzYGfp3OfW5Z8zD|AKJ|bAzH?fH}b1 z0nsNE{W;g<_d`JP>lXL}ToPlvp1^oV_$xrPm7+O-Wq@Y`E&!ySGsf>8f!`8HeP$R+ zi?0ILBn2Q&cZ0e%Xw z6mS|K^XUL0TLSoNz`1~5Lty0FBygp`ivd}#w}UzJyGr0Zfztu$?==t+UMg@ZAnWOE z@Wk-S0h!LXKtzaYqhK%WVKpTvuuh;;phKWd;9(GxzE5DUz@Wf7flh%Afi{7M5h^~X z^a<=07!+71&?(R%5J36sMLc*96?Imb{}f!$-}VZw=WEoHMS4B|dPLKsozXlmxSs#K zqW#N!<(PIi`xDy~G~HVT?-rc*Iuw7wdjvl$__qbmzR>jlGr>y*zen(9!I^cu z524L3@lCy4gA!kK3(8%uANs^S?^C7^0{YkMhbP6|DegPPUC-}lBk#z6MBLYjdmrp+ z;(Eu#9c@kV*Xxh}7XHoRelc3;;z>xi^V-p_%q+=U(f%)DDK6&yx@kvxM@nkAAyV2ow`Y__yZ~K zuchF;|6-;8AjSRU6!#ZX+^yK7f_~wiNnQy<|U1p_khztLxj^)-|@7ioW8y zrdCr?S2BgVexdCenj0I|r(7*5r`{@kvnAzXid;s)ZIJp6>uwgUSfbiXf@y%p=e3R0 z2`v`TSms~10s5#!Pgl9R`$Dy3t3MAlX6=g1qbx-i*m&Jzyc5!BGBhdiv>~ptE3f14 zz9iqRSxLoFh^#~h&(1eA#&wM$GJy@aCL)o5I<+;8tD$%ecVotBEVJqd8?U}AuDT6g zla!e?C>3ZHm0|JHsnxe&;x?+h#@U)hmatAKwS5)kFDtJ3KZwZftCWS^}teYpieET)!dEh&rT@^^G^-b4`mM)tb4U ztYXY^wFp%L?v_ZYn8xE}V)3Xcl(ADEarO#JimtLTW2`4*cjGF6=)zGH4*6pftX$<3@@S%VgO(oVFNeM5wpQ`Q z_Z!Ji8%*m_YZ8WJj6xm8$40>2m)LA;kU^k}>pfe7Z~hpcD*Ujd`Pe4Dzpm~h;N0$#rNv<`BnJM9q)25+>Vp! z?WNJh89YFUV8H_!g{+J$JYQ(Orx9Ba{o>eh98$nJs+^5TR{xH7IhJmRP{Q`oxaiIU z#eL>65$>g%p0!2F{yEbVxyF2rLB~hGBN=)P&oV$j$5iRoUIQ78JnEssvCF+!Lzt(( zk!5&*=@uQbFZ^yrctqY2gxDjuxvL>uRqBd%7N`T3@Cy(^+A>3A`;^y6xk2$K9nT|7 zcr4p3(#&FyK>0FTxL=slXW|Sxex9JqhxccA*@W^@iXkGyLj@y>haK@Wq%T|y>5k>u zp$DCKBn{%#IMr{3xRtuLFrqz$I&erc1^TCQV~zneUm0+!76?{(@}ioi>anLpaZAkwgrv~ z&8&eWS?p}}E>;9Ayx9mBZsoZ;p5{rTS-*Au>iZ~#MmVqsS#3mA&nOQyB0m|CY{bK6 zMDs(atggL9Kw^AxPDNSdg*=gqV&_<2PQjV7!xO$p%QLt_@8i8k-gd^%&%+h zx7G10>MnREG&^|IMMe2kA*pCoo_Y|yorHO=11>2s_OS-355?KltSDRD}m z!{;)8L+@V~n57c}p@Z&H*aF9+JbUzuF?%n7-LRYFC=RppQmf#jS(zE;^EQd|H~7^J zdt5vMr|D9PCG_1`vO=nc4h8Hp1HV!^2;uZdC4?Ews)a+xJ!lQCy$-}F*pZF9fImXr zgLo!{x$K?)hVPTvm|fvNsQXFdB9i)+k1aM?XQ?Ora_oAIxb||{5*l3;zzx%sD(5du z$w$383@?VZQL zIyv<0;WuChU;AbQs`!tKvAvTU1Xh2{@Zk(trlGwmg%+)4ctLv7`ZT0hrzh=5L%J?K z=~vT`24SZXr~ZZeU17Vs>_vO$7}~Ed!Vbt5IyUA%KXmN+0Ay8CiY(w$-eOgOGl$#3 zDRc~tZkzf*qYK~z87Q*L6M0r)4u1*ZSu;|1C1d_Yq0tMrK%9J#a*^ zP#Rt^&NK9r+K1=B`W|k*+q=FFPs1~Sheog4az10Q(0v*ela z**9?y9Cm+qkk4v0JczqaC);vSzmarT|0`MH0aaiw2%(SdkCtbIMl-kma2#uU*HZ{q zQ4T+guWz|zFj{0+lc#C!7Y(Nr2?`3ZNwQI+5 zc3xZ096k>rjIU*gt~+eroIs3O{kyUuxu>jOQ3)NF0rt)#EMrSo%hvof?9BXC!zQM3 z_D&wn8PP>ZI69?QlH}X%oln8>!-KgwCC2Driii26frNuT5Qh<{l2_Wh-h!l8nwb6| zg#}~!jU*17nxap(cl|m&hd>$*O-US>KEB0n|9{7 zfLy$n1GmZ+iycQ=Wf$6ySE&OBWEl{fAs_Ik6~KzuI1QY_e^Hj|AI2NY$Z3on#1(+! zpfSDa0aT6bpT{*GJ?6Uha{NdvPEgO6!5JPW9Mw|?)5ODguJHN3sOpq4&nUKcQD+Zs z^?g<<7{v0q;xl8!fqRNszvPN;n!53Xiko%rlsC+tt>l^EKWa|s0X^X>Tzk(1Gxe%t z1R65qRr+X3mEHtLl{kGBDP_p8cix_+B)gL80+(mQGr>q_yld|{v^p)xii(ql$8cJj zpgNmYuW76B{zQJsk~8*+p5#WG2NLu+l;pk(35E<)N+t&EuJH52{|Yymf3sScSDwe^ zr|uRZz&1V@u2~S-Yc`^lW5KOc$7Tnzx_wh& z53K-0fnl?4zz5cZV-LqK___9;k1|1B?5f5&xNB!^vkDojo}D)6d1w~yYQ`TaQ)?-R z1{biSFTLJAhA`ZAGmJ+Ad`#VpRdN{Q{tiy%y^(9+yf~XtJx@h7a+(os9V_)s8VgK5 z=$A#3OOeu#Q!*BycU>n+Ztb!BSbrWXp~OwRBoV}=(fcH`Au2vmP$pIE4m z^@Yo`7Gcode(PkVaYhPQFW4>er1AAQ_oLqTMCKLf!QYEp{~s;3u5eZXq&+d>{T>~I zEl{m4TXgapUC68ZI2@|18P76cR}Qf=b$(jgw3_v16=2>ny2yXGn!6%1+;-0~SIG;I zYK(7$rAZIlJ!-i)&Z5C8VA4)#0d4ox<*c6co< zgu-1mYVTSF3)C{P8W+mMwTyMhL7pg_o zRV1}RWkk(g8*|nHE{5I1&9B7dL)R~*zXe)+&?WKVVQiCeE?hRWdA_j+Juc05+$L>D zjoV&|n-r&cLu1GNz~XF#sRusg9N%-=cfGE%xRtQ2z*3)Gk$K+<9Ut>!1JINX#>sh|awr&%SqSmc( z@Wm#)&WpE`);iWSZdkW*oge3li zu~!`G+aMU-+}Hu7-=^c5b!*r89gQ8W=KE0=?v`j<169@yEgKmtq&l!^y`#ClUBz!> z{id57c-j}IZ!_DkoVn&oJPC|1$0nT0@e>dK+E(M7ZM|(xi>+}(J4CecZ(WlOk3QL& z>S=*Yuu%oLQZv4m$_(MWZj()EF0^gJLsED$*ao7u#@5DqKY%~bw#kO$J^X76G$N)r zTDEOzUbmsqHhVVyX4@7mvVD4yZQ&x@wnerpue2>}Y-#$mZK0XZ{D5jf05dbWIMK$3 zk92aml|t|Z6JiRHY=#6i#jm&^O*V%GOO6In4q%lBPrGrM$7fGG6Z454s_tlX4$N$MC;{ z-yWf3`75LOElZYXX83=?&v?a*FYALcn%*Lx{5BkR3tiBpN`!CG3(RfQ>{m^GtRKo~ zeir#xZdn%#9qUOFU5flGt#_q1SR%@p7`{)45!dVvbAGDQr{e7`_{H`W;@@Gi7x6DRRXxqdsOq zKJXzx>{%E6Tp-_}#IAPHdU0O^h`h@N}fGXd9t?sXhSlm1CS`riXc`!L{{2=9x4II7Rz3`n{Lft3Om z3A|X~yQs(H^9msOJPin^{Jntm|0Qv67x%S*D60Ic0g<)&l)oiiJ|OvI12Xc|0b|T z;6;Fp$0q=po+*G#&j<>i^nHMI|B1lWV*d^b5uZg*0g~=sfqd8P2H@8TUW2JP>COct zT^1nuy@0K8;(Gy^{#}Cez2Pd@9|RHUz9Mi9U^VEf0O{{4KxAD$<@Jdl!$g~~7w{@T zDkdYo6c8jug@6p_6hLH2(I_$vNiF&jAnBF?(*82B=TQyqpUyNP^C>rZ4e-CCZ}}YHZvpE8dBjiy*adhaU;q$F&))=iHSjfJ ze*+*`P98Ed?9`yaI3#@N&RD!1;iC z0OtYj2Am7H3vdo#FJKAa9e~AvJ%E=1b_31^3<4Gbb^u-q*a~{K12jB&Od4TvnB^MB)L#Jc|o(BkE%LnX5 zKHzUkP+*-vr$C25o4~{HhtDZ}0(%7p1=b043UmkrQ2q|WGv%1IJksODQIJ}m=r4j# zLFYyDlHeam!LgoEPWrHNHODmipU#BBd?4<6ew2x@=zfN{^Ii?{lZ5~2#NkKJ_s$kv z&);SV-hF@9L~u$5(0_;ElviSW^!$w{9(3;! z_mJSlf=2|OEBMz1zg+Nd3tlGp_XS@lIPV;h|679pR`3IY?-TqP!3PAd5S;x3{a+yY z`?TOQ1%FBKO9YPzK3nj&1)nSU2ZCQIxRQ$p|4$1}o%IaQEqI>bhTsOFAS-6Hrc;vN*dQ}8aq zqk=~S|EA#oBDi`V9Co)0zDwNi5d7DIe_L=KfiOM1cSN&a@P8NlPlEqI@IMRwW5J&n z{1<}1D)`-kj|je3@MFZ$aclXzOmy1B9hkh)g7*r( zO7KC!*_0{wuFX~Wwj=yrOd4q@4ncRle!ENDM2Prtlz@+d$nc^RFkRpRSMk}1i)0#8U_ z=VqNLFK-o8uc55JY%Gy7`K@e&&x@-dEduRe-{@brsWo7_q+Adn!w$GuADBx#K&Ri& zwz|fjpId>~={o9_JU7I?8#gvIo5@|l=eFlC?k(6NYiwxQv{~|MLrcs0dOm5V@TAwx z&5TrH)<~8m2NPD7TuNBRvm;@plbf(%5))WF76~g=UhT=^=X3Ov)rc&fEpKbXww5WM zUQz}*cu2PkI!C{0Jr|T9wV_TlaGy=~3TxZfuWLmi-~n^qflyDxGmEg{C>-Vq)K6WP z#KVr;fHyV@lVYKLT`s=$gW08m>nFBLbo@%RONsVUqWzTU=e*~{KXe@C#GmNa0nX8} znxpy5(R}9UAm-@M=jzbsYR+>t=ee5mT+Ml|<~&z(o~t>})tu*Q&hs?qd7AS)&3T^Y zJWq3;r#a8loabrI^EBsqn)7_kdA{a6Uvr*6*Lo{KR}8Zz0aG7I#jk914NypGB`_&a zpVWsgWg`Ex_f)PZRqv}f_?`-y<%iub7-5I)zz+s{3bt<80f>9?^wxW#yfAgqScUtcnn8s_S^myZWRsxgr3%?efD3yq13rU zS_8*$fgwCs>kGf(8aoqW0)fkT4tO!tUqTV*MxNZVavZ^rGH>I^{Z|?9JOf!-%AFZ@ z_tUTZSbFQ4vJd7;RmTJ4=@pqa^QcfX)g zb^`?VlXNg9#hC|3>SzZ?Ifd%@%CWB9!Lu$j{+70z9J~+KP|qV9hZ;YwbgYKOdUYnW zdfi%Pvelf9tWURZ?~wK?%Td7+KAmFI4Xbqiu}7y&#?4pTGCFcIa;Hzt=3X%NAk@Bp zD{Bx8!&gS{=cd`u_JN>I4sRtsiT!l(PQHHpYJ`sQQbzMl*(c_nHus-)0HPl%nhl6H zS9B2|{_=D2kM5a(=<|x+12ekEOs@Ig2c$nIAV{V-1Oh0W;dB2%_g9?%66Zbx4ciL$ z#&mx{YtF~D!QP#^N8By_iHA7cb-r&F_rv1O^wZrTJetIPkGOMR#=@R^PDwcSXp(T5 zv#o7w*-{_qFekG~w=tL2;!0v-5}P!=v(8~tW}p?dnxz{5F#FR!6S%tl*V3TwUru;O z5b>4w$IJ)D9HuFmTY5#w{43^9bRTd2+~UM|Y2J9$Lnb(;e}~M;Jao|Y#P{;{u;YfQ zlYG~>9yig=EAvsu%^rG$AwPCpdDv0Ah!*3=&6In2Rh}AFA~BkeLn^@tDlhp>WKJ{= z@6I-TE)xd1l5WjUlCRMdj>G0;0NE_@s{=odbCq_PCw$C%c@8vQnmdGFaC&?^SN34v ztUlx)g|ro~HTUG~mZE9EU?=+3i{3(Hr*P!%Pf~ z<+hy@m*WZbXO9hpM;|>B8aqEcuw?|=c}GKiqd9|o>CA1ugB3p3Kb#qQ@qGWZu?Iu1 zP7OVh{rIb7r{%!L9w~Wn$CwQ%Z#z9a+J7V)On0EKwb{V&b#e^%i4JZ1-C4OA;2jU2 z@x$~Wx5-{O)MUS=FEln~OH23|1aLMXu8^zmhPw5!7vHqkJQ`d1rv3UyV-;`OKlf;C z>6`W&AC0--?E!rCziB_UdKCXEMvgFdK;jvB)1F%ayXyx*)E_&Wq!{UPMU%4qnoqW3 zf)lsh-_-MM#QERx`!RmM!0#^np2zPs{Inbw;~QO?EQ&b^5^V!Ru_>WP9HD`qFlQ3? zdgAk-s+CNpH-2x>6fIJ*g^U@;@oGpeAJXzjZ@TQKLd|`|bBLO^ue9F{0U?~5;O3)y zT1GY=JsayY<+j3}Lv$SLQx1WD7-NGN*5L_{9zl3?)YOufYmq7AL?it?12HtzJ4*i? zcXJJ5K>KDQcokvXAA~CH6~)FZyxju0?nV--DxYKaP@HHkkOa6r3Z4I37Z8!yqf{$-1R(Om$V-R)R6+UISM}^XE@4Au^ z)pXo#!h0PSx?j*nJ0BhAJfhg(!pK`HPS(h-$})Dm+Y5L5ZJZp$Bb@6BugXFl&lrB+ zWC!*5xUm^tp6!d+e9?`)D6*2H_ZGrYq~P`SQhaNw-I(6V1%x_VZXAsv=>W% zr}{cRMX2+`fF%0PsSBNfGAKsgd>x)3m^8b|H85rN>^+MqQK?eu>tx&&l{~OK>DCW`M4q|Kj^-2%r^WlAR~!#z|u###kL_5 z7WvbAt~0mD9NzFLh)4DeZ**G@!h8dq+o8g@FMtk=3n%3px72fDm%$cyo@b3B8KCmo zmp*GDS$xnv_oUfPiwE3ub7s$mhv}|^Zd^n{`m)ZOaYMZOMdWCL>VEo>TGa~kqM0)xZ;7>~<08!DYg+^D z%}r)OUZkY`bg9m;&A1_vrTki8qHNqr#wnQPm?g=*POvLXIL?2sxbK|6y;6K!IDvam z+*xbW$;&x7hQfRoy<56eUakiB*=Se}N%TfYaUfsn5j`w)ERQ6*6uGuFScf4^MJ|D- z0Tu$!6#P|`E8Qt?L)Z;C3$Pv#au7vcKg6SH_f}mks!Se&43&6z1gOF zj^OtSeyZSi34WH~_X~c3;C~lf$zy=u>w=ev`>5b$#8DP{or%0r`!Bs_@U{-bkLR(w zrUlf;4LXM`4gN5cfLqzgXOL|8|?W9};(< z%D;HGEfM!pai``AJJQrE`OEW9hNt^8Y8PjExGtyJiXYu|fA|w|FBbP&aSy_t=HJ9! zEvSJH;wMgYwsC*WigUlrieH|B|1<@EEd{?f1%Dw0zd8lydA&8fMJew8k%B*!g0D}( z{VBNGPg{YrLjRnm)q*swo&#KvhQ@W+xm`O)(E7G@{$^Wk6OJ!&&f40tMeHqyuo!Vu z&YI;U7NB)CwR7Ra-(nuWng`LFWpqw^0t{+>sOwg{bWjS{04@l}a`249;Z_`G`kQcS zZ3eLc;{GIBg`<{D*m_oob$f7v^JL3xK@t}~2j}^6>rG;diw5RKojy`GGg0psuBbKh zF@fu>OxUR0OrY^hOjxO`OQ4LK&a7lx$-#uBMA~8@B{>_#S*uSH<&;(*Q0fy)?X1r$ z^>L*>tt_>iKmL#QJLk;5Vve~piu1vi)&?m4YqxHArqe?@vB2$OQZc#zb5%jWJsQe-y!tD7Xx-+9NLPwu)D3q zkA}SXBQ0tEC#GV>Dv!;#!sT9O{;yGB@ro5b^|9RRvn};hRadTZsgEkx;_6D;;KS#! ztyCYd!G}p>+Q4bK=Ne7pTViv$-L{q0i)|IvKAYQ%hvHYbZIvsou~jdxuq|IvW%GHK z+saogFLzbhuBxcCc|L3N(b87sSy`q2fv>IH<@4F9Twb60xEeuTz1+5B#nrwQD=G;q zul7{hs_^@G}5+0e%v&7Z7VSC2x&$03~mYqXH#weJWrO?%1PI^42&?Q1aH8yD52V z>=&O>2lwfKHGpWlO5S=JpaDDw&#Q^{Ln$)Mz|(ezJoz#jdClD9?|q~xv9 z-j%#HlFn%&%_&H$nlCF1|Bz=22M=Yq{^5L@{RhoF{D>nh$}AL|^Hv%+eso8kE8`QK zd}ylhqr2J)#`pDte;SZx4Ssaj&1-|;y6*}I{y9LJZTOLXwZd$++XP=Lc#q)g1^<@d zErS1t;O&C{Ozgz1m7$8cEJw{9uoW!!5I&lL-;X%5rx@oFADxO!T&Becc^LJ z!jJTfC(Zl#5&w?Du=Zo&0l!ml%4QS)f#6gFLj31~vmFrswcxV^=e(C@j^OT@zJjV_bXcaSqNl%2exdRL$)w zYg<}*;}cq8F@GdR#l-D0R}!Fwvh-9*Po4BsYT~Jrd3LPDyb^+OnqxxnPV+3$OiMJ^ zG{SRQfDD3xW(aYS!2e%})BVrR&F9RYF9+wCN4C~O)o+`18fi;6kL*GHu{q2NfxgvN zNPGh0EH@o?3ysF7!kRzyfy#W;dE_#7pfKczYG@nrpzW{{jypHsz#HK88-zY}9$6{& z=#x#eAo(1byshR$^U@mOcb%j&8~m&$HH%I(kLuOqIe>CIHw)}WZ)TbCgV?@5eh`J+PjQ!9jVaBECsk>YO|BT^@Ty zL+>NN(CFEl<8STlc<(ecv%m{6936lEU|V+V6_eD6?q&LRyhnXufwL7qA6|^xae!HG zIeOa{S14vZN7m&gnEkve#1KqV?V5A(u&OCf9nFgwpS#5CEHN_WhH?{c4 z3-IaX0FY*=H|Eh@MPxSA0WT>Z>s!Q`u08Z;#LN}Bp|b2y_|Ue?ywU1Pym4EKV_gK^ z0R<;YM&TaJNNuh?WB9M~9S6gue6tvGp7}<@f2lWmBh{tGKo+K=$fQue`SL7OKY~fD)RU9t|3o}a z;n$&k*{n}YN_YS9epfewNS1mexerOe%f!uHj|Fn%7AXXz;6ZMwQ9B_NKgkUMvysKf)q=T zISevEr@}Erb&&`%lXcHJc67~r2AN=1&18^r9pqKEoQ3XGKVu$(PG`b;09TU_}L%AMOE-x%S_R`oytQ! zm<%xP=p|58Wmcgt28u9Xs!RPjH|EEVyH`WUXo(H&`@k@{$X&0h@@&v zt_k~owhuW|lY^4EV<#l{@T&dP{0)9))ruRzhzq5jv5Bt8rOoR`xFQ$YX+Wg1ch`(O zptb-&$7l1pkq}}%x7)jg+gb1++hW31C%^@K7jjn$u7%owHLo~ae@C%D9&}Hvx@_Zk zBR+$AJ$(#hk2X%$7;T$mw4p|P(AUfX-~MLK^!SpcXs4R48_c|7TH=bjIFH5Tq_Q`7D=GwmAd_FBv)KJTNI!~GKjMFkteH91R)(AWq2M?*AF|JCFo za@_kvndw(TR=5Z;O=`!Kpa(u~%%4Riny)~$wjO~K=M)vJe>Q9_?Z)uMpsDtu@v5ib zUrnC5fBa*5)UK#?-|X>ky=_YQQ>!XM)>)0){MM@C6HobDZ=2%X^|3!^<0PXVYz(uJ z$@2{Fqm$Md?Qf&VUoJHx6Z3Sy)d%1^fI`-yJI(T#Un&NiJ3JKI0M6Zd4E5Un^HO|J zA!}oSELyQ+?$~oK|HQh24SqEx*F#qPgvzZm-_M6S`@HhURy`YzF9g!O0WE%pcUQL+ zc^`b%x^vNszcsh0|CbYQEm-fxER)7AZuv3Bo-*QjA;TKo)qJNXH|lM^bGR#l2}jK{ z{X^x$3U}qHt`U2zKxP(Hr9H85ed?Ubc~;l7yW?{*hwL2W2upbg!1MxLrugb+}9rHvl7PVCU_!FIFZNZ5fiZ^_<#%e(K zTR#TFXCM0i)v969(l4WzwNU`}*1*&GXwaEs^2@u!Rup*%?p#&ayk>+eI-KeID}u!v zM_7@kF|ltfRl!4UFjE}0qR-ph9=kCiVPQxU?(FPu$@0#eVg3zcF45RiJs-dl!Zpdw)=|(4> z>Bh7Xar+E2;`SKkXg8U568ro*^i%79?>DEbhE)?q&UExgh!h)ZShpbDO{nhE*)4Cd z!X0_KYmTOv{ZdF1#VV6)kM|HFMV8Bx?R(VOzJ4WNFN`@*wwIc; z@tCY1*>7@>1*Sf~bxSUaTJHT%e|4g*(ezi>SgT7LCqId$ovP@dlsfgL6pM(W(OB5RcB(mK6Y!#7BRnHQbE^v#d1U_);9cFd=;<)c#gZO-@uTI$kb1rK$NS zW4%dELI;siE;k?O!LF8@=lafLjMBB(;X8s)yZl?Lr?dtSfaR?X422lAA?%&MRNRP1 zN{v>ipwX<^-x2&BTJA4#agOPLy4=YpJptweHY*&X<_$$7|&w`I3-SHq3GfneYa=z*6U5{W$+-g=oq^r=B% z?~C{Fu&j!c-I-^COlRd&9}>0F@V;Ac>b7%l#OJm-eDvpSb6~mv*Lt@M0^yKi2X>_TJn685q@$m%f96_1e;7!Xynztb@;Z^SG|0gsve5dPg*DE zt0zESK&4`>NzGaC1xbmjplbSxN87d_%UQ zlE#VAbK{iO_)HavbMV~DW4iRxoABAuG7JChUaAsx_ELxu;sL)B3(ra8sR9DD)5g;i z98Zb8e0slU6#hBJ5$0cZ7^$(?hBkL}D5wpjBw>y$rL$@nYwq*SkEk3)MtOJL%lxCd zWaDR7oU#enY^QHvd?0ESoO1^nC%>$1^Kp)3@7+&>C=@$B(f=?~!eDv@Xy3OSJ=u=a z9#Ws0O>k|a6z}Pr2A?-uI3T4BWggJ=t|y7KdjCwb17`)5@0L3pdBkR4X2d`dr$nBj z&@Y6RVAfzh1S!D`%6u5WF~AJA)tERB_@x1}wclEZ6+XHB-d3fvtA$nFVclDfa*BOI z&y#1Rx39y$^&8fT^4&)+HEDWfq1NAU{5R~ZXfq5)>qnex%@>rj-4*QRfw;7N9|cRL znmN5f^coRnr3|!4gjp$EB~UxMQnK{u+rd;gaE(aGPfIVkC56#ry6;PzvGktF50Czb zQMyF1^j+r+k7C#aI6YTR_HLp48Ejj;En$oayPW3355+|he$l3i~a{AUV~wtP+GbIaxgZmN7$`Xn!Dh^`VGg0buUv7n6CxPWDZkZ zy009$RLU6kpz5$mE)9BjH3S@s_9<57Q#g|{rwW9O*h{|pltmk@2vrgk3k6%{F|}w* ziPdnEs!&Duwp{W#{SW=D{`*c-K98cScw0EdsVvFXf~3n-E`PHE^$ApR>FC1OW9ksc zWLw%xIs)KR!X$ffe_m$`L!h#tO#!5yqpx6zl{n<}05=2PUB(o=48NLp8#=b z#gv>C2=|sz59!qKNpJ8?A8?Pp(m!5Tfg-P%JYJg}_M*ntm>Bigb;2BCtI}$KTr#!1 zF=14LOwJRdgG`R$r?<(smRq%;ka}AV!h=vr`*^@ebv>0ZBHzmsO%h4A3SGGOR4!RU zO-5wNP?y;V2Kw9p-a8F;k7aA>8v;P{6;Zf_@6^2s(m-p-?Em6JNDU-1{!d1%w&P^u zkj24XV*1`ARZ$aTa3NtI2gM?OCgO0x{-G|w>_p$h;Y8xQkm3K#`{}<@$n(FJeC=>w z3rP1p0&TyWutYqIh113fbB`qwY3F&!fTw(KTohF_4FCxS??8`WFsY}I@yZE!TYCD6xb$(rx+6CLqOnQ<>UV~t zGNb2hUMFYzU!sDb;t;23ooxRZklb!lK2(^H*$L`KZB2b+fl{R6pIAMHhufR+#A_9X z!n%P-oH*&^^Ke_8e?vU)P1PcxsPPVfb^&vV2lpW}Qs>(0d~4S8+#vfCxTs*+-^x;B za7e8MJpDT8n`!08JIQh_gCFH94OsQLxRg_?a&!bDv8Rmw*|B5A-j?O47P}6#tIQ%y zZ#*)u-soY1S9O9?W98Jxi2k#a_Xj$lJ$~)vRu{*P-MRXUv14Ce9Y9)Uc{;W zs~G#A0sVUN`N&1&^uFid#{G8e*g9`Z2M`RDWODxqy;(^LjctpVR5aY2s#xE%v#)Zh zcdM~=`E$K3-_Z%{a>Qq~IpXdMq2EJ)5nj1Ue9}*%%fr?k$v&b>uj9nCvmLk`L^#|S zs(nspa0j+OE|4*uF)Q_%vB%3DlT~W?>b#($=OSPdNv`vS9t?MvJ*oP~I?u4^4c=W%XIL9{RGf&8_3m1C z`os-8qXivRXAEtvI$cevR&+=IP*ooDMC`=S=sDg;o3OC#jOI6*GxC)e(WgT?ealPH z9Z>sHTy_K*7#bP87rS?tRfER-tG%~Lo5Ohy0j09CI^aGA3MD#jd^`Sw6pa#XM~MRF zN4-^;t^2>Iw^Xn=VK2I|$Dv{5(`nsa*$;3Xd@dDyQV5yea z$Ai{SOJLWFGq0WjNxxR>h4!Zk+w#)Ji?EyA7*PI{6~0vEW&}#1`#ycXEXE}RuF*lM z$1Wm`{Jc@f&;8iX`Z0T>3$Gp(J2uYS@+SJR|51!NS3fN7Ts>9k9Q{3P@nXKl{4i)m zia;kxHUUP3dVbTp2~DYn2C|Hi5is9Jd#hsfQ3m;BF8x#jh$(P0K2^!}fa)WUv!Z3L zZkS9SIPcvYCX>%lpBLc&;Nyz+?eX5tCoO)yQ^A}t;ycKFk^&wwU-oxmdSH*@$7ubL zTLe$wt_T!)09}23DB5K85U1rH-~)!@FiD1jV1WGU0*VJfG<`p16y#0yw)`ifu!c6T zSqs9}L$Jpjx%VPimOZNmqCLb0Oon7SsNqAbwTzVuMzn$Vr-(>Z-hd%FDeI6Fn>?9s zv!a&{=o?;A#p!zko*fO~$9sGyEYMfHcef%`to3>!zrX^Kv-_b*w;JwliM)qW$X)$6#g0#k4&BX0?5~a;zs}pT2cJsvO8?cn zIe+wDL8_{&zj!x@`L6!+cMl^tcQ+4J{bwi{IsJKRJK8^(hiZ_!H?%?RYKp!c1eZ;m zIdg${n7d+PaQDXBxa8!T!H4ZGFI^nEuH>0=GQi9gc!Z9%SQcOxst3IvcQ|QGcn14x5J%RHfQ? zHbYrZv^U)`LE;KVmABuQ+>vVUDfBbWmpFGO=gTO{{}bF>1Th2&oxgh6z3_1&aS5_B z1mD?yEFkS?0)7R*1^6w-@B4`BSwQD+67cC_$7P9bH{i$h)Sj>H`&sNC{|ozf?j5;@ zjeJ;~*abR+T^bx92%AgW{GCCWU4k;X1Qp9#(2ROc+B4~}ym$j6 z0MknD*)RcaV=tF28Fq0Syjy<3G~!Elr0svPV!I+&t8JGKjlCEnjBV(?64zi>unj8V ztXT)(Srid?GL0E{mR? z49u*mdlT5~-GCJLkhR+0MMHWUmcpB@;0|2;P1b}a?18WYb+5iCMP5qJH=0>bbcvb+ z{hDKpQsA6rQyHqMKZ4%N`#e&tHo2#Drs;QE<~HpQ@YNhp5HJlu`@gmnay#6un=1n!YUj!rIQ zPW6FaHV?d7UjV0qz2Cq!p%468`{CJTB-$(5*T1V~m_sU$kopp;50*ottKY0C$GG-| z&7yYbgDnC>)|uqX%8iUvO_~(v0H(ujRtw9(m17Zhblb4uYPRPHe{5qu&Q5&xYFot~ zVOd>~FQ+DiJzRNI4%D=yw@5ewlA1BV#mfqiS60;;*44atxjEzF1yzUYn^ffQn7USN zMuKJU#*U4TECvL(h~qryPds7gi<=hRwJ!lTQ1ZrE{^Ax-0^c>l6J2 zvS>GA^d;j#qHboM#G-(^5BEmFmUkl!pb!Pd_kl>1okC=jhd}$mbnaFZqB2DY35F|$9r3z zMl~n1`6#Kve(SdM`%gVrr%|^%n|e_t&nW| zT@X~+Wthjq)_mk{aV>jA&|1APRR4PJ`qMB6v+Tr^R}zF%<$*F>3rWS5f2 znHZQmTyO#5BJOa}gbUf`nU8b*N1zln0)*iLYc@t4#O>I`ila)P4$oJw`OP+!`>nyB zff+fFv7Tkpj-%u3z22orB%L%f8JW@*acUB5db^N?&psxn=#@(DnlDAI!vv$F&mcpE z2WkYYN?o17gIIb%hI(0pF5M8_h%8Aai#_hMxk&f1R7o0>qK{a!l9fDyZFX(Rbwqr+yk~?Uc@2k4TPQ-&R=dA*s_b=#@>JzFr=mN8Unz+vwk zfdAvJlO@08=c_eqz@N|lL*2Gz@7A1qMxLqY};!QPDt;;2DV2yIyu7sf&kNzj>R7H{9I&KaXSeuki&= zJ74R3+=B z@CoGRRe$1lYq7rqMHC_7j>af^viD6)q;S0w9YNda9%DX{CG#Gn9yFIB^Ze4MTxeIF zCHsf)dzbso1Lmv;x!n96n`=z!Q>WzSV8evtc^j5>)UoI9kfw)CJ*P@? zPhjol9#gTc`>oZQyC*{Ko?F0zzj_j?XVa8;=LgqNPF`Oy`t6%pZRsSUB3{?NpgSyy*tklxhe|oC@9cfNx zNfiHaq_5v6_XnE4bZm;hbhP3xjdY??RCe&-qJNf+^pPFw|B2k9r61SqJZgGN<(K!K z{`g(V?qla4*P!wqjU1p)G+|oO`P)seIi!TRSD$5D0^){YNAd!jeO#3$qkR$kUbc^N zL(yz=`1(l~HeKhNA5ofjA(q_-4Y|I>%bFH1Z1By8&fw)MpflIEYH`!z1xp%yOXe?V zSmL9SVjpzv`X*7wt~0bt*+5&b)6)0V=+YHUh!j%ypla9GRKFaGhL<-Y_IfB7Rw|FR zVqX<~(-n+Wss2qW7S_5|w0wA1m2XMID(L=o)z4qX+(w%kd>2Di@5R35(THSx)%=xE zR_seE18!o{U~+1Ys7>M=6_Vvs!_Ic=4)EJbiwi^E=Rr3UqS^PYoQAonw+7= z8DjIP%mq#7x_C0G0EJt;?BY~p#cZhC8zA|7K5{nE&WoG_F+i-%%&H4g}ATBEk(BYE7j58<=TYs+1%U2 z{r!R5&w~TZp9ZME?c7$w>=>wie9GBHc@o*$=dif9;^dPpe-xTRLovwN+$)Q<``n!D z?%OZb?*BYM{%cFL``rN9>bFPSzd1no6<6r+7C^T4qcTgHy9NlqtxUWB6d+spN;W)9 z{Q%*2eo?#sc7Xa>L4k8HFAWfWw00g)ul4qJ9+46Wjz48=`Ifb@q2Cx1AAC>lH&OFi zE=w5Dw@>@$cvQyrFZz-%gJlH2Uh&6qsf_I}L%#+6-;ZCx6FOeS9?1Z<{|xz-^#445 zJ36#~j$37H|5@a0l4sxZr1mf4I2FGHXS|oe-{CIpkKb^OxoDgO>V)(^tp8u7<*uZ*3KjCNr@cokakqK=pIfHJoKEcHztpNqsl z=Y>=Gr+$I*mvsD`C(`_9)Hm}Jf&X4b@kk^%Z+x16*313O&#O9q&Lhg$`FHfI1Mt@) z{y3kc`OA`zPvF1p4IMA%ms9z_3_ZR3E$yH4&8hs8-`Dky_Rsm})BLOUhyUh&?Vs~e zntx~e!(XrXM;)S~Woh=0yoY5udsAAo<)Uv>PP$I|>~ zi9Z7Wt>T~aTAKeX{qcVI?>emG=RB9@KTCd|hyU5&lceFi_i6s8mMb|UC6@wz4f0-n zfOUYU11UB27Ci>E#U6}Sr2W1bbk<#@qJ(H*9+b# zuo{s0fO0$PGbuTW^_KbkGa&Q13y|*r3dnfw6&MGs2Yv@2^H~Sj3|Iq*Dk`i7#MZ3v zda=I>a47K00U7`K0#64V0{cUk>vBB}I3Mm01F{@D1pgtRsuzJP02|=G5Rm?6h1_{(c3>{QXSqe+0<FnFq*tuLETGGC+nO3y7vJEC6Kq zQDQ$7kl|0D5*hwK0oTL-&j9Iv5#TJ~A7Q^l`*#3o|9wE#$2S0(&K5v)ox%-bKOYd& zOUbQ(3jx0f$o_T~Alv=WCAwdB0J4654Hy9&EBJ8`bs0>%K}zevaPJ3z+sPk{9QO~J1KWPJqyncs52X26R8S-!D=EMI}xj|61-1_QD@Z;#dO^CBR_KMRN|D|{I6 zPT)%bk(H8CK&C$qkonyLK~ZM{MgW=5n*i4UUJi(;OU?&mK1YlD`-R&65Fq`38!#8} zE`e(Snf})R(RB-N23!UF3P6t6aexd*frNygjM4MYyMV-B0&D>MJs{KHEB3npIS*0) zGV`+<5K)xe0Ei(_QU*8=@IpZLw|qc`&jDn-htE@T9!q`+$ox`o@(92i0M`Rv3wRo$ z90mAw;CX<^MxknL9ocpKmhz-55b00*HduLESd zWde%;ncp#h7bD&?#oi3-F%7Ne`eOf};Qs`e3-_&puL5NL?hyQofNO#00y4g%qjh}!fQ;`sK-zyx@FqZpUnF=H z;Mag(1&FFCDFkHy`1u(+{0{*efqx6|PQcB87~&-h069*+1jz7JfDAVgknxNITmg6n z;1a;o#Qnb0b-X2ji(#J+$ozdW%H_Hp@Iyf6`!RvP0c1Qo02%*wz~z83K!#ro$nakQ zWV)vVGW_y<9p5#8%E15zUj^O`h^eS#Dj>^M0f-@9a*4Q~4aj=S6X*tH zzxZ&Zl2=#wE+E}s2c-QU05L=hpBDRlV!sOzUA^!wK;~nKz%u}u|Bo?wu$*@R(tRah z9^iby&45dRa9)`U$a&>TK>GU&5Ol4QCjikEN*)44(Mx^_*bMkDfN0vn^?;1$Qb2|q zCGa>VB{WgVUjdf@-Ui5VI|Gp6s{zqeh1Uae9=Z&W@t-g5rvswu3tN!+6?6wg)=JI; zTn_j$CL^Xh2axfG0U6#8$oMY@M3oj^2#BgEd~>J{_cK5gUFpAId>>%)U_7@2vK}Zs z07WRg81U=BF91YV3WouH4fu({I-b7(vRu@Mu@P_w;LU)ofNZZ?zzu*G3VbJ56_)~f@T!1g*-(7(Csd_=1 zxNZf$2$1nk0Gth2iO3Lch)*CRC*Fg|3EKp27uYOtp1?|hK7lTQJqWDA3*0WSS>QZ@ zl>&VNT>^WMKYR{p6S!Sqv%q-*D+T%l0;q6jpd6HKYtx_kP?-33#oBDhV@9)@~k`O2lfPAAU#zf_0!iMt{0;{~57_?6<{roT=W+@|MFwehQU ze6t0wEY|pKf*1z#n&O`qLF9Qj=!>61Q1e3{_i68uiV|55P2Oa1+`;N!&o z7lIF$`unxuE#m$#any%Rf9??Xe)0c%+x;S)|Cfp5XUk!IOZ=Z9{@)Y-Ha(nT4H&;o zKhMFW!tyK;|9OI6C-`W=s{}6;e2(B33BF43D+K?&;N`@To=p$0CXNZtmdncdm3ZrQ zx;(cDzEkj}g7*l%Uhw?uwSPjc(dSx5EtXyDflSCdjuaRxX15O<_f{f1;1YKMS>fG-zWI3f_Dkd^^NHr7Ca)j zZ;Fn8v*5LY-y?Xl;6D_6r{KR7yhred1kbP1@wox`Y{oV@=qq0MnQgZR930L{F1Zu; zWw>JvPxD`zf!Al?I}n*Oz6FEQ@uxEIgBkvhWVj#6aDO4goeW*h^oD1+w`8~%X1K4; zaK9k~e=EcPtr_l@X1L#-fgjGOpA{MI`!nMEIK%%X8SZ>{kH4h(c1C=6X5epR`2V+z z_@`$0=ep{Q|E3K5dl~UjuDjDe8UCI4(v0*T%D@k0;M6(m3~yz)Q%srDozs95|5Zl# zt_=6t8F(lI|4{~hZAN-Z^8BrJTB5l^s_T|DtPb-kKDx3&*<@-%Qa)C!1Y3o2R?3mo z*X+8chREV&E23Hl(rm=EMt>TNRQX9MKv!s0-GccmS1xW?X)8C%)QW^S*Dj09Uz1X` zKCNzLgN`*rw>r~XEn0CXP`?Tapc+<4s^Fklu=sX`OsgXciF~e@AE{rY7!RBlk>!gT zr1UfD8oq`|ovuq3H`yhOEWe{+*_A2x+Z!T^yF$F*zI<_GWMx#><22-F`N{?`hKOt9 z;x%Np5DZ)zSF*xZHrUxjZK9~rmCLk(fN4-U)lh#&N-fp2I)<6QY;7vYvgpzU4J)Tf zlvH=5HCVCIAhUiIN_D#(+rq_7^^3sQ!W`LlsR*NX4bciL7!sx8=xESNwOAnPAhMHF zY%#2PI5b3-gGodh3OPqk{8OqV5~#G2uN5o7c(NuLcj|k^@}?Am*c^2ZHljP`F9O?& z3YMl+%udLTk$Jz#&K?`1asHAfyTTpny6h34v{-?kXjvUOYFzA4!hb?-V&HNiZ;h)? z^%wD?Iwl*Up+16o5tRr@B?;LyD%34$n7^uF0r-UO5dU8kI6>kj&l0qsp|W*v(y@xC zGUNprS-BFdLz0}pt6X)8+X*?f{Z_zpv=LR=08Sh<>HMaq#kVh$Vz4{aE#(NXBSPFL zbDd&gVn>zuZRHcV{;6w1i-To~y|{64!;*z)byr=ap(#=acC2M}x>$7!mM???v!>_* zqza$&7k)JgA3AjeT)t9ykm&77y3$rVaiy&Y%!WxF6SiisE3ZK;Xe0FBCcCWVs6A@2 z61J*3C~8{{J#uTs9nLEo>Q$c6b1;VWr_MuC8HTOZB8$EZyOqk2cCr@cN7p!%ltG7w zbRN}}QvFAvseYr?r6s$8LhVLXNV4ry0ok+)OYd?ztlc@a_f*3w-0l?GYpOdaJk=vK z>TD?qpc+wqJL*^AY(@3q>@~_FS-}dkD_$XXx6z0+qC%3jnvS84wO`$B)OSXYqaDn+ zvMb6&;hT@9?2F~slwEbrRo9gId{>p0!RAVQ!M?Qg>IoBkz6lkj<-~nH==D$|T&wlS zrqAOr7iJ$*Q8YDIt8<~&*2(`K5PxX$v3}FoIA|=Sv)IRZ=v|9&jZB(M{TsGJP|nMY z4@W3h0fTj7Kl<#BiT(_ol0NEY{{2T>S7V%!xr6Dj*YgE z2-2cFmA;HM5@?&m*NS>%e6|6q+S$e#c>#XSNbh36!yw*W21{0dEq*jOE~p>({-8CI zp7^;9`R^gSy1*EJ*l+RD?zL%y<-M^WuFEIbRfy@Gju%r-;6Dn-8#JS}%D{8Xuvry`2#(o? zIc+v1<|C`B2Ak1_D(~t&F!EE5^otQv_^&&2Ss>J7d;aF*RJs^_*QlRXsoo^U!)~yW zPb=++{j>7Z8M}`V#^{V~(_dgJk2TZAe8GtIH5>6-)WeK?R0Q3Pcylc}ApEo{KWw~% zs-Erl$M$;+>f@kd3Ou^Rdq>S$&2Iy(R!99FvEF9=P~mQ7BGjpXN(1jiE=|2}vS#B& z6(!r9)Wip)uQSF_{Vgb-QiG7>+NZ90X;jst)T75f#%|}&@xK2E5|q5ju9 zOW6D^(+QiuKB$uW0T0<_x~`4*hMf?1G6F0+hJ_0T<|_Jt8GHbOhR_M3yCF@!jc+aX z`rsyv?MD3D&1_!vyt7M%xeEVXW{lIAVSf8Q4YmVx#4g5vS7)q%00w=CL;?BSo%-xf zefFe2J*iJu>hqY60I^>P%fX0qP0Dda>XXM&Noii{b9U;J-Bdgnsn5#PXL;(gH1*ko zFl=rl+^fQ~*j5`nbjG^yUsXzHOg(yoJG||LZyFXq^~vM4*xr}=+?M*}&=e0G((<{+ z{!BjjXlaAkjtHJ2zpCe=u{tg0vWaO{*lnVNGGJsI&Q_Y2l;&H!4Z6`z+h zEL$GEeUT3uo|ms&iz0|oQ&&3aN4faKo!1F&mz%AgX66Z237Cx!eY?1GBFW}%?@#G3 z8=t*B><^*9+4$(UgC0%ub;O^I551I|U6}Xr%NBpBM>+FunC7JNalc06zVjxRdriJO zKX0gK8+>u^I|jc+kWWb?;ZuCi3z!viN%#4hJDSlV-d2l}gvafBXjAY9UjThV`tB9bXncRm!u$@75Y01p6O0Qe{%`5pcV5LbI8-xqu} zAlkiTrr7h|lIedF5PhZO4nXE_4&XU}uj#`>;gf(q;6DW%3z=Y)k9HC8{m2B$I{5)W z#>1tHaHYUvK;}P+NNLZF2>BsM_bmYYCLry0()@@Ajs2H~6caQ68rPw-Yb-<>PC68VMrz|)}aReXRnlru+t zrAjgwaBdTM?=laN<{okHk@MMn*wNjdKX!_{eJ>3(?cU}Nao;B4=Ml%x9{+z3_a4db zMhS1vKaY$1Y;osxCBttAr1`P9d&K=uu!B|7d?N#=$Tp|@%nbKX2Hu{5ugt)?>2}8V zw+x()PIvT~H2fzS_^u3`dpBqJ5g9neaXQ_(t#snoW#Io;M*NDD8YJ0vVZ#DV+zx`M z8EIIyuqvb+Gl=cMy2h0a4dONLe)KMGy`a+j}hSOzc-Qs17wf*eWr@Ht6(MXf?>p)v?TD*Lj z)BsC5e~IK&Q`a4ZP1dv`Wr1Rzs_c}Fu3#Ha)v;}(n?P5mZI`UYq=lk6Dy)&DdD16s z0=BMhP5*S#Fq0ltFio`7v@u0w8x8|Hn?aGRBMRyZA8*dFXp$+|zCL6tN zJ3FwCuA1IvA7!*n`u}FE2Q+Qc>1`a#j-t0=x>x42(%a@?E~H_6{3KmK(acV!w|%NU zSv#H{Mh4?UKAD$p#K*kBU}jF4Q_;sNWj&~raxxOTY>Z_f`j`jvF4kig>2t*h>!gn{ zD*i|x7}ZhG%b1{Q@jGo0PXW4@ zl83W(x~H`5+8aI5E1HkzMh7Es{{@aX7{gB2z;STLop#3V4kg+`6^B<} z;&6u~;qWyH^O^R(L1uS*&tP{~z};2$Sa^I#xT2%!HM5)4Jcs`z{bc40zi1w9EZECU zmnw=MGNmR3Dvocc517ZO7L)hf(4`ZC2-s4dW7v zm`_8zMow9xe}s~cU?e&z@Uql!ABNm5MIML;u5|}0j;(*A<;jf={`gcV2uPJz3DAUu zls~~Y*E&c}J`yQUxm!2poe#Z-l+SF9`MqIXXP93ISri0pPI#)haoD3q3y4i8qJL5) zF%pke>|g&26lmkcsz7V5)+K>oZu?t< z-6!0C^p_o_zTt}YCP;>#+YJHmlc1S05jg*tQIFW6jhIq4tTF8n?T{XymjCSCaxbzH zn7A%4`d+xAK0n%P#3|VbbhX!|%SQj;-BmR#b{OK#YP!98Oak$DAKkloPGpo$r= z7EOXsn&A0=57j?`%tBstUc1Ty0_^1+=AipB4@{r=$eIVnoT!A9j)OSlIwcsXYSH6Y z=>w#^Gn@W^iUUO&+5kx^<&Maeq;IP6MEbN+UL5=Qk4?o;9a;>9%IUQ;+XuRLK7)qM z6-f8Cx%*U#w4u3N1AF$<82*>a*OUR=o5j6q0C(=|X|6}i+0L={KKB*4XFCUz?~vwV z{IZ?1eX^cZ4&csSLNm}gcl$@`SeB6Tr_PZ&Sn`~^L;OiSWc9~$ZnyZ8`Z&qoW$^PI z{Emq~){8RsxiRA%GW|b}pGVG_tS4n`{~71lA~=4CAI197u-=rh{X5RvV-Q!H_^T9e z$#>l1Zw~4g>vPEzK&)XUX8>Z!D{%wjd{^=g+K28PfT-(|9f0(=5)fBuB~!$nBC%=z z99CuWol}hq!%?siVK4Fm0$Is<0{f94bk~xFfb{PZ*aiqML$(WS7C28}r9huR0Og+= zO2`jsuk%3D&QZT24)@uz55O5zpQ8Y2+VG=$v$z)#M?&LG4iQ`9iyZ@db z4);>oPkmL~?f(C+xVyxi=Lm+k`}b-1R{0b6E5zL%Uz{K5-Yw~`0gfO^GbsbVF$15Q zfuruz!nb7L-^;+&?wl+=OP1ZPcJ3g=)eAF_lhem>sz^HtRMp{p5m~ISidAG8=c1ZA z2d7c`2_bbBVxlX+9)bP1a8DsGOSmz&ZK4b3N9Jc_*51-fK2s4>-8bu)vrXXOTM z{Jj!in+(?bB))?nj*ZlDq-F6`=a?O+FPcRXYBt*0nZJR~F$Rf&2v-0C$`XWio?}S* z;g56T1^ChJ^P1$oU&%ELnQGHYJ;l&Nfb+|i-ylNhUWryv??G-6^goR_jydQ9@9eG* zyrXKmty$gPTb}&Dd&&Mr@8w<5)9=i0d3IwS?zzh=9`oMgNA0QIulT6JWN%WCa6+Wm zhAxE)`1bys#n1ijz<~oy+WlDnFv2}tX^r~*yd{@=^!T0bip~w!QmsO4{m25`o`&+x zk0QN^PL!dOY8`Tml&%Lhj$!4FKG+l00glh9;T7Lq0g# z<;U@v-PF|?@EjAU5&~mMF$SA2@l^EX{!vmw#(@Sc345ew^{&;0#Vs&}b2o4a)k zU)JQBUHzw-`;Weeq4kV6_!vf@s*2|hC7y~s<^KNBkCP1!UD5H}cE>q7wx%E_Is!2p z`D%h1wC*&>2E|O$7JZ|Cq#+G|uB1OIc(60rqlSKb)XhvviSFe#K+$B%n{HKdiUdQ=S#jS!!jva^qlGQREpRZ;DW+wfsGm{JnFFIM#kGU-O7@Zm<+Sv0Z?5@v zHveTeGiW}i2Eqx$(rH7GE2cFn0)rN?mS3WM(4aYJ&o=MYoxmV|6G`aiG9UNH))!%- z!FgYW4pltvZ5an&hWVpX%%kk(A*-fX&!?cJtlD72Z#@_?=N8A-9)_yXlMfp(mT6h+9`I)2mlFcZ zgO4?z)Fsr{f>^`mZ;I9QehZ{Oj}LC=zis^2jDJeGC81I;3|OnYj&G?1grX5fXLJU4 z5(c4b0;5%lNG^NUd|Is+fr<|E=tfVVqCH@CZVHyYRB?RMrKkcl)C)@PeLPTbtn8&^ ze~y*AV=pE2{0{2aVfPR3Wm10k%kCqfn#DdEyZ!SJ*s(?wt5oy`rwe*R94YAl7v4DzIFb50Q^=9lf@R*u^5V5o7IQgEaSn=lB3&N)&EMIzXh1))gf zH0R2h8lhxex`t%UlT?>tAK7v%l9pAXe`s>Kur;u$>Py?-*nEaih2n|zTpv4j#_G!w zT^RqX7hwMS00m2G`{IsFrpQE>f85YM3$C$aqoY@atg+4OhP$HYS~H-JvPn?@RZ?aZ zsen-SF*YsmxT?JVFU5|X<=EpTo{l~3_FF^Co;`X5-S;2*%efIAiq1HgPutNMgFRMF zPfpDnYs#=pm8ZoAVbtUNd7LY`L&Odtl!F~wYAJB6X_-lW|0u*#t6dCsP?&^s+xt7t zM(Z!e?=JlA$IsSl6t7N9oa$Urr-D}(+u06w<~uM6+Pn2*R?V@Tnomw%P^a5lT2dqVE{>rGwJ{77!a_S2D{>Ho<%Z=6`^Lx~G|MkRv zFhq^3MgI32@i8X6=D=%)-1Qh}%+cXSMOD6c%fB&BIkvpr_hVqmeSwJuw;2{Lbr!1j z;MOPJl+WYP2daZ&dlIpOzTDr)hWrn;?CDv_?s6yXj6S^~$Fy%l{`7umn!O)FHS3cV zSYtm<(!bSKMf9@FfKp;G@1BL;P!O+8aCwidALW6XJ8~)5+lh+lKIpE31+);c-iIT< z!LldAnoHGh?&}|h_z+dl+~+sD{Ba|JdyKJ0eY@TUPAyP+;WF+mxH0R(^#2T+up3P{ z>#$XGIH%^rwP%@KM-NuC`@Mno{=C$^iP?n)lk?dCojL71lkCs6tdD1+gK$q__vf(L zjYR^*9E(y_#q*%i4piAq-n*{B;M3ZSQw8kzsQ&3sv<2g{6M>0!h~qf_H{Hi z%K!g~@|2-GeK)ZX=Dt31Ib&ZCJ2uGs^#XjS-y8YkqjR2lC%zJ`{uWxj%;O4pgD-jm zkC~4J#=jW*$i4c{eXpZv0kbVI{-BEFIiRU}$!O22_=JLI-jf;YbWV-x41mVpj9`u1 zFf^ae*4$@1ntOy}eo^f`&}l$VUZ1zUQNULM-T)-}>ms?KY7%u707v}XeaIwCd6kCt zEA~u$V0%R>gb-^yPV+5p^6_C{hSiPpZxpNL;IL?1vV65`@iM$eT)fbCN5fhl#71At zSCh#L1f7%5`u|_i!rAU~$j?Oc`vKgWF`8*!#V=d-E6k|Ae+8_1KhLmMQ&4j zb$y=%FOnO4iD?seL*pm8=L=zU5!|z--z@H@A)nduzm0@67~Z{P%U_!i*S@8_os|AO zoLgyFKA4l-cZ&Pc0pj-wQ86F&oQ>}lU^&`jt3kK$aG%tX#7`z#K-ay1@5mP za+ZVqx5T#tGJeYUKp!i)O(5li5HA9x|0Bo@;q!nO!v5EQO!s?Ye-|J~`z7-MnZGXs zGJllgLVLH^Z_CyB`3hh$>}LR81Q-IuU*S3U$8`RLe@y=efGpQKK>A-O_SXR7udo3B z7{3RQ>AC@#?n5Xv!+#Ud2Y4eO{z|Ayo%WBS@JyF-0gY)1#xea@aGW6&t6wZ8esSp;{HW(x7UTY#JyMC`5=wq?RDo# zalcR8AC&a%byM*(BmOSQ-*Rzph8@k%C47N|2dd&%j`(+-xVOnY)}`WZ?;AL$s`88b zKa0D)uCEpM?UMd|;%@H?mWcZrai1#g_P%0{xYvq1*92H4%^x%Hz6^YC2F^9p8NNIN z=bGnqH#6|tGH~`qr+L7tbMSc>au;Ti~mQlH;UDHpmt8Z8gUftWTlx%?wTE6sUIz*Jr*WpsE!>QYR+}ZQu zya8OqSvZ&BniO)ffLzV#zLHGI4vqs=2q?IbJfK91RY9c#M6(I#%Cj%>?FvfaC|3ZxL0CxyWYHJ8GXi?qmf7Sr6*kYx&^o*T&ZSR5gnv}QY|JPDKt(m_^% zV;cf3>J~PoCg`@Je0REWkv6>azgIJfw&Hi;M4SSVs6u z$}Iqk1K$>@esLk7Gd`f7$vE%hPL#bAjw{k&iavCMH38ZUg-O}E5jQql&ha51N(z9r zrGVefc>js}UeD%_Tajk;fP-SI?`v-ckMt2dxi!o`s`eq3D0-%%LGyaH$GdCV@L}z( z(}tI|>D$6o`ph3lma!gh?ATE1R38ilz19%WobvlYd7=)tE$usy3EWUd&NiO`b2+RY z+|PU&W~aXWlY6nb`>0!t%A#DPBP>|H9CCJ+xwJ?mmvnzcT}bN7a>-*9EzL@a`oYjp zGKf zXh442UfjRXFnwk0^P%Hh8i0dO_)eJ*Wo&;A{?sLKC>MW{pOen792XbiJoOqN#&XHm z1aj>_rG=)9*hrQUygMeUl8rcnq^VG;LK=8_qYy-r+F>*KH*?_$1#5rf=4nS;G zM{Wm1*+i{hEds>Rb>uui?A1oj2E<%6 zvKDYSpaF;}YGfrK=G~FyfF8h7KulpHivckekMsdz>H{Z{_J_1MZ;gas&Ur{m?E_Uj zXtW_djU%YCAM$NLo?G%|KK&(ee7{EzFc0EK{HVfQu7?HZ`wN=K@#8tiUVok=4*xmQ zLtYYmxZsBbA0>Fd;Aac|H^DjI&@dgwr-VY_oADAa5qI*x66bk^hHrI=PZV77_X4jL zoaYw0PZRtK!EX|r_cwH(Ex2Fsxq{yyc)j2=1YayT&j}2_T<`|L`JR<#nc(XLr~F9z z-z<2u;N+E}F$MpI;MC7a|KAdv=RV^9C^%_AJV)B=Bl@a7r>WSKOm1~fDwoCW3US{q z?wg1s{5)}Iv^?k8W&v@y+w_|+5l8>A_X`&QcX)SIX5i@SY3^#v?Rf5&5^gw?CyNNC za(f$Y@5#ks!CL#7<4GrvnRSu1cy_l_yF;8Bt5eZJLP2& zMwYoR7GY|xI>pdyCn>&c*=4qt^bHWn4k z|1`*P%A9KdY`+^nEI}$UFlERq8$`b-6`PKnYfLlJJ0EZx7PlXwU05uxSu|XG_+!0s zKY*(H+{WHNL(4gC*yrJ~liaR{tf64SI=Iz6>Ac9ONs}YFlPaS*Mxq@r&hG0!&E^s_ zgZG8aXfp&6wL%clHt4%QFAQoyJorx?!N+f+Hft!p22)IDZbz`o(-C|Ua6jNvkeL=C(#4K@Hw`DR+7T7TJ{f?0s{qNM939#ovUU7;>R1~) z;f{PE<%@6IAnAoN#bzJwtURWZ8EQ-n9*i#3cj@zzZw6I_aka5hky^pFiNWnrf3iH7 z*6s2{Cnjw|v-LxK`ps(aX=U}}2%=MUk$6->&l)oTXuac9!U+5vpze;rfQ|nwB@btrUtLvaSzkHt11wG7o`&V-V#ff#FYOj?BbhTb`{VG&{&I zg?#fI=56Ukz;5>Nt?hST>y~TU?HxNgtKKHJ$`*5OXN@wn+z+L?V)q4-7 zC{lOIPC<(whuK!${J@^L3^0% z+yuNmYMs4@@!2w$P(-% zPg`Q2zvAWS!2$C5Z&(zP-SFRmr1Hoc8J)-6VA;FQOoBtEu@<@T-t#?V$?MEf z6L;haKi=LZ9^y2w_)YMRpd6XUk%hgaJwMSE{R?_f@|}1xU+I0|Y$T2WglVvRN^4-e zX8>>92{^nBWA94r3sf9h|1-M@QK?2Ubb2HG2SO(c{~(Z5;kk{@J_d_X_&F-Vj4`-S zMUZv!38{pZVz9sKZRN>ACDhA7I9?^xrw3uGACv~oWebDwe$UQS75igA_3mUZyx&onfO)X=j?A>Upj}XMSnLWSmk=~+`urW<~DXt&ByXSHIK`C zCjY#8AAmLVW5ZgB)!JC}o^$?b^cuB)TU;U!!vO8S$%U7<9uAmo+Mw{;v z5h}i=i<^{GYA^R$2=x`+m zkxAPB7?A$H3drzPf}bgn`ikg&8zB7`3qC?1^@Gs6^I(E&*Je+Ojv?*cO4*8;*6f+k72z6L+q6^uI`OvU(C_%{VVCOGMz zq;J{t)L)1r{0?!4QyTs2WpOvey#YA=*oFjGCtjU_cW2-eGVq%-@YNakT^ab^44m5u zXZqVS@bfcp&U;S(irh8}L&r^$e-o%BT8>!ytN-bBnJP^JP?WHeS3}6UT{N4}XGct22xqRk@bdW! ztFf3m?#-d;!Knbkrn1>YHk-xjW3*{=lE4J#g}O5-l_y&0&c)cIOax0cf%a0%x9&$ zc`niZ86Sq9YYi4a_H`i51hzT(-a1`QK)%FNDgjoYgEPK?4C0erl=hK%PhTnValWP5 z&H>{vQv9UNsqVp#NqpO-ZfBRM`QNnzdp@C;rA2uvI^KPfpJoYl>~bBSouPr~c==bm zTsOkgVJsY_s30dDFAw(oVVzNYt&(M6pWP@rkKR|~l?)$I;Ze+BY;yar!QC_2{d1!w zhIPGRtp-sHLd)W_dV3i?uAR@s^NnCHUMh?l;_s{`M7A`fG;prcv&tVYx^`0C+VcYVgcgw5r5PQuVJ3hqQvINKrE`kPLy)$H$7){!sd6ShtbD^9WmS4iKPrKbOXCJy;04cEak#?cBZ;WWn6#fSK;$SrT9INt} z892w&kGxPWSeIeC@k9{$$v8zO4~uWxN2fS9M5t1hUZo=E=9B1U zgSNtEwA>+ch~>v)&uS0Fq8;($y=O73)qBseN2>7L^Bf6#a_s2|+GlHcAF%OLbg8uV zuf^MWsFlF%q@H_XrYdAB;;r|Ok$b-68`9|aUOv?Oy|%tZYyoo5nmaW9ccJkIFh@Sx-aEFB1DMgO7yl>raQ#rpDSn`HwH$zS zTkn=GhPkx99MbyK5T_On=Lk2fDmB3IXdJ`UtA_VTp^crg zNKiZ49>woJq|0r;SxkFpmD#?3!YZWN7p;Z%_4#9)*uMXU+F<(*W%~~Cew#`5HDN8a zoA@4h&~JcslWzoGV_gxlzL2$HSrDjty}e0OYfTYPq;Y^E#)L+-G+-i zS2$jO7&BatRn=>@s~rafFJR{MwmgeI(YVc;cFf!#d)*uRC^s@ab{zJ5V2_=46?Sfa zHsVwU^lI4=wa1oyciL7P*$$iiQUg_orPaL&V%}hpqYfyg+Ta9JS_ughw2t z=iTxxPSDH?wcRkyo)Gq6pCwI|AoN4^NP>QIYH!~ZPT6YrzX#k6&KXtNzLjq4-STDl zueo$1w#hfjF8OAR9}J)5CK(so}!SmGSrBz$#+H1$7+tIJZ4t) z>ZtliXLH`0K%DP(|0A$;#Wp-J$oq{S;!ERtzrr=p?g)6NAAy*PoamisLgVOjT4=%C z?P~0V%6y}u%NrwoGUR?d6ze=3 zN<0ymxby+~=8_w zj|dfyJj zr#EIPW)3aJfVauvOPk8M-Q(%7x{4x&$%Rbkpw; zf9#2m0wOmGT^!ahd*C|9cUpVZqJ6@UC58#K9D>3>fyi~p^obiE#g32h z-c7m*Wc-z)50E=JxnYu%&|#j049hs|Z~yBMh&KF_5=?03orO+h2F~*I^{`%ff?0d) zKip`wk)_WwhjD68}-k)&QA>!@>-dc_6&wyBr2X6Y4cNZm6r7FyR@mIo9D>B4{?j2M z&4X1wKQ(^ICRhW>>6SZe`B8Wb_25ptdcpLDmBtM2?jNCsM2!_JRrE4z>3tAWhMB|2 z4Vg9N7Sxda4NbVt@E_^S^KRk2oK;nu=rXHnBg0{bZOMCT(A4{|p})5cLJMK*@wSi? z9jR~gZw(Y(u%&Iy|IOaJfag_I`~PoxBS2|_+zJ?YfdVa1OlS)!ASN_{1QV%ps|qBg zO=*v9Q=0^eatWq^zQka?;Ncwc5Rag!sMRA_uBH^*qJRYyiXcQlYz#s{gepjWpYP0? zz4yEOmZInPJpbqU|Nrx3=liZ%Yu4On&z?QA_Tjb5-)Mgy)#2XhI}@QUX6fkIm#4r9 zm4n@CQn@E5Tv5G(K!evndTVa&ERKL-x+204XM3iup8i_sMA{`~SJ3~8s zmmpJ2cHVqs<$4va-#53WdpTv5QMsx7RfxH$DL--~!8KXR ziSPE64$8Db?%_2r)8Stn)ljrTJdB2v8P>0(1bFK+@%`1d0Z(it}0pnHWQWlo;@eLaq`Y1Y1vS3oU$`*`~`lw z8H(SrQ=i*3_y}HctUu+&Y>4%Ce!B%Mwi`Z-NyUcTqFY>BS1s{OdGh+2Ba3S(CmtDU za&NAAWuNLbFORFf^2K3tR+HPZ^VaqQoP2IAZ1>BldolOh+#0W_hleC=D3Q6BD2iKH z!oL3UeNXGH$@0v4Dkc>Dt|10ZHy%&~4Lvi;2M-|06hc&*v^{oD)r=^m@s$@dnI18o z0$wvX?v0-pb(CEBd!LyS0B>btQEjGHUSS4s}J$sN(0&r}Z`zQG=(KV%w3GJGV+c z>6xN+p+b3tU_5eFqS2^lPm;A~IaZE~b7z)w*W%D(*Js9OO0FHrqA1JGebawi()A24 zwd#sC3_b>DegLeJmb& zAMg}a(6yBq&Xh#gi4z!s*5fx=1MNo&_o(v=S2aZc=6!CM>ec};t>9cM1w46l?}0~G zB`+p+;m6>`cx&Vycjfac_}(*AQ&cK<&e}f8NCRYjQGcWFLk+nXH)}XkidrZ<)+OK9^fZu&=T+wNomR5dCFj;=#O5U_Bc@LZL*12Yd^2A& zcsFU|9aVX@p1bf&mGDH}k7sdH;(b$j>6$;WO8h1^YAeghSY`8-XZMzFGqW>`5M zBjS~Hy06HqTwdJX8Y(MoM7{&zFuSNNR!a~g?;c&Oragv%cA$RE3!@r~?k8$m3Q3tT zUS)bd)`r}xFWo(zJ#*4@<$XQ__o<(9_q@KYsJe1+3Zl~HM;O;uJ9cB1SgM7FHG`vu zA3%2l%LY8vY7mHLe3~fKd}{MCb-9fv_ntYC8`!$Wo(U7GPdIZz<>eS5jVc;duTzqxVeCYPm3B!@o0bdU%}~H$6ZLg}mM0LeasJ82wJ;Zmk+LeP1>~mxab_*2=JIrjk!;fMvR@+z8vt(vNkG^hH zRi#PbY4yF0J14(yRWtpylHNbju}W^Q=)7b&(^0|-3u@ZmM8`#?Y*hD?j=G*pnP;%k z8)Lk6(=RS<*N|MJFDm&7fkx%reL8#NdQt9VjAZWV8(K|Kv35hLw9aNDH^s4#NbX zPp=IddRne$lDV>7Hr3r?qkrUW$bG7cj!E;lWw4a&s?0PV<<>VId0D1@%`2lq@v*YA zj3uPn+&`)(@viZWhHLI!E0FGP(zug|pr>ZqZo zs=T4d9koE|EsW00d1`Wl-88v}dumsdT>I6(U;}aZSJji&*Ux!^4c5i1yRUgpqrr#< zZiJH_p`^WC$C~MzFJoizN4M&|_|~4?t0`4JvK8&KuU^OTH899Ht%retNqY5a zZU~vd+pyTC7niy(GeZnT{tVJ_luRTCH@Wz>5uD1cAzx6ZNeXB@d>g@o@S$@b>1GUl z5N^iMzW?A?#Nh7kW&$$d=EUJ$6mW=Zg51ydNZoQ-9xZ4@Cra zw~?Cia?$QU@!-!ff4A-YcxbO}{U|e)Z{BaqNVlxbV&T&H_2Wmf)yThvAL}=6nIqSriR=B!(*G*+PI+!%@HFY}tr!=6n%lG3cTF+ofWh`;a0}YK##mWaC=XI!` z{_kEll6N9JCMwhx35EM;*Rtk}O_%(Wf;s2n_zfAZ+8 zKX}w&wGpfYt#0T!sDU@tS`1?*M8(xqmeB*-e}LxLC((SvUHO0$;dVuSBu77at!$?@cbuQP}xPHbpm7Bpbt}k)j%C(Mb zE7x(a5f9hpte4#lzRq>#>*(S-h`DGn)9w>FOGDPpmCsWfyg{wP!DA$UMzp71M)4`kVEJ9XESB`Zu!hBquv2g~E55;hyui!*7=10o<;<&npz(*xR*JRQH%x z#D|Aff6j&TS9VV8C_LG|m+3S))uVGkuE4pnb_51YUiF$MpE_42{WoznYtso%_3T{G zUqJrX2$VnJx|F9CNHmcup{}Y$ag;F<<&0oNzj3c9kbzK>q~Fr2ly@uXdIvU!XkC zM1IL1yu8|7o_tFGtV!6e;=EQPNLMSX0hvygebD@;fJ{rvjsiIXG5OkwnanZZ!QcnL zeT?3CxVKx}Wq3L$x!)Y-@g|V{`;%9Iy!M~`G4tOOq>D}NKNK5C;CzsvlNa#x$m7f8 ziQoa?>skKs_Z9F6@O*HJ{14>p6<7_D#K{MORp4dQEgucN>vj3?8;DWKAQ+wR`~8-`ba)%dr7%Fq6W z_fUw_p??gHp}sx`D*P^>^uEA2cLMkXcq;f6Q2F`1;U__ge)8F1CHP@*wAurBEc5{& zRrSFqN$e@mKLt+%+rWA-YyP`~RN3TRKwQ~rtamFNkCIuX<8H(2LFu^$lzbN``NPeB zZ}TrP{~s`pEB+-QS(^8^GhBpDyytjp!DqoDxNP;ND6m};pw2lO#l^c7o)#4%Gb};Amv`x z396hg0vTe;nnAVS{lE``JA*S&F#=RP4G1Y7J$s)D{skq+gV%wo_iI4u?c$&GUIH>y zlm(e1W10=C z46}w}@;7Dxd11d{pJAtAvtgBC)(~*v?jxVF;}*_4Jz#Xh5t86uYV;{aKWX%NM*m(k z3D~lWmw(y#i;e$=(cMPBWAvAe9z(e+{?$h745#Sd7`?Y>>NcEr${M|uK}zm!;?_CN zFn?G{*b?Md9PRmfc`AOGpDZ!{MB{5eocLk>bDr@xn10|KPAO)NzoUl=nX0Tho$&Wr}T4=$cta|ret~= zQ~aw^^p{e!#?55-Yf|(hsr0-*#XmGfyTiX{^Q~}u&eK`o(>dI{^cc=D^II%C2wLdS zGY6KJV9mLGUelcUpK<{bhmH%LWTDXu z7TV92EpGqx>+^yMUJN2))Z3dp%(K3pHi+&rys)LMt$jWQdsPf`TCt6*AK|O$r#7`N z<-m0^LIrSE2U zyO>W;{65wHPAZtkBYxZb(>cBFlF_oPWll%CKPg_*G{3dg*I!g5iQ+Qt^Da0hHU{r4 zw>!=Z%BRJvJ*8>R!q&E+REAb$Ti920!q&U_c+>EX*!G(*~`80j~rq4*7PoE!t3nf0DYc-LL1(z{b=>w6A>`^L-x{A4YEb;jS{~4!!#AnQ8 z|1egc#&_jC9nY=)@MjnQF=p^^1HW84w{%_^1H)$+5D{im5G za*#)Bm2tRE`*|x^Xg#ppLVN^%q4ipp4V+7V_iO^bniCJOV^dD)b1tmYnY|{-)o>NF zPA+HZWKm&U=~W|U>}Jz_Ju_w&a+R8#((7E1ORYOe?+silO{DgbzyP2Z#O2aM6>y0TH#)+v`tWY~UHS&sYHl%gCc9bi!*=gnc%X%}* z73Jl}PMr!ht-KPzVaH{5$FhYBE(o_6R|JLbGp_8jj_vLxlt9g&3$I!g7%iBvlp_6BDanG71N`!UapUZuVxvXbSK@8 z?77S`eGif@xz*@PI`fXac4W_G;-Ox2z&i4Z!+rWz)wp#lG4oXJ=ssAifdCiQA?6>Q zpWp4>2j`!X$-G3kiD$7ELT60g2VrTgDRVy8OT~}{oNde1`t6Ci?gwGJO@9r&H_v1YbjOoZ=c{tRAx*6v3y-#wNvR_qZUz2n>R1ITw)X0Ykp)4iGB*JMtd z(ZT+ZSAxA8ezN;_4yTxo19d#&l6pNu${=*j`UXHj9VH{JP%Tq%Q$|J?r4COmxDufVqkce{P7OsEv0dJJ8dr2baQQwF^DIs^JsV1Q z_u$P*c;5?9u6U3MXP{M8x@W@HqDa`|l0Akea(}@Fmyi6Z_B~~zlbxG?j4ODkpO*SS^NU5Ju%QX2FO$18H%S^`2;+Oy{%6V_*l^d@;f{$eK{Y)@>qW zLuYaZ;Q1@CvX1IZ*IQR~jN)7NrQJ_;j4rwT>7kvBQQdh`OUEAgmJmFVGalBwb}*!} zZq8qV?`kDDQIC1)J)5#)7t>p={RA^Rp_TaJ>~9~%6X6N+q>K5OAR=?(dD0@(6oV?) zrrgt>JI}7?>@6WWZWAtspxHl452_5J=geTwfb?&dB8?aFy1KE1oZ6tKqnN71h zDNaD#!b$b;ol)AEV@N1!_7(lL-NOwfHCq~UJRPT>c=Mm@Bl{n}_Md0-HOS8L?%|H( zT}pf-;it8nWN&>gZe3nBlt4pnYc!y8v+?tV(4MMoUEm>>28h+Hj;IZUZra^{d8sEO z^W*p5rA+IN8m&vXlO;6xL&DZP?9zAryqFuzAK3qy|C}H72`chA>kvK$ZT-)a-L}5e zA2~`veZ3y)ixlqdvdpddwUAX8Qg!$~t#u5yN9~xEf@F!L#zR&~wk`bA&>q__U=zMC z;LyJQ<;qBupN)Uq^vPA%x;;bh810(3@-aSH*{_xNi{UaE`zJg@{hl$iT4kkP=v3BB z-`cTjqQAPFc&ml=uIYwqhfyG3i6P9FK~!TJ#a(g|^O^9SK^L=zti5A93B(iSz~#|R z(4zJfrJu9e90*eSSvh;bY0~cHOP420mQa|mF_^`} zTDWOy*yx#p89TK4i2@6m*}CZ?+jm1gzWX)g7(?4!^emG09MVuU5XQ6u_Ly|fd(1sM zzr!gdS7dxAZh^dnUXK5dS{R`!iFyKpn}MH*HX8j9wWx@-`xW3-&*Q zr=O-UgAWfD+~8Cy(JfvUMdCK;Lvr%2{ji#xE$+Jq0FxiuFHd}EUn|{p)x%OmJRw+q zx7)V9T>mBg#I>xBpxaArLM3zDAn4d$Ij?ui3^D?S^kRJ=C+Y|MK!tGRy%#e?fcZtaWVCNv?zC-qFk|jH$_PmR$7wKj5OR*0}g}m!7D)T|sjs-&eod-A4)3^L0gQLz4?@#ma;ocJ7&irK%Td zaO33$CpzR5x_mfILk&rV?_N))k%LXqD6cy8xw%^_-l?UZz4&sMR)1(?8p_R3my<6v z9%~j}y z;3!OWZcN1kU0V<7!0u?IW*2?EdAQ@xkrz^Kl@;?n>&Ljk-~oFB>6Z@*jrVT8`j@&n zBWdcFmoT+n?-tkfm7bxa^>G`QX4!+}y&@-pKa9oYwT$h4apX=7eNKXq&hDUWb4TNu zCR?0q+rnw!tx*d)Yl{m&mo7y%@BV{1l48=)PM{Idd(oaT=dG>iFF3wdbH8y>@O01p z(l<5^@DKPE2U}D-Yrx%qo~*6tk79PWt!>ML`;G3WPcVKt(b|ePNREcFuu`g=zZ330 zB2>;^ZSGlQ-xqVM-9z}$F7dNuYV6!`{94b^=*x^HELpZ6;eA}3J_;p6jZCZ1nTiKO zK8Hq<{B)Fg@Ihs!%>T-*00&`DkW{~$Qz#r1)Ql`MDD@)gs&8^OZ3+}&Tt z3j)}VH`Ex~CHA+X=a8Y}f+FPXAu2pH`pDx@%qjAo+g*c5KgMEDGdw@I=Q+QsV#VNA zL}Hr=L>YAW$cKX^|B$3w!^H=v^S7?fhaWJodLfSK#V4gj<)hwl2^dMlwR3!1O zH#{6JS7}E1@#_!OdZcG-!Z0KKUg3U}*S?uE-^;5kKUy$6WAn6wqxm+G=C)e&JVt;T zC;frY?r3m0uAeuv9(G0J5{Mjk=UH({xaQw^!qM#`nXACH1@;~2!w`_~zeDfOOK%*J zY$G0kmN=%0exkuZYEjAZLkT{l<(0UXZ@Wqq&5t#o)%wK4Zq6?gu{>ms{yp;qmnCiK zIDyFz=2hNb*L6asoyYANr4^4VJk}OCvt8F)RobCl8ew9~*zo4#(7w(HxHkl|e~KVH zbhvt}c2Y>^`4*V}hv(xk1TqFxcwETr>go8klc?{yq7=(9SCn?#QT^txo!E=M zpM|-F?`uSuKVJLxlRut@Li2HJ8@#M}w%3MIa{druNaM+Y#Zf%AyF`m*7zLR3ga*SV zrb6k_c!m{Bw;GarJXC1@`;7uOr}!4&hQE-=xQ~V8hm-``NwOr{ez1I~AZz+A#?)XH zlkxgOcwVS;&kGN7vk!^?`bs9JiHRTYucMBY>%K+IoS)|Qc58~vJET>D^={6tF_E8| z;A&FDlp{T^HWcOjQ+M@>WS<~}5N53ZmMxqGe$+km*PqTl zqoK!*2$=WJOJpO-^3(gfg~&3*P0I_HN5K8=(AjxjHf62O z^NdT^-CZSeM1FYDBt zu~47WBmr3tZn^JjW?Gi9ldNsQg^On| z>S)QfEL*~UeZIzdLC3s#ElacQt*zOGU)9nk|vhIVP;S@W&w8Ciyz6#osnKyeOo7FiX;IqIU_J-4|YiesUi)Sxt$+Am( z-ogcQ+Or&x&n{}6+p)04XGG~)G<)$SS+_gAqopmgsAFOKf+g@9I%a3jZfwiWZE5#e zNPkN7`0VT@OODPiZfTj@mOXUdQ7#1EA8p~Yq^%b%nA;*>SN2370{g=mlTTv%{R#ev zee?-a7ye?704V$t3QN1xsn)j4%<7NS&p1BYu~-}CU1GBCIDi_A>YieCfvacMySmsV z^U7U6qg5OQ6#F-~+1L?@tPw;w&C z(05!X zJ`$(!h4Q!3-A=v!LVTSYmgB5;!T6hZ!0$8uw+LTI|4ci7sO_AE^0(6XGq%GYF#d_~ z3*|rSmfih+#zOoh#@}B1%5Z*L?jR4_^sjQ`AGsZVv+-|-UnqZB&XLQ_=PJZsX?%UT zqEP$Ix<`>r=9}9IztQ-gfL|#8<$J@x9p+)1{52bYd--2!eAQ1O{R76={_H~eYt}|? zTnkqr{zl`U1HX{|a@**u^R9*3SCtOT;MQ{$(qFotV`q*ce4+BK+TZi90}AOMFn&M$ zLh0+%rhnXHT!r*^mN|Cjb3h^er3ZNa4}n7I?>GL>wv+zOtPihgYN7G9-}t5mE%|Q1 z_*Hlp%3t;%FTWol3#EU1=OHxSt7tZvofF;voD1g>W_IoL`7yntuO0OT$B}#k*M`US z3^zQi`=N6|{v%yuJ|9W@?@(Tfz-qH|qWfc>d_$L$o`B~~T*1DH?vu_1y{E)-55lN> z(#Nm+rE@{&IP@R_#2SB-sD=- za&~@0`r45jFgc~ixuDO^naKYJ@~M1D{%zz} znEb6K9-U(;p#LbwxMH&dqx-RQ@1p-)<;g4`;T z(|tQnE>Ry(E4{z-<)Qm`o?JrTDB4BV2m#C*(k(+OFr))<~`S~?+D@|@k{bmC4 zqnLwlG5LeidX1LcQOIpIIh#+!<3>X6OwH*BhMl|J{G)!AD4$D_yWZq9zi=+(+vJp= zn~)nYIn6Wj@)Py@^NVlc>jq$X)-UFGtO1^7IxMZ*P#iK9qvf{3cJn zK)-wt`Qpu9zTd>7bR_ckI&ys`r+JTap&SaNV*<~3GY7ri&!y!Hq(iptSDC!#Ma~8N ziSoDk*MdfAf zU;S?a&!}5WPV*?|LVnWuKRA>5Dd#cw0sFySz+Zs>ILO(vDtiO`4fOB9-+~W=KL^(s z{a@fl=p6VQc%kt>0sa!Y-u(9hZ-w3s`~k@1Pxh(G{+7*Teh2+0@Y~oOdK_E@{RsFX z_-*hf;Emw%$gc#~Lg&Eg(4PfwhW;e@EyAA(N?$dobWZ?Xey|hv2k2M8Yrx-ue*zx@ zhrsU}|3>3~(fFS=|3&71EGYTEQBey2Cs6UO0-u2X8u&1n165v^f{%j>&A$m;0{tmQWA7lUIesCUm7dQfYVK;z^=W0;lE(4E4z7-sRo&`P) z)`Jg%)u6&n2POXj@L1&cGQ#^NpUj_TXe(=lS=fP%B>G~un z{fB{)F9uc5Z|vvG;dkJZ&>KPJcP*&;zYSFR{TKLKuoqOh>DzRVfNh}UJ`Sp0>%l*Q z9{{CiB&c{^+Sixs)1dr+1uCESfm6xX?cfyXZ-I}3Ujcs$ehyT89pGJH3n;m>LA8VF z;P0Rh0yluWgBAGi0zM1%k0b@+rmVJD^KMStG{|BJ-eGybV zp97`u)1dTJfzop{sB$a=m5x$SdAc^|0si~yCM zx8CQ|^C$58(9eMk&1Fx4%Fn|fLulFE;Lo5}f!`vYOTb@4UjRM;o?~=9_$c&r@PEKj z=D%fkw`MVU5LCW@3o86Wpycl~|L=lNLx0WudqC;A6nqXm2fPM+zSNid22kU=4$I2_ zd!WXRFM-PEd7$cN2B>n`!|1=2c)A}{_#cA`e-rp8u*3W>H2=du=_xh;cgAHh_e1{$ zoDU9y+#1Sy!MV`wpwin2o()bl`X9Twb%)8XfGXc-!Tkug2~_`n7*x1^qrVGkoLvMq zfK8ynoenBo9jI_8feKe{^nReq@#V3Z%qPGnK=Hp0O3xQS>A3=w9({X8dKQC{Yc{$L zdOPe(*G3ct@^p=3! zLdyQUv)iOGc|9n3eL76?7lV>t080MjpyK}+sQBwZ$xQ?Q6MVhcx9=CgjnI#R8t?A~ z?*VTCe-EwzH-R0-|0wu4bT#-eI2F7DoCy9F)aR2F&lphpe!Y|LcMpIMLEj7h68s6c z4*WXEt)px?$dFyu21;%|I0!a_l0OU7cytK(05~3$+^*mT@U1bK3`29-E1<&t5mdO} zg6lv%%P9PJL5-&?!C!z^fec|~mx0nFJDLnRWwXJ%p+5#PG?bkR-U~ey{1)R%38?)3 zW3vN2PnOI##Z|NHp-{(N1)Po9C$PQ@!))LG{}%t_U1^QWx$s~`O6+9Lrt0N zR*GH&GIW&byrbIZ%^*cQ`ATpzcqzybQMMRV{7oQTxJ+v^DxZ@;#lJVG_}>`e=~qDI z?^#g!{}m{CeH=voKQjOCfXerc;8^rt25x|E1?ggC=YbmEW}5#gAWgdLL{RBH8dP}M zCf)`AJwb(+-9*W~TIBhE1dE}c1eL$r%>R2JRa^EAP~rX)q=?I|GI|+EQI;(RmH&Al zSuN8VrQ$sqB&xE#K;`dm8SnoRh*#MkK?bjV8`Edl zY1nL7WtcV07!HtVh3hx$Gwd{MHmowt8fFX!$fOHz*k{;j*lbv3m^I884p1mAykVbV zr(v^Um0{K}V>mz|y6}d5hMk7ZhE;}H!;Ikofn9jRKEqDKX2UAOtYOA*fb!?(n0~`P z!%o9y!z#n9A>hL8P2-bYpkPO(%;<9umIQMoqZb)H+2}T-ry0G>=noowxzV*of6nMe z(Ihy$_nvM1CyoDaM*n?+kDu)%E`7y^diqkM_b|HK=&LP!uhBm?`Z}Y3V)TC*eS^{8 zGWsr~e`xemMz1#dZ$_^%`fa0sVf3g&eEJ?U`VC9})1t|5cn|YO|ldm4R|(Pc(g8GV@1ryKnNqt7?G(&&qft~UBJMxSQ%BNqP| zMqg_DbB%5_x<$0|%S}XXsqwEg{%4IJ-g{nY{2t?9WAt*PzijkF7XJ+vKD_t*Z{x2t z`R^J11EYUp^c_auWAwd7uQU37qkm=e2BS9_{VSt?FPi*?_mZy~{|V#&-RPYxy(76f zsQwNzdaTjs7`>O#f3@%jh(>>Z))iky_Pj+87=5(Kf6c-lXY^L1t3)$42D?M28GXx9 zUf*n^H&uB0(?;u|S?)7N&oo+g#ieh_6wm)^2tU=+{~f|l^YpDoPYg79mz}V%k3egK zvO`>1?&a?>e%MDa-}ueO|BLa%K7elE;FrcPH~tuODSUVjemXa2>EB@G^P3T#zlD02`vEs;@du9f^j?XzGlgvG6w;KkS3K+W0Gt|8wJq zeK21$ez0?WY6wrh<)#{c<77`eyVayG>{EHi_$w@ZU$ycJ@8Q2?<+st=6LWZ%Ki!|@ zerWaAY4xXhjPhTFUO8>9SNTq~_%(kKKkS2g$oN|={2#4;!#;=U7Jr}B-)2i+c+dYU z<4?5qJzo0IAKv4?Vf;?xYd#`=*atD&_*+c>{h@s^*_JB}`i;NH_+cN(Kdk-TV(sto zz_;-F+^_P#%);j^|6w23UoHPLt$dEO^mk@m^qEoIUle|orGJH`zlw)8x$8`SpVg1E zn@${IpV3~HzSUO0?jw8f!#=I^tp3ZbeT}yEANE20Ch#r%V&jK>O8RoH>p#ZtG=A8p zbdvFlt^ezJ#I+9|&g8DN^w(MXAF}XaAJS(n{0a;IjPb)hq%RnMmGR51{KGz>-y46H z)z9B8{;&_^1&e={mG5_r-}io>zI%+n)zbHz)nC|Wr{_dhzgB-ch5k*vat9f|&-hbJ zf7oZU*z}J#{it{4;{x;V8fza}>mRc%e_@}~%a*@R%iqqHKF!FSxVn!DZZYQllt#T@y}23uTAmwoSF=Oe2T71 zh2M+%NXp+v{UzxYsq*+siv9`0NqIegC28#mNz%IkkCEgbkxKu+ zr})RG^801_PcnRGivIzaN&e$0{U@c;b74yU^c24;#b1}wcTS4`^A!C+O5gNUdHp?= z-xpKzXQlW$+&~nOyEG-A{%*j|sq*=2Dt(_x<>wzMeKS)0iK+5ml#;rf%J5 z11w_=O&8C{#J@#{tz3vUcKEAM5{i`J3tC$jw&+^{A;UUMpme3=lEt8K?Bs7D7Z!!g zxrZoF)X=oJqykc_6BU+Q$My$9l0M1i z(9i@w@}Tg-rw>edqS-lZF>L}-0U6C{jbvPjuU$mnzF1}g#GGJT_+)(%!pIQBXLzyB zzHn;ARRe`)bP!UG^J*QBAY)PU!Gt9`^U}89Ggg~4gt+h%Ux;XEnmu=JR6wrH;E`x$ z4XzX9H7d0`?-A*DY7(tw!D4FKn}cp>Qc5E0&@q_^ytHMW&+Y6B+Wa>uUEXO9v?}Xi z5OL*oEDk{$nijUso~yn^`OI?%c-)Y~@g6$#JUi3l)JYI8>rwOU3lp@$Ir42K35ZL? z6@#SxxuH<-^2sY1Yrt{8X!2u%X_&*|7&UO8HBtW47$mvHdV2UlU&$ZF+FSERg!a}Y zuC0WQt}5^+iTvO--!t;RS)#_@vKUL&AwB9&b`;2e_rmpKowI54X*8xM6i1=~yLK=~ zh1L-bX%s+P#|81A(a^M%{<|R5jgoUAUrm`EM%)XLb_u2!Em1T~I-Pw#MB`P0n%%x+ z_TmN94%M=7VXLZXX$uWn<2m0>S*i;5pN-+iyoIFKr+jhCve5RT8&NPCPD{06KlX7g zA|~CS9h3369s9)tZS0pEYh&N!uo(MBBV+6p4|XX(_4n4ru_v^3*x1hnF6`@uw3MVq zwUieFTgu1Ree6lRX)hP84MwqG-Y6D(D<6K`%JU0DSL~S_y<*>ZoXYd_9WwTc2d6@Q z8gpWQRJt)M_6bAPwm$hGY2mSm8;oKy8jte5Y%Iz5Os76MqQsJ6Ac=h#H)0|hI%2PQ ze2D#QFo-=|J%#Zg_NK+UAtCljbo1CV^z_(Ay*s8tSC&uSw`D3)-z$3zOJF@k<-!IC+xi*z8@ z(mAEveWB-+K!!M`gjlB@>jcgS0wL}xA?_(5%Tq!kri8esgt(_r2=3;nlJLX6FNvuk zms3N;Q$qw(Lj+SR2;5`?xgXdqaEN(YdEz4u1uEY)u0-A)P2)Tz{5Zq?$WNj7^6|Rg zE^7BHs!vh8_r?9Q-;LnAL{lrXa(p-9g4vvV&i`;kq3=cv@C=p7a^bX0rZwm7xmC7K zmEk!~F3>DHWx^%@_xjz4#u7>6(8r^4X4Qdif0~F+c?Z|j^zPq{2=5PU87wpNefi%} zknW_@cODkEwMSm*?@%;bx=u8SX7r_XM1lFSqwi4MVEQhyvb_O)NtZ72ZPQm%eP(qW zBCN*^@H{N1_i0LBLvX^jukn5jyvfJRk@8s-| z#P-l-;UHyKDY9A>8)ArUBLs66k)?<`)%rIpISE@Q@30fy`8mti&OV8^Y?f!I!ly?S z>146rG>+tW>A{pn<-Otoi^sh~lc=mzB;-?eFd{qEZ<_%z%b7Qn726K4o3lw~n_Lu+ zS`@n}{+{>$2aMb^W};ixX5ZQwb98Tw?!XMEzRTgHhtBDGYh*{Ybg0&?h;nORD>>qq zua$g!w~Z*nde9N;Un`ll1}PtfY?J$+)h_Cx-RtLIOeJ`!Sd!)?oLQRKPKL9?;p~{Y zd{jJYg@YX-x)%Zz4~N>#+-{r3CBnnVUa<`wB4rs`nEn`m0h@fZ5v&P zs=+s!-X$`?XniGEAjFW(SNbV%IC+CnIz6sEnH_sSJjNfg2qu{5EhX3fHwEiI-q7P- zXJJS#tz0NLHetO?UUo^rfraU4VDD#ysS7swShO+zV?^@i=uxAw~Nye6r z2tL+XIx7$9*cbM_0QOX+tLjNh`j!-A^ssxn}xX)g`AtJ2bMU=&kOjt_UTa zCt5v;JAq8Bo8jYx9aY)sqya=F=FNh-6vhQ2BfI-mcfB)O#vY@JjKU=RqVnKgu~!%i zWY90V$!t?uQ4m*zcJu2@mY=t)*7Z^)Mh)YXVpMhseQiVNj;>I2XY4u8`9;a2A6EC) zOn9d;_gC!PMr~2yVws|6EVY=-3&mS~O-&g?{)tC+Og*jl+#`#Is)!GpdcONRsjka@ zohj+o2ch%42j3w5Cr<7d>%w`N%ipA}eLa?S${er&3CVk=S8d+Nrntvg@5S5?Wq>%00l4jqsj z{|MFC@04Mxu(7|Z|ACt61D92oOkBeZ$?0RZw1ElIhLYPqTU0l^R*BlBx~Jxz6Kf9I zGPI|QC8dO0!3yUUSFSIvqD_1+XI1+yl!Nma+P~|vTQjoV*xz0}ujHK3AK`Wxn4z~+ zCTy|!@9M<;+pD$PP`Ht(vH0c+*Rczw~GS{fKywAx?VZLED=P zM)6rJh=*U%6vJg>wR%gT{;BcpSA1H*zOdu!$foZq2hk+puuvy{aPiYA@*fXNZc-MH zI)ugipw)a(6qIO4+P&h9RNxe;yT`Wm>+Di9)pG+`JOrd;V0x~U$2WKhMAHE>G$ZA) z9b3lHEKA}dFgqEQx%{I0e7*lpZ-pByt$q9Pnaq|U8ZsXTvB#K`{H%;G1y4mR_qY?Z z2QZ5v(KhMB`qoyg#Xa-bY%X11X16*qR$^h-s}4h6TxG*+>*hR#cQ7;=By!$>qsXWP zY0cGL&kPfHTx;9TCtXg4H=MVYg7a?Xhr%zz&LpbJ)K1mBRM@2vj%db@D;(hFu^*pivss+S-c|K`lr zsQvQaf+e#TEN#n#HE;LB{j(Qk?p2JJSu%&Uzl?idlZjsR+FLz)Zw9dXoM9D>$brQB z;r3R07ZqFH)4S_sUaMQikL=5(ECgn>E|+cXXwSCJ%PyV0m<(md?y}p?yUJo;7Mpx7 zD{<(iruenAnX#KQU%|4oWgO3J;KefTjb*-muMyS07-HRrhvXj~?C-UAEM1IZ6O?U4 zS44+XRlBgv<;(7Z_RI$-s*opTBBOzedAr^+Hyh04Vabq}ml*B~9t9&nqg7cO?-U8b z>!G;5srL?+l+n9HrN3l0?~L_B9+)O{H8T6(T9+y^pV3VT_n%ya?6vh7|3BatDxWId&~PtrCx7L34nW(V3#G5w_|@CtuQL7@ z;1`U4EDYS?T!r*6G5!Mhg~AUQ{~PcN|G{>`SB-;#`!rV}{r$#ogI`F0mAxl% z>(0tT%Gqm*OwngPmML0RT2wlAr{a}JO+Zesrm|+YM*Z8lV234P|D^`T3X@YmcP=G& z6rKyY`b|##-MJu_w(A1(2CgM$*G6HT3-SqjN%zB8ZF1_T&J~b*Ner`p^ARr<+o?(9 zXHW7!(c}(E%NecwoQPbx$!!yFDnF86i2M?he>ttUfZZ|eJuWvpIO?Cy70B29$jvvo ztcgW-b&OVhzJy$}$!R=sF6c|x!PD8;TTD*lN}gQGUXk?HAb?t zT))X}lb?j#SCHFkavFD>OQlos-i=(AFCWNh{Bf>;oX+&jGC7Syd2$K6R%02RtVm(X_;jIi88!vR8e6e~^|-=(`lT z%xhjwC!YXzgB76klp23{ zY$kIx^e@4iz_sA9=(`*IFX$hGO7HhTmB)>s()%Uj>m1@r=s6%;2qrgx*MTP(t#guJ zhb{pRK<_9};osafllc<(2TYx zva2DzPk@u5e-5htR)NyjZTw~6k?=nOD&AU9^?wYg_H_U#`Ej7iQ|BDN3qA!Z9S?)b z-x@>N)lfV=;J3lcLCNX-qvYm-;!gn;&qVM$;QpY}I}SXY^b9j!RJ@x&wWEi@Z-IA% z(xdZ)!q05bk2|GH9I-x*Ti<55fOz@UzrU4XE@SXZ(W=_W%z@?yb>2-+uzt z&L0DB1|Klgxd`dG3H&PlH-HBb?n|J`XEAsnI15y})wvF}+Y^mH6;yvd98|kH5L7-! zgL{DQjPiC<-UOK!l|2GV?&l!$l*y|>rT=EI8`Qa|y}%{l*T80QU&4JHlw1QSx#Ped zP~XNI5C1@L1@tcF{|6eo%KJB<~1u455R6Do4V_EL;nm^Iot|<8SDeU2!0v78N3R-7F-HyTx$W9 zzq7z=zzR_1KM7R5jRzSj%612(uLxASUoZ0EUI3MD+1uy?uQ%)kzX^RQNRYi2gI|H3 z1*#oZ8C?O=#mkNW75{j!3)Gozx@6f-AYG>H_ZivpNFmniK6UyQ1bL~xw6CfcMG)U+d@6p&f=)|2JjrP zA3Ph>TZ6N}Rp6Q6E#MhoA4pu|R30A%HAg2O<5qw(!A|gWa6UK{Yz999s(hw^Gr>l% z4m<{|0uKT!!4H7tU;{W2JPOQ$cUdIi9 zr-GZnL&1&UDc}Y$3-*Jxpvs%qz2hk3ObvJoxIfqj&H%3m_XAggCxa`%y}?ef8eC@d z60iz-K1dmlYX(0A&H_upnczua9XO7^D)56~CAb?{4xR{31a}3q;0fS(a3>HQvfrrT zHbd7$h1(Z4PS5`o#h6aRX2UAOtYOA*fW{*Ee#1V)PQzxyD#NT{#&CeZF1%r%VW(lU zVU=OlFk?7Cy7@V#->}cH)3DjF$}npPxNytJhtBwi{dZT0ro)8&b3Mktu|y&0<3@km z=&y+;0V_Q_bBpmcD9QcE=zlOc$?2N>o{d z-^eBRexs|5uW?s=mA9O1EsGB8MyHDA`iU9{7pK|9J|BIHMdBzXV<)1b>tOIDy zEB#?zsmJIl*P@tX8Qo|4`$Th{YWj6vSM+H{|5!Bo!aBlzfd=IsGCHg?Jt>;&Ll*uy z%+@_l=O#n4%ufA-3iLQPc$+gv+~*B=o3u;1fxG_^kkz;jXqX1`ufIr zeYHl1bt#>nl>RqO|0j(f)}`i$@N`nS4x=?V%6-nlzhL3@C1Dqz@&C*C|7HAd8{Kd8 zDw7ZEP(L$%xAA4qOX>S}qaQK(ur4)VbXbQPGCHg~ZME% zkoXIYe!tPHtUXUK`lm)8W%N3uWv5KxA2RwxqaQO`^DyxTjBYUck4B$q^cJJfGy1Pa z&of$suAJt3(l^>@ogWvytI<~)y}QvmFE9Q+Mt|ApU@zbXqYpR!%|;(>^bd@lX7o>u zKGEoYqw9@+!01mJ{ixB+Mn7fre_DCJVDybf|Jmpt8vTaRw;8SZvhpMQkaESknLw{K zdUvBAHhMp!WnWTGcI_npg3(7A{i@N^M017x!5=c(ZT=VvyA?&(Va#Q8hwk=TaDgm^iK3kh1X4A zZeOD(8ZCPj;?FdCy3xywt~a{R=#Lw{!RS__w-|k;(OD)Pa$h#O&ggF#y~OAr8GXIc zKQp@D=wBJV+34RHUCKj)+!muNjh6ip<)_)`U74hcUSTvtW1c;U3%M_pz~96}fZQ#9 zUf>D-YfVgHg8K(VlHQQwm!|0A6n$8VJ|(5^<0<~-Df)9HBpLrHq(4djIHm8RlziGg zL0?LKC?)@u6y1`dnak$I|5z%$TJKDzZ%m4wkV^mYDSlCk|5hr#n^Ux&%aZZEoYHqz zivD;i{NpM9?kW1d6#Za|mOT{yBKQ52eyw#T`46Y~(^K?kQu^*q@n21q_mL@iJs&3H zt4`6n%_RBLQvAjgy=yA{>Q>3{T9Z!F&!+h2q{8zIlqdg10w=@&M@rw-DgN^*{ufiU zJAb8r* zSGlu;I?>tcPcplM_Q_-EO&4-p7g2YND=(5l=Zf<}l7%=GVP}aygq<{-pzS37Ky}lC zHrsCEQyyDgaIw41AwDs|B1D{raG+m?5#lW!UXOXj<>}Np%M8j{WE&uLc-tRI&p$iv z$}0|_T=^75XO){0XXcySt`^H2sR)Ot-N9!zvgqLR#Y-3H)O7OPGYuhWJ|P@*_7TAh zr_Gbc)b*PJcQS=+6u?Uti_1&Yj41iGC3c)WY|^2!nrd3+&BoTn$2u0bG_+Dz?%ejG z*=?U<+lc#(WrHPrXwqVi4zc>ws;DAU53bk~HOyJEU~L0K2MhVGsSiX+&1tuW;u7i3 zK6{>8UF!6DT7<0Hhd5o3sF&$m!B4nQcmO0 zremizR@nha&Snx92lG!R$H@&@j>CQ^3ufE1nmp3ReRZCk=q)Gbw{IUWheLh5 zwk60?GbLktgl2b8m~I1-nt;iM4hcykZgMg%@vcpq;^-KxJC@4!papYuh@b6ArX_0j zC)*Au3s`A&e9e*y&B3suX~)VhOZ7`5l^*<@ueBX zMCcnQW6Z$qN;7#1$t5DMe;6+uhMf``Md%k6S$vk)pQk;U0VL79A+@#5>$eSVmdntd z;`70w{Y3|FqjR?wSvXu9f`&uA;Y@F+s_1xhMNk5 z%=ox) zvb^Kmdp*BhYyqT?$NtQC7NOKxi#r5`;pg<&PT6cT|}TaU3C76t@c_{-K?PTxspO> zJ__&We`z{;Ru$Nphv+<4^_gcR4s=!Dtz82l8@WPiZzc7^)$XT{D3pMQ(Uz1>5ha$DVi1bLicgXI0cb zbsi^iMvZe!I(QK!*%ikN^3ovSQte8ir}2g12V7D7h2nXhi(;uc=#8Bz8GokBwb;~Y zjYRz=@)JeIVUagE5t2OfxT6v(RNn7eKJTsj#^vMA6V9y5owd;)m2yQ;pIcwsySRw% zR+D=YX+<~wbv!sgvS>s3W+Yk989s6}9*ea5Sde;!z9 zAH4Pl$mxDrP`~jT;THe|P`?Rlr)9<5H{W=%+Q6~0z*1%Y0a;j(N zf?Q&M>p~b?O-}XgT#!rcYn}k}2Cj))ef+9_=YqV&e-xhgbCsK%+JSRHE~QuUuXD}( zC*&v4MwXbo+KF@9(XVu$iTo;)SG#d8mLGL3bt*aSIofP;YCp~exx{|fn~*F0n=c2| z^Y-Ml2487%YEOA`iT$kF6SdOh)UNX667jyDw!L}>@v1zvPkX@R)Xtm>`AF^S9vbEL zJx=~T$g5Dd-)%C};C0YUnal13MgI_FzFyV`RzT;#qrvmRW5Ev@T@Labmj%Zx{xtbt3`*Zz<7+?KG-$nN zko+r@@l^1apyYM?m;a6C|5@|bzAE{jZvJ|2;nHLNde0+T_eaV743yp*&A$m$x@H>x zV358#*`CG9^g5S)T5kW@ZWO7;Ti#W;{ZM1UK4@Mky8TeQf-9kUh3WP~@mw;l6PjmL zw;xKc5SKus+wF(q(QjNcG_MTZeki??Ryy_u>p&ju##MoPft4Ut<@Q4{=D7V(6!o|) z{yZYN{ZJI0+YiN-9k(BfA{Yl-`w87XHRv&&{1Y}CRvBgu#pG|y0O5rFhJA*ehRudm zhFL?vg}WadM}orh?t`LHSOv;G!6jPdDfbMQ=y1RKgV9y^$qjLdAMQu589iY9zZ)Iy zH>2^Fd>Fr_*TqMg$8pCY|rltjQ+FHpEmk6qc1V~4Wq9#TKjM1^!*FPuYD?VdjBO_cGl(o!|2_O z{)W-|u7})rjLsUZ_rD51(P){c(SEM*JpXf}SI~*&9y40|rR9ES^nlTSG`g5hAh*Tn zN~8a7^n9a7t1%Pb^+xYubidID7`@r(BaJS##Q@o}S9pDwQBGs5=w_ooYV-=Di9YXr z{*OgV-qQc?(2@zRh960~JVk#iMPHSo4@%LcDSAPQ?nu$+q-eKt>ff9!Xt(w6CQbzB z*%nW|mbBMS!4RxdQRr2aUg6{k>77P+Q@G80#%_-G**lC>g~>fk&F{suc>HSi zyDYrhdUsgv4%RmRZ!G%P)?r>5>*~C+i8AhsLwUDfWZ!q+qfOA@2)a^8c*a(mBEAy*$-Yj zTHn<<3%RTfUaQf^FrQgP;%q3*Q@Nw{UF{o`TVeV(Q4i7=9CIRCPwb>zbE~bycLI0| z1K*wmKrUL}J&@nJB&%`KwuJHPy}M{Vll5ICakGN{^Xt2jy}DS3nL;UG2NA=I@#2lG zu(FC5ub2AuJC&4A4y$3^Pjv*lR(UH`VL`BW<}g2lO%u05hvlvP5(|vay!m(#9$q`N zui4L$vdFm0T`I}kCRbzx*MuVc&PmkO~HUm z$ALpKZfTm@!QZwL1OTVne)VlT`O7ldMa zIc*(nYy_Ii*H9L>E?tC88EH$D3(v^Re~WC?j~P|=^TS}F^~#mT&uxbv?n@Kk7t%k| zVpQD~TJNh;BgW~uzEJ#q#y=Q-A^lpfkh_GdQ26kCsJ>BXy_9Ej=eD;VIN#QJRDRBd zb)M9EV5iBc9P{K7>q`q^++uPnPv?TZgxptPl>XhXf2mxZ3v!8g?}jnnR@H`i}WhUpw zCJBakQ|pw6jrAd4ksj~cxOJREW}t@Wm@v@?=2c?gvL0gyGG z$r^-@2fu6n+J~z3yXD|m(svoC^ezImj&&ZWbuFFioB&P*4+8bPto)7vnaY;w`)WIb ze*zWXBVaLfKgcb$>^AU7{QE%V=gZ(B;8h?=F1r|1`sRTLb3{*dRt~N6oLV2#_YsxP zx2Y2OzY2=}gVB$I%J2Q4;#XUf{vU$U-v>(nWuVI+=<)};{DI0JaqHY--um1m=vnyh zMitHkwO&>SGN&9@1=1(o`WbULw|=JeGU~>yuVq2XVTbEy3>NwuGl0CX->}cH)3DjF z$}npPxNv<0*1A}DPSAJdv@TU80h}x|x^*s3W;TeXfOI}fZlm$TIP{d!Sx{~$@Qrrs zDuh4H!jB|w>2sFLk>AzmD&xz>i1;5hx=b{>szA9Tj1J>urO|!Hck3*K-$Z50HHZ(b z^JsEs8vR$}pKEk@&Y5GhzIQ42DWkQ%E!SqW&dsF12>{t_yGZ8`;qx^dvvSnD`Q;O)gz-SkO!D*^c&^CqqXc zadfMGdE2_1-28Nh=K>N30TR2U{TBxlDXk>*$gMM@IO-FWpR;>SVIOeV z{~LDKrdAfWT~SP|58AF-pGB8_^YK~A^YKO^lU_b!NgpLOrd?`d(z4<_qEZuO-|MM3 zCL6noDV4|ZO`d7TRb;c%%K4W)rd-^L^73P+P6ek{R8~51)&u8W5UmFOZ`T3C`NU?% zVYxtS_|?Tw>)dQp$Ny)LaIlQxKfi+48@ulmFeCa89+7@kFlweO}+{ zL)`qudnW$xXdUo+UgF8=+?Cu`CNW88-jUai)&U1Be5VDh;-w?EuFSv$H(!#TJe50I z2W%$1+!86l^^bpV>wulyz-~l-36s2+s4(Vi(K_Jy{MMy}G;@83>z{SWbwE|^W+{l* zX5QOAPpy0CI}WUU6;q!q!qn-!I=^}#YB!o`^yGIIl#h6EqQ2*{5c547S(b~I&i1)i zFD`weWOZG)tA^g&Bs0&g8?qE)sdYk<`LSedk0{GFtb*`eoI3x#irA)i$9Q-Zd85fv}=d-q_PZs{P84<)4L-nDh7jsBcpU0aLm zbI){?svOiqeU7zR(eJ(WA4_n)b(Gn`R=jo7H|R4oZWW23ck;yHgASb%Z_;z$S8_pv zHjowExH%}+XmK`=sOYbLV|`Kk&g*KQpX0IvIih{1bv2`(Upg$_sPHYEc2tzTRLP7+G57$yGxw9*+i*U(~m!%rG2ZKfcgwb=sPN| zp4*nFfm>gL>*0f+mm{;CHHn* zy`z*gBttB&pZ-j{K82Fkorh+`bxw;P+AT@?*3Nh`*n=iwOSB4ze~_O-&s#~{%g!R=9u@n=9+8FFVPCnQ%eU-AL^oj?=3*CifYl7}MVYGY<$CP$yYsjmME^m8vyea14q$Pdp1h?;LmV z^(HuXi~7pQ%nWCC-j1FQQX340HCk#U!mNXL(g_ihLb~#zQTnf#S?*pEhl2fB%oTQ0 zSoq|P!RIdIN~@P-pSU1>3kW~;bDqn>AyDaWtX_;uwI@PH8j>m1wq@$ZeZ(S%%rO(* zB};-MvJw)mkMucU><*d0ce9`;XX@1Y$lJ+%X_6UdIz)MDdwJ(|`X1)b9^|2O=XXeu z>p1V)qq8#gc)*hR)ZMmrI8Lb-{lhg?!NEjtJX+&3M=xcY$QzF~c?Y7ZPQ6B)a?Ly? zf@x(URlPCMc0+f}PP98u2hCNd{#iyfaO6?E{F&4wnqFl^_&anTIPh%oYYN6v-@YJK7()J%$FkLU)j&pPcl_mQ9NMN zrhR>*bFuLSw<7ggMd$or??EI*3}ctUGn}A)|5oTWhzp0TIZavH)59E7Frmqe zf`dCyKZj+pWbPhLUOvYeR(3F!YpTwZp?8QOE!^Ki{ifx>wrxY5*A?zzBrsD(S=}ec zc$gk+2xW)w1Y?|PD2qQ`KkT#F{!y!9v2DXicP$;HmpsIkW$-LVLqSK__<3mmWFE)v zY^06RLbn4U|CCzeYCDrdJ~rF_8~TSH??Z`dlI%5bMJDu!=T4j}npY zeR@VusjM00UywRZTH^y%)?7WA`$YRYOUDH1+{0-lc*$;HwfEDsx`8hb|GvGPcFFNh zWvRCZ_cFg5%Fpg!%_=9~l>O^LFv<6c(>}o6;}2IXD=XQ+Fdymw@3{1ZTmMk=BK4X7 zx&Ct{Ft7HCq)xCwy`i=#SO|w$uz2xRa;$HtTP$2C117p@s-4f?sitdmpD~L9;SGlv zUb(owA!hgW^K@=bMm~g-4+e6%$;c9GV~`MS46D6jZp~FgoKv*0_Uc;BFAAS)G&}K$ zihqr<`aOHm;(4_(QoRse4jnNRTPWp=;C!DJj^bex8Gd!ig$oOmw0Uz|=BBkSjw_hI zxTRoW{rm+jY0ubcNzV2mVfFJ0EP(~?;3Id2RQk-J+NF&g-GsVE-NJ_RTavNUI0Go{ z$$3aYn$uifqFEAZUYu;I;l!Z@iF^ zIcIpk3OXLXT>2&jdMt5GWCEQ_{!A@Gb4?#2{uQGGfA;{+{uJjtygvO<>DyxAzb?lwwV8IL-@B^O{^Irf6{x^rEkc&%4d$2(6~OuFIW8C z=6~c6{#(p{75=&8cex!f&c=Dp{1;fktss0ZeIIYX^MN7c>-(v$q4a%P?fet9Pj`8J zmC*jXay;%aKDE;JRRU@Tq*HLowRUyHLN#;)|R^ zB7W&itb8jdPxX^5{z&<&oLb;t{&v8xe&eo4I>h%?__~cx{l{GqK3D(n^%$S}Q5Iih z|Doi*4S(VvLHyF!ahI1HD%V4XQ(nfW{*}cS((5XRZ}dBXya%Fuk^IjZ=e`9Mo&+vH zEoKUM68b~q!KG4@0jENLNW(x^q3|tmA=nFE32p@EqQCS2*bIFaNL>~#2bY0Mz~$go zAbmFfQt%$=Pl7Dq6`ld6z>kBAz#@<#Fn<(yBlLTWHwyn6_<67wydL}osB}CGDjmx~ z-n|Q#f{Ve+L8bSTpyHbWegT{Wei7Wu++Sk6qb>`d2J6B5!OwzU0zU`d0jgYX0#6`a zi$Te|7@Px6HUG)rVfY^gD!t>u72t4C>3e%ja6ZC|pyd7rRD9haIw^(U1;zJeQ0cn` zR6JLLD&OP4&p;mx-T{sUmA~QOSHQRUK&Eo+2bKO8LHR!e-U+S)k0X7LfJ)y(;IYu( z0T)5v3+@4(0+qfqz|qjtLB_qpNrvMMhl48Tw+XZmd>On7{3WP#{|Hn*x{RI=-UWRz zDEZZ(!kuFN#~3{URC(_SP9gq*-2-_qg6+8f2K*AZ4&+m3;pf0FgV%xzw+K9na94mg zL0@R@33ETy+zUa4pJ2G1%&Hx10@Z$h30@1z?rlBzW$N{vlB1ct0q<&x0z@>&^X2Q0<}= zRC@A_-XBzb?+)hkHw^5A{s;O|lKU#C^sEO}uRjLG{{VOh{IWAG{(C_2w}A^l>3FY_}spek zWtU3n**+pTKjdvt>HG^Qcj@7wI^gz+FN4;(D00`iC=8YP-vj0Tb#s@U`#A1*f|7HK zxhKJ~xHp*lr$D8z5^Moa1ebyZpvrk1sQQq;t;Vsph6m?;yb3bJ>iR2-U|IGkgk@04mcV-4NT%b6!8vhJzJ$?b6${-mqDJ1 zg-?TW{|`{@{SI(0>6FcaTIhw~Jg^3w4_*KwD!&rccq2VN`JW8dfyaSVb-wl~t33Av zZwB9r#bOO$KR5#a=fQu2{snk1xE`cv^6v)~FJn=xhICLCPW~;R;^$fD;$Hw>f&aze zT<{3+)A&ySx!itu)prr`SJEUVg9)$zJR6(;}ug)!;GUDzFq>2~GyPz|+Bdz@xzxAaggj?|vfK3VkZL6eJIB-~9}5 z0rcVE9B?`~3oHO0>hYLFY$0Ys@t&3u+?ymVX0w(A>hLO zfW{$xWUsH}&-Ex31J^qF^ZP!7kFKYTe$;67WBIQ$`X!@(YxHK(B(R&GuJ?>q{&kI{ z(aOJoK}XjZ(eQlJ!tZDF{CxudLp?t{x{fjbH_d;l(c6rkVf0ZZufpg;qt7+^6r(RP z`b?we7=6Cc^+wM!y2uYl-+8L1^uJm70i*xjXw5Su?*~T5jsB_82N=E1=);WOX!OxW|IujKqmaDKM(f-* z(Qg}ly3rpREqfL6-_z26p3(aneX-Gp7+quZ6r&d!eUi~hqpvplMx(DY`Zl9)Fcx3ZF1~q0x;-UuSfe(K`3frQhiLjP~bve9!0t zCaJm}GkT`cnuja=QloXwpy)26Y06pq557iOYyZJgE1xy^i^pGj&V}hSBlP7F`cn~F z&)0DH2O{*j5&DeaIf!d;>Abpdc-iR)(;r0W=Oc6p%wc}ssj}#CqJ~{ZK^SHzV{V5%~v4{1->$Es4;X{Vc&3IPF^4 z;a-;T_7B@U;!Z=rh)a&s5S&+igM9cnhZz<=+SM$A1pO%pgO6#*I(8v+AVHn8G+*b^ zj2ZY~8%Q`onf)l4jW+rynEs~dvgZ!Is9zX}$=Y6{{WSXMq~j3+Z*vF;1x)XQp`fb7 z-<-UnW$qOVZR3tu{5~5MWoRQ$$f7+q_%j=P6eO_XofT#9i7=hu@W~v`q)s>?9K69P z1Xq|%`ls7`eGtGzV>TJSh`N|vU{gV5bR5HE*AfZY$3}qp<*B^tC0l>Igz790v}i6 zmO5V=oXlXp)^-BcOd5?pEhL=4P!n_Yc)b4WLwmDNqpybac^Bs4i{2NeFI`{mzSw;k zdpW)~eeyGV;Jm~gSk5Z;Qcv{EC;Ir)hliZ#Q^0W)q3v#zO1KwfHE8P@egqGZYP})S zm2imm4I|`~F87d|mAH2awTg&SePE(1(hNKkO+(caBD2zi_n^qtnu50JL#1onIb_C!`!v2`}CHwSguR*Sh9%CIg;-~nuv{vwemlG?QEZ3tI6q7Sgs=8 z>m+aWac*7GxrP7jY@c3%y;t>`Jbyl;mk}+Z!Rfo8V%7zo8?^UAgV-uQW<+I#xKTht zOQsPOo7u^RCFlvwo?TTQ_Mc#ax|ql6()o+Joy;O^zH`YIzq5URs}BwWZBwCfEnxA~ zL_3?+#(kj+r9m!ySU{!}SARpCBqLYfIV&#Uj zN4qpQ-%vS8Z}ZI5O=KS>*55Kp!s+ay#9rBUV<^3u(y8n?8N%&2$)qy94<@6h zU77k|SBl{cD~76$sm5+<$J(=?(ZUsu+q?OO+niDtzo^@}ZLNwQ*Sobce#|fH;>Y(S zhh68lt0<(#E5}t?v%v&*jK7&u$7GomcgsOAYBz15J?+)E`v{rdi@P-uKSp~hT#!r| zW^}!y^`rc|^D=fN?*rkyyTxgCADIfZi!o8NNiNFFPxJ^29E1HE9pk@5cF>wPP4rCr z8Sq(>2|SmbVBfJDKRCd$2!YH-;)`THk2#$|>LE8Db%I5k?8ail7VA?LoHnW^76i+F+3d|B#oSNmlp ze~d5t7E;Pw+SUCt`xG+U$lA6IPZk$FA$9(XovVK)rT1j7%5&+U((YT+f3n{f&PF+o zmf7gMg5U=yIxgIpNNsS@Ri$1IS^!%(;&-hnk3an8z*>@&Y$qm{zT_C9Q=1O>v~N1o zR9r1bpWY() zn#!^wz3GW{ix#L+qHAy`70c zORW=F7JsxNuWj3$>eL5IuB=YI(YCEB-u`JCYp?~W_}Bf7@xw|3YP+}NN&Biw?}PUB z_1CJ@n@*&*bLBnQO)lZ9wCx+p$=%&l!PY}?k5yokE+U9a=*m1NVppNx8*zcoItU2YU#P`++k`HBJ8 zVmjK@DA?t4>OfD*-B+lBx3ZtB|Cn?edadIjH4zs)wWj}kFDj71)-&H25F|^L=|%wa zQ3%vt)z>m}D<8b0Q&NxZR2vTU0B6mBZ8bNqQy&R+As4@IPtpD~+4ZO21;a*28vQBJ zd9NCLrg&cpSJ+zGgrlo$GpsiKoLANPpu%Lv7r0#f^4+cV`UwMjw9K@MjkJJV0+Zc| zpw~GW^vckTlop^vvAX*Yt*rS~VoHy1E};Oy!>_|Vr4k*xC;YBhWqNP{wbDv6_C;l9 zgS}AiR;K>xB4?8-XCn=iwSBP9^_hqEYme&trDOQ19t^6m^aG-@<{!S!K)>&gioNlm z^!Tl<#@<+HS;>pZH_F=9W4PdBN{b7$HOG@aG=8V+Q|GY_WZ7g@as7@RR5q|OQn~3- zd|ArL4()>G7^fQ#E_?Td;^$X%{@_`H`0;Px7iA?cB>R~@;gYpsS6jN$XJSzm?Og~h zYx{86^=G>RD4+5ULHwBR^Fw38tcQv|{g_YZmEM=-q2&M8Zvd+(euoBhIv}aRtC1Me zHfYnGE|jhC0~+RmXUbDsd=wbwXeGr#eP_)tGSlzy3s8D;IUzk{NF_uY>21`g>^RM} z1C30Y6XO$_6Nmd>MuJk{0=bsTV?Di3n$}0l%d{oEB#aKVri>5qE&DQZf~Pwy&MRH% z8|0FH@zb934QGy4yy=1u#ipa=+za|=rt9Xl%nn52i`z?2_+(LDl>AyjLP+v?J#rkwY zY{L3P5WD6K1DP^XN7+!W#eh&DSs8S?(y81qVxoL2Q?SJ!oywGn7lBjdl-a zy1ZkPY)U+HSpNwA=e16|A~`%U(A~~~gXjPM`TptN0o5Wh?*Ku63+$oqu#*I{Hs39RW}x0-El6FXWe=+;Y^_rSdYWe< z3itnvU4bBUu2*-&O>phM>q{pBjIYA4E40P%B1xvGIQcBhK=`2w? z#}t7a|IhXRffATq`AO_$HYQtQ%`NlTGc1}Nz2?B3+|hA}omE*?aSR)J8#sZbpl0FX z=Gp?jtv7JW%)ElSdZ_^*XI|~nnDb-%Eg#q2_St4O0MFGHrO+2(qD@k#Szb6Z+!7d5uX%sXFm3+4uiu*e%0yRF2* zCSzjJzT6mg+p*f-QZToHox&}(^J|;Hg2pC3D>oH1&25+;G6tVEBcI-6Y+Hi;4&geP ze{YFRT3DB{ARn->dshjsZ!Va-P+7gkQpWaNgsCL;9Xn>F+USUuMUAe|+z0w}IZkSJ zMJZ81DFlUSd2|7q(7Lxukf4D7=t<2-7fhbiJSEn&WNtbGZU?rOoOEgE(Ixb5qJM}( zuKl9j7NFXN$@9S##9iY|NE=kH{i$-?vF8?{^--~~)^lAT(E?IKR<-fx8 zd=DI=epcyu%k?dOxx&w3lZY=p4 z6)YBemtU^<8}-oR;xn19LGo9azw(zWe5u}hxul1gEB#&OKYs}Sai&+>fPb#~Yc>C& zeued!Kd}X#H)ck^>251zR+onbKJ{~VdA?A*uj8@O z_|)Is<@rMUW5<)%jmD>bpT(CW-{tUky%wZX<3JXFXn(HuAWhgD@M%2A;tS>HF8F2| zpT>nOzEFN-^k}*9X?)1Vr+Rz^zHZ~|4Y+uX9y{*VVQ20&Dv}@ZYd>|P?T^>E;V#b~ z*&i(aa`;!g9^^~o$jtEs_q&eF6TJ#;@_kT|OP5au_j!{%Cv}$A;oN4!+5@&tBtM7GJ1c zUI1UC@$D$y>)~5zd>Y?|lJ`ycx{XicTrNJ9yY}8}GCqxWS$vUp)xyB{CAPkO3S>FI z@GS5fU|xnL)F8u(rCWKi)Q2P)kD;GNJP?i1_-eg~BQ>!AGq0HPXF zxE@sce+KgC&wmI!7W^jo0Pfo7qkL<>hx{ABF6g-+3p@Fp|t?2cXjV0H}0)3sidV1r<*RsPtY3Dt)qx@E~{|_%*QH=p(`7p$`Qm=KxUY83Epj z)8F?B>f=>V>3RWFx&9VZ{jLKa!2L&{^7EkiF9ntFt3ah^9;kkJ5%|BrGr^VM$)My; z1gF54Z}ezzGISoO{`B&gApOsPG?~JmfRgt$Q1WgCzYVs44}j-^_kz>FqmeTi6u;~z zF#mA&6Yc}I?HRbg3aVW^2Ob6g;~>xc!f%1iU_01CSGoqg3;IIvn_$A|Q^4z?CxV{` zM}R*7Uu7OH_uqhWUk~02t^y@*87TQz82w35^>a3;d=-PLhr_{ZL7mGh{}G_l`_Asp zoJcaW?rQ;N%k1%>1sC0cW+U@Htd-J_s%WCFg8V>H0W$ z7<|Rxzd>u?-=Wa^gB{Rgz&vQ#B@q22DEeWeA23?`ArHo1b_mq2n!r221t3i<{~}P~ zt3ic78C3cY0>20D0Un6E_Jyv1{`-hvAN@-pdVTr71tsqnpyX-kRPuDbkL2kYtNLCH z-U7}CC0}*~ZU(1=`@>fZwnI+@Sx(R26Z{CBFSZ@r?n+w`Ew6?mvLn;r?q- z{5_!fe*}vEK~Vfljn;WaqUV9)zZew1&Pfvg>E^F%NsuOzzZO*Z?}Aie{z_1Cs7oj37Vv7) zK^eMnqXE1d|9K!qoqri9`7=R^AiolnJmvza{=y2<`!8&X zR5{R2#Q8^15O85 zfC+Fp_;IimJR4jJmVk|*;#&Zo0?q*|z**qOz?ono(N7ndnx-IfkW%1%@%h zUYK2Y!!E;C!#Refh6RQ(!(P(M?Wk_UF2h#CIfkW%1%`kNcMti{-c7GRexGQ5mHUf> zwrup3Mt|4%OZN->9}-Ohy7}o^WBgu!yvOKcEc`~Ji;Ui6^mL0_iFW)!*C(VC2om2i@k;{r-k(_dbpD*^2aJB&=ygWR&W_^q>z98v|HCXluN!@$ z(f=@drqLf7U1s!dq)YK#VDvcA$e%MNNMFABUvK_L8C`4i3C8c&J4?*}o92Ip`TOHV6~twz6Qbjs+z8vQw=-!S?sM!#+JH;w+M z(GQB|=l6^J$Y{5yOMS_{m;5L5u+{Y&qh}iZlF>_zc6JoWQs^Y1Y_k8w!ywiz8a zx`2nfu7izE7(LPGMx&=1eUH(n8{K2{IYw_Y+Sz>|zR66=b=8^wETi>)p!6&^y3OcS zMz1h>lhOAYJ(@|su5TMX&FCK)J;!L-VUzq7M(g}Z(W{Mq$>?6A`;8u5;Kawa8C_)b zC?4zzKg(#n4~cFyny!^)S0Y8*iQ~WVU_5j|i^pHGvlXVFg$UDMhcQgoN9Zp`=+`3Q z7ewNdUU68Sh%ns|@qaHuuZr+T?NHQ5_|J*(|4W3ndATo+*glc)(3nTnjM*IsR;k6ep9A5U*!t|^Nt!5wgUlyTf zMdUMQ&fCt;@IKMAMD0zS4;QgowY} zX|FH+v+EZJyY7QSFEgeWs+^62WJ3*BCY*@@PFPLvr452a3>}~!5wd9j<&G82n5>Z9 z1B65j3cwc<>$s)TfC2{w6Qm--ZN|hwQU={Ku{U_L6G}?h=D_TXi2}CiXOdOrPerW@ zG)V%{Qi0GBp9=#E1ZKm)G&KSih>%H$uz`j;si07ZbuG0E7g}K|Ia%zI73hj!tHZQa zB-kDFnq@tLoYl(6NjgBCQp-+H>zg0)Hb(RORWp^mN3C0-6oS; zyR??>mTqs>58ZZiw6M!VCR6K;efJ`P={1$ zQ*jfV79dj%{ z);!T)rl__`D28=JL4A%P;Bw8Looz>Aj>$3a*c=vZEs2g_vcuQT>{4`@JX?;5bs;Y*W5@Ec z&&ytA@;2HeQR|G7H;2V`pXP`>GiepLM)T|Kg+6A1TJ^#Zx}sIMGrJl3UaG6h3N68k zw{8nqU$7;BERj32o3Yugm?O^$P4+s&^+9wCT!i*d!nG7Sn#gVhH&0~!pEW5ZYbHNk z7u!#~m-0J;-$%Wq*YEZPU@t>UCz~Z8vlGJhtguOQq%6k!9TBEn51H9EDW3gz!n0bn z?e|Qi?E*yhY1G9p7&$T|C>+S`BZ=?_Nw)ouVP@^aP3JGOQ{kiXZ;kI=p<4x%aD??_tpG2r+3Iy{ckIe%SV2Ur61oI!bSdnL;WN=Z+JVa3==g;PNRFtxvf@b zvlcu=c@AzbuCb&xWC;zIT4bN;M{X}VXB0~vnI=9s2^?a0Oja8f%VvyYjFd&|64q zKdAg^Lc!qRO4*g5Z$MzC2z_f(aRvMCbBtGmEAziL{%no^>&SMRu}_h&v(Y3X=)abq zpuN^~C+d4B@6tr-$;6t!o}O6q-l=)d)IWiK=}l7@2aoBd4UC+DK%Y<-j#GGBE@X#) zy!|2d7=};PnN_JZy*PoI{r1cV3&Sf3O*ge!BmYErc>0qOMr6rF{W2}Rmxf)jIZJfN ze_VC%*7&8>o43Yi?R5uIUHuT*8Vf(mN$elPE?n&abl%R(mz1h2^NcL&W<0>Dj}*A) zO(v(-=Uw39ZolvNBlmCFv&sl{(nwcUl2my^jz{Np=VrJ5`F|=sDvt?;u0_6+0z4hVrho%ra`?_7PxOQ|5z;0Vjj53W8nWk|Nn0(fyVmSg5><# z*xW0cV{>a3^RJoRd90~6oap|?YHC?h#bbf~#pcz{=lIA*w%sje?XHf+o*3(VI4opK z9{(55XSsm?u|;#2#ugz7j=EUm;w7;r7LV8qH*fJG175t@tykZ$K>uRRpKfZ25$gi| zV`~}jR#$UEB|Fr#8Sff)@-1$dUl6Q*7A&qS$n2xbu8C_QbMCV-Hgs)r`mZv7bZ>I{ z_wK}B`bfIY;+HG_Ip#l<{1rR#@7{_3mYw+P`-HBc@;}r3he}`TPW)Gy|4{k&FIzK6 zL$2~EwU@DqA^caE|4`}cHvg{-5q=J{EM0Z{a_!UGxD)?U-u-l;W0o`hE6jhW{P&vw zP~|^vloKB-r5XAT?YxJSU$hf{ zbVuDa)VZD8Y`={9ue0#uk2$-*_cQnw z7@z9bT{+~vg2#$okT-_fyJr{pPJ+*$f4QT4TneAx=d&X|ePdl^@$RVn9)NH4E~HO7 z1>L*A_fPnGjBiKfH<2-9i}7ika956UmhP@U?^EN&P<+~FR%H8uc2q7pw{x2DY5d5N zSJCE1mWep7gKw4b)froQUs-6M-|O&g+XcSyNG`Q=NHwmw%jY)~?+o}B7~hV{ZytOr zjBiKvdk1{?7@x+Qq2iS;_bNN5)W)4b`{PtDZl9U)?WmkbjL68_5#Mp}tu}cYkKEQ0Fu*1P?KH>Eql09XEIB^N3%1KH~eC z(LV&Qf&Q+!-(l{{K*qMho6KGMN=u>Vf~+qWUJNb*tH1_u26zxlol`)?qjPfRfm+a} zdF}W2QNg*7FN5e_=l=?H=`j2bC_bI%qi~-GuLN%e#eakOH-ZXxA^2%f=MyQM^yid5 zou8!mb*_@!-vGtG-rOGrmq35d-0w5I*8CS4>YT-^;rkc!Kf>JiGWsp*NOE5Um5%R& ziuYb~Z!>H#|4*3zDc}P5qz@}R#BdylPLn$iQR)5%ZCUbP0h8dbjn(i`H2>qkCg=iC;U|D~VBGv)B~rP+2-bqnfRg)jLybA|zYClPe#YE& zE~4DEU!ew^ZSJR=`zauQ`$=C(^2V6^2yia6&To^Pf^)$8 z%>8lz5yzpUz+EJyeW7}BGzdsHx2lK&JkhsP!1rGrm!D-+E@L+HbcnUZRB+juj z!IQxRcmP-mehi!j@(Ic9XE+I*42=r4+s`l+oB++-$n9s)zJSrt`+_mB7~Do?_5rtm zMc`(TPZwi*LB@EupJ5!h5&C$r2aJQ=AUb63JV!o#xbqy316ShCr^;h z(Z4jhfX=E*`=R9T-y?gCZZ-ecjrQ+}?;5Q^K-X~i6u#7GEls-g7_D=cM0XoK$!Pyx zr}0q!{ynb5=u*m1SGm#tJ?&hhd(D5A(f&QGRy2P5(;0L%7(LnOCC2aH%a$AM-@|n7 zm(t_kyY4mGzh|v9+P_!*z-a#-^@wQVUvBmNxY2hQ{glz4HTt(kf5GTK8vRwH|6=sl zjMjO*l7GL^I>%S^zZ?C5(cd+C6y+}e9~iCYoM@fntxL~8(T^B?xY3UpeT>mPM(Z3g z@&C$b&2dFPYjlOtn~Xl!=ogH>$mm|9=NSDLqw9_CGrGy>zZrd<(K?@8*D|9AjP5jg zgw?n9Gb(+fjduHwp!YI*rTOn;^!G$F5c==VKQ&tWyLI&#t$pCSerNPjqcu-a_%5U0 zGP=j;JPn%oZ!tP<^n`JNynLfejdtg@!oR?1&6^Z{h0*0kuQuB455m9K=(*-Unum|B zMx%?2zRBoWM&D_4tI=OEdZp1TjrQkiK4kPZ^IvOp0S`Z2>eotd!stI5-DvdRjK0U{ zJnBaL-A2ca-fZ+CMvvoRtLqq}rx`uXXultauAHTRUxkDAIOt)ki@A}WQ|YTVLN`U| zt0J_Xv*GZ|BJ_&SXua2l<*$#>FGlF6BD4aB!~Y=SUmc+jj_}7LbU}n) z#Tb_V=Lr4v2z^3?K0QJ|8=>Eb(Eo_g??>nvk@V_Z@NoK0h|t>48}=`Y&`#0Q>2*p8 zDp050iH5aPV+|<{JN@hW+Jz`#I_=w<1+_I-d4IQdKie(d&kk1a9dJmI*6%r_h6Q~6 zkImLPJ&K-Mzn|?E@TI9MH?K+?)~z+o;*679=ARv`^9MS?QZJN4Ai!%YyLErG6qlfZ z$*R94nN|CYZf#oiI+L4ZLv#K72EGf-ZVp1Z?*p^-fnc`#IH3PdR=OyiqM9j|nVO>k zDw%Shtxp?v=L#TjbTWfmWTFq5zPH<;;GAnvdj8h@^(iC>`v{jchs&a`=ve}D0`rUd?{^zN$O={8=f-NihQsZ4Ap^N$>#b?Ji#SC2y!}XL_vDOdjv}?wW=?l9;}tvIpz2X6v1n zn!F-=Se9D)v=91-wA9QE@^+|q+Gz9bOHE#*TRF&t=QSql+L_+zMixVKwVJ$*OiYyD zUKT3MD@)|g^iF5`^jN5w%x}ZxNAg{}c9HT=Y+4g3Ws$ZSY%HKHFc(!eXY$ikYCrLw z!LOL#N4?T|PCGoOZM90l>x&MuNA2`hHY?`3M7*K9E`G(xZ_$kF;+Kwm(Bbt?HR%cN zbLqbfl9xW8it}$|AEz?)Vf3U9md;`^r;1bTjkZ6IQd&m)2tB*;Sq_{MbzFDS5aRZO{@1NVND)mU~`y8axJ`i7~6;x9~!eq4z z?2ahFd42oOkjG(458VSd$*D>`w46J~)IUvnLL53G-5Sc}(H^pt=)7A&5*?kA@Ayc8 zLSrSL!z7$b+3gjv8I$7e&k>-yGdZlfvo^0P_23G)DvAeGoEbg5iuj|)P2>oUma`Ip z5%+UCW^60>XW(FU{rK|b4?f~DPf7D#yW{$8qgzjpwVclZJBPME-!j(p{}O0nom;n} zvTegKlmtgL-Jj^VS9u}j>D>Rx4lGb^T#K;;SEv5cw=cO|-!3&}4&3`k-w4R%_ljKK z{&P82b+`;vwmm+)?=>8jam<4jrznb*ie`Fe7tnNw6-P!5OQqqNI?u~Xr0#b79e1nL zmXFwjYV3OwfnH~^?;@l^(BL)Jx)QCdImLUY?UlcqQK_!1Su$cL{u~?eu2q+7n~+)I zIrC{~|FVv=#|?BRYPRfzY5d5AJX3bgH(^(V9kL5dOA6ZGS$fQlQq@1kDkR8!a2#Ty zBbLzdJO>2h#?9;0i*_EtKEH!=V=gXukQ6VGVhNo9G3dOR?E2t*8NYcUI4Vztss~w+UX)$!1icv? z2$((^G%NS6{9OG=uNht0giZv~xZ`AytUHfzT|IF8iN-hQqtj2)Z0Y_UK5MD-!dJv3 zWk(l+!&%yHcqR5zB*a>V1?Q(Qqy(O+%U14^5J_km&bdkwoeo`|NXLP`5Lwag$>arhxq*&tFu^cqCYj#|6XYAFbYM$>V3SjH92>*`wS7uBLjTU(RFp>`=- z=vg?cZMd2U7jyupMD~qU*)&r9~$a;8wj{FdTb$mvUT{aHa^v(yS&_xz4X`d=rumor@M0S zjb{Lz{7w+B>NSfm6tBKDlp0@p-6n^;dGO6LKGk!Uyioe?fUni~<``RAPcg*zL-fL$2)qJ10nP`9e-adbHz@!6!TI3bp!}DEWHJ8+Q2z75 z`QWEO`B#EOkuSSw@;?Hc5AF@he+0;1{s;79`ELQw1AhlD0KX5aUj7%j2>dF@5>vkH z%CW9g*bcJplz$`0Qe1uuhz^$13%me49eN>n5_m3ngy9HK{(l=8=*RsDl>ZMw#rJJ6 z0e;Qgmw{(PH-eXd^T0ar0`Nlc45N!crCW9xrH?iYJRf{xM4%t|3aIq`3{?C1A$S(} zP4FV{GvFt|t3kEP^FXz?bHIOvo&nASPXN`9q(7*5CYZbIAG36qKLVVCyS~5A178JM zvdn)8l>4vDUG_xPu6|EjpxQyTxtE#yNucV# z(A*C<_wk_WeJ^t#21?)V@56%rq<5=Xk`Gpava80o>cX=@sxDu8G!4+wBczD)-=nXK z{u?NI75EA0e*+uAtHEmUJa92s2~tG)`W|`?w8p$j@GS-j^@qQJs)uJm)#o};^|l%$ zsrlal&!k?o)_Dc)R|W3->3cd!+K;+)i0oK7{zrfpgS1s$PR~#Im0sOcs;mG!5u53gvw!34MuSPGIyr#H7ZNZNVc z26}VjzyfG~PH&F#ae8xyfunIJYc$zFpK%TZf1^qb3k>Bb_uhbiRJUQ5VXNUB!&1Wn zL%@Z1`b$)N=^k=HZ%v6oaH*rP<7)H@qt}Y2LCvC*==!D6ml*Bzmn3h`z+d*(#J|$~ z-!giu`RnW!`M+cINE(yq_l=fqP0<5JA7J!wlUHE$?nX~B`f{UBG`hy<=|<~Z0A1yx z$!{xZ)^(oIejX_M=JNORzB;4*Jnz$ww){E! z#*|5c)rZctRs4Qlx6#6nxA3yxE`L9-`-}NMW%B-RwEw;${b|L2wfTQw^mRs$BrWn^ zX7pZ0-(j?~XN>=6jduD;(DxWU$@uRxy3pwRjsBR?-X8L)Mn7c!XBqv7(VsNB#PU1K z=rW_7J`?euZS(a(7%qz=UJAO-b2YREa_`{gic0i>D7k$M@IbhoDKWyxfiAzBL3SW z{-22W9~$vr6Y<|G;(t*jJs*$oKOfUU`@;V*ri6yeu=BJ6)$g#JV%{;x&+Ya{-8 zo`&V6BK|i=Xr1E_=HEZ!UlgH#6OsS52)#N&FOSGy7V*z0ElCGUs#ZJF{t8x$(i&M_ z$t!Fs(d;=o-KnryLWxe>x-|7IAKon@&7QwVI2-jZx3=U7KC{;>^0qZImK|{pR;!d6 z%v{c!m$rbY5VC-%C}or}Y_>9N5Yq+BHV)~7WZCP?Xqh39rLT;YPA5KXu`!TGgx+Lg zxLoSynhDS;dGt#m5MW@^tZ*ahX`l57$i+A1iqhKi~sWWv*B!Zhv{ zT@_USqN`K@RJ3IV9;Zxa8cmdsGcCEeSqwE-#b$Ho)-6q0Dx@`qVNp~NgA^YhK(pyo zP4#TWUR^9>2+%8F?Lf6FtcexGD_f3AiC;Vw;TKSYd)Xny(boaDzS!NZTLcwDrerNg zC<=z1kFS~AB4+w&)Y-YXVzi(|fs3unT1vg5oE3$)jp&_yfq27+zBqh|d2KYW=H|8B zu&iJaq$PThCwiGDdZ8zJsbOuvAUM`7?Z$_i>O)QaSXl3k+`A^=^spe*3exvh51zKF z$dL7cG8e&u3h_Qcon$DLw5QTF;~iAg>HDCNMRK7B_L1xmo>+8p#ttFfGOY+EVO;-J zeXt@u@N_XR*5zrYM0!7WKe_L!KG=#W;^smgQ@L2tDXa_V0X9e#kJzN zbP^pc+2L!j{#LeK!&R290t>VXc~KcVmY1y$w$bEmu|OM5-cl60dEXv%?Mxr6`9Gx)>Is?))m}0Li5{I2nd2tGLv&EUVM%ES`NBbr%d?3$HbSayN4|5cg#XQK1M zjiC?xd`qoLz2=k)LP>7#UOJKw;%InvRBuGHD)H_gil0xEJkvBX(Rt};^r>FcQD%IJ z{e#P5RY!6oDo{&Dq8Qe{Zz8oO@$PddTUD0)s%hl8o!1xT1*vO)J`t~2TU~;t*L#)m zvwu}l{I^6&PyDtU5mlLbs&dNXs3TR@{5FyISfb>~t3Q?g9{rlv$wF7_#`7(!+w&6f zv)7V9zBpexdZ6;%-&MZ*dxTfV&-$?J-IvOyY*-P0cq&N^YGGh)*}&7uzx89u%T+xd z_IbE0^>}$|vonvC(Zb1mk4AqYD8HLu*LgvFn9kO>bK+C&4{YbViIkKc>f#QqwpD`E zOI4|@j-xWQuA=>&8!M%R=If`ra|tS0FO{1PM`h~qviQS~mzQjA*(Y$e5^w^}UVhw+ z@{)%XPj%|uB(}XCaZz-*2!l)xp<$$SM>UMn`asGbt>fm`i-O!$bxcy*sq7drk#Fmp z%3Nb{|9(Q3vNmlxY%bQS&PP`Jyav|nGF_r7^}gdla{z5YSMcO4UGVFjhLl1(E*IzY zicQIV%TrqtH?LEQly0XX;5f4N_tYO<$^x@y&MsV7KT`XrR9~rk87*()I&rD? z3*^yxVHc^&^a?713T(xTmfb~_&JmX>4pg_l6TfpYMNyUapxigKFXX?vdzFRhtXde-FJ|hcva>pmj<|eN^4Y3XU)7ZN5^e8|YC6zlTLt*iM>SCV@rS$Hx;M6M z+oLjm=2KOj^*H1O4ps3p`_q{c^@!mFlmWvOUpxe%|_uRVaYo@V%xp#7MSHnI3O*2LSiLoLyH*(zT-w^xn)?)vhP-;FH~ zZdRfF7%JDGCORHbO%%VA*zlOX*CkTVt;%ygeIFpV?fp4R_H289R=oY^G@t%MI?uST zZQB9y+jJNgdRIMynh`fA@_Gh(2MezY%pUGH_eh!SyYxwE<*iBl7`eJy6U9AStK!FP z!}Q-{6xX)8%6P-m=mhU|9{lJ8@Aa<^uYZEDYh?KHaOkVYV%=}A!<^6YJxhFb4sI&h zB{5-OeK{-qbsNej3@lu@ylO%o^e`1jH2c-5ZPqAI1gu$`$ZKCg0rlN5oU9HiK9~Nj zmGNVq_G!G~2-3KZ(s&(rq?$4P(<<0-SZmUK=SMwq*GXsfs>>e1t23LKo>#kNPpF|P@Au0Vmc`1!t{@;FCMb{UhM%G9PzAqORsdGhzQyHJ_r zBnH;fk>ktuA}8^OrzhG5E?II=MR9lOGPJ6HN-9cQ2li+g%l{)T$&Y99R4vPD375DNn!}<=P7SRJ8 z9)I{ujW9fcnI~x}p24SichhO?-_35UuqfH8)T=@FeBKq(f3~)%o5MaBKm|Ol4;tu- zCudc6-jIj3dmd`z3G|{FlRAQ?GQHC^sRJ~Ur<+vS?YnvZK&3jIO;oDe9v{|U;pPvX z&BRQIh;gdfE^tmc1CLitcTbr3Ew0maKB9tjC82|sXsir=fvZl|Po-F8NanR?&bKIQsv(-G6bL@w>usc(E%upFSR;wmx-~Q1oQ@(CS z>r&w+gb&U@nIqA0VRvHSG5J!ip1ZvWuiJ+&Z~r7%)>-iZW@MWR%Gy2{)p8L3N49ut zu~|}?Q7nKTHy26kBMNcl_~b1h(P{|HB??v*YHGmn)NEif5sL;G@w9@4=M zixu25_wBCAdyjGL9#MIlm}7KtS5f>5lS45xBT<}vpQjAths8Fuufh=lNchlC-rX?s z4H{JCz&f@qC_-f-c}7+0TeApkqKe;PE~lw|s&fvmzPd7{)~A$Z&(BDYcukNBDBkXN zgh*BU-kEr1f@{0TUESp!4=Rbw^W%4~8NJ5UczL{hGXts;#(O|`YE=9@jO5W}wc}fg z>&7EO{hP8*y-2dFQZKvo@(xh)$7CP5RNTxNkmufdil1O;bu3n5nhw&S)7fO`J3KR5 zCpzwS`IIT4ADhn(CJw)D6LKyj!UR&}_V zSn|oL>5r(Y<89AUUkt@dm5u4`jlkgNo;=HLkK0)6SUc`kb6_m49N0j*tqoS9?H;t3 zczZp9`>v66Nubw*G0~&*&N* znSSB>xE|uuFYAfl@@F1geTVWdyMI(o|5g!&7{8^4fs`WYAI?7-m+Q_`w(?>Xj2J;P z^qSPL7a~07X5O!| z-xu9$NM*-v3}Ks)6k1-;Muv_HH)h_3olII1s|js4Y>c%`QHnCp)gx?>RW*w>*n; zbW7^4%?o65eR^s!+M+m4eFncef<;0nJ&LuFC68tl3tOh<|reBJV8* z&wF?TQ>#oduLF|&2ddEkBq`aGcOg*@GJ04OhTy?lY>pwF44U+|=z0HMO`{#Z3 ztYv&^6SEdoM6|7vUbRnWC!f^`tzl4CRUM($)=M>Q3Re>i=0cj_L#tixZA$(Gg}*7$ z{!Yt;+b=kDVEOpbiGg1v2G%&&k~f?F+CPj}!C(y|)UK{4 z(Dv?Y#sxK?WzYi?o#mso($W%FODgGMS{c7>6w$NBSDt$44n3ro?dcxUk0>FT>0?z# zZ4c9fisI+1f+=oj{L{-7%vGJo@#uTQcVD7mErO)^9ki@>4$rG9`SaEEVwa=J&P#V= zzwImWWz|Gk#h_U|<-^K>_0=VB$8T%IsdC_#x?d*c=;|r2T0HSbN2fZK)C9X7gEFX0 z{V|jtBJ6N^@r#(+DA@jdeAyw2rt>-$f|-Oq+K5ovTUVhITy@dz_TJT_vXO z)>PN6Pv~I$T2}n+0EVWSQ&m^wkbm>*hvb#exM*HPFyF z*Y=1?pBdH7aJaF9X_aECn)3ImJWT?FA_yME)l*)l*=8R5kF18XyyGF|$sR?1C0Q%Y zN2`Uo>0)|*Ms=lLEcUxTH5-00*W=HjPOEGi7)Va6?6|Rj)y+tBY`Emb zC(YS$E-!6t%A4|BVnanYa${8`@5OJqfP^GqUDG?Fvg7(uMO7&#FE0PC9jF(d4NFxX zqtmANvgzDcwyhhc)Tzsgy|Ux136&-5;_aV9Xy1Y2=)82|F!ha+O;sH?bS>FODU2kK z7s%UVJ}Dm`9&g{cI{`^$Wy#a=Hdz*MgIU?_Efa^A-F{f)rKtd;PIn(<#qU$?XE02Yh3(Ry^pX=Rm9uO#Q385794RA3O?Pxuuk63JZQG<|ZT0kq3CSGekE^<|JOnz= z(`TXhEqAkw*!JEP@nxs0xI1Y@3>J)FYjTBl?W*raUV!+6gCF9Gc9o7`@KPXs_m_~VQXxU5Shst7AdB>t2Eln+x zAxFZieWr)(x5#y$G*~mwzqW11#M^6mS69+Bt*Pc&RNY08aT@LQNxdh2YaYuidXjYFkTf!Ss)eN6Q)c|y&yO9N%DS=ZC|{oY1>@EB z<}n(t;*3{Kd-Puv3|0DQsbT8-wcoy#IQi$N)gcyS(&Nd6dJt8WY>l_w1Y_tSr16RVkhBL-s6Qm!7mILz2*wNR z50}N7#`aAo*L5q@AAZ}CU)gyfb-1-@mFn=|Y0ufOf-JY znmVfv%+u12G(Waen(7yqt!7lNTam6v-Z7R-d78joiO!QIs0B!s;1_Htb$x(0c!WRQ z_fAki8fIOWY8h6{429DEBOcVqN3LG-Il#m?b@^oLdsV#HT;QYCVA~c%xp5#d*{8R^ zY4CF|QA6YTvuiww)RxL)%MUH8OqCxxEhP2>j&HCYoh)+Y)LA}ZT4IA+@kz_xUqeN| z%UwU#6u4(%rZJ&nIOpc|)k>mszi1hF#J;`Nk8f zYCf!7^V*1WJ6fhQ1O9LzdFtTV_BnWxyz2`3EA*d*lrz#3P-kStEh6+$EEq^KR%Csc z++Y3o*yhm@CSE4{cTY^=rR{e*t*>p}=)eYqlaMvuWYWu9eQLWObK1K3B7fkL;zZ|O ze^(>%U*p@h-xR-1bFW0rFA^R5DM72H&wgb2?KAq8aKrmf&{q3aLOJ$BBkT+jjy)lU zwHw>E?@@8!K;Mgqa_rl<2}@@(>(~$U@_Hi-m3#G5X7&N7G467m%N{!)R z&)`Pykc3uaxZ5+}kd;Utn@VK=5_FGl-mdrGB}ske@7Rl59v?rt{^rxl+Fr}+pH08x z8%+G+ZT%OpK%%niKUFuBO8-f^A;0~{>V|yvAEBE9ZVuETpsco4Sf|Zci!3-HQ_?^S=D!Uhb zP3T^E#Cl_WlyzI9y zq;5+b>%J;hmwd={D*iAl)U4Rw>#}E093Qo-87V*A)orT)Wj~{V#5y_^3G=hN*N$Gx zQo+kC6)2bG_SL?k{goRF-THuXoz=f>ePAmpPENX3Bwk4Nm8W`H6INko4Qr)teKL`H z+VSe7O64pT>pe5TEk8FrJwW~6x&4+5@Ba_(X3wr~z&LU2ifd$?WWii)oFv)hP={-* zZgCSfTx0Y3SF<2Czd3nDY+-E!=M*lfZQ`UtIX2Zc@{@@XtghgnY;43Y*kB?*gA-P> zcv0g**u24&qc1tSU~V1WGHz0Lv<$Eqdv5s!m_V6F9u_K(#NlO6u5FmtT(G3RWq|}8 zJtY@QI?l^>?4LesQ5I&9b_MM94Oh=ySf7c{N+EXn#AA*<{rJh3Oe%~8MRr16vY|#> zT262_WD2lPTU*nDiDxf?l3zHtrgl+nLrVcNFKS2pMZw+)^;tpAxB}Yhr6lQvv3YsWFV#nE&F2!iL)Ub6e`Kt{sZmr!LslqFgI_ z_^54i%rtACs_TF=ZaXTmX&!5|9+e!!dcMT7Ci&*!_ zCBJCTz#m%?In%$w{EK-a=L)}($FQyw_~pvK4%5-~AN+Eqf0g-`7x%|5)2L9g| zBL2onf&bprbFTDlIXdu{&6!;CTc-s6Rt;{PVURmQJ&?k>-NZri9k z($bx6huE_)l>R!9Z|$B5`q*)|4m)!%mfzeZx&P!h+4$7{-R1cr=}!m>Mm?*!| zDhHiiR%(3eNAB|Z%8}la;P37Ym~@mFQ+7F`P8w3h=u^{*^GJFijkFN3ew_;!{r z@&6G1IZ_1VQonQ85a|{FEAVgmOTe#wn8hDypQ>lsbSX0XR_d4T^72FHOwNGMpVO)S znTt>H&x3EAou{aNn#Gr+eD8w4(d=7Uza7+mm(#E3U^?Ye@L;eQtOxf5*|(Md;pAA1 z%`b&-g4crUK$iG5YfwQm&Gu7y4jtc1S8Llu~Yu9gI9rLz+%$9l?o8u4;DdBHu`XozLEdrk%9kOQ2BiN z2sfq_-elN+c;NpEDE~M}9TcuD2=M2J1vnE_JeA<_@a<#to<^@YG~mz=Ls($wZRlg%aG)v( zSnM{i4eS7$z&pV6K$=2+DR>L?R-ShY!QX)M!Jiu54qgg9A8Z8A0%wCqg0#DVO^RC@$?OI(|yH;C^ z^#C4f@ld7eu2^Z6#wu;q;-RwN-^?}li3h=b_x<#r_x=!m&+nd@YmWEabI)9JO;1qi zdyjF4;(r-b{P%;q!S4W-jw?aQZv@ruCxen#3M$;bpu)Y|&)3Hrpzi++RQMY~xqrjl zF9(~se-WtXekeEt><_AaY~)2ZAAA~AK39P>-TZ}ie;TN8ANKLj{cWK9p94zHX`sTL z0Ot8u4qgEt3$6eU2N#3;fhyOX!OOtEFwvuS@fz3){uEStt^w69uLKW7-kIPM_6VRXUyrRZc%QyaQA@$qvqi+@BB9r1P^u zwexd9rE@B%a21A6vjDDgegr%pybq*_=5?N%;nD+_`xpTewWU%mH)4U zN`C>Af7zu|JCr>-nq>YEusd1U$FLhX2lxN#;r(mR>eX=Bom2VV0MZ1bb7))P3O^Iv z37l>?#O@yqO5Uqq@bZ2EihmcB+!^56;ABwcc{E7V%s;WS=f41Hg85s(D{=n@*ayB4 zRC<~~nnYd-amsHua2B|M#LNbN2`&O3230>dgS){m1yzsdfU2((LB(GIQU&?3U>kf0 zNYUo|gOa-^sPdQHs;`1?k$K5o14`bl#&u5Y0{DgCOi=5+6h(eI*a#m7Hh{8cqV)9w zB}eval#VqZS;_wgsP?!7oC~(tec5YM``(cA_zbB0-T+<((iU<{!6hJ~^E^B5IYNeW zC#|`5+)uXqlfaAN<3L2`%fJHsP;eng_pi&@ZPWdAkRzyywcxSf8t`y%6?hDIKiD6< z8=MH<4kD{hCwMe?BX|gSEjR(Z3M>KJ!K1*%Ag@$shiyDK2fi;@2aW^J1bMYMJ8VaS zQ{X)EeagYHAbxVaz!BgWa3Dz2?o$Ge29c%7;6DApQD9GyDy3<8J9O<78s*TV&am9D z#4u;L9#8VO%COV0-LTHE+_1zjXSkmD_}OEXVW(lcVVz;QVTmE&!nyMqX((Yoez1QQ z_S277rpV~SgB60|pg0k#UUaG5%RTJ3Kh503{K0wVerKuoKik~H{6VmX7QPoRH2+^W z|CgKpFrRQu;B=b0zHPh{)Fu0iO3%-RdVZJjqfMUn-^+cHaXr`KGmJlJ{P!0AdE<{8 zf7SR{^B?S|jWizYr}Z=bSNW&B!hFUSPjtj++_a%$(a&r&! z9kRcv^oIG38;ytgj9V@I6id&)8gDXr_Zh#{xU@_aUpMo=+W70{zE+(0!hFSlntQvs z|K9jR#@{tQ!sKl>ewMj+BQC`^*?2GGPgwik)A%#S_c#8$@k5QTGp@b8lJ}p+oqaX< z2IEJWdzbM^#y1&1!T5W|Pc{CL@pFu8u&=AZ_|C@X8}Ds=k@0@U+l{|r< zeAD>->Ik_yjlX65PUHKk!{^ee3kpBQ_-f+|jK65S)A;Mg*BF1t_-5lD87~>><@e+z zDEU*3f64e_ihVk>vMf-2YF;{e+DBBN_K=GhADRlJb{l!nbDlVHtjC zMxM^M=3jJW?d9!}@vqHhN&nTE^!zsCe__VGG{f)7_}62Rl&|xglYCOfy%+5*>CRX+ z#iwQX%nX;-VKTfll#+a9h98^ZOEdfi0w=@keCi~ZLQ|6eKI32Wgh}^TGya`{H)q$( z)`*-M$a1xVt*!UgWVKdWvNomd^UDC*% z`DrcG&&1AJh%fEKthXgi+{LEiGRdVULcEFMf5 zCfkM*K2tXFSj_dgin8m9SqpOhKJuEZz6#ArtAw?jno%INb{4L}d#iJ*+C-{dE|QiM zu?p7gSEGFqu<96P(U+6bUugEL(kiY6Gg?T3++@m6@|FI`oMItu1Q1JjZjsgbOgt6N zwi?o8@z2|YGr%Msw`<*Ex_1~o%HMKJ>voG%bLGp|{-Tz-EL&Un(I&txzdKL*Ra@W2 z(Y6ZW7eUSQs9?`-R4{orD%iXm9c zI^~u{e^+L;&GQ?=>b3U}oixiau>KB4^jxxCBUSpXvh>qL=_jQe%5SU>5L60WXz3NW zAHEtbH6a@#LsmzI97Z<$uOX@HlEz(w?A-NG&R~Iv(lzmWZeoMMSM7CQg0BQD420i)u9@R8IU`svQw? zRTMF5De>E>d_+7c&(%`o656l35ew8)muNw;tFJ1@eWKMC9rX{2esXrUWH{UPP?p^%+X*Z&IU!K{?q1$vP2MC0+3)Sy3G6g^{}sY! zgjn{2E8VX&b?RppYTM>7Qdd@6QyDq(qrJChbyl|Pk;jlL_ZI21s8S-gXD4ty`O~%8 zr^`WH5LAX2O{J)ad{_?J{Bz$usy3l>UO)#`HHMm~ zCBmxD`CPVnC)A$pj#V=Tv8pyL!YpD!BHJb&=sGmqlI*u!c#LROu?50K)^=mpZsMD| zc5WmAcy?Y~n?NUaUo1T)&ynvykWx27{_yA$r*QWr=q6T>cvwmS1K+;MK!>J?8^Ln~gn^iNB{;5>n2~KJI=AW@O^_5?n2RTb^3>akr&^h#$`Ac|0vTTQyz&Dz!K=c2P^B>-m&H zhl$0rqoUR^x3V#}k13M#fV%VRQW#P^bef?n_z7hj@= zD#pLo_J_)j_1iD}w4J4G6%JK%+OieYEp4vtE2F! z6Ku&Sw{L|_uu+q;N(lK4p2<>0$E$5GP(nDlwvhE=6=v-%QNMA2y>)L8w;B$+41Fq( z@<6iaTO1^MDyT=9?sPX|vy95?G{c~F)@`!AMeQlrZLR3|wYO_fHU6ExE5AlV zQHL7!XQ3YnB4h6Ly~Xv0c_4ZuxI-7T&qHWr`(CVTU_zeD^R|Rlb-Z0Q=)H<%pLFZH zd}mTJd1d7otS+psc=+9eE4r<&c-E=C`yBd*JWh@`g(|L;JfJj%G9fur;zu?P^4U2U zlgPnwY}#8+!P-{((8a`}eC%BZU2FNvrp`x2&bs$qKA0+vL&iR%Bv-9$K*hb`X|@}( zXWe)0p)JNd4(JQS8%e0@c%PGP*U}$$^;i40^mxZ?;Hr+_5f|G5w~j-JiR+YJU23RA)yl?h{E+RKC@FFF)R5x( zT!A64wzY+@PrGXTUzct#DLW>%?Or11)zf$78d}gp>>7<4kT1lmmrx^dvXZ4OTs8jFs*b<)y=E!D z-Rn5sf)$?MQ>RvRyjUUg5FaPIh(eQ+67?CrL@UjVSjDo(G0lc$vgllA-4sKrE4@stir#SICD z%_56^*h#7E_%OC@7AMBV=^oL)>wj(Y`A9iG$8o8gVt~^B;`u11w>GpC*mb~tI}xF^ znH!PDdUMMxl;neUc?okfCGwzotOd=jbEUjrV#?+-n%me{kc&1y*vz36<1Oa-xkW9g zo(H{p6x7q(2YhMJNGr(tOK%!(%<#(}jNbAhc zXc|>9edJCxHm)c5E2a;=Ky8;x--X5W!KZ2@!_~=OvG_Nc`zyE?3$JxbUBBk9nET!K zfvw)YnEZ0qm2|Blo?`ivvVyKV_$#KbeYd&K--i1a6_{&V`q;TY>w(#_Mdk0VpqFar zifZ|gZaO#4{HY$?75o*^H>D}&ru@arRlT??_^(>#N>p;c!`~+J7k#$}f5&gFhy67E zJ5BGkli%(N{uAka4~KnC-&OVIuHY{tSLx_ap4OOu)uX$%;lDqQr{RCGowKTXbyx78 zNXI4kTW|hUzbSu3^n|64y@0Lxx>VmO{|PJ2agBO1JRc$m06f_aGc>_LuUYn`}geX z&*%JS!|OoFz1(mfu8y}vF{a-KAPzwz&Zl6M2B zaMywg*8)m@9jI{C;3ROo;em#|4L@P-L;lu-%HQ+Ge*!Ap4-9WI>@ZviD*if9@qHPT zoMY^Msog)o?(b&!n;u^76NYzzlJi|qa;^a-=Muv~U|;xt;BjDYa2WUj{Yy2t5kxh` z>C@5F^3TCXz#jwUPwV~4$1)H-EO%b3cpY5vNY73<3LFd`0g}|b3|X)?S^B}wUfxDf z@}#e!@|IplZ~RFQPvK>5LMZ(^^sP!y1eFe*&&sn_Is{aD4*(^1S5Wd^A<;_DgWzQF zN5;Pcsy?m;D?#b!(d6=rK=j8-n?Q8BN~eS9hn1cHDqZ71sy2TFD7m{Ce%#%sZ#}4d zJ`XCNKL?e*?}3u@kD$`s0V;iGf#|c9js?+ED?P|i`gv2}A9S;N098LvgYqXsZ7Of+ z>q(BRZX5xg4-Oy;vp`e~O3wr-ic;-&83+zC-W?nQ-^4?%^t=u#oohjr<0??)_#;sA zZvs()D7^|K%XxGJT|8AFf2HIthu&N%dFOqZ%O3`ghHD;~D^DNc%5x6bhktb-I&n^~ zjwwv1SI3m3)2pLv=~Iq7a-3crkF3+H(-baw$k9amlz^yorS$4}Cpo=3ijFA!xvAv{ z;a`suLlN=yxC>Vqb{e)D))|%?mKXvqoYt-T@K-`&b)6ti!E_p*CQbx(&J~?gbAQU* zXPA3<&o&wFB#f>W<6)d}v4wxv!Y?y^Sa0wD8uK5<9Xcmb={dyQZ#MTZ?vUQ7+x`q8V}=$Ux_2{X-nTr#;Z-fo(s9(X718s75|a(O~(J-_-5k| z7+0f{f9X@}>S_FODpOOW@fs9?sDmZhW!1PcVMF@k--sjh}2>ouw}I z3yN=q@ma>tG`_%iI7d_ci~NUkG*!)gt*#|cdK`Um-)!^wf8buiS!XGy_?iq?zmfEx z)r0v-#=pi$N&inml6+ytJ*x+ESH}Ia46n=Z-(>h98U9KpeoYnfFS_2(@P3)_^kFIg z$7K9>&yLA)CJ-^T} z8wCKTj1Z|#6jecqbv=U0iVKxKUDCy)k<`m6G<$6l zbPpm$iMDw&LRwQgG%4+v+Lro7xX$(AAV~Fuqa#~dniFSVrgEQB1ac`%=ny4UF(_#C zb7K9Utrdc1Zd2F9tw#n`mCsN-N$SOreW(55+KO9@=2xx0{DV?KuC`!v2VOnl$efP+ zG_@u-olr|ny9ovFA*e{84p8f+82s%r6hLf7z;2*IQ3wYzy7>n!i2EP<->t8jGD1*V zh&2m>%7fvywHT_V)Hb$oq@ZH+8FATE%6)!);@xj0*ZuGb_3nxD36(5&(-P`_M``sg zRyHEJUR-pchQK+&qv)uQ%L@*txcaJ800)->H5=N=Fz}zM>n^pA5h02QP%&!>YKS4mJRiQ8Mxznk>vT4ka7Q7@7gE`~cA zLPwXpX>ZAm#CIjwa~S)#7$9p{G?hPHC)=O=PUDa7r_X(9e)QC-vi##MzCW}s81-TL z^Rv(TGZXR2=~>O6Msu}ZfHL`(lC_nNfIO>;g7x%N*l5NzxwdF)E2`Si*ggiqFEWsI3F~A$t7BoO02fUn%^McxCAmVP!Ht_d)BCQ%~wx%|Ud2nP5uCOD?oo(8fyLy9r(x8|uJv z?cCI)qv)|TDIUd)dCkJ^+~FV$=ecV_5aFxQIr-zDf&)ujGPdtcNTq}Yf@Y0hg9s`i z8`VDI_0zEa5%g)U!j*FoYOXGozv`?v2rh-JzPLjYK21D?zAghDCqyd`xyna(V!?pyg%%^;4y*-pqrGO=7XmC8}f zQ4hkx;*iiWMb0koxa=XXQFZD@q{tBt*p!c`f*+LFa3?OZaK{(vvQN8Ta$;OR(qDMf zOssPVVB3(GroxFxyiA;j1AS!U{O7I;Qz}BL;)HcE7j3kD9JPn^IVZej)EewuOie=h zmD{LIxMjGg*y8q?dSAHZyo9b-vhXn7P4LicU82x{(rFglGaB_rk=;4@k2>OIo4-&P z7iudyYP0L`q`p908_9DoDlmd=l9EfPiMnk&Hj^}W@TX6gJ=Ebn6}_7D>~%aG4&2d$ z9WQLEs9Z-FS64cMj@PK}!hl42rMJ*`#RL)+ul$qnjgwrXjYUW8O#;=|x~7(nCy}#4 zzu+%fGYXgFi2!Yb6(Fu_%YIZA$)K*uZ11p|Wc|4I=ky2DeNIyUB!0_S)Z0pEIPjMA z;>9W=)?G^3Ii$UJe4IG(HEP)$npV8ssYoJU?i7W6L*t7=gv!spi0RH`U6n$XC3aaP zY;cME)CAI*Ob(?S#o?Z@M64k;mpk49)jBmY=ry^1-ph2+`12W99}gbTpsP%ud-C_n zzsj!A=+gT8pgQ$GDS+3vQ2_p(S*!rOT}5|}imU%jo72F6akU?_>1a6~z~#^C$ryyW zN)Ly(+j?DKQ{1WGgrTTx+NR2vv#tj6jdYR*#!ppuykIRRR&{o| z-A>cmMbJJWS2!fpB~4_byNi~07sp~OCq{bLEsx4T{Bj=L2cSn!DEv`FC6=f|D|_su z6@P5&!%YkP*h$@fhqc(6LBDm9edmFn!VHuaY%?dO6Rr04b;*K zTBhF|&Y9Od!;Ykh$0O0bYW!FBgo}eS91;$cMsV=CpaY#6L-1UNpN-grNkeScoX!sB(3ES>^cFujIc5+Siq*Iyg zo;?!-we@IbwdPtI>e=R~Uzm5DldCzsqIPPH^ZFU^q%D$?G z;Y{`pA2V#^@MDMZYr?jjhhv|%koChnIOPphT8q8>Req z)ZwkU+Amj}RE7DS0bZzgrQn-n?X{(O9ujKW>LZQ1TV#Z3 zS8-oHx$4VjpnuS7S4`M?VLm$4-x}vOH8_%UOAQ!wt)C@J#7S>1vdH66y>=yW!?1f6 z=J}yfMwN>=hc-ETtdBYpk!uMz8k%I>*O!r%;dGV6xvqq%9cz`Yu3H-#$UTkL>F?#V z#(;v~+yW2i-|4!6F0Pn;a;r%Y+8Ps`iUbpsu$j}MfLBl zpl4@xO#5@QlE2%#yg#)AcLje5eLU6Cdh@6D;I82Bgstt$YVG~nx4m4okCgw6-s4al zpXP7DJKn$Ai@SpSBKA~O=c_h(|4N&?g8xLirJvZ-?1!oyrTi7qXOw>8I`gkMw&!2A zG;TNjPPMb``M+24O>a}}ZhQVW;D3(kZK@rn{1++rFH&|lnm(r5Wy*i1++F?Sf1T-B zs-33%C+xyXcc+|ld3340ru=2nA-S@lvda8lX5J&azt;Yi)4nf3Eo2dhZdHB(cp>~e z5Su8a)4;`GB{&Bx1J4KhgXe;O;`x~mZU8R;Ujm1KkAO45d%?lTy~Fs;;2^l{IG%(1 zQp4lGMewm8`kVRT;8<`VDES9~lD`{R2L6rbTH(74SA)~wtH7^--v&=XKkXY}1AGa1 zHn3cdth1g-|_!3RLq z+Z~|l=N6FHTj_P+TyO=*m2Ux0hff0~rvkhj91Y4}f5ZJj`G2doFW=`tmCs|~2=4!z z-M`iD|D)aiI;e8E095`P!8&j{IGk{&fvWG3AbnfuKHyMzKTzfPDGP|gH$cTFdzQm+ zm;RN?>u#`=f8PR!fLDNOPfJ0`T?|UD>|9bM&d%jP@JzVmR)fmt(dItV?jHs!-9131 z`vcxnYEO@YiuXZKayvn#_a;#Ct~4xwN|*GChk#ST!T6JXOr>iQsPNJ=R=UbSrRz{o za`pn1t{&$8$*w;B$3VsZ0I2Z)1SAgM;x`4Gsb)fi8ZKDDq{X ziyw6HgL4Vr1C;wGJ$?MofU1Xw!2#U=F}Mu=15o~NGQ0-d2lvZCm0K;S=Whb2b~yx8 zyObSIwd37E$;p9|vx&ui`Fj=A{a=Bz!TZ7a;15BS!_DBO;1%EkQ1(9Me>ON9oC?Zc z6{!4<0nty*4+E9YgF!w2dx4VE9aQ-Dnf_2e_ghf?!i%8XH7z1J_kxEbM|MKx|7K9> z{u)S;<*x+wd@lwSPIf}u!81VlJI-)CxHtY~?@Rs;1yx?M7p8vU4aR3GxBJ1_;P*h4 z+YN?Sfr`HgRQOtu9mJ(m%zXl=^p=5#5s&nqo8fzdUj=)BhjRbpoxMHHH$lmN8C3cI z5b+AA>iskd z*Z4}~4;#PU_>;zO5hp*Yd|l3-D)F7h!=UR&=KpNtKQ=zc_|J{E7++)jKa4+X{1?Vw zHvWY1H;g}P{B7gwjK6REb>p9k^ViA4tg9!DTIF*Q53{a4j4w34zwv_c!;CLBuKrW` zUyn>(N1FQ>b60;W`3=Uajn6TDit!1?ryHMWe3m%!!+e3WuZq0QmLF$d6@H-kzudy_ zY5BX_`0M8WE#uD_*Zvx%Z@KaBixXe?e!s`uzh~|bntPZZc+A|dF!yJSzhL|&<1ZRt zZ{frI!5__ii@9q*kkS+E!EQ0$Ez}pCl+qXG556dl|I^JqZ~ScIdhfdYsAJ$7V?4|s zl$-yP%zw4XQ2`MMbp}_0vO+^X`|^y?vsv z-1cS@p9HqZP``f7vvwE-5Vo>VsM{Pd3H)AUk3^vn-h8#2jgDQ&Vb}4)#dBpplXF z&=4s$OXb@dviS;Gi7ko-;Uh!tWMhXIPOwlryeLvf7` zi5?x&Fglb-WHJ>as)^l1YG!@|kgsd^J1XeFtoY1hx&fwd(gxEvCTFNxqPrD}#S@=> z6=%Y~a+`FfbOMcwBfg`>S}`v6E0v8biLbIz8$rql#9sRHIk}mCU)D`$H{MH|z z3+~#{eM&#GxFktw_5dT-&n~8sto}06GUKd0BF!Tie@Ll(PUO7NQ^NlE^iT zr7g)Rk=xr>RARo%P2LETXH;`guAT#zcMbX15+Cz&ybTdHw1pY#(Kf|_^z zs=1$Q?o&ZNVJB9DJ#n98?qke-Ajr4h#6v(HmHhtZuK8EV*F(!E^286xE}zW#KZA<@ zcc9$YfqcSGd=})9%Rg!EKQniIXHX{-e*p66=KtB;uQ&Ir!2NN*45XiM_BkYpTYJRY}=gnQyGfeqS4D+*4`RlO()cnii5M6Kc zC$8^MUGMQH{;cs&jBCHYE`6`b{dMELjc+in?`OHcY5YLr?-=iI{5|8E|Cav`jjMjd zL;E;doB|B}p}ZySFgz!Y`#8erTE(A<64e}ZikD_MWtwvTR)(LD;s2K5O&Om3UR|7V zAD`jNGyL2PXJDj{Aq|pw`JSWjy5=HbW~&3@a>ZvTE`*dCq5Due`mTN z^Z}6*ok8?F@lD~=;JSy%+4U0<^Bsoh)?c%6hBRF9W4JIFj7E`R9B3E@bYVOfhJ0a| Q7)F(4VQiZi<>hk!4JQj$O8@`> literal 0 HcmV?d00001 diff --git a/lua/linit.c b/lua/linit.c new file mode 100644 index 0000000..c1a3830 --- /dev/null +++ b/lua/linit.c @@ -0,0 +1,67 @@ +/* +** $Id: linit.c,v 1.32.1.1 2013/04/12 18:48:47 roberto Exp $ +** Initialization of libraries for lua.c and other clients +** See Copyright Notice in lua.h +*/ + + +/* +** If you embed Lua in your program and need to open the standard +** libraries, call luaL_openlibs in your program. If you need a +** different set of libraries, copy this file to your project and edit +** it to suit your needs. +*/ + + +#define linit_c +#define LUA_LIB + +#include "lua.h" + +#include "lualib.h" +#include "lauxlib.h" + + +/* +** these libs are loaded by lua.c and are readily available to any Lua +** program +*/ +static const luaL_Reg loadedlibs[] = { + {"_G", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_COLIBNAME, luaopen_coroutine}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_BITLIBNAME, luaopen_bit32}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_DBLIBNAME, luaopen_debug}, + {NULL, NULL} +}; + + +/* +** these libs are preloaded and must be required before used +*/ +static const luaL_Reg preloadedlibs[] = { + {NULL, NULL} +}; + + +LUALIB_API void luaL_openlibs (lua_State *L) { + const luaL_Reg *lib; + /* call open functions from 'loadedlibs' and set results to global table */ + for (lib = loadedlibs; lib->func; lib++) { + luaL_requiref(L, lib->name, lib->func, 1); + lua_pop(L, 1); /* remove lib */ + } + /* add open functions from 'preloadedlibs' into 'package.preload' table */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); + for (lib = preloadedlibs; lib->func; lib++) { + lua_pushcfunction(L, lib->func); + lua_setfield(L, -2, lib->name); + } + lua_pop(L, 1); /* remove _PRELOAD table */ +} + diff --git a/lua/liolib.c b/lua/liolib.c new file mode 100644 index 0000000..2a4ec4a --- /dev/null +++ b/lua/liolib.c @@ -0,0 +1,666 @@ +/* +** $Id: liolib.c,v 2.112.1.1 2013/04/12 18:48:47 roberto Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +/* +** This definition must come before the inclusion of 'stdio.h'; it +** should not affect non-POSIX systems +*/ +#if !defined(_FILE_OFFSET_BITS) +#define _LARGEFILE_SOURCE 1 +#define _FILE_OFFSET_BITS 64 +#endif + + +#include +#include +#include +#include + +#define liolib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#if !defined(lua_checkmode) + +/* +** Check whether 'mode' matches '[rwa]%+?b?'. +** Change this macro to accept other modes for 'fopen' besides +** the standard ones. +*/ +#define lua_checkmode(mode) \ + (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \ + (*mode != '+' || ++mode) && /* skip if char is '+' */ \ + (*mode != 'b' || ++mode) && /* skip if char is 'b' */ \ + (*mode == '\0')) + +#endif + +/* +** {====================================================== +** lua_popen spawns a new process connected to the current +** one through the file streams. +** ======================================================= +*/ + +#if !defined(lua_popen) /* { */ + +#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)) + +#elif defined(LUA_WIN) /* }{ */ + +#define lua_popen(L,c,m) ((void)L, _popen(c,m)) +#define lua_pclose(L,file) ((void)L, _pclose(file)) + + +#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), -1) + + +#endif /* } */ + +#endif /* } */ + +/* }====================================================== */ + + +/* +** {====================================================== +** lua_fseek: configuration for longer offsets +** ======================================================= +*/ + +#if !defined(lua_fseek) && !defined(LUA_ANSI) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#define l_fseek(f,o,w) fseeko(f,o,w) +#define l_ftell(f) ftello(f) +#define l_seeknum off_t + +#elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ + && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */ +/* Windows (but not DDK) and Visual C++ 2005 or higher */ + +#define l_fseek(f,o,w) _fseeki64(f,o,w) +#define l_ftell(f) _ftelli64(f) +#define l_seeknum __int64 + +#endif /* } */ + +#endif /* } */ + + +#if !defined(l_fseek) /* default definitions */ +#define l_fseek(f,o,w) fseek(f,o,w) +#define l_ftell(f) ftell(f) +#define l_seeknum long +#endif + +/* }====================================================== */ + + +#define IO_PREFIX "_IO_" +#define IO_INPUT (IO_PREFIX "input") +#define IO_OUTPUT (IO_PREFIX "output") + + +typedef luaL_Stream LStream; + + +#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + +#define isclosed(p) ((p)->closef == NULL) + + +static int io_type (lua_State *L) { + LStream *p; + luaL_checkany(L, 1); + p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); + if (p == NULL) + lua_pushnil(L); /* not a file */ + else if (isclosed(p)) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static int f_tostring (lua_State *L) { + LStream *p = tolstream(L); + if (isclosed(p)) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", p->f); + return 1; +} + + +static FILE *tofile (lua_State *L) { + LStream *p = tolstream(L); + if (isclosed(p)) + luaL_error(L, "attempt to use a closed file"); + lua_assert(p->f); + return p->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 LStream *newprefile (lua_State *L) { + LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); + p->closef = NULL; /* mark file handle as 'closed' */ + luaL_setmetatable(L, LUA_FILEHANDLE); + return p; +} + + +static int aux_close (lua_State *L) { + LStream *p = tolstream(L); + lua_CFunction cf = p->closef; + p->closef = NULL; /* mark stream as closed */ + return (*cf)(L); /* close it */ +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) /* no argument? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ + tofile(L); /* make sure argument is an open stream */ + return aux_close(L); +} + + +static int f_gc (lua_State *L) { + LStream *p = tolstream(L); + if (!isclosed(p) && p->f != NULL) + aux_close(L); /* ignore closed and incompletely open files */ + return 0; +} + + +/* +** function to close regular files +*/ +static int io_fclose (lua_State *L) { + LStream *p = tolstream(L); + int res = fclose(p->f); + return luaL_fileresult(L, (res == 0), NULL); +} + + +static LStream *newfile (lua_State *L) { + LStream *p = newprefile(L); + p->f = NULL; + p->closef = &io_fclose; + return p; +} + + +static void opencheck (lua_State *L, const char *fname, const char *mode) { + LStream *p = newfile(L); + p->f = fopen(fname, mode); + if (p->f == NULL) + luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno)); +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + LStream *p = newfile(L); + const char *md = mode; /* to traverse/check mode */ + luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode"); + p->f = fopen(filename, mode); + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; +} + + +/* +** function to close 'popen' files +*/ +static int io_pclose (lua_State *L) { + LStream *p = tolstream(L); + return luaL_execresult(L, lua_pclose(L, p->f)); +} + + +static int io_popen (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + LStream *p = newprefile(L); + p->f = lua_popen(L, filename, mode); + p->closef = &io_pclose; + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; +} + + +static int io_tmpfile (lua_State *L) { + LStream *p = newfile(L); + p->f = tmpfile(); + return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, const char *findex) { + LStream *p; + lua_getfield(L, LUA_REGISTRYINDEX, findex); + p = (LStream *)lua_touserdata(L, -1); + if (isclosed(p)) + luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX)); + return p->f; +} + + +static int g_iofile (lua_State *L, const char *f, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + if (filename) + opencheck(L, filename, mode); + else { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_setfield(L, LUA_REGISTRYINDEX, f); + } + /* return current value */ + lua_getfield(L, LUA_REGISTRYINDEX, 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 toclose) { + int i; + int n = lua_gettop(L) - 1; /* number of arguments to read */ + /* ensure that arguments will fit here and into 'io_readline' stack */ + luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options"); + lua_pushvalue(L, 1); /* file handle */ + lua_pushinteger(L, n); /* number of arguments to read */ + lua_pushboolean(L, toclose); /* close/not close file when finished */ + for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1); /* copy arguments */ + lua_pushcclosure(L, io_readline, 3 + n); +} + + +static int f_lines (lua_State *L) { + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + int toclose; + if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ + if (lua_isnil(L, 1)) { /* no file name? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ + lua_replace(L, 1); /* put it at index 1 */ + tofile(L); /* check that it's a valid file handle */ + toclose = 0; /* do not close it after iteration */ + } + else { /* open a new file */ + const char *filename = luaL_checkstring(L, 1); + opencheck(L, filename, "r"); + lua_replace(L, 1); /* put file at index 1 */ + toclose = 1; /* close it after iteration */ + } + aux_lines(L, toclose); + 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 { + lua_pushnil(L); /* "result" to be removed */ + 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, int chop) { + 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_rawlen(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 - chop); /* chop 'eol' if needed */ + luaL_pushresult(&b); /* close buffer */ + return 1; /* read at least an `eol' */ + } + } +} + + +#define MAX_SIZE_T (~(size_t)0) + +static void read_all (lua_State *L, FILE *f) { + size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + char *p = luaL_prepbuffsize(&b, rlen); + size_t nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, nr); + if (nr < rlen) break; /* eof? */ + else if (rlen <= (MAX_SIZE_T / 4)) /* avoid buffers too large */ + rlen *= 2; /* double buffer size at each iteration */ + } + luaL_pushresult(&b); /* close buffer */ +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t nr; /* number of chars actually read */ + char *p; + luaL_Buffer b; + luaL_buffinit(L, &b); + p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ + nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ + luaL_addsize(&b, nr); + luaL_pushresult(&b); /* close buffer */ + return (nr > 0); /* true iff read something */ +} + + +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, 1); + 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, 1); + break; + case 'L': /* line with end-of-line */ + success = read_line(L, f, 0); + break; + case 'a': /* file */ + read_all(L, f); /* read entire file */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (ferror(f)) + return luaL_fileresult(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) { + LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); + int i; + int n = (int)lua_tointeger(L, lua_upvalueindex(2)); + if (isclosed(p)) /* file is already closed? */ + return luaL_error(L, "file is already closed"); + lua_settop(L , 1); + for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ + lua_pushvalue(L, lua_upvalueindex(3 + i)); + n = g_read(L, p->f, 2); /* 'n' is number of results */ + lua_assert(n > 0); /* should return at least a nil */ + if (!lua_isnil(L, -n)) /* read at least one value? */ + return n; /* return them */ + else { /* first result is nil: EOF or error */ + if (n > 1) { /* is there error information? */ + /* 2nd result is error message */ + return luaL_error(L, "%s", lua_tostring(L, -n + 1)); + } + if (lua_toboolean(L, lua_upvalueindex(3))) { /* 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) - arg; + 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); + } + } + if (status) return 1; /* file handle already on stack top */ + else return luaL_fileresult(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) { + FILE *f = tofile(L); + lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ + return g_write(L, f, 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); + lua_Number p3 = luaL_optnumber(L, 3, 0); + l_seeknum offset = (l_seeknum)p3; + luaL_argcheck(L, (lua_Number)offset == p3, 3, + "not an integer in proper range"); + op = l_fseek(f, offset, mode[op]); + if (op) + return luaL_fileresult(L, 0, NULL); /* error */ + else { + lua_pushnumber(L, (lua_Number)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 luaL_fileresult(L, res == 0, NULL); +} + + + +static int io_flush (lua_State *L) { + return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); +} + + +/* +** functions for 'io' library +*/ +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} +}; + + +/* +** methods for file handles +*/ +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", f_gc}, + {"__tostring", f_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_setfuncs(L, flib, 0); /* add file methods to new metatable */ + lua_pop(L, 1); /* pop new metatable */ +} + + +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + LStream *p = tolstream(L); + p->closef = &io_noclose; /* keep file opened */ + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; +} + + +static void createstdfile (lua_State *L, FILE *f, const char *k, + const char *fname) { + LStream *p = newprefile(L); + p->f = f; + p->closef = &io_noclose; + if (k != NULL) { + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ + } + lua_setfield(L, -2, fname); /* add file to module */ +} + + +LUAMOD_API int luaopen_io (lua_State *L) { + luaL_newlib(L, iolib); /* new module */ + createmeta(L); + /* create (and set) default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, NULL, "stderr"); + return 1; +} + diff --git a/lua/llex.c b/lua/llex.c new file mode 100644 index 0000000..c4b820e --- /dev/null +++ b/lua/llex.c @@ -0,0 +1,530 @@ +/* +** $Id: llex.c,v 2.63.1.2 2013/08/30 15:49:41 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define llex_c +#define LUA_CORE + +#include "lua.h" + +#include "lctype.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 */ +static const char *const luaX_tokens [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "goto", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "..", "...", "==", ">=", "<=", "~=", "::", "", + "", "", "" +}; + + +#define save_and_next(ls) (save(ls, ls->current), next(ls)) + + +static l_noret lexerror (LexState *ls, const char *msg, int token); + + +static void save (LexState *ls, int c) { + Mbuffer *b = ls->buff; + if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { + size_t newsize; + if (luaZ_sizebuffer(b) >= MAX_SIZET/2) + lexerror(ls, "lexical element too long", 0); + newsize = luaZ_sizebuffer(b) * 2; + luaZ_resizebuffer(ls->L, b, newsize); + } + b->buffer[luaZ_bufflen(b)++] = cast(char, c); +} + + +void luaX_init (lua_State *L) { + int i; + for (i=0; itsv.extra = cast_byte(i+1); /* reserved word */ + } +} + + +const char *luaX_token2str (LexState *ls, int token) { + if (token < FIRST_RESERVED) { /* single-byte symbols? */ + lua_assert(token == cast(unsigned char, token)); + return (lisprint(token)) ? luaO_pushfstring(ls->L, LUA_QL("%c"), token) : + luaO_pushfstring(ls->L, "char(%d)", token); + } + else { + const char *s = luaX_tokens[token - FIRST_RESERVED]; + if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ + return luaO_pushfstring(ls->L, LUA_QS, s); + else /* names, strings, and numerals */ + return s; + } +} + + +static const char *txtToken (LexState *ls, int token) { + switch (token) { + case TK_NAME: + case TK_STRING: + case TK_NUMBER: + save(ls, '\0'); + return luaO_pushfstring(ls->L, LUA_QS, luaZ_buffer(ls->buff)); + default: + return luaX_token2str(ls, token); + } +} + + +static l_noret lexerror (LexState *ls, const char *msg, int token) { + char buff[LUA_IDSIZE]; + luaO_chunkid(buff, getstr(ls->source), LUA_IDSIZE); + msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); + if (token) + luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); + luaD_throw(ls->L, LUA_ERRSYNTAX); +} + + +l_noret luaX_syntaxerror (LexState *ls, const char *msg) { + lexerror(ls, msg, ls->t.token); +} + + +/* +** creates a new string and anchors it in function's table so that +** it will not be collected until the end of the function's compilation +** (by that time it should be anchored in function's prototype) +*/ +TString *luaX_newstring (LexState *ls, const char *str, size_t l) { + lua_State *L = ls->L; + TValue *o; /* entry for `str' */ + TString *ts = luaS_newlstr(L, str, l); /* create new string */ + setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ + o = luaH_set(L, ls->fs->h, L->top - 1); + if (ttisnil(o)) { /* not in use yet? (see 'addK') */ + /* boolean value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setbvalue(o, 1); /* t[string] = true */ + luaC_checkGC(L); + } + else { /* string already present */ + ts = rawtsvalue(keyfromval(o)); /* re-use value previously stored */ + } + L->top--; /* remove string from stack */ + return ts; +} + + +/* +** increment line number and skips newline sequence (any of +** \n, \r, \n\r, or \r\n) +*/ +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, + int firstchar) { + ls->decpoint = '.'; + ls->L = L; + ls->current = firstchar; + ls->lookahead.token = TK_EOS; /* no look-ahead token */ + ls->z = z; + ls->fs = NULL; + ls->linenumber = 1; + ls->lastline = 1; + ls->source = source; + ls->envn = luaS_new(L, LUA_ENV); /* create env name */ + luaS_fix(ls->envn); /* never collect this name */ + luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ +} + + + +/* +** ======================================================= +** LEXICAL ANALYZER +** ======================================================= +*/ + + + +static int check_next (LexState *ls, const char *set) { + if (ls->current == '\0' || !strchr(set, ls->current)) + return 0; + save_and_next(ls); + return 1; +} + + +/* +** change all characters 'from' in buffer to 'to' +*/ +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; +} + + +#if !defined(getlocaledecpoint) +#define getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + + +#define buff2d(b,e) luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e) + +/* +** in case of format error, try to change decimal point separator to +** the one defined in the current locale and check again +*/ +static void trydecpoint (LexState *ls, SemInfo *seminfo) { + char old = ls->decpoint; + ls->decpoint = getlocaledecpoint(); + buffreplace(ls, old, ls->decpoint); /* try new decimal separator */ + if (!buff2d(ls->buff, &seminfo->r)) { + /* format error with correct decimal point: no more options */ + buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ + lexerror(ls, "malformed number", TK_NUMBER); + } +} + + +/* LUA_NUMBER */ +/* +** this function is quite liberal in what it accepts, as 'luaO_str2d' +** will reject ill-formed numerals. +*/ +static void read_numeral (LexState *ls, SemInfo *seminfo) { + const char *expo = "Ee"; + int first = ls->current; + lua_assert(lisdigit(ls->current)); + save_and_next(ls); + if (first == '0' && check_next(ls, "Xx")) /* hexadecimal? */ + expo = "Pp"; + for (;;) { + if (check_next(ls, expo)) /* exponent part? */ + check_next(ls, "+-"); /* optional exponent sign */ + if (lisxdigit(ls->current) || ls->current == '.') + save_and_next(ls); + else break; + } + save(ls, '\0'); + buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ + if (!buff2d(ls->buff, &seminfo->r)) /* format error? */ + trydecpoint(ls, seminfo); /* try to update decimal point separator */ +} + + +/* +** skip a sequence '[=*[' or ']=*]' and return its number of '='s or +** -1 if sequence is malformed +*/ +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) { + save_and_next(ls); /* skip 2nd `[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) { + switch (ls->current) { + case EOZ: + lexerror(ls, (seminfo) ? "unfinished long string" : + "unfinished long comment", TK_EOS); + break; /* to avoid warnings */ + case ']': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `]' */ + 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 escerror (LexState *ls, int *c, int n, const char *msg) { + int i; + luaZ_resetbuffer(ls->buff); /* prepare error message */ + save(ls, '\\'); + for (i = 0; i < n && c[i] != EOZ; i++) + save(ls, c[i]); + lexerror(ls, msg, TK_STRING); +} + + +static int readhexaesc (LexState *ls) { + int c[3], i; /* keep input for error message */ + int r = 0; /* result accumulator */ + c[0] = 'x'; /* for error message */ + for (i = 1; i < 3; i++) { /* read two hexadecimal digits */ + c[i] = next(ls); + if (!lisxdigit(c[i])) + escerror(ls, c, i + 1, "hexadecimal digit expected"); + r = (r << 4) + luaO_hexavalue(c[i]); + } + return r; +} + + +static int readdecesc (LexState *ls) { + int c[3], i; + int r = 0; /* result accumulator */ + for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ + c[i] = ls->current; + r = 10*r + c[i] - '0'; + next(ls); + } + if (r > UCHAR_MAX) + escerror(ls, c, i, "decimal escape too large"); + return r; +} + + +static void read_string (LexState *ls, int del, SemInfo *seminfo) { + save_and_next(ls); /* keep delimiter (for error messages) */ + while (ls->current != del) { + switch (ls->current) { + case EOZ: + lexerror(ls, "unfinished string", TK_EOS); + break; /* to avoid warnings */ + case '\n': + case '\r': + lexerror(ls, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': { /* escape sequences */ + int c; /* final character to be saved */ + next(ls); /* do not save the `\' */ + switch (ls->current) { + case 'a': c = '\a'; goto read_save; + case 'b': c = '\b'; goto read_save; + case 'f': c = '\f'; goto read_save; + case 'n': c = '\n'; goto read_save; + case 'r': c = '\r'; goto read_save; + case 't': c = '\t'; goto read_save; + case 'v': c = '\v'; goto read_save; + case 'x': c = readhexaesc(ls); goto read_save; + case '\n': case '\r': + inclinenumber(ls); c = '\n'; goto only_save; + case '\\': case '\"': case '\'': + c = ls->current; goto read_save; + case EOZ: goto no_save; /* will raise an error next loop */ + case 'z': { /* zap following span of spaces */ + next(ls); /* skip the 'z' */ + while (lisspace(ls->current)) { + if (currIsNewline(ls)) inclinenumber(ls); + else next(ls); + } + goto no_save; + } + default: { + if (!lisdigit(ls->current)) + escerror(ls, &ls->current, 1, "invalid escape sequence"); + /* digital escape \ddd */ + c = readdecesc(ls); + goto only_save; + } + } + read_save: next(ls); /* read next character */ + only_save: save(ls, c); /* save 'c' */ + no_save: break; + } + 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': { /* line breaks */ + inclinenumber(ls); + break; + } + case ' ': case '\f': case '\t': case '\v': { /* spaces */ + next(ls); + break; + } + case '-': { /* '-' or '--' (comment) */ + next(ls); + if (ls->current != '-') return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') { /* long comment? */ + int sep = skip_sep(ls); + luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ + if (sep >= 0) { + read_long_string(ls, NULL, sep); /* skip long comment */ + luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ + break; + } + } + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); /* skip until end of line (or end of file) */ + break; + } + case '[': { /* long string or simply '[' */ + int sep = skip_sep(ls); + if (sep >= 0) { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } + else if (sep == -1) return '['; + else 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 ':': { + next(ls); + if (ls->current != ':') return ':'; + else { next(ls); return TK_DBCOLON; } + } + case '"': case '\'': { /* short literal strings */ + read_string(ls, ls->current, seminfo); + return TK_STRING; + } + case '.': { /* '.', '..', '...', or number */ + save_and_next(ls); + if (check_next(ls, ".")) { + if (check_next(ls, ".")) + return TK_DOTS; /* '...' */ + else return TK_CONCAT; /* '..' */ + } + else if (!lisdigit(ls->current)) return '.'; + /* else go through */ + } + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + read_numeral(ls, seminfo); + return TK_NUMBER; + } + case EOZ: { + return TK_EOS; + } + default: { + if (lislalpha(ls->current)) { /* identifier or reserved word? */ + TString *ts; + do { + save_and_next(ls); + } while (lislalnum(ls->current)); + ts = luaX_newstring(ls, luaZ_buffer(ls->buff), + luaZ_bufflen(ls->buff)); + seminfo->ts = ts; + if (isreserved(ts)) /* reserved word? */ + return ts->tsv.extra - 1 + FIRST_RESERVED; + else { + return TK_NAME; + } + } + else { /* single-char tokens (+ - / ...) */ + int c = ls->current; + next(ls); + return c; + } + } + } + } +} + + +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 */ +} + + +int luaX_lookahead (LexState *ls) { + lua_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); + return ls->lookahead.token; +} + diff --git a/lua/llex.h b/lua/llex.h new file mode 100644 index 0000000..a4acdd3 --- /dev/null +++ b/lua/llex.h @@ -0,0 +1,78 @@ +/* +** $Id: llex.h,v 1.72.1.1 2013/04/12 18:48:47 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 + + + +/* +* 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_GOTO, 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_DBCOLON, TK_EOS, + TK_NUMBER, TK_NAME, TK_STRING +}; + +/* number of reserved words */ +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) + + +typedef union { + lua_Number r; + TString *ts; +} SemInfo; /* semantics information */ + + +typedef struct Token { + int token; + SemInfo seminfo; +} Token; + + +/* state of the lexer plus state of the parser when shared by all + functions */ +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; /* current function (parser) */ + struct lua_State *L; + ZIO *z; /* input stream */ + Mbuffer *buff; /* buffer for tokens */ + struct Dyndata *dyd; /* dynamic structures used by the parser */ + TString *source; /* current source name */ + TString *envn; /* environment variable 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, int firstchar); +LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); +LUAI_FUNC void luaX_next (LexState *ls); +LUAI_FUNC int luaX_lookahead (LexState *ls); +LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); +LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); + + +#endif diff --git a/lua/llimits.h b/lua/llimits.h new file mode 100644 index 0000000..152dd05 --- /dev/null +++ b/lua/llimits.h @@ -0,0 +1,309 @@ +/* +** $Id: llimits.h,v 1.103.1.1 2013/04/12 18:48:47 roberto Exp $ +** Limits, basic types, and some other `installation-dependent' definitions +** See Copyright Notice in lua.h +*/ + +#ifndef llimits_h +#define llimits_h + + +#include +#include + + +#include "lua.h" + + +typedef unsigned LUA_INT32 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_LMEM ((l_mem) ((MAX_LUMEM >> 1) - 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 */ +#if !defined(LUAI_USER_ALIGNMENT_T) +#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } +#endif + +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 */ +#if defined(lua_assert) +#define check_exp(c,e) (lua_assert(c), (e)) +/* to avoid problems with conditions too long */ +#define lua_longassert(c) { if (!(c)) lua_assert(0); } +#else +#define lua_assert(c) ((void)0) +#define check_exp(c,e) (e) +#define lua_longassert(c) ((void)0) +#endif + +/* +** assertion for checking API calls +*/ +#if !defined(luai_apicheck) + +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(L,e) assert(e) +#else +#define luai_apicheck(L,e) lua_assert(e) +#endif + +#endif + +#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) + + +#if !defined(UNUSED) +#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#endif + + +#define cast(t, exp) ((t)(exp)) + +#define cast_byte(i) cast(lu_byte, (i)) +#define cast_num(i) cast(lua_Number, (i)) +#define cast_int(i) cast(int, (i)) +#define cast_uchar(i) cast(unsigned char, (i)) + + +/* +** non-return type +*/ +#if defined(__GNUC__) +#define l_noret void __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define l_noret void __declspec(noreturn) +#else +#define l_noret void +#endif + + + +/* +** maximum depth for nested C calls and syntactical nested non-terminals +** in a program. (Value must fit in an unsigned short int.) +*/ +#if !defined(LUAI_MAXCCALLS) +#define LUAI_MAXCCALLS 200 +#endif + +/* +** maximum number of upvalues in a closure (both C and Lua). (Value +** must fit in an unsigned char.) +*/ +#define MAXUPVAL UCHAR_MAX + + +/* +** 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) */ +#if !defined(MINSTRTABSIZE) +#define MINSTRTABSIZE 32 +#endif + + +/* minimum size for string buffer */ +#if !defined(LUA_MINBUFFER) +#define LUA_MINBUFFER 32 +#endif + + +#if !defined(lua_lock) +#define lua_lock(L) ((void) 0) +#define lua_unlock(L) ((void) 0) +#endif + +#if !defined(luai_threadyield) +#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} +#endif + + +/* +** these macros allow user-specific actions on threads when you defined +** LUAI_EXTRASPACE and need to do something extra when a thread is +** created/deleted/resumed/yielded. +*/ +#if !defined(luai_userstateopen) +#define luai_userstateopen(L) ((void)L) +#endif + +#if !defined(luai_userstateclose) +#define luai_userstateclose(L) ((void)L) +#endif + +#if !defined(luai_userstatethread) +#define luai_userstatethread(L,L1) ((void)L) +#endif + +#if !defined(luai_userstatefree) +#define luai_userstatefree(L,L1) ((void)L) +#endif + +#if !defined(luai_userstateresume) +#define luai_userstateresume(L,n) ((void)L) +#endif + +#if !defined(luai_userstateyield) +#define luai_userstateyield(L,n) ((void)L) +#endif + +/* +** lua_number2int is a macro to convert lua_Number to int. +** lua_number2integer is a macro to convert lua_Number to lua_Integer. +** lua_number2unsigned is a macro to convert a lua_Number to a lua_Unsigned. +** lua_unsigned2number is a macro to convert a lua_Unsigned to a lua_Number. +** luai_hashnum is a macro to hash a lua_Number value into an integer. +** The hash must be deterministic and give reasonable values for +** both small and large values (outside the range of integers). +*/ + +#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ +/* trick with Microsoft assembler for X86 */ + +#define lua_number2int(i,n) __asm {__asm fld n __asm fistp i} +#define lua_number2integer(i,n) lua_number2int(i, n) +#define lua_number2unsigned(i,n) \ + {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} + + +#elif defined(LUA_IEEE754TRICK) /* }{ */ +/* the next trick should work on any machine using IEEE754 with + a 32-bit int type */ + +union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; + +#if !defined(LUA_IEEEENDIAN) /* { */ +#define LUAI_EXTRAIEEE \ + static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; +#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) +#else +#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN +#define LUAI_EXTRAIEEE /* empty */ +#endif /* } */ + +#define lua_number2int32(i,n,t) \ + { LUAI_EXTRAIEEE \ + volatile union luai_Cast u; u.l_d = (n) + 6755399441055744.0; \ + (i) = (t)u.l_p[LUA_IEEEENDIANLOC]; } + +#define luai_hashnum(i,n) \ + { volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \ + (i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */ + +#define lua_number2int(i,n) lua_number2int32(i, n, int) +#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) + +/* the trick can be expanded to lua_Integer when it is a 32-bit value */ +#if defined(LUA_IEEELL) +#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer) +#endif + +#endif /* } */ + + +/* the following definitions always work, but may be slow */ + +#if !defined(lua_number2int) +#define lua_number2int(i,n) ((i)=(int)(n)) +#endif + +#if !defined(lua_number2integer) +#define lua_number2integer(i,n) ((i)=(lua_Integer)(n)) +#endif + +#if !defined(lua_number2unsigned) /* { */ +/* the following definition assures proper modulo behavior */ +#if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) +#include +#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) +#define lua_number2unsigned(i,n) \ + ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) +#else +#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) +#endif +#endif /* } */ + + +#if !defined(lua_unsigned2number) +/* on several machines, coercion from unsigned to double is slow, + so it may be worth to avoid */ +#define lua_unsigned2number(u) \ + (((u) <= (lua_Unsigned)INT_MAX) ? (lua_Number)(int)(u) : (lua_Number)(u)) +#endif + + + +#if defined(ltable_c) && !defined(luai_hashnum) + +#include +#include + +#define luai_hashnum(i,n) { int e; \ + n = l_mathop(frexp)(n, &e) * (lua_Number)(INT_MAX - DBL_MAX_EXP); \ + lua_number2int(i, n); i += e; } + +#endif + + + +/* +** macro to control inclusion of some hard tests on stack reallocation +*/ +#if !defined(HARDSTACKTESTS) +#define condmovestack(L) ((void)0) +#else +/* realloc stack keeping its size */ +#define condmovestack(L) luaD_reallocstack((L), (L)->stacksize) +#endif + +#if !defined(HARDMEMTESTS) +#define condchangemem(L) condmovestack(L) +#else +#define condchangemem(L) \ + ((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1))) +#endif + +#endif diff --git a/lua/lmathlib.c b/lua/lmathlib.c new file mode 100644 index 0000000..fe9fc54 --- /dev/null +++ b/lua/lmathlib.c @@ -0,0 +1,279 @@ +/* +** $Id: lmathlib.c,v 1.83.1.1 2013/04/12 18:48:47 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 ((lua_Number)(3.1415926535897932384626433832795)) +#define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0)) + + + +static int math_abs (lua_State *L) { + lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sinh (lua_State *L) { + lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cosh (lua_State *L) { + lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tanh (lua_State *L) { + lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_pushnumber(L, l_mathop(atan)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan2 (lua_State *L) { + lua_pushnumber(L, l_mathop(atan2)(luaL_checknumber(L, 1), + luaL_checknumber(L, 2))); + return 1; +} + +static int math_ceil (lua_State *L) { + lua_pushnumber(L, l_mathop(ceil)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_floor (lua_State *L) { + lua_pushnumber(L, l_mathop(floor)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_fmod (lua_State *L) { + lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), + luaL_checknumber(L, 2))); + return 1; +} + +static int math_modf (lua_State *L) { + lua_Number ip; + lua_Number fp = l_mathop(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, l_mathop(sqrt)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + lua_Number y = luaL_checknumber(L, 2); + lua_pushnumber(L, l_mathop(pow)(x, y)); + return 1; +} + +static int math_log (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + lua_Number res; + if (lua_isnoneornil(L, 2)) + res = l_mathop(log)(x); + else { + lua_Number base = luaL_checknumber(L, 2); + if (base == (lua_Number)10.0) res = l_mathop(log10)(x); + else res = l_mathop(log)(x)/l_mathop(log)(base); + } + lua_pushnumber(L, res); + return 1; +} + +#if defined(LUA_COMPAT_LOG10) +static int math_log10 (lua_State *L) { + lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); + return 1; +} +#endif + +static int math_exp (lua_State *L) { + lua_pushnumber(L, l_mathop(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, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); + lua_pushinteger(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + int ep = luaL_checkint(L, 2); + lua_pushnumber(L, l_mathop(ldexp)(x, ep)); + 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 */ + lua_Number u = luaL_checknumber(L, 1); + luaL_argcheck(L, (lua_Number)1.0 <= u, 1, "interval is empty"); + lua_pushnumber(L, l_mathop(floor)(r*u) + (lua_Number)(1.0)); /* [1, u] */ + break; + } + case 2: { /* lower and upper limits */ + lua_Number l = luaL_checknumber(L, 1); + lua_Number u = luaL_checknumber(L, 2); + luaL_argcheck(L, l <= u, 2, "interval is empty"); + lua_pushnumber(L, l_mathop(floor)(r*(u-l+1)) + l); /* [l, u] */ + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + return 1; +} + + +static int math_randomseed (lua_State *L) { + srand(luaL_checkunsigned(L, 1)); + (void)rand(); /* discard first value to avoid undesirable correlations */ + 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}, +#if defined(LUA_COMPAT_LOG10) + {"log10", math_log10}, +#endif + {"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 +*/ +LUAMOD_API int luaopen_math (lua_State *L) { + luaL_newlib(L, mathlib); + lua_pushnumber(L, PI); + lua_setfield(L, -2, "pi"); + lua_pushnumber(L, HUGE_VAL); + lua_setfield(L, -2, "huge"); + return 1; +} + diff --git a/lua/lmem.c b/lua/lmem.c new file mode 100644 index 0000000..ee343e3 --- /dev/null +++ b/lua/lmem.c @@ -0,0 +1,99 @@ +/* +** $Id: lmem.c,v 1.84.1.1 2013/04/12 18:48:47 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 "lgc.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) +** +** * frealloc(ud, NULL, x, s) creates a new block of size `s' (no +** matter '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 *what) { + void *newblock; + int newsize; + if (*size >= limit/2) { /* cannot double it? */ + if (*size >= limit) /* cannot grow even a little? */ + luaG_runerror(L, "too many %s (limit is %d)", what, limit); + 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; +} + + +l_noret luaM_toobig (lua_State *L) { + luaG_runerror(L, "memory allocation error: block too big"); +} + + + +/* +** generic allocation routine. +*/ +void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { + void *newblock; + global_State *g = G(L); + size_t realosize = (block) ? osize : 0; + lua_assert((realosize == 0) == (block == NULL)); +#if defined(HARDMEMTESTS) + if (nsize > realosize && g->gcrunning) + luaC_fullgc(L, 1); /* force a GC whenever possible */ +#endif + newblock = (*g->frealloc)(g->ud, block, osize, nsize); + if (newblock == NULL && nsize > 0) { + api_check(L, nsize > realosize, + "realloc cannot fail when shrinking a block"); + if (g->gcrunning) { + luaC_fullgc(L, 1); /* try to free some memory... */ + newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + } + if (newblock == NULL) + luaD_throw(L, LUA_ERRMEM); + } + lua_assert((nsize == 0) == (newblock == NULL)); + g->GCdebt = (g->GCdebt + nsize) - realosize; + return newblock; +} + diff --git a/lua/lmem.h b/lua/lmem.h new file mode 100644 index 0000000..bd4f4e0 --- /dev/null +++ b/lua/lmem.h @@ -0,0 +1,57 @@ +/* +** $Id: lmem.h,v 1.40.1.1 2013/04/12 18:48:47 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" + + +/* +** This macro avoids the runtime division MAX_SIZET/(e), as 'e' is +** always constant. +** The macro is somewhat complex to avoid warnings: +** +1 avoids warnings of "comparison has constant result"; +** cast to 'void' avoids warnings of "value unused". +*/ +#define luaM_reallocv(L,b,on,n,e) \ + (cast(void, \ + (cast(size_t, (n)+1) > MAX_SIZET/(e)) ? (luaM_toobig(L), 0) : 0), \ + luaM_realloc_(L, (b), (on)*(e), (n)*(e))) + +#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) luaM_reallocv(L, (b), n, 0, sizeof((b)[0])) + +#define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) +#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_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) + +#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 l_noret luaM_toobig (lua_State *L); + +/* not to be called directly */ +LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, + size_t size); +LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, + size_t size_elem, int limit, + const char *what); + +#endif + diff --git a/lua/loadlib.c b/lua/loadlib.c new file mode 100644 index 0000000..bedbea3 --- /dev/null +++ b/lua/loadlib.c @@ -0,0 +1,725 @@ +/* +** $Id: loadlib.c,v 1.111.1.1 2013/04/12 18:48:47 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 Windows, and a stub for other +** systems. +*/ + + +/* +** if needed, includes windows header before everything else +*/ +#if defined(_WIN32) +#include +#endif + + +#include +#include + + +#define loadlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** LUA_PATH and LUA_CPATH are the names of the environment +** variables that Lua check to set its paths. +*/ +#if !defined(LUA_PATH) +#define LUA_PATH "LUA_PATH" +#endif + +#if !defined(LUA_CPATH) +#define LUA_CPATH "LUA_CPATH" +#endif + +#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + +#define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX +#define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX + +/* +** LUA_PATH_SEP is the character that separates templates in a path. +** LUA_PATH_MARK is the string that marks the substitution points in a +** template. +** LUA_EXEC_DIR in a Windows path is replaced by the executable's +** directory. +** LUA_IGMARK is a mark to ignore all before it when building the +** luaopen_ function name. +*/ +#if !defined (LUA_PATH_SEP) +#define LUA_PATH_SEP ";" +#endif +#if !defined (LUA_PATH_MARK) +#define LUA_PATH_MARK "?" +#endif +#if !defined (LUA_EXEC_DIR) +#define LUA_EXEC_DIR "!" +#endif +#if !defined (LUA_IGMARK) +#define LUA_IGMARK "-" +#endif + + +/* +** LUA_CSUBSEP is the character that replaces dots in submodule names +** when searching for a C loader. +** LUA_LSUBSEP is the character that replaces dots in submodule names +** when searching for a Lua loader. +*/ +#if !defined(LUA_CSUBSEP) +#define LUA_CSUBSEP LUA_DIRSEP +#endif + +#if !defined(LUA_LSUBSEP) +#define LUA_LSUBSEP LUA_DIRSEP +#endif + + +/* prefix for open functions in C libraries */ +#define LUA_POF "luaopen_" + +/* separator for open functions in C libraries */ +#define LUA_OFSEP "_" + + +/* table (in the registry) that keeps handles for all loaded C libraries */ +#define CLIBS "_CLIBS" + +#define LIB_FAIL "open" + + +/* error codes for ll_loadfunc */ +#define ERRLIB 1 +#define ERRFUNC 2 + +#define setprogdir(L) ((void)0) + + +/* +** system-dependent functions +*/ +static void ll_unloadlib (void *lib); +static void *ll_load (lua_State *L, const char *path, int seeglb); +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); + + + +#if defined(LUA_USE_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, int seeglb) { + void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); + 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. +** ======================================================================= +*/ + +#undef setprogdir + +/* +** optional flags for LoadLibraryEx +*/ +#if !defined(LUA_LLE_FLAGS) +#define LUA_LLE_FLAGS 0 +#endif + + +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_EXEC_DIR, 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)/sizeof(char), NULL)) + lua_pushstring(L, buffer); + else + lua_pushfstring(L, "system error %d\n", error); +} + +static void ll_unloadlib (void *lib) { + FreeLibrary((HMODULE)lib); +} + + +static void *ll_load (lua_State *L, const char *path, int seeglb) { + HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); + (void)(seeglb); /* not used: symbols are 'global' by default */ + 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((HMODULE)lib, sym); + if (f == NULL) pusherror(L); + return f; +} + +/* }====================================================== */ + + +#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); /* not used */ +} + + +static void *ll_load (lua_State *L, const char *path, int seeglb) { + (void)(path); (void)(seeglb); /* not used */ + lua_pushliteral(L, DLMSG); + return NULL; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + (void)(lib); (void)(sym); /* not used */ + lua_pushliteral(L, DLMSG); + return NULL; +} + +/* }====================================================== */ +#endif + + +static void *ll_checkclib (lua_State *L, const char *path) { + void *plib; + lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); + lua_getfield(L, -1, path); + plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ + lua_pop(L, 2); /* pop CLIBS table and 'plib' */ + return plib; +} + + +static void ll_addtoclib (lua_State *L, const char *path, void *plib) { + lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); + lua_pushlightuserdata(L, plib); + lua_pushvalue(L, -1); + lua_setfield(L, -3, path); /* CLIBS[path] = plib */ + lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ + lua_pop(L, 1); /* pop CLIBS table */ +} + + +/* +** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib +** handles in list CLIBS +*/ +static int gctm (lua_State *L) { + int n = luaL_len(L, 1); + for (; n >= 1; n--) { /* for each handle, in reverse order */ + lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ + ll_unloadlib(lua_touserdata(L, -1)); + lua_pop(L, 1); /* pop handle */ + } + return 0; +} + + +static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { + void *reg = ll_checkclib(L, path); /* check loaded C libraries */ + if (reg == NULL) { /* must load library? */ + reg = ll_load(L, path, *sym == '*'); + if (reg == NULL) return ERRLIB; /* unable to load library */ + ll_addtoclib(L, path, reg); + } + if (*sym == '*') { /* loading only library (no function)? */ + lua_pushboolean(L, 1); /* return 'true' */ + return 0; /* no errors */ + } + else { + lua_CFunction f = ll_sym(L, reg, sym); + if (f == NULL) + return ERRFUNC; /* unable to find function */ + lua_pushcfunction(L, f); /* else create new function */ + return 0; /* no errors */ + } +} + + +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_PATH_SEP) path++; /* skip separators */ + if (*path == '\0') return NULL; /* no more templates */ + l = strchr(path, *LUA_PATH_SEP); /* find next separator */ + if (l == NULL) l = path + strlen(path); + lua_pushlstring(L, path, l - path); /* template */ + return l; +} + + +static const char *searchpath (lua_State *L, const char *name, + const char *path, + const char *sep, + const char *dirsep) { + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + if (*sep != '\0') /* non-empty separator? */ + name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ + while ((path = pushnexttemplate(L, path)) != NULL) { + const char *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 */ + luaL_addvalue(&msg); /* concatenate error msg. entry */ + } + luaL_pushresult(&msg); /* create error message */ + return NULL; /* not found */ +} + + +static int ll_searchpath (lua_State *L) { + const char *f = searchpath(L, luaL_checkstring(L, 1), + luaL_checkstring(L, 2), + luaL_optstring(L, 3, "."), + luaL_optstring(L, 4, LUA_DIRSEP)); + if (f != NULL) return 1; + else { /* error message is on top of the stack */ + lua_pushnil(L); + lua_insert(L, -2); + return 2; /* return nil + error message */ + } +} + + +static const char *findfile (lua_State *L, const char *name, + const char *pname, + const char *dirsep) { + const char *path; + lua_getfield(L, lua_upvalueindex(1), pname); + path = lua_tostring(L, -1); + if (path == NULL) + luaL_error(L, LUA_QL("package.%s") " must be a string", pname); + return searchpath(L, name, path, ".", dirsep); +} + + +static int checkload (lua_State *L, int stat, const char *filename) { + if (stat) { /* module loaded successfully? */ + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; /* return open function and file name */ + } + else + return 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 searcher_Lua (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + filename = findfile(L, name, "path", LUA_LSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); +} + + +static int loadfunc (lua_State *L, const char *filename, const char *modname) { + const char *funcname; + const char *mark; + modname = luaL_gsub(L, modname, ".", LUA_OFSEP); + mark = strchr(modname, *LUA_IGMARK); + if (mark) { + int stat; + funcname = lua_pushlstring(L, modname, mark - modname); + funcname = lua_pushfstring(L, LUA_POF"%s", funcname); + stat = ll_loadfunc(L, filename, funcname); + if (stat != ERRFUNC) return stat; + modname = mark + 1; /* else go ahead and try old-style name */ + } + funcname = lua_pushfstring(L, LUA_POF"%s", modname); + return ll_loadfunc(L, filename, funcname); +} + + +static int searcher_C (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (loadfunc(L, filename, name) == 0), filename); +} + + +static int searcher_Croot (lua_State *L) { + 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", LUA_CSUBSEP); + if (filename == NULL) return 1; /* root not found */ + if ((stat = loadfunc(L, filename, name)) != 0) { + if (stat != ERRFUNC) + return checkload(L, 0, filename); /* real error */ + else { /* open function not found */ + lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, + name, filename); + return 1; + } + } + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; +} + + +static int searcher_preload (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, "_PRELOAD"); + 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 void findloader (lua_State *L, const char *name) { + int i; + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + lua_getfield(L, lua_upvalueindex(1), "searchers"); /* will be at index 3 */ + if (!lua_istable(L, 3)) + luaL_error(L, LUA_QL("package.searchers") " must be a table"); + /* iterate over available searchers to find a loader */ + for (i = 1; ; i++) { + lua_rawgeti(L, 3, i); /* get a searcher */ + if (lua_isnil(L, -1)) { /* no more searchers? */ + lua_pop(L, 1); /* remove nil */ + luaL_pushresult(&msg); /* create error message */ + luaL_error(L, "module " LUA_QS " not found:%s", + name, lua_tostring(L, -1)); + } + lua_pushstring(L, name); + lua_call(L, 1, 2); /* call it */ + if (lua_isfunction(L, -2)) /* did it find a loader? */ + return; /* module loader found */ + else if (lua_isstring(L, -2)) { /* searcher returned error message? */ + lua_pop(L, 1); /* remove extra return */ + luaL_addvalue(&msg); /* concatenate error message */ + } + else + lua_pop(L, 2); /* remove both returns */ + } +} + + +static int ll_require (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_settop(L, 1); /* _LOADED table will be at index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, 2, name); /* _LOADED[name] */ + if (lua_toboolean(L, -1)) /* is it there? */ + return 1; /* package is already loaded */ + /* else must load package */ + lua_pop(L, 1); /* remove 'getfield' result */ + findloader(L, name); + lua_pushstring(L, name); /* pass name as argument to module loader */ + lua_insert(L, -2); /* name is 1st argument (before search data) */ + lua_call(L, 2, 1); /* run loader to load 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_isnil(L, -1)) { /* 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 +** ======================================================= +*/ +#if defined(LUA_COMPAT_MODULE) + +/* +** changes the environment variable of calling function +*/ +static void set_env (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); /* copy new environment table to top */ + lua_setupvalue(L, -2, 1); + lua_pop(L, 1); /* remove function */ +} + + +static void dooptions (lua_State *L, int n) { + int i; + for (i = 2; i <= n; i++) { + if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ + 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 lastarg = lua_gettop(L); /* last parameter */ + luaL_pushmodule(L, modname, 1); /* get/create module 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); + set_env(L); + dooptions(L, lastarg); + return 1; +} + + +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_pushglobaltable(L); + lua_setfield(L, -2, "__index"); /* mt.__index = _G */ + return 0; +} + +#endif +/* }====================================================== */ + + + +/* auxiliary mark (for internal use) */ +#define AUXMARK "\1" + + +/* +** return registry.LUA_NOENV as a boolean +*/ +static int noenv (lua_State *L) { + int b; + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + b = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + return b; +} + + +static void setpath (lua_State *L, const char *fieldname, const char *envname1, + const char *envname2, const char *def) { + const char *path = getenv(envname1); + if (path == NULL) /* no environment variable? */ + path = getenv(envname2); /* try alternative name */ + if (path == NULL || noenv(L)) /* 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_PATH_SEP LUA_PATH_SEP, + LUA_PATH_SEP AUXMARK LUA_PATH_SEP); + 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}, + {"searchpath", ll_searchpath}, +#if defined(LUA_COMPAT_MODULE) + {"seeall", ll_seeall}, +#endif + {NULL, NULL} +}; + + +static const luaL_Reg ll_funcs[] = { +#if defined(LUA_COMPAT_MODULE) + {"module", ll_module}, +#endif + {"require", ll_require}, + {NULL, NULL} +}; + + +static void createsearcherstable (lua_State *L) { + static const lua_CFunction searchers[] = + {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; + int i; + /* create 'searchers' table */ + lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); + /* fill it with pre-defined searchers */ + for (i=0; searchers[i] != NULL; i++) { + lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ + lua_pushcclosure(L, searchers[i], 1); + lua_rawseti(L, -2, i+1); + } +} + + +LUAMOD_API int luaopen_package (lua_State *L) { + /* create table CLIBS to keep track of loaded C libraries */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); + lua_createtable(L, 0, 1); /* metatable for CLIBS */ + lua_pushcfunction(L, gctm); + lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ + lua_setmetatable(L, -2); + /* create `package' table */ + luaL_newlib(L, pk_funcs); + createsearcherstable(L); +#if defined(LUA_COMPAT_LOADERS) + lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ + lua_setfield(L, -3, "loaders"); /* put it in field `loaders' */ +#endif + lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ + /* set field 'path' */ + setpath(L, "path", LUA_PATHVERSION, LUA_PATH, LUA_PATH_DEFAULT); + /* set field 'cpath' */ + setpath(L, "cpath", LUA_CPATHVERSION, LUA_CPATH, LUA_CPATH_DEFAULT); + /* store config information */ + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" + LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); + lua_setfield(L, -2, "config"); + /* set field `loaded' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_setfield(L, -2, "loaded"); + /* set field `preload' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, "_PRELOAD"); + lua_setfield(L, -2, "preload"); + lua_pushglobaltable(L); + lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ + luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ + lua_pop(L, 1); /* pop global table */ + return 1; /* return 'package' table */ +} + diff --git a/lua/lobject.c b/lua/lobject.c new file mode 100644 index 0000000..882d994 --- /dev/null +++ b/lua/lobject.c @@ -0,0 +1,287 @@ +/* +** $Id: lobject.c,v 2.58.1.1 2013/04/12 18:48:47 roberto Exp $ +** Some generic functions over Lua objects +** See Copyright Notice in lua.h +*/ + +#include +#include +#include +#include + +#define lobject_c +#define LUA_CORE + +#include "lua.h" + +#include "lctype.h" +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "lvm.h" + + + +LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; + + +/* +** 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; /* exponent */ + if (x < 8) return x; + while (x >= 0x10) { + x = (x+1) >> 1; + e++; + } + return ((e+1) << 3) | (cast_int(x) - 8); +} + + +/* converts back */ +int luaO_fb2int (int x) { + int e = (x >> 3) & 0x1f; + if (e == 0) return x; + else return ((x & 7) + 8) << (e - 1); +} + + +int luaO_ceillog2 (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 = 0; + x--; + while (x >= 256) { l += 8; x >>= 8; } + return l + log_2[x]; +} + + +lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2) { + switch (op) { + case LUA_OPADD: return luai_numadd(NULL, v1, v2); + case LUA_OPSUB: return luai_numsub(NULL, v1, v2); + case LUA_OPMUL: return luai_nummul(NULL, v1, v2); + case LUA_OPDIV: return luai_numdiv(NULL, v1, v2); + case LUA_OPMOD: return luai_nummod(NULL, v1, v2); + case LUA_OPPOW: return luai_numpow(NULL, v1, v2); + case LUA_OPUNM: return luai_numunm(NULL, v1); + default: lua_assert(0); return 0; + } +} + + +int luaO_hexavalue (int c) { + if (lisdigit(c)) return c - '0'; + else return ltolower(c) - 'a' + 10; +} + + +#if !defined(lua_strx2number) + +#include + + +static int isneg (const char **s) { + if (**s == '-') { (*s)++; return 1; } + else if (**s == '+') (*s)++; + return 0; +} + + +static lua_Number readhexa (const char **s, lua_Number r, int *count) { + for (; lisxdigit(cast_uchar(**s)); (*s)++) { /* read integer part */ + r = (r * cast_num(16.0)) + cast_num(luaO_hexavalue(cast_uchar(**s))); + (*count)++; + } + return r; +} + + +/* +** convert an hexadecimal numeric string to a number, following +** C99 specification for 'strtod' +*/ +static lua_Number lua_strx2number (const char *s, char **endptr) { + lua_Number r = 0.0; + int e = 0, i = 0; + int neg = 0; /* 1 if number is negative */ + *endptr = cast(char *, s); /* nothing is valid yet */ + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); /* check signal */ + if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ + return 0.0; /* invalid format (no '0x') */ + s += 2; /* skip '0x' */ + r = readhexa(&s, r, &i); /* read integer part */ + if (*s == '.') { + s++; /* skip dot */ + r = readhexa(&s, r, &e); /* read fractional part */ + } + if (i == 0 && e == 0) + return 0.0; /* invalid format (no digit) */ + e *= -4; /* each fractional digit divides value by 2^-4 */ + *endptr = cast(char *, s); /* valid up to here */ + if (*s == 'p' || *s == 'P') { /* exponent part? */ + int exp1 = 0; + int neg1; + s++; /* skip 'p' */ + neg1 = isneg(&s); /* signal */ + if (!lisdigit(cast_uchar(*s))) + goto ret; /* must have at least one digit */ + while (lisdigit(cast_uchar(*s))) /* read exponent */ + exp1 = exp1 * 10 + *(s++) - '0'; + if (neg1) exp1 = -exp1; + e += exp1; + } + *endptr = cast(char *, s); /* valid up to here */ + ret: + if (neg) r = -r; + return l_mathop(ldexp)(r, e); +} + +#endif + + +int luaO_str2d (const char *s, size_t len, lua_Number *result) { + char *endptr; + if (strpbrk(s, "nN")) /* reject 'inf' and 'nan' */ + return 0; + else if (strpbrk(s, "xX")) /* hexa? */ + *result = lua_strx2number(s, &endptr); + else + *result = lua_str2number(s, &endptr); + if (endptr == s) return 0; /* nothing recognized */ + while (lisspace(cast_uchar(*endptr))) endptr++; + return (endptr == s + len); /* OK if no trailing characters */ +} + + + +static void pushstr (lua_State *L, const char *str, size_t l) { + setsvalue2s(L, L->top++, luaS_newlstr(L, str, 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 = 0; + for (;;) { + const char *e = strchr(fmt, '%'); + if (e == NULL) break; + luaD_checkstack(L, 2); /* fmt + item */ + pushstr(L, fmt, e - fmt); + switch (*(e+1)) { + case 's': { + const char *s = va_arg(argp, char *); + if (s == NULL) s = "(null)"; + pushstr(L, s, strlen(s)); + break; + } + case 'c': { + char buff; + buff = cast(char, va_arg(argp, int)); + pushstr(L, &buff, 1); + break; + } + case 'd': { + setnvalue(L->top++, cast_num(va_arg(argp, int))); + break; + } + case 'f': { + setnvalue(L->top++, cast_num(va_arg(argp, l_uacNumber))); + break; + } + case 'p': { + char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ + int l = sprintf(buff, "%p", va_arg(argp, void *)); + pushstr(L, buff, l); + break; + } + case '%': { + pushstr(L, "%", 1); + break; + } + default: { + luaG_runerror(L, + "invalid option " LUA_QL("%%%c") " to " LUA_QL("lua_pushfstring"), + *(e + 1)); + } + } + n += 2; + fmt = e+2; + } + luaD_checkstack(L, 1); + pushstr(L, fmt, strlen(fmt)); + if (n > 0) luaV_concat(L, n + 1); + 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; +} + + +/* number of chars of a literal string without the ending \0 */ +#define LL(x) (sizeof(x)/sizeof(char) - 1) + +#define RETS "..." +#define PRE "[string \"" +#define POS "\"]" + +#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) + +void luaO_chunkid (char *out, const char *source, size_t bufflen) { + size_t l = strlen(source); + if (*source == '=') { /* 'literal' source */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* truncate it */ + addstr(out, source + 1, bufflen - 1); + *out = '\0'; + } + } + else if (*source == '@') { /* file name */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* add '...' before rest of name */ + addstr(out, RETS, LL(RETS)); + bufflen -= LL(RETS); + memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); + } + } + else { /* string; format as [string "source"] */ + const char *nl = strchr(source, '\n'); /* find first new line (if any) */ + addstr(out, PRE, LL(PRE)); /* add prefix */ + bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ + if (l < bufflen && nl == NULL) { /* small one-line source? */ + addstr(out, source, l); /* keep it */ + } + else { + if (nl != NULL) l = nl - source; /* stop at first newline */ + if (l > bufflen) l = bufflen; + addstr(out, source, l); + addstr(out, RETS, LL(RETS)); + } + memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); + } +} + diff --git a/lua/lobject.h b/lua/lobject.h new file mode 100644 index 0000000..3a630b9 --- /dev/null +++ b/lua/lobject.h @@ -0,0 +1,607 @@ +/* +** $Id: lobject.h,v 2.71.1.1 2013/04/12 18:48:47 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" + + +/* +** Extra tags for non-values +*/ +#define LUA_TPROTO LUA_NUMTAGS +#define LUA_TUPVAL (LUA_NUMTAGS+1) +#define LUA_TDEADKEY (LUA_NUMTAGS+2) + +/* +** number of all possible tags (including LUA_TNONE but excluding DEADKEY) +*/ +#define LUA_TOTALTAGS (LUA_TUPVAL+2) + + +/* +** tags for Tagged Values have the following use of bits: +** bits 0-3: actual tag (a LUA_T* value) +** bits 4-5: variant bits +** bit 6: whether value is collectable +*/ + +#define VARBITS (3 << 4) + + +/* +** LUA_TFUNCTION variants: +** 0 - Lua function +** 1 - light C function +** 2 - regular C function (closure) +*/ + +/* Variant tags for functions */ +#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ +#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ +#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ + + +/* Variant tags for strings */ +#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */ +#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ + + +/* Bit mark for collectable types */ +#define BIT_ISCOLLECTABLE (1 << 6) + +/* mark a tag as collectable */ +#define ctb(t) ((t) | BIT_ISCOLLECTABLE) + + +/* +** 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 Value Value; + + +#define numfield lua_Number n; /* numbers */ + + + +/* +** Tagged Values. This is the basic representation of values in Lua, +** an actual value plus a tag with its type. +*/ + +#define TValuefields Value value_; int tt_ + +typedef struct lua_TValue TValue; + + +/* macro defining a nil value */ +#define NILCONSTANT {NULL}, LUA_TNIL + + +#define val_(o) ((o)->value_) +#define num_(o) (val_(o).n) + + +/* raw type tag of a TValue */ +#define rttype(o) ((o)->tt_) + +/* tag with no variants (bits 0-3) */ +#define novariant(x) ((x) & 0x0F) + +/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ +#define ttype(o) (rttype(o) & 0x3F) + +/* type tag of a TValue with no variants (bits 0-3) */ +#define ttypenv(o) (novariant(rttype(o))) + + +/* Macros to test type */ +#define checktag(o,t) (rttype(o) == (t)) +#define checktype(o,t) (ttypenv(o) == (t)) +#define ttisnumber(o) checktag((o), LUA_TNUMBER) +#define ttisnil(o) checktag((o), LUA_TNIL) +#define ttisboolean(o) checktag((o), LUA_TBOOLEAN) +#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) +#define ttisstring(o) checktype((o), LUA_TSTRING) +#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) +#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) +#define ttistable(o) checktag((o), ctb(LUA_TTABLE)) +#define ttisfunction(o) checktype(o, LUA_TFUNCTION) +#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) +#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) +#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) +#define ttislcf(o) checktag((o), LUA_TLCF) +#define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA)) +#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) +#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) + +#define ttisequal(o1,o2) (rttype(o1) == rttype(o2)) + +/* Macros to access values */ +#define nvalue(o) check_exp(ttisnumber(o), num_(o)) +#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) +#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) +#define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) +#define tsvalue(o) (&rawtsvalue(o)->tsv) +#define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u) +#define uvalue(o) (&rawuvalue(o)->uv) +#define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl) +#define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l) +#define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c) +#define fvalue(o) check_exp(ttislcf(o), val_(o).f) +#define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h) +#define bvalue(o) check_exp(ttisboolean(o), val_(o).b) +#define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th) +/* a dead value may get the 'gc' field, but cannot access its contents */ +#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc)) + +#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) + + +#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) + + +/* Macros for internal tests */ +#define righttt(obj) (ttype(obj) == gcvalue(obj)->gch.tt) + +#define checkliveness(g,obj) \ + lua_longassert(!iscollectable(obj) || \ + (righttt(obj) && !isdead(g,gcvalue(obj)))) + + +/* Macros to set values */ +#define settt_(o,t) ((o)->tt_=(t)) + +#define setnvalue(obj,x) \ + { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); } + +#define setnilvalue(obj) settt_(obj, LUA_TNIL) + +#define setfvalue(obj,x) \ + { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); } + +#define setpvalue(obj,x) \ + { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); } + +#define setbvalue(obj,x) \ + { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } + +#define setgcovalue(L,obj,x) \ + { TValue *io=(obj); GCObject *i_g=(x); \ + val_(io).gc=i_g; settt_(io, ctb(gch(i_g)->tt)); } + +#define setsvalue(L,obj,x) \ + { TValue *io=(obj); \ + TString *x_ = (x); \ + val_(io).gc=cast(GCObject *, x_); settt_(io, ctb(x_->tsv.tt)); \ + checkliveness(G(L),io); } + +#define setuvalue(L,obj,x) \ + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TUSERDATA)); \ + checkliveness(G(L),io); } + +#define setthvalue(L,obj,x) \ + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTHREAD)); \ + checkliveness(G(L),io); } + +#define setclLvalue(L,obj,x) \ + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TLCL)); \ + checkliveness(G(L),io); } + +#define setclCvalue(L,obj,x) \ + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TCCL)); \ + checkliveness(G(L),io); } + +#define sethvalue(L,obj,x) \ + { TValue *io=(obj); \ + val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \ + checkliveness(G(L),io); } + +#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) + + + +#define setobj(L,obj1,obj2) \ + { const TValue *io2=(obj2); TValue *io1=(obj1); \ + io1->value_ = io2->value_; io1->tt_ = io2->tt_; \ + checkliveness(G(L),io1); } + + +/* +** different types of assignments, 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 + + +/* check whether a number is valid (useful only for NaN trick) */ +#define luai_checknum(L,o,c) { /* empty */ } + + +/* +** {====================================================== +** NaN Trick +** ======================================================= +*/ +#if defined(LUA_NANTRICK) + +/* +** numbers are represented in the 'd_' field. All other values have the +** value (NNMARK | tag) in 'tt__'. A number with such pattern would be +** a "signaled NaN", which is never generated by regular operations by +** the CPU (nor by 'strtod') +*/ + +/* allows for external implementation for part of the trick */ +#if !defined(NNMARK) /* { */ + + +#if !defined(LUA_IEEEENDIAN) +#error option 'LUA_NANTRICK' needs 'LUA_IEEEENDIAN' +#endif + + +#define NNMARK 0x7FF7A500 +#define NNMASK 0x7FFFFF00 + +#undef TValuefields +#undef NILCONSTANT + +#if (LUA_IEEEENDIAN == 0) /* { */ + +/* little endian */ +#define TValuefields \ + union { struct { Value v__; int tt__; } i; double d__; } u +#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}} +/* field-access macros */ +#define v_(o) ((o)->u.i.v__) +#define d_(o) ((o)->u.d__) +#define tt_(o) ((o)->u.i.tt__) + +#else /* }{ */ + +/* big endian */ +#define TValuefields \ + union { struct { int tt__; Value v__; } i; double d__; } u +#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}} +/* field-access macros */ +#define v_(o) ((o)->u.i.v__) +#define d_(o) ((o)->u.d__) +#define tt_(o) ((o)->u.i.tt__) + +#endif /* } */ + +#endif /* } */ + + +/* correspondence with standard representation */ +#undef val_ +#define val_(o) v_(o) +#undef num_ +#define num_(o) d_(o) + + +#undef numfield +#define numfield /* no such field; numbers are the entire struct */ + +/* basic check to distinguish numbers from non-numbers */ +#undef ttisnumber +#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK) + +#define tag2tt(t) (NNMARK | (t)) + +#undef rttype +#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff) + +#undef settt_ +#define settt_(o,t) (tt_(o) = tag2tt(t)) + +#undef setnvalue +#define setnvalue(obj,x) \ + { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); } + +#undef setobj +#define setobj(L,obj1,obj2) \ + { const TValue *o2_=(obj2); TValue *o1_=(obj1); \ + o1_->u = o2_->u; \ + checkliveness(G(L),o1_); } + + +/* +** these redefinitions are not mandatory, but these forms are more efficient +*/ + +#undef checktag +#undef checktype +#define checktag(o,t) (tt_(o) == tag2tt(t)) +#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS)) + +#undef ttisequal +#define ttisequal(o1,o2) \ + (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2))) + + +#undef luai_checknum +#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; } + +#endif +/* }====================================================== */ + + + +/* +** {====================================================== +** types and prototypes +** ======================================================= +*/ + + +union Value { + GCObject *gc; /* collectable objects */ + void *p; /* light userdata */ + int b; /* booleans */ + lua_CFunction f; /* light C functions */ + numfield /* numbers */ +}; + + +struct lua_TValue { + TValuefields; +}; + + +typedef TValue *StkId; /* index to stack elements */ + + + + +/* +** Header for string value; string bytes follow the end of this structure +*/ +typedef union TString { + L_Umaxalign dummy; /* ensures maximum alignment for strings */ + struct { + CommonHeader; + lu_byte extra; /* reserved words for short strings; "has hash" for longs */ + unsigned int hash; + size_t len; /* number of characters in string */ + } tsv; +} TString; + + +/* get the actual string (array of bytes) from a TString */ +#define getstr(ts) cast(const char *, (ts) + 1) + +/* get the actual string (array of bytes) from a Lua value */ +#define svalue(o) getstr(rawtsvalue(o)) + + +/* +** Header for userdata; memory area follows the end of this structure +*/ +typedef union Udata { + L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ + struct { + CommonHeader; + struct Table *metatable; + struct Table *env; + size_t len; /* number of bytes */ + } uv; +} Udata; + + + +/* +** Description of an upvalue for function prototypes +*/ +typedef struct Upvaldesc { + TString *name; /* upvalue name (for debug information) */ + lu_byte instack; /* whether it is in stack */ + lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ +} Upvaldesc; + + +/* +** Description of a local variable for function prototypes +** (used for debug information) +*/ +typedef struct LocVar { + TString *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} LocVar; + + +/* +** 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 (debug information) */ + LocVar *locvars; /* information about local variables (debug information) */ + Upvaldesc *upvalues; /* upvalue information */ + union Closure *cache; /* last created closure with this prototype */ + TString *source; /* used for debug information */ + int sizeupvalues; /* size of 'upvalues' */ + int sizek; /* size of `k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of `p' */ + int sizelocvars; + int linedefined; + int lastlinedefined; + GCObject *gclist; + lu_byte numparams; /* number of fixed parameters */ + lu_byte is_vararg; + lu_byte maxstacksize; /* maximum stack used by this function */ +} Proto; + + + +/* +** Lua 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 nupvalues; GCObject *gclist + +typedef struct CClosure { + ClosureHeader; + lua_CFunction f; + TValue upvalue[1]; /* list of upvalues */ +} CClosure; + + +typedef struct LClosure { + ClosureHeader; + struct Proto *p; + UpVal *upvals[1]; /* list of upvalues */ +} LClosure; + + +typedef union Closure { + CClosure c; + LClosure l; +} Closure; + + +#define isLfunction(o) ttisLclosure(o) + +#define getproto(o) (clLvalue(o)->p) + + +/* +** 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)) + + +/* +** (address of) a fixed nil value +*/ +#define luaO_nilobject (&luaO_nilobject_) + + +LUAI_DDEC const TValue luaO_nilobject_; + + +LUAI_FUNC int luaO_int2fb (unsigned int x); +LUAI_FUNC int luaO_fb2int (int x); +LUAI_FUNC int luaO_ceillog2 (unsigned int x); +LUAI_FUNC lua_Number luaO_arith (int op, lua_Number v1, lua_Number v2); +LUAI_FUNC int luaO_str2d (const char *s, size_t len, lua_Number *result); +LUAI_FUNC int luaO_hexavalue (int c); +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 + diff --git a/lua/lopcodes.c b/lua/lopcodes.c new file mode 100644 index 0000000..4190dc7 --- /dev/null +++ b/lua/lopcodes.c @@ -0,0 +1,107 @@ +/* +** $Id: lopcodes.c,v 1.49.1.1 2013/04/12 18:48:47 roberto Exp $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + + +#define lopcodes_c +#define LUA_CORE + + +#include "lopcodes.h" + + +/* ORDER OP */ + +LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { + "MOVE", + "LOADK", + "LOADKX", + "LOADBOOL", + "LOADNIL", + "GETUPVAL", + "GETTABUP", + "GETTABLE", + "SETTABUP", + "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", + "TFORCALL", + "TFORLOOP", + "SETLIST", + "CLOSURE", + "VARARG", + "EXTRAARG", + NULL +}; + + +#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) + +LUAI_DDEF 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, OpArgN, OpArgN, iABx) /* OP_LOADKX */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ + ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ + ,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, 0, OpArgN, 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(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ + ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ + ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ + ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ +}; + diff --git a/lua/lopcodes.h b/lua/lopcodes.h new file mode 100644 index 0000000..51f5791 --- /dev/null +++ b/lua/lopcodes.h @@ -0,0 +1,288 @@ +/* +** $Id: lopcodes.h,v 1.142.1.1 2013/04/12 18:48:47 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 + 'Ax' : 26 bits ('A', 'B', and 'C' together) + `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, iAx}; /* 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_Ax (SIZE_C + SIZE_B + SIZE_A) + +#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 +#define POS_Ax POS_A + + +/* +** 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 + +#if SIZE_Ax < LUAI_BITSINT-1 +#define MAXARG_Ax ((1<>POS_OP) & MASK1(SIZE_OP,0))) +#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ + ((cast(Instruction, o)<>pos) & MASK1(size,0))) +#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ + ((cast(Instruction, v)<= R(A) + 1 */ +OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ +OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ +OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ + +OP_TEST,/* A C if not (R(A) <=> 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) > 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_DDEC 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 diff --git a/lua/loslib.c b/lua/loslib.c new file mode 100644 index 0000000..052ba17 --- /dev/null +++ b/lua/loslib.c @@ -0,0 +1,323 @@ +/* +** $Id: loslib.c,v 1.40.1.1 2013/04/12 18:48:47 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" + + +/* +** list of valid conversion specifiers for the 'strftime' function +*/ +#if !defined(LUA_STRFTIMEOPTIONS) + +#if !defined(LUA_USE_POSIX) +#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } +#else +#define LUA_STRFTIMEOPTIONS \ + { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \ + "", "E", "cCxXyY", \ + "O", "deHImMSuUVwWy" } +#endif + +#endif + + + +/* +** By default, Lua uses tmpnam except when POSIX is available, where it +** uses mkstemp. +*/ +#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); } + +#elif !defined(lua_tmpnam) + +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } + +#endif + + +/* +** By default, Lua uses gmtime/localtime, except when POSIX is available, +** where it uses gmtime_r/localtime_r +*/ +#if defined(LUA_USE_GMTIME_R) + +#define l_gmtime(t,r) gmtime_r(t,r) +#define l_localtime(t,r) localtime_r(t,r) + +#elif !defined(l_gmtime) + +#define l_gmtime(t,r) ((void)r, gmtime(t)) +#define l_localtime(t,r) ((void)r, localtime(t)) + +#endif + + + +static int os_execute (lua_State *L) { + const char *cmd = luaL_optstring(L, 1, NULL); + int stat = system(cmd); + if (cmd != NULL) + return luaL_execresult(L, stat); + else { + lua_pushboolean(L, stat); /* true if there is a shell */ + return 1; + } +} + + +static int os_remove (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + return luaL_fileresult(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 luaL_fileresult(L, rename(fromname, toname) == 0, NULL); +} + + +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, isnum; + lua_getfield(L, -1, key); + res = (int)lua_tointegerx(L, -1, &isnum); + if (!isnum) { + if (d < 0) + return luaL_error(L, "field " LUA_QS " missing in date table", key); + res = d; + } + lua_pop(L, 1); + return res; +} + + +static const char *checkoption (lua_State *L, const char *conv, char *buff) { + static const char *const options[] = LUA_STRFTIMEOPTIONS; + unsigned int i; + for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) { + if (*conv != '\0' && strchr(options[i], *conv) != NULL) { + buff[1] = *conv; + if (*options[i + 1] == '\0') { /* one-char conversion specifier? */ + buff[2] = '\0'; /* end buffer */ + return conv + 1; + } + else if (*(conv + 1) != '\0' && + strchr(options[i + 1], *(conv + 1)) != NULL) { + buff[2] = *(conv + 1); /* valid two-char conversion specifier */ + buff[3] = '\0'; /* end buffer */ + return conv + 2; + } + } + } + luaL_argerror(L, 1, + lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); + return conv; /* to avoid warnings */ +} + + +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 tmr, *stm; + if (*s == '!') { /* UTC? */ + stm = l_gmtime(&t, &tmr); + s++; /* skip `!' */ + } + else + stm = l_localtime(&t, &tmr); + 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[4]; + luaL_Buffer b; + cc[0] = '%'; + luaL_buffinit(L, &b); + while (*s) { + if (*s != '%') /* no conversion specifier? */ + luaL_addchar(&b, *s++); + else { + size_t reslen; + char buff[200]; /* should be big enough for any conversion result */ + s = checkoption(L, s + 1, cc); + 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) { + int status; + if (lua_isboolean(L, 1)) + status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); + else + status = luaL_optint(L, 1, EXIT_SUCCESS); + if (lua_toboolean(L, 2)) + lua_close(L); + if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ + return 0; +} + + +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} +}; + +/* }====================================================== */ + + + +LUAMOD_API int luaopen_os (lua_State *L) { + luaL_newlib(L, syslib); + return 1; +} + diff --git a/lua/lparser.c b/lua/lparser.c new file mode 100644 index 0000000..9e1a9ca --- /dev/null +++ b/lua/lparser.c @@ -0,0 +1,1638 @@ +/* +** $Id: lparser.c,v 2.130.1.1 2013/04/12 18:48:47 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" + + + +/* maximum number of local variables per function (must be smaller + than 250, due to the bytecode format) */ +#define MAXVARS 200 + + +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) + + + +/* +** nodes for block list (list of active blocks) +*/ +typedef struct BlockCnt { + struct BlockCnt *previous; /* chain */ + short firstlabel; /* index of first label in this block */ + short firstgoto; /* index of first pending goto in this block */ + lu_byte nactvar; /* # active locals outside the block */ + lu_byte upval; /* true if some variable in the block is an upvalue */ + lu_byte isloop; /* true if `block' is a loop */ +} BlockCnt; + + + +/* +** prototypes for recursive non-terminal functions +*/ +static void statement (LexState *ls); +static void expr (LexState *ls, expdesc *v); + + +static void anchor_token (LexState *ls) { + /* last token from outer function must be EOS */ + lua_assert(ls->fs != NULL || ls->t.token == TK_EOS); + 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); + } +} + + +/* semantic error */ +static l_noret semerror (LexState *ls, const char *msg) { + ls->t.token = 0; /* remove 'near to' from final message */ + luaX_syntaxerror(ls, msg); +} + + +static l_noret error_expected (LexState *ls, int token) { + luaX_syntaxerror(ls, + luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); +} + + +static l_noret errorlimit (FuncState *fs, int limit, const char *what) { + lua_State *L = fs->ls->L; + const char *msg; + int line = fs->f->linedefined; + const char *where = (line == 0) + ? "main function" + : luaO_pushfstring(L, "function at line %d", line); + msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", + what, limit, where); + luaX_syntaxerror(fs->ls, msg); +} + + +static void checklimit (FuncState *fs, int v, int l, const char *what) { + if (v > l) errorlimit(fs, l, what); +} + + +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, + "%s expected (to close %s 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.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, "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++; +} + + +static void new_localvar (LexState *ls, TString *name) { + FuncState *fs = ls->fs; + Dyndata *dyd = ls->dyd; + int reg = registerlocalvar(ls, name); + checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, + MAXVARS, "local variables"); + luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, + dyd->actvar.size, Vardesc, MAX_INT, "local variables"); + dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); +} + + +static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { + new_localvar(ls, luaX_newstring(ls, name, sz)); +} + +#define new_localvarliteral(ls,v) \ + new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) + + +static LocVar *getlocvar (FuncState *fs, int i) { + int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; + lua_assert(idx < fs->nlocvars); + return &fs->f->locvars[idx]; +} + + +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 (FuncState *fs, int tolevel) { + fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); + while (fs->nactvar > tolevel) + getlocvar(fs, --fs->nactvar)->endpc = fs->pc; +} + + +static int searchupvalue (FuncState *fs, TString *name) { + int i; + Upvaldesc *up = fs->f->upvalues; + for (i = 0; i < fs->nups; i++) { + if (luaS_eqstr(up[i].name, name)) return i; + } + return -1; /* not found */ +} + + +static int newupvalue (FuncState *fs, TString *name, expdesc *v) { + Proto *f = fs->f; + int oldsize = f->sizeupvalues; + checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); + luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, + Upvaldesc, MAXUPVAL, "upvalues"); + while (oldsize < f->sizeupvalues) f->upvalues[oldsize++].name = NULL; + f->upvalues[fs->nups].instack = (v->k == VLOCAL); + f->upvalues[fs->nups].idx = cast_byte(v->u.info); + f->upvalues[fs->nups].name = name; + luaC_objbarrier(fs->ls->L, f, name); + return fs->nups++; +} + + +static int searchvar (FuncState *fs, TString *n) { + int i; + for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { + if (luaS_eqstr(n, getlocvar(fs, i)->varname)) + return i; + } + return -1; /* not found */ +} + + +/* + Mark block where variable at given level was defined + (to emit close instructions later). +*/ +static void markupval (FuncState *fs, int level) { + BlockCnt *bl = fs->bl; + while (bl->nactvar > level) bl = bl->previous; + bl->upval = 1; +} + + +/* + Find variable with given name 'n'. If it is an upvalue, add this + upvalue into all intermediate functions. +*/ +static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { + if (fs == NULL) /* no more levels? */ + return VVOID; /* default is global */ + else { + int v = searchvar(fs, n); /* look up locals at current level */ + if (v >= 0) { /* found? */ + init_exp(var, VLOCAL, v); /* variable is local */ + if (!base) + markupval(fs, v); /* local will be used as an upval */ + return VLOCAL; + } + else { /* not found as local at current level; try upvalues */ + int idx = searchupvalue(fs, n); /* try existing upvalues */ + if (idx < 0) { /* not found? */ + if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */ + return VVOID; /* not found; is a global */ + /* else was LOCAL or UPVAL */ + idx = newupvalue(fs, n, var); /* will be a new upvalue */ + } + init_exp(var, VUPVAL, idx); + return VUPVAL; + } + } +} + + +static void singlevar (LexState *ls, expdesc *var) { + TString *varname = str_checkname(ls); + FuncState *fs = ls->fs; + if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */ + expdesc key; + singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ + lua_assert(var->k == VLOCAL || var->k == VUPVAL); + codestring(ls, &key, varname); /* key is variable name */ + luaK_indexed(fs, var, &key); /* env[varname] */ + } +} + + +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) { + lua_State *L = ls->L; + ++L->nCcalls; + checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); +} + + +#define leavelevel(ls) ((ls)->L->nCcalls--) + + +static void closegoto (LexState *ls, int g, Labeldesc *label) { + int i; + FuncState *fs = ls->fs; + Labellist *gl = &ls->dyd->gt; + Labeldesc *gt = &gl->arr[g]; + lua_assert(luaS_eqstr(gt->name, label->name)); + if (gt->nactvar < label->nactvar) { + TString *vname = getlocvar(fs, gt->nactvar)->varname; + const char *msg = luaO_pushfstring(ls->L, + " at line %d jumps into the scope of local " LUA_QS, + getstr(gt->name), gt->line, getstr(vname)); + semerror(ls, msg); + } + luaK_patchlist(fs, gt->pc, label->pc); + /* remove goto from pending list */ + for (i = g; i < gl->n - 1; i++) + gl->arr[i] = gl->arr[i + 1]; + gl->n--; +} + + +/* +** try to close a goto with existing labels; this solves backward jumps +*/ +static int findlabel (LexState *ls, int g) { + int i; + BlockCnt *bl = ls->fs->bl; + Dyndata *dyd = ls->dyd; + Labeldesc *gt = &dyd->gt.arr[g]; + /* check labels in current block for a match */ + for (i = bl->firstlabel; i < dyd->label.n; i++) { + Labeldesc *lb = &dyd->label.arr[i]; + if (luaS_eqstr(lb->name, gt->name)) { /* correct label? */ + if (gt->nactvar > lb->nactvar && + (bl->upval || dyd->label.n > bl->firstlabel)) + luaK_patchclose(ls->fs, gt->pc, lb->nactvar); + closegoto(ls, g, lb); /* close it */ + return 1; + } + } + return 0; /* label not found; cannot close goto */ +} + + +static int newlabelentry (LexState *ls, Labellist *l, TString *name, + int line, int pc) { + int n = l->n; + luaM_growvector(ls->L, l->arr, n, l->size, + Labeldesc, SHRT_MAX, "labels/gotos"); + l->arr[n].name = name; + l->arr[n].line = line; + l->arr[n].nactvar = ls->fs->nactvar; + l->arr[n].pc = pc; + l->n++; + return n; +} + + +/* +** check whether new label 'lb' matches any pending gotos in current +** block; solves forward jumps +*/ +static void findgotos (LexState *ls, Labeldesc *lb) { + Labellist *gl = &ls->dyd->gt; + int i = ls->fs->bl->firstgoto; + while (i < gl->n) { + if (luaS_eqstr(gl->arr[i].name, lb->name)) + closegoto(ls, i, lb); + else + i++; + } +} + + +/* +** "export" pending gotos to outer level, to check them against +** outer labels; if the block being exited has upvalues, and +** the goto exits the scope of any variable (which can be the +** upvalue), close those variables being exited. +*/ +static void movegotosout (FuncState *fs, BlockCnt *bl) { + int i = bl->firstgoto; + Labellist *gl = &fs->ls->dyd->gt; + /* correct pending gotos to current block and try to close it + with visible labels */ + while (i < gl->n) { + Labeldesc *gt = &gl->arr[i]; + if (gt->nactvar > bl->nactvar) { + if (bl->upval) + luaK_patchclose(fs, gt->pc, bl->nactvar); + gt->nactvar = bl->nactvar; + } + if (!findlabel(fs->ls, i)) + i++; /* move to next one */ + } +} + + +static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { + bl->isloop = isloop; + bl->nactvar = fs->nactvar; + bl->firstlabel = fs->ls->dyd->label.n; + bl->firstgoto = fs->ls->dyd->gt.n; + bl->upval = 0; + bl->previous = fs->bl; + fs->bl = bl; + lua_assert(fs->freereg == fs->nactvar); +} + + +/* +** create a label named "break" to resolve break statements +*/ +static void breaklabel (LexState *ls) { + TString *n = luaS_new(ls->L, "break"); + int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); + findgotos(ls, &ls->dyd->label.arr[l]); +} + +/* +** generates an error for an undefined 'goto'; choose appropriate +** message when label name is a reserved word (which can only be 'break') +*/ +static l_noret undefgoto (LexState *ls, Labeldesc *gt) { + const char *msg = isreserved(gt->name) + ? "<%s> at line %d not inside a loop" + : "no visible label " LUA_QS " for at line %d"; + msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); + semerror(ls, msg); +} + + +static void leaveblock (FuncState *fs) { + BlockCnt *bl = fs->bl; + LexState *ls = fs->ls; + if (bl->previous && bl->upval) { + /* create a 'jump to here' to close upvalues */ + int j = luaK_jump(fs); + luaK_patchclose(fs, j, bl->nactvar); + luaK_patchtohere(fs, j); + } + if (bl->isloop) + breaklabel(ls); /* close pending breaks */ + fs->bl = bl->previous; + removevars(fs, bl->nactvar); + lua_assert(bl->nactvar == fs->nactvar); + fs->freereg = fs->nactvar; /* free registers */ + ls->dyd->label.n = bl->firstlabel; /* remove local labels */ + if (bl->previous) /* inner block? */ + movegotosout(fs, bl); /* update pending gotos to outer block */ + else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ + undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ +} + + +/* +** adds a new prototype into list of prototypes +*/ +static Proto *addprototype (LexState *ls) { + Proto *clp; + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; /* prototype of current function */ + if (fs->np >= f->sizep) { + int oldsize = f->sizep; + luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); + while (oldsize < f->sizep) f->p[oldsize++] = NULL; + } + f->p[fs->np++] = clp = luaF_newproto(L); + luaC_objbarrier(L, f, clp); + return clp; +} + + +/* +** codes instruction to create new closure in parent function. +** The OP_CLOSURE instruction must use the last available register, +** so that, if it invokes the GC, the GC knows which registers +** are in use at that time. +*/ +static void codeclosure (LexState *ls, expdesc *v) { + FuncState *fs = ls->fs->prev; + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); + luaK_exp2nextreg(fs, v); /* fix it at the last register */ +} + + +static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { + lua_State *L = ls->L; + Proto *f; + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + ls->fs = fs; + fs->pc = 0; + fs->lasttarget = 0; + fs->jpc = NO_JUMP; + fs->freereg = 0; + fs->nk = 0; + fs->np = 0; + fs->nups = 0; + fs->nlocvars = 0; + fs->nactvar = 0; + fs->firstlocal = ls->dyd->actvar.n; + fs->bl = NULL; + f = fs->f; + f->source = ls->source; + f->maxstacksize = 2; /* registers 0/1 are always valid */ + fs->h = luaH_new(L); + /* anchor table of constants (to avoid being collected) */ + sethvalue2s(L, L->top, fs->h); + incr_top(L); + enterblock(fs, bl, 0); +} + + +static void close_func (LexState *ls) { + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; + luaK_ret(fs, 0, 0); /* final return */ + leaveblock(fs); + 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, fs->nups, Upvaldesc); + f->sizeupvalues = fs->nups; + lua_assert(fs->bl == NULL); + ls->fs = fs->prev; + /* last token read was anchored in defunct function; must re-anchor it */ + anchor_token(ls); + L->top--; /* pop table of constants */ + luaC_checkGC(L); +} + + + +/*============================================================*/ +/* GRAMMAR RULES */ +/*============================================================*/ + + +/* +** check whether current token is in the follow set of a block. +** 'until' closes syntactical blocks, but do not close scope, +** so it handled in separate. +*/ +static int block_follow (LexState *ls, int withuntil) { + switch (ls->t.token) { + case TK_ELSE: case TK_ELSEIF: + case TK_END: case TK_EOS: + return 1; + case TK_UNTIL: return withuntil; + default: return 0; + } +} + + +static void statlist (LexState *ls) { + /* statlist -> { stat [`;'] } */ + while (!block_follow(ls, 1)) { + if (ls->t.token == TK_RETURN) { + statement(ls); + return; /* 'return' must be last statement */ + } + statement(ls); + } +} + + +static void fieldsel (LexState *ls, expdesc *v) { + /* fieldsel -> ['.' | ':'] NAME */ + FuncState *fs = ls->fs; + expdesc key; + luaK_exp2anyregup(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) { + 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.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.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.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.info, cc->na, cc->tostore); + } +} + + +static void listfield (LexState *ls, struct ConsControl *cc) { + /* listfield -> exp */ + expr(ls, &cc->v); + checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + cc->na++; + cc->tostore++; +} + + +static void field (LexState *ls, struct ConsControl *cc) { + /* field -> listfield | recfield */ + switch(ls->t.token) { + case TK_NAME: { /* may be 'listfield' or 'recfield' */ + if (luaX_lookahead(ls) != '=') /* expression? */ + listfield(ls, cc); + else + recfield(ls, cc); + break; + } + case '[': { + recfield(ls, cc); + break; + } + default: { + listfield(ls, cc); + break; + } + } +} + + +static void constructor (LexState *ls, expdesc *t) { + /* constructor -> '{' [ field { sep field } [sep] ] '}' + sep -> ',' | ';' */ + 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 */ + checknext(ls, '{'); + do { + lua_assert(cc.v.k == VVOID || cc.tostore > 0); + if (ls->t.token == '}') break; + closelistfield(fs, &cc); + field(ls, &cc); + } 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); + f->is_vararg = 1; + break; + } + default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); + } + } while (!f->is_vararg && testnext(ls, ',')); + } + adjustlocalvars(ls, nparams); + f->numparams = cast_byte(fs->nactvar); + luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ +} + + +static void body (LexState *ls, expdesc *e, int ismethod, int line) { + /* body -> `(' parlist `)' block END */ + FuncState new_fs; + BlockCnt bl; + new_fs.f = addprototype(ls); + new_fs.f->linedefined = line; + open_func(ls, &new_fs, &bl); + checknext(ls, '('); + if (ismethod) { + new_localvarliteral(ls, "self"); /* create 'self' parameter */ + adjustlocalvars(ls, 1); + } + parlist(ls); + checknext(ls, ')'); + statlist(ls); + new_fs.f->lastlinedefined = ls->linenumber; + check_match(ls, TK_END, TK_FUNCTION, line); + codeclosure(ls, e); + close_func(ls); +} + + +static int explist (LexState *ls, expdesc *v) { + /* explist -> 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, int line) { + FuncState *fs = ls->fs; + expdesc args; + int base, nparams; + switch (ls->t.token) { + case '(': { /* funcargs -> `(' [ explist ] `)' */ + luaX_next(ls); + if (ls->t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + explist(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"); + } + } + lua_assert(f->k == VNONRELOC); + base = f->u.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 primaryexp (LexState *ls, expdesc *v) { + /* primaryexp -> 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"); + } + } +} + + +static void suffixedexp (LexState *ls, expdesc *v) { + /* suffixedexp -> + primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + primaryexp(ls, v); + for (;;) { + switch (ls->t.token) { + case '.': { /* fieldsel */ + fieldsel(ls, v); + break; + } + case '[': { /* `[' exp1 `]' */ + expdesc key; + luaK_exp2anyregup(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, line); + break; + } + case '(': case TK_STRING: case '{': { /* funcargs */ + luaK_exp2nextreg(fs, v); + funcargs(ls, v, line); + break; + } + default: return; + } + } +} + + +static void simpleexp (LexState *ls, expdesc *v) { + /* simpleexp -> NUMBER | STRING | NIL | TRUE | FALSE | ... | + constructor | FUNCTION body | suffixedexp */ + 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"); + 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: { + suffixedexp(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}, /* ^, .. (right associative) */ + {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ + {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ + {2, 2}, {1, 1} /* 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, int limit) { + BinOpr op; + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) { + int line = ls->linenumber; + luaX_next(ls); + subexpr(ls, v, UNARY_PRIORITY); + luaK_prefix(ls->fs, uop, v, line); + } + 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; + int line = ls->linenumber; + 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, line); + 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 void block (LexState *ls) { + /* block -> statlist */ + FuncState *fs = ls->fs; + BlockCnt bl; + enterblock(fs, &bl, 0); + statlist(ls); + 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 an upvalue/local variable, the +** upvalue/local variable is begin used in a previous assignment to a +** table. If so, save original upvalue/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) { /* check all previous assignments */ + if (lh->v.k == VINDEXED) { /* assigning to a table? */ + /* table is the upvalue/local being assigned now? */ + if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { + conflict = 1; + lh->v.u.ind.vt = VLOCAL; + lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ + } + /* index is the local being assigned? (index cannot be upvalue) */ + if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { + conflict = 1; + lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) { + /* copy upvalue/local value to a temporary (in position 'extra') */ + OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, op, extra, v->u.info, 0); + luaK_reserveregs(fs, 1); + } +} + + +static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { + expdesc e; + check_condition(ls, vkisvar(lh->v.k), "syntax error"); + if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ + struct LHS_assign nv; + nv.prev = lh; + suffixedexp(ls, &nv.v); + if (nv.v.k != VINDEXED) + check_conflict(ls, lh, &nv.v); + checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, + "C levels"); + assignment(ls, &nv, nvars+1); + } + else { /* assignment -> `=' explist */ + int nexps; + checknext(ls, '='); + nexps = explist(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 gotostat (LexState *ls, int pc) { + int line = ls->linenumber; + TString *label; + int g; + if (testnext(ls, TK_GOTO)) + label = str_checkname(ls); + else { + luaX_next(ls); /* skip break */ + label = luaS_new(ls->L, "break"); + } + g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); + findlabel(ls, g); /* close it if label already defined */ +} + + +/* check for repeated labels on the same block */ +static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { + int i; + for (i = fs->bl->firstlabel; i < ll->n; i++) { + if (luaS_eqstr(label, ll->arr[i].name)) { + const char *msg = luaO_pushfstring(fs->ls->L, + "label " LUA_QS " already defined on line %d", + getstr(label), ll->arr[i].line); + semerror(fs->ls, msg); + } + } +} + + +/* skip no-op statements */ +static void skipnoopstat (LexState *ls) { + while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) + statement(ls); +} + + +static void labelstat (LexState *ls, TString *label, int line) { + /* label -> '::' NAME '::' */ + FuncState *fs = ls->fs; + Labellist *ll = &ls->dyd->label; + int l; /* index of new label being created */ + checkrepeated(fs, ll, label); /* check for repeated labels */ + checknext(ls, TK_DBCOLON); /* skip double colon */ + /* create new entry for this label */ + l = newlabelentry(ls, ll, label, line, fs->pc); + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ + /* assume that locals are already out of scope */ + ll->arr[l].nactvar = fs->bl->nactvar; + } + findgotos(ls, &ll->arr[l]); +} + + +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_jumpto(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 */ + statlist(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + condexit = cond(ls); /* read condition (inside scope block) */ + if (bl2.upval) /* upvalues? */ + luaK_patchclose(fs, condexit, bl2.nactvar); + leaveblock(fs); /* finish scope */ + luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ + leaveblock(fs); /* finish loop */ +} + + +static int exp1 (LexState *ls) { + expdesc e; + int reg; + expr(ls, &e); + luaK_exp2nextreg(ls->fs, &e); + lua_assert(e.k == VNONRELOC); + reg = e.u.info; + return reg; +} + + +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); + if (isnum) /* numeric for? */ + endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); + else { /* generic for */ + luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); + luaK_fixline(fs, line); + endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); + } + luaK_patchlist(fs, endfor, prep + 1); + luaK_fixline(fs, line); +} + + +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)"); + new_localvarliteral(ls, "(for limit)"); + new_localvarliteral(ls, "(for step)"); + new_localvar(ls, varname); + checknext(ls, '='); + exp1(ls); /* initial value */ + checknext(ls, ','); + exp1(ls); /* limit */ + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ + luaK_codek(fs, 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 explist forbody */ + FuncState *fs = ls->fs; + expdesc e; + int nvars = 4; /* gen, state, control, plus at least one declared var */ + int line; + int base = fs->freereg; + /* create control variables */ + new_localvarliteral(ls, "(for generator)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for control)"); + /* create declared variables */ + new_localvar(ls, indexname); + while (testnext(ls, ',')) { + new_localvar(ls, str_checkname(ls)); + nvars++; + } + checknext(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, 3, explist(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 void test_then_block (LexState *ls, int *escapelist) { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + BlockCnt bl; + FuncState *fs = ls->fs; + expdesc v; + int jf; /* instruction to skip 'then' code (if condition is false) */ + luaX_next(ls); /* skip IF or ELSEIF */ + expr(ls, &v); /* read condition */ + checknext(ls, TK_THEN); + if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { + luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ + enterblock(fs, &bl, 0); /* must enter block before 'goto' */ + gotostat(ls, v.t); /* handle goto/break */ + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ + leaveblock(fs); + return; /* and that is it */ + } + else /* must skip over 'then' part if condition is false */ + jf = luaK_jump(fs); + } + else { /* regular case (not goto/break) */ + luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ + enterblock(fs, &bl, 0); + jf = v.f; + } + statlist(ls); /* `then' part */ + leaveblock(fs); + if (ls->t.token == TK_ELSE || + ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ + luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ + luaK_patchtohere(fs, jf); +} + + +static void ifstat (LexState *ls, int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + FuncState *fs = ls->fs; + int escapelist = NO_JUMP; /* exit list for finished parts */ + test_then_block(ls, &escapelist); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) + test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ + if (testnext(ls, TK_ELSE)) + block(ls); /* `else' part */ + check_match(ls, TK_END, TK_IF, line); + luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ +} + + +static void localfunc (LexState *ls) { + expdesc b; + FuncState *fs = ls->fs; + new_localvar(ls, str_checkname(ls)); /* new local variable */ + adjustlocalvars(ls, 1); /* enter its scope */ + body(ls, &b, 0, ls->linenumber); /* function created in next register */ + /* debug information will only see the variable after this point! */ + getlocvar(fs, b.u.info)->startpc = fs->pc; +} + + +static void localstat (LexState *ls) { + /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */ + int nvars = 0; + int nexps; + expdesc e; + do { + new_localvar(ls, str_checkname(ls)); + nvars++; + } while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist(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 {fieldsel} [`:' NAME] */ + int ismethod = 0; + singlevar(ls, v); + while (ls->t.token == '.') + fieldsel(ls, v); + if (ls->t.token == ':') { + ismethod = 1; + fieldsel(ls, v); + } + return ismethod; +} + + +static void funcstat (LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + int ismethod; + expdesc v, b; + luaX_next(ls); /* skip FUNCTION */ + ismethod = funcname(ls, &v); + body(ls, &b, ismethod, 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; + suffixedexp(ls, &v.v); + if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ + v.prev = NULL; + assignment(ls, &v, 1); + } + else { /* stat -> func */ + check_condition(ls, v.v.k == VCALL, "syntax error"); + SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ + } +} + + +static void retstat (LexState *ls) { + /* stat -> RETURN [explist] [';'] */ + FuncState *fs = ls->fs; + expdesc e; + int first, nret; /* registers with returned values */ + if (block_follow(ls, 1) || ls->t.token == ';') + first = nret = 0; /* return no values */ + else { + nret = explist(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); + testnext(ls, ';'); /* skip optional semicolon */ +} + + +static void statement (LexState *ls) { + int line = ls->linenumber; /* may be needed for error messages */ + enterlevel(ls); + switch (ls->t.token) { + case ';': { /* stat -> ';' (empty statement) */ + luaX_next(ls); /* skip ';' */ + break; + } + case TK_IF: { /* stat -> ifstat */ + ifstat(ls, line); + break; + } + case TK_WHILE: { /* stat -> whilestat */ + whilestat(ls, line); + break; + } + case TK_DO: { /* stat -> DO block END */ + luaX_next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + break; + } + case TK_FOR: { /* stat -> forstat */ + forstat(ls, line); + break; + } + case TK_REPEAT: { /* stat -> repeatstat */ + repeatstat(ls, line); + break; + } + case TK_FUNCTION: { /* stat -> funcstat */ + funcstat(ls, line); + break; + } + case TK_LOCAL: { /* stat -> localstat */ + luaX_next(ls); /* skip LOCAL */ + if (testnext(ls, TK_FUNCTION)) /* local function? */ + localfunc(ls); + else + localstat(ls); + break; + } + case TK_DBCOLON: { /* stat -> label */ + luaX_next(ls); /* skip double colon */ + labelstat(ls, str_checkname(ls), line); + break; + } + case TK_RETURN: { /* stat -> retstat */ + luaX_next(ls); /* skip RETURN */ + retstat(ls); + break; + } + case TK_BREAK: /* stat -> breakstat */ + case TK_GOTO: { /* stat -> 'goto' NAME */ + gotostat(ls, luaK_jump(ls->fs)); + break; + } + default: { /* stat -> func | assignment */ + exprstat(ls); + break; + } + } + 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); +} + +/* }====================================================================== */ + + +/* +** compiles the main function, which is a regular vararg function with an +** upvalue named LUA_ENV +*/ +static void mainfunc (LexState *ls, FuncState *fs) { + BlockCnt bl; + expdesc v; + open_func(ls, fs, &bl); + fs->f->is_vararg = 1; /* main function is always vararg */ + init_exp(&v, VLOCAL, 0); /* create and... */ + newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ + luaX_next(ls); /* read first token */ + statlist(ls); /* parse main body */ + check(ls, TK_EOS); + close_func(ls); +} + + +Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar) { + LexState lexstate; + FuncState funcstate; + Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ + /* anchor closure (to avoid being collected) */ + setclLvalue(L, L->top, cl); + incr_top(L); + funcstate.f = cl->l.p = luaF_newproto(L); + funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ + lexstate.buff = buff; + lexstate.dyd = dyd; + dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; + luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); + mainfunc(&lexstate, &funcstate); + lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); + /* all scopes should be correctly finished */ + lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); + return cl; /* it's on the stack too */ +} + diff --git a/lua/lparser.h b/lua/lparser.h new file mode 100644 index 0000000..0346e3c --- /dev/null +++ b/lua/lparser.h @@ -0,0 +1,119 @@ +/* +** $Id: lparser.h,v 1.70.1.1 2013/04/12 18:48:47 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 */ + VNONRELOC, /* info = result register */ + VLOCAL, /* info = local register */ + VUPVAL, /* info = index of upvalue in 'upvalues' */ + VINDEXED, /* t = table register/upvalue; idx = index R/K */ + VJMP, /* info = instruction pc */ + VRELOCABLE, /* info = instruction pc */ + VCALL, /* info = instruction pc */ + VVARARG /* info = instruction pc */ +} expkind; + + +#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) +#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) + +typedef struct expdesc { + expkind k; + union { + struct { /* for indexed variables (VINDEXED) */ + short idx; /* index (R/K) */ + lu_byte t; /* table (register or upvalue) */ + lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ + } ind; + int info; /* for generic use */ + lua_Number nval; /* for VKNUM */ + } u; + int t; /* patch list of `exit when true' */ + int f; /* patch list of `exit when false' */ +} expdesc; + + +/* description of active local variable */ +typedef struct Vardesc { + short idx; /* variable index in stack */ +} Vardesc; + + +/* description of pending goto statements and label statements */ +typedef struct Labeldesc { + TString *name; /* label identifier */ + int pc; /* position in code */ + int line; /* line where it appeared */ + lu_byte nactvar; /* local level where it appears in current block */ +} Labeldesc; + + +/* list of labels or gotos */ +typedef struct Labellist { + Labeldesc *arr; /* array */ + int n; /* number of entries in use */ + int size; /* array size */ +} Labellist; + + +/* dynamic structures used by the parser */ +typedef struct Dyndata { + struct { /* list of active local variables */ + Vardesc *arr; + int n; + int size; + } actvar; + Labellist gt; /* list of pending gotos */ + Labellist label; /* list of active labels */ +} Dyndata; + + +/* control of blocks */ +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 BlockCnt *bl; /* chain of current blocks */ + int pc; /* next position to code (equivalent to `ncode') */ + int lasttarget; /* 'label' of last 'jump label' */ + int jpc; /* list of pending jumps to `pc' */ + int nk; /* number of elements in `k' */ + int np; /* number of elements in `p' */ + int firstlocal; /* index of first local var (in Dyndata array) */ + short nlocvars; /* number of elements in 'f->locvars' */ + lu_byte nactvar; /* number of active local variables */ + lu_byte nups; /* number of upvalues */ + lu_byte freereg; /* first free register */ +} FuncState; + + +LUAI_FUNC Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar); + + +#endif diff --git a/lua/lstate.c b/lua/lstate.c new file mode 100644 index 0000000..c7f2672 --- /dev/null +++ b/lua/lstate.c @@ -0,0 +1,323 @@ +/* +** $Id: lstate.c,v 2.99.1.2 2013/11/08 17:45:31 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define lstate_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.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" + + +#if !defined(LUAI_GCPAUSE) +#define LUAI_GCPAUSE 200 /* 200% */ +#endif + +#if !defined(LUAI_GCMAJOR) +#define LUAI_GCMAJOR 200 /* 200% */ +#endif + +#if !defined(LUAI_GCMUL) +#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ +#endif + + +#define MEMERRMSG "not enough memory" + + +/* +** a macro to help the creation of a unique random seed when a state is +** created; the seed is used to randomize hashes. +*/ +#if !defined(luai_makeseed) +#include +#define luai_makeseed() cast(unsigned int, time(NULL)) +#endif + + + +/* +** thread state + extra space +*/ +typedef struct LX { +#if defined(LUAI_EXTRASPACE) + char buff[LUAI_EXTRASPACE]; +#endif + lua_State l; +} LX; + + +/* +** Main thread combines a thread state and the global state +*/ +typedef struct LG { + LX l; + global_State g; +} LG; + + + +#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) + + +/* +** Compute an initial seed as random as possible. In ANSI, rely on +** Address Space Layout Randomization (if present) to increase +** randomness.. +*/ +#define addbuff(b,p,e) \ + { size_t t = cast(size_t, e); \ + memcpy(buff + p, &t, sizeof(t)); p += sizeof(t); } + +static unsigned int makeseed (lua_State *L) { + char buff[4 * sizeof(size_t)]; + unsigned int h = luai_makeseed(); + int p = 0; + addbuff(buff, p, L); /* heap variable */ + addbuff(buff, p, &h); /* local variable */ + addbuff(buff, p, luaO_nilobject); /* global variable */ + addbuff(buff, p, &lua_newstate); /* public function */ + lua_assert(p == sizeof(buff)); + return luaS_hash(buff, p, h); +} + + +/* +** set GCdebt to a new value keeping the value (totalbytes + GCdebt) +** invariant +*/ +void luaE_setdebt (global_State *g, l_mem debt) { + g->totalbytes -= (debt - g->GCdebt); + g->GCdebt = debt; +} + + +CallInfo *luaE_extendCI (lua_State *L) { + CallInfo *ci = luaM_new(L, CallInfo); + lua_assert(L->ci->next == NULL); + L->ci->next = ci; + ci->previous = L->ci; + ci->next = NULL; + return ci; +} + + +void luaE_freeCI (lua_State *L) { + CallInfo *ci = L->ci; + CallInfo *next = ci->next; + ci->next = NULL; + while ((ci = next) != NULL) { + next = ci->next; + luaM_free(L, ci); + } +} + + +static void stack_init (lua_State *L1, lua_State *L) { + int i; CallInfo *ci; + /* initialize stack array */ + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue); + L1->stacksize = BASIC_STACK_SIZE; + for (i = 0; i < BASIC_STACK_SIZE; i++) + setnilvalue(L1->stack + i); /* erase new stack */ + L1->top = L1->stack; + L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; + /* initialize first ci */ + ci = &L1->base_ci; + ci->next = ci->previous = NULL; + ci->callstatus = 0; + ci->func = L1->top; + setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ + ci->top = L1->top + LUA_MINSTACK; + L1->ci = ci; +} + + +static void freestack (lua_State *L) { + if (L->stack == NULL) + return; /* stack not completely built yet */ + L->ci = &L->base_ci; /* free the entire 'ci' list */ + luaE_freeCI(L); + luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ +} + + +/* +** Create registry table and its predefined values +*/ +static void init_registry (lua_State *L, global_State *g) { + TValue mt; + /* create registry */ + Table *registry = luaH_new(L); + sethvalue(L, &g->l_registry, registry); + luaH_resize(L, registry, LUA_RIDX_LAST, 0); + /* registry[LUA_RIDX_MAINTHREAD] = L */ + setthvalue(L, &mt, L); + luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &mt); + /* registry[LUA_RIDX_GLOBALS] = table of globals */ + sethvalue(L, &mt, luaH_new(L)); + luaH_setint(L, registry, LUA_RIDX_GLOBALS, &mt); +} + + +/* +** open parts of the state 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 */ + init_registry(L, g); + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + luaT_init(L); + luaX_init(L); + /* pre-create memory-error message */ + g->memerrmsg = luaS_newliteral(L, MEMERRMSG); + luaS_fix(g->memerrmsg); /* it should never be collected */ + g->gcrunning = 1; /* allow gc */ + g->version = lua_version(NULL); + luai_userstateopen(L); +} + + +/* +** preinitialize a state with consistent values without allocating +** any memory (to avoid errors) +*/ +static void preinit_state (lua_State *L, global_State *g) { + G(L) = g; + L->stack = NULL; + L->ci = NULL; + L->stacksize = 0; + L->errorJmp = NULL; + L->nCcalls = 0; + L->hook = NULL; + L->hookmask = 0; + L->basehookcount = 0; + L->allowhook = 1; + resethookcount(L); + L->openupval = NULL; + L->nny = 1; + L->status = LUA_OK; + L->errfunc = 0; +} + + +static void close_state (lua_State *L) { + global_State *g = G(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_freeallobjects(L); /* collect all objects */ + if (g->version) /* closing a fully built state? */ + luai_userstateclose(L); + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); + luaZ_freebuffer(L, &g->buff); + freestack(L); + lua_assert(gettotalbytes(g) == sizeof(LG)); + (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ +} + + +LUA_API lua_State *lua_newthread (lua_State *L) { + lua_State *L1; + lua_lock(L); + luaC_checkGC(L); + L1 = &luaC_newobj(L, LUA_TTHREAD, sizeof(LX), NULL, offsetof(LX, l))->th; + setthvalue(L, L->top, L1); + api_incr_top(L); + preinit_state(L1, G(L)); + L1->hookmask = L->hookmask; + L1->basehookcount = L->basehookcount; + L1->hook = L->hook; + resethookcount(L1); + luai_userstatethread(L, L1); + stack_init(L1, L); /* init stack */ + lua_unlock(L); + return L1; +} + + +void luaE_freethread (lua_State *L, lua_State *L1) { + LX *l = fromstate(L1); + luaF_close(L1, L1->stack); /* close all upvalues for this thread */ + lua_assert(L1->openupval == NULL); + luai_userstatefree(L, L1); + freestack(L1); + luaM_free(L, l); +} + + +LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { + int i; + lua_State *L; + global_State *g; + LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); + if (l == NULL) return NULL; + L = &l->l.l; + g = &l->g; + L->next = NULL; + L->tt = LUA_TTHREAD; + g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); + L->marked = luaC_white(g); + g->gckind = KGC_NORMAL; + preinit_state(L, g); + g->frealloc = f; + g->ud = ud; + g->mainthread = L; + g->seed = makeseed(L); + g->uvhead.u.l.prev = &g->uvhead; + g->uvhead.u.l.next = &g->uvhead; + g->gcrunning = 0; /* no GC while building state */ + g->GCestimate = 0; + g->strt.size = 0; + g->strt.nuse = 0; + g->strt.hash = NULL; + setnilvalue(&g->l_registry); + luaZ_initbuffer(L, &g->buff); + g->panic = NULL; + g->version = NULL; + g->gcstate = GCSpause; + g->allgc = NULL; + g->finobj = NULL; + g->tobefnz = NULL; + g->sweepgc = g->sweepfin = NULL; + g->gray = g->grayagain = NULL; + g->weak = g->ephemeron = g->allweak = NULL; + g->totalbytes = sizeof(LG); + g->GCdebt = 0; + g->gcpause = LUAI_GCPAUSE; + g->gcmajorinc = LUAI_GCMAJOR; + g->gcstepmul = LUAI_GCMUL; + for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { + /* memory allocation error: free partial state */ + close_state(L); + L = NULL; + } + return L; +} + + +LUA_API void lua_close (lua_State *L) { + L = G(L)->mainthread; /* only the main thread can be closed */ + lua_lock(L); + close_state(L); +} + + diff --git a/lua/lstate.h b/lua/lstate.h new file mode 100644 index 0000000..daffd9a --- /dev/null +++ b/lua/lstate.h @@ -0,0 +1,228 @@ +/* +** $Id: lstate.h,v 2.82.1.1 2013/04/12 18:48:47 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" + + +/* + +** Some notes about garbage-collected objects: All objects in Lua must +** be kept somehow accessible until being freed. +** +** Lua keeps most objects linked in list g->allgc. The link uses field +** 'next' of the CommonHeader. +** +** Strings are kept in several lists headed by the array g->strt.hash. +** +** Open upvalues are not subject to independent garbage collection. They +** are collected together with their respective threads. Lua keeps a +** double-linked list with all open upvalues (g->uvhead) so that it can +** mark objects referred by them. (They are always gray, so they must +** be remarked in the atomic step. Usually their contents would be marked +** when traversing the respective threads, but the thread may already be +** dead, while the upvalue is still accessible through closures.) +** +** Objects with finalizers are kept in the list g->finobj. +** +** The list g->tobefnz links all objects being finalized. + +*/ + + +struct lua_longjmp; /* defined in ldo.c */ + + + +/* extra stack space to handle TM calls and some other extras */ +#define EXTRA_STACK 5 + + +#define BASIC_STACK_SIZE (2*LUA_MINSTACK) + + +/* kinds of Garbage Collection */ +#define KGC_NORMAL 0 +#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ +#define KGC_GEN 2 /* generational collection */ + + +typedef struct stringtable { + GCObject **hash; + lu_int32 nuse; /* number of elements */ + int size; +} stringtable; + + +/* +** information about a call +*/ +typedef struct CallInfo { + StkId func; /* function index in the stack */ + StkId top; /* top for this function */ + struct CallInfo *previous, *next; /* dynamic call link */ + short nresults; /* expected number of results from this function */ + lu_byte callstatus; + ptrdiff_t extra; + union { + struct { /* only for Lua functions */ + StkId base; /* base for this function */ + const Instruction *savedpc; + } l; + struct { /* only for C functions */ + int ctx; /* context info. in case of yields */ + lua_CFunction k; /* continuation in case of yields */ + ptrdiff_t old_errfunc; + lu_byte old_allowhook; + lu_byte status; + } c; + } u; +} CallInfo; + + +/* +** Bits in CallInfo status +*/ +#define CIST_LUA (1<<0) /* call is running a Lua function */ +#define CIST_HOOKED (1<<1) /* call is running a debug hook */ +#define CIST_REENTRY (1<<2) /* call is running on same invocation of + luaV_execute of previous call */ +#define CIST_YIELDED (1<<3) /* call reentered after suspension */ +#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ +#define CIST_STAT (1<<5) /* call has an error status (pcall) */ +#define CIST_TAIL (1<<6) /* call was tail called */ +#define CIST_HOOKYIELD (1<<7) /* last hook called yielded */ + + +#define isLua(ci) ((ci)->callstatus & CIST_LUA) + + +/* +** `global state', shared by all threads of this state +*/ +typedef struct global_State { + lua_Alloc frealloc; /* function to reallocate memory */ + void *ud; /* auxiliary data to `frealloc' */ + lu_mem totalbytes; /* number of bytes currently allocated - GCdebt */ + l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ + lu_mem GCmemtrav; /* memory traversed by the GC */ + lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ + stringtable strt; /* hash table for strings */ + TValue l_registry; + unsigned int seed; /* randomized seed for hashes */ + lu_byte currentwhite; + lu_byte gcstate; /* state of garbage collector */ + lu_byte gckind; /* kind of GC running */ + lu_byte gcrunning; /* true if GC is running */ + int sweepstrgc; /* position of sweep in `strt' */ + GCObject *allgc; /* list of all collectable objects */ + GCObject *finobj; /* list of collectable objects with finalizers */ + GCObject **sweepgc; /* current position of sweep in list 'allgc' */ + GCObject **sweepfin; /* current position of sweep in list 'finobj' */ + GCObject *gray; /* list of gray objects */ + GCObject *grayagain; /* list of objects to be traversed atomically */ + GCObject *weak; /* list of tables with weak values */ + GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ + GCObject *allweak; /* list of all-weak tables */ + GCObject *tobefnz; /* list of userdata to be GC */ + UpVal uvhead; /* head of double-linked list of all open upvalues */ + Mbuffer buff; /* temporary buffer for string concatenation */ + int gcpause; /* size of pause between successive GCs */ + int gcmajorinc; /* pause between major collections (only in gen. mode) */ + int gcstepmul; /* GC `granularity' */ + lua_CFunction panic; /* to be called in unprotected errors */ + struct lua_State *mainthread; + const lua_Number *version; /* pointer to version number */ + TString *memerrmsg; /* memory-error message */ + TString *tmname[TM_N]; /* array with tag-method names */ + struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ +} global_State; + + +/* +** `per thread' state +*/ +struct lua_State { + CommonHeader; + lu_byte status; + StkId top; /* first free slot in the stack */ + global_State *l_G; + CallInfo *ci; /* call info for current function */ + const Instruction *oldpc; /* last pc traced */ + StkId stack_last; /* last free slot in the stack */ + StkId stack; /* stack base */ + int stacksize; + unsigned short nny; /* number of non-yieldable calls in stack */ + unsigned short nCcalls; /* number of nested C calls */ + lu_byte hookmask; + lu_byte allowhook; + int basehookcount; + int hookcount; + lua_Hook hook; + 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) */ + CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ +}; + + +#define G(L) (L->l_G) + + +/* +** Union of all collectable objects +*/ +union GCObject { + GCheader gch; /* common header */ + union TString ts; + union Udata u; + union Closure cl; + struct Table h; + struct Proto p; + struct UpVal uv; + struct lua_State th; /* thread */ +}; + + +#define gch(o) (&(o)->gch) + +/* macros to convert a GCObject into a specific value */ +#define rawgco2ts(o) \ + check_exp(novariant((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 gco2lcl(o) check_exp((o)->gch.tt == LUA_TLCL, &((o)->cl.l)) +#define gco2ccl(o) check_exp((o)->gch.tt == LUA_TCCL, &((o)->cl.c)) +#define gco2cl(o) \ + check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl)) +#define gco2t(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 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))) + + +/* actual number of total bytes allocated */ +#define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt) + +LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); +LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); +LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); +LUAI_FUNC void luaE_freeCI (lua_State *L); + + +#endif + diff --git a/lua/lstring.c b/lua/lstring.c new file mode 100644 index 0000000..af96c89 --- /dev/null +++ b/lua/lstring.c @@ -0,0 +1,185 @@ +/* +** $Id: lstring.c,v 2.26.1.1 2013/04/12 18:48:47 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" + + +/* +** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to +** compute its hash +*/ +#if !defined(LUAI_HASHLIMIT) +#define LUAI_HASHLIMIT 5 +#endif + + +/* +** equality for long strings +*/ +int luaS_eqlngstr (TString *a, TString *b) { + size_t len = a->tsv.len; + lua_assert(a->tsv.tt == LUA_TLNGSTR && b->tsv.tt == LUA_TLNGSTR); + return (a == b) || /* same instance or... */ + ((len == b->tsv.len) && /* equal length and ... */ + (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ +} + + +/* +** equality for strings +*/ +int luaS_eqstr (TString *a, TString *b) { + return (a->tsv.tt == b->tsv.tt) && + (a->tsv.tt == LUA_TSHRSTR ? eqshrstr(a, b) : luaS_eqlngstr(a, b)); +} + + +unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { + unsigned int h = seed ^ cast(unsigned int, l); + size_t l1; + size_t step = (l >> LUAI_HASHLIMIT) + 1; + for (l1 = l; l1 >= step; l1 -= step) + h = h ^ ((h<<5) + (h>>2) + cast_byte(str[l1 - 1])); + return h; +} + + +/* +** resizes the string table +*/ +void luaS_resize (lua_State *L, int newsize) { + int i; + stringtable *tb = &G(L)->strt; + /* cannot resize while GC is traversing strings */ + luaC_runtilstate(L, ~bitmask(GCSsweepstring)); + if (newsize > tb->size) { + luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); + for (i = tb->size; i < newsize; i++) tb->hash[i] = NULL; + } + /* rehash */ + for (i=0; isize; i++) { + GCObject *p = tb->hash[i]; + tb->hash[i] = NULL; + while (p) { /* for each node in the list */ + GCObject *next = gch(p)->next; /* save next */ + unsigned int h = lmod(gco2ts(p)->hash, newsize); /* new position */ + gch(p)->next = tb->hash[h]; /* chain it */ + tb->hash[h] = p; + resetoldbit(p); /* see MOVE OLD rule */ + p = next; + } + } + if (newsize < tb->size) { + /* shrinking slice must be empty */ + lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); + luaM_reallocvector(L, tb->hash, tb->size, newsize, GCObject *); + } + tb->size = newsize; +} + + +/* +** creates a new string object +*/ +static TString *createstrobj (lua_State *L, const char *str, size_t l, + int tag, unsigned int h, GCObject **list) { + TString *ts; + size_t totalsize; /* total size of TString object */ + totalsize = sizeof(TString) + ((l + 1) * sizeof(char)); + ts = &luaC_newobj(L, tag, totalsize, list, 0)->ts; + ts->tsv.len = l; + ts->tsv.hash = h; + ts->tsv.extra = 0; + memcpy(ts+1, str, l*sizeof(char)); + ((char *)(ts+1))[l] = '\0'; /* ending 0 */ + return ts; +} + + +/* +** creates a new short string, inserting it into string table +*/ +static TString *newshrstr (lua_State *L, const char *str, size_t l, + unsigned int h) { + GCObject **list; /* (pointer to) list where it will be inserted */ + stringtable *tb = &G(L)->strt; + TString *s; + if (tb->nuse >= cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) + luaS_resize(L, tb->size*2); /* too crowded */ + list = &tb->hash[lmod(h, tb->size)]; + s = createstrobj(L, str, l, LUA_TSHRSTR, h, list); + tb->nuse++; + return s; +} + + +/* +** checks whether short string exists and reuses it or creates a new one +*/ +static TString *internshrstr (lua_State *L, const char *str, size_t l) { + GCObject *o; + global_State *g = G(L); + unsigned int h = luaS_hash(str, l, g->seed); + for (o = g->strt.hash[lmod(h, g->strt.size)]; + o != NULL; + o = gch(o)->next) { + TString *ts = rawgco2ts(o); + if (h == ts->tsv.hash && + l == ts->tsv.len && + (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { + if (isdead(G(L), o)) /* string is dead (but was not collected yet)? */ + changewhite(o); /* resurrect it */ + return ts; + } + } + return newshrstr(L, str, l, h); /* not found; create a new string */ +} + + +/* +** new string (with explicit length) +*/ +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { + if (l <= LUAI_MAXSHORTLEN) /* short string? */ + return internshrstr(L, str, l); + else { + if (l + 1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) + luaM_toobig(L); + return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed, NULL); + } +} + + +/* +** new zero-terminated string +*/ +TString *luaS_new (lua_State *L, const char *str) { + return luaS_newlstr(L, str, strlen(str)); +} + + +Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { + Udata *u; + if (s > MAX_SIZET - sizeof(Udata)) + luaM_toobig(L); + u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s, NULL, 0)->u; + u->uv.len = s; + u->uv.metatable = NULL; + u->uv.env = e; + return u; +} + diff --git a/lua/lstring.h b/lua/lstring.h new file mode 100644 index 0000000..260e7f1 --- /dev/null +++ b/lua/lstring.h @@ -0,0 +1,46 @@ +/* +** $Id: lstring.h,v 1.49.1.1 2013/04/12 18:48:47 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_newliteral(L, s) (luaS_newlstr(L, "" s, \ + (sizeof(s)/sizeof(char))-1)) + +#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) + + +/* +** test whether a string is a reserved word +*/ +#define isreserved(s) ((s)->tsv.tt == LUA_TSHRSTR && (s)->tsv.extra > 0) + + +/* +** equality for short strings, which are always internalized +*/ +#define eqshrstr(a,b) check_exp((a)->tsv.tt == LUA_TSHRSTR, (a) == (b)) + + +LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); +LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); +LUAI_FUNC int luaS_eqstr (TString *a, TString *b); +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); +LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); + + +#endif diff --git a/lua/lstrlib.c b/lua/lstrlib.c new file mode 100644 index 0000000..9261fd2 --- /dev/null +++ b/lua/lstrlib.c @@ -0,0 +1,1019 @@ +/* +** $Id: lstrlib.c,v 1.178.1.1 2013/04/12 18:48:47 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" + + +/* +** maximum number of captures that a pattern can do during +** pattern-matching. This limit is arbitrary. +*/ +#if !defined(LUA_MAXCAPTURES) +#define LUA_MAXCAPTURES 32 +#endif + + +/* 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, (lua_Integer)l); + return 1; +} + + +/* translate a relative string position: negative means back from end */ +static size_t posrelat (ptrdiff_t pos, size_t len) { + if (pos >= 0) return (size_t)pos; + else if (0u - (size_t)pos > len) return 0; + else return len - ((size_t)-pos) + 1; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + size_t start = posrelat(luaL_checkinteger(L, 2), l); + size_t end = posrelat(luaL_optinteger(L, 3, -1), l); + if (start < 1) start = 1; + if (end > l) end = 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, i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + char *p = luaL_buffinitsize(L, &b, l); + for (i = 0; i < l; i++) + p[i] = s[l - i - 1]; + luaL_pushresultsize(&b, l); + 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); + char *p = luaL_buffinitsize(L, &b, l); + for (i=0; i> 1) + +static int str_rep (lua_State *L) { + size_t l, lsep; + const char *s = luaL_checklstring(L, 1, &l); + int n = luaL_checkint(L, 2); + const char *sep = luaL_optlstring(L, 3, "", &lsep); + if (n <= 0) lua_pushliteral(L, ""); + else if (l + lsep < l || l + lsep >= MAXSIZE / n) /* may overflow? */ + return luaL_error(L, "resulting string too large"); + else { + size_t totallen = n * l + (n - 1) * lsep; + luaL_Buffer b; + char *p = luaL_buffinitsize(L, &b, totallen); + while (n-- > 1) { /* first n-1 copies (followed by separator) */ + memcpy(p, s, l * sizeof(char)); p += l; + if (lsep > 0) { /* avoid empty 'memcpy' (may be expensive) */ + memcpy(p, sep, lsep * sizeof(char)); p += lsep; + } + } + memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ + luaL_pushresultsize(&b, totallen); + } + return 1; +} + + +static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + size_t posi = posrelat(luaL_optinteger(L, 2, 1), l); + size_t pose = posrelat(luaL_optinteger(L, 3, posi), l); + int n, i; + if (posi < 1) posi = 1; + if (pose > l) pose = l; + if (posi > pose) return 0; /* empty interval; return no values */ + n = (int)(pose - posi + 1); + if (posi + n <= pose) /* (size_t -> int) overflow? */ + return 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 %%%d", l + 1); + 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 == ms->p_end) + luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); + return p+1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a `]' */ + if (p == ms->p_end) + luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); + if (*(p++) == L_ESC && p < ms->p_end) + 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 'g' : res = isgraph(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; /* deprecated option */ + 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 (MatchState *ms, const char *s, const char *p, + const char *ep) { + if (s >= ms->src_end) + return 0; + else { + int c = uchar(*s); + 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 *matchbalance (MatchState *ms, const char *s, + const char *p) { + if (p >= ms->p_end - 1) + luaL_error(ms->L, "malformed pattern " + "(missing arguments to " LUA_QL("%%b") ")"); + 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 (singlematch(ms, 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 (singlematch(ms, 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) { + if (ms->matchdepth-- == 0) + luaL_error(ms->L, "pattern too complex"); + init: /* using goto's to optimize tail recursion */ + if (p != ms->p_end) { /* end of pattern? */ + switch (*p) { + case '(': { /* start capture */ + if (*(p + 1) == ')') /* position capture? */ + s = start_capture(ms, s, p + 2, CAP_POSITION); + else + s = start_capture(ms, s, p + 1, CAP_UNFINISHED); + break; + } + case ')': { /* end capture */ + s = end_capture(ms, s, p + 1); + break; + } + case '$': { + if ((p + 1) != ms->p_end) /* is the `$' the last char in pattern? */ + goto dflt; /* no; go to default */ + s = (s == ms->src_end) ? s : NULL; /* check end of string */ + break; + } + case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ + switch (*(p + 1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p + 2); + if (s != NULL) { + p += 4; goto init; /* return match(ms, s, p + 4); */ + } /* else fail (s == NULL) */ + break; + } + 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)) { + p = ep; goto init; /* return match(ms, s, ep); */ + } + s = NULL; /* match failed */ + break; + } + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': { /* capture results (%0-%9)? */ + s = match_capture(ms, s, uchar(*(p + 1))); + if (s != NULL) { + p += 2; goto init; /* return match(ms, s, p + 2) */ + } + break; + } + default: goto dflt; + } + break; + } + default: dflt: { /* pattern class plus optional suffix */ + const char *ep = classend(ms, p); /* points to optional suffix */ + /* does not match at least once? */ + if (!singlematch(ms, s, p, ep)) { + if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ + p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ + } + else /* '+' or no suffix */ + s = NULL; /* fail */ + } + else { /* matched once */ + switch (*ep) { /* handle optional suffix */ + case '?': { /* optional */ + const char *res; + if ((res = match(ms, s + 1, ep + 1)) != NULL) + s = res; + else { + p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ + } + break; + } + case '+': /* 1 or more repetitions */ + s++; /* 1 match already done */ + /* go through */ + case '*': /* 0 or more repetitions */ + s = max_expand(ms, s, p, ep); + break; + case '-': /* 0 or more repetitions (minimum) */ + s = min_expand(ms, s, p, ep); + break; + default: /* no suffix */ + s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ + } + } + break; + } + } + } + ms->matchdepth++; + return s; +} + + + +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 */ +} + + +/* check whether pattern has no special characters */ +static int nospecials (const char *p, size_t l) { + size_t upto = 0; + do { + if (strpbrk(p + upto, SPECIALS)) + return 0; /* pattern has a special character */ + upto += strlen(p + upto) + 1; /* may have more after \0 */ + } while (upto <= l); + return 1; /* no special chars found */ +} + + +static int str_find_aux (lua_State *L, int find) { + size_t ls, lp; + const char *s = luaL_checklstring(L, 1, &ls); + const char *p = luaL_checklstring(L, 2, &lp); + size_t init = posrelat(luaL_optinteger(L, 3, 1), ls); + if (init < 1) init = 1; + else if (init > ls + 1) { /* start after string's end? */ + lua_pushnil(L); /* cannot find anything */ + return 1; + } + /* explicit request or no special characters? */ + if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { + /* do a plain search */ + const char *s2 = lmemfind(s + init - 1, ls - init + 1, p, lp); + if (s2) { + lua_pushinteger(L, s2 - s + 1); + lua_pushinteger(L, s2 - s + lp); + return 2; + } + } + else { + MatchState ms; + const char *s1 = s + init - 1; + int anchor = (*p == '^'); + if (anchor) { + p++; lp--; /* skip anchor character */ + } + ms.L = L; + ms.matchdepth = MAXCCALLS; + ms.src_init = s; + ms.src_end = s + ls; + ms.p_end = p + lp; + do { + const char *res; + ms.level = 0; + lua_assert(ms.matchdepth == MAXCCALLS); + 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, lp; + const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); + const char *p = lua_tolstring(L, lua_upvalueindex(2), &lp); + const char *src; + ms.L = L; + ms.matchdepth = MAXCCALLS; + ms.src_init = s; + ms.src_end = s+ls; + ms.p_end = p + lp; + for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); + src <= ms.src_end; + src++) { + const char *e; + ms.level = 0; + lua_assert(ms.matchdepth == MAXCCALLS); + 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 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]))) { + if (news[i] != L_ESC) + luaL_error(ms->L, "invalid use of " LUA_QL("%c") + " in replacement string", L_ESC); + 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, int tr) { + lua_State *L = ms->L; + switch (tr) { + 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; + } + default: { /* LUA_TNUMBER or LUA_TSTRING */ + add_s(ms, b, s, e); + return; + } + } + 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, lp; + const char *src = luaL_checklstring(L, 1, &srcl); + const char *p = luaL_checklstring(L, 2, &lp); + int tr = lua_type(L, 3); + size_t max_s = luaL_optinteger(L, 4, srcl+1); + int anchor = (*p == '^'); + size_t 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); + if (anchor) { + p++; lp--; /* skip anchor character */ + } + ms.L = L; + ms.matchdepth = MAXCCALLS; + ms.src_init = src; + ms.src_end = src+srcl; + ms.p_end = p + lp; + while (n < max_s) { + const char *e; + ms.level = 0; + lua_assert(ms.matchdepth == MAXCCALLS); + e = match(&ms, src, p); + if (e) { + n++; + add_value(&ms, &b, src, e, tr); + } + 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; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** STRING FORMAT +** ======================================================= +*/ + +/* +** LUA_INTFRMLEN is the length modifier for integer conversions in +** 'string.format'; LUA_INTFRM_T is the integer type corresponding to +** the previous length +*/ +#if !defined(LUA_INTFRMLEN) /* { */ +#if defined(LUA_USE_LONGLONG) + +#define LUA_INTFRMLEN "ll" +#define LUA_INTFRM_T long long + +#else + +#define LUA_INTFRMLEN "l" +#define LUA_INTFRM_T long + +#endif +#endif /* } */ + + +/* +** LUA_FLTFRMLEN is the length modifier for float conversions in +** 'string.format'; LUA_FLTFRM_T is the float type corresponding to +** the previous length +*/ +#if !defined(LUA_FLTFRMLEN) + +#define LUA_FLTFRMLEN "" +#define LUA_FLTFRM_T double + +#endif + + +/* 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--) { + if (*s == '"' || *s == '\\' || *s == '\n') { + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); + } + else if (*s == '\0' || iscntrl(uchar(*s))) { + char buff[10]; + if (!isdigit(uchar(*(s+1)))) + sprintf(buff, "\\%d", (int)uchar(*s)); + else + sprintf(buff, "\\%03d", (int)uchar(*s)); + luaL_addstring(b, buff); + } + else + luaL_addchar(b, *s); + 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)/sizeof(char)) + 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++) = '%'; + memcpy(form, strfrmt, (p - strfrmt + 1) * sizeof(char)); + form += p - strfrmt + 1; + *form = '\0'; + return p; +} + + +/* +** add length modifier into formats +*/ +static void addlenmod (char *form, const char *lenmod) { + size_t l = strlen(form); + size_t lm = strlen(lenmod); + char spec = form[l - 1]; + strcpy(form + l - 1, lenmod); + form[l + lm - 1] = spec; + form[l + lm] = '\0'; +} + + +static int str_format (lua_State *L) { + int top = lua_gettop(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 = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ + int nb = 0; /* number of bytes in added item */ + if (++arg > top) + luaL_argerror(L, arg, "no value"); + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) { + case 'c': { + nb = sprintf(buff, form, luaL_checkint(L, arg)); + break; + } + case 'd': case 'i': { + lua_Number n = luaL_checknumber(L, arg); + LUA_INTFRM_T ni = (LUA_INTFRM_T)n; + lua_Number diff = n - (lua_Number)ni; + luaL_argcheck(L, -1 < diff && diff < 1, arg, + "not a number in proper range"); + addlenmod(form, LUA_INTFRMLEN); + nb = sprintf(buff, form, ni); + break; + } + case 'o': case 'u': case 'x': case 'X': { + lua_Number n = luaL_checknumber(L, arg); + unsigned LUA_INTFRM_T ni = (unsigned LUA_INTFRM_T)n; + lua_Number diff = n - (lua_Number)ni; + luaL_argcheck(L, -1 < diff && diff < 1, arg, + "not a non-negative number in proper range"); + addlenmod(form, LUA_INTFRMLEN); + nb = sprintf(buff, form, ni); + break; + } + case 'e': case 'E': case 'f': +#if defined(LUA_USE_AFORMAT) + case 'a': case 'A': +#endif + case 'g': case 'G': { + addlenmod(form, LUA_FLTFRMLEN); + nb = sprintf(buff, form, (LUA_FLTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'q': { + addquoted(L, &b, arg); + break; + } + case 's': { + size_t l; + const char *s = luaL_tolstring(L, arg, &l); + if (!strchr(form, '.') && l >= 100) { + /* no precision and string is too long to be formatted; + keep original string */ + luaL_addvalue(&b); + break; + } + else { + nb = sprintf(buff, form, s); + lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ + break; + } + } + default: { /* also treat cases `pnLlh' */ + return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " + LUA_QL("format"), *(strfrmt - 1)); + } + } + luaL_addsize(&b, nb); + } + } + 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}, + {"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); /* table to be metatable for strings */ + lua_pushliteral(L, ""); /* dummy string */ + lua_pushvalue(L, -2); /* copy table */ + lua_setmetatable(L, -2); /* set table as metatable for strings */ + lua_pop(L, 1); /* pop dummy string */ + lua_pushvalue(L, -2); /* get string library */ + lua_setfield(L, -2, "__index"); /* metatable.__index = string */ + lua_pop(L, 1); /* pop metatable */ +} + + +/* +** Open string library +*/ +LUAMOD_API int luaopen_string (lua_State *L) { + luaL_newlib(L, strlib); + createmetatable(L); + return 1; +} + diff --git a/lua/ltable.c b/lua/ltable.c new file mode 100644 index 0000000..5d76f97 --- /dev/null +++ b/lua/ltable.c @@ -0,0 +1,588 @@ +/* +** $Id: ltable.c,v 2.72.1.1 2013/04/12 18:48:47 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 + +#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 "lstring.h" +#include "ltable.h" +#include "lvm.h" + + +/* +** max size of array part is 2^MAXBITS +*/ +#if LUAI_BITSINT >= 32 +#define MAXBITS 30 +#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)) + + +#define dummynode (&dummynode_) + +#define isdummy(n) ((n) == dummynode) + +static const Node dummynode_ = { + {NILCONSTANT}, /* value */ + {{NILCONSTANT, NULL}} /* key */ +}; + + +/* +** hash for lua_Numbers +*/ +static Node *hashnum (const Table *t, lua_Number n) { + int i; + luai_hashnum(i, n); + if (i < 0) { + if (cast(unsigned int, i) == 0u - i) /* use unsigned to avoid overflows */ + i = 0; /* handle INT_MIN */ + i = -i; /* must be a positive value */ + } + return hashmod(t, i); +} + + + +/* +** 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_TLNGSTR: { + TString *s = rawtsvalue(key); + if (s->tsv.extra == 0) { /* no hash? */ + s->tsv.hash = luaS_hash(getstr(s), s->tsv.len, s->tsv.hash); + s->tsv.extra = 1; /* now it has its hash */ + } + return hashstr(t, rawtsvalue(key)); + } + case LUA_TSHRSTR: + return hashstr(t, rawtsvalue(key)); + case LUA_TBOOLEAN: + return hashboolean(t, bvalue(key)); + case LUA_TLIGHTUSERDATA: + return hashpointer(t, pvalue(key)); + case LUA_TLCF: + return hashpointer(t, fvalue(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 signaled 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); + for (;;) { /* check whether `key' is somewhere in the chain */ + /* key may be dead already, but it is ok to use it in `next' */ + if (luaV_rawequalobj(gkey(n), key) || + (ttisdeadkey(gkey(n)) && iscollectable(key) && + deadvalue(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); + if (n == NULL) + luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ + } + } +} + + +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, gkey(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[luaO_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(gkey(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 = luaO_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 */ +} + + +void luaH_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])) + luaH_setint(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))) { + /* doesn't need barrier/invalidate cache, as entry was + already present in the table */ + setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); + } + } + if (!isdummy(nold)) + luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old array */ +} + + +void luaH_resizearray (lua_State *L, Table *t, int nasize) { + int nsize = isdummy(t->node) ? 0 : sizenode(t); + luaH_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 with 2^(i-1) < k <= 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 */ + luaH_resize(L, t, nasize, totaluse - na); +} + + + +/* +** }============================================================= +*/ + + +Table *luaH_new (lua_State *L) { + Table *t = &luaC_newobj(L, LUA_TTABLE, sizeof(Table), NULL, 0)->h; + t->metatable = NULL; + t->flags = cast_byte(~0); + t->array = NULL; + t->sizearray = 0; + setnodevector(L, t, 0); + return t; +} + + +void luaH_free (lua_State *L, Table *t) { + if (!isdummy(t->node)) + luaM_freearray(L, t->node, cast(size_t, sizenode(t))); + luaM_freearray(L, t->array, t->sizearray); + luaM_free(L, t); +} + + +static Node *getfreepos (Table *t) { + while (t->lastfree > t->node) { + t->lastfree--; + 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. +*/ +TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { + Node *mp; + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisnumber(key) && luai_numisnan(L, nvalue(key))) + luaG_runerror(L, "table index is NaN"); + mp = mainposition(t, key); + if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ + Node *othern; + Node *n = getfreepos(t); /* get a free place */ + if (n == NULL) { /* cannot find a free place? */ + rehash(L, t, key); /* grow table */ + /* whatever called 'newkey' take care of TM cache and GC barrier */ + return luaH_set(L, t, key); /* insert key into grown table */ + } + lua_assert(!isdummy(n)); + othern = mainposition(t, gkey(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; + } + } + setobj2t(L, gkey(mp), key); + luaC_barrierback(L, obj2gco(t), key); + lua_assert(ttisnil(gval(mp))); + return gval(mp); +} + + +/* +** search function for integers +*/ +const TValue *luaH_getint (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 short strings +*/ +const TValue *luaH_getstr (Table *t, TString *key) { + Node *n = hashstr(t, key); + lua_assert(key->tsv.tt == LUA_TSHRSTR); + do { /* check whether `key' is somewhere in the chain */ + if (ttisshrstring(gkey(n)) && eqshrstr(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_TSHRSTR: return luaH_getstr(t, rawtsvalue(key)); + case LUA_TNIL: return luaO_nilobject; + case LUA_TNUMBER: { + int k; + lua_Number n = nvalue(key); + lua_number2int(k, n); + if (luai_numeq(cast_num(k), n)) /* index is int? */ + return luaH_getint(t, k); /* use specialized version */ + /* else go through */ + } + default: { + Node *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (luaV_rawequalobj(gkey(n), key)) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; + } + } +} + + +/* +** beware: when using this function you probably need to check a GC +** barrier and invalidate the TM cache. +*/ +TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { + const TValue *p = luaH_get(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else return luaH_newkey(L, t, key); +} + + +void luaH_setint (lua_State *L, Table *t, int key, TValue *value) { + const TValue *p = luaH_getint(t, key); + TValue *cell; + if (p != luaO_nilobject) + cell = cast(TValue *, p); + else { + TValue k; + setnvalue(&k, cast_num(key)); + cell = luaH_newkey(L, t, &k); + } + setobj2t(L, cell, value); +} + + +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_getint(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_getint(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_getint(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 (isdummy(t->node)) /* 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 isdummy(n); } + +#endif diff --git a/lua/ltable.h b/lua/ltable.h new file mode 100644 index 0000000..d69449b --- /dev/null +++ b/lua/ltable.h @@ -0,0 +1,45 @@ +/* +** $Id: ltable.h,v 2.16.1.2 2013/08/30 15:49:41 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.tvk) +#define gval(n) (&(n)->i_val) +#define gnext(n) ((n)->i_key.nk.next) + +#define invalidateTMcache(t) ((t)->flags = 0) + +/* returns the key, given the value of a table entry */ +#define keyfromval(v) \ + (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) + + +LUAI_FUNC const TValue *luaH_getint (Table *t, int key); +LUAI_FUNC void luaH_setint (lua_State *L, Table *t, int key, TValue *value); +LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); +LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); +LUAI_FUNC TValue *luaH_newkey (lua_State *L, 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); +LUAI_FUNC void luaH_resize (lua_State *L, Table *t, int nasize, int nhsize); +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 diff --git a/lua/ltablib.c b/lua/ltablib.c new file mode 100644 index 0000000..6001224 --- /dev/null +++ b/lua/ltablib.c @@ -0,0 +1,283 @@ +/* +** $Id: ltablib.c,v 1.65.1.1 2013/04/12 18:48:47 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_len(L, n)) + + + +#if defined(LUA_COMPAT_MAXN) +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; +} +#endif + + +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 */ + luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); + 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")); + } + } + lua_rawseti(L, 1, pos); /* t[pos] = v */ + return 0; +} + + +static int tremove (lua_State *L) { + int size = aux_getn(L, 1); + int pos = luaL_optint(L, 2, size); + if (pos != size) /* validate 'pos' if given */ + luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); + lua_rawgeti(L, 1, pos); /* result = t[pos] */ + for ( ; pos < size; pos++) { + lua_rawgeti(L, 1, pos+1); + lua_rawseti(L, 1, pos); /* t[pos] = t[pos+1] */ + } + lua_pushnil(L); + lua_rawseti(L, 1, pos); /* t[pos] = nil */ + return 1; +} + + +static void addfield (lua_State *L, luaL_Buffer *b, int i) { + lua_rawgeti(L, 1, i); + if (!lua_isstring(L, -1)) + luaL_error(L, "invalid value (%s) at index %d in table for " + LUA_QL("concat"), luaL_typename(L, -1), i); + luaL_addvalue(b); +} + + +static int tconcat (lua_State *L) { + luaL_Buffer b; + size_t lsep; + int i, last; + const char *sep = luaL_optlstring(L, 2, "", &lsep); + luaL_checktype(L, 1, LUA_TTABLE); + i = luaL_optint(L, 3, 1); + last = luaL_opt(L, luaL_checkint, 4, luaL_len(L, 1)); + luaL_buffinit(L, &b); + for (; i < last; i++) { + addfield(L, &b, i); + luaL_addlstring(&b, sep, lsep); + } + if (i == last) /* add last value (if interval was not empty) */ + addfield(L, &b, i); + luaL_pushresult(&b); + return 1; +} + + +/* +** {====================================================== +** Pack/unpack +** ======================================================= +*/ + +static int pack (lua_State *L) { + int n = lua_gettop(L); /* number of elements to pack */ + lua_createtable(L, n, 1); /* create result table */ + lua_pushinteger(L, n); + lua_setfield(L, -2, "n"); /* t.n = number of elements */ + if (n > 0) { /* at least one element? */ + int i; + lua_pushvalue(L, 1); + lua_rawseti(L, -2, 1); /* insert first element */ + lua_replace(L, 1); /* move table into index 1 */ + for (i = n; i >= 2; i--) /* assign other elements */ + lua_rawseti(L, 1, i); + } + return 1; /* return table */ +} + + +static int 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_len(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; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Quicksort +** (based on `Algorithms in MODULA-3', Robert Sedgewick; +** Addison-Wesley, 1993.) +** ======================================================= +*/ + + +static void set2 (lua_State *L, int i, int j) { + lua_rawseti(L, 1, i); + lua_rawseti(L, 1, j); +} + +static int sort_comp (lua_State *L, int a, int b) { + if (!lua_isnil(L, 2)) { /* function? */ + int res; + lua_pushvalue(L, 2); + lua_pushvalue(L, a-1); /* -1 to compensate function */ + lua_pushvalue(L, b-2); /* -2 to compensate function and `a' */ + lua_call(L, 2, 1); + res = lua_toboolean(L, -1); + lua_pop(L, 1); + return res; + } + else /* a < b? */ + return lua_compare(L, a, b, LUA_OPLT); +} + +static void auxsort (lua_State *L, int l, int u) { + while (l < u) { /* for tail recursion */ + int i, j; + /* sort elements a[l], a[(l+u)/2] and a[u] */ + lua_rawgeti(L, 1, l); + lua_rawgeti(L, 1, u); + if (sort_comp(L, -1, -2)) /* a[u] < a[l]? */ + set2(L, l, u); /* swap a[l] - a[u] */ + else + lua_pop(L, 2); + if (u-l == 1) break; /* only 2 elements */ + i = (l+u)/2; + lua_rawgeti(L, 1, i); + lua_rawgeti(L, 1, l); + if (sort_comp(L, -2, -1)) /* a[i]= 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<=l) luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[j] */ + } + if (j + +#define ltm_c +#define LUA_CORE + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +static const char udatatypename[] = "userdata"; + +LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { + "no value", + "nil", "boolean", udatatypename, "number", + "string", "table", "function", udatatypename, "thread", + "proto", "upval" /* these last two cases are used for tests only */ +}; + + +void luaT_init (lua_State *L) { + static const char *const luaT_eventname[] = { /* ORDER TM */ + "__index", "__newindex", + "__gc", "__mode", "__len", "__eq", + "__add", "__sub", "__mul", "__div", "__mod", + "__pow", "__unm", "__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[ttypenv(o)]; + } + return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); +} + diff --git a/lua/ltm.h b/lua/ltm.h new file mode 100644 index 0000000..7f89c84 --- /dev/null +++ b/lua/ltm.h @@ -0,0 +1,57 @@ +/* +** $Id: ltm.h,v 2.11.1.1 2013/04/12 18:48:47 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_LEN, + TM_EQ, /* last tag method with `fast' access */ + TM_ADD, + TM_SUB, + TM_MUL, + TM_DIV, + TM_MOD, + TM_POW, + TM_UNM, + 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) + +#define ttypename(x) luaT_typenames_[(x) + 1] +#define objtypename(x) ttypename(ttypenv(x)) + +LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; + + +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 diff --git a/lua/lua b/lua/lua new file mode 100755 index 0000000000000000000000000000000000000000..ac0a71bdc6729c7f8ec402b915b4c0f81143c418 GIT binary patch literal 191568 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

+B+k==rpx*cf9`F%=UUmv!e#ry zrI)1Qh#nhPIgg~`h$Mnwx2GVlfpG-*!RP!ywrFk*j9}dxm@`jhs4e#Sa4{v-{#>#K&Q!_#<`FtQ@ld<-9y z+6pB&3=e+|h)v;1y#>hjrIgJv0U`ivC`4wi7`4hDpm0ju| z2Haih56{gb6K7jjT3O&!WRN{ciQzjqG(la6TNSy+Y?HMvetpSX(Lsc`*q0t^fdoL5 z-doi&r4jnnSD?82-cErX0%e>Qnv{ zRle#bd;VznRvLC&4X2(Tv|lhl`)`U5Fbef;-)+pC<4&77n+t|;<~DblcLsmeT+M|W zT=mS1uckfnzFgA-JHF!03r_DUN7{-#heTja3z$NVK0w{FCee3M<(cUWmilX|%0%JK zpH@|bIzd@sbM)jme6*FzghQ}MeJ|hF8U2RdVnahDKtuFD2kRPN=Y>*x-Aqt7uK7!OX-66#*?-mpNHhI5a-b;BG^;_{K!qw-Sq@kPH@G8IV zl~pIW@!G=E&V!PbdKwysAIjOOw!p5o@@xcz zGSPX_*ZIUP!h$TdXu^t{TW}#m={046KgAdG*OLAu>CvC6ohP%yRz_{+T`IEKIn?e7 z*q*CNiG0X^GHmpo9gdxQaRpW6(0<;6i0%lb9yUl7wM*7XMp7Bh-HdoPw6`p@*yRY0 zVz<^Lx_h17-6;Dha8jbH5dPifXu5==PH-aq1>os2CTf=``;c^kTClxOQ{y^CGJk^G zuc$AfNS!5HOL+z>({(qgnX8tbYk|n@j{QMC8UoKDnvPK{?iH)FG%t>^YFKhdM zIotXobK9rPQ0t45p7*ZpQylhCTYLX9Z(3hE`hR)O`m(G4mtR<4_V)j>!un#`Uq-6w z7w2#46qy^jO}<+9Isd{#r5Cl8-0~jZ+QVGM_(z985 zm^6imROFF6bBmTdt=jX~v?jOQgcfl}m^|+-aQb|~Z2%*n+9@7e%L0)kKq}1tj%r52 z=bG2kuG)kzsk9et1lU!cT^4vc0sm{_@c;8Z^k0>6Yi>bh$viZ^_X#!Gn`j>3zDc<& zO!l{m3t8F7OOfftH)0IkMEC_+s>Wvb3-Y_vYlFZ?paRwp z{h4faUSnJnKd-s;`PAHxyDcei;beLU?X$&Qyk!YG)6`yrP)80Bam^A=M^%pZ;>}v< zbl?&3NCLhr3@ff~1jiQ24c@bKBffB2!ykCFhZ*@f&wbXfafgKUX7=`Jp(E+Rb9<7X1&Nk zfL#;L)VAOk(xOjfseC1K+qLh?Ew50>fsuZr@iBUi!4Ej^8F`FefXqpKSe^VJkAff@ z1uNQ_<&XHjNxY!%w13yb81|KPqdy3?g}15gB)r5n*EiL8Lpz%8fQ@n@E#{7f9%{o&vuF zqBhg%TD(8@eKOds49^?@v_kg_X2Ub!=cjHpXuz^~A9p%O_B0H`7E8+;?h~Elqn640 z44Og=C(}L?X1~ZCZpc*|Uf%;#yzne!O}{u<;Etk3xlh>f@WgSdpJp~?qb_l*^?{5w zJaKSP*@lUQpx%PQbN6XhNsA^r(!zli$Di^2sN!M6mI=RZPPs{SMu6NG#=w|Z$d!5l z6hDUdFO^}ehqxaq^Iq70OqxP3c1odN-UfrR2&94I*L$;~Ic>5;sK$uMPxedPvQP5X zVkM!%Afd%*aUQmUj=GPP^YZi7^7-R^`r;ywp4L{La|V_8^lQp|ZRG`2=U|Y=cbsgz zbk#_?)rdZAwt2_RlC%6K0jA_^(c9{*XLBfN{$!+dXPQqW$TE{C{z!Vtd8N*4qdZ+N zcP(G6n#Ma?7_|<1ej!`z(Vh{4VB)Z{=C>ep)A=wcq0N8^0gT!(Z2WoILo9 zjN2a-fTXh+GZ<5(BSIoFw9`YwA*?ojgBM)abB6pD*{#jLdX4jik~ttO+f zd69%RFYH1m;zT9qPEJ%rTwLG=5x)`x^kSISAhuvc($X5_@={sYZQ`MSznaa#YOq71 z?e2{NX<7r8V#KLs3YP{6E!1arEUKkXqmi*Pzo9R$59Z529$^U~f}4aJ;T?O9^$g)k zhUeaRCTS6mWM?@n2RwkPDFtd=mKfC#*D>=;G5a#A*0USj8*}JW{UR5-DZil;hzk)eXbnH%S%tH} z?Wejg?>8ZRZAx%_X8z>~>Ddsk{&94U`5WuSy>TgZg?c6h(Rk`Jm_S~i35||*Z@gY* zj|JFm6EB11kDSL9uQ@wjn@l+yDd&G#8wq1}t??VAp&!6@PW9_zPvZ>=y!y1PH5{jz z-mSYLpOHqXP2>4B&mFkj2u^|2ax&o&CyD(=r!`FNlUG~kh?ESR_2vPxUOjNuMFV8L zec-I$A0TTzY3A#5@tKnTOYmBYTi3+RQ$vjXTN(a_29GI$f5wH5%n8Cf^_jR}rTOYF z*e5fBqaq8aDRhKQw^Ti_>4H2kfymO$%mHSE!mB8(+KfCzd#Mx2f9Uw5mocP$*}-o(Wmb=(X_Q4hBSFSZOv zB7fsO?E7D#Blwj%hw_N3e+U9gC@FvF7oMa;sDZ|<`!t<*O3<5jCYja7TACle3B?O!>g=3al;^UhwN7? z&s6J^{;s)^MAQ748fVJMiGxy;D0-Lt2Ay*1e%PJ0h5^aCc;z)b#03W#Fw|{WAB)QB=kqoz`H;?QeL}I>>MK zjRn$A&$gSqn~!R6UFKnq>VAXM8Xg&7B^w16zN;DonuI-zoI^$CJ@KT|B$*GpIgVVpZCbF~Ecchncri zDXS38O088e0qe5L9j>t1-&^J=2+Il-+6(ZVf$Gy5k3s{Rr>KrH`p8$jVjMm`@Djz~ zGD}n`sB8m9ldIk~(Hd7C_wo@T&G&_?WA#gh#Ks5Hn<|Hpj+SaiFkl$aGCE#9p<9zd;YnfQXvC@Iw@qD{>F0yG4583cih^li1(HG6pVzlAW ztTwg>#i@_gt7ID=usx;rZnVB|SI1|(jv)g%Lv__S$rrviR#Z7C7R+e%42q3M_=0Xg zFam}+nNywtZ;<|(m%)yjgV4uT*eqMX=-1R3;XbvIKlzP6-^_OZf8$T;lX_mJoxb%A zlqPwGqOas+9_9I4TwVSS@{{6ZAD{7;X=OX^% z{H5@-mOMMWAkRF52oQM9v3ci&JVg0>@EFKr#r4_0Fg_PXVdan5GigHMWk}fL0uSCF z5b*ySC973Q81-1QUYflH<_)94P8vWl%GJLJiST@%c>M(~9a% z&xLO3nG{&3Xjdi!x2Q+lg?o^)B?Mt9^1!%!LG;&cKYGR`=KVDOZ%yHFI+HT_;vd8m zdkiBjdaAn5?9)HV3p*yORl#Zn+@YSi!4spmC*(<5!!AZIeyNF7B^nt~Ui)<=xW@be zSK)eEbS=3Q8E?KQ8EJk4>qvR6agpF1OG3joXHVWH3FIiEgP!6Zt?^nCfHIOA2WqA7 zNh;7bRy8aA%agj@;pu}2N#si_C=XX&kq*r)jIp@OqSCztbHVaIML>lQ(OYf?uEG=V zgyU`y(HbYWEjN)iVch{=Q&F7CL0qHjIjmw(I9Zdw4uEi2+??<9XH zb{vQP#wFPMn_aSgItE_iZDyJ)ipwn=L|lc+<25c%(*z7r#4(bRnbDWoh;~rS{0_~V zKci%-yg1&UxIZZT^#dlj01%fV37ONTIn19aZWg&ETbi2!&u(MF&m@8o0>Dqrab$q3 z_7opmf-ihYH2wo)Xd_L+nDE{0fJCn(An4{lQgmS;^fvLXk-H>v^ zSNJr~JL1I7iJl7TO&&d;DNhw~GwpdyJC#=I#59N?Wi9-@&^`yv(KI5B$)L>dJ*gCu z67qYQAIc7cNMw95lv3J&f7^a*(%cJw3Dd?r#56|#Ooy<&9{+HNK zGbCm%ia+uD1x`4T+q_0!IEw@xX2QMf61=rTMnH@%)H4n5F3}jfTw4bM8h(Ye=Naa7 zVXTL{Q&}IR&%5MftXX{se(H<010EE@SO+4r$GY9gN;!La-A5(*r~F|me@Dp9F0ZbSuadVwz=n-dt}XE=UsPdm7O#02D`WfG1`S;Lt> z0UD)%FDz!6Q$R!?R_6bm&vI%1_!NaG$WA8OoJe z1l$R|i0tFk2vogwVU*bKp`-T($N6hUFeplJ+EN0eWoJ7u?$$@Bz*C{43$(_|rK9nD z!i@CJ_eV*If9~q{xs#O8Q3OjC*^%1WYtwzpkFMsswjwRH!&!KYOb5oDkuR<4#3>NU zq*uBs4H%}oR)OB(necw0=x9HmJJiQ=pzwc0Ev`(Ey;gn3?t_6^<+ z4qC8UH5K`%_b~$hrowBL{;}3LgOe#b%m&&j{S(%AoCUPfy7}=M3uvjzJcnB1^Q9*1 zfDCxQ+I;bT5rLwyi~FXfCxl*elF9tyE`b2n(J1Tm8N(+nmYppl%n%R-gmSUexc;?;tV^20Z&pGWUiKXdD~{CTUi{JU0b z`N6eXeqA%3#C?3ilep!5Ib6h>Pk*#PevH$fd{8=+#@6oig&T9!H}78CulO!5?d6)T z&D)X15B{|}%$@3@;RHs|iB9kGEz%*P3z=8Z&wrtH@G@iIGgU63oAy_K&$+XMwY{OGc8teF#QtYAhhvpfSR^CfXClPX2LPG4n z{|tY4MlRz+`RBO#6}>2L^_&}XME;A8Nfz~iBh=i-x9C!))}m93q$kf_zaVhm?RVdn z*nEQ0+-47rUPLN)qxn4ygIs=X%6oQ}da_Jz z^;~ko_}a;Bo=b*~A5Vcyg5e;rWPIsooHaLretYBF<)8G>TaO<80-CZ)->PCi;-B{! z%kBFyi{M%RJiw^8LGOY*i-7bBSrob4#YL`MTtZ`li(7zUZJChmhyikcW6|2LY?87V zH|UMxSe}o9b_Waa8kVd1@E~8S;6Ixfnbx7Lv=i$kfZa%(V#dO_IU<9wQxy{+9c7EDSz}pDL&n z%>$Wso$$%}jRjn4tNB_lqv1nATX~TTr4{F)ZRKV1NU>_9F?x9^nRD!v***eC>uz7G z`$2G4%v|jwBS=JyN4U@93KiUEVUhm6ke3akh{$_>#r(8ZjBuIPOyB~Nx2(F> z@a5so?@CuKZvS~8+)``BZ~+@&elVWVEUw=g`vCNc&;yLw-ojPJc+>|f%45xwgwE4K zqB`j|=2jQ)(swPr$RD0rjgDp!=$*zF!4M7qH6q1l1$(&HLkJQd72yX5L=h^I)$k3c zi=!9OF*Rlu`P$Nv(ld6vt}D$+L`7soU7=jENU+=?+9Mtp6GJizW-Rf#Yx(veGOVnj zy)swor7khqPYa9@Lqoh3B>JQuLR-VUek1cGLuqO`-r{beiQZJSWUpihXx7fhs%Fwg$ei5%IBH8{#_6=h63TO=G6`;u$7gBk8 z`RtS;UaN@hLnK*bwpAq0E;2`oOt4y!JtXQ*xDvq`2`ZAxok+|)$10-21y9h+XGoDE ztH>T%xrA4feQ6Yd@r{{>k&w}`9BHKpg$}>=LL~wkVWV5jQlT3ge`OW5-I*j?`#gkjEmjjCua14DYciNT2GUO@QcxYqzt zN(+@Z0vFUT9_|R7BWjVNbN%8GZ1}kyTEpi8IhI0G z_EoS2^SDsqY;LD_1yC>59^N$#z7Uh8tN zykTgZ`n{3juuIkcW(UWlX|+DT7u%&v1Q zlw5;u*@Uu{Gd|1093!*n#rt z*-QFbOZf~!Lx`)ZOg|w=+Up;5r3bb82ZxD)Q+VR(fIt+n>%>cWFe=+K6=+~X1!jpN zaAqn6vB=^HJ<&Er@T|kkc_%5qO6V)8$gg$n*12_$T1)_IEeq-r*S69D+zf(-IdW#M zuMAJv#*MEhya@D`&TbvM73+W$dl?K+a1~Timsj^~T+{-7OUAN&HY3=$)a<-Wt@L|9 zS+gk2tn|E=#e&Wln^n|-Ye4$oU3>rO^^1l(g2SYJcd<8b>2M?P8i;*qf$6@3E$M`) z>NbLJ2-TOvpw@$sI2d{GIJ97QiGdA!6mF*m-Y&Yka5MrA_p(R@eY<~>s4 zjJN-#JPJNSXe^j}w=s*OcY2ZbH@9+i?yewMK|$@LmpIzTpe*Btb(!R3?iY>-^^|Ch zVzC-|6Fmq0Q4jDiX{>yjm~mWDVI#E_AId6)hYv$LAz>FKJK>M>6tvQ{&3uadlo}?< z{h-#kmJ)(jr|n`bmM_c7QK>-)0eS+8j+upg5gY{RD!dDPr-EMXh1o#v<{0F|-Zb=| z%X-N(#LLOtJT3fJ87HE|YTz%T1ZuA8=s#q6g(sDDUlqj$)Q+Sb1m)}B5T00 zp}IAhTH{AbjfSXUgkh?wTDu{3MSbk-kxk3DIm(#Vkxh|0GRRa|6SRdlY3zK~6xvxj zDyM+IW^Nv;AMO$_rvP-{!OE*A<0~mkK6rHeCAnkXyyz*t=2v>O2Hsf#h{z)r4hKL2X0*i8 zmz*S2bYNt-NfGEr((W6o)*Geht*Q@(#fKXHoR$7eEUvF_s_dY_0Ztk%d>48&Af)U4 zEeF!7(t_&H(d5u6NaE{0=gp<&9hay@-bF{{xH)XT3*%}XH#;MzNsWx)tv3ap78bO6 zU&8{XVsaBcoWowQ;FSP^AKLkH-D?o=IWyp>1m z5cH}3z@^V7saAjVCizi43*W+HYa@FsX7?{Fd8CUn%FZ`Zx7HY?LvW+oT5ri08-P!k zlu2K-MlrUxx0}ca5V&}(jmMU#Md(M38-ROMGN%Bu6If1XXX2_)7$XR3ItU7CS5@`MD)9m>S2b)*=CLeEU@M2SMlg- zvDyRHdI8wAY=B2C0J}1$Ro&jPd#;?^6rQ0fN!>h;3Y%_2>D4^8HqPY#IFzbJZ77|( zgD!5gHdGmCwcma!M&YK{e%dPgDYoep)@8$q{Acf@eT*6WD*(fcg@DyiU9&Sd1Zjha z2Ema9^4Zh_+&a#Eqkg06QQ$;v-J{ZfrVBuPo)OE$jr_t+!K<8k8(S{&5&J^`;3t@< z3+`ZXh`qi1i0ou-#cL3?p(7>k=V^(}^Z~Dt|FR)@J|(2iEUJlbsdzWv)as?$S+pL5v zfw-kgl%RWUeCUA<(7nwPpeiT6fCH`H1K_>>>vz!nGpDOei$2$y>Q>{?BG$n?a)Z3v zc=FWb`a0DDV6SSGGoBGNWiFPrDQ6qnOK%PXm8kQ#GW?7HD^;-_jmHJo;hX3LmFwlkofU^FTwN6w&U z@hSKW7M?a`3eG*1S}`B9j=bPF>D~@LCx-koDVt@6(w3?$&k=2{np8ENjt0Dcv>EZ2mSQYK{0HV<7E%peYdqi1U)4AND=GQcCi4%m^Pk=~|IbqL*OOnxj|X%B z6|GTFoH<6MFwe^>MMQKdy?mSD_`=Vy^JRMJ<+aq30>W2-I_!_;AINJ#ahExc1}FeJ zq0Cv7NkDNlv#n7|&q)L+y zamkdT+L*5bF}ZMzDPnTApG78LS7cNpA=MgpkpU^`kHA9_VK4xmV`U2T%!k|61Z)zH z#w@h4n_87z`$cF^a}+O>ic*6t&uqKYBq}qHby`(iC@+V2VIXro+!XZ&4$(|h{JchDIVeIU#gix*^Bk-~Zjvm=L?Nl)>D zbSrw=+E1A%qozo%R|2So`bD(|#kAvQEpH6<6}4<=#Nddj#j8U3E)nx*eUA*Og-pHU zk%)gC8uu7?qi{4|-B}Wujsmg$Id?}L7#rZOQ zZAdq&t7>YqmEyI#q++Zvx7Tvjdp}!Yv4}Vy{$_9H_G(d-!GX9iw-s4a!d*9zF z|CeGe%J>QhI-Aa=oH~_*!>L5LfS-YEqqA}Er8Q#zB!FaI2WVJd!6NT*j!S#Yg5|;< z1aFQK$fHK7;5n$F6#ubSLD|1gpDZka)!f3oP|t%4FA4R0YoUj>0v9W0=uw#us~i8s zlVEf^^6N=w(u=@Jk)3=K{hd(HVy&^27YnbMrEI3?Pq4E|NNA)J=W>Wqllk9(fDosu z)!!y@#IY>Ef3>BTz=3PU(4#b#t%|Ar7Fk;)+7o{L8VETqhYWtdL zThtIX&849Eo77eQF)zLJky7RRKDEC-NA(Re?@;p*Om4K$U``{{S&#>MACv111VNmE zO==bonh$K1J_~_=kQq8gUi)ZSk_&lsxq6XFRPshqFz``8R83j$L*{b|X|V@odPRdq z&KM~fcmusXt#J(Nr!ot%A*br)bL`THTp#1cI)YY{MdIP?gk?Qwnri5CSJSCA@?P{6 zq-{8mTYy|@sMheftd^+I%d*Ku-%2lvLmlD*9{5=78X6=H>4KAux;4eegX6Syi%%-4 zTN})7EkAikQ~5~>r5eFC(IIL)`ti{5A;Hnw3k$MJf@_0WwfZ$#DvPauZ~Gu!gPM3= zVHX`363EyD_3kjLSjdxQeC)O|)hV|17&FzS_a|Z+bi8%W)GwW6swx8aHcDWow2hCq%md&rFJ?s_98_q8Z6t6xF zS?_nO<5FEH-boR4q4*tDwwtqMpoT@`YS|T~zo|Y_sNjhx)+cOv`l~{GnrmmQ0I5^}_R77*OQb zkxgjiTKUXNu19%(_tJBrCYO3tK6AD8RZVV6p`rMyPrhze7eWbnOT2%{`-qwAxkl&K z3@W0R_<5-!P1Nkwz6O8>%((^}*t z2hEtZ1ndeGpvGLrQmVZ|m)RK}{WI3v{M~$z#m^``NhEP%Gzbb@&Z8Rn2j+F)mdFzM zF0#yp^CperM_VD=WYWp%@htw&I0C?hdR*Fy3f^ol72)BJ(EEf0oEXZ)^Uci?h?0kq z)>9QIyucwv=p>L@5*mvnsMhO^|9LzmY1kRTY1eDvTlZ zizHU@v!sI~tq?6c)JBvo)>XyCd|l^6OecZET#;(2RSt~cJh?xmBJ;f&|DvQIWvk?= zQgWn}yx?owAxm;Nk&no1FTi8aIRq`sVriEjage^SG<0O{!kNfdv=xG7LoK_-R&@p1 zXbxOXhflemx@=ob_eK#?#`YY z()EHrq8BL_rqR6h@W_tnnc^wf5goH$n5yW>>tzO_nTi~ZW(ZS_xVx?yGwme3;nfd8 zTmR;KG>p)ly|=`>e(4Qz0_AXUTChfKZx> z?cE?*(Np&r-sjD4-@%vAS6c89Yjg_R3hh6T6?V7z(@kn|*l(Z{;c353zav%5+1D;K z^Os!cN_{^?%^6e^5jqD@&(`zvkTYvIXTg^$+eS_71lM=hL0RJP-6I1C;a`{9e!B zE&Sci-;b$l2fwL*rMyqK)8tr^Z&Ue;>r1E77x+*Ary`+i(uIbUy(;h{t_o$NR!x;< zYvphv5f!O+>*p2u!O3*9yUlB37q5+6ybdYv)q}2nG?P_UF5VI}TNN@;Xf_bwDuHsS zujiO7QtB+vIM6A|fpr3(b7JF5Uy)shOpVgeVp3tKuH#~^!3=LRCS=CUSIF_~#iX0p zL-g6*hgyZO42-oXt7VRgvvb!Pb+4FBP!js)mi?nVL-*Sm zChKF@F5fRVenwrpc^es8_KrBm(Y(wtbeF{W;5uirp8jW!(O%>$Lz2;$UHcS?>ap(o zQ{iWk9$rF6^+%azNOUE(P%0^Rb0<+-gj;A4$=)Q6>56wPnGtJN3R~yo{+*e>J=1UdzUEb%i2Mv@Eu*MB7B#=KQVql`gLj`>h@ zt01`Q1xM7ghuxv2S@2H9ph`(Poiz(>l(9Mj-vS}*EKvACg)B2W>AgZrt>#4X!vcyl z<7+Nn?nS(EKjM{3<>KYqJ{K=c9n)8ui@}MVcr5YJ66( zVuj88oiD*oB>8TVRgXR}pJ0Ds$?||BI7G&DVE~cq)@ZhUXxH*p3QUrEXw)g47h#dd z8R6cD7=3|xNQgZ75rjkoONip)A!I+GbElFJ6)GaylP}KY8)V7Q&t5b+ZBePSTl8ko zOn5-F5{%h-`kc#MvDV;T@wbj1;gm&)SpvC}<%s!RrL_$CTH|ZfAl>{SGwpssq{4(U z?0x@2})!!b4UdyQ*5HyYHmDC3BH`HA6wKc`lL(88O;8sF+PJiit6+(&6TS z8C@Y8R6%xIg~E1i6$;t44Hi_VSGdS*hN{(6n?D6;*hY&|xIk$!kDTUHAMlM}@#C#S zrSln8MDgC{5BN5aeiw#M?LPfTrExR8yS-YV!fPzN)nD_0rJW`_YUxDw)2-|$$o&V3 zkpJWBarm{g5?6o}m8@TifK5l8D?CN+j&6;j`&rc?Z_uUg;@9d<^R?_}lCs!dh^E+H zA@OXF#YjfdB2Vsev_m6PaX@8@H zSQw-Ki6R{iOI@hnxi9eKmMT7~Zg$u`2u*^_rQbl402P3s91J3C`SCaCypSjE^&D`^ z%#UA^&U@JlRW7AX;J}*AtWEfnO0aWQ3GR>*>Xa~_$;7W#rQ1Z z0X)D#e%f}mCW|E@e9DZ{7yw?C`;{gRzIgHXu2IK1LYbckNRj|#xdZNA zg!f_lOEX`s#dfSM`cCqJVl43}+j&*>TF}<{@gA-6iy_@K^iXdb9as zcPzHj`&*QeJ$=rzzOrK?jD|CAynxxifJQ9Q%n69~x7X>dwg$!JhbZs=QL!U*%ZN-E2zBoGwQ{Q_{u?#+Risz6ei~7@x%h zQ>59M?QLGLi>$|c)=#^&5FH>O5tC^mtqN@+irXC9xRZh8fac7J3`EIC`trlsZXJ6o z3q)!PM4qPvbU3+L9GonRq5Ahvh~*b#l~4c{lzc7y`8uGG0$mK<;%-FnD7O-lx|dW| zJU=*;D{;~s(d+CMSlnwm)yE5i6GS$ZI4`8!8p>HSamXAyjb}xZQD&T7Ch(30HU~MK zA)R`BDo?6R^E0zN0zerzx}dbe)n6386goQSzHEpxlz^0|%zRNuUD5INvxE7Rc?I>;E2el%Y6N2(l@)C=Hv?GrQ#!CrZ`^#k$Lnf zwrg+vVcCE61UMV~ykH zPhi!pqi`#|*+U%P2cWNzh*DC~k%tK)@-c{%uNMOdR+@Rq>p+UWb%4&hXx*#dP3Psw z;&QRZP8fp70Q$p+Z68_W)?d+Q{#A~fuOO~L>Qg4Cr$I2mo;P!>Gsmv4u&RTo7gQufcSG({hO>Xoa#;IGWCKM7vO7`!WR@}@HxrT*@-$79^KyjqHsG{ZcVAEf8{ z+$USTt?2MfLEU4E)nCyzbE5_1ZARN+y{!TFVyky6D>gj`k_GRF#ELS!HhH>_YfLEA zK&>KAQUCvU$kQ(^^7LYxJUx({@BfKDWmH_+c=UN|%o8WeaWof|mAAzBrOEpSJw`bS zXO2nrj1GGQJ6gSOvL^}Ri5`nGOHejNtGvd%EO)peSLr%nPjs@}D7L);>@5FM85Dh> zRQOsK5T;>|c^sgk2WFS`>oMl7r8j2xByeZluN=nQClRTvAxB`;rks>%zqUk_H-mqT zPS|voN(N-_yIj>J$%4C1o=Y8@#iV1?*(oK*Qj%+2lC4|Y_ju<;O6;4XP(~`lNar`H z>(#A0zvjGwIt_B7s|zdh^(O^41=lh(u=!PgSEry7aW;zeiH!J3vIyhd?wTamdRpV3 z=$zm-DQCWhs9vVuf*>{jBFy=^`L`hm|It%&4C`onlKaKfc#YDgkIu_UC?iq&$AL&R z$G$(X^h?Jj^-D)8{n9`ilVV;`EPH-Sbf&yq4Ji;2b*w~hS6%u4xVNnI7E7H+p|>Qw z%DtyM{7?dXr2kDj1bmJw@Y$olXX^scQp|h-zIwf6CB&sjAWoIUl|^brxnWqt1$HGv zAXT917c6xj0*cx<$@-WdLp3Xp4MI<#+n?>r@ANq_H`Nyskhc&1QvP1Vw&>Yvro+7M z1?p8hK|(akj=)81TNxULf@lYbuT8vcC9fxLmI2!w&kAxGyNb|Q!s%|1ngQysHc>Zb z!}*(W?KU9&0 zlCWIaqN#0L*ToI#+RDqwg0qS8d*!#bt-M0L&6c;;avvsmmDVGsrRCC3$$OLhk{2zP zR$RxCvPe>((S1$06)`F*_3}!tC}!gvb~YA8bXCou#B4Q3F-j#bp+7~mpGQd>KHJh| zK+I!H*774wWDfqrS2In8Q^4K4ldU$bpf&VMm8UKAnEdk3*A`l3J+bLR^^!t3$55mm zcTLR0HH0y@stwmyv;5>~Qh8+YcBy%e^Y?N3Qf&9c_7uhJGYAPl{a*)`O8q%$r&70qn(05?MeBuV>}Lvh zQnwa^h~W^VFe<-6O%;Usr0#tZdoO?>xE^bpW;u(jbK*rajoTex_y_f}yo&v8S0kAy z*Ts5Bm)E&f|YaTS#twT-PDii!jB$WCmGFae=e|nSjjN%gE?t zOOvZlHIl2!%B41eDc6ls#D&7D{MP?MHqXRc$128c1J*PS^G^1?UvJ3Grk#3RgbPP8 z%gLsD!U2NgLlz%cl|Bwn`qA^sU%F`R3koyWEmfzkd8pBnaB$9Hlv+(#S7pn}fOC;} z`i*tF=!4(*p}?kv?=mG_e@LabJrsx8IHsNVKVsU#KJ)}EQ6GH!`@j7weEU7VDzVB^ zPSxWZWbY7+Sx#|?^r8i|dw9 z8;5smw)rr3=9un2(hR!;p`rA_R!(;nG+%zDD|k^oArdku96c+g4yj?SBc+b1z3b?= zUkVTV^-h0_nc)jE_dSYY{^Fi zi<;*SPeI`{Nk6I!Svc;u$^ABMt6(uj$?wLMnP*~0i*k_982h@<_@+-k!%{5KC%jx= zJM;x#BlzQZ@NG2`U+l%=ZA<>ZfR>)82DIo>Yb02k^d8I%gobJ`UVTY!X+mHn;~XvW zM1D`?x3|8ZW$!E=jQpW5afc((;-n$Tfe4hfq z#QuZXoiPIPHrDd#Aha@C4rDlwJKu5_c8mXt;+6$_1f!r(Sc;`{%yTAQ#;6_d7Q(d| zV_RSqde>*^6KM^i>*gt0oEbb+SzMD9G=2E{XApABv>QGGDb1UNz#B@~ajqdcv~~U& zq0iD9+qK3IDcDp#H1aOLe&zKw)N?=!y)Q$9uJ#yRXB=uId)+cfH;WrDM@3a>%M za4`a`#VA7!10i%tbNA64-ayXIc0?Xhm3TWm#q*1h(l_6Co_o3Y>%3yw8D8fca1Iigj z=-68e@-RiuQ=YXg3jSNFXR~u8FazVKvU_Rw23*B7BS%c^$E1G=q5niYc~;u|fgeBYz$a&+WeeQ~#D|+U+}EedU!`q-p1i(V_CI#Gk&JZE{0n z^8?`royBc+my7yLXvv6dNIZX*el%dl+89Hd<>gE1^awpmc#{#bDYMoy4h+9XxS}^m zWE~|Y*?A!U#dxfg^m>3|tBXvr7Ymz<57(8#9p!{dT~dFZ#QT}y+UwUx<{BQCsWfsh z@yfxFd02<4+RxFRWmFE^<<{knMjaOk`B!XP1eR2m+|&QQIa`0(ijl&iNt<%Cv!^Rg z(7mrz)!bd=E&jOfCXc>XaOnz0Vd)M1T^Iy^%_}l7Or-hNTERXQIIXy{2#?)$=ZiTU zS$tv7AeU_L1iolvj7$vvPhu_PT!M(JRu~#K8`>^hu{mgQ>9-}-U-Mq=Dy5qaup=Q0 zEpZa3Y=jt$j!nR?1f7kELkFvZSE&Ghg-h@dsJi?HjY*gBn2^$6@mg@U-DPWOs$SW- zmk|>i?iQ3Ch)RzgYQ103N8l(> zQ^V;W^8~16s^-NQB7?fc(in|F&$BsvjE|pVO~BOA=5eXRkY7b4!64_c*>Ykp2j7z$ z!Hj4I>>o8iVS5X@yiLIqriC+q#k3+V^5*pcQTF6Rh*uaDd-8$V7V&m7LQiXa;4>x5 zM>)R39WINNR1_^3E+>hE8%(RnjxJ>5o!>0TZ14!FUiam+mYpEKdEz^=LB1*f z708#Y`&)5nLTC1J1PP#zTRAP>7i;lsi0_6Te?&x=mOC6``HA#FQkRly9bR_#)B!f1 z)L!k$eUFmoTmBG~i%vGeai5X#h+IG;um`P)!Z+I9jelf)SkN@qvsqiYmN&$#OsOem zrD(i}dNznAi=LlL&;7+)w8pdfF`|Et+>vs9|xp|=nI?44; z@b7-Ku|W`@ns-U<#e21eZ4mNue}f?gzCvV&x;(`#9=&auw{Umyk!6JN_2Tm29i`t8 z_GI^@_@@mOIYYa_R)XK5T05OTdsLcoJKuA5LCuDaj$86%uh5(VlPUHP?(RJvXQvS^ zrBJLzSHB=J!fx_KA!QCqfkyj0Mrqs~ia7)G@pzIGS~9F1@bvErn1#)u(qU=AwJfw} z7!f}5AU9?YKlivS{fSl0MqRT-cD$~3wf^9W@buX7BeZ#iwgT{vnVs>EmJOO$9qaj4Y^2#G``Uff7i^bT81sFZ9KotBHgG!+9Cs?3YR z7y(I?vO(bj+432Oa(PXa(^_;x$!dN@|f8j0QufqcNHR;Ro`x!$;DuE(n?e4ROL=3)$dPW8( z`i*h*i-&>Ujcc$w!iyG^xq1F)+_jYpb&gWkxL$?NF3*f!73w)Pg~p4$h6720VioS_ z?gD)OSF}h7;UR!WMvDcE-n~ZE-n6QZ78P<#;SMdOGh8~J?amZjDbxrQfh}Z(`-<<)LKDHRIBHeg8$K-Fw+k}gRT-Z2 zCUOG6L~AJG$QFL3T$X7B6OeJ3XhbZRxFq)OGVsnjtC_h0*N$%q-t*vHv3BN83n^`! z8t7D1zS3^Yj(o0QC_Pw3=QmKNW9NslZ3uSGuBQLn@WZ5&HI1x&?$<-`e)!`oE+fDAB?TRk)DGgcoE9J9O9_intB(BoHt9UbI#g@@gh2 zj+Npd*N-y#*9$qeWflFi=%HzGdWdPZI4eZ_#}a(0B2{etyK68$P! zvw2nvkl^>+;gMH+%ATsY=9@ z(VCYldhF_w>r)<{kiGqojj>L$$Vhe^6SSOSwX4{guMM=^qf(Z8cnW?|>-}}yfQ7vN zPuH6Pe&EqOXl__T!V3Z#ugJ)D;a@kE-alTr8`QHck1K}6eBs{;Etzg}!XcqF@dTnb zjLuMGpZe44$HB7-9eRYU`#A z8`{z|ZCGKm#f>D}m;QkgRd8WU`9eJzD0(Un4OvkjTXX>$TGr4BxmFydJt*e}4&=F;d&QdtvE1jjM1x_rT6iCO9a2guu zNCqE6l{TE=hLa=5V|cKw=Yp+?3$|70xt&%SycxZaU$lC+TrFBGD7-)lI9knZ6cs%*HzMik&~azr49WE?u|-reNNzBsmD!zbWj$6iL!gaz1#h)*>rDyS zuBtFRaXh@3*$A_UCSHkmbttAW6JXxKQbNcw!ICkU3VpPjtw)ES}@=9KZj~w(fs1)p0SW9hM^h-wLTjCbcs| zy4k^F(-%DA#TL3fHD@@Uvo)D>o0apVb;WR{*2En5n44>Eb5)Z9nbM#BF6*0 zbBv4Un4QS+U?NAlwDMJf-SbPyQCTyuLsasbig@uGSJ*P96Xlb>pYwc>+ylY@nyrru zp-{ zXKe4}w)6|6xoDqx|82aeh)SgBWZiQ?kK~q`qtg-%iKxkZAfEeaazhz-I}T6AO42Go z5(ap%D5iJ~n=19#uH~`6xd8v7u`P7JnLy*(_bl!`72M8&m6_?1pgtQ3lxj& zQFWTG8im_)e0usjDzhv?_y^*ppQdzT@PFkcIe1ZT>$3+ZqmV>pc?^Dzs?gel7sPA3RaKA*4O#I|e$~)j zZ1#U>P1E8HnX(CCR%s|=Z9?GSy&tPqi2Zi=tyuMF4~r%+hD)gQ(UvCfE5U;hAt^HJ z&E^x2!Iu9w|8a5{2t=gd9t!gMbNjV}*Y^=d9^~&PVE+{UD)>u$I~YzaS6!W7{No!-tGXDI_4rWi)?+uab*4U>EvR`YZZ*ovL-p z;ny!b@e!3rLcf107~3eZ{6WRad)?K`wY@q|t^RY8itqwvG=s{bmqC*WnVlZ|hPW5R z5w5z#56?8s+WO?81dgXiGtYdNIw9;`5bi{|Lb=`n;Tfs0`>|x?g~D1|X972NiH7 z@~hFlU%@_chw5D3;B{4)I?)liQZYw&N>4V+O^xL;3LidMT&rtBlRCPl48xPuCp?J| z3)*#+kgm{cFMdHW&a(yqOT*`ijX@hx zE@P_o6;ZNe$-#W^EChQUp?zWmu7nC^-BdYBs9TyYLc5SjQ%zR`fFnm6Wj(rQv@1$q z~bt0OhKYey9AUXvmn`!~kBj035;Zq8%1d$QGT`a<)dWPMf-upjTuOB4W3q5by zG-|zW7gk5^sg}xup&W$JgE(ulU|-N83pPk=6e>jqDhmd~c+4L3s83YVw}bh)|g&hr^gC1)MiRgRc-v|YA$?a$9; z#(E_Q4!a&k+gkiDOV#3EVkOApzl*dYx&M06`_-1Q3fM`BS;17N%PMlmBEl+>pbf5d zYvYG#KWdK5mlfEn36a=X&sPz=S?|FBPHGUPRw7-k3I|d1fN$zD@BC0PF4N(avZ{=` z5UCb=FpU?Gf z;040nMPvg@wd$tr_=e%UnrVo26`wrDx_`4${{b$sWH{|o<^r5;8PnLvS5fwwUOOD8 z(`tirS;J=3)b^e(8@Ts})XPATDC3_$Wna^@1-idRVt}rev}IhwzWxr|S#p1;bE-b! zEW_V3S+6{cs;6ZcSGhRHhOZ^YmNPgwRP4|m1-hD9<5U|MX2(ir_|g5=xJ6d@N0z&n ze53FB+A%EEYO%gK`1_OfeTvzT^&KMXJ6QXHG#OdI5g1?Mhsj{c-mN8H%6pY@k>5C@ z&oVdewfODv6izI465eFJ17wM>_wkhV)*6oR)^E)(k?g5!{#;}``4S7>wP6IEF;Dum z*Mc9nQojTlSqmA>r#6{I8z>aKR)0l>YVs>hbnyg1vw`J26H%>i+#P z{-;3Q0lD)Z0d=U;89gxp%AD2zJpia%+gC!vbZ~4X;925V*_N4@b-6eRrjxhcq{*u9#l4$%JArpqUF|Vh0oLdUOi-e(=>)^=HOfuBMNu4Fcq+An9l%8GDq~uY zzAf~j7CM?9m>xO;D&0Ujly*6k+xz%{TMIN1<}XJeh^R}Qiqu~B4sVLorrVWz)SUR1 z%s_c(B8*;-H25MF3%QMRgDeqLHHto!dn1^YV1(&f!+!~a78MB5mX|j7`k}%4wpnPk zIXSgWa|?@!eaT+CL5y_G$Yep;iu$)4$u~#h7*(Ynuu^|-r)mw~B7fBd5*>*cjfzUX zmi@!_Nf5~hJ{673cVpUKp@FBF>=h*uO@81kU z6!q5Cme1f&-IIf~@BNIqw%#pzMb5xDAaFkx;CeVM_#jK@>)vTy7S3I*_D&`Ccl15E z^uI?$3zzjAxP+zm8Ffg)yUbEd8U6Z@|&Mp2> zTcV_!jXb6Z={4O@g=)9RZg43#u^OXHE97`YvZY7J;mTOsXP#M5t zg&m%EfG&Y&ioju}i3CBekXiR6ryf~DeHLM63C-`Lh((Er)UNV^1w}&c{RgCHuQTTB zDUtJq0}x`?n5K4&Md+#>Q)um&LPc4s8(t2}De%%(zs;vEu&ButcuCB+jXx2`5f$-u z0?~1&1FnN}@Z^e+15bW|%j48zm=XJpQVhxyQjT_Wd6SZI1VqXq%ER9Eb|e6{&iXh5 zl1WJAz*VxNwCFkZqE6;WOR1^Dyv(ZUd}^xdki3K4p{++f=xa?{A%pj#Hk1fK8flI% z3}(uIH+O$zBRM1$dk}m`TAQ7wH9R3pWw4X~?d3u^B9Z`t;Qec&;OiIcfy@8r1!J$| zrR){eb^IP2HSa_yp1Qw#tyeYcgQt@m5NHvK^F#~pK}jO)I~qDNR$C!*6Lf0}fPr&) zOb|>8c)~ugv~VxJPIt?vgHb7dTPXzVnWq9oy603^WUtJta4-+_JndxFMilHolPfqx zwCJ=)i0#~>s=z|zL$Cg^JM>Q{0V0DrbfU!^r7)F~Ta`T)-R{|MElVH`lx4TrhSWb$ zhp}l)Nk?e#_3O)x>}=?*O1-XLOu3_Y8v-8_(>Y21$aQR$Xi_>W z4L5_AlVUB3HJ~?68r{1-I^4_#Iai4T0g(?IcRhxBAeh6K?#E}Cff>{1Ea76GyQ?je z*e*bdQC=Nu#|Aerj5Np+4m#mnavTcEf5APz-a?Obie)2ucW;4Dhos%llxT1>A`-yYk`n%E%B09mv2To5UKuys#? zE3#0EGIb5y&TZt`D98G_+P%&hd5SkxbcBL_?469N^_VG~C^Z-oqDED4sgN2=!^LpAx35aMpKJ*pj{MQeCqo4*`wUNejsiS`A=5lD=Tv_mBAaTO`C~+q zu_cFj!tO6Cau?muUu!wUhCh&A>1>V65y(>2&0I~+4ywF2OW)S=_fcJ~$cE)|MyVh> zUyP*jY)`cmK{-x!%Ij=X?u-nuG=0^=X?q$rfl z=I;>j`So3q?Ia~z{hQbkh~hJ?uH#t=u(;NJ4V`{GL#{Ee-XXhS_AmaP81 zNAGU=bdLAN%d5}na`$+Cso}6{awAqJR;rz4VWZ!ml)h9 zOvM^R*pDq8JvHpffoGMN?)Y2ymMj?2Yk6l1Dv5FzIfE`U35nSR_PC|;48qA9%MCF- zD4PjxiHzvl>I`bj_ep;Q(EQH!XeL;o#Sej5ndV(j15&5{A~%-i|7Pq=;G-&%$De@! z;c{>VMMOjaB`6xyxQT!gNpzwU#T674yrQnRE@T8(j^HrLFg|5naamn8 z;sxReJB4Igf+f-7`rsw4sy-w#ilBIpX=I2YRxJ_EV>nncFTmlI!J;}$+6WK^bz+1N7hportMs{Ybs! zg&P9Pr9%hc;baPdKGH4`ZItK?TAhp7T~rVsUc{(HFi-UNUGstuw8SZj+j&muC&B23 z4m<}|B-is>8Rsa_-BodJudbMbRy-ITfdx?0daDeSXW-#Mx3LmipE_vD(m>u`VyH#L zTT})rN~+>b$xnA$#1GrC3{mT#-33bo>XPlHyF`8Hmm_>%y5)T7=lfE~v$CG6Wn!n1 zAZs}5=>ksV;9hvi!G*(Upa#;C<-A)>p;MhVwQH!pafzy_*g*mS56%MufSE_^5E7y# zEKIcHAvum@(cA}d_$R#WTqHe3r!sO@%z;LtAS(lPRaS;LTgsewf>^D=sna zwQXbqbK;8NJ=akrc_puv@pmenQAJps2y9h+IhJ?LP|xgsUOG6}?5;EICfWu(#78l` zb=s2OyP+j95qWw-)p))z4@QYV17{@n0e_ia72iq~UB$9zxxD5AY<{nn%cLpJ2}~g; z!eUtiA8gF*3DUH!LNIAD14GvWYwt5xs>o}|lSD-H0L~& zW|;Lqcd_9ox~y4MYfLfqNF^W3$N1XwobnQ_M`i=QdbVN9*SeG~3y!MDlg})YqA@Kh zsJbbfBOq*EuZPpHMpe|al0j*hP`IxQPa_$WSZ^xoRR0ZL;zss{lyGQddC65%z7QT_ zMX+QDY*@n4ap97Xj4P5rn7|0Z#wXzz*w;RN}RGe#E(Yqv(xZsHQu z{Hnk*s)kcQr8j4@1*cxILki0ZB%>#|^)3LXDNAevmWZ4(dd}js*OKHZWX) zti(>@XsA!-r&j_yjN5=&ttf%4#V3YB`OW6!P<+i<&hWkrV9WK?uz|ySmrNq~A0@Qe z41bIBEMq$+-CS9{Jh)(eD1erb(CN`Ln2N2++Mh$6;l*|=+$@1r-{CvdO$En=+)V{N z^fcQ18aaDM0I$ar>YINOpRlzoy^5+Pzeu;u!g|P#XcaS(VKgcx*jzf2&z@z=2%nEF zRxziXD~rPk+3h=Ih!}zARytK}{rkPkOScD|ZxF2Df&sO6rSl@3{mY7ZqNWiTcXlEm z$Qm7?#02aNPLW{~OsI5Rry5boocaW#nz@4nhjk1P662^+6hDhVy3Ur-$^#m1DAc-` zfEmIu#RW66r;Qg5E{Jdr?L=zsY#UI%wP&hFW`CDXQ3A*Vdiia$ikc)wh|NS2*F_8| zw28cmz+eE(k!8bh;<{NFnKNo+FQYmezcF(;05TlEc?g0Dd(2Hr+@H`)^ijN_>iCIy zmGwX5d*s8jGaeUGMSM?LA#3&Tz&h!bcMWAmR8)C94!-&(c4B@O;`lh(2qHVCLw#s} zOYXDK^HPcUvh?b*!iLJ~j|pTc!0*oe z>GBt5AS`?rO51qq@=_xw&t2Fg>*7s`gUg_*|9q;lhWy^B6glY*dT?KTUFq`3o5^A- z2rhU})Jv%4h=taoVHXM>%p9vGc@Zi5$ymNm#xwSpQF%7STqh@cI8dKFb${7|F{v(# zfMg8sKjSs~WW0R;8GpA=#+&w^@gb6>*K?|eeUpj(=U;K4{PldG;cyS~ijiKXhv_Hh zW1h&urHsp1h#tx1=EZE47(~gnTHihyPi1Jx%_vcO`+<1eJ{gZD1>rtkErvO~sKroo zMDk(z!04`)z}>v4B`}5uu&<0(Fq3Hy+KjRF!FvKc`NsplI<@15PKqe3!$^5ik-W=w zZ+Xc#SZChXK2CMnHw~J>;-+SUYY8SO$x(eeooiXOF#3BUcMgr-#s4UIwM(%H0(x@hXs|F zdLyCTqxV96&a<%5LPotKP~CL9S9HV1gR0zB0MY>PLqik$({l7lPe zY!6;hZ+=xT*36|9l3Yd7s1;IUhu*1>uNEeMdC4OWT+0Bh<@gNRo!Xik1g;thm=&VE z=;J&M#Y%q8va1g`mPcN)jx>KCCx#Uitt=ZjtRTX{g*1*)Vu>lix5el^lXF8VN~EP? zm%kf~;m^)Xbd9g8Pqv2fd8s*q97S=<3{Fj8D=^H{#BWGJuvDYGg<30IRi8gC`51-# z)o1IJ`)g9&_Wy0|MuAwxpa>poB4;EHkFRCS@8h9RRTQ_<>C_Y`3dbo5Rn1T!@T9|( zR2%R@@v5^(t=m_=Q|lK08)=|Ti;_=~hW|$09PzLiuAFXJQS!eV|Lkc8Y`g-GZ%Upk zu$}VOh>M;0UdoZUKvy$CemzSIM3YC7S+J0Cke)5jky*yf%!GPUH)hc?2eZIBC@>5y zNdQ6>rdUz(BZSYI{|AR!vL?bbQA%x<=l@f%OIIAQSFDn7tAa6$_uyzppj(E`lw zLAaZ}Bb>w^f6*}f@VYrZad%J79^RVf4lZ>-GH9{ZG-9iSvK~x)YAAjPj#pfc=M@AO zFd5J&AlXxyiJugBq4*@6W2}S5*h#c?X%0U>QDt2=f6Dh)}chqp1-zj)T3sN23{qyQ!TE!}URq*Ve zJpHrX{PL=FUHfq1wotr%I54)LD$rO}_*3L>1L{(+;ieSRO86`%$SD&~Am2f0`QpFl`+KYR+8TxHL>!dC0JUNX1((saI z^p)dRWGWy|lP}B_ZPRI|!x6E%_}a+VRqz&^KVDj9nHSaRFwG%ZbrS2ky>ZwSM z1ZfSx#LOn3ayrn#Hpggk@F@jQn=ni&(zy2qqD{C3z8|uw#bj>3M^OMi}3J zka*=6u)BC<_BxE}ZkDpNhWmmkn|y>Pk3VOwrKqi8I58YlIi4z0cMiHWQel(NBl#7v z6}bP9FQXQVY!WhDROg{~1UZ=AQFf3;cQG*2=0SY?ss0H^j*zvW+Dpbvvx8)A#xJ#t z+E6mDrnAj|^=hh?ldR19Z)j!a)&J~GAFr%O4m>LBKaq6iS@hv9v!}K8Tx^7`(KyX= zKTB?S`HF8qgY^no2tID)~mj z4V;7E725)OD4BC)35L%?`xl{bYA`^COAYajTq(#^8+5?UpqQ#a6cmtCe3AWbKb|ii zIRLBG<(g_MbBZs>z`)JQEEq5{Y1AbEiEQr#iKOY7_#xANfkc!Luj0qIw!c#a?*fm%<0lk% z=IYPPIg*$d{0}3D$==FMAtyFNzr{rRuxS#F9}Dr=5F^?!T?EDrdb&j?p6DK>2qaWF zct2k_rRG#fc-uSv&t@gvm#CV?>34?-ef8rAR;4yVmeHsPy%3~AlJ(Th)0e6u86qgy zlWm$L#ak^Khu*}kvu}GNAy!D(Y zmE~aaU#};3nPWjwYFPX7*0dgRX--9hR5+6u8exUKHf_ie$~G*(TegvFC&LJYytAN$ zd;(jQc1l+FlYzU5K#+j=2WYb4V|I%L>RPGg((0y3E$uQa|zjgr)0K|&H6Q+$X-9&J(`JHO@l-0dqrbUP znpnLfH5?!Amy_9z7yyyz?#YpS&H(7d5pJ!53qDP?;lp=tGF7iV1j)$95*a9o zh!`>H&u9+ac2|Ph&g345l*)^+qJTQ@O_!(C%FzB2`);dO9m9la<5nk-tqGTW@twVy z^E&+Y*vDmh-<)~)HHa2p&PFn^vZ|<2JZmR{38-?&q=&#R^Rz2{z)ruSxQ~B9M5sYB zDcjHbw=j7{EFBJ(Z{^a)eJ!p1*oVSzAJ}c@<`O`22Q-WnIbAW?VLo8xnMXM1G9idl zyp_Hq0jtMyS1&rn<`oJ&$ubdVt!5Nz#-Hi&lkPW02fSlzg|);W6&?^Vy`I`Q7pIeb zWjJ724%NHtRcW-0s2O`$R|a7CUNW`%@joo=FU2)lzyR|#^Y>i)60Gl8p==7)2*e$) zD|b<$xNdXuCckPDgJ?)bUzG`caD~%focpxfEJKli;i1}OhUV>FQH(Vq>Rk zl#j=N7#6CZBF*$6@Ll4+@{(|Z68~JF+xWAusgCwr0-JMqXo^j@d!+9 z^GauQr7ixd{q%G7pPnDNJG#8HdG(*la;=oTr5#;?e`SLUe|u4#d`Nx`NYXF2>2Bg0 z621Pth`Z3Cl}MqP^(@M%v?=001x>NrYdUJXgmtCcZzrQ|*U$3A#zVS`gp3MXOf-be zo9Qvp;>pvPaanuMZI4@X55S1ZI+Pfv#hA;sthS&fMYN4-pk??egTI_FW1%o(`^w}a zW8!^U8=d%7UPL=aRHg}21HEMdo9C<+p<_<94S3TdoU4QPAm*6{7`ap){}r~C?( zNzuvjx7!}D=_J(~w_z1j1p6K0!ovBjjXDGI5P$}NcE_OC9{5XOWLos8X+ev?JUa1H ze|shXILl}o&?HnrdsII<#k(vKGg99_r#;Uz0oD_in;-YwtUa0ii++60vRbSeKHq{t z7N7Go_^R}^^*I4}hQq^pzwMy*;I%0?Uezm1u;uN+a0d))gh!i+OdxlC| z)^tR@+R<;lL(Or!C#L|76U2-(G3JDw8RO@i;z&iJ8O-r~i$* z3tWM_$0J?t`GWMncfOa5=fedjIXeS`aD({| z?Na)0#2P_CMlbUT<_B^Yc5dbr!Q-V9EN&(soxqlD*iHtsFBr=$9mKQn%+qvlpt_Sb zgL08p3XQ_1Em&AeXJV;y@xfmN3UW4VYurULS-@R{+laaLe*H!NM}9qo<)hKb3Xlut z%#YxIvFFPaE!)yLb|@KT<;eW!@1B{01<#m%wbdP(m)9{m6i7s<<;nNRZcDOqT61hU zw%19Xwvplwi8(9#qHOkmkUe#{`BtgBoO>E=St)h{IdjD>mp)>Tsr-UJb&U^E)U*Vi zHL5JOFL;`Th~e#~3m~y^CF3jeJv?gD%>Vf&+p0|QOicYXzIWDkb=KjPd zbPh9j@j}geT&G5~MGT265b|zyBINi#b|L5gSwIa=aXU>*n+|hDief8>!IJs)aC6c> zSzahH-)K70^#emJbh}I}Ij8ujda^rRR=v(D#y^-)kaPlOJ=tDq4TG4W(yTvTEkDfL`5c9beX-_K7p>Md=X z=Ha8x|2LV_@bhpn5vLw1KJ?uzWTH8pEW0ctzUFu!%AR+=%xF9urmWZnQ8bQen<~ z$<@bt@OOj20r?|$Q=^>UJh{MpM*+;JnkzYYDqXrFa$IF~Q12T(j5yt3r`mz!zdR6m zzswfaGA~o6EZ&-n1)F+B*f$E8rxZ*(Ih86M`A(DmXmhETmGJ8Z=KZ*TR=S>V>ps|@ zzE^wo$53@kSbb6u)7suYBd1xUPLx9+%(^F-(6XNoe|Arz)Y&n=6y0u}Bd>_+Gh4_( zN!>SQkMu3K{s}RZSeM*NG)EI0bhy%E#8#6h(>e?*lxEKOLpW&xc+^m+MaCbWXgzxA z0J)Mu|K;SD^L4d~A6d~AX1fR~5P-D_smJ3`JQo@;WNgy$XPulbf3M8>Jd$kNh7e7~rM6?9`=2h;We!ES7 z@f15Fz7<&7q!aL_A(qjJ-{wWcENUU^5bBIMnUx~RreuhKrLDs~SfjZ-=zPyJ=o%lB zHZ4Q2pHowXrfoL&00?+At+%`$Lc0Wfvle~I95X4K${0n=gXAGbq2_Q3oe{0uLw;Vz zRm!*b|3=gABt>2h{g*VWV>NpVX~Wh0#OgvU5b)WwWB#40B6*m6W&ecELmoz}r+zJE z`&mS=+2`@(+0J{-HCCVWu%$8<{LQX^L#XGU#-0KS?1%K`4?3T-UKPl&i5PnIh}f7m zG?!qaJs>`kHkk6>yLps`vCpdJI!RIDH$7@UXT5tDqs;g`KulaVcbJO>AVlg+Gbd0N z-}r*oyHz%Vx;2?Of3#A|3jHf=~)s>qv^ZIcvJ<*9R9{; zUVI|hm_Ix&XvmFMa!mXd^Edk*4t&YJ&#J<&DXpO$--oB`mndT&i#;p;iB)Rz%NAcInXUeS z{xlPyjd*SbV*KEv>>i2^%;Tg`XK1GZ?@4*0<%qcnIYT-{WOYys+keqt=!V9RcsCt{ z7btirFIfMOz?*a=KL>P~<|20{_0?I@Lz(tApC5|~>`NAO0GAN;kS9(qXH~WMTGl+^ z4w$H~q4B+l^3VffD~yELa`309i%V^$c`Zy!GD$1X(_wj|dBILSmA+U}%l-l0gWqO_ z8Rvq_kR(sU7S~jkbDiR{OqKHqk@vBtovm;E)834~#LgG=DhIBK+aom(_y_duPDhn- z8o8_&nWG+&iD?95zWAN_w8rT&k#!2b(5Q>3p)z`AUd^>g0R%4OK78bs`$bj1KU+54&yBm`M?avfT@g5?nLD8Y@4l|dA3FJNSc&WpQk@^^ywBcmOLr`z101hs7=ul6&{t$do-38QEB6N#1_Xn zN`ks*XS!n=E#*8bt53)&THtAf2fN2(7&`#x@{4Qlvx`yuQ=#}r^xP@dbtAK8nZFAf zf|E+89h?q+g=DA8S9rSRt7tECB=yUSklb{#c<75@($i`+`>`c$z$IIAjAU1|KS$_z zp+=vwdJTP%ea-q8y!k>1%Y{hL%-&ZHwV#1;is5&YET7n!g9uidK?lovu6&GJGuMfU ziA>@=`Dsv_ohC9FjER9OMiC~5m<*p#xHA5RoS!!JkK_o)pPWMu*1@G{IKF5WKRW+o zCv>mO%*$i>c5+ zi7GCHX*ple4hM9yAy!agzEo(2X3&bJcl%K!Z^9}|ma@X?d~u1pO>iH`Dd^W8OB%QA^O zq>xj54HH_@REEtMKfW`S-gYaZ84pwo0+TSKH*5rt&`0BURNn2n<6L(r$l5QDs5i39 zoO-R#3j8s4on+vf%_a7AED%z9is$>d!OedJ=e{-Lx6FASzqp1v z8-%5x)A4&6qiWHdx*34gYsEYwoHvi={Z~vgr{lmmOpm+&nGfudTw*?bNmX}rcUz`? zyIVzYcS-zXPX0mXR`nf#?W~=g1wGqwC)ywzK2fziBKc*D`T@JGsnB;^~q# zz%8bn$1<%tb#P@hN^6T5ph-d&e>ci#)VzJ_FVuDncn{)qr7hSC!aYjVku#`96*DNE zhemyA+HcZ9zNVk-7wAK(%#rfi&YnkICXuvw>bC7r>Nw9mFfLV5jZ*CzbZJ{70$TC-= z&~~DDLx~Y<6}`>sNNO??44t}w8s>7MmY1K*Z;;tey%ZJeQrkqelBbo_`J+R};d6tI zqz!nF&`kE%nZH;zlFP-no7d%|PW!#Z3s2vBw6%d*_W{@ngNK57SipN7|1riJN>#Lk zd5cM*PuYp%qq%&5)~e^UzZt9~80TYjmD}0P_{*_PG7&rJv~(|dKuf1dybh6`z)aPF>Pn$=9Y6C__Ju7{K{f8}%v;-gc zJA}1C5{dp}-w-F4e7ED*ScIAvY=j%_lkFIh5^LU_jK21A!$WJ#00t-eP*`Dnba#sh z-SpT;XYf3#%@#IqJ|u%G2SRelpQtjGyZIyvFmyrM6o9dulKW%ufm?YGC64@P8RSiH zO8Vdhm@qzI6Dh~>qUJb$iBFJ8#G$s84BvOGr?9$|J$u{QhraP(j~s65vaQ+bz6eHk z)+4NOwqbuIM;s+bMY>}v+fVu#`<-(E^Tm)wS6VD7T$P2yp;Q*UXl&|m*4q;569h+ z3w$b6%jy?dui9&RP=tvHcB3W1VmMuno$2SLAS}BubZSd_MGnOd(vhjr{Ao7D#95w~ zlFI>X*=w|+OJnQDw=FN-T^77xW2$9&V0Uc&WTEs=vfkrmy<{!&UC2lvOPTHhgIqyY z?&6mnU(5+$B+}uEz9q;ASz95ZqSb!4 z!44Cg$SP^d5v6n*awrE~vtR9J{K?9TWB+AEO!E}egv!7Mu)R%_e=rBnkQOfG^ob)8 z@Il8%PCeHdb$lQ-g!-7fy7l!(AfgjLV0*CKuboL=u#sT=9pFExf24z!vmWY};XsNb zjW|7QUU0#{Ayd=i**M(M)S({p(CWR)Umk?xR36PsjyUatQyF<=LrK47vV6agtE9ME z{Ur*NX|@@Fan9lB^|s@>3<)l7h}NxP^Pf-uQL3uWOamA$fvUP_-OBRPO%uz4eYwx( zQiX@LBzI%2;Eav{r;iI#?btB7Xi)jlTT`9277L`02ZW(unkGT6Gj(-nqxs?i$Q4*i zT-v;vcF@861A$H*!J$}EaYbECfozXI{}CmUd5Vvow3PVfJlXS;?a*&-r9VAhL^l44 zjp&stxSXL!$Fry~9`y|?>J??@W5Tah1jTb5p=6Cn1D8Tap6{$r} z_;^15!z^Ov5?2!lD_IMzmCM-5Tz#hjD7t(vV_AQ4&>n0u9m|v}WH^h!`@Z2!EyV%k z&9;xZ-#m1TY*A}A=rPDku(D6zT))2Eba2lInZU^`a!HilLGX$qiKJB1ELo*3K!UG6~jJSKBRDv<$ z?v+E&D1t!enWNz+?*;dc(!8U8cG{DUskjSJ3E4XSvgu zGptp{PLNai%*`+L^sPGqbF*9Cyo>pvtnf-qtA+BXBa0%$a&1KOI>E^37&E(N+k+l-;26N9x zS9zyvItW$YVr+!wKP^?7!ztf1*Add9ocS;7XAH)+qo1KM8aiT`prf{}KDKiFk+Jo6 z9j=&0cOEsl*ZV1be*gQ%kJ@fXbtYUl|NT@dzj59BUk=zoj^O!BD;v#`G}u3eW!68` zf4SEjNlP#Q%3c!^;3S#Ui;E%r_{m+ijZm&Lh?E_@tgLin=E3tOP(WB8hI@$8y3Dgz+@~E2pY3tsvBb9zzhfR^?A;H$yULQQs zOy*nQ`S`a=!3+Q9zyGDOXUfl>lX5_3{0kZRR*-)N1}2~gs-nzg!Im6cXqL7!?afrJ zR7g~Pm0qc&_!07a$sc4XKYB-7D8u@aS6x;oA7DK@L!bM_mW(fLM1!~#YDe|WDD)Cq zGnYacerQggw}I!QPk#juefBTDSL6Wp)5or_$i)P11m%|>iB;K9;oN5T6u4*3e@g`z zo3QI$T*=qP%u%%@C}AJs7cifE-OOg%A3tUM0SaRrhm2C#1n-o_ zWF`aVcBGqhyyJExnLNSY4_W=<)31Ngxx6lW%Df>#>oPrC_m;ZQO~J&yY3>CiUB-;x z!*tqX%xt<@AsGiB#W%=O9zOd?j0H_SlISuHQBpOil4 z9&%g7*jLz6vbu_KANdk_U`NL^vcQ;ZsyUz4GIvvr#pn%nk7SzlBA&)fvyyMptkNHA z#4Bw&FzIBh{dIPG4Tz6>R}v=`(ocV~CDp-`DktGEH$mLHsZ$srBS&%Z8j!xYTP+UZ zk&$j5vHVi94B#c?lVDad=N4oKR&0tKqGH10g0uy?=ysahrZkJ+vGYF>e(Pu&_nzDT zHO=~ea#o^nbvmgD@N%Gz;>s3ziSFFT9 z9`whfOrI?miJfiTea*% zljY0AJTsODmg3gXSBP8+k1@-~i+2f9SI8%!@khLco%xc-`Y&iX*q#bVQ(S9j%+w?V zF@t%h2~bah{hf|o$Ru;EOEE?0yROna0vgr0=e|j^4eJ!#{Su%%&_8YWk+f=EaHo^Kbg>zgyAB;1g|X6X{?jU^mJx)yi~c2JG*}ocW@T|K1Q_ z3V{)A;=qCpY;5!d=>sN2$f3~n&u^112t`zSA1Em z&Ed60O`GNAt-c(SmT&nr?YIy-_WG*O`}y*5cXttalwO+$iQp2e1ktWVlgd%hb1P;lrj~y-oa!DFQx4Jx*k-b zOJ@eT2Rsqxn=OYU#d=OT)I89~X( zJWPgCGt~8pUnDP2OyHYj!kGq<=HDR<4yq5x?4RXI){l9$eSEr%%Z}Xd$^Kva{R98^ zZt}f){sb39LT2VpmskB+Wc?*nE!Tu@G&kGt|MY+VSiUFbds{9GY%LG_v%E+aF>h}X z^uNAa(XZ)6z2n__53z8s^%t7#7K%urd2XSrIFW0rVDdTr4yI@LOH@&U?=kr<^K-uU z@_+9y-xo*jmG4uepPVl3{olo3AZXquHJ;(tcs6Yt>7sdpMRVgUABES-l5S$YyS>-6 zwOQ)@S>}^P;MNG-&A+$J?+GUN2_}t}V6*%sqHc+>lz7oCaa(2Sh8l5EXT*8b7=(W) z&G_a|iV+;oW?H99o%i~^dAVNZ8x4BxI<;A@$Vb@aMPl>JZ^v3n`Ri}#)_=X!e=7A` z5fE)uAy{yAQWlGkeg_uWSpR>zI!1xFv%uf82-(`7f|*gsm#}%nQ^>?ZH)ZUoj2Ui@ z8Lt{S*M9Mhht`Hg>tLm8^w67;$296CrmU1fA-hD=}FUb-`IHd>$0xH<{S1 ze%K0}rfL~HLWOF)xLdS8$(wb0oVjY)nX{5o05&*#Y zEoF2AOHsk{cjNCySLVx*SpH^N{GGDsI|Z@z<-zllDcL0^$oINU8XDr(YHGwz{f-_v z>LImctvqbU;Q)8bnHC*wx;YbXBH3Px+iWV4DQn}TZ8TWF@e=5U4SX+Z>N*3ygseFmSUSj6lyWrhlez;DY`iZBz^ zDe1gdd=hpDsLK~sC<`!>bHryq z`aqS+;H3(}T@)FeTm&y2xPOMxGybkP3GDXQ6(2Jrz=GATxZQPkAzH(*6%hznJ=;Gbn?Hyf!xPxZ6)yID$I zPcyB}s`Rm9U5_2%QH(jatPZs?6J~-zD-(MJ)?F#aK@YNsYHW!w1GiiwD^?rLa^Z+H zF*Dn8b`E*|ZSOn?I_!SdIjuZiW7l>}KkF2;GIk_mx8R`Cw+WG!F}kp_x;2X8@n`Al z#HsaCVN962`p&+B3_AupFtY>CcIvq@H}EV#gk#+Ksk$lFzy%&X{PPjrIV^#fNZAvA z&q|qi9S1G(C9UYzPDxW;mu7eaMu`wseHGuYu_g5DyEpJP(dzGyqa71M>BZ{c zkog3>Q`vA%0eEBD_qL=c};75}YR5w_;LY|UFN0c_{TwB|0KxoKLTtQS+? z>CNhUnxSvs`tqr-c}1OUMGyEZ>TWBF`70{071htlZCKfUD|!rV1>MdAfUiD9xDHD$ zt5vcx*Ib{gy#btI_H5n46|raE3HR@8}dK=mz@D*L1Hm@1j}(tD4ap_Kx~6*vpBPE0t)J9Jh}E)N)ZL_u@q8KZp33M1 zWaB{eTZR9~f?qD0KGTxU7I9#&nlIJL+ItOHXZuDL?_hlXx$7GU68KKc0E_?-4P7aB z=qkQ-d;$_Me-BJO=x(E0i;Cq_3>LolA8)?G8vY)@9-9H%Lq{YZ8E)hg1`uF-0XEE* zd8f-Hsmkd%2D3|SBOT{PP*4M%eo!Nr*pE8%yG87X2?tNuw7oLe?`?O}jC6dN1!~RZ zf4=~_)eQi=k;!PH^Au<+yMF$3vqlhfqYClbS^L378JC4S|A(J7is?8NrMxvVSI+@)k zx{h|!oCn5Aa|mqajyIw|%{AH}8_YoguSvT3`!smW*FWl?2RR2r&oWR1V;Igk%shC2B;(KRcg<@=RAxgGO8(5E)RkQp|?SG?g*w ze8xxX`|XYgn%nrkyFrEiZ}q9uEd4a6hI@{IB)0ewAwoIXm7>+j1t(i5C4*(~;d%mu zx22bYQY1!AieIFIbiZt^KNG&nW$dNR$9vf%qPx6gvo)j5i{ja{UPx1SwX7?^U}n{C z<;1K&q(6`|W^VwYhbHXliqHPbZnoPG4a8$l@W4bRDaU|2W7+4{<-PlqrOh$4C%SZR zTzB4ZDhsDP&LeZCczm{$)d|s-gg!&a@2*pV2`wvha`h==n!6JyRtxn7yA5C$Uuwtr zPaq8x*5-F&rX1aEx4U}%t3bA3NLe5?Z8+;buU`!(ac4S+7u4Pen*Fs6A}z~FLj5k=jt0mqsdXVa&c(TDu|K2>q z$oZ<>DfPo*-9~=8uX0rwQhnljx|LHsp>SxhWE(TY@|$e(sW)fHO!DFS(EDGa=cF+| ztFp2!VCRy62>C#it{p2U4S=UM2}htF?+6bg0sj@p z9TK3cCYbO0Zls!YZL{@GPhYUcD`y*EKU=i{v};{xIO#&pY+-mIuSDyKLe&n7i|)fV zaNp&0mBrK`lZy+(&a+Y`t6#`vUZjcgwN34WuIY9)!`zOgLoC3OeF5HT0Y>WFy=i7R z9gHwri}V~Z+u;Dc={wbVM-=hSjuO=N)*7)gw^)s9o zKG1{u(&nD4;MBLuNJIbsY``fcGIs?I--_TLQ;5zjxQ626Y zm$G@dD+p6zvX&pUF%Jb_*%&zQ>a0!77uP1f0r~gzx%3wh9+jd_mj~{GRZ3gArY^&J z#viNka=+Lvnnn9$lEBX5E#^GNf((~U;tRx|${^^D?%pRT|2ZUJ;w33M@jII7j>v7p z&;qhkeeqzh5SZhh(|*VUn~>A05a|fH=YeoiHIy@3uOcbl5}AwiGKcZPxj669R$!d2 zRA-2BPiSlZv~-;-1t-E>DRysmc^dOUQg!LGFD#tN(w;12_^+EG0A}W&;6qnuX9(Nv zSM>8U|5ETW4ZrXgSHeBE*(V;)vN)vphyfCbpq}omR|w;XDag{}Xg)v_Nl_Z@(Y1$V zl?~;+JtB40y15UIUW7XBu_7uP+)GpB2BF~MQ!tsB2n;^A)^n7f42eYJ9a(#K;P?p6 zkD)D6`TQTKEx9JrGL)|4SZ4Kq9YGNf9W(Er(l!kOntY`UzZ_N%kb_i>Wg1C#J?Fto zNVbLfGWx{juXAN-o#`XEn{~8RK^%a;pw9vbZt3$23lY*cE`0{;hb#|$CLY%u9@@#0 zJO$YQ&1!1eJa>h>%EF1cgf?LJcLS904rj9Ow>1oV8V&4<{y_MrxqkEH^IGb%EcCVO zTvz#=rP|FWpW|)oOUZ8K^G+!1&H;tNbPn+MpQ*@;FP8W_Wq@DQo8=dhuG+vx^BYlC zu2?v&@_{4gxSK%miEdCp*6pgWbOEtc)D{r`zX-iv$>T1%XWNw_4%k;lxg`#mwVkGxx(zZOf};| zS`8I@LO#l8G~>1>untRU=W03*ccVUsoL~@94va9M);}tA&IWD8!wMuK#PTYnJO<*D%f)S85 zkD#$7&-WNg!hM@%PVIEL)t_e!d2)C!v!3bW_s>*U4R7^^3urcg{Drdk+8%tC{N{^G zZLN1S%k0Ic`ruEL{0rUuL;iRED)P(5B8i2uo|}QB1pBfhs8hvO^LrQ4j_Y&L%-XlY zf4=(nz_{iNw^UuTQv1R89m(I#%|GLR=btV43*7uy{qOv@O8)moTKX0J@BD+w&;3BH zI$mRo>|s9pfAvpCf&X_G{+ec)_tW0b;CAzfn}5##&i^d=bNlBpQZoJX8yC{W%^)4H ze@2V6ITL>}gWQtcDM{!Is|OoRkwB4w&uSaYi6PneS<8<{?t{;IO@UeB4dzG}Xv4L+ zRBJY#`S|4>6q?z4i6!=oX2mk~%epWc+@kO(MRG|peuOSM$q8YWhsU{DwTWTa<5r+!G7wy>wxuLsr8M{t*_hvtWS1FWa-}xAh6I@bMwWPWJW0{6k3hfjbBT` zCA@gtB;>OGi)Q-b9R}9i&U}@W41af{3ITklz>?9+<;(-}_e6zvX{##CFex~=SwX8` z-S(LJ5#*|_3*EQ^*hA#*==yKY4At)(9C-J}mFWG+h3LV4b)pbD0MJ9!TynllNLtj4 zkllE(`GOa$C-|9Pp0o{8*4xNHI94XhA4{l!mu2N&BnuKFJ1~uzHe4W&Z1rCmHRBso zkxa&U9xO=_xio)uQ#Qfa6-Gf%a6#+$+brm+OjeCT`(*dqR~G(gKm4Bi6xc`K z^_ToTTzs}N+w|k_t#4|3y>-ojY8n&|x4|^n7nkAG^_SY$e$(=%=Wp;$hl01&T_3!r z)qKpV>w}|OEz;i!b;5${c$RkF*bI#W+k^PGZeVhaagS$f`c#TrPca-htj4ufnFNk} zTxLHKB4fF%FItR6e2xrr6OQ`_R1O7Cs7tkBigUz8f=8?g%SfEDM@O*G7s(r;WOe+Q zcCsuK|z6hxxO} z4LafY{AoOy>(N1}65$`5ba`r#Zd|-VR+{B>_P^tE=?$graz5vwMjKi%7_=Vq6lYpVTj)_* z-$`39mkJy~?~ifzopdgvc4hUiU;YUDoi&n1^Pv4c(EoimMqL?K!%4KaZuq;&X6ok8^pVZfxz#Ogpoq

Fd&@dQCv($qouodjXXm8ap)u#qvECSO)C*}2d#-YabHIf&G~2j4 zq~+3@?zG46U(Aj_09((H$XcAa-8Nc6e+rtl8;Q@gud@5s0Pv^+(ALie2D-^x@@Jt% zDKHHY_1Eufujqfui*Lzo4Jjc~goL1Sp${TCT#w1G6(Ee@`s1_o)Bc$In1$$c`7Lqa zxS0OwXop(u{R#acMvc>P#t5e4gIGY{VSWf}4ym#oPJwJ!dHw^j@j~K3N4WFMvFBRH z!7(c8HqnN7j#Av+Y`0e^Q~&)|k>~VcR8rcU2Pd!|s(VE>;S)v^oSAa(#jDbynikgI zh)PMD{y>nMLDxBJgs=Sw#F|6s3?y|A96i6-IfP9ICd}apnUlnrtt@!AL!0zvd zy;PNwj|RWlFYITAy0CW>jsT1#KU56XXDRF{OCN3m`_ZqJY4?)jZJR@1&1h=L^xD>Q zgllS8%5!<)L5Sw>uQREP{#wEGVJ*B?w4`EDnMMXRj5)!cHhNAn*L!dHo5GOR6NL!5HBGqo@MDp#=zjTm@&Ol|| z;;96Ss6d;`a1qFpyNB-x`@PRq-uG_Q#CO}(9nbc?)G;&5d}(=>?`5+UynkEwpe?%H zH5`;NKP=1APdDx5=%>v3r^Z|VBH;^G?w|XU;3}ce)&p*rvAd#gFm=Yaf;F+|62v;k zmxLNWAzZoiU2YI@MipQ`ZPEB0IX2Uvf#kkVErTJLBB-}M)W}KX9HzT!Osn&q2}J?h zyRr2gOTDzJ6w7XBW$>I;68BuXB6uGTY)r^^DhuDh{HUz{Fcje4k~i;UTV$6;<#Lu2 zzc-UXSC$hma#>|}AQU`jDG0)0qYBcMjUQDuehhG~7TsIcxRLAPIWOlF@zz%`q;S{` zM=V9YQ#bPC7Akyy?hI@q36qdZaQu(W67@Q1M`XprZo&#CJ@p6rli$d`BTNIa7 z$QWwpKN_z&Ty{Vg+17;Jvy)~LM@T{aa#BSk#8A;izs%4z(mg{~KhW*8POw~;} zoy#O@B>57WJ6#vo-+@{`;xLJunimO@iTMJJexHWl( zL#5hP28X^Ac5WmgU=zZ@p-G)SoftVma>AS=0+mihi|CRy(OvDhUbjB%+(7<Tz`BOrH73od6z`tVnA-dT?C%Vi<*Bh_X2bu zq@1dGW$`+&nmdF-*EKJM$j&w2p}b|Pl2CL*17p*`dW?E9L>$dK+S&G_UX<-fv&3D% z&+`1hF&wyoH5vj))!Zazb#7~MFN`OnIrOi#8fW4>d%FJ%5DF>7pB7ytIj$Xp`POJo zL@^FnpL~@ud4J8ZH?gccQ;BRTW5@DCPiLMT(^6S<7_X=zI8|cQIrc3SOsc3kSU{n(OEl zazdS`urAFRsc6qXjeLoPD)r-8R#fW9VVJwS?c#xQZ~Jf_uaZs{LRFL5`CjZszU7t zFPjTSc7ItgrzjY8#c1LE!b!go9;hQs@Scl=|D8obNb_qbp-0KlS^vPF;rS2xYdD+? zdA^|@m7g!GkCxvc>81B+#NASJ@nBqTG?s%U)8l_hr+e`y@7|xJOPc&P|0@FzNqg4) zelTQ}cQ4(0&h`H@86L>EgR0iKE3YT`UQO`VYV#8BG?NJ_h)-e(m(2FclKOD2jk{m_ zY$2nv>;Gg&O2+>=qRvu%5n~S)D!OB#^aO03XZ}SRIz-;lc6sLTfijE1AbfVvPT{8! zb)obU`3hb0IImf9$BOtgz2&sn1^kvd6?^2w)1Cy&wU$FO_t?!|>#kDXwNRH%rJOVW z2J!>TJWTi3E|St$aOy&$Vqqw~A{3XOr9{ridwli~%{zZCq{RT~%UeTi8ZYAb#G^Wc zM{M7^aA0RB?#z-m4rGkS=I|s}A2^F7GZu-|nfxPdV?RbiY#xaK00Kwseq!$K0GUM1 z$faJDX}RM{DwIY<*b@BYND8~4BydHdo~Z3AQq8=>w0CU#UZ8i9f?2LV6?`PG3rGkQ zjHw40H)wqJFh1Gh`K5c+J&ao@@vNYTozLdVf_gRe%Y)?x1{TDa2QZF|VtK~gkq~W5 zM%t)NO*|=eO*+OW-_Tm`3XrhuJn*%#*hyL`b;Dc0(^-!_^KY~S9$1PAlfuwx^D=WQ zUQm5UTWx*AsU&crxU{Pff^3xNpP?Zpw57Jh$Eb6%AD;oSyhK6ZjS16ElHu)7Xo7|Z zniWwYP@~x@ti`^4fm@0TUl{;$2pfhI+7sh02oGE&T^)>mK!2g^#!E8>#_r(9H|~8X zVr4&;P3OcQ)y0}MF;mz9U0j(a%xSO7gL1jH<(FXWMgS-866jDsBm!w!VJ?CSgjBNY zbwyrq>Ievf2U<|AD%`^fZJvEvHa)-lpgxfj47Zx@fg!;K%Te<%wdnV;Lu&UH1!I#rpb?lZ#;czTjXeqvih2FegyCi$bn(-f1_NnRS@(xsw zF@=7m57|(J!|urtX_r|bym4IJ(=LhAU=>C z!S{U0z?JO5f4TAz9{6MtL=4_jjUt64T%{?iH#1e73%4_|vKk|8{;Otl+MKRkyGYc5 zjEXmlYar3;FEXvlxRFJ#F?kYY=o<;lb-#AWlk5Lf|0$ik)#}JUGd_e8a-A9eU!c2_ zZ9NRg##hOFICs7{xI6XR6SLL=$#pMW03>mR%JzuNY}l-%0dNxDgy_UIc{PPXkc>Z; z3C5rvX31&9cTS_Tp`JJvN`D-)IYmevI{n%a1-3vkDYIDdipo7K-)3gz&qVvud2|*2e z?pg_shLa4z~^wx?G*gSz7h(UC3oUZevd->GhHe6VbfxPtfJ(K*nDwPPv`|h{|Vb|~2 zZsDSf&u62X+~fN{ml0Ox0-U+;=#7b@R49#T7q*^c)v_1^ejkfG_oSJo?*yGfW0<(<1 z%iw4Cla1J9S!M*d!1>}CRd#t&Sjg{E+q6HInjH(>IjQ-BmBUSLx%w0yA$7y843&N) zZn$t!K!+~YM?%5!Pq^6^ci5^>>05UmL@&I+l#Ke>2y@W6PR%LlP~j(`z?-C)Svk%^ z&)GUv7%jUWpqYFRV&b-seBaK%wXb|9@(D)55(xa8l_C%*x<>t*IU#A2*NQFN5^d_Bu!}5=5-|cnjk{m-eo}Jg6A3KFt2- zi$y1A^q)*$$Q*V~VCW;3a)-I)6hs9BE%rLyBP-@3B*7WgG7v8P@=l~!TU6wmNm1EPW0L z9Y0&^lvDf?^93zYF5eGEo3#`bsZs13d38@`=A3u!b(7FEYT!f>acByI`o`qwBB4GO z)f955?!c^)n!<(OhXY~+S`utD_W-D>P;Rc2VZTOdPApnT&ho^3X%j=y*%wJIJIp1u zVn6SgbewRQnu{5Ih5XAFJEB0gx3|{thDfT6JvhnHj4=|R@o;@YX+$^9Tw-0n1#gxI z2^qE3QO}0o*m{1Ltn~yRIGVCj*Rw9Uv-}MIWbE(SOpVFp4_HDu{%4h6U6cHPyHsJu z-HDd?W#a9T6o`3uPgL6D)XTs!YrOROP(sv3uL+lK3QqkI4?^-9XdG=iJ~(w2R!_94 ze{kx{Jh0c1+0-1SR&~kQkT|&D-T0bl-RkjO%Lbm^cjB)?)hj~vpXXO4CLB~!i8_n) zu1rkoiFcFgZnV`EN_8x-GV#geOq|c8jYYV^b)4W*2i&}H>CWIi!$Cx{)^EzMOiXB9 z#KHe-uv)|g-sL2fjMzD32?yAbxHdR-AkUT2WgJYx;WLP=WUow|-L za7OiRA+k}rHk_C^XWXv@L(uDM(VIR_s8O+SI-6K5DyO#$#@4i@AXrwGt`0_5@}kPD zYkun!{7=N|pv6UK(7mJFp9mC-<05$vIM%m*_I0I40Jq>&>(8 zWx|QCjOE8l+&fis1Z`~n4!xZVKaK8cHSQ!3tEGIXy7MEU!1nYP$a-&9izcq9ENuwJ z{w$3;zd(j|JKj_}!+Qs6cU~Sjwyc(nSA?7+i*W5mIMQ>(3MtznRpggnN#-)U)J3kn z;=Q+b-!1tXA_pmv;u~O>8}CG^Ip^TsIkQhBSUK?Qu4CIuSWc=n_7GZ|^wANbml}kM zm8EBQ3f}t>XyT?SV#3ioxOhc$XP@BIH%W``ygV5DkO#7^s4cl79RHG$cdcyA#FZUf zP+#TT&fM*rV6+@=jMv92=0&#!;#GAS`3o)>+hTgV+MRtOeI%6ONJu5Ry)D_fakxcl zAdU66m-$QoNH;#U4402k`P&$nRgY1%B% zT3!*1{ekL*-;($9kf_MgOZjVh5G7FTv3KpxGlTc#5!eI0UAKB~-0Hd*kVNF^Nu)k` z4H#cPBe=Le+H^+n-WuMbO=kvUDXe00h{o21on7WGHK18Cj@3~vIJJpYz;=m-5Y-scXV`n0A_FAf1D=RLY7Vu6AY)G`|MZh6v8vLa#~xj}Zd_lcSQUAtYsVaw{2PUu!7p9M)Fn8z zR=|N77>&6 zHNmN83b`G)2xWl=tIw2{DFLP59wYn#OC={U0cIsP)u}4}ZE^|2gS@nqwOv=O#a1FG zve*M_i|hr8 zRsQ?&-O3lQ(5G?i!6oa)buKG8YD_RCTUN{S@=BmbLrq7~A3}?H<%wHYh-+%>p`$at8gE9siL%bwaD(*tUdmLaS0@8xh5!RHy6W4Kw(v(qHsutpR)RkW3U>{XkdvctGer0kDgtuzS=#u zgXpUu`f5zO)FoC`$)csGsa<1Uq#sjo+w?@8A{zw8!E%^gPZzgZpFv78A(>pNGyc^whc}@T5E;?_GblxsH zZw?P`=fS_&HqGC@jr%{=!A+jX(5mV>=QMWi5Eo<<2x|TQ5SRhmA@mH zAza5_)?a~zT{^b!q?5wcdn@a=`e3@P;k`S`(skWg)CT$$Y_NMRS9zN#i zn=HP}>f^gb=RA1~qEW|+{NdvUgt%i=n8aI+kM5ovyiaVeQ1x4(M3+fKL@vzZwO9G{ zLCJAEaOQyJ)#O~>G<%Os_6sySBB9wsl40qZ=biADJ<-wOGOgW=0x+Rdh61mgR+@{oU+#o`` z)L?mlDydWDf%c}3mj~LFIz}FP@^H934B?@ZJk;{gMjoiwe8zXAMh{VG;>d)_QAo=56X2bi=Pp5o45;{oy7uRSbO(92J5cU{~0exkK1fQQS zM)64|!{TL^s{+r+9Dc$9-0m@%)srCQ!vRc2osSD7 zIUfQi>bO38)8{)iMbxj0b*%Pz;{h(8@WA;3Ab8(PfNzMc;h6`p#&N(3-Zy62R%|l6 z9~hO|6gpm46{|}3Voq^fQ7C}N-ZqaBqJ4iH4Q|!ud`K_BPY>7O1z39);-nX`Cmg8+ z`)uaYf~B|$KF3uct(4O<-@09V1Yb?+ul@mPb&hqg)dfQ-|mu z^AM`W(!`7_c2_yvXm+2yi|1++z#gS^_Wb8$uU(S9)8&=**2j7k6)_#_|ghb{lA_?W>INf*0 z*j~dpCai}zrp=Fs+MLpT=1%xf&YU__K1&MS{Ls--`oxN@2)>l%;NJgnd zU>mdJ4Bg*dfvKsLMP{Yi>$bR5z92wm^J8Il<;(8=tfjc$Kh9Ewg0w9x4m@l zU9$Ay9#w3*g1T%UycLv#F)_*{BfOnwIAKS6R|KS0Md>e-Wb6S?l zw3Y(;LE1r&UU(AM=wM2FmHr1Vh7p|0)05Y+_~fO_btI4QNj6Zp_iiB`MYa;(88l}R zVdXy`!d%^j=tv2R@UChYCK4mpX*Zgm(Pp5!=VXhK_R!S`UTpm&j(u{eP;|KPvOSI1 z`qB>qkId)5VUUG;a#^m=&M&;LwC{74+0$=vtl8vmbcIiaGb4|3{*RyjFWhYDFJ!fq zU8p>kjq510=%{Fk0GduJq79yCy^AA_&Acd6?pK{0uHZQ5!cWH!D@!i}DN$u>ekI&g zbA}JcchHXHp4h|Fzq-{|nSd5N&sVnkM!rFv`H4Skh?31m{5Ps)xIsf5uzl~}%0YK{?hYFj2QuhM18Qk`stmN`qW$wCrQZwr!Cv;u0* z#a%~OFx<7R2!%s(U+Jut2b~9ClpKBP2f5~We-+=DI`>@^(km(wS5TZ1sG!5_%?AC!D%ICl zzjle>_v3(EU|;fH5&yQL@F#9G4+N*?18S&KUd-xNLs|U~N0kK{%HH+0aF;2|L1()e z;JyncuLw?NHN>;%gsf8i>%qB|?se6%$?!aO^oyMVqhb9k?a|I7}QHR!`sZ{hFE$7oLGU1qFi{+haQyJYM5mSI5NvlN+* z`b7&|0|}7V3MUdM9~k+7yWHX%(W}uxI%)d(O3Ts81tp!Nsc*>n<8Jlen1}a)d$Pg> z-^jl!oa+NT$Qpg7$S!lWTLcrz?N71mVgyV@*3@|Z@QTvL$u25Q0~M8<{HQz|1eIK{ z?e+mXSHVVJq;iIyptFKjEXF&RHn&kcgHmE5J+jNZDMLX9%`eO=Iq$nnH-;(y_jbG| zMtl%oQ(m}9xSI{Rs3{i5%7ft@74aYV*%b_LEenP}q?oy!iYrR@R>b!N@1M*wlSTg~ z4NqTQG)zy$W*Kg`9a%3rM3wa|Qnl)gzax6K>2mV@!}7)*y?mAxvzV(bB&UuZHXQ8y zle4{V{)5pWiV1+)tydo;yPLLVXRoqn5ZH3LgACEx56P#{SC(J=_;TGCC&Ris;iJd- zs(J*jM`@fWbwPLbM_K#`AZt&%;Il_gS5am?x;(z~|F!oX;B8j-|LA#TJHup{kN{!6 zggAqdn6MK9b{2#`IA@m^Ypik>ai?n@;dFi*t(zcqQFW zBKQ=~vMJh^dl&ae|Hp2bG!SjAeS+(4l+k666-z`r3>&mj|KJ^d7E3xLxLQ zkP$Nuh&W!c9VRu8oFz7P=MRUa=tr+ZwRIes%++4 zEquQ&=Q~3u31VQi(!H;YMhdolX3@N`e&30>5GmH&0-Vr_4Et_T+D-phKCL8w+uMvy z8(tckV%L|ly;cAz66A`%7=w|-e80vm1UYgozf=qB`7_=+^;x^pm)=)neOYs%r2tZ9 zJnRlT`%k@xZ%L;){-ObH*FNo?T*Qg}P*rbiS5_@8+7meW8!(`8LtZT3Vx)}60txyM z0$$+jy<{h>ep3*|Uk*SN(40<|Jh?wws`n4#0tsC@`pzUrTbmt-%mSQLWlY=4z0KcX zqA2Z`?R;X-r|Zx~@je&63~`~$0vW1h&z2C&u08`mwxo8kv7chM|_31 z1mP_8+=)|F5&SS%P6Vo?)sHA3ntfu?{}A|7nKc4#lR3z)B+{GQk-ayRd+)*CKZsPt zS!hgL>e9QGvxm<36JD;>kRReyjEL8lhy0wkotn*O1`)$0UNjEnhNj{g`r{K43x+VN8C4}IU?sz0fbdIJ|s4qVsN=<**kMhVehrN&BIMalO_ehyyqAkh(u4I?9 zcQ|6kT6#z^YqyjI{zpK@9dV*Ax=|El;4R4}jlHvQBzg%L?|1D zdYa#D*V-A=D9Kr#5SaBA&^$;3Y*7r0F=klNzAS&)MB#!xC zUb5W^uk`deA94RHo$pYmhcA=QYr@xOW51ELr+W#J+nM+X4;o z36AikyMR9Tv*_>mxD9t{b0ox+I4SR!i{fM;^ z0%`8Hh`R3JS)it5NV`@=1&rWC z$}6Bsc7Y#DI_LqA(CAwMcQ4Qi_^@{tEw?{W0dgN~<(G9UjWWH4shclf|0N4cHD044 zkr)iXwSS;FY&@>nX*^^9+BM__tN_>==pSoN&ASo z$XnB+H0^%01FjHz==JI=ZDiDEkklLC>2twU>UY;*U#4@r=KEaPsr8h{(YM+sBj=^{ zt86{Nwux@O*Vjzhg$g^^$8q2R-c!A2;_{7N3`NR&BCov{W7nzr41|<@=-T_?hNN~vQWODCeA`Lv^b+S2Tyjac*HbOI zpj0Rq!*&wP%fY@_Kd~#KNEknZwX+Cb|KUH-%ysZ?J=oBQ(%0U75%XSeeKZ$)3|d+~ zpx0(-gM)`K^Z|k2qMyf5k00&P`xv~$tv8ROC4W-=qY=F~mYkm@XPU_HE(Aa8wOdil zK&AUiegAqKX2iL)F@E0arlm&*-(%xed{)A05qdAevXGo&61&*8L>JlII~9jkbl8vZ zI^SBPh?@LiBfZ!{+N~Y|JZMS+UlI7*<2bLF-U(dO&)^FUJwxEwdyr!1uXxJUJRaH= zQAZ#4-h!zXJc*Nmxs6fyGkD8|E=l){$3e=FzMzop;9g8@T*>+G|3eERI^b*I=zR-C zLnZcffB|m5M599P0zGmmDySIfHVUKy}!jEXwvOf`GrTt z`}f`-Ex~htl&2}|f(KY5zCfi?`m}4q`^ZmWy2ra`@OWr<@j%hZ;}*LP(2|2rg6XRF z42%+Li|r|Q{9X5{k5boO0J(*Nj1s#_anYq?ir7W?e)k~I8jDv3hiBn z@lSvTMDGxcQ39o7@uNJ!jc~S=B5>UvhNYwUtsJXJMr~?OmA~5e0xI|V5f5Vw@C8!u zsdywq(Q_=He@h)}--s}c{)D}R@5pk#=Y(&*@V#(y8Q;WmzUzcm zpE`DP5NxR*>W{&G@Q3>2*z~j6!e%R*ZESY1c|4mW&GAEhH=9v5V{9haT*2llHcw>p zBsNcBGs)%}HrKLwCY$TnJcrG5**uTU6q^^ac`=)`x&5L3GB&SZ^C~v4VKdFTRO1pE8?YCJHBCvw0IyhZ99pPDcw-_YoB*>Qbv;oK0{o%l z9-`I|^#oC?h9KXiOS6y2V5)L>%UJd3EUh&qU)m-`k1IohMf!&L~SPOMxy>j)Kx@PW4+saAyLDKT1V6Ifv5ygQ;9mB zsJTS>iCRX~5~7YLs+p+OL`@@V9Z?4mbtzF3h`OFA+(rJ-aW7Gr+<)lUNEDW#A39zk z3Mcy?I^HAdJ1kTkUl2tfOX?Va#cp#iQNxLPhp16Ry-L(xL_J4TBT*#P(=nf@2Z-_! zbvserL|sSJFNmV|ggVY4>O7(@BWf*C*AsOjQFjv+CF)6{+K9>#bqrDO619M+&xksV zCR7nFBjJvlKHlByzytT$b5g@zdlSoqNUVJi*SmQ7o(sYecQnP&)RX9l#Nw0P1ryxa zp;%8m&>8NE2Rl~p;Wkfj51Zh&hTK`<_MT8U7HW;`;T}1`ogV58#of`84>gPVGD&r@ zHsApIQ|B^kP<7wGt&4x^K7#*he&UZ9YO4Qd|FV?+zeFZAGuAHU&GC4u@MkNfve^Cp zm%sl15C6E8{tp`d6Pgxzy~lJORCmy#&Xf4h@Ar3%di2pp*M6{QQC&+*b<6N0yxZ6c zqw0_%*AA?yrkb;V9uG+x$Y0?QOZ{(lPdpTB4I~03KGICpFtdb-A~&|Jds49W`+e@o z3ijG``}k9~FvA+mUG&1Kp_4eh3P_^^&+<$yep}#2JoIOaVZ)KzwtLQ4^zAMK8;Lfi zaO#0qFSu^jyBBDBqZ^IMVl{iW2?qV0$|h{d`~O@Xn-1jj+^$epB(~a&3&moQm>X$1J`_y2;W)Dd zz#j{Dw~sfSJpt3axXCwf{>*txOt?D%_MT`W)VhoD`4SOfGvm4=uEf(7ipK-(q46dW ziMU;X?$vHA6z}Ow#N9;1jUvv35mVTMfzD2(xNc^f<4^O)Nt-tYVfhd5O(DcwGoQB+=78%BD^Bxc15tb1lq`1LQ6od zEe_i0b_cpbE}D>Q3iZ|!3&d8tW67C0R%qn$j>t-Pg{+21qb(Ba3Q!R#12dH;+}<6D zh0y(0gkzCzY8`h)AQq-l#ffiE8&@I{bvw{b+%vRFh(Z0)H-Cb`rG_n40=iEvTBFvq z^>m}OsBCod(5fhUBdyrzjS&~!A=(*QWrC4z^y8jj0xaa-8R>2p#{hbei9~~_s5rSK zVv$Z78sP0gQHsogL?YA`O~8Sg5&yXhj0+ICBGB1`-qx3;xFaT7v5(B^xHZ9?93Xlk`N|cA{j06xp)qSv|r+c|OjypQ0HfojeMrNLHx6W9$ zrx~3vX}&_I?~Ziu8SjZlL*1sPvtTJHpRYX#S6h)X&yB4Q zjy1uKKx|xn>v*0uFu|fF!kD4Z1$7R_4iH;HY7H|pWR|Wn-l*AqPc%R$brs~TyQixK zp6JP8RHTdDA&;$M=j`cj3wMX(9bnbz+NKhU2Ln+|AQ;}E?qJBYhJs#94)fYuC| zj?k)r^=u8dhp~vPiekM8q3@JpFU$0goN4OCh(~d$MLGhs9_Ru=voZBjOqqcgbyJLF z(}HDdxoM4T4%N2nV)NQ67h%8qbn z$V`}ErcN~nPc;WkHK$B9lP8;lq}C1wfzAy}s^(x*%oZ{?KHchVjln(kz}g*UX#0$TZKKXQt1e zH@#_*Ief0y%sj$0lcQNQbKxR35U-iu)ZAkd@tGF1v9;7 z5eQ+lJ_y=88_`T}p1*MMf|+JX(}Jc2hnks77cFQa;-LEY!EPYIOEy}8cPHU)oe4T4 zkthwf72$Z8)<&$5p-!25X$Cup`bl|c!!GDz<&N(0Jzdc_7A>?1I*uC;MldEKZ5V?z zoM_H49C3Ui#m7Ch*!$zFyAy#`GLvA=>kO?xf3-6ScC_wTH0s#0$xG%(*RDz?9_nn< zK1eH+uot73EEHGC;$jvzm=C%r(>xy*moJ`{OOe}D$|~@`_iu^}gRc~(xP>Zar>EPJ zZhUoDOQcgOMru6Ji6Ps%8q*b~8_YFWWNBoh(ahMXr~(u&+Uag3uTY7ceGDucCy zFmF?p*7a6V81wKdrFmEuLxiFjYVl&k?l?4Lurq?nhij?pjJL~NoFWsRW~b5Rq18N~Q9FsT+#hMlH!YD!XDEOvO6F%;(O92-z9^PjpRcF8 z3ub463<@rL3?eXlneA!ambKHa2qP~VT)SPZ!On&^Bdw@V-jQOzL|YEbp;+c<>c$>H z4**sy#)2LCUf@kA*49`TP8li&;5c|Cus3(9X5#?kO$+Tlbnv*lV$R}2 zO*ieMXb(k1k^V>0X%E|3*vHj<3u7%gm+^|ai@wJA1!G!XBa+Qplh~uhH>4=V|VFf zwq$M`Q%yoPA(fqQvKxp-C+Hchz72P22!Wm(!VxsG0^3Ne=xtonNZtmPJnwlhR)Q(g zD~g?;!}ER`;ju|agC(#7ZI2so)4bW!C%Zk}G@Lmzx~)X_pq8eIff8@>&gPo0HJ|?G z3A;dGev)y9nkmj-d$?F;;BMN?gwkxxRYIF?9fo!`aj`(6I~;5%5!^r;-;$XN7S5hO z&jjMQP{D>P(%Ff8wFhD?IA&r;)kYg4-nkfzD%z9EPz*-{;TW9}0mp!o?FA|wm7Lkk;{g;kbBB4Yc6y*Nm$j)u%CiLWJqDH}U`T6<%G zZe-RSR6BU!7SwfU`H%^@*hw+t74vTIIP)RJgXY;7^BLs6>TXaL&`BFKT(1FG@B@evd#Xu@$!=-ue3Xlh<)arEU` z0=Gi69S4n$COw5t#ci0$=xQeri+6Z{diDh1yX799Kcx z1Gn18N3dur9d4x-EJX>xQNos}$XCzn#Wf0tKWsev4j$iOb7mf8mK)lHVdtVt6lN4m zN)$cawH6B}lTIf;wy>V&;GW`oqA6n0qh*}tnqm(w4w|;k?uCgSb1+R^WtT3JwIWyF z70SdTJu!3`+#kgfzIZIi+0`v1c9-!4W#8hJ9XR6!dtxzk11?r~PZYa3+=v9auqBSm z=97YdCHGzwQnE z+4Hegi}uj?qZ>-Xm{QaM6uDz^HM3?n&)m(<^RgR7KIno2vjNS(>}J|JaRB5p$I7J6V~3CH8LW2Wm=&{%pn7a~%Py19T66}W{jSE`9pOf%sHn1JpVp10ON81n z^U!Rv07IL2QOE3TKWt?`ch%F)2OG?!x&TmT>FEyR z!iQ^B;|iJ%j6r?<`s&1yfiFT3SJi6Y@G{NaaoB3$6!)ABQUC7?6i;Z8ldBa6rFpR9?lv!U-NA{N0lpS2I znO2jM>C&nGk- zI(chc92mGtqf24TLwbj&4yY}fGt2JD)B~F-TpQ!b21P*!Cc2BZRXldtSiPD@dD`f( z<0|`4$M2%lt!0;jHtun_Gt;YJM1 z`HyQ%HtRCa@y#szV>4lQAa*cTPKq{D#dB2g)=uWcvE~?5_c8Sid$*cBcXxMfC{~2{ zyW@~Odhmuhxiip?hgvp9>n~d$>^=sMK)dXN6TU6qkS1Ns7dlo zeY~_Jl)4W^G#z_*e1J9L)9 z`DO1(wA^%HS;KCV-!i}(&ipn4UIgSnvgs{^KP;_rb}=4$F~D)~Kj2h3TW(S9Bu5z2 z3`hFCvxmH|Ky(#;gG|(UfnIOGUwW{qi4HMUg(1e{4mDNYp{6=pXFTbxj1wJhJelo` z)3CkqBzHj2o#DQ-sjfqUnR?h`jFTK=svE`uk25vyc-Z4jb#gaTmEOZtyL*Cv0^BE> zs@z0Vo!$#^PJ+FUsfzAvJgI$+Q@5X~_V17Q_ct|-2f*zBQ*9<2Pu*mMnQWZKDW)nv z1$jFNVGjb|R8y5b*mxS6;NN6Cg(k!|&3K~Ik={&%n`KPhVWv8I7{biPYm$eX>V`SS z)7WgP8s-`&GuN2>0^>mAT212;WBf;&>c(ZJD!I(m_UD97o>MAsT8dWNaVoN1iGnTY#5Qg4Z`hi8%Avxp0J_BKNt#zEt7EZNykYgH$IyJdEr#iPK{DwI-W;pmqIF5H~$7Hs1 zoYeMCb$)xtQqNZJ5|ZC@E_|q?l{L29f$OGL%0UVlW%Yw z|6Wd2dM{*P64IaKn8IYIreP|EPLop;od&*T$jdQ~r{NgHdyL~W9P1dbAASMkE$BG; zAm~=7+6^HeA*U)Ef`6M+lWlWMv>j=6I8GX`JGx<{6?Uo%up5qt`*M_Lxl@zuL|(hV z)8&|kZpV}AcB-=x#1V6<57JxVR5wE1V04vJQ@7f2a;uTg6P=pI zUm*TpfIiu&DxBP~SS?^X*9)EM)P>-?$T7K#oT|Eu9j9 zKA>{dsy$roozxzu_9V3rQhS!#UbT-_yH)LOwO6UVM(uOe-k^3`?OWBpPwmIm-lX=+ zYQL@ahiVtp{zmQUy`(%t)ZSL@QEKm@_I_$Ns(rZHi_|_&?GCkLYM-R`nQEuhzC!Km z)xJ~hhtz&b?HAO3P3^qee^>hpwZB(;z$7WpFtvA3dyLu*YEM>shT8MgUaEGB+MQ~z zP&=viIci_5w(aP(2Wx$*JzVW=)ZRhuUDbYLrtptdoS!Cmcf}2A@2z%liuk{);r3Ja z$!bqkdxqL`)P7a@y^5EpeT>?kLnL0G;uf_-YImr;TiDu+SjOk zgW9*KeY@IsseO;y532oy+8fpWz1pv;{kGa4sQnMMzf${qwfi+ny$)8})}ysIY5%b8 z{|CipKMD7S;`f&beobxLuPonYv4hFAQg;>N4Q zf0N}`{F35=;@7PI)x!T5#SPa8{#db_7W}1Rui|eM;{?F@vGs24;j<cFJ+KbdaPVMDt+xX8_oV;GrzgTfW@#TuWH;Df=mS6F8igSu@QtaZ?LiKxx z;*{e16&DmgrnnI&8{*$+`4zvQxb9~0e^s$xu`P$SCmb&ImAXav_f?!%e30TOzLrDj z%}|_HJjaH=P5ixz3yN(z*8W1rckT}1e^B|ocM0BT<5T>C;tb?7Dg9R!=kF8zXT|OV zg6;TeRJ>XJakAs^Unou~Hglx>jSq@{t>UEOZ4}o*?GL5Dv*P^2f^C1s36cHBsXtDO zjQ6(jDYo@s?TrUX`gZ+Ws{FRU9;?{$f7&ekCM)rOsW|n#;NL>Bl=5j_5d5wByNa*V zb=CiS@qa=2{VxiBMR8K`-OAtalK8)&{wc+Fe9{S*(jB7yQN=dj*8Z>g*Yeo>78Kj` z8=sW;9h<)5eilE~H~ogE1>5x?rTA{0-wKLtzN|f4<7-yiwukjULfsduZTCgifBHPB ze>&w;eH^OTeMNAyVz1&O6ekrQsW_+j7{vykTc-E|iW?NSDfTNqUU5osx8khgnBs!s zRf^p|O8h4)jw(J~aYpgkip^`nf4<@d#TO~gDZW&3yzJsW`3pKpj5?#UpL_yzsl0U-4MQdBqbHH{f=N%5#9?l;Ww18*yVq{*`|ZtN&wa zKcn{ZYQL(sjkhxV$LhbAmSdP#%0FD~?bY5DapvEG zE9>Xzg;F2cAz}vxX5igSv)6lb;+|AmUZ!vx#@(6E)@nEKb@_U@X#mo@o!Y4VSo=HIc&KVcfsw$qN8=69zp zZt`zE%|C3~!ls2y{sX1~EScsXHSIW9i>4hx`QEb8=bI5~3*bfl1rStkCh7f{#w=?|}@CbtGAxXc0horAU(q3qb4Y&Q=8OY4Jf|8r&v1ASJaFYoru? zB1xGtvBMa41>(ygjTSO+@rp~RD;Ql(Nt4@Bc8jy{V4HRHi(@g1B!)-K9qgWnh=2kd zqUs=032<0N4)o6W@sM!E_I?6A1aR2>GTMCPGj|Lhv$%A}|J+CWx#D$?s+bBtQh1Vc10?Lq0C|L*x*SLl9*( z`DY1=6co@VMm&y4(uNpvMW<36uZvqd`RA2}02NR#A*f9Wc5q?^3#G4qZDEwtPF551 za>#g!_d3BW-h{YP3`r0R;4%WyQp+;5Re7_ZmBg4Knk2ReJj8(B+>UVNWCgQW6}&eI zWRWPq9Kn*96RGLy;&Vdk_j-QFxnF1A^DJEn_gCNJj(2wEKG22atagDyICcfOpU4Xb#-8Hvu-nA2MbS|F|2%QH@xs~CW z<_}vghTB%NeCGMBru)oi!A?Fn{caNOuGY^hj=riYU zcbLz7yWJw6`PB|feC97Z9PKmr?$nG}ccSj)Gry@1`&h`$XI>xU^+7!QgE6KqXwLSm z;(qiSPrzh7s#3tb=V><|dE(~JRWb8;b=Z7Z9X08igt@9;r^(f_VA@}5rD?yc#iH?T ztrhKkbqkhXUT!Yi%G7j(f*2Ph%JYCHV$P^RO(h^;N7^+u4McZdZZ_7E0H`^8yDF2O zgSWnOkOioMY@80&bV3sEtv=2R`SIk`Azsle}d2o?Yz#H=(h>CvY37Su9%@zss zT$O4E`_({}i!iqgEQ!&-IIzdOIxv`6g-;srNNO{eZNcKRH`hrXpRHq28}m{f%Rs*c zX#-T#>s6fJ>jxr-^CZQOt3+ITbFCSWFt=4}ss&B;yRuZTs_ik?+4QcF^sdu%{wN7N zT+Io5g#@ykfO)n$u+n_p&s1^CyjLx<>B$-v8NYBVWMn>SNd%(4t&W?A`?Zpas+Y%9 znY z4R9Jtmw{M=hx8`g+%IB&jke4k>F}g=Uq57gDKtk0i;_1V^iz!soBL_vpY$urcmEUo z$)l*CM^k5jl!Pf9gW#go;o|-@qg*=xur^}aDa-c zo7=#UhLna$hGC?ShmqURZrQjqH~$yG42WTZ}nk@*FTJQ>N82$GRLnW$4twMix&PuM&ILPEwoAhH4@VRWN%O34mkl2 za?EBD@5P{HTFv`gu)c#{#GS>vF7U@2DrSpr^T42>d0`N#<1%Lr#*nytaJ#vCaMV0I zIBwEITEkF_Od_|C@{gPEhCoz%l36np``1r~wuM*m%CP}c0owkzgShSIn5T!J4)Oj9 z%5L5nRGLOFhBOrPDt$bN2lPdQji+gv`PZQ3<~(>zH>V9=W!4Wyp&@X9?6H~75S@i- zJeaHoQ$vQJ(;;rIKqA?@$sID;q=C#lJvajGbblC%sv`F)mMnfBMM6H!+PX-b>{Okp z>ckRgz8jo~K!P!3)(nvy%{oL_KtR;r{bXhyATx#cQsB;J=26MUtwTcQS!9_6Z0DHA zhCss&YR5c-lp*{;fwIE*>JZ5AKM(mYQ8f}bg&~m91~6X@;Y?grhjgB#AbGr>fdb*J z3sX%xUr@-%|eV_`(iW)hEt!Nz9xJEBwnL6ZGQSY1}%JGP`l8=nU5 z-BLtN1wFha>*5sf#Fi{2E8v+e+3t$Bo9DMgjAwZeZ~6i*eFa;vHx}UEwzl6Ykv zB$~a3!WM4e7;a+oW->DwHt#00a4*HoJDF#;f^aAe-aqZ28?`?}4SeAtFrXu?G@oqM zW^NuXUHpyVSXOwOz$@2B!%g*cyAo~~-fYRMhVy>NTsNFb9Wn0?N9le?>1NqX(+9FV z*xU%)Z-&Q0A@d}da_k|luV~=E!ae^i1x`OlX6gkpGruP@{~{vl*Aj@uphCc0KLVNn zem?@4hI%V=+SaIb=#rFa?V_#Q%;j5?vK{l>*4Un!-;5wFVLtQZ2+pI={B8tdeTibt zzRYpMq-tIcK{wJ*grj4~tlt{@2b!~?IRQt|Z%05u0W^P}h}6&88X;eykf~S6EU=k- zjp+32hzo<58@`29Hpk85TSuTmg>$rVYiM_Y-nbm1$b*$e4w=a>n1*R;SZFo5O(L>9 z)IABSpgD7!xH)$l>^^VX24~#m0ct$+;x-6%eig#zU}C>PdJd)I->?m7w;?qjPk||y zB5!nMnuE-v+hFC`1n2aH6gG1an-_CD_kgjAx_zK$mCt;M97IT8=C|8mJ4;70pE+$? zlosC!M#&%JfG`bhrzW+vn3uL~YncSv{Bhf$d23r9mgcK%Nj0ggsNZdiOiXGuYete* zO|xz!^hSw#GM{;84C)l$4?>}yp!`A~2o!uwGKFnPsT~%j+eRYK@It+@nR=4wEKK8B zVRv7@8fmE;z@C4K<9m+G%=2XCeosZjRta*w$md8>FVo#ReYSaPBovH<%zKo`azJC_$8lUKQ=Q@5uJOQ%@@IqZJD`!J7`YrFwbrWk$dzN^U`)Su>QE6 z@pM8N8QSu(?Z|u@OK$;TklIUR7TC<@C{5aqnfJCce*;hQ74pr$R_*k#=JhY(miiO8 zYS0_5*OEeCH?`EJ z?ahnu&g98E^*$%YX6i514zwnkkKvpD3%Tb$K(bX7==2>ZhiC6#&d2PL`jk8~1u~PL zRXg40a+*{ADa??*eryNiC(&h|-hn1_noQz8vt}%~zv1M*sdidc(Z4!IpsQXya45n8F^=ItFr=HENYf?zJ$2@%nz_{yE6_g%Y_Xx5z{ zH8<^qO{?rUH|~f6&|r9OMl|keOjK{{eyy#kp_ifcfXnA#;wqlJ_Gwur$7CcQCg>Yu8Hipi6z> z6*p+UgeG$H&t0PCAEQWJAgB25uGqzVzALFZZ!>3&?lkL1x0`22W5QBhism0XW1^DI z_Ng1OM}yPqk(Iwv$+5lTMR=_XEthBSihl7CJJU7YuUu4y=H_k}rT+&NA@>=X`OnEL z{F9hVXVu?BT?=hR???RUFZ=p!W_=oQb2a=@Us32ROyi+VqFJ{KW+aNod^y_Cfp-^C z1Y-WNi_P=hqh#5Aa1^V&d2AGRNapEL+6SH;g{~YzVay*#>1BY=Tw0G^4zv=PzwKhr zg>Q{Q3I4^Ye@&?;%xR-S-K1?`eZ8r+Y29X{eW@7jd!veH%fBIx!oMkw+&64~OJ@2z zHvdCrp3TDdL}z{=Gn?!OGj|%9sWttm=0j0xN1j$r-<2lNd#L)!ugd1*#$B~%-@dC% zxo?0axt1cy!lXz@PmcNRuA;8NoJEy;Mn8vReTCvXgP7B2l9@S6JwAp<{wxaLW=5}){H$p8d*7qLggm>3oSs+D%TpHlA8?oUsGxqQHa#VWF{}+IM^&)N_62$Hm0Nm;;J!N5TNMcx-n1$aWk&3a0zqg7+j3sH%9aQ$Qa2- zc8paa@!K)j@6kQ_7*-dt0SOmw;lwtPnR}Vc)LUd0zGd_J{^Wi?o6nM&ziI%?kC=1QK=34=A83-hr>ins=KAHFq|?xl zbJ9+o-*p>Yf7Z!5IVbB$J1GZ3AQ|}JpC{?$JUMvefeM~1yQV-POoKn#ND(x+4bc=> zGWeH8v_vKG%R2?oNl(U;b6kqY%{q;B1y5bpiKZRb^`<;ocv6yXhB(~1OjXM9C#(I9 zjSU4jXB>ZlqN?>qqbX0C{#7APPh-A+4&M1{M4U#Ry>)eU-XxOqCTlaEeE*E6p%Iw= zJC9CsQxteqpa@D_p^pV!?-Ubvb-7oFQ zd5{qPWt=FA97Wxt2ndO6lXD}o-so-grqC_2PBc{mhK2?(MExmG&Y?83$N`1VR-vG2 zMCZ>t(Wtip_3L+0176e}3Xe)^plFZ;RW|CYG3rNAqJA%;^Lo=r2i^#Tj2BSTRfsGz zAnS1(>yU?(ldDR3{K$4vQv){zMGo)@o4k`lVUP(=)TMTGGmbwRMUP2)lE`|47eD$# zQP2{|p0@!pvs0tD&>z`oZ1nmwHCzx+9)+q)4fSVhksi7qYK{unzpyouM2INsybN{O(FwmVkhrGb0A;}=TQ0k=AA)U0nBLpu!}7IS$}NZ<&TIV zaCPw|9`dB`))3C^EV$14?Je>@1oeRxIuC9De*tR;->}ARGi-^*sD18jNqVR|0cm*HvDsf7$Dak?sW{my_+iVxSun1Im_PS-!MG8U`uSM! zpB1~G3Wj(A`!^{5-1-;9pKfZnJw6jW7z2QCqvCB9*E#auf4$<$-vuHuYhy2;`EqhnC|X~j9k zw<`8;EB^N@t{W-%X~oIy1mhM%;@eU1pA~0E3+`3y9V7Tlizf=Mu9EQn{R9tFoI6CY zYyD>l-a~O-@!pE-7KneN;>J~i7b(u2B{-lsiQ8@}f4dEjdvC&BinHjLgilr+y-4tx zic^Z$D~5I&=BJMuQvF)F-WwEKxnA5au)me-{heYf*ZYcME7$v>Vk_7CPsLWQ*HbO= zS-D=^8%z3^OMY;t!Pv_2j#g~tcpDU3Io^X5r*Jh-<)352D_*MD%JGIQ|5d^tQ*7mU zPqqG6i~og+tsL*QiruvMXB1=A<@A4}IIVb-4S%ip;|_t#=U1FpoKyUf;^cM0kJC5v zH~d;~4OTsBuZ-e4#SNHvsQf!9wsO2<6-(Y~^^{E&ojte@wBJ<2_NamE&EjID=;$R32OfaCxm9?=_0894}7x>~H0G z>9gxpKUR*HG`kT_sod@xime{FLBXimhDieCz+T_%Bv$BhvtldfOV)wa^R8;jLWleu}MJ?R3RfuC`gR zm8(5cvHu&%Pe`%*z2Hv8sevMwda~liTEXWi&JGg1L9tima<8%eif>YE<#g{*Y~^$x zP;BLNA60DSbT=xta=O1)Y~^%cQJfww`FUHh9|sE>27j~sBL#n^*xfZ^GKT7ca7Vj!}y2YafFI1exL5K2ptm5Pt!N)7kj}^Q^v6VYs zWBpa`_yWaN?)WOg*rOe=w}ii2adIEQzg3*sS8z`8>x$o2Z1n+sq}aco@DCUy@t>=B zTg8_tu2*bSetCbwh{Fv^_!)}xA;HHfjX(A=S6p|l;7yA2n*N*C zU->^&+__G^1b z6{mhJ{A(0v6<@5lPUHKvVprq4N3l6a!auDzceda^Do&~Y2Z|dNf2laVPWY?QHK{+O zP8U2}aegnUkDV1KadAfT;dslxzu^587Y-EMq_{!(=UIM@Z>eJMB;gM!&h0KZsyMl) z;FA?Y`!J_}zT!H?mn&{)5dRw$7mk(kJgC@vq~K>1yLgk6%JYiil=8o;xKaH-R-6q8 zzu8jjD=c`hVtuUDLn z3cgZt11^3k{7p8zmj52b^qMRAKdQLSFZekdUhkXVQe4pde54pJwQ~6XD9&kmwZo)- z%n9PZjp7EquO6>BtMTn^@p9omSh1`1(X807^?!_Fyd=x%cPYjjtBg-l9M$yBQA`)J zRNgBUH!8kOv3t7sKcYC-Bluax8TEf%abEF9itF%3DaHSd;`Awk2W}TSE{)F}ah47zY!zTq_t~hm`;5!r-RtSFB;?;tmQ|wp# zmJP4>ho2~JNC`hFN~ZZEdV%0A6eqPlMkvnfedJihjb{k|{uXQehbc~|p`ceU>uj!p@ zvEC0~rZ}q47jClQ-;we1fZ~+mrxoYl75|qMrxm|r!~a$MKUSPn|9>k^<;8#C){?(Q z_1~H>_Pfe)>VCM5@D|w5v`YIYls`IF>gRODX~pL& zE-1c2v0vAp>lG)*OZa;fr_}#R#f{^{|3w>qs^B*jrxkys*eL#rF!Gz!{dNCsq<*6M zd~BHF2EG5^S#d$b?_u$glHLJ|Gx~gBrsAkq{1+=uE)yJ7oIXl$OmW>|f={#la|K_Z zI6FshT5)oT;5)4UY{8Ezb`KT&yyaK?rp3RL_Wi43uRcHf(uRLl{A;$A`e}GhaGm0e z`tPjRyGi`_Qk>KHn=JlN{O2idI6?Avl;Wh~R>giDUkSw-^*>c{VT{DLUU5T%;L9w( z`rn|qZjSh86sPM2XBB(3KR$26YkaR;f3NU=ptvwz@F$AhX@Y-HoSiFp;7F;z^(_vKyg%YT(MvATE(eTg#QA?IraaQ z;#ynmUa>n?{NGSq(DH0nj4zyU_-_eg{>e;|`J&%;Qa}E2;y+Ar zau30~D#q7XIQ(9UbBYg99GxKk^A%^cy_PCA+8!-7yq-6rmS4{srz%cs{!@xm+J0A9 zto`Xm#hIy+{)39^6hEuD@gVVkQ!%~{!{zx%abEd7+v|9nBK}(`PAR{uIHMR}w~_OM z@;53r+CE;3)xSk?!|oFQ3D#fpce>)biQ<2O^=}k>wc?E8TNV48#Q#CXsr>{$t+-*9 z;FlD;hYEgMaY6BB#cAzNUs`@0Z=M~byxxl?{1C-SZLb}z|4i}UU9meu@MOj2B*BL& zZq)IxSaIPn@o!h0*6=-+U-NgGVzW^AFHr32`2Dr@*YSRr;^aQU|F~lB{(@gpoSP*0 zUB&LcfU z^hm|vv53K=4im$V-qlOs*Mr{*{8r+(3cuC(orvEr@H+{=lkqzRzf4SOOW}6`ei!0*5q=lrcL{zQ@VgYh%kaA# zKZt4?2x^+E@Vgp62ws|B;YaTVUW?y#`28Bc>+!n*zZ>zp3BQ~1y9K|a@jD;C!}0Ut zcLaV5@LPx<{*t$f-S~4`{J+;0uJJ`#QHifLLh5y(-y}+Un0$$%G?cHCzDOUzXXGJa z192)J2`;iAyRRf3?1P#p64~`Z-^m|M1G-vbq6C=_L>avyyz9D;NtE$cgU`XYP>7L@@JD=rXyhCa{^0WAt_ zd}MYZc#zafv3yZn0Yn8sqTcws+@WYk2%i<_YJu4j@t{V)>Rm{0hVenrjYV^Nz`)|lK5<9BR)ktmamZ|( zvOrR4KCVm_`xoYR5>%F|q837pgwQN3h(_PGMwBFChSJjK#(l(1e&8S}I*7p2C+K|v zd}zJBTlfR5$M?h&>O_1kU_ruYZxp5{2qikk*Ai((7emfbO4KfC0q{{1h@=zBA5@C1 zIFuA{p`cFzH7l*eVTvS#biopdNyG`Xp$`q$?bGtNQFmmGOIk%DX-5i^y3s{fpxBfx z8UXh5(Z<&dA+A!#A+%6iL+cW~(Z?c@)Kh3Mh)Ni$e(9prqUh36G2ots8Vn^C^5AIZ zrVu$QU#AaU3~HXxg-Hhvdua_IMIt3-m14N7Cdzz1xhbd1iuu|khC0;-hJ}m;|qXbAS zQ+&|2JPNsFaIVa2B4URJb5Qq_5h0Ki%Sc44G+%6?vmpTyceUlU2dQeQgy2mzbFtRchz~E#* zR?nm~iYGoGY=o^XJ`wu!fkIP}q7)IDR0me`pfoE=Qd%cw35Dq$gBVJ()U&KHHComC zLjF2wv38X*4C!`4=n8%F0Ec28K$p_(+i5gtSvqA47z$jRDk-uyo!;0H^Kk^NDjFY% zR;tY>iuSO;&}@zBZR4IpHomNl*_G@Bt62jnn(aV9u>s6dhi$iB?HXKWc|?f`6gmbp zawJS1vaSMX;-Ex}0p+a3Dsvi~NC6~t9FT9c=tvQl-8vw6Lx@iI}ftHKm7FZ4gVm-eY#{sgsoE}zeuPDwS$1Q7u^Zzl`Rks=PjIY{bcf35yJ_ti6EvV)EjtPTiAgo>j`91bZ`$x*u70m zYDJoVIhV>IlXJNXIvI{D)VWv3*{&>&hU6WuXi%VP!HEY6VjOT7Y}jnxqRTCXmec&= zkkBqAmc3xJ@%@BKNUEsmKGolY_9=&=o~MtKYU&X;jA*Ns$2wqxjxnwJc*-1kSrd&t z;)?OEs&^FkRn4Q0qLfDfw&*w~X%5R33yHTJm5}`zrBmOG^3x!D$-2#CY4bP(>y&7B zqNsqd>9?JoP+tX4!h=0!AC*$-Dhhe9`JuUhBP&-?B`%`Ois+fNJrhMY0!dR0bla4G z>bMaHbS>78Lui)W6EIElsO}sDBOY!lj%t>V;w|^b)XuvW=^q>f)mu~~B?-W#s86cs zQXVT9N|7FljVW|wmiGIH(m4wQv)qMgQv5~n9f}<*6hoK$qe{ym%@ZYj7#D+s9!85( zi6ZSc6eBy!MxRNH6m>^dOB5;45%%J_;xJ6JtZPHu1&B@_aY5Z{7*IAn+$xk*;}M@+ zGc--Z3|xk={uhyS3*wVSgguJ446LC~n6br}1Z8n0po-)w9iTt1lk0&Iv^KVkL7Hk*YbNS?QpV&>E$Va!#_D$MO>F(7hZd z#tw4LQNpUqPolzjEG2>ASORF7qW(bPC0%?%;Q)tS6-S9iDoX%JmG%{VtvWw-z?qvB z09r@~JIQ}Dtjs#$6 zmEx2+_01D=m7Px!D|JoPzEc*gG&d=WY{E+^i;|(T5Ji1CWp29k%YxBt@3%M-+Dp<| z4(e;Z2mY#dw6f=or_gnBW%2vVWl=D+^2Cc^2^SC z93PzY(uEY*e8-4$Ah906+&ZZoN=%SLuM5`6ib9qIj zGa~0>E*%g>1)cb+YB~b*WkF!R((ceg)gC8|s-I3kNiUsXR6l946Hum^P8_J3tZuoI zOHuKhIH90WZ$~sKo~F&DG%q3DX~AzHZqQU49I+BaKn}Lh$Liz6*{&rE>DG`cQCWaW z6}+%~L0Lroo3{9fR%y|#CJw9uOh~&khAuX8SgdCyCRI12xU0rU0!zv&dP(`hvP7-~ zSs|J*7SDMcOfIFMgH1dskF3p2AgOUH-J&h=5oYCU;*D7CxLiV;-twS*ZpxOFT|6M! zrMxTWB$r}5TeXQ4=~AlDvQ9}@@BNli5_;>vobfWfiW0V@myvK$MLB_^asQ?d0*)>v ze>7SjX9d>pCR}n!fdF*Lz-u1ov#fr70o4so0eIq;1-)`3P_{cmi-;C%2~t}3;Q<}l z;);~5VsdtnBQm8?+W+u14mqKrc+knmc`Qny6lMDe61HP<*AOg;1$OFrue48j?4S^o+pb(hVQEgjtz5d)l)#JI70Eu*H*3 zi7k9jF4g_fS#LWR+w-phq+$+M8BEO=OUhUfeQ0rIpqDzqyqN`oYWmWqX z9m;w-=R(_1o*Mte$Bc@f8v;@M&=Aq3PYeN-e_V)Q-_Hv5aglE!v6FlWNl2_vxMe}e zR{jbSNc#;UCiNl`laPFOsQAGl{nC&x!1vMR-}u1uHo7&&rJ0(zS(B@5e%g!G0a$K# z^@zn$$Q5_#j<;1m5rmKb=z@ah*l0goYw_2Ba1jBWurQH-dj;P{U;Od4DSw-N^gt6m zoaJgI(YT>zTED9UK-UX;6)&IA;dZ7gS7~q9`n4Poa&3)0A +#include +#include +#include + +#define lua_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#if !defined(LUA_PROMPT) +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " +#endif + +#if !defined(LUA_PROGNAME) +#define LUA_PROGNAME "lua" +#endif + +#if !defined(LUA_MAXINPUT) +#define LUA_MAXINPUT 512 +#endif + +#if !defined(LUA_INIT) +#define LUA_INIT "LUA_INIT" +#endif + +#define LUA_INITVERSION \ + LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + + +/* +** lua_stdin_is_tty detects whether the standard input is a 'tty' (that +** is, whether we're running lua interactively). +*/ +#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_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. +*/ +#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_rawlen(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)) + +#elif !defined(lua_readline) + +#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 + + + + +static lua_State *globalL = NULL; + +static const char *progname = LUA_PROGNAME; + + + +static void lstop (lua_State *L, lua_Debug *ar) { + (void)ar; /* unused arg. */ + lua_sethook(L, NULL, 0, 0); + luaL_error(L, "interrupted!"); +} + + +static void laction (int i) { + signal(i, SIG_DFL); /* if another SIGINT happens before lstop, + terminate process (default action) */ + lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +} + + +static void print_usage (const char *badoption) { + luai_writestringerror("%s: ", progname); + if (badoption[1] == 'e' || badoption[1] == 'l') + luai_writestringerror("'%s' needs argument\n", badoption); + else + luai_writestringerror("unrecognized option '%s'\n", badoption); + luai_writestringerror( + "usage: %s [options] [script [args]]\n" + "Available options are:\n" + " -e stat execute string " LUA_QL("stat") "\n" + " -i enter interactive mode after executing " LUA_QL("script") "\n" + " -l name require library " LUA_QL("name") "\n" + " -v show version information\n" + " -E ignore environment variables\n" + " -- stop handling options\n" + " - stop handling options and execute stdin\n" + , + progname); +} + + +static void l_message (const char *pname, const char *msg) { + if (pname) luai_writestringerror("%s: ", pname); + luai_writestringerror("%s\n", msg); +} + + +static int report (lua_State *L, int status) { + if (status != LUA_OK && !lua_isnil(L, -1)) { + const char *msg = lua_tostring(L, -1); + if (msg == NULL) msg = "(error object is not a string)"; + l_message(progname, msg); + lua_pop(L, 1); + /* force a complete garbage collection in case of errors */ + lua_gc(L, LUA_GCCOLLECT, 0); + } + return status; +} + + +/* the next function is called unprotected, so it must avoid errors */ +static void finalreport (lua_State *L, int status) { + if (status != LUA_OK) { + const char *msg = (lua_type(L, -1) == LUA_TSTRING) ? lua_tostring(L, -1) + : NULL; + if (msg == NULL) msg = "(error object is not a string)"; + l_message(progname, msg); + lua_pop(L, 1); + } +} + + +static int traceback (lua_State *L) { + const char *msg = lua_tostring(L, 1); + if (msg) + luaL_traceback(L, L, msg, 1); + else if (!lua_isnoneornil(L, 1)) { /* is there an error object? */ + if (!luaL_callmeta(L, 1, "__tostring")) /* try its 'tostring' metamethod */ + lua_pushliteral(L, "(no error message)"); + } + return 1; +} + + +static int docall (lua_State *L, int narg, int nres) { + int status; + int base = lua_gettop(L) - narg; /* function index */ + lua_pushcfunction(L, traceback); /* push traceback function */ + lua_insert(L, base); /* put it under chunk and args */ + globalL = L; /* to be available to 'laction' */ + signal(SIGINT, laction); + status = lua_pcall(L, narg, nres, base); + signal(SIGINT, SIG_DFL); + lua_remove(L, base); /* remove traceback function */ + return status; +} + + +static void print_version (void) { + luai_writestring(LUA_COPYRIGHT, strlen(LUA_COPYRIGHT)); + luai_writeline(); +} + + +static int getargs (lua_State *L, char **argv, int n) { + int narg; + int i; + int argc = 0; + while (argv[argc]) argc++; /* count total number of arguments */ + narg = argc - (n + 1); /* number of arguments to the script */ + luaL_checkstack(L, narg + 3, "too many arguments to script"); + for (i=n+1; i < argc; i++) + lua_pushstring(L, argv[i]); + lua_createtable(L, narg, n + 1); + for (i=0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i - n); + } + return narg; +} + + +static int dofile (lua_State *L, const char *name) { + int status = luaL_loadfile(L, name); + if (status == LUA_OK) status = docall(L, 0, 0); + return report(L, status); +} + + +static int dostring (lua_State *L, const char *s, const char *name) { + int status = luaL_loadbuffer(L, s, strlen(s), name); + if (status == LUA_OK) status = docall(L, 0, 0); + return report(L, status); +} + + +static int dolibrary (lua_State *L, const char *name) { + int status; + lua_getglobal(L, "require"); + lua_pushstring(L, name); + status = docall(L, 1, 1); /* call 'require(name)' */ + if (status == LUA_OK) + lua_setglobal(L, name); /* global[name] = require return */ + return report(L, status); +} + + +static const char *get_prompt (lua_State *L, int firstline) { + const char *p; + lua_getglobal(L, firstline ? "_PROMPT" : "_PROMPT2"); + p = lua_tostring(L, -1); + if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); + return p; +} + +/* mark in error messages for incomplete statements */ +#define EOFMARK "" +#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) + +static int incomplete (lua_State *L, int status) { + if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(L, -1, &lmsg); + if (lmsg >= marklen && strcmp(msg + lmsg - marklen, EOFMARK) == 0) { + lua_pop(L, 1); + return 1; + } + } + return 0; /* else... */ +} + + +static int pushline (lua_State *L, int firstline) { + char buffer[LUA_MAXINPUT]; + char *b = buffer; + size_t l; + const char *prmt = get_prompt(L, firstline); + int readstatus = lua_readline(L, b, prmt); + lua_pop(L, 1); /* remove result from 'get_prompt' */ + if (readstatus == 0) + return 0; /* no input */ + l = strlen(b); + if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ + b[l-1] = '\0'; /* remove it */ + if (firstline && b[0] == '=') /* first line starts with `=' ? */ + lua_pushfstring(L, "return %s", b+1); /* change it to `return' */ + else + lua_pushstring(L, b); + lua_freeline(L, b); + return 1; +} + + +static int loadline (lua_State *L) { + int status; + lua_settop(L, 0); + if (!pushline(L, 1)) + return -1; /* no input */ + for (;;) { /* repeat until gets a complete line */ + size_t l; + const char *line = lua_tolstring(L, 1, &l); + status = luaL_loadbuffer(L, line, l, "=stdin"); + if (!incomplete(L, status)) break; /* cannot try to add lines? */ + if (!pushline(L, 0)) /* no more input? */ + return -1; + lua_pushliteral(L, "\n"); /* add a new line... */ + lua_insert(L, -2); /* ...between the two lines */ + lua_concat(L, 3); /* join them */ + } + lua_saveline(L, 1); + lua_remove(L, 1); /* remove line */ + return status; +} + + +static void dotty (lua_State *L) { + int status; + const char *oldprogname = progname; + progname = NULL; + while ((status = loadline(L)) != -1) { + if (status == LUA_OK) status = docall(L, 0, LUA_MULTRET); + report(L, status); + if (status == LUA_OK && lua_gettop(L) > 0) { /* any result to print? */ + luaL_checkstack(L, LUA_MINSTACK, "too many results to print"); + lua_getglobal(L, "print"); + lua_insert(L, 1); + if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != LUA_OK) + l_message(progname, lua_pushfstring(L, + "error calling " LUA_QL("print") " (%s)", + lua_tostring(L, -1))); + } + } + lua_settop(L, 0); /* clear stack */ + luai_writeline(); + progname = oldprogname; +} + + +static int handle_script (lua_State *L, char **argv, int n) { + int status; + const char *fname; + int narg = getargs(L, argv, n); /* collect arguments */ + lua_setglobal(L, "arg"); + fname = argv[n]; + if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) + fname = NULL; /* stdin */ + status = luaL_loadfile(L, fname); + lua_insert(L, -(narg+1)); + if (status == LUA_OK) + status = docall(L, narg, LUA_MULTRET); + else + lua_pop(L, narg); + return report(L, status); +} + + +/* check that argument has no extra characters at the end */ +#define noextrachars(x) {if ((x)[2] != '\0') return -1;} + + +/* indices of various argument indicators in array args */ +#define has_i 0 /* -i */ +#define has_v 1 /* -v */ +#define has_e 2 /* -e */ +#define has_E 3 /* -E */ + +#define num_has 4 /* number of 'has_*' */ + + +static int collectargs (char **argv, int *args) { + int i; + for (i = 1; argv[i] != NULL; i++) { + if (argv[i][0] != '-') /* not an option? */ + return i; + switch (argv[i][1]) { /* option */ + case '-': + noextrachars(argv[i]); + return (argv[i+1] != NULL ? i+1 : 0); + case '\0': + return i; + case 'E': + args[has_E] = 1; + break; + case 'i': + noextrachars(argv[i]); + args[has_i] = 1; /* go through */ + case 'v': + noextrachars(argv[i]); + args[has_v] = 1; + break; + case 'e': + args[has_e] = 1; /* go through */ + case 'l': /* both options need an argument */ + if (argv[i][2] == '\0') { /* no concatenated argument? */ + i++; /* try next 'argv' */ + if (argv[i] == NULL || argv[i][0] == '-') + return -(i - 1); /* no next argument or it is another option */ + } + break; + default: /* invalid option; return its index... */ + return -i; /* ...as a negative value */ + } + } + return 0; +} + + +static int runargs (lua_State *L, char **argv, int n) { + int i; + for (i = 1; i < n; i++) { + lua_assert(argv[i][0] == '-'); + switch (argv[i][1]) { /* option */ + case 'e': { + const char *chunk = argv[i] + 2; + if (*chunk == '\0') chunk = argv[++i]; + lua_assert(chunk != NULL); + if (dostring(L, chunk, "=(command line)") != LUA_OK) + return 0; + break; + } + case 'l': { + const char *filename = argv[i] + 2; + if (*filename == '\0') filename = argv[++i]; + lua_assert(filename != NULL); + if (dolibrary(L, filename) != LUA_OK) + return 0; /* stop if file fails */ + break; + } + default: break; + } + } + return 1; +} + + +static int handle_luainit (lua_State *L) { + const char *name = "=" LUA_INITVERSION; + const char *init = getenv(name + 1); + if (init == NULL) { + name = "=" LUA_INIT; + init = getenv(name + 1); /* try alternative name */ + } + if (init == NULL) return LUA_OK; + else if (init[0] == '@') + return dofile(L, init+1); + else + return dostring(L, init, name); +} + + +static int pmain (lua_State *L) { + int argc = (int)lua_tointeger(L, 1); + char **argv = (char **)lua_touserdata(L, 2); + int script; + int args[num_has]; + args[has_i] = args[has_v] = args[has_e] = args[has_E] = 0; + if (argv[0] && argv[0][0]) progname = argv[0]; + script = collectargs(argv, args); + if (script < 0) { /* invalid arg? */ + print_usage(argv[-script]); + return 0; + } + if (args[has_v]) print_version(); + if (args[has_E]) { /* option '-E'? */ + lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + } + /* open standard libraries */ + luaL_checkversion(L); + lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ + luaL_openlibs(L); /* open libraries */ + lua_gc(L, LUA_GCRESTART, 0); + if (!args[has_E] && handle_luainit(L) != LUA_OK) + return 0; /* error running LUA_INIT */ + /* execute arguments -e and -l */ + if (!runargs(L, argv, (script > 0) ? script : argc)) return 0; + /* execute main script (if there is one) */ + if (script && handle_script(L, argv, script) != LUA_OK) return 0; + if (args[has_i]) /* -i option? */ + dotty(L); + else if (script == 0 && !args[has_e] && !args[has_v]) { /* no arguments? */ + if (lua_stdin_is_tty()) { + print_version(); + dotty(L); + } + else dofile(L, NULL); /* executes stdin as a file */ + } + lua_pushboolean(L, 1); /* signal no errors */ + return 1; +} + + +int main (int argc, char **argv) { + int status, result; + lua_State *L = luaL_newstate(); /* create state */ + if (L == NULL) { + l_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; + } + /* call 'pmain' in protected mode */ + lua_pushcfunction(L, &pmain); + lua_pushinteger(L, argc); /* 1st argument */ + lua_pushlightuserdata(L, argv); /* 2nd argument */ + status = lua_pcall(L, 2, 1, 0); + result = lua_toboolean(L, -1); /* get result */ + finalreport(L, status); + lua_close(L); + return (result && status == LUA_OK) ? EXIT_SUCCESS : EXIT_FAILURE; +} + diff --git a/lua/lua.h b/lua/lua.h new file mode 100644 index 0000000..149a2c3 --- /dev/null +++ b/lua/lua.h @@ -0,0 +1,444 @@ +/* +** $Id: lua.h,v 1.285.1.2 2013/11/11 12:09:16 roberto Exp $ +** Lua - A Scripting 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_MAJOR "5" +#define LUA_VERSION_MINOR "2" +#define LUA_VERSION_NUM 502 +#define LUA_VERSION_RELEASE "3" + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2013 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 LUAI_FIRSTPSEUDOIDX +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) + + +/* thread status */ +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRGCMM 5 +#define LUA_ERRERR 6 + + +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 + +#define LUA_NUMTAGS 9 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + +/* unsigned integer type */ +typedef LUA_UNSIGNED lua_Unsigned; + + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* +** RCS ident string +*/ +extern const char lua_ident[]; + + +/* +** 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); + + +LUA_API const lua_Number *(lua_version) (lua_State *L); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_absindex) (lua_State *L, int idx); +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 void (lua_copy) (lua_State *L, int fromidx, int toidx); +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 lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Unsigned (lua_tounsignedx) (lua_State *L, int idx, int *isnum); +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_rawlen) (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); + + +/* +** Comparison and arithmetic functions +*/ + +#define LUA_OPADD 0 /* ORDER TM */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPDIV 3 +#define LUA_OPMOD 4 +#define LUA_OPPOW 5 +#define LUA_OPUNM 6 + +LUA_API void (lua_arith) (lua_State *L, int op); + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); + + +/* +** 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_pushunsigned) (lua_State *L, lua_Unsigned n); +LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t l); +LUA_API const char *(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_getglobal) (lua_State *L, const char *var); +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_rawgetp) (lua_State *L, int idx, const void *p); +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_getuservalue) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_setglobal) (lua_State *L, const char *var); +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 void (lua_rawsetp) (lua_State *L, int idx, const void *p); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API void (lua_setuservalue) (lua_State *L, int idx); + + +/* +** 'load' and 'call' functions (load and run Lua code) +*/ +LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx, + lua_CFunction k); +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) + +LUA_API int (lua_getctx) (lua_State *L, int *ctx); + +LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, + int ctx, lua_CFunction k); +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) + +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, + const char *mode); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx, + lua_CFunction k); +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) +LUA_API int (lua_resume) (lua_State *L, lua_State *from, 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 +#define LUA_GCSETMAJORINC 8 +#define LUA_GCISRUNNING 9 +#define LUA_GCGEN 10 +#define LUA_GCINC 11 + +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 void (lua_len) (lua_State *L, int idx); + +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_tonumber(L,i) lua_tonumberx(L,i,NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL) +#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL) + +#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_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_pushglobaltable(L) \ + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILCALL 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 debugger 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 void *(lua_upvalueid) (lua_State *L, int fidx, int n); +LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, + int fidx2, int n2); + +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 linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams;/* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct CallInfo *i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2013 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. +******************************************************************************/ + + +#endif diff --git a/lua/lua.hpp b/lua/lua.hpp new file mode 100644 index 0000000..ec417f5 --- /dev/null +++ b/lua/lua.hpp @@ -0,0 +1,9 @@ +// lua.hpp +// Lua header files for C++ +// <> not supplied automatically because Lua also compiles as C++ + +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} diff --git a/lua/luac b/lua/luac new file mode 100755 index 0000000000000000000000000000000000000000..013c9ae3e99445c426badae0215f55411db85a49 GIT binary patch literal 133648 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 +#include +#include +#include + +#define luac_c +#define LUA_CORE + +#include "lua.h" +#include "lauxlib.h" + +#include "lobject.h" +#include "lstate.h" +#include "lundump.h" + +static void PrintFunction(const Proto* f, int full); +#define luaU_print PrintFunction + +#define PROGNAME "luac" /* default program name */ +#define OUTPUT PROGNAME ".out" /* default output file */ + +static int listing=0; /* list bytecodes? */ +static int dumping=1; /* dump bytecodes? */ +static int stripping=0; /* strip debug information? */ +static char Output[]={ OUTPUT }; /* default output file name */ +static const char* output=Output; /* actual output file name */ +static const char* progname=PROGNAME; /* actual program name */ + +static void fatal(const char* message) +{ + fprintf(stderr,"%s: %s\n",progname,message); + exit(EXIT_FAILURE); +} + +static void cannot(const char* what) +{ + fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); + exit(EXIT_FAILURE); +} + +static void usage(const char* message) +{ + if (*message=='-') + fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); + else + fprintf(stderr,"%s: %s\n",progname,message); + fprintf(stderr, + "usage: %s [options] [filenames]\n" + "Available options are:\n" + " -l list (use -l -l for full listing)\n" + " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" + " -p parse only\n" + " -s strip debug information\n" + " -v show version information\n" + " -- stop handling options\n" + " - stop handling options and process stdin\n" + ,progname,Output); + exit(EXIT_FAILURE); +} + +#define IS(s) (strcmp(argv[i],s)==0) + +static int doargs(int argc, char* argv[]) +{ + int i; + int version=0; + if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; + for (i=1; itop+(i)) + +static const Proto* combine(lua_State* L, int n) +{ + if (n==1) + return toproto(L,-1); + else + { + Proto* f; + int i=n; + if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); + f=toproto(L,-1); + for (i=0; ip[i]=toproto(L,i-n-1); + if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; + } + f->sizelineinfo=0; + return f; + } +} + +static int writer(lua_State* L, const void* p, size_t size, void* u) +{ + UNUSED(L); + return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); +} + +static int pmain(lua_State* L) +{ + int argc=(int)lua_tointeger(L,1); + char** argv=(char**)lua_touserdata(L,2); + const Proto* f; + int i; + if (!lua_checkstack(L,argc)) fatal("too many input files"); + for (i=0; i1); + if (dumping) + { + FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); + if (D==NULL) cannot("open"); + lua_lock(L); + luaU_dump(L,f,writer,D,stripping); + lua_unlock(L); + if (ferror(D)) cannot("write"); + if (fclose(D)) cannot("close"); + } + return 0; +} + +int main(int argc, char* argv[]) +{ + lua_State* L; + int i=doargs(argc,argv); + argc-=i; argv+=i; + if (argc<=0) usage("no input files given"); + L=luaL_newstate(); + if (L==NULL) fatal("cannot create state: not enough memory"); + lua_pushcfunction(L,&pmain); + lua_pushinteger(L,argc); + lua_pushlightuserdata(L,argv); + if (lua_pcall(L,2,0,0)!=LUA_OK) fatal(lua_tostring(L,-1)); + lua_close(L); + return EXIT_SUCCESS; +} + +/* +** $Id: print.c,v 1.69 2013/07/04 01:03:46 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" + +#define VOID(p) ((const void*)(p)) + +static void PrintString(const TString* ts) +{ + const char* s=getstr(ts); + size_t i,n=ts->tsv.len; + printf("%c",'"'); + for (i=0; ik[i]; + switch (ttypenv(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; + } +} + +#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") +#define MYK(x) (-1-(x)) + +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) ? (MYK(INDEXK(b))) : b); + if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); + break; + case iABx: + printf("%d",a); + if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); + if (getBMode(o)==OpArgU) printf(" %d",bx); + break; + case iAsBx: + printf("%d %d",a,sbx); + break; + case iAx: + printf("%d",MYK(ax)); + break; + } + switch (o) + { + case OP_LOADK: + printf("\t; "); PrintConstant(f,bx); + break; + case OP_GETUPVAL: + case OP_SETUPVAL: + printf("\t; %s",UPVALNAME(b)); + break; + case OP_GETTABUP: + printf("\t; %s",UPVALNAME(b)); + if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABUP: + printf("\t; %s",UPVALNAME(a)); + if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } + if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } + 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: + case OP_TFORLOOP: + 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; + case OP_EXTRAARG: + printf("\t; "); PrintConstant(f,ax); + break; + default: + break; + } + printf("\n"); + } +} + +#define SS(x) ((x==1)?"":"s") +#define S(x) (int)(x),SS(x) + +static void PrintHeader(const Proto* f) +{ + const char* s=f->source ? 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 at %p)\n", + (f->linedefined==0)?"main":"function",s, + f->linedefined,f->lastlinedefined, + S(f->sizecode),VOID(f)); + printf("%d%s param%s, %d slot%s, %d upvalue%s, ", + (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), + S(f->maxstacksize),S(f->sizeupvalues)); + printf("%d local%s, %d constant%s, %d function%s\n", + S(f->sizelocvars),S(f->sizek),S(f->sizep)); +} + +static void PrintDebug(const Proto* f) +{ + int i,n; + 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); + } + n=f->sizeupvalues; + printf("upvalues (%d) for %p:\n",n,VOID(f)); + for (i=0; iupvalues[i].instack,f->upvalues[i].idx); + } +} + +static void PrintFunction(const Proto* f, int full) +{ + int i,n=f->sizep; + PrintHeader(f); + PrintCode(f); + if (full) PrintDebug(f); + for (i=0; ip[i],full); +} diff --git a/lua/luaconf.h b/lua/luaconf.h new file mode 100644 index 0000000..18be9a9 --- /dev/null +++ b/lua/luaconf.h @@ -0,0 +1,551 @@ +/* +** $Id: luaconf.h,v 1.176.1.1 2013/04/12 18:48:47 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(LUA_ANSI) && defined(__STRICT_ANSI__) +#define LUA_ANSI +#endif + + +#if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_WIN /* enable goodies for regular Windows platforms */ +#endif + +#if defined(LUA_WIN) +#define LUA_DL_DLL +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#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 */ +#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_LONGLONG /* assume support for long long */ +#endif + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* does not need -ldl */ +#define LUA_USE_READLINE /* needs an extra library: -lreadline */ +#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_LONGLONG /* assume support for long long */ +#endif + + + +/* +@@ LUA_USE_POSIX includes all functionality 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 +#define LUA_USE_GMTIME_R +#endif + + + +/* +@@ 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_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" + +#else /* }{ */ + +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.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_ENV is the name of the variable that holds the current +@@ environment, used to access global names. +** CHANGE it if you do not like this name. +*/ +#define LUA_ENV "_ENV" + + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all auxiliary library functions. +@@ LUAMOD_API is a mark for all standard library opening 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 +#define LUAMOD_API LUALIB_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +@* exported to outside modules. +@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables +@* that are not to be exported to outside modules (LUAI_DDEF for +@* definitions and LUAI_DDEC for declarations). +** 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. Not all elf targets support +** this attribute. Unfortunately, gcc does not offer a way to check +** whether the target offers that support, and those without support +** give a warning about it. To avoid these warnings, change to the +** default definition. +*/ +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#define LUAI_DDEC LUAI_FUNC +#define LUAI_DDEF /* empty */ + +#else /* }{ */ +#define LUAI_FUNC extern +#define LUAI_DDEC extern +#define LUAI_DDEF /* empty */ +#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 + + +/* +@@ luai_writestring/luai_writeline define how 'print' prints its results. +** They are only used in libraries and the stand-alone program. (The #if +** avoids including 'stdio.h' everywhere.) +*/ +#if defined(LUA_LIB) || defined(lua_c) +#include +#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) +#endif + +/* +@@ luai_writestringerror defines how to print error messages. +** (A format string with one argument is enough for Lua...) +*/ +#define luai_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) + + +/* +@@ LUAI_MAXSHORTLEN is the maximum length for short strings, that is, +** strings that are internalized. (Cannot be smaller than reserved words +** or tags for metamethods, as these strings must be internalized; +** #("function") = 8, #("__newindex") = 10.) +*/ +#define LUAI_MAXSHORTLEN 40 + + + +/* +** {================================================================== +** Compatibility with previous versions +** =================================================================== +*/ + +/* +@@ LUA_COMPAT_ALL controls all compatibility options. +** You can define it to get all options, or change specific options +** to fit your specific needs. +*/ +#if defined(LUA_COMPAT_ALL) /* { */ + +/* +@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. +** You can replace it with 'table.unpack'. +*/ +#define LUA_COMPAT_UNPACK + +/* +@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. +** You can replace it with 'package.searchers'. +*/ +#define LUA_COMPAT_LOADERS + +/* +@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. +** You can call your C function directly (with light C functions). +*/ +#define lua_cpcall(L,f,u) \ + (lua_pushcfunction(L, (f)), \ + lua_pushlightuserdata(L,(u)), \ + lua_pcall(L,1,0,0)) + + +/* +@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. +** You can rewrite 'log10(x)' as 'log(x, 10)'. +*/ +#define LUA_COMPAT_LOG10 + +/* +@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base +** library. You can rewrite 'loadstring(s)' as 'load(s)'. +*/ +#define LUA_COMPAT_LOADSTRING + +/* +@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. +*/ +#define LUA_COMPAT_MAXN + +/* +@@ The following macros supply trivial compatibility for some +** changes in the API. The macros themselves document how to +** change your code to avoid using them. +*/ +#define lua_strlen(L,i) lua_rawlen(L, (i)) + +#define lua_objlen(L,i) lua_rawlen(L, (i)) + +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) + +/* +@@ LUA_COMPAT_MODULE controls compatibility with previous +** module functions 'module' (Lua) and 'luaL_register' (C). +*/ +#define LUA_COMPAT_MODULE + +#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 /* } */ + + +/* +@@ LUA_INT32 is an signed integer with exactly 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. Probably you do not need to change +** this. +*/ +#if LUAI_BITSINT >= 32 /* { */ +#define LUA_INT32 int +#define LUAI_UMEM size_t +#define LUAI_MEM ptrdiff_t +#else /* }{ */ +/* 16-bit ints */ +#define LUA_INT32 long +#define LUAI_UMEM unsigned long +#define LUAI_MEM long +#endif /* } */ + + +/* +@@ LUAI_MAXSTACK limits the size of the Lua stack. +** CHANGE it if you need a different limit. This limit is arbitrary; +** its only purpose is to stop Lua to consume unlimited stack +** space (and to reserve some numbers for pseudo-indices). +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_MAXSTACK 1000000 +#else +#define LUAI_MAXSTACK 15000 +#endif + +/* reserve some space for error handling */ +#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) + + + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +** CHANGE it if it uses too much C-stack space. +*/ +#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. +*/ +#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 */ + + +/* +@@ l_mathop allows the addition of an 'l' or 'f' to all math operations +*/ +#define l_mathop(x) (x) + + +/* +@@ lua_str2number converts a decimal numeric string to a number. +@@ lua_strx2number converts an hexadecimal numeric string to a number. +** In C99, 'strtod' does both conversions. C89, however, has no function +** to convert floating hexadecimal strings to numbers. For these +** systems, you can leave 'lua_strx2number' undefined and Lua will +** provide its own implementation. +*/ +#define lua_str2number(s,p) strtod((s), (p)) + +#if defined(LUA_USE_STRTODHEX) +#define lua_strx2number(s,p) strtod((s), (p)) +#endif + + +/* +@@ The luai_num* macros define the primitive operations over numbers. +*/ + +/* the following operations need the math library */ +#if defined(lobject_c) || defined(lvm_c) +#include +#define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b)) +#define luai_numpow(L,a,b) (l_mathop(pow)(a,b)) +#endif + +/* these are quite standard operations */ +#if defined(LUA_CORE) +#define luai_numadd(L,a,b) ((a)+(b)) +#define luai_numsub(L,a,b) ((a)-(b)) +#define luai_nummul(L,a,b) ((a)*(b)) +#define luai_numdiv(L,a,b) ((a)/(b)) +#define luai_numunm(L,a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(L,a,b) ((a)<(b)) +#define luai_numle(L,a,b) ((a)<=(b)) +#define luai_numisnan(L,a) (!luai_numeq((a), (a))) +#endif + + + +/* +@@ 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_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned. +** It must have at least 32 bits. +*/ +#define LUA_UNSIGNED unsigned LUA_INT32 + + + +/* +** Some tricks with doubles +*/ + +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ +/* +** The next definitions activate some tricks to speed up the +** conversion from doubles to integer types, mainly to LUA_UNSIGNED. +** +@@ LUA_MSASMTRICK uses Microsoft assembler to avoid clashes with a +** DirectX idiosyncrasy. +** +@@ LUA_IEEE754TRICK uses a trick that should work on any machine +** using IEEE754 with a 32-bit integer type. +** +@@ LUA_IEEELL extends the trick to LUA_INTEGER; should only be +** defined when LUA_INTEGER is a 32-bit integer. +** +@@ LUA_IEEEENDIAN is the endianness of doubles in your machine +** (0 for little endian, 1 for big endian); if not defined, Lua will +** check it dynamically for LUA_IEEE754TRICK (but not for LUA_NANTRICK). +** +@@ LUA_NANTRICK controls the use of a trick to pack all types into +** a single double value, using NaN values to represent non-number +** values. The trick only works on 32-bit machines (ints and pointers +** are 32-bit values) with numbers represented as IEEE 754-2008 doubles +** with conventional endianess (12345678 or 87654321), in CPUs that do +** not produce signaling NaN values (all NaNs are quiet). +*/ + +/* Microsoft compiler on a Pentium (32 bit) ? */ +#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ + +#define LUA_MSASMTRICK +#define LUA_IEEEENDIAN 0 +#define LUA_NANTRICK + + +/* pentium 32 bits? */ +#elif defined(__i386__) || defined(__i386) || defined(__X86__) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEELL +#define LUA_IEEEENDIAN 0 +#define LUA_NANTRICK + +/* pentium 64 bits? */ +#elif defined(__x86_64) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEEENDIAN 0 + +#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ + +#define LUA_IEEE754TRICK +#define LUA_IEEEENDIAN 1 + +#else /* }{ */ + +/* assume IEEE754 and a 32-bit integer type */ +#define LUA_IEEE754TRICK + +#endif /* } */ + +#endif /* } */ + +/* }================================================================== */ + + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + +#endif + diff --git a/lua/lualib.h b/lua/lualib.h new file mode 100644 index 0000000..da82005 --- /dev/null +++ b/lua/lualib.h @@ -0,0 +1,55 @@ +/* +** $Id: lualib.h,v 1.43.1.1 2013/04/12 18:48:47 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + + +LUAMOD_API int (luaopen_base) (lua_State *L); + +#define LUA_COLIBNAME "coroutine" +LUAMOD_API int (luaopen_coroutine) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUAMOD_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUAMOD_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUAMOD_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUAMOD_API int (luaopen_string) (lua_State *L); + +#define LUA_BITLIBNAME "bit32" +LUAMOD_API int (luaopen_bit32) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUAMOD_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUAMOD_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUAMOD_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#if !defined(lua_assert) +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/lua/lundump.c b/lua/lundump.c new file mode 100644 index 0000000..4163cb5 --- /dev/null +++ b/lua/lundump.c @@ -0,0 +1,258 @@ +/* +** $Id: lundump.c,v 2.22.1.1 2013/04/12 18:48:47 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; + +static l_noret error(LoadState* S, const char* why) +{ + luaO_pushfstring(S->L,"%s: %s precompiled chunk",S->name,why); + luaD_throw(S->L,LUA_ERRSYNTAX); +} + +#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) + +#if !defined(luai_verifycode) +#define luai_verifycode(L,b,f) /* empty */ +#endif + +static void LoadBlock(LoadState* S, void* b, size_t size) +{ + if (luaZ_read(S->Z,b,size)!=0) error(S,"truncated"); +} + +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) error(S,"corrupted"); + 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*sizeof(char)); + 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 void LoadFunction(LoadState* S, Proto* f); + +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)); + break; + case LUA_TNUMBER: + setnvalue(o,LoadNumber(S)); + break; + case LUA_TSTRING: + setsvalue2n(S->L,o,LoadString(S)); + break; + default: lua_assert(0); + } + } + 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]=luaF_newproto(S->L); + LoadFunction(S,f->p[i]); + } +} + +static void LoadUpvalues(LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->upvalues=luaM_newvector(S->L,n,Upvaldesc); + f->sizeupvalues=n; + for (i=0; iupvalues[i].name=NULL; + for (i=0; iupvalues[i].instack=LoadByte(S); + f->upvalues[i].idx=LoadByte(S); + } +} + +static void LoadDebug(LoadState* S, Proto* f) +{ + int i,n; + f->source=LoadString(S); + 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); + for (i=0; iupvalues[i].name=LoadString(S); +} + +static void LoadFunction(LoadState* S, Proto* f) +{ + f->linedefined=LoadInt(S); + f->lastlinedefined=LoadInt(S); + f->numparams=LoadByte(S); + f->is_vararg=LoadByte(S); + f->maxstacksize=LoadByte(S); + LoadCode(S,f); + LoadConstants(S,f); + LoadUpvalues(S,f); + LoadDebug(S,f); +} + +/* the code below must be consistent with the code in luaU_header */ +#define N0 LUAC_HEADERSIZE +#define N1 (sizeof(LUA_SIGNATURE)-sizeof(char)) +#define N2 N1+2 +#define N3 N2+6 + +static void LoadHeader(LoadState* S) +{ + lu_byte h[LUAC_HEADERSIZE]; + lu_byte s[LUAC_HEADERSIZE]; + luaU_header(h); + memcpy(s,h,sizeof(char)); /* first char already read */ + LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char)); + if (memcmp(h,s,N0)==0) return; + if (memcmp(h,s,N1)!=0) error(S,"not a"); + if (memcmp(h,s,N2)!=0) error(S,"version mismatch in"); + if (memcmp(h,s,N3)!=0) error(S,"incompatible"); else error(S,"corrupted"); +} + +/* +** load precompiled chunk +*/ +Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) +{ + LoadState S; + Closure* cl; + 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); + cl=luaF_newLclosure(L,1); + setclLvalue(L,L->top,cl); incr_top(L); + cl->l.p=luaF_newproto(L); + LoadFunction(&S,cl->l.p); + if (cl->l.p->sizeupvalues != 1) + { + Proto* p=cl->l.p; + cl=luaF_newLclosure(L,cl->l.p->sizeupvalues); + cl->l.p=p; + setclLvalue(L,L->top-1,cl); + } + luai_verifycode(L,buff,cl->l.p); + return cl; +} + +#define MYINT(s) (s[0]-'0') +#define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR) +#define FORMAT 0 /* this is the official format */ + +/* +* make header for precompiled chunks +* if you change the code below be sure to update LoadHeader and FORMAT above +* and LUAC_HEADERSIZE in lundump.h +*/ +void luaU_header (lu_byte* h) +{ + int x=1; + memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-sizeof(char)); + h+=sizeof(LUA_SIGNATURE)-sizeof(char); + *h++=cast_byte(VERSION); + *h++=cast_byte(FORMAT); + *h++=cast_byte(*(char*)&x); /* endianness */ + *h++=cast_byte(sizeof(int)); + *h++=cast_byte(sizeof(size_t)); + *h++=cast_byte(sizeof(Instruction)); + *h++=cast_byte(sizeof(lua_Number)); + *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */ + memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char)); +} diff --git a/lua/lundump.h b/lua/lundump.h new file mode 100644 index 0000000..5255db2 --- /dev/null +++ b/lua/lundump.h @@ -0,0 +1,28 @@ +/* +** $Id: lundump.h,v 1.39.1.1 2013/04/12 18:48:47 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 Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); + +/* make header; from lundump.c */ +LUAI_FUNC void luaU_header (lu_byte* 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); + +/* data to catch conversion errors */ +#define LUAC_TAIL "\x19\x93\r\n\x1a\n" + +/* size in bytes of header of binary files */ +#define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char)) + +#endif diff --git a/lua/lvm.c b/lua/lvm.c new file mode 100644 index 0000000..141b9fd --- /dev/null +++ b/lua/lvm.c @@ -0,0 +1,867 @@ +/* +** $Id: lvm.c,v 2.155.1.1 2013/04/12 18:48:47 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), tsvalue(obj)->len, &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); + int l = lua_number2str(s, n); + setsvalue2s(L, obj, luaS_newlstr(L, s, l)); + return 1; + } +} + + +static void traceexec (lua_State *L) { + CallInfo *ci = L->ci; + lu_byte mask = L->hookmask; + int counthook = ((mask & LUA_MASKCOUNT) && L->hookcount == 0); + if (counthook) + resethookcount(L); /* reset count */ + if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ + ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ + return; /* do not call hook again (VM yielded, so it did not move) */ + } + if (counthook) + luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ + if (mask & LUA_MASKLINE) { + Proto *p = ci_func(ci)->p; + int npc = pcRel(ci->u.l.savedpc, p); + int newline = getfuncline(p, npc); + if (npc == 0 || /* call linehook when enter a new function, */ + ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ + newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ + luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ + } + L->oldpc = ci->u.l.savedpc; + if (L->status == LUA_YIELD) { /* did hook yield? */ + if (counthook) + L->hookcount = 1; /* undo decrement to zero */ + ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ + ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ + ci->func = L->top - 1; /* protect stack below results */ + luaD_throw(L, LUA_YIELD); + } +} + + +static void callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, TValue *p3, int hasres) { + ptrdiff_t result = savestack(L, p3); + setobj2s(L, L->top++, f); /* push function */ + setobj2s(L, L->top++, p1); /* 1st argument */ + setobj2s(L, L->top++, p2); /* 2nd argument */ + if (!hasres) /* no result? 'p3' is third argument */ + setobj2s(L, L->top++, p3); /* 3rd argument */ + /* metamethod may yield only when called from Lua code */ + luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); + if (hasres) { /* if has result, move it to its place */ + p3 = restorestack(L, result); + setobjs2s(L, p3, --L->top); + } +} + + +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 not 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)) { + callTM(L, tm, t, key, val, 1); + 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 = cast(TValue *, luaH_get(h, key)); + /* if previous value is not nil, there must be a previous entry + in the table; moreover, a metamethod has no relevance */ + if (!ttisnil(oldval) || + /* previous value is nil; must check the metamethod */ + ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && + /* no metamethod; is there a previous entry in the table? */ + (oldval != luaO_nilobject || + /* no previous entry; must create one. (The next test is + always true; we only need the assignment.) */ + (oldval = luaH_newkey(L, h, key), 1)))) { + /* no metamethod and (now) there is an entry with given key */ + setobj2t(L, oldval, val); /* assign new value to that entry */ + invalidateTMcache(h); + luaC_barrierback(L, obj2gco(h), val); + return; + } + /* else will try the metamethod */ + } + else /* not a table; check metamethod */ + if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); + /* there is a metamethod */ + if (ttisfunction(tm)) { + callTM(L, tm, t, key, val, 0); + 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; + callTM(L, tm, p1, p2, res, 1); + return 1; +} + + +static const TValue *get_equalTM (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 (luaV_rawequalobj(tm1, tm2)) /* same metamethods? */ + return tm1; + return NULL; +} + + +static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, + TMS event) { + if (!call_binTM(L, p1, p2, L->top, event)) + return -1; /* no metamethod */ + else + 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 (ttisnumber(l) && ttisnumber(r)) + return luai_numlt(L, nvalue(l), nvalue(r)); + else if (ttisstring(l) && ttisstring(r)) + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; + else if ((res = call_orderTM(L, l, r, TM_LT)) < 0) + luaG_ordererror(L, l, r); + return res; +} + + +int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { + int res; + if (ttisnumber(l) && ttisnumber(r)) + return luai_numle(L, nvalue(l), nvalue(r)); + else if (ttisstring(l) && ttisstring(r)) + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; + else if ((res = call_orderTM(L, l, r, TM_LE)) >= 0) /* first try `le' */ + return res; + else if ((res = call_orderTM(L, r, l, TM_LT)) < 0) /* else try `lt' */ + luaG_ordererror(L, l, r); + return !res; +} + + +/* +** equality of Lua values. L == NULL means raw equality (no metamethods) +*/ +int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2) { + const TValue *tm; + lua_assert(ttisequal(t1, 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_TLCF: return fvalue(t1) == fvalue(t2); + case LUA_TSHRSTR: return eqshrstr(rawtsvalue(t1), rawtsvalue(t2)); + case LUA_TLNGSTR: return luaS_eqlngstr(rawtsvalue(t1), rawtsvalue(t2)); + case LUA_TUSERDATA: { + if (uvalue(t1) == uvalue(t2)) return 1; + else if (L == NULL) return 0; + tm = get_equalTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: { + if (hvalue(t1) == hvalue(t2)) return 1; + else if (L == NULL) return 0; + tm = get_equalTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + default: + lua_assert(iscollectable(t1)); + return gcvalue(t1) == gcvalue(t2); + } + if (tm == NULL) return 0; /* no TM? */ + callTM(L, tm, t1, t2, L->top, 1); /* call TM */ + return !l_isfalse(L->top); +} + + +void luaV_concat (lua_State *L, int total) { + lua_assert(total >= 2); + do { + StkId top = L->top; + 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 operand is empty? */ + (void)tostring(L, top - 2); /* result is first operand */ + else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { + setobjs2s(L, top - 2, top - 1); /* result is second op. */ + } + else { + /* at least two non-empty string values; get as many as possible */ + size_t tl = tsvalue(top-1)->len; + char *buffer; + int i; + /* collect total length */ + for (i = 1; i < total && tostring(L, top-i-1); i++) { + size_t l = tsvalue(top-i-1)->len; + if (l >= (MAX_SIZET/sizeof(char)) - tl) + luaG_runerror(L, "string length overflow"); + tl += l; + } + buffer = luaZ_openspace(L, &G(L)->buff, tl); + tl = 0; + n = i; + do { /* concat all strings */ + size_t l = tsvalue(top-i)->len; + memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); + tl += l; + } while (--i > 0); + setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); + } + total -= n-1; /* got 'n' strings to create 1 new */ + L->top -= n-1; /* popped 'n' strings and pushed one */ + } while (total > 1); /* repeat until only 1 result left */ +} + + +void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { + const TValue *tm; + switch (ttypenv(rb)) { + case LUA_TTABLE: { + Table *h = hvalue(rb); + tm = fasttm(L, h->metatable, TM_LEN); + if (tm) break; /* metamethod? break switch to call it */ + setnvalue(ra, cast_num(luaH_getn(h))); /* else primitive len */ + return; + } + case LUA_TSTRING: { + setnvalue(ra, cast_num(tsvalue(rb)->len)); + return; + } + default: { /* try metamethod */ + tm = luaT_gettmbyobj(L, rb, TM_LEN); + if (ttisnil(tm)) /* no metamethod? */ + luaG_typeerror(L, rb, "get length of"); + break; + } + } + callTM(L, tm, rb, rb, ra, 1); +} + + +void luaV_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 res = luaO_arith(op - TM_ADD + LUA_OPADD, nvalue(b), nvalue(c)); + setnvalue(ra, res); + } + else if (!call_binTM(L, rb, rc, ra, op)) + luaG_aritherror(L, rb, rc); +} + + +/* +** check whether cached closure in prototype 'p' may be reused, that is, +** whether there is a cached closure with the same upvalues needed by +** new closure to be created. +*/ +static Closure *getcached (Proto *p, UpVal **encup, StkId base) { + Closure *c = p->cache; + if (c != NULL) { /* is there a cached closure? */ + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; + int i; + for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ + TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; + if (c->l.upvals[i]->v != v) + return NULL; /* wrong upvalue; cannot reuse closure */ + } + } + return c; /* return cached closure (or NULL if no cached closure) */ +} + + +/* +** create a new Lua closure, push it in the stack, and initialize +** its upvalues. Note that the call to 'luaC_barrierproto' must come +** before the assignment to 'p->cache', as the function needs the +** original value of that field. +*/ +static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, + StkId ra) { + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; + int i; + Closure *ncl = luaF_newLclosure(L, nup); + ncl->l.p = p; + setclLvalue(L, ra, ncl); /* anchor new closure in stack */ + for (i = 0; i < nup; i++) { /* fill in its upvalues */ + if (uv[i].instack) /* upvalue refers to local variable? */ + ncl->l.upvals[i] = luaF_findupval(L, base + uv[i].idx); + else /* get upvalue from enclosing function */ + ncl->l.upvals[i] = encup[uv[i].idx]; + } + luaC_barrierproto(L, p, ncl); + p->cache = ncl; /* save it on cache for reuse */ +} + + +/* +** finish execution of an opcode interrupted by an yield +*/ +void luaV_finishOp (lua_State *L) { + CallInfo *ci = L->ci; + StkId base = ci->u.l.base; + Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ + OpCode op = GET_OPCODE(inst); + switch (op) { /* finish its execution */ + case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: + case OP_MOD: case OP_POW: case OP_UNM: case OP_LEN: + case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { + setobjs2s(L, base + GETARG_A(inst), --L->top); + break; + } + case OP_LE: case OP_LT: case OP_EQ: { + int res = !l_isfalse(L->top - 1); + L->top--; + /* metamethod should not be called when operand is K */ + lua_assert(!ISK(GETARG_B(inst))); + if (op == OP_LE && /* "<=" using "<" instead? */ + ttisnil(luaT_gettmbyobj(L, base + GETARG_B(inst), TM_LE))) + res = !res; /* invert result */ + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); + if (res != GETARG_A(inst)) /* condition failed? */ + ci->u.l.savedpc++; /* skip jump instruction */ + break; + } + case OP_CONCAT: { + StkId top = L->top - 1; /* top when 'call_binTM' was called */ + int b = GETARG_B(inst); /* first element to concatenate */ + int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ + setobj2s(L, top - 2, top); /* put TM result in proper position */ + if (total > 1) { /* are there elements to concat? */ + L->top = top - 1; /* top is one after last element (at top-2) */ + luaV_concat(L, total); /* concat them (may yield again) */ + } + /* move final result to final position */ + setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); + L->top = ci->top; /* restore top */ + break; + } + case OP_TFORCALL: { + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); + L->top = ci->top; /* correct top */ + break; + } + case OP_CALL: { + if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ + L->top = ci->top; /* adjust results */ + break; + } + case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: + break; + default: lua_assert(0); + } +} + + + +/* +** some macros for common tasks in `luaV_execute' +*/ + +#if !defined luai_runtimecheck +#define luai_runtimecheck(L, c) /* void */ +#endif + + +#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) \ + (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++))) + + +/* execute a jump instruction */ +#define dojump(ci,i,e) \ + { int a = GETARG_A(i); \ + if (a > 0) luaF_close(L, ci->u.l.base + a - 1); \ + ci->u.l.savedpc += GETARG_sBx(i) + e; } + +/* for test instructions, execute the jump instruction that follows it */ +#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } + + +#define Protect(x) { {x;}; base = ci->u.l.base; } + +#define checkGC(L,c) \ + Protect( luaC_condGC(L,{L->top = (c); /* limit of live values */ \ + luaC_step(L); \ + L->top = ci->top;}) /* restore top */ \ + luai_threadyield(L); ) + + +#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(L, nb, nc)); \ + } \ + else { Protect(luaV_arith(L, ra, rb, rc, tm)); } } + + +#define vmdispatch(o) switch(o) +#define vmcase(l,b) case l: {b} break; +#define vmcasenb(l,b) case l: {b} /* nb = no break */ + +void luaV_execute (lua_State *L) { + CallInfo *ci = L->ci; + LClosure *cl; + TValue *k; + StkId base; + newframe: /* reentry point when frame changes (call/return) */ + lua_assert(ci == L->ci); + cl = clLvalue(ci->func); + k = cl->p->k; + base = ci->u.l.base; + /* main loop of interpreter */ + for (;;) { + Instruction i = *(ci->u.l.savedpc++); + StkId ra; + if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && + (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { + Protect(traceexec(L)); + } + /* WARNING: several calls may realloc the stack and invalidate `ra' */ + ra = RA(i); + lua_assert(base == ci->u.l.base); + lua_assert(base <= L->top && L->top < L->stack + L->stacksize); + vmdispatch (GET_OPCODE(i)) { + vmcase(OP_MOVE, + setobjs2s(L, ra, RB(i)); + ) + vmcase(OP_LOADK, + TValue *rb = k + GETARG_Bx(i); + setobj2s(L, ra, rb); + ) + vmcase(OP_LOADKX, + TValue *rb; + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); + rb = k + GETARG_Ax(*ci->u.l.savedpc++); + setobj2s(L, ra, rb); + ) + vmcase(OP_LOADBOOL, + setbvalue(ra, GETARG_B(i)); + if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ + ) + vmcase(OP_LOADNIL, + int b = GETARG_B(i); + do { + setnilvalue(ra++); + } while (b--); + ) + vmcase(OP_GETUPVAL, + int b = GETARG_B(i); + setobj2s(L, ra, cl->upvals[b]->v); + ) + vmcase(OP_GETTABUP, + int b = GETARG_B(i); + Protect(luaV_gettable(L, cl->upvals[b]->v, RKC(i), ra)); + ) + vmcase(OP_GETTABLE, + Protect(luaV_gettable(L, RB(i), RKC(i), ra)); + ) + vmcase(OP_SETTABUP, + int a = GETARG_A(i); + Protect(luaV_settable(L, cl->upvals[a]->v, RKB(i), RKC(i))); + ) + vmcase(OP_SETUPVAL, + UpVal *uv = cl->upvals[GETARG_B(i)]; + setobj(L, uv->v, ra); + luaC_barrier(L, uv, ra); + ) + vmcase(OP_SETTABLE, + Protect(luaV_settable(L, ra, RKB(i), RKC(i))); + ) + vmcase(OP_NEWTABLE, + int b = GETARG_B(i); + int c = GETARG_C(i); + Table *t = luaH_new(L); + sethvalue(L, ra, t); + if (b != 0 || c != 0) + luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); + checkGC(L, ra + 1); + ) + vmcase(OP_SELF, + StkId rb = RB(i); + setobjs2s(L, ra+1, rb); + Protect(luaV_gettable(L, rb, RKC(i), ra)); + ) + vmcase(OP_ADD, + arith_op(luai_numadd, TM_ADD); + ) + vmcase(OP_SUB, + arith_op(luai_numsub, TM_SUB); + ) + vmcase(OP_MUL, + arith_op(luai_nummul, TM_MUL); + ) + vmcase(OP_DIV, + arith_op(luai_numdiv, TM_DIV); + ) + vmcase(OP_MOD, + arith_op(luai_nummod, TM_MOD); + ) + vmcase(OP_POW, + arith_op(luai_numpow, TM_POW); + ) + vmcase(OP_UNM, + TValue *rb = RB(i); + if (ttisnumber(rb)) { + lua_Number nb = nvalue(rb); + setnvalue(ra, luai_numunm(L, nb)); + } + else { + Protect(luaV_arith(L, ra, rb, rb, TM_UNM)); + } + ) + vmcase(OP_NOT, + TValue *rb = RB(i); + int res = l_isfalse(rb); /* next assignment may change this value */ + setbvalue(ra, res); + ) + vmcase(OP_LEN, + Protect(luaV_objlen(L, ra, RB(i))); + ) + vmcase(OP_CONCAT, + int b = GETARG_B(i); + int c = GETARG_C(i); + StkId rb; + L->top = base + c + 1; /* mark the end of concat operands */ + Protect(luaV_concat(L, c - b + 1)); + ra = RA(i); /* 'luav_concat' may invoke TMs and move the stack */ + rb = b + base; + setobjs2s(L, ra, rb); + checkGC(L, (ra >= rb ? ra + 1 : rb)); + L->top = ci->top; /* restore top */ + ) + vmcase(OP_JMP, + dojump(ci, i, 0); + ) + vmcase(OP_EQ, + TValue *rb = RKB(i); + TValue *rc = RKC(i); + Protect( + if (cast_int(equalobj(L, rb, rc)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + ) + vmcase(OP_LT, + Protect( + if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + ) + vmcase(OP_LE, + Protect( + if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + ) + vmcase(OP_TEST, + if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + vmcase(OP_TESTSET, + TValue *rb = RB(i); + if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) + ci->u.l.savedpc++; + else { + setobjs2s(L, ra, rb); + donextjump(ci); + } + ) + vmcase(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 */ + if (luaD_precall(L, ra, nresults)) { /* C function? */ + if (nresults >= 0) L->top = ci->top; /* adjust results */ + base = ci->u.l.base; + } + else { /* Lua function */ + ci = L->ci; + ci->callstatus |= CIST_REENTRY; + goto newframe; /* restart luaV_execute over new Lua function */ + } + ) + vmcase(OP_TAILCALL, + int b = GETARG_B(i); + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); + if (luaD_precall(L, ra, LUA_MULTRET)) /* C function? */ + base = ci->u.l.base; + else { + /* tail call: put called frame (n) in place of caller one (o) */ + CallInfo *nci = L->ci; /* called frame */ + CallInfo *oci = nci->previous; /* caller frame */ + StkId nfunc = nci->func; /* called function */ + StkId ofunc = oci->func; /* caller function */ + /* last stack slot filled by 'precall' */ + StkId lim = nci->u.l.base + getproto(nfunc)->numparams; + int aux; + /* close all upvalues from previous call */ + if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); + /* move new frame into old one */ + for (aux = 0; nfunc + aux < lim; aux++) + setobjs2s(L, ofunc + aux, nfunc + aux); + oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ + oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ + oci->u.l.savedpc = nci->u.l.savedpc; + oci->callstatus |= CIST_TAIL; /* function was tail called */ + ci = L->ci = oci; /* remove new frame */ + lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); + goto newframe; /* restart luaV_execute over new Lua function */ + } + ) + vmcasenb(OP_RETURN, + int b = GETARG_B(i); + if (b != 0) L->top = ra+b-1; + if (cl->p->sizep > 0) luaF_close(L, base); + b = luaD_poscall(L, ra); + if (!(ci->callstatus & CIST_REENTRY)) /* 'ci' still the called one */ + return; /* external invocation: return */ + else { /* invocation via reentry: continue execution */ + ci = L->ci; + if (b) L->top = ci->top; + lua_assert(isLua(ci)); + lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); + goto newframe; /* restart luaV_execute over new Lua function */ + } + ) + vmcase(OP_FORLOOP, + lua_Number step = nvalue(ra+2); + lua_Number idx = luai_numadd(L, nvalue(ra), step); /* increment index */ + lua_Number limit = nvalue(ra+1); + if (luai_numlt(L, 0, step) ? luai_numle(L, idx, limit) + : luai_numle(L, limit, idx)) { + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + setnvalue(ra, idx); /* update internal index... */ + setnvalue(ra+3, idx); /* ...and external index */ + } + ) + vmcase(OP_FORPREP, + const TValue *init = ra; + const TValue *plimit = ra+1; + const TValue *pstep = ra+2; + 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(L, nvalue(ra), nvalue(pstep))); + ci->u.l.savedpc += GETARG_sBx(i); + ) + vmcasenb(OP_TFORCALL, + 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), 1)); + L->top = ci->top; + i = *(ci->u.l.savedpc++); /* go to next instruction */ + ra = RA(i); + lua_assert(GET_OPCODE(i) == OP_TFORLOOP); + goto l_tforloop; + ) + vmcase(OP_TFORLOOP, + l_tforloop: + if (!ttisnil(ra + 1)) { /* continue loop? */ + setobjs2s(L, ra, ra + 1); /* save control variable */ + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + } + ) + vmcase(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; + if (c == 0) { + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); + c = GETARG_Ax(*ci->u.l.savedpc++); + } + luai_runtimecheck(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-allocate it at once */ + for (; n > 0; n--) { + TValue *val = ra+n; + luaH_setint(L, h, last--, val); + luaC_barrierback(L, obj2gco(h), val); + } + L->top = ci->top; /* correct top (in case of previous open call) */ + ) + vmcase(OP_CLOSURE, + Proto *p = cl->p->p[GETARG_Bx(i)]; + Closure *ncl = getcached(p, cl->upvals, base); /* cached closure */ + if (ncl == NULL) /* no match? */ + pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ + else + setclLvalue(L, ra, ncl); /* push cashed closure */ + checkGC(L, ra + 1); + ) + vmcase(OP_VARARG, + int b = GETARG_B(i) - 1; + int j; + int n = cast_int(base - ci->func) - cl->p->numparams - 1; + if (b < 0) { /* B == 0? */ + b = n; /* get all var. arguments */ + Protect(luaD_checkstack(L, n)); + ra = RA(i); /* previous call may change the stack */ + L->top = ra + n; + } + for (j = 0; j < b; j++) { + if (j < n) { + setobjs2s(L, ra + j, base - n + j); + } + else { + setnilvalue(ra + j); + } + } + ) + vmcase(OP_EXTRAARG, + lua_assert(0); + ) + } + } +} + diff --git a/lua/lvm.h b/lua/lvm.h new file mode 100644 index 0000000..5380270 --- /dev/null +++ b/lua/lvm.h @@ -0,0 +1,44 @@ +/* +** $Id: lvm.h,v 2.18.1.1 2013/04/12 18:48:47 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) (ttisstring(o) || (luaV_tostring(L, o))) + +#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) + +#define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2)) + +#define luaV_rawequalobj(o1,o2) equalobj(NULL,o1,o2) + + +/* not to called directly */ +LUAI_FUNC int luaV_equalobj_ (lua_State *L, const TValue *t1, const TValue *t2); + + +LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); +LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); +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_finishOp (lua_State *L); +LUAI_FUNC void luaV_execute (lua_State *L); +LUAI_FUNC void luaV_concat (lua_State *L, int total); +LUAI_FUNC void luaV_arith (lua_State *L, StkId ra, const TValue *rb, + const TValue *rc, TMS op); +LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); + +#endif diff --git a/lua/lzio.c b/lua/lzio.c new file mode 100644 index 0000000..20efea9 --- /dev/null +++ b/lua/lzio.c @@ -0,0 +1,76 @@ +/* +** $Id: lzio.c,v 1.35.1.1 2013/04/12 18:48:47 roberto Exp $ +** Buffered streams +** 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; /* discount char being returned */ + z->p = buff; + return cast_uchar(*(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 (z->n == 0) { /* no bytes in buffer? */ + if (luaZ_fill(z) == EOZ) /* try to read more */ + return n; /* no more input; return number of missing bytes */ + else { + z->n++; /* luaZ_fill consumed first byte; put it back */ + z->p--; + } + } + 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; +} + + diff --git a/lua/lzio.h b/lua/lzio.h new file mode 100644 index 0000000..441f747 --- /dev/null +++ b/lua/lzio.h @@ -0,0 +1,65 @@ +/* +** $Id: lzio.h,v 1.26.1.1 2013/04/12 18:48:47 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 zgetc(z) (((z)->n--)>0 ? cast_uchar(*(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 */ + + + +/* --------- Private Part ------------------ */ + +struct Zio { + size_t n; /* bytes still unread */ + const char *p; /* current position in buffer */ + lua_Reader reader; /* reader function */ + void* data; /* additional data */ + lua_State *L; /* Lua state (for reader) */ +}; + + +LUAI_FUNC int luaZ_fill (ZIO *z); + +#endif diff --git a/md5.c b/md5.c new file mode 100644 index 0000000..facab82 --- /dev/null +++ b/md5.c @@ -0,0 +1,394 @@ +// MD5 code originally from http://sourceforge.net/projects/libmd5-rfc/ +// License: zlib. +// I cleaned it up a little for MojoSetup's specific purposes. --ryan. + +/* + Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved. + + 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. + + L. Peter Deutsch + ghost@aladdin.com + + */ +/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */ +/* + Independent implementation of MD5 (RFC 1321). + + This code implements the MD5 Algorithm defined in RFC 1321, whose + text is available at + http://www.ietf.org/rfc/rfc1321.txt + The code is derived from the text of the RFC, including the test suite + (section A.5) but excluding the rest of Appendix A. It does not include + any code or documentation that is identified in the RFC as being + copyrighted. + + The original and principal author of md5.c is L. Peter Deutsch + . Other authors are noted in the change history + that follows (in reverse chronological order): + + 2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order + either statically or dynamically; added missing #include + in library. + 2002-03-11 lpd Corrected argument list for main(), and added int return + type, in test program and T value program. + 2002-02-21 lpd Added missing #include in test program. + 2000-07-03 lpd Patched to eliminate warnings about "constant is + unsigned in ANSI C, signed in traditional"; made test program + self-checking. + 1999-11-04 lpd Edited comments slightly for automatic TOC extraction. + 1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5). + 1999-05-03 lpd Original version. + */ + +#include + +#include "md5.h" + +#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */ +//#ifdef ARCH_IS_BIG_ENDIAN +//# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1) +//#else +//# define BYTE_ORDER 0 +//#endif +#if PLATFORM_BIGENDIAN +# define BYTE_ORDER 1 +#else +# define BYTE_ORDER -1 +#endif + +#define T_MASK ((uint32_t)~0) +#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87) +#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9) +#define T3 0x242070db +#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111) +#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050) +#define T6 0x4787c62a +#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec) +#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe) +#define T9 0x698098d8 +#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850) +#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e) +#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841) +#define T13 0x6b901122 +#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c) +#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71) +#define T16 0x49b40821 +#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d) +#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf) +#define T19 0x265e5a51 +#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855) +#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2) +#define T22 0x02441453 +#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e) +#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437) +#define T25 0x21e1cde6 +#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829) +#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278) +#define T28 0x455a14ed +#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa) +#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07) +#define T31 0x676f02d9 +#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375) +#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd) +#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e) +#define T35 0x6d9d6122 +#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3) +#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb) +#define T38 0x4bdecfa9 +#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f) +#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f) +#define T41 0x289b7ec6 +#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805) +#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a) +#define T44 0x04881d05 +#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6) +#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a) +#define T47 0x1fa27cf8 +#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a) +#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb) +#define T50 0x432aff97 +#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58) +#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6) +#define T53 0x655b59c3 +#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d) +#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82) +#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e) +#define T57 0x6fa87e4f +#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f) +#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb) +#define T60 0x4e0811a1 +#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d) +#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca) +#define T63 0x2ad7d2bb +#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e) + + +static void +MD5_process(MD5_CTX *pms, const uint8_t *data /*[64]*/) +{ + uint32_t + a = pms->abcd[0], b = pms->abcd[1], + c = pms->abcd[2], d = pms->abcd[3]; + uint32_t t; +#if BYTE_ORDER > 0 + /* Define storage only for big-endian CPUs. */ + uint32_t X[16]; +#else + /* Define storage for little-endian or both types of CPUs. */ + uint32_t xbuf[16]; + const uint32_t *X; +#endif + + { +#if BYTE_ORDER == 0 + /* + * Determine dynamically whether this is a big-endian or + * little-endian machine, since we can use a more efficient + * algorithm on the latter. + */ + static const int w = 1; + + if (*((const uint8_t *)&w)) /* dynamic little-endian */ +#endif +#if BYTE_ORDER <= 0 /* little-endian */ + { + /* + * On little-endian machines, we can process properly aligned + * data without copying it. + */ + if (!((data - (const uint8_t *)0) & 3)) { + /* data are properly aligned */ + X = (const uint32_t *)data; + } else { + /* not aligned */ + memcpy(xbuf, data, 64); + X = xbuf; + } + } +#endif +#if BYTE_ORDER == 0 + else /* dynamic big-endian */ +#endif +#if BYTE_ORDER >= 0 /* big-endian */ + { + /* + * On big-endian machines, we must arrange the bytes in the + * right order. + */ + const uint8_t *xp = data; + int i; + +# if BYTE_ORDER == 0 + X = xbuf; /* (dynamic only) */ +# else +# define xbuf X /* (static only) */ +# endif + for (i = 0; i < 16; ++i, xp += 4) + xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24); + } +#endif + } + +#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) + + /* Round 1. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ +#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + F(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 7, T1); + SET(d, a, b, c, 1, 12, T2); + SET(c, d, a, b, 2, 17, T3); + SET(b, c, d, a, 3, 22, T4); + SET(a, b, c, d, 4, 7, T5); + SET(d, a, b, c, 5, 12, T6); + SET(c, d, a, b, 6, 17, T7); + SET(b, c, d, a, 7, 22, T8); + SET(a, b, c, d, 8, 7, T9); + SET(d, a, b, c, 9, 12, T10); + SET(c, d, a, b, 10, 17, T11); + SET(b, c, d, a, 11, 22, T12); + SET(a, b, c, d, 12, 7, T13); + SET(d, a, b, c, 13, 12, T14); + SET(c, d, a, b, 14, 17, T15); + SET(b, c, d, a, 15, 22, T16); +#undef SET + + /* Round 2. */ + /* Let [abcd k s i] denote the operation + a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ +#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + G(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 1, 5, T17); + SET(d, a, b, c, 6, 9, T18); + SET(c, d, a, b, 11, 14, T19); + SET(b, c, d, a, 0, 20, T20); + SET(a, b, c, d, 5, 5, T21); + SET(d, a, b, c, 10, 9, T22); + SET(c, d, a, b, 15, 14, T23); + SET(b, c, d, a, 4, 20, T24); + SET(a, b, c, d, 9, 5, T25); + SET(d, a, b, c, 14, 9, T26); + SET(c, d, a, b, 3, 14, T27); + SET(b, c, d, a, 8, 20, T28); + SET(a, b, c, d, 13, 5, T29); + SET(d, a, b, c, 2, 9, T30); + SET(c, d, a, b, 7, 14, T31); + SET(b, c, d, a, 12, 20, T32); +#undef SET + + /* Round 3. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + H(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 5, 4, T33); + SET(d, a, b, c, 8, 11, T34); + SET(c, d, a, b, 11, 16, T35); + SET(b, c, d, a, 14, 23, T36); + SET(a, b, c, d, 1, 4, T37); + SET(d, a, b, c, 4, 11, T38); + SET(c, d, a, b, 7, 16, T39); + SET(b, c, d, a, 10, 23, T40); + SET(a, b, c, d, 13, 4, T41); + SET(d, a, b, c, 0, 11, T42); + SET(c, d, a, b, 3, 16, T43); + SET(b, c, d, a, 6, 23, T44); + SET(a, b, c, d, 9, 4, T45); + SET(d, a, b, c, 12, 11, T46); + SET(c, d, a, b, 15, 16, T47); + SET(b, c, d, a, 2, 23, T48); +#undef SET + + /* Round 4. */ + /* Let [abcd k s t] denote the operation + a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ +#define I(x, y, z) ((y) ^ ((x) | ~(z))) +#define SET(a, b, c, d, k, s, Ti)\ + t = a + I(b,c,d) + X[k] + Ti;\ + a = ROTATE_LEFT(t, s) + b + /* Do the following 16 operations. */ + SET(a, b, c, d, 0, 6, T49); + SET(d, a, b, c, 7, 10, T50); + SET(c, d, a, b, 14, 15, T51); + SET(b, c, d, a, 5, 21, T52); + SET(a, b, c, d, 12, 6, T53); + SET(d, a, b, c, 3, 10, T54); + SET(c, d, a, b, 10, 15, T55); + SET(b, c, d, a, 1, 21, T56); + SET(a, b, c, d, 8, 6, T57); + SET(d, a, b, c, 15, 10, T58); + SET(c, d, a, b, 6, 15, T59); + SET(b, c, d, a, 13, 21, T60); + SET(a, b, c, d, 4, 6, T61); + SET(d, a, b, c, 11, 10, T62); + SET(c, d, a, b, 2, 15, T63); + SET(b, c, d, a, 9, 21, T64); +#undef SET + + /* Then perform the following additions. (That is increment each + of the four registers by the value it had before this block + was started.) */ + pms->abcd[0] += a; + pms->abcd[1] += b; + pms->abcd[2] += c; + pms->abcd[3] += d; +} + +void +MD5_init(MD5_CTX *pms) +{ + pms->count[0] = pms->count[1] = 0; + pms->abcd[0] = 0x67452301; + pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476; + pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301; + pms->abcd[3] = 0x10325476; +} + +void +MD5_append(MD5_CTX *pms, const uint8_t *data, int nbytes) +{ + const uint8_t *p = data; + int left = nbytes; + int offset = (pms->count[0] >> 3) & 63; + uint32_t nbits = (uint32_t)(nbytes << 3); + + if (nbytes <= 0) + return; + + /* Update the message length. */ + pms->count[1] += nbytes >> 29; + pms->count[0] += nbits; + if (pms->count[0] < nbits) + pms->count[1]++; + + /* Process an initial partial block. */ + if (offset) { + int copy = (offset + nbytes > 64 ? 64 - offset : nbytes); + + memcpy(pms->buf + offset, p, copy); + if (offset + copy < 64) + return; + p += copy; + left -= copy; + MD5_process(pms, pms->buf); + } + + /* Process full blocks. */ + for (; left >= 64; p += 64, left -= 64) + MD5_process(pms, p); + + /* Process a final partial block. */ + if (left) + memcpy(pms->buf, p, left); +} + +void +MD5_finish(MD5_CTX *pms, uint8_t digest[16]) +{ + const uint8_t pad[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + uint8_t data[8]; + int i; + + /* Save the length before padding. */ + for (i = 0; i < 8; ++i) + data[i] = (uint8_t)(pms->count[i >> 2] >> ((i & 3) << 3)); + /* Pad to 56 bytes mod 64. */ + MD5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1); + /* Append the length. */ + MD5_append(pms, data, 8); + for (i = 0; i < 16; ++i) + digest[i] = (uint8_t)(pms->abcd[i >> 2] >> ((i & 3) << 3)); +} + +// end of md5.c ... + diff --git a/md5.h b/md5.h new file mode 100644 index 0000000..395a257 --- /dev/null +++ b/md5.h @@ -0,0 +1,19 @@ +#ifndef _INCL_MD5_H_ +#define _INCL_MD5_H_ + +#include + +typedef struct MD5_CTX +{ + uint32_t count[2]; + uint32_t abcd[4]; + uint8_t buf[64]; +} MD5_CTX; + +void MD5_init(MD5_CTX *pms); +void MD5_append(MD5_CTX *pms, const uint8_t *data, int nbytes); +void MD5_finish(MD5_CTX *pms, uint8_t digest[16]); + +#endif + +// end of md5.h ... diff --git a/pkcs5_pbkdf2.c b/pkcs5_pbkdf2.c new file mode 100644 index 0000000..760b162 --- /dev/null +++ b/pkcs5_pbkdf2.c @@ -0,0 +1,122 @@ +/* $OpenBSD: pkcs5_pbkdf2.c,v 1.4 2013/06/03 21:07:02 tedu Exp $ */ + +/*- + * Copyright (c) 2008 Damien Bergamini + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include + +#include "sha1.h" + +/* + * HMAC-SHA-1 (from RFC 2202). + */ +static void +hmac_sha1(const u_int8_t *text, size_t text_len, const u_int8_t *key, + size_t key_len, u_int8_t digest[SHA1_DIGEST_LENGTH]) +{ + SHA1_CTX ctx; + u_int8_t k_pad[SHA1_BLOCK_LENGTH]; + u_int8_t tk[SHA1_DIGEST_LENGTH]; + int i; + + if (key_len > SHA1_BLOCK_LENGTH) { + SHA1Init(&ctx); + SHA1Update(&ctx, key, key_len); + SHA1Final(tk, &ctx); + + key = tk; + key_len = SHA1_DIGEST_LENGTH; + } + + bzero(k_pad, sizeof k_pad); + bcopy(key, k_pad, key_len); + for (i = 0; i < SHA1_BLOCK_LENGTH; i++) + k_pad[i] ^= 0x36; + + SHA1Init(&ctx); + SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH); + SHA1Update(&ctx, text, text_len); + SHA1Final(digest, &ctx); + + bzero(k_pad, sizeof k_pad); + bcopy(key, k_pad, key_len); + for (i = 0; i < SHA1_BLOCK_LENGTH; i++) + k_pad[i] ^= 0x5c; + + SHA1Init(&ctx); + SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH); + SHA1Update(&ctx, digest, SHA1_DIGEST_LENGTH); + SHA1Final(digest, &ctx); +} + +/* + * Password-Based Key Derivation Function 2 (PKCS #5 v2.0). + * Code based on IEEE Std 802.11-2007, Annex H.4.2. + */ +int +pkcs5_pbkdf2(const char *pass, size_t pass_len, const uint8_t *salt, size_t salt_len, + uint8_t *key, size_t key_len, unsigned int rounds) +{ + uint8_t *asalt, obuf[SHA1_DIGEST_LENGTH]; + uint8_t d1[SHA1_DIGEST_LENGTH], d2[SHA1_DIGEST_LENGTH]; + unsigned int i, j; + unsigned int count; + size_t r; + + if (rounds < 1 || key_len == 0) + return -1; + if (salt_len == 0 || salt_len > SIZE_MAX - 4) + return -1; + if ((asalt = malloc(salt_len + 4)) == NULL) + return -1; + + memcpy(asalt, salt, salt_len); + + for (count = 1; key_len > 0; count++) { + asalt[salt_len + 0] = (count >> 24) & 0xff; + asalt[salt_len + 1] = (count >> 16) & 0xff; + asalt[salt_len + 2] = (count >> 8) & 0xff; + asalt[salt_len + 3] = count & 0xff; + hmac_sha1(asalt, salt_len + 4, (const uint8_t *) pass, pass_len, d1); + memcpy(obuf, d1, sizeof(obuf)); + + for (i = 1; i < rounds; i++) { + hmac_sha1(d1, sizeof(d1), (const uint8_t *) pass, pass_len, d2); + memcpy(d1, d2, sizeof(d1)); + for (j = 0; j < sizeof(obuf); j++) + obuf[j] ^= d1[j]; + } + + r = MIN(key_len, SHA1_DIGEST_LENGTH); + memcpy(key, obuf, r); + key += r; + key_len -= r; + }; + bzero(asalt, salt_len + 4); + free(asalt); + bzero(d1, sizeof(d1)); + bzero(d2, sizeof(d2)); + bzero(obuf, sizeof(obuf)); + + return 0; +} + diff --git a/pkcs5_pbkdf2.h b/pkcs5_pbkdf2.h new file mode 100644 index 0000000..e187caf --- /dev/null +++ b/pkcs5_pbkdf2.h @@ -0,0 +1,11 @@ +#ifndef _INCL_PKCS5_PBKDF2_H_ +#define _INCL_PKCS5_PBKDF2_H_ + +#include + +int pkcs5_pbkdf2(const char *pass, size_t pass_len, const uint8_t *salt, size_t salt_len, uint8_t *key, size_t key_len, unsigned int rounds); + +#endif + +// end of pkcs5_pbkdf2.h ... + diff --git a/sha1.c b/sha1.c new file mode 100644 index 0000000..4ec57e2 --- /dev/null +++ b/sha1.c @@ -0,0 +1,179 @@ +/* $OpenBSD: sha1.c,v 1.9 2011/01/11 15:50:40 deraadt Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + * + * Test Vectors (from FIPS PUB 180-1) + * "abc" + * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 + * A million repetitions of "a" + * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#define SHA1HANDSOFF + +#include +#include +//#include + +#include "sha1.h" + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if PLATFORM_LITTLEENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#else +#define blk0(i) block->l[i] +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void +SHA1Transform(u_int32_t state[5], const unsigned char buffer[SHA1_BLOCK_LENGTH]) +{ + u_int32_t a, b, c, d, e; + typedef union { + unsigned char c[64]; + unsigned int l[16]; + } CHAR64LONG16; + CHAR64LONG16* block; +#ifdef SHA1HANDSOFF + unsigned char workspace[SHA1_BLOCK_LENGTH]; + + block = (CHAR64LONG16 *)workspace; + memcpy(block, buffer, SHA1_BLOCK_LENGTH); +#else + block = (CHAR64LONG16 *)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1Init - Initialize new context */ + +void +SHA1Init(SHA1_CTX *context) +{ + /* SHA1 initialization constants */ + context->count = 0; + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; +} + + +/* Run your data through this. */ + +void +SHA1Update(SHA1_CTX *context, const unsigned char *data, unsigned int len) +{ + unsigned int i; + unsigned int j; + + j = (u_int32_t)((context->count >> 3) & 63); + context->count += (len << 3); + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64 - j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void +SHA1Final(unsigned char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context) +{ + unsigned int i; + unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count >> + ((7 - (i & 7)) * 8)) & 255); /* Endian independent */ + } + SHA1Update(context, (unsigned char *)"\200", 1); + while ((context->count & 504) != 448) { + SHA1Update(context, (unsigned char *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + + if (digest) + for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { + digest[i] = (unsigned char)((context->state[i >> 2] >> + ((3 - (i & 3)) * 8)) & 255); + } + memset(finalcount, '\0', 8); +#if 0 /* We want to use this for "keyfill" */ + /* Wipe variables */ + i = 0; + bzero(context->buffer, 64); + bzero(context->state, 20); + bzero(context->count, 8); +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite its own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +#endif +} diff --git a/sha1.h b/sha1.h new file mode 100644 index 0000000..ac9cc55 --- /dev/null +++ b/sha1.h @@ -0,0 +1,28 @@ +/* $OpenBSD: sha1.h,v 1.5 2007/09/10 22:19:42 henric Exp $ */ + +/* + * SHA-1 in C + * By Steve Reid + * 100% Public Domain + */ + +#ifndef _SHA1_H_ +#define _SHA1_H_ + +#define SHA1_BLOCK_LENGTH 64 +#define SHA1_DIGEST_LENGTH 20 + +#include + +typedef struct { + u_int32_t state[5]; + u_int64_t count; + unsigned char buffer[SHA1_BLOCK_LENGTH]; +} SHA1_CTX; + +void SHA1Init(SHA1_CTX * context); +void SHA1Transform(u_int32_t state[5], const unsigned char buffer[SHA1_BLOCK_LENGTH]); +void SHA1Update(SHA1_CTX *context, const unsigned char *data, unsigned int len); +void SHA1Final(unsigned char digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context); + +#endif /* _SHA1_H_ */