[
  {
    "path": ".gitattributes",
    "content": "*.data text eol=lf\n"
  },
  {
    "path": ".gitignore",
    "content": "*.preserve\nrelease/\nsrc/test/modules/\nTesting\n*~\ngh-pages/\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: generic\nsudo: required\nservices:\n  - docker\n\nenv:\n    matrix:\n        - DOCKER_IMAGE=centos:7 CMAKE_URL=auto\n        - DOCKER_IMAGE=debian:8 CMAKE_URL=auto\n        - DOCKER_IMAGE=debian:8 CC=clang CMAKE_URL=auto\n        - DOCKER_IMAGE=debian:stretch\n        - DOCKER_IMAGE=fedora:latest\n        - DOCKER_IMAGE=ubuntu:latest CMAKE_URL=auto # LTS\n        - DOCKER_IMAGE=ubuntu:devel\n\nscript:\n    - ./build/run.sh build\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\ncmake_minimum_required(VERSION 3.6 FATAL_ERROR)\nproject(luasandbox VERSION 1.4.0 LANGUAGES C)\n\nset(CPACK_PACKAGE_DESCRIPTION_SUMMARY \"Generic Lua sandbox for dynamic data analysis\")\nset(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})\nset(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})\nset(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})\nset(CPACK_PACKAGE_CONTACT     \"Mike Trinkala <trink@mozilla.com>\")\nset(CPACK_DEBIAN_FILE_NAME    \"DEB-DEFAULT\")\nset(CPACK_RPM_FILE_NAME       \"RPM-DEFAULT\")\nset(CPACK_RPM_PACKAGE_LICENSE \"MPLv2.0\")\n\ninclude(GNUInstallDirs)\nif(WIN32)\n  set(INSTALL_CMAKE_DIR cmake)\n  set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_BINDIR})\nelse()\n  set(INSTALL_CMAKE_DIR \"${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/cmake\")\nendif()\n\nset(CMAKE_MODULE_PATH \"${CMAKE_SOURCE_DIR}/cmake\")\ninclude(mozsvc)\n\ninclude(CheckFunctionExists)\ncheck_function_exists(clock_gettime HAVE_CLOCK_GETTIME)\nif(HAVE_CLOCK_GETTIME)\n  add_definitions(-DHAVE_CLOCK_GETTIME)\nendif()\n\ninclude(CMakePackageConfigHelpers)\nconfigure_package_config_file(cmake/${PROJECT_NAME}Config.cmake.in\n                              ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake\n                              INSTALL_DESTINATION ${INSTALL_CMAKE_DIR}\n                              PATH_VARS CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_LIBDIR)\nwrite_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake\n                                 COMPATIBILITY SameMajorVersion)\ninstall(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake\n              ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake\n        DESTINATION ${INSTALL_CMAKE_DIR})\n\nfind_library(LIBM_LIBRARY m)\n\ninclude_directories(\"${CMAKE_SOURCE_DIR}/include\" \"${CMAKE_SOURCE_DIR}/include/luasandbox\" )\ninstall(DIRECTORY \"${CMAKE_SOURCE_DIR}/include/\" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})\ninstall(FILES \"${CMAKE_SOURCE_DIR}/README.md\" DESTINATION ${CMAKE_INSTALL_DOCDIR})\n\nadd_subdirectory(src)\nadd_dependencies(luasandbox luasandboxutil)\nadd_dependencies(luasandboxtest luasandbox)\nadd_dependencies(luasandboxheka luasandboxtest)\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Community Participation Guidelines\n\nThis repository is governed by Mozilla's code of conduct and etiquette guidelines. \nFor more details, please read the\n[Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/). \n\n## How to Report\nFor more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page.\n\n<!--\n## Project Specific Etiquette\n\nIn some cases, there will be additional project etiquette i.e.: (https://bugzilla.mozilla.org/page.cgi?id=etiquette.html).\nPlease update for your project.\n-->\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this file,\n# You can obtain one at http://mozilla.org/MPL/2.0/.\n"
  },
  {
    "path": "README.md",
    "content": "# Lua Sandbox Library\n\n## Overview\n\nSandboxes provide a dynamic and isolated execution environment\nfor data parsing, transformation, and analysis.  They allow access to data\nwithout jeopardizing the integrity or performance of the processing\ninfrastructure. This broadens the audience that the data can be\nexposed to and facilitates new uses of the data (i.e. debugging, monitoring,\ndynamic provisioning,  SLA analysis, intrusion detection, ad-hoc reporting,\netc.)\n\nThe Lua sandbox is a library allowing customized control over the Lua execution\nenvironment including functionality like global data preservation/restoration on\nshutdown/startup, output collection in textual or binary formats and an array of\nparsers for various data types (Nginx, Apache, Syslog, MySQL and many RFC grammars)\n\nThese libraries and utilities have been mostly extracted from\n[Hindsight](https://github.com/mozilla-services/hindsight). The goal was to\ndecouple the Heka/Hindsight functionality from any particular infrastructure and\nmake it embeddable into any tool or language.\n\n### Features\n\n- small - memory requirements are as little as 8 KiB for a basic sandbox\n- fast - microsecond execution times\n- stateful - ability to resume where it left off after a restart/reboot\n- isolated - failures are contained and malfunctioning sandboxes are terminated.\n  Containment is defined in terms of restriction to the operating system,\n  file system, libraries, memory use, Lua instruction use, and output size.\n\n[Full Documentation](http://mozilla-services.github.io/lua_sandbox)\n\n## Installation\n\n### Prerequisites\n* C compiler (GCC 4.7+, Visual Studio 2013)\n* CMake (3.0+) - http://cmake.org/cmake/resources/software.html\n* Git http://git-scm.com/download\n\n#### Optional (used for documentation)\n* Graphviz (2.28.0) - http://graphviz.org/Download..php\n* Doxygen (1.8.11+) - http://www.stack.nl/~dimitri/doxygen/download.html#latestsrc\n* gitbook (2.3) - https://www.gitbook.com/\n* lua (5.1) - https://www.lua.org/download.html\n\n### CMake Build Instructions\n\n    git clone https://github.com/mozilla-services/lua_sandbox.git\n    cd lua_sandbox\n    mkdir release\n    cd release\n\n    # UNIX\n    cmake -DCMAKE_BUILD_TYPE=release ..\n    make\n\n    # Windows Visual Studio 2013\n    cmake -DCMAKE_BUILD_TYPE=release -G \"NMake Makefiles\" ..\n    nmake\n\n    ctest\n    cpack -G TGZ # (DEB|RPM|ZIP)\n\n## Releases\n\n* The main branch is the current release and is considered stable at all\n  times.\n* New versions can be released as frequently as every two weeks (our sprint\n  cycle). The only exception would be for a high priority patch.\n* All active work is flagged with the sprint milestone and tracked in the\n  project dashboard.\n* New releases occur the day after the sprint finishes.\n  * The version in the dev branch is updated\n  * The changes are merged into main\n  * A new tag is created\n\n## Contributions\n\n* All pull requests must be made against the dev branch, direct commits to\n  main are not permitted.\n* All non trivial contributions should start with an issue being filed (if it is\n  a new feature please propose your design/approach before doing any work as not\n  all feature requests are accepted).\n"
  },
  {
    "path": "build/functions.sh",
    "content": "#!/bin/sh\n\n# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n#\n# Author: Mathieu Parent <math.parent@gmail.com>\n\n# =================================================================\n# Show usage\nusage() {\n    echo \"Build, test and make packages (optionally using Docker)\" >&2\n    echo \"  $0 build\" >&2\n    echo \"\" >&2\n    echo \"Options are passed using environment variables:\" >&2\n    echo \"  - DOCKER_IMAGE: Run the build in a container (default: <none>)\" >&2\n    echo \"  - CPACK_GENERATOR: DEB, RPM, TGZ, ... (default guessed)\" >&2\n    echo \"  - CMAKE_URL: If set, download cmake from it (default: <none>, auto also supported)\" >&2\n    echo \"  - CMAKE_SHA256: Used to checksum CMAKE_URL (default: <none>)\" >&2\n    echo \"  - CC: C compiler (default: gcc)\" >&2\n    echo \"  - CXX: C++ compiler (default: g++)\" >&2\n}\n\n\n# =================================================================\n# Run command within container\ndocker_run() {\n    DOCKER_IMAGE=\"${DOCKER_IMAGE:-debian:jessie}\"\n    DOCKER_VOLUME=\"$(dirname \"$PWD\")\"\n    (   set -x\n        docker pull \"$DOCKER_IMAGE\"\n        ret=0\n        docker run \\\n            --volume \"${DOCKER_VOLUME}:${DOCKER_VOLUME}\" \\\n            --workdir \"$PWD\" \\\n            --rm=true --tty=true \\\n            --env \"CPACK_GENERATOR=${CPACK_GENERATOR}\" \\\n            --env \"CMAKE_URL=${CMAKE_URL}\" \\\n            --env \"CMAKE_SHA256=${CMAKE_SHA256}\" \\\n            --env \"CC=${CC}\" \\\n            --env \"CXX=${CXX}\" \\\n            --env \"DISTRO=${DOCKER_IMAGE}\" \\\n            \"$DOCKER_IMAGE\" \\\n            $@\n    )\n}\n\n# =================================================================\n# Guess environment variables\nsetup_env() {\n    if [ \"$(id -u)\" = 0 ]; then\n        as_root=\"\"\n    else\n        as_root=\"sudo\"\n    fi\n    if [ -z \"${CPACK_GENERATOR}\" ]; then\n        if [ -x \"`command -v apt-get 2>/dev/null`\" ]; then\n            CPACK_GENERATOR=DEB\n        elif [ -x \"`command -v rpm 2>/dev/null`\" ]; then\n            CPACK_GENERATOR=RPM\n        else\n            CPACK_GENERATOR=TGZ\n        fi\n    fi\n    CC=\"${CC:-gcc}\"\n    CXX=\"${CXX:-g++}\"\n}\n\n# =================================================================\n# Install cmake from URL\ninstall_cmake() {\n    if echo \"$PATH\" | grep -qF \"/cmake-dist/bin:\" ; then\n        # Already done\n        return\n    fi\n    if [ \"$CMAKE_URL\" = \"auto\" ]; then\n        CMAKE_URL=\"https://cmake.org/files/v3.7/cmake-3.7.1-Linux-x86_64.tar.gz\"\n        CMAKE_SHA256=7b4b7a1d9f314f45722899c0521c261e4bfab4a6b532609e37fef391da6bade2\n    elif [ -z \"$CMAKE_URL\" ]; then\n        echo \"Missing env CMAKE_URL\"\n        exit 1\n    elif [ -z \"$CMAKE_SHA256\" ]; then\n        echo \"Missing env CMAKE_SHA256\"\n        exit 1\n    fi\n    (   set -x\n        wget -O cmake.tar.gz \"${CMAKE_URL}\"\n        echo \"${CMAKE_SHA256}  cmake.tar.gz\" > cmake-SHA256.txt\n        sha256sum --check cmake-SHA256.txt || {\n            echo 'Checksum error'\n            exit 1\n        }\n        mkdir cmake-dist\n        cd cmake-dist\n        tar xzf \"../cmake.tar.gz\" --strip-components=1\n    )\n    PATH=\"$PWD/cmake-dist/bin:${PATH}\"\n    echo \"+PATH=${PATH}\"\n}\n\n# =================================================================\n# Install packages from distribution\n# The following substitutions are done:\n# - cmake is replaced by downloaded, if CMAKE_URL is set\n# - rpm-build is ignored on DEB distributions\n# - ca-certificates is ignored on RPM distributions\ninstall_packages() {\n    local packages\n    packages=\"$@\"\n    do_install_cmake=no\n    if [ -n \"$CMAKE_URL\" ] && echo \" $packages \" | grep -qF \" cmake \"; then\n        packages=\"$(echo \" $packages \" | sed \"s/ cmake / wget ca-certificates /\")\"\n        do_install_cmake=yes\n    fi\n    packages=\"$(echo \" $packages \" | sed -e \"s/ c-compiler / $CC /\" -e \"s/ c++-compiler / $CXX /\")\"\n    if [ \"$CPACK_GENERATOR\" = \"DEB\" ]; then\n        packages=\"$(echo \"$packages\" | sed -e \"s/ rpm-build / /\" -e \"s/ clang++ / clang /\")\"\n        (   set -x;\n            $as_root apt-get update\n            $as_root apt-get install -y $packages\n        )\n    elif [ \"$CPACK_GENERATOR\" = \"RPM\" ]; then\n        packages=\"$(echo \"$packages\" | sed -e \"s/ ca-certificates / /\" -e \"s/ g++ / gcc-c++ /\" -e \"s/ clang++ / clang /\")\"\n        (   set -x;\n            $as_root yum install -y $packages\n        )\n    else\n        echo \"Unhandled CPACK_GENERATOR: $CPACK_GENERATOR\" >&2\n        exit 1\n    fi\n    if [ \"$do_install_cmake\" = \"yes\" ]; then\n        install_cmake\n    fi\n}\n\n# =================================================================\n# Install all packages from directory\ninstall_packages_from_dir() {\n    local dir\n    dir=\"$1\"\n    if [ ! -d \"$dir\" ]; then\n        echo \"Not a directory: $dir\"\n        exit 1\n    fi\n    if [ \"$CPACK_GENERATOR\" = \"DEB\" ]; then\n        (set -x; $as_root dpkg -i \"$dir\"/*.deb)\n    elif [ \"$CPACK_GENERATOR\" = \"RPM\" ]; then\n        (set -x; $as_root rpm -i \"$dir\"/*.rpm)\n    else\n        echo \"Unhandled CPACK_GENERATOR: $CPACK_GENERATOR\" >&2\n        exit 1\n    fi\n}\n\n# =================================================================\n# Build\nbuild() {\n    (   set -x\n\n        rm -rf ./release\n        # From README.md:\n        mkdir release\n        cd release\n\n        cmake -DCMAKE_BUILD_TYPE=release ..\n        make\n\n        ctest -V\n        cpack -G \"${CPACK_GENERATOR}\"\n    )\n}\n\n# =================================================================\n# Main\nmain() {\n    if [ -n \"$DOCKER_IMAGE\" ]; then\n        docker_run \"$0\" build\n    else\n        setup_env\n        install_packages c-compiler cmake make rpm-build\n        if [ \"$(basename \"$PWD\")\" != \"lua_sandbox\" ]; then\n            local old_dir\n            local lsb_dir\n            old_dir=\"$PWD\"\n            lsb_dir=\"$(dirname \"$old_dir\")/lua_sandbox\"\n            echo \"+cd $lsb_dir\"\n            cd \"$lsb_dir\"\n            build\n            install_packages_from_dir ./release\n            echo \"+cd $old_dir\"\n            cd \"$old_dir\"\n        fi\n        if [ -n \"$build_function\" ]; then\n            \"$build_function\"\n        else\n            build\n        fi\n    fi\n}\n"
  },
  {
    "path": "build/run.sh",
    "content": "#!/bin/sh\n\n# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n#\n# Author: Mathieu Parent <math.parent@gmail.com>\n\nset -e\n\n. \"$(dirname $0)/functions.sh\"\n\nif [ \"$1\" != \"build\" -o $# -ge 2 ]; then\n    usage\n    exit 1\nfi\n\nbuild_function=\nmain\n"
  },
  {
    "path": "cmake/doxygen.cmake",
    "content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nfind_package(Doxygen QUIET)\nfind_program(LUA_EXE lua QUIET)\nfind_program(PANDOC_EXE pandoc QUIET)\nfind_program(gitbook gitbook QUIET)\nif(DOXYGEN_FOUND AND LUA_EXE AND PANDOC_EXE)\n    set(DOXYCONF_IN  ${CMAKE_SOURCE_DIR}/doxygen.in.conf)\n    set(DOXYCONF_OUT ${CMAKE_BINARY_DIR}/doxygen.conf)\n    if(EXISTS ${DOXYCONF_IN})\n        configure_file(${DOXYCONF_IN} ${DOXYCONF_OUT})\n    else()\n        file(WRITE ${DOXYCONF_OUT} \"\nPROJECT_NAME            = \\\"${PROJECT_NAME}\\\"\nPROJECT_BRIEF           = \\\"${CPACK_PACKAGE_DESCRIPTION_SUMMARY}\\\"\nOUTPUT_DIRECTORY        = \\\"${CMAKE_SOURCE_DIR}/gh-pages\\\"\nHTML_OUTPUT             = doxygen\nGENERATE_LATEX          = NO\nGENERATE_TODOLIST       = YES\nFULL_PATH_NAMES         = YES\nSTRIP_FROM_PATH         = \\\"${CMAKE_SOURCE_DIR}\\\"\nSOURCE_BROWSER          = YES\nTAB_SIZE                = 4\nEXTRACT_ALL             = YES\nJAVADOC_AUTOBRIEF       = YES\nRECURSIVE               = YES\nINPUT                   = \\\"${CMAKE_SOURCE_DIR}/include\\\" \\\"${CMAKE_SOURCE_DIR}/README.md\\\"\nUSE_MDFILE_AS_MAINPAGE  = \\\"${CMAKE_SOURCE_DIR}/README.md\\\"\nEXAMPLE_PATH            = ${EXAMPLE_PATHS}\nIMAGE_PATH              = ${IMAGE_PATHS}\nBUILTIN_STL_SUPPORT     = YES\nSTRIP_CODE_COMMENTS     = NO\nSHOW_DIRECTORIES        = YES\nPROJECT_NUMBER          = ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}\")\n    endif()\n\n    add_custom_target(docs ${DOXYGEN_EXECUTABLE} ${DOXYCONF_OUT}\n    COMMAND lua gen_gh_pages.lua \"${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}\"\n    \"${CMAKE_SOURCE_DIR}\" \"${CMAKE_BINARY_DIR}\" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})\nelse()\n    message(\"The optional documentation tools were not found; the doc target has not been created\")\nendif()\n"
  },
  {
    "path": "cmake/luasandboxConfig.cmake.in",
    "content": "set(LUASANDBOX_VERSION x.y.z)\n\n@PACKAGE_INIT@\n\nset_and_check(LUASANDBOX_INCLUDE_DIR \"@PACKAGE_CMAKE_INSTALL_INCLUDEDIR@\")\nset_and_check(LUASANDBOX_LIB_DIR \"@PACKAGE_CMAKE_INSTALL_LIBDIR@\")\n\nFIND_LIBRARY(LUASANDBOX_UTIL_LIBRARY    NAMES luasandboxutil    PATHS ${LUASANDBOX_LIB_DIR})\nFIND_LIBRARY(LUASANDBOX_LIBRARY         NAMES luasandbox        PATHS ${LUASANDBOX_LIB_DIR})\nFIND_LIBRARY(LUASANDBOX_HEKA_LIBRARY    NAMES luasandboxheka    PATHS ${LUASANDBOX_LIB_DIR})\nFIND_LIBRARY(LUASANDBOX_TEST_LIBRARY    NAMES luasandboxtest    PATHS ${LUASANDBOX_LIB_DIR})\n\nset(LUASANDBOX_LIBRARIES ${LUASANDBOX_HEKA_LIBRARY} ${LUASANDBOX_LIBRARY} ${LUASANDBOX_UTIL_LIBRARY})\n"
  },
  {
    "path": "cmake/mozsvc.cmake",
    "content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nif(MSVC)\n    # Predefined Macros: http://msdn.microsoft.com/en-us/library/b0084kay.aspx\n    # Compiler options: http://msdn.microsoft.com/en-us/library/fwkeyyhe.aspx\n\n    # set a high warning level and treat them as errors\n    set(CMAKE_C_FLAGS           \"/W3 /WX\")\n\n    # enable C++ exception handling\n    set(CMAKE_CXX_FLAGS         \"${CMAKE_C_FLAGS} /EHs\")\n\n    # debug multi threaded dll runtime, complete debugging info, runtime error checking\n    set(CMAKE_C_FLAGS_DEBUG     \"/MDd /Zi /RTC1\")\n    set(CMAKE_CXX_FLAGS_DEBUG   ${CMAKE_C_FLAGS_DEBUG})\n\n    # multi threaded dll runtime, optimize for speed, auto inlining\n    set(CMAKE_C_FLAGS_RELEASE   \"/MD /O2 /Ob2 /DNDEBUG\")\n    set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})\n\n    set(CPACK_GENERATOR         \"ZIP\")\nelse()\n    # Predefined Macros: clang|gcc -dM -E -x c /dev/null\n    # Compiler options: http://gcc.gnu.org/onlinedocs/gcc/Invoking-GCC.html#Invoking-GCC\n    set(CMAKE_C_FLAGS   \"-std=gnu11 -pedantic $ENV{CFLAGS} $ENV{CPPFLAGS} -Wall -Wextra -fPIC -fvisibility=hidden\")\n    set(CMAKE_CXX_FLAGS \"-std=c++11 -pedantic $ENV{CXXFLAGS} $ENV{CPPFLAGS} -Wall -Wextra -fPIC -isystem /usr/local/include -isystem /opt/local/include\")\n    set(CMAKE_C_FLAGS_DEBUG     \"-g\")\n    set(CMAKE_CXX_FLAGS_DEBUG   ${CMAKE_C_FLAGS_DEBUG})\n\n    set(CMAKE_C_FLAGS_RELEASE   \"-O2 -DNDEBUG\")\n    set(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})\n\n    set(CMAKE_C_FLAGS_PROFILE   \"${CMAKE_C_FLAGS_RELEASE} -g -pg\")\n    set(CMAKE_CXX_FLAGS_PROFILE ${CMAKE_C_FLAGS_PROFILE})\n\n    set(CPACK_GENERATOR         \"TGZ\")\n\n    set(CMAKE_SKIP_BUILD_RPATH              FALSE)\n    set(CMAKE_BUILD_WITH_INSTALL_RPATH      FALSE)\n    set(CMAKE_INSTALL_RPATH_USE_LINK_PATH   FALSE)\nendif()\n\nset(CPACK_PACKAGE_VENDOR        \"Mozilla Services\")\nset(CPACK_RESOURCE_FILE_LICENSE \"${CMAKE_SOURCE_DIR}/LICENSE.txt\")\nif(CMAKE_BUILD_TYPE MATCHES \"^[Dd][Ee][Bb][Uu][Gg]$\")\n    set(CPACK_STRIP_FILES FALSE)\nelse()\n    set(CPACK_STRIP_FILES TRUE)\nendif()\n\ninclude(CPack)\ninclude(CTest)\ninclude(doxygen)\n"
  },
  {
    "path": "covfn.txt",
    "content": "Function                                                                                          Source                      Line  FnCov           C/D Coverage\n------------------------------------------------------------------------------------------------  --------------------------------  -----  ---------------------\nadd_table_ref(table_ref_array*,const void*,size_t)                                                .../luasandbox_serialize.c   171  1 / 1       1 /     4 =  25%\nlsb_create(void*,const char*,const char*,lsb_logger*)                                             ../src/luasandbox.c          428  1 / 1      16 /    42 =  38%\nrestore_global_data(lsb_lua_sandbox*)                                                             .../luasandbox_serialize.c   488  1 / 1       7 /    18 =  38%\nlsb_heka_create_input(void*,const char*,const char*,const char*,lsb_logger*,lsb_heka_im_input)    ../src/heka/sandbox.c        407  1 / 1      14 /    34 =  41%\nlsb_heka_create_analysis(void*,const char*,cons...,const char*,lsb_logger*,lsb_heka_im_analysis)  ../src/heka/sandbox.c        598  1 / 1      14 /    34 =  41%\nlsb_heka_create_output(void*,const char*,const ... char*,lsb_logger*,lsb_heka_update_checkpoint)  ../src/heka/sandbox.c        689  1 / 1      14 /    34 =  41%\nserialize_data(lsb_lua_sandbox*,int,lsb_output_buffer*)                                           .../luasandbox_serialize.c   230  1 / 1       9 /    20 =  45%\nheka_create_stream_reader(lua_State*)                                                             ...rc/heka/stream_reader.c   174  1 / 1       5 /    10 =  50%\nlsb_get_output(lsb_lua_sandbox*,size_t*)                                                          ../src/luasandbox_output.c   110  1 / 1       2 /     4 =  50%\ninstruction_manager(lua_State*,lua_Debug*)                                                        ../src/luasandbox.c          119  1 / 1       1 /     2 =  50%\nread_config(lua_State*)                                                                           ../src/luasandbox.c          201  1 / 1       1 /     2 =  50%\nset_random_seed()                                                                                 ../src/luasandbox.c          400  1 / 1       7 /    12 =  58%\nlsb_read_file(const char*)                                                                        ../src/util/util.c            49  1 / 1       6 /    10 =  60%\nheka_encode_message_table(lsb_lua_sandbox*,int)                                                   ../src/heka/message.c        874  1 / 1      16 /    26 =  61%\nmin_expand(MatchState*,const char*,const char*,const char*)                                       ...c/util/string_matcher.c   171  1 / 1       5 /     8 =  62%\nencode_field_value(lsb_lua_sandbox*,lsb_output_buffer*,int,const char*,int)                       ../src/heka/message.c        399  1 / 1      70 /   110 =  63%\npreserve_global_data(lsb_lua_sandbox*)                                                            .../luasandbox_serialize.c   368  1 / 1      27 /    42 =  64%\nlsb_init_heka_message(lsb_heka_message*,int)                                                      ../src/util/heka_message.c   429  1 / 1       4 /     6 =  66%\nprocess_fields(lua_State*,const char*,const char*)                                                ../src/heka/message.c         89  1 / 1      55 /    82 =  67%\nencode_field_array(lsb_lua_sandbox*,lsb_output_buffer*,int,const char*,int)                       ../src/heka/message.c        326  1 / 1      19 /    28 =  67%\nlsb_heka_pm_input(lsb_heka_sandbox*,double,const char*,_Bool)                                     ../src/heka/sandbox.c        564  1 / 1      11 /    16 =  68%\nset_restrictions(lua_State*,lsb_heka_sandbox*)                                                    ../src/heka/sandbox.c        308  1 / 1      20 /    29 =  68%\nread_string(lua_State*,int,const char*,const char*)                                               ../src/heka/message.c         48  1 / 1       7 /    10 =  70%\nlsb_init(lsb_lua_sandbox*,const char*)                                                            ../src/luasandbox.c          528  1 / 1      27 /    38 =  71%\ncheck_int(lua_State*,int,const char*,int)                                                         ../src/luasandbox.c          254  1 / 1       5 /     7 =  71%\nlsb_outputfd(lsb_output_buffer*,double)                                                           ...rc/util/output_buffer.c   177  1 / 1      29 /    40 =  72%\nencode_fields(lsb_lua_sandbox*,lsb_output_buffer*,char,const char*,int)                           ../src/heka/message.c        614  1 / 1      27 /    36 =  75%\nserialize_kvp(lsb_lua_sandbox*,serialization_data*,size_t)                                        .../luasandbox_serialize.c   288  1 / 1      18 /    24 =  75%\ndecode_header(char*,size_t,size_t)                                                                ../src/util/heka_message.c    25  1 / 1      12 /    16 =  75%\nread_message(lua_State*)                                                                          ../src/heka/sandbox.c         41  1 / 1       6 /     8 =  75%\nmm_eval(lua_State*)                                                                               ../src/heka/sandbox.c         74  1 / 1       6 /     8 =  75%\nhsr_decode_message(lua_State*)                                                                    ...rc/heka/stream_reader.c    27  1 / 1       6 /     8 =  75%\nprocess_varint(lua_State*,const char*,int,int,const char*,const char*)                            ../src/heka/message.c         68  1 / 1       3 /     4 =  75%\nencode_int(lsb_lua_sandbox*,lsb_output_buffer*,char,const char*,int)                              ../src/heka/message.c        283  1 / 1       3 /     4 =  75%\noutput(lua_State*)                                                                                ../src/luasandbox.c          127  1 / 1       3 /     4 =  75%\nlsb_stop_sandbox(lsb_lua_sandbox*)                                                                ../src/luasandbox.c          621  1 / 1       3 /     4 =  75%\nlsb_clear_heka_message(lsb_heka_message*)                                                         ../src/util/heka_message.c   443  1 / 1       3 /     4 =  75%\nlsb_outputc(lsb_output_buffer*,char)                                                              ...rc/util/output_buffer.c    78  1 / 1       3 /     4 =  75%\nlsb_outputs(lsb_output_buffer*,const char*,size_t)                                                ...rc/util/output_buffer.c   146  1 / 1       3 /     4 =  75%\nlsb_set_tz(const char*)                                                                           ../src/util/util.c           143  1 / 1       3 /     4 =  75%\nlsb_decode_heka_message(lsb_heka_message*,const char*,size_t,lsb_logger*)                         ../src/util/heka_message.c   207  1 / 1      59 /    77 =  76%\nprocess_message(lsb_heka_sandbox*,lsb_heka_message*,lua_State*,int,_Bool)                         ../src/heka/sandbox.c        478  1 / 1      33 /    43 =  76%\nlsb_pcall_setup(lsb_lua_sandbox*,const char*)                                                     ../src/luasandbox.c          721  1 / 1      14 /    18 =  77%\nread_string(int,const char*,const char*,lsb_const_string*)                                        ../src/util/heka_message.c    45  1 / 1       8 /    10 =  80%\nread_string_value(const char*,const char*,int,lsb_read_value*)                                    ../src/util/heka_message.c    63  1 / 1       8 /    10 =  80%\nread_integer_value(const char*,const char*,int,lsb_read_value*)                                   ../src/util/heka_message.c    84  1 / 1       8 /    10 =  80%\ncheck_string(lua_State*,int,const char*,const char*)                                              ../src/luasandbox.c          232  1 / 1       4 /     5 =  80%\nmatchbalance(MatchState*,const char*,const char*)                                                 ...c/util/string_matcher.c   137  1 / 1      13 /    16 =  81%\nlsb_outputf(lsb_output_buffer*,const char*,...)                                                   ...rc/util/output_buffer.c    92  1 / 1      23 /    28 =  82%\nheka_read_message(lua_State*,lsb_heka_message*)                                                   ../src/heka/message.c        925  1 / 1      48 /    58 =  82%\nheka_decode_message(lua_State*)                                                                   ../src/heka/message.c        689  1 / 1      54 /    65 =  83%\nhsr_find_message(lua_State*)                                                                      ...rc/heka/stream_reader.c    56  1 / 1      25 /    30 =  83%\nlsb_heka_timer_event(lsb_heka_sandbox*,time_t,_Bool)                                              ../src/heka/sandbox.c        811  1 / 1      15 /    18 =  83%\nset_missing_headers(lua_State*,int,lsb_heka_sandbox*)                                             ../src/heka/message.c         28  1 / 1      10 /    12 =  83%\nlsb_heka_pm_analysis(lsb_heka_sandbox*,lsb_heka_message*,_Bool)                                   ../src/heka/sandbox.c        670  1 / 1      10 /    12 =  83%\nignore_value_type(lsb_lua_sandbox*,serialization_data*,int,lua_CFunction*)                        .../luasandbox_serialize.c   115  1 / 1      10 /    12 =  83%\ninject_message_analysis(lua_State*)                                                               ../src/heka/sandbox.c        191  1 / 1       5 /     6 =  83%\nlsb_destroy(lsb_lua_sandbox*)                                                                     ../src/luasandbox.c          634  1 / 1       5 /     6 =  83%\nlsb_pb_output_varint(char*,unsigned long long)                                                    ../src/util/protobuf.c        56  1 / 1       5 /     6 =  83%\nlsb_output(lsb_lua_sandbox*,int,int,int)                                                          ../src/luasandbox_output.c    42  1 / 1      27 /    32 =  84%\nheka_encode_message(lua_State*)                                                                   ../src/heka/message.c        816  1 / 1      11 /    13 =  84%\nmatch_class(int,int)                                                                              ...c/util/string_matcher.c    68  1 / 1      11 /    13 =  84%\nmatch(MatchState*,const char*,const char*)                                                        ...c/util/string_matcher.c   183  1 / 1      39 /    46 =  84%\ninject_message_input(lua_State*)                                                                  ../src/heka/sandbox.c        112  1 / 1      18 /    21 =  85%\nlsb_heka_pm_output(lsb_heka_sandbox*,lsb_heka_message*,void*,_Bool)                               ../src/heka/sandbox.c        785  1 / 1      12 /    14 =  85%\nlsb_expand_input_buffer(lsb_input_buffer*,size_t)                                                 ../src/util/input_buffer.c    49  1 / 1      12 /    14 =  85%\nnumeric_test(match_node*,double)                                                                  .../heka_message_matcher.c    67  1 / 1       6 /     7 =  85%\nlsb_find_heka_message(lsb_heka_message*,lsb_input_buffer*,_Bool,size_t*,lsb_logger*)              ../src/util/heka_message.c   331  1 / 1      31 /    36 =  86%\noutput_print(lua_State*)                                                                          ../src/luasandbox.c          143  1 / 1      19 /    22 =  86%\nload_sandbox_config(const char*,lsb_logger*)                                                      ../src/luasandbox.c          285  1 / 1      19 /    22 =  86%\nmatchbracketclass(int,const char*,const char*)                                                    ...c/util/string_matcher.c    99  1 / 1      19 /    22 =  86%\nupdate_checkpoint(lua_State*)                                                                     ../src/heka/sandbox.c        275  1 / 1       7 /     8 =  87%\nlsb_init_input_buffer(lsb_input_buffer*,size_t)                                                   ../src/util/input_buffer.c    20  1 / 1       7 /     8 =  87%\nlsb_outputd(lsb_output_buffer*,double)                                                            ...rc/util/output_buffer.c   160  1 / 1       7 /     8 =  87%\nprocess_fields(lsb_heka_field*,const char*,const char*)                                           ../src/util/heka_message.c   127  1 / 1      50 /    57 =  87%\ncopy_table(lua_State*,lua_State*,lsb_logger*)                                                     ../src/luasandbox.c          327  1 / 1      22 /    25 =  88%\nlsb_expand_output_buffer(lsb_output_buffer*,size_t)                                               ...rc/util/output_buffer.c    52  1 / 1      16 /    18 =  88%\ninject_payload(lua_State*)                                                                        ../src/heka/sandbox.c        216  1 / 1      18 /    20 =  90%\nlsb_add_function(lsb_lua_sandbox*,lua_CFunction,const char*)                                      ../src/luasandbox.c          710  1 / 1       9 /    10 =  90%\nlsb_init_output_buffer(lsb_output_buffer*,size_t)                                                 ...rc/util/output_buffer.c    27  1 / 1       9 /    10 =  90%\neval_node(match_node*,lsb_heka_message*)                                                          .../heka_message_matcher.c    89  1 / 1      31 /    34 =  91%\neval_tree(match_node*,match_node*,lsb_heka_message*)                                              .../heka_message_matcher.c   151  1 / 1      22 /    24 =  91%\nmemory_manager(void*,void*,size_t,size_t)                                                         ../src/luasandbox.c           83  1 / 1      11 /    12 =  91%\nlsb_read_heka_field(const lsb_heka_message*,lsb_const_string*,int,int,lsb_read_value*)            ../src/util/heka_message.c   474  1 / 1      24 /    26 =  92%\nclassend(const char*)                                                                             ...c/util/string_matcher.c    43  1 / 1      16 /    17 =  94%\nstring_test(match_node*,lsb_const_string*)                                                        .../heka_message_matcher.c    21  1 / 1      18 /    19 =  94%\nencode_string(lsb_lua_sandbox*,lsb_output_buffer*,char,const char*,int)                           ../src/heka/message.c        254  1 / 1       2 /     2 = 100%\nencode_field_object(lsb_lua_sandbox*,lsb_output_buffer*)                                          ../src/heka/message.c        377  1 / 1       4 /     4 = 100%\nmm_check(lua_State*)                                                                              ../src/heka/sandbox.c         58  1 / 1       0 /     0       \nmm_gc(lua_State*)                                                                                 ../src/heka/sandbox.c         66  1 / 1       0 /     0       \nmm_create(lua_State*)                                                                             ../src/heka/sandbox.c         91  1 / 1       4 /     4 = 100%\nlsb_heka_stop_sandbox(lsb_heka_sandbox*)                                                          ../src/heka/sandbox.c        761  1 / 1       0 /     0       \nlsb_heka_terminate_sandbox(lsb_heka_sandbox*,const char*)                                         ../src/heka/sandbox.c        767  1 / 1       0 /     0       \nlsb_heka_destroy_sandbox(lsb_heka_sandbox*)                                                       ../src/heka/sandbox.c        773  1 / 1       2 /     2 = 100%\nlsb_heka_get_error(lsb_heka_sandbox*)                                                             ../src/heka/sandbox.c        853  1 / 1       2 /     2 = 100%\nlsb_heka_get_lua_file(lsb_heka_sandbox*)                                                          ../src/heka/sandbox.c        859  1 / 1       2 /     2 = 100%\nlsb_heka_get_stats(lsb_heka_sandbox*)                                                             ../src/heka/sandbox.c        865  1 / 1       2 /     2 = 100%\nlsb_heka_is_running(lsb_heka_sandbox*)                                                            ../src/heka/sandbox.c        886  1 / 1       4 /     4 = 100%\nlsb_heka_get_message(lsb_heka_sandbox*)                                                           ../src/heka/sandbox.c        894  1 / 1       2 /     2 = 100%\nlsb_heka_get_type(lsb_heka_sandbox*)                                                              ../src/heka/sandbox.c        901  1 / 1       2 /     2 = 100%\ncheck_hsr(lua_State*,int)                                                                         ...rc/heka/stream_reader.c    18  1 / 1       0 /     0       \nhsr_read_message(lua_State*)                                                                      ...rc/heka/stream_reader.c   142  1 / 1       6 /     6 = 100%\nhsr_gc(lua_State*)                                                                                ...rc/heka/stream_reader.c   154  1 / 1       0 /     0       \nlibsize(const luaL_Reg*)                                                                          ../src/luasandbox.c           50  1 / 1       2 /     2 = 100%\npreload_modules(lua_State*)                                                                       ../src/luasandbox.c           57  1 / 1       2 /     2 = 100%\ninstruction_usage(lsb_lua_sandbox*)                                                               ../src/luasandbox.c          113  1 / 1       0 /     0       \nunprotected_panic(lua_State*)                                                                     ../src/luasandbox.c          215  1 / 1       0 /     0       \nget_int(lua_State*,int,const char*)                                                               ../src/luasandbox.c          223  1 / 1       0 /     0       \nstop_hook(lua_State*,lua_Debug*)                                                                  ../src/luasandbox.c          613  1 / 1       0 /     0       \nlsb_usage(lsb_lua_sandbox*,lsb_usage_type,lsb_usage_stat)                                         ../src/luasandbox.c          657  1 / 1      10 /    10 = 100%\nlsb_get_error(lsb_lua_sandbox*)                                                                   ../src/luasandbox.c          667  1 / 1       2 /     2 = 100%\nlsb_set_error(lsb_lua_sandbox*,const char*)                                                       ../src/luasandbox.c          673  1 / 1       4 /     4 = 100%\nlsb_get_lua(lsb_lua_sandbox*)                                                                     ../src/luasandbox.c          686  1 / 1       2 /     2 = 100%\nlsb_get_lua_file(lsb_lua_sandbox*)                                                                ../src/luasandbox.c          692  1 / 1       2 /     2 = 100%\nlsb_get_parent(lsb_lua_sandbox*)                                                                  ../src/luasandbox.c          698  1 / 1       2 /     2 = 100%\nlsb_get_state(lsb_lua_sandbox*)                                                                   ../src/luasandbox.c          704  1 / 1       2 /     2 = 100%\nlsb_pcall_teardown(lsb_lua_sandbox*)                                                              ../src/luasandbox.c          745  1 / 1       4 /     4 = 100%\nlsb_terminate(lsb_lua_sandbox*,const char*)                                                       ../src/luasandbox.c          759  1 / 1       6 /     6 = 100%\nlsb_add_output_function(lua_State*,lua_CFunction)                                                 ../src/luasandbox_output.c    22  1 / 1       0 /     0       \nlsb_get_output_function(lua_State*,int)                                                           ../src/luasandbox_output.c    30  1 / 1       0 /     0       \nget_serialize_function(lua_State*,int)                                                            .../luasandbox_serialize.c    93  1 / 1       0 /     0       \nfind_table_ref(table_ref_array*,const void*)                                                      .../luasandbox_serialize.c   150  1 / 1       4 /     4 = 100%\nget_preservation_version(lua_State*)                                                              .../luasandbox_serialize.c   196  1 / 1       4 /     4 = 100%\nserialize_table(lsb_lua_sandbox*,serialization_data*,size_t)                                      .../luasandbox_serialize.c   215  1 / 1       6 /     6 = 100%\nfile_exists(const char*)                                                                          .../luasandbox_serialize.c   477  1 / 1       2 /     2 = 100%\nlsb_add_serialize_function(lua_State*,lua_CFunction)                                              .../luasandbox_serialize.c   523  1 / 1       0 /     0       \nlsb_serialize_binary(lsb_output_buffer*,const void*,size_t)                                       .../luasandbox_serialize.c   531  1 / 1      11 /    11 = 100%\nlsb_serialize_double(lsb_output_buffer*,double)                                                   .../luasandbox_serialize.c   558  1 / 1       6 /     6 = 100%\nread_double_value(const char*,const char*,int,lsb_read_value*)                                    ../src/util/heka_message.c   103  1 / 1       2 /     2 = 100%\nprocess_varint(int,const char*,const char*,long long*)                                            ../src/util/heka_message.c   116  1 / 1       4 /     4 = 100%\nlsb_free_heka_message(lsb_heka_message*)                                                          ../src/util/heka_message.c   463  1 / 1       2 /     2 = 100%\nlsb_write_heka_uuid(lsb_output_buffer*,const char*,size_t)                                        ../src/util/heka_message.c   519  1 / 1      22 /    22 = 100%\nlsb_destroy_message_matcher(lsb_message_matcher*)                                                 .../heka_message_matcher.c   175  1 / 1       6 /     6 = 100%\nlsb_eval_message_matcher(lsb_message_matcher*,lsb_heka_message*)                                  .../heka_message_matcher.c   195  1 / 1       0 /     0       \nlsb_free_input_buffer(lsb_input_buffer*)                                                          ../src/util/input_buffer.c    36  1 / 1       2 /     2 = 100%\nlsb_free_output_buffer(lsb_output_buffer*)                                                        ...rc/util/output_buffer.c    42  1 / 1       2 /     2 = 100%\nlsb_pb_read_key(const char*,int*,int*)                                                            ../src/util/protobuf.c        15  1 / 1       8 /     8 = 100%\nlsb_pb_write_key(lsb_output_buffer*,unsigned char,unsigned char)                                  ../src/util/protobuf.c        25  1 / 1       2 /     2 = 100%\nlsb_pb_read_varint(const char*,const char*,long long*)                                            ../src/util/protobuf.c        36  1 / 1      22 /    22 = 100%\nlsb_pb_write_varint(lsb_output_buffer*,unsigned long long)                                        ../src/util/protobuf.c        75  1 / 1       2 /     2 = 100%\nlsb_pb_write_bool(lsb_output_buffer*,int)                                                         ../src/util/protobuf.c        85  1 / 1       4 /     4 = 100%\nlsb_pb_write_double(lsb_output_buffer*,double)                                                    ../src/util/protobuf.c        99  1 / 1       2 /     2 = 100%\nlsb_pb_write_string(lsb_output_buffer*,char,const char*,size_t)                                   ../src/util/protobuf.c       114  1 / 1       6 /     6 = 100%\nlsb_pb_update_field_length(lsb_output_buffer*,size_t)                                             ../src/util/protobuf.c       127  1 / 1       8 /     8 = 100%\nlsb_init_running_stats(lsb_running_stats*)                                                        ...rc/util/running_stats.c    13  1 / 1       0 /     0       \nlsb_update_running_stats(lsb_running_stats*,double)                                               ...rc/util/running_stats.c    21  1 / 1       4 /     4 = 100%\nlsb_sd_running_stats(lsb_running_stats*)                                                          ...rc/util/running_stats.c    37  1 / 1       2 /     2 = 100%\nlsb_init_const_string(lsb_const_string*)                                                          ../src/util/string.c          11  1 / 1       0 /     0       \nsinglematch(int,const char*,const char*)                                                          ...c/util/string_matcher.c   119  1 / 1       4 /     4 = 100%\nmax_expand(MatchState*,const char*,const char*,const char*)                                       ...c/util/string_matcher.c   156  1 / 1      10 /    10 = 100%\nlsb_string_match(const char*,size_t,const char*)                                                  ...c/util/string_matcher.c   261  1 / 1      10 /    10 = 100%\nlsb_lp2(unsigned long long)                                                                       ../src/util/util.c            35  1 / 1       2 /     2 = 100%\nlsb_get_time()                                                                                    ../src/util/util.c            75  1 / 1       0 /     0       \nlsb_get_timestamp()                                                                               ../src/util/util.c           114  1 / 1       0 /     0       \n------------------------------------------------------------------------------------------------  --------------------------------  -----  ---------------------\nTotal                                                                                                                                100%    1568 /  2029 =  77%\n"
  },
  {
    "path": "docs/cli/index.md",
    "content": "# Command Line Interface Tools\n\n## lsb_heka_cat\n\nA command-line utility for counting, viewing, filtering, and extracting messages\nfrom a Heka protobuf log/stream.\n\n```\nusage: lsb_heka_cat [-t|-c|-h] [-m message_matcher] [-f] [-n #] <FILE>\ndescription:\n  -t output the messages in text format (default)\n  -c only output the message count\n  -h output the messages as a Heka protobuf stream\n  -f output appended data as the file grows\n  -n output the last # of messages (simple header check so not 100% accurate)\n  -m message_matcher expression (default \"TRUE\")\n  FILE name of the file to cat or '-' for stdin\nnotes:\n  All output is written to stdout and all log/error messages are written to stderr.\n\n```\nSee the [message matcher](/util/message_matcher.md) documentation for more\ndetails about the message_matcher expression.\n\n"
  },
  {
    "path": "docs/heka/analysis.md",
    "content": "# Analysis Sandbox Interface\n\n## Recommendations\nSince the sandbox does not run in isolation there are some expectations of how\nthe host infrastructure behaves.  The current recommendations are based on the\nHindsight reference implementation.\n\n## Disabled Functionality\n- [base library](http://www.lua.org/manual/5.1/manual.html#5.1)\n    - collectgarbage, dofile, load, loadfile, loadstring, newproxy\n- [coroutine](http://www.lua.org/manual/5.1/manual.html#5.2)\n    - the entire module is inaccessible\n- [string](http://www.lua.org/manual/5.1/manual.html#5.4)\n    - dump\n- [io](http://www.lua.org/manual/5.1/manual.html#5.7)\n    - the entire module is inaccessible\n- [os](http://www.lua.org/manual/5.1/manual.html#5.8)\n    - getenv, execute, exit, remove, rename, setlocale, tmpname\n\n## Required Lua Functions (called by the host)\n\n### process_message\n\nCalled when the host has a message available for analysis.  Usually used in\ncombination with a [message matcher](/util/message_matcher.md) expression.\n\nRecommenation: specify this as a `message_matcher` configuration option.\n\n*Arguments*\n* none\n\n*Return*\n* status_code (number)\n    * success (less than or equal to zero)\n    * fatal error (greater than zero)\n* status_message (optional: string) logged when the status code is less than\n  zero\n\n### timer_event\n\nCalled when the host timer expires or on shutdown.\n\nRecommendation: specify this as a `ticker_interval` configuration option.\n\n*Arguments*\n* ns (number) - nanosecond timestamp of the function call (it is actually\n  `time_t * 1e9` to keep the timestamp units consistent so it will only have a\n  one second resolution)\n* shutdown (bool) - true if timer_event is being called due to a shutdown\n\n*Return*\n* none\n\n## Available C Functions (called from the plugin)\n\n### read_config\n\nProvides access to the sandbox configuration variables.\n\n*Arguments*\n* key (string) - configuration key name\n\n*Return*\n* value (string, number, bool, table)\n\n### read_message\n\nProvides access to the Heka message data. Note that both fieldIndex and\narrayIndex are zero-based (i.e. the first element is 0) as opposed to Lua's\nstandard indexing, which is one-based.\n\n*Arguments*\n* variableName (string)\n    * framed (returns the Heka message protobuf string including the framing\n      header)\n    * raw (returns the Heka message protobuf string)\n    * size (returns the size of the raw Heka message protobuf string)\n    * Uuid\n    * Type\n    * Logger\n    * Payload\n    * EnvVersion\n    * Hostname\n    * Timestamp\n    * Severity\n    * Pid\n    * Fields[*name*]\n* fieldIndex (unsigned) - only used in combination with the Fields variableName\nuse to retrieve a specific instance of a repeated field *name*; zero indexed\n* arrayIndex (unsigned) - only used in combination with the Fields variableName\nuse to retrieve a specific element out of a field containing an array; zero\nindexed\n* zeroCopy (bool, optional default false) - returns a userdata place holder for\nthe message variable (only valid for string types). Non string headers throw an\nerror during construction, non string fields throw an error on data retrieval.\n\n*Return*\n* value (number, string, bool, nil, userdata depending on the type of variable\n  requested)\n\n### decode_message\n\nConverts a Heka protobuf encoded message string into a Lua table or throws an\nerror.\n\n*Arguments*\n* heka_pb (string, userdata) - Heka protobuf binary string or a zero copy\n  userdata object containing a Heka protobuf binary string.\n\n*Return*\n* msg ([Heka message table (array fields)](message.md#array-based-message-fields))\nwith the value member always being an array (even if there is only a\nsingle item). This format makes working with the output more consistent. The\nwide variation in the inject table formats is to ease the construction of the\nmessage especially when using an LPeg grammar transformation.\n\n### inject_message\n\nCreates a new Heka protocol buffer message using the contents of the specified\nLua table (overwriting whatever is in the payload buffer). `Timestamp`,\n`Logger`, `Hostname` and `Pid` are restricted header values. An override\nconfiguration option is provided `restricted_headers`; when true (default) the\nheaders are always set to the configuration values; when false the headers are\nset to the values provided in the message table, if no value is provided it\ndefaults to the appropriate value.\n\n*Arguments*\n* msg ([Heka message table](message.md))\n\n*Return*\n* none (throws an error if the table does not match the Heka message schema)\n\n### add_to_payload\n\nAppends the arguments to the payload buffer for incremental construction of the\nfinal payload output (`inject_payload` finalizes the buffer and sends the\nmessage to the infrastructure). This function is a rename of the generic sandbox\noutput function to improve the readability of the plugin code.\n\n*Arguments*\n* arg (number, string, bool, nil, supported userdata)\n\n*Return*\n* none (throws an error if arg is an unsupported type)\n\n### inject_payload\n\nThis is a wrapper function for `inject_message` that is included for backwards\ncompatibility. The function creates a new Heka message using the contents of the\npayload buffer (pre-populated with `add_to_payload`) and combined with any\nadditional payload_args passed here. The payload buffer is cleared after the\ninjection. The `payload_type` and `payload_name` arguments are two pieces of\noptional metadata stored is message fields. The resulting message is structured\nlike this:\n```lua\nmsg = {\nTimestamp   = <current time>\nUuid        = \"<auto generated>\"\nHostname    = \"<the Hostname from the config>\"\nLogger      = \"<the Logger name from the config>\"\nType        = \"inject_payload\"\nPayload     = \"<payload buffer contents>\"\nFields      = {\n    payload_type = \"txt\",\n    payload_name = \"\",\n}\n```\n\n*Arguments*\n\n* payload_type (optional: string, default \"txt\") - describes the content type of\n  the injected payload data\n* payload_name (optional: string,  default \"\") - names the content to aid in\n  downstream filtering\n* arg3 (optional) -ame type restrictions as `add_to_payload`\n* ...\n* argN\n\n*Return*\n* none (throws an error if arg is an unsupported type)\n\n### Modes of Operation\n\n#### Lock Step\n* Receives one call to `process_message`, operates on the message, and returns\n  success (0) or failure (-1)\n\n#### Example simple counter plugin\n```lua\n-- cfg\nmessage_matcher = \"TRUE\"\nticker_interval = 5\n```\n\n```lua\n-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nlocal cnt = 0\n\nfunction process_message()\n    cnt = cnt + 1\n    return 0\nend\n\nfunction timer_event()\n    inject_payload(\"txt\", \"count\", cnt)\nend\n```\n"
  },
  {
    "path": "docs/heka/index.md",
    "content": "# Heka Sandbox Interface\n\n## Overview\n\nThis document describes the 1.0 release of the Heka sandbox API built on the\n[Generic Sandbox Interface](/sandbox.md). The 1.0 release is a refined\nimplementation of its predecessor which was developed in\n[Heka](https://github.com/mozilla-services/heka). The goal is to decople it from\nGo and make it easily embeddable in any language. The Go version of Heka has\nbeen deprecated and replaced by\n[Hindsight](https://github.com/mozilla-services/hindsight).\n\n## Sandbox API Changes from the Go Heka Sandbox\n\nThere are a few intentional changes between tho original Heka sandbox and this\nversion.\n\n### Changes\n\n#### Input Sandbox\n\n1. `inject_message` accepts a numeric or string checkpoint as the second\nargument\n1. `process_message` receives the checkpoint value as the first argument (if it\nwas provided by `inject_message`).\n\n#### Output Sandbox\n\n1. `process_message` receives a sequence_id as the first argument (if it was\nprovided by `update_checkpoint`). Extended return codes have been added to\nsupport skipping, retrying, batching, and asynchronous output.\n\n#### Analysis/Output Sandbox\n\n1. `read_message`\n    * returns `nil` for optional header fields if they don't exist instead of an\n    empty string or zero\n    * added a `framed` parameter to retrive the raw message with stream framing\n    * added a `size` parameter to retrive size of the raw message without having\n    to copy it down\n1. `timer_event` has a second parameter `shutdown` that is set to true when the\nsandbox is exiting.\n\n### Additions\n\n#### Input Sandbox\n\n1. [create_stream_reader](input.md#createstreamreader) function was added.\n1. [is_running](input.md#is_running) function was added.\n\n#### Output Sandbox\n\n1. [update_checkpoint](output.md#update_checkpoint) was added for batch and\nasynchronous processing.\n1. [create_message_matcher](output.md#createmessagematcher) function was added.\n\n### Removals\n\n1. The `write_message` API was removed; messages are immutable and this API\nbroke that rule.\n1. The `read_next_field` API was removed; instead the raw message should be\ndecoded and the Lua table iterated.\n\n### Notes\n\n1. The `read_config` API in unchanged but now has access to the entire sandbox configuration.\n"
  },
  {
    "path": "docs/heka/input.md",
    "content": "# Input Sandbox Interface\n\n## Recommendations\nSince the sandbox does not run in isolation there are some expectations of how\nthe host infrastructure behaves.  The current recommendations are based on the\nHindsight reference implementation.\n\n## Disabled Functionality\n- [base library](http://www.lua.org/manual/5.1/manual.html#5.1)\n    - dofile, load, loadfile, loadstring, newproxy\n- [string](http://www.lua.org/manual/5.1/manual.html#5.4)\n    - dump\n- [os](http://www.lua.org/manual/5.1/manual.html#5.8)\n    - exit, setlocale\n\n## Required Lua Functions (called by the host)\n\n### process_message\n\nEntry point for message creation.\n\n*Arguments*\n* checkpoint (nil number, string) - value of the last checkpoint value passed\ninto `inject_message`\n\n*Return*\n* status_code (number)\n  - success (less than or equal to zero)\n  - fatal error (greater than zero)\n* status_message (optional: string) logged when the status code is less than\nzero\n\n## Available C Functions (called from the plugin)\n\n### read_config\n\nProvides access to the sandbox configuration variables.\n\n*Arguments*\n* key (string) - configuration key name\n\n*Return*\n* value (string, number, bool, table)\n\n### is_running\n\nProvides a synchronization point for collecting statistics and communicating\nshutdown status.\n\n*Arguments*\n* none\n\n*Return*\n* running (boolean) - true if a sandbox state is LSB_RUNNING, false if not or\n  throws an error if the request to the host fails.\n\n### decode_message\n\nConverts a Heka protobuf encoded message string into a Lua table. See\n[decode_message](analysis.md#decodemessage) for details.\n\n### inject_message\n\nSends a Heka protocol buffer message into the host. For the Heka message table\narguments `Timestamp`, `Logger`, `Hostname` and `Pid` are restricted header\nvalues. An override configuration option is provided `restricted_headers`; when\ntrue the headers are always set to the configuration values; when false\n(default) the headers are set to the values provide in the message table,\nif no value is provided it defaults to the appropriate value.\n\n*Arguments*\n* msg ([Heka message table](message.md),\n  [Heka stream reader](#heka-stream-reader-methods),\n  Heka protobuf string,\n  or nil (if only updating the checkpoint))\n* checkpoint (optional: number, string) - checkpoint to be returned in the\n `process_message` call\n\n*Return*\n* none - throws an error on invalid input\n\n### create_stream_reader\nCreates a Heka stream reader to enable parsing of a framed Heka protobuf stream\nin a Lua sandbox. See:\n[Example of a Heka protobuf reader](#example-of-a-heka-protobuf-stdin-reader)\n\n*Arguments*\n* name (string) - name of the stream reader (used in the log)\n\n*Return*\n* hsr (userdata) - Heka stream reader or an error is thrown\n\n#### Heka Stream Reader Methods\n\n##### find_message\n\nLocates a Heka message within the stream.\n\n```lua\nlocal found, consumed, need = hsr:find_message(buf)\n\n```\n\n*Arguments*\n* buf (string, userdata (FILE*)) - buffer containing a Heka protobuf stream data\n  or a userdata file object\n* decode (bool default: true) - true if the framed message should be protobuf\n  decoded\n\n*Return*\n* found (bool) - true if a message was found\n* consumed (number) - number of bytes consumed so the offset can be tracked for\n  checkpointing purposes\n* need/read (number) - number of bytes needed to complete the message or fill\n  the underlying buffer or in the case of a file object the number of bytes\n  added to the buffer\n\n##### decode_message\n\nConverts a Heka protobuf encoded message string into a stream reader\nrepresentation. Note: this operation clears the internal stream reader buffer.\n\n*Arguments*\n* heka_pb (string) - Heka protobuf binary string\n\n*Return*\n* none - throws an error on failure\n\n##### read_message\n\nProvides access to the Heka message data within the reader object. The zeroCopy\nflag is not accepted here.\n\n```lua\nlocal ts = hsr:read_message(\"Timestamp\")\n\n```\nSee [read_message](analysis.md#readmessage) for details.\n\n## Modes of Operation\n\n### Run Once\n* Set the `ticker_interval` to zero and return from `process_message` done.\n* The `instruction_limit` configuration can be set if desired.\n\n#### Example startup ping\n```lua\n-- cfg\n-- send a simple 'hello' messages every time the host is started\nticker_interval = 0\n```\n\n```lua\n-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\n-- the checkpoint is optional and not being used by this plugin\nfunction process_message()\n    inject_message({Type = \"hello\"})\n    return 0\nend\n\n```\n\n### Polling\n\n* Set the `ticker_interval` greater than zero and non fatally (<=0) return from\n  `process_message`, when the ticker interval expires `process_message` will be\n  called again.\n* The `instruction_limit` configuration can be set if desired.\n\n#### Example heartbeat ping\n```lua\n-- cfg\nticker_interval = 60\n```\n\n```lua\n-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nrequire \"io\"\n\nlocal msg = {\nType        = \"uptime\",\nPayload     = \"\",\n}\n\nfunction process_message()\n    local fh = io.popen(\"uptime\")\n    if fh then\n        msg.Payload = fh:read(\"*a\")\n        fh:close()\n    else\n        return -1, \"popen failed\"\n    end\n    if msg.Payload then inject_message(msg) end\n    return 0\nend\n\n```\n\n### Continuous\n\n* Don't return from `process_message`.\n* The `instruction_limit` configuration **MUST** be set to zero.\n\n#### Example of a Heka protobuf stdin reader\n\n```lua\n-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\n--[[\nReads a Heka protobuf stream from the stdin file handle\n\n-- .cfg\ninstruction_limit = 0\n\n--]]\n\n\nlocal stdin = require \"io\".stdin\nrequire \"string\"\n\nlocal hsr = create_stream_reader(read_config(\"Logger\"))\n\nfunction process_message()\n    local cnt = 0\n    local found, consumed, read\n    repeat\n        repeat\n            found, consumed, read = hsr:find_message(stdin)\n            if found then\n                inject_message(hsr)\n                cnt = cnt + 1\n            end\n        until not found\n    until read == 0\n    return 0, string.format(\"processed %d messages\", cnt)\nend\n```\n"
  },
  {
    "path": "docs/heka/message.md",
    "content": "# Heka Message Table\n\n## Hash Based Message Fields\n\n```lua\n{\nUuid        = \"data\",               -- restricted header, auto generated if not a 16 byte raw binary UUID or a 36 character human readable UUID\nLogger      = \"nginx\",              -- restricted header, defaults to the Logger configuration value\nHostname    = \"example.com\",        -- restricted header, defaults to the Hostname configuration value\nTimestamp   = 1e9,                  -- restricted header, defaults to the current time\nType        = \"TEST\",\nPayload     = \"Test Payload\",\nEnvVersion  = \"0.8\",\nPid         = 1234,                 -- restricted header, defaults to the Pid configuration value\nSeverity    = 6,\nFields      = {\n            http_status     = 200,  -- encoded as a double\n            request_size    = {value=1413, value_type=2, representation=\"B\"} -- encoded as an integer\n            }\n}\n```\n\n## Array Based Message Fields\n```lua\n{\n-- Message headers are the same as above\nFields      = {\n            {name=\"http_status\" , value=200}, -- encoded as a double\n            {name=\"request_size\", value=1413, value_type=2, representation=\"B\"} -- encoded as an integer\n            }\n}\n```\n"
  },
  {
    "path": "docs/heka/output.md",
    "content": "# Output Sandbox Interface\n\n## Recommendations\nSince the sandbox does not run in isolation there are some expectations of how\nthe host infrastructure behaves.  The current recommendations are based on the\nHindsight reference implementation.\n\n## Disabled Functionality\n- [base library](http://www.lua.org/manual/5.1/manual.html#5.1)\n    - dofile, load, loadfile, loadstring, newproxy\n- [string](http://www.lua.org/manual/5.1/manual.html#5.4)\n    - dump\n- [os](http://www.lua.org/manual/5.1/manual.html#5.8)\n    - exit, setlocale\n\n## Required Lua Functions (called by the host)\n\n### process_message\n\nCalled when the host has a message available for analysis.  Usually used in\ncombination with a [message matcher](/util/message_matcher.md) expression.\n\nRecommenation: specify this as a `message_matcher` configuration option.\n\n*Arguments*\n* sequence_id (optional: lightuserdata) - pass in when `async_buffer_size` is\n  configured\n\n*Return*\n* status_code (number) - see the [Modes of Operation](#modes-of-operation) for\n  a detail explanation of the return codes\n    * fatal error (greater than zero)\n    * success (0)\n    * non fatal failure (-1)\n    * skip (-2)\n    * retry (-3)\n    * batching (-4)\n    * async output (-5)\n* status_message (optional: string) logged when the status code is -1\n\n### timer_event\n\nCalled when the host timer expires or on shutdown.\n\nRecommendation: specify this as a `ticker_interval` configuration option.\n\n*Arguments*\n* ns (number) - nanosecond timestamp of the function call (it is actually\n  `time_t * 1e9` to keep the timestamp units consistent so it will only have a\n  one second resolution)\n* shutdown (bool) - true if timer_event is being called due to a shutdown\n\n*Return*\n* none\n\n## Available C Functions (called from the plugin)\n\n### read_config\n\nProvides access to the sandbox configuration variables.\n\n*Arguments*\n* key (string) - configuration key name\n\n*Return*\n* value (string, number, bool, table)\n\n### read_message\n\nProvides access to the Heka message data. See\n[read_message](analysis.md#readmessage) for details.\n\n### decode_message\n\nConverts a Heka protobuf encoded message string into a Lua table. See\n[decode_message](analysis.md#decodemessage) for details.\n\n### encode_message\n\nReturns a Heka protocol buffer message using the contents of the specified Lua\ntable. `Timestamp`, `Logger`, `Hostname` and `Pid` are restricted header values.\nAn override configuration option is provided `restricted_headers`; when true the\nheaders are always set to the configuration values; when false (default) the\nheaders are set to the values provided in the message table, if no value is\nprovided it defaults to the appropriate configuration value.\n\nNote: this operation uses the internal output buffer so it is goverened by the\n`output_limit` configuration setting.\n\n*Arguments*\n* msg ([Heka message table](message.md))\n* framed (bool default: false) A value of true includes the framing header\n\n*Return*\n* heka_pb (string) - Heka protobuf binary string, framed as specified\n  or an error is thrown\n\n### inject_message\n\nCreates a new Heka protocol buffer message, in the input queue, using the\ncontents of the specified Lua table. The `restricted_headers` configuration\ndefaults to false (see encode_message above for a full description).\n\n*Arguments*\n* msg ([Heka message table](message.md))\n\n*Return*\n* none (throws an error if the table does not match the Heka message schema)\n\n### create_message_matcher\n\nReturns a Heka protocol buffer message matcher; used to dynamically filter\nmessages sent to the output plugin.\n\n*Arguments*\n* message_matcher [message matcher](/util/message_matcher.md)\n\n*Return*\n* message_matcher (userdata) - or an error is thrown\n  The message matcher object has one method `eval` that returns true if the\n  current message matches, false if it does not.\n\n#### Example\n\nSee: [heka_tcp_matcher.lua](https://mozilla-services.github.io/lua_sandbox_extensions/socket/sandboxes/heka/output/heka_tcp_matcher.html)\n\n### update_checkpoint\n\n#### Batch Mode\nAdvances the output checkpoint when in batching mode. The standard use case is\nto call it from `timer_event` after successfully flushing a batch on\ntimeout/shutdown.\n\n*Arguments*\n* none\n\n#### Asynchronous Mode\nAdvances the output checkpoint and optionally reports the number of failures\nthat occured.\n\n*Arguments*\n* sequence_id (lightuserdata) - sequence_id for the message that was just\n  successfully delivered/acknowledged\n* failures (optional: integer) - number of failures that occured in the\n  asynchronus processing (added to the failure count)\n\n*Return*\n* none (throws an error on invalid arg types)\n\n### Modes of Operation\n\n#### Lock Step\n\n* `process_message` operates on the message and returns one of the following\n  values:\n    * success (0) - the message was successfully processed and the output\n      checkpoint is advanced\n    * failure (-1) - the message was not successfully processed\n        * the failure count is incremented\n        * any optional error message is written to the log\n        * the message is skipped\n        * the checkpoint is advanced\n    * skip (-2) - the message was intentionally not processed and the checkpoint\n      is advanced\n    * retry (-3) - the message was not successfully processed and the host will\n      call `process_message` again, with the same message, after a one second\n      delay\n\n#### Example Payload Output\n\n```lua\n-- cfg\nmessage_matcher = \"Type == 'inject_payload'\"\nticker_interval = 0\n\n--location where the payload is written\noutput_dir      = \"/tmp\"\n```\n\n```lua\n-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nrequire \"io\"\nrequire \"string\"\n\nlocal output_dir = read_config(\"output_dir\") or \"/tmp\"\n\nfunction process_message()\n    local pt = read_message(\"Fields[payload_type]\")\n    if type(pt) ~= \"string\" then return -1, \"invalid payload_type\" end\n\n    local pn = read_message(\"Fields[payload_name]\") or \"\"\n    if type(pn) ~= \"string\" then return -1, \"invalid payload_name\" end\n\n    local logger = read_message(\"Logger\") or \"\"\n\n    pn = string.gsub(pn, \"%W\", \"_\")\n    pt = string.gsub(pt, \"%W\", \"_\")\n    logger = string.gsub(logger, \"%W\", \"_\")\n\n    local fn = string.format(\"%s/%s.%s.%s\", output_dir, logger, pn, pt)\n    local fh, err = io.open(fn, \"w\")\n    if err then return -1, err end\n\n    local payload = read_message(\"Payload\") or \"\"\n    fh:write(payload)\n    fh:close()\n    return 0\nend\n\nfunction timer_event(ns)\n    -- no op\nend\n```\n\n#### Batching\n\n* `process_message` batches the message/transformation in memory or on disk and\n  returns one of the following values:\n    * batching (-4) - the message was successfully added to the batch\n    * failure (-1) - the message cannot be batch\n        * the failure count is incremented\n        * any optional error message is written to the log\n        * the message is skipped\n    * skip (-2) - the message was intentionally not added to the batch\n    * retry (-3) - the message was not successfully added to the batch and the\n      host will call `process_message` again, with the same message, after a one\n      second delay\n    * success (0) - the batch has been successfully committed and the output\n      checkpoint is advanced to the most recent message\n\n#### Example Postgres Output\n\n```lua\n-- cfg\nmessage_matcher = \"Type == 'logfile'\"\nmemory_limit = 0\nticker_interval = 60\n\nbuffer_max = 1000\ndb_config = {\n    host = \"example.com\",\n    port = 5432,\n    name = \"dev\",\n    user = \"test\",\n    _password = \"testpw\",\n}\n```\n\n```lua\n-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nrequire \"os\"\nrequire \"string\"\nrequire \"table\"\n\nlocal driver = require \"luasql.postgres\"\n\nlocal ticker_interval = read_config(\"ticker_interval\")\nlocal db_config       = read_config(\"db_config\") or error(\"db_config must be set\")\nlocal buffer_max      = read_config(\"buffer_max\") or 1000\nassert(buffer_max > 0, \"buffer_max must be greater than zero\")\n\nlocal env = assert(driver.postgres())\nlocal con, err = env:connect(db_config.name, db_config.user, db_config._password, db_config.host, db_config.port)\nassert(con, err)\n\nlocal buffer = {}\nlocal buffer_len = 0\nlocal table_name = \"test_table\"\nlocal MAX_LENGTH = 65535\nlocal columns = {\n--   column name        field name                  field type      field length\n    {\"msg_Timestamp\"    ,\"Timestamp\"                ,\"TIMESTAMP\"    ,nil},\n    {\"payload\"          ,\"Payload\"                  ,\"VARCHAR\"      ,MAX_LENGTH},\n    {\"sourceName\"       ,\"Fields[sourceName]\"       ,\"VARCHAR\"      ,30},\n    {\"sourceVersion\"    ,\"Fields[sourceVersion]\"    ,\"VARCHAR\"      ,12},\n    {\"submissionDate\"   ,\"Fields[submissionDate]\"   ,\"DATE\"         ,nil},\n    {\"sampleId\"         ,\"Fields[sampleId]\"         ,\"SMALLINT\"     ,nil},\n}\n\nlocal function make_create_table()\n    local pieces = {\"CREATE TABLE IF NOT EXISTS \", table_name, \" (\"}\n    for i, c in ipairs(columns) do\n        table.insert(pieces, c[1])\n        table.insert(pieces, \" \")\n        table.insert(pieces, c[3])\n        if c[4] ~= nil then\n            table.insert(pieces, \"(\")\n            table.insert(pieces, c[4])\n            table.insert(pieces, \")\")\n        end\n        if c[4] == MAX_LENGTH then\n            table.insert(pieces, \" ENCODE LZO\")\n        end\n        if i < #columns then\n            table.insert(pieces, \", \")\n        end\n    end\n    table.insert(pieces, \")\")\n    return table.concat(pieces)\nend\nassert(con:execute(make_create_table()))\n\nlocal function bulk_load()\n    local cnt, err = con:execute(table.concat(buffer))\n    if not err then\n        buffer = {}\n        buffer_len = 0\n    else\n        return err\n    end\nend\n\nlocal function esc_str(v)\n    if v == nil then return \"NULL\" end\n\n    if type(v) ~= \"string\" then v = tostring(v) end\n    if string.len(v) > MAX_LENGTH then\n        v = \"TRUNCATED:\" .. string.sub(v, 1, MAX_LENGTH - 10)\n    end\n\n    local escd = con:escape(v)\n    if not escd then return \"NULL\" end\n\n    return string.format(\"'%s'\", escd)\nend\n\nlocal function esc_num(v)\n    if v == nil then return \"NULL\" end\n    if type(v) ~= \"number\" then return esc_str(v) end\n    return tostring(v)\nend\n\nlocal function esc_ts(v)\n    if v == nil then return \"NULL\" end\n    if type(v) ~= \"number\" then return esc_str(v) end\n    local seconds = v / 1e9\n    return table.concat({\"(TIMESTAMP 'epoch' + \", seconds, \" * INTERVAL '1 seconds')\"})\nend\n\nlocal function make_insert(sep)\n    local pieces = {sep, \"(\"}\n    for i=1,#columns do\n        if i > 1 then\n            table.insert(pieces, \",\")\n        end\n        local col = columns[i]\n        if col[3] == \"TIMESTAMP\" then\n            table.insert(pieces, esc_ts(read_message(col[2])))\n        elseif col[3] == \"SMALLINT\" then\n            table.insert(pieces, esc_num(read_message(col[2])))\n        else\n            table.insert(pieces, esc_str(read_message(col[2])))\n        end\n    end\n    table.insert(pieces, \")\")\n    return table.concat(pieces)\nend\n\nlocal last_load = 0\nfunction process_message()\n    local sep = \",\"\n    if buffer_len == 0 then\n        buffer_len = buffer_len + 1\n        buffer[buffer_len] = string.format(\"INSERT INTO %s VALUES\", table_name)\n        sep = \" \"\n    end\n    buffer_len = buffer_len + 1\n    buffer[buffer_len] = make_insert(sep)\n\n    if buffer_len - 1 >= buffer_max then\n        local err = bulk_load()\n        if err then\n            buffer[buffer_len] = nil\n            buffer_len = buffer_len - 1\n            return -3, err\n        else\n            last_load = os.time()\n            return 0\n        end\n    end\n    return -4\nend\n\nfunction timer_event(ns, shutdown)\n    if buffer_len > 1 and (shutdown or last_load + ticker_interval <= ns / 1e9)then\n        local err = bulk_load()\n        if not err then\n            update_checkpoint()\n        end\n    end\nend\n```\n\n#### Asynchronous\n\n* `async_buffer_size` Recommendation: this configuration variable should be set\nand consumed by the host\n* `process_message` is called with a sequence_id parameter and asynchronously\nsends the message/transformation to the destination and returns one of the\nfollowing values:\n  * asynchronous (-5) - the message was successfully queued\n  * failure (-1) - the message cannot be queue\n    * the failure count is incremented\n    * any optional error message is written to the log\n    * the message is skipped\n  * skip (-2) - the message was intentionally not queued\n  * retry (-3) - the message was not successfully queued and the host will call\n  `process_message` again, with the same message, after a one second delay\n* When an asynchronously sent message is acknowledged\n[update_checkpoint](#updatecheckpoint) **MUST** be called to advance the\ncheckpoint to that specific message\n\n#### Example Kafka Output\n[kafka.lua](https://github.com/mozilla-services/lua_sandbox_extensions/blob/main/kafka/sandboxes/heka/output/kafka.lua)\n"
  },
  {
    "path": "docs/index.md",
    "content": "# Overview\n\nSandboxes provide a dynamic and isolated execution environment\nfor data parsing, transformation, and analysis.  They allow access to data\nwithout jeopardizing the integrity or performance of the processing\ninfrastructure. This broadens the audience that the data can be\nexposed to and facilitates new uses of the data (i.e. debugging, monitoring,\ndynamic provisioning,  SLA analysis, intrusion detection, ad-hoc reporting,\netc.)\n\nThe Lua sandbox is a library allowing customized control over the Lua execution\nenvironment including functionality like global data preservation/restoration on\nshutdown/startup, output collection in textual or binary formats and an array of\nparsers for various data types (Nginx, Apache, Syslog, MySQL and many RFC grammars)\n\nThese libraries and utilities have been mostly extracted from [Hindsight](https://github.com/mozilla-services/hindsight).\nThe goal was to decouple the Heka/Hindsight functionality from any particular\ninfrastructure and make it embeddable into any tool or language.\n\n## Features\n\n- small - memory requirements are as little as 8 KiB for a basic sandbox\n- fast - microsecond execution times\n- stateful - ability to resume where it left off after a restart/reboot\n- isolated - failures are contained and malfunctioning sandboxes are terminated.\n  Containment is defined in terms of restriction to the operating system,\n  file system, libraries, memory use, Lua instruction use, and output size.\n"
  },
  {
    "path": "docs/sandbox.md",
    "content": "# Generic Sandbox Interface\n\n## Configuration\n\n* **input_limit** - the largest input string that is allowed to be processed\n  (bytes (unsigned), default 65536, 0 for unlimited*). This is not directly used\n  by the sandbox it is made availble to modules to standardize the configuration.\n* **output_limit** - the largest output string an input or analysis plugin can\n  inject into the host (bytes (unsigned), default 65536, 0 for unlimited*)\n* **memory_limit** - the maximum amount of memory a plugin can use before being\n  terminated (bytes (unsigned), default 8388608, 0 for unlimited*)\n* **instruction_limit** - the maximum number of Lua instructions a plugin can\n  execute in a single API function call (count (unsigned), default 1000000, 0\n  for unlimited)\n* **path** - The path used by require to search for a Lua loader. See\n  [package loaders](http://www.lua.org/manual/5.1/manual.html#pdf-package.loaders)\n  for the path syntax.  By default no paths are set in the sandbox and\n  everything has been moved to a sandbox configuration table.\n* **cpath** - The path used by require to search for a C loader (same notes as\n  above)\n* **disabled_modules** - Hash specifying which modules should be completely\n  inaccessible.  The existence of the key in the table will disable the module.\n```lua\ndisabled_modules = {io = 1}\n```\n* **remove_entries** - Hash specifying which functions within a module should be\n  inaccessible\n```lua\nremove_entries = {\n    os = {\"getenv\", \"execute\"},\n    string = {\"dump\"}\n}\n```\n* **log_level** - syslog severity level, when set to  debug (7) the print\n  function will be wired to the specified logger (default error (3))\n* *user defined*  any other variable (string, bool, number, table) is passed\n  through as-is and available via [read_config](#readconfig)\n\n*_0 == SIZE_MAX which in not necessarily the upper limit of the\nconfiguration range UINT_MAX_\n\n## Lua functions exposed to C by the core sandbox\n\nThere are no functions exposed by default, see lsb_pcall_setup() and\nlsb_pcall_teardown() when defining an API.\n\n## Functions exposed to Lua by the core sandbox\n\n### require\n\nBy default only the base library is loaded, additional libraries must be loaded\nwith require().\n\n*Arguments*\n\n- libraryName (string)\n\n*Return*\n- a table - For non user provided libraries the table is also globally\n  registered with the library name.  User provided libraries may implement their\n  own semantics i.e. the grammar libraries return a table but do not globally\n  register the table name (see the individual module documentation for the\n  correct usage).\n\n*Notes*\n\nThe following modules have been modified, as described, for use in the sandbox.\n  - [base library](http://www.lua.org/manual/5.1/manual.html#5.1)\n    - The require() function has been modified to not expose any of the package\n      table to the sandbox.\n  - [math](http://www.lua.org/manual/5.1/manual.html#5.6)\n    - Added Functions\n        - erf(x) - Returns the error function value for x.\n        - erfc(x)- Returns the complementary error function value for x.\n  - [os](http://www.lua.org/manual/5.1/manual.html#5.8)\n    - The local timezone is set to UTC in all sandboxes.\n\n### read_config\n\nProvides access to the sandbox configuration variables.\n\n*Arguments*\n* key (string) - configuration key name\n\n*Return*\n* value (string, number, bool, table)\n\n### output\nReceives any number of arguments and appends data to the output buffer, which\ncannot exceed the output_limit configuration parameter. See lsb_get_output() to\nconnect the output to the host application.\n\n*Arguments*\n- arg (number, string, bool, nil, userdata implementing output support) - Lua\n  variable or literal to be appended the output buffer\n\n*Return*\n- none\n\n### print\nReceives any number of arguments and sends a debug message to the host's logger\nfunction as a tab delimited message. The function clears and then uses the\noutput buffer so if pending output has been queued and not flushed it will be\nlost (the same output_limit restrictions apply).  Non-printable characters\nare replaced with spaces to preserve the host's log integrity and any embedded\nNULs terminate each argument.\n\n*Arguments*\n- arg (anything that can be converted to a string with the tostring function)\n\n*Return*\n- none\n\n**Note:** To extend the function set exposed to Lua see lsb_add_function()\n\n## Special Lua Global Variables\n\n- **_PRESERVATION_VERSION** (number) This variable is examined during state\nrestoration; if the previous version does not match the current version the\nrestoration is aborted and the sandbox starts cleanly. The version should be\nincremented any time an incompatible change is made to the global data schema.\n\nWhen versioning is required, the use of a configuration variable name\n`preservation_version` with the following syntax is recommended.\n```lua\n-- initial (allows the user to bump the version due to a cfg change)\n_PRESERVATION_VERSION = read_config(\"preservation_version\") or 0\n\n-- if the plugin code alters the global data schema in an incompatible way this\n-- ensures the state is properly cleared when there is a user provided version.\n_PRESERVATION_VERSION = (read_config(\"preservation_version\") or 0) + 1\n```\n\n## How to interact with the sandbox (creating an API)\n\nThe best place to start is with some examples:\n\n### Unit Test API\n\n[Unit Test API](https://mozilla-services.github.io/lua_sandbox/doxygen/test_2sandbox_8h.html)\n\n#### Lua Functions Exposed to C\n\n- int **process** (double)\n    - exposes a process function that takes a test case number as its argument\n      and returns and integer result code.\n- void **report** (double)\n    - exposes a report function that takes a test case number as its argument\n      and returns nothing.\n\n#### C Functions Exposed to Lua\n\n- void **write_output** (optionalArg1, optionalArg2, optionalArgN)\n    - captures whatever is in the output buffer for use by the host application,\n      appending any optional arguments (optional arguments have the same\n      restriction as output).\n\n### Heka Sandbox API\n\n[Heka Sandbox API](https://mozilla-services.github.io/lua_sandbox/doxygen/heka_2sandbox_8h.html)\n"
  },
  {
    "path": "docs/util/message_matcher.md",
    "content": "# Message Matcher Syntax\n\nThe message matcher allows sandboxes to select which messages they want to\nconsume (see [Heka Message Structure](/heka/message.md))\n\n## Examples\n\n*  Type == \"test\" && Severity == 6\n*  (Severity == 7 || Payload == \"Test Payload\") && Type == \"test\"\n*  Fields[foo] != \"bar\"\n*  Fields[foo][1][0] == \"alternate\"\n*  Fields[MyBool] == TRUE\n*  TRUE\n*  Fields[created] =~ \"^2015\"\n*  Fields[string] =~ \"foo.example.com\"% -- literal pattern vs \"foo%.example%.com\"\n*  Fields[widget] != NIL\n*  Timestamp >= \"2016-05-24T00:00:00Z\"\n*  Timestamp >= 1464048000000000000\n\n## Relational Operators\n\n* == equals\n* != not equals\n* &gt; greater than\n* &gt;= greater than equals\n* < less than\n* <= less than equals\n* =~ Lua pattern match\n* !~ Lua negated pattern match\n\n## Logical Operators\n\n* Parentheses are used for grouping expressions\n* && and (higher precedence)\n* || or\n\n## Boolean\n\n* TRUE\n* FALSE\n\n## Constants\n\n* NIL used to test the existence (!=) or non-existence (==) of optional headers or field variables\n\n## Message Variables\n\n* All message variables must be on the left hand side of the relational\ncomparison\n\n### String\n\n* Uuid - 16 byte raw binary type 4 UUID (useful for partitioning data)\n* Type\n* Logger\n* Payload\n* EnvVersion\n* Hostname\n\n### Numeric\n\n* Timestamp - in addition to nanoseconds since the UNIX epoch an RFC3339 string is also accepted e.g., \"2016-05-24T21:51:00Z\"\n* Severity\n* Pid\n\n### Fields\n\n* Fields[_field_name_] - shorthand for Field[_field_name_][0][0]\n* Fields[_field_name_][_field_index_] - shorthand for Field[_field_name_][_field_index_][0]\n* Fields[_field_name_][_field_index_][_array_index_] the indices are restricted to 0-255\n* If a field type is mis-match for the relational comparison, false will be returned e.g., Fields[foo] == 6 where \"foo\" is a string\n\n## Quoted String\n\n* Single or double quoted strings are allowed\n* The maximum string length is 255 bytes\n\n## Lua Pattern Matching Expression\n\n* Patterns are quoted string values\n    * An 'escape' pattern modifier of `%` is allowed e.g. `\"foo.bar\"%` is\n    treated as a literal instead of a pattern and behaves like the 'plain'\n    option on string.find(). If there are no pattern match characters in the\n    string this modifier is set automatically.\n* See [Lua Patterns](http://www.lua.org/manual/5.1/manual.html#5.4.1)\n* Capture groups are ignored\n\n## Additional Restrictions\n\n* Message matchers are restricted to 128 relational comparisons\n* A NUL character '\\0' is not allowed in a matcher string\n"
  },
  {
    "path": "gen_gh_pages.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nrequire \"os\"\nrequire \"io\"\nrequire \"string\"\n\n\nlocal function output_menu(output_dir, version)\n    local fh = assert(io.open(string.format(\"%s/SUMMARY.md\", output_dir), \"w\"))\n    fh:write(string.format(\"* [Lua Sandbox Library (%s)](README.md)\\n\\n\", version))\n    fh:write([[\n* [Generic Sandbox](sandbox.md)\n* [Heka Sandbox](heka/index.md)\n   * [Input Interface](heka/input.md)\n   * [Analysis Interface](heka/analysis.md)\n   * [Output Interface](heka/output.md)\n   * [Message Schema](heka/message.md)\n   * [Message Matcher](util/message_matcher.md)\n* [Command Line Tools](cli/index.md)\n* [Source Documentation](https://mozilla-services.github.io/lua_sandbox/doxygen/index.html)\n* [Sandbox Extensions](https://mozilla-services.github.io/lua_sandbox_extensions)\n]])\n    fh:close()\nend\n\n\nlocal args = {...}\nlocal function main()\n    local output_dir = string.format(\"%s/gb-source\", arg[3])\n    local rv = os.execute(string.format(\"rsync -rav docs/ %s/\", output_dir))\n    if rv ~= 0 then error\"rsync setup\" end\n\n    local fh = assert(io.open(string.format(\"%s/book.json\", output_dir), \"w\"))\n    fh:write([[{\"plugins\" : [\"collapsible-menu\", \"navigator\"]}]])\n    fh:close()\n\n    os.execute(string.format(\"cd %s;gitbook install\", output_dir))\n    os.execute(string.format(\"mv %s/index.md %s/README.md\", output_dir, output_dir))\n    output_menu(output_dir, args[1])\n    os.execute(string.format(\"gitbook build %s\", output_dir))\n    local rv = os.execute(string.format(\"rsync -rav %s/_book/ %s/\", output_dir, \"gh-pages/\"))\n    if rv ~= 0 then error\"rsync publish\" end\nend\n\nmain()\n"
  },
  {
    "path": "include/luasandbox/error.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Error handling and logging  @file */\n\n#ifndef luasandbox_error_h_\n#define luasandbox_error_h_\n\n// See Identify your Errors better with char[]\n// http://accu.org/index.php/journals/2184\ntypedef const char lsb_err_id[];\ntypedef const char *lsb_err_value;\n#define lsb_err_string(s) s ? s : \"<no error>\"\n\ntypedef void (*lsb_logger_cb)(void *context,\n                              const char *component,\n                              int level,\n                              const char *fmt,\n                              ...);\n\ntypedef struct lsb_logger {\n  void          *context;\n  lsb_logger_cb cb;\n} lsb_logger;\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/heka/sandbox.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Heka sandbox implementation @file */\n\n#ifndef luasandbox_heka_sandbox_h_\n#define luasandbox_heka_sandbox_h_\n\n#include <stdbool.h>\n#include <time.h>\n\n#include \"../../luasandbox.h\"\n#include \"../error.h\"\n#include \"../util/heka_message.h\"\n\n#ifdef _WIN32\n#ifdef luasandboxheka_EXPORTS\n#define LSB_HEKA_EXPORT __declspec(dllexport)\n#else\n#define LSB_HEKA_EXPORT __declspec(dllimport)\n#endif\n#else\n#if __GNUC__ >= 4\n#define LSB_HEKA_EXPORT __attribute__ ((visibility (\"default\")))\n#else\n#define LSB_HEKA_EXPORT\n#endif\n#endif\n\n#define LSB_HEKA_MAX_MESSAGE_SIZE \"max_message_size\"\n#define LSB_HEKA_UPDATE_CHECKPOINT \"update_checkpoint\"\n#define LSB_HEKA_THIS_PTR \"lsb_heka_this_ptr\"\n\nenum lsb_heka_pm_rv {\n  LSB_HEKA_PM_SENT  = 0,\n  LSB_HEKA_PM_FAIL  = -1,\n  LSB_HEKA_PM_SKIP  = -2,\n  LSB_HEKA_PM_RETRY = -3,\n  LSB_HEKA_PM_BATCH = -4,\n  LSB_HEKA_PM_ASYNC = -5\n};\n\nenum lsb_heka_im_rv {\n  LSB_HEKA_IM_SUCCESS    = 0,\n  LSB_HEKA_IM_ERROR      = 1, // generic error for backward compatibility\n  LSB_HEKA_IM_CHECKPOINT = 2,\n  LSB_HEKA_IM_LIMIT      = 3,\n};\n\ntypedef struct lsb_heka_sandbox lsb_heka_sandbox;\n\ntypedef struct lsb_heka_stats {\n  unsigned long long mem_cur;\n  unsigned long long mem_max;\n  unsigned long long ins_max;\n  unsigned long long out_max;\n  unsigned long long im_cnt;\n  unsigned long long im_bytes;\n  unsigned long long pm_cnt;\n  unsigned long long pm_failures;\n  double             pm_avg;\n  double             pm_sd;\n  double             te_avg;\n  double             te_sd;\n} lsb_heka_stats;\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n#include \"../lauxlib.h\"\n#include \"../lua.h\"\n\nLSB_HEKA_EXPORT extern lsb_err_id LSB_ERR_HEKA_INPUT;\n\n/**\n * inject_message callback function provided by the host. Only one (or neither)\n * of the checkpoint values will be set in a call.  Numeric checkpoints can have\n * a measurable performance benefit but are not always applicable so both\n * options are provided to support various types of input plugins. This function\n * can be called with a NULL pb pointer by the 'is_running' API or if only a\n * checkpoint update is being performed; it should be treated as a no-op and\n * used as a synchronization point to collect statistics and communicate\n * shutdown status.\n *\n * @param parent Opaque pointer the host object owning this sandbox\n * @param pb Pointer to a Heka protobuf encoded message being injected.\n * @param pb_en Length of s\n * @param cp_numeric Numeric based checkpoint (can be NAN)\n * @param cp_string String based checkpoint (can be NULL)\n *\n * @return 0 on success\n */\ntypedef int (*lsb_heka_im_input)(void *parent,\n                                 const char *pb,\n                                 size_t pb_len,\n                                 double cp_numeric,\n                                 const char *cp_string);\n\n/**\n * inject_message callback function provided by the host.\n *\n * @param parent Opaque pointer the host object owning this sandbox.\n * @param pb Pointer to a Heka protobuf encoded message being injected.\n * @param len Length of pb_len\n *\n * @return 0 on success\n */\ntypedef int (*lsb_heka_im_analysis)(void *parent,\n                                    const char *pb,\n                                    size_t pb_len);\n\n/**\n * update_checkpoint callback function provided by the host.\n *\n * @param parent Opaque pointer the host object owning this sandbox.\n * @param sequence_id Opaque pointer to the host message sequencing (passed into\n *               process_message).\n *\n * @return 0 on success\n */\ntypedef int (*lsb_heka_update_checkpoint)(void *parent, void *sequence_id);\n\n/**\n * Create a sandbox supporting the Heka Input Plugin API\n *\n * @param parent Opaque pointer the host object owning this sandbox\n * @param lua_file Fully qualified path to the Lua source file\n * @param state_file Fully qualified filename to the state preservation file\n *                   (NULL if no preservation is required)\n * @param lsb_cfg Full configuration string as a Lua table (NULL for lsb\n *                defaults)\n * @param logger Struct for error reporting/debug printing (NULL to disable)\n * @param im inject_message callback\n * @return lsb_heka_sandbox* On success a pointer to the sandbox otherwise NULL\n */\nLSB_HEKA_EXPORT\nlsb_heka_sandbox* lsb_heka_create_input(void *parent,\n                                        const char *lua_file,\n                                        const char *state_file,\n                                        const char *lsb_cfg,\n                                        lsb_logger *logger,\n                                        lsb_heka_im_input im);\n\n/**\n * Host access to the input sandbox process_message API.  If a numeric\n * checkpoint is set the string checkpoint is ignored.\n *\n * @param hsb Heka input sandbox\n * @param cp_numeric NAN if no numeric checkpoint\n * @param cp_string NULL if no string checkpoint\n * @param profile Take a timing sample on this execution\n *\n * @return int\n *  >0 fatal error\n *  0  success\n *  <0 non-fatal error (status message is logged)\n *\n */\nLSB_HEKA_EXPORT\nint lsb_heka_pm_input(lsb_heka_sandbox *hsb,\n                      double cp_numeric,\n                      const char *cp_string,\n                      bool profile);\n\n/**\n * Create a sandbox supporting the Heka Analysis Plugin API\n *\n * @param parent Opaque pointer the host object owning this sandbox\n * @param lua_file Fully qualified filename to the Lua source file\n * @param state_file Fully qualified filename to the state preservation file\n *                   (NULL if no preservation is required)\n * @param lsb_cfg Full configuration string as a Lua table (NULL for lsb\n *                defaults)\n * @param logger Struct for error reporting/debug printing (NULL to disable)\n * @param im inject_message callback\n * @return lsb_heka_sandbox* On success a pointer to the sandbox otherwise NULL\n */\nLSB_HEKA_EXPORT\nlsb_heka_sandbox* lsb_heka_create_analysis(void *parent,\n                                           const char *lua_file,\n                                           const char *state_file,\n                                           const char *lsb_cfg,\n                                           lsb_logger *logger,\n                                           lsb_heka_im_analysis im);\n\n/**\n * Host access to the analysis sandbox process_message API\n *\n * @param hsb Heka analysis sandbox\n * @param msg Heka message to process\n * @param profile Take a timing sample on this execution\n *\n * @return int\n *  >0 fatal error\n *  0  success\n *  <0 non-fatal error (status message is logged)\n *\n */\nLSB_HEKA_EXPORT\nint lsb_heka_pm_analysis(lsb_heka_sandbox *hsb,\n                         lsb_heka_message *msg,\n                         bool profile);\n\n/**\n * Create a sandbox supporting the Heka Output Plugin API\n *\n * @param parent Opaque pointer the host object owning this sandbox\n * @param lua_file Fully qualified path to the Lua source file\n * @param state_file Fully qualified filename to the state preservation file\n *                   (NULL if no preservation is required)\n * @param lsb_cfg Full configuration string as a Lua table (NULL for lsb\n *                defaults)\n * @param logger Struct for error reporting/debug printing (NULL to disable)\n * @param ucp checkpoint_updated callback when using batch or async output\n *\n * @return lsb_heka_sandbox* On success a pointer to the sandbox otherwise NULL\n */\nLSB_HEKA_EXPORT\nlsb_heka_sandbox* lsb_heka_create_output(void *parent,\n                                         const char *lua_file,\n                                         const char *state_file,\n                                         const char *lsb_cfg,\n                                         lsb_logger *logger,\n                                         lsb_heka_update_checkpoint ucp);\n\n/**\n * Create a sandbox supporting the Heka Output Plugin API with\n * inject_message support\n *\n * @param parent Opaque pointer the host object owning this sandbox\n * @param lua_file Fully qualified path to the Lua source file\n * @param state_file Fully qualified filename to the state preservation file\n *                   (NULL if no preservation is required)\n * @param lsb_cfg Full configuration string as a Lua table (NULL for lsb\n *                defaults)\n * @param logger Struct for error reporting/debug printing (NULL to disable)\n * @param ucp checkpoint_updated callback when using batch or async output\n * @param im inject_message callback\n *\n * @return lsb_heka_sandbox* On success a pointer to the sandbox otherwise NULL\n */\nLSB_HEKA_EXPORT\nlsb_heka_sandbox* lsb_heka_create_output_im(void *parent,\n                                         const char *lua_file,\n                                         const char *state_file,\n                                         const char *lsb_cfg,\n                                         lsb_logger *logger,\n                                         lsb_heka_update_checkpoint ucp,\n                                         lsb_heka_im_analysis im);\n/**\n * Host access to the output sandbox process_message API\n *\n * @param hsb Heka output sandbox\n * @param msg Heka message to process\n * @param sequence_id Opaque pointer to the message sequence id (only used for\n *                    async output plugin otherwise it should be NULL)\n * @param profile Take a timing sample on this execution\n *\n * @return int\n *  >0 fatal error\n *  0  success\n *  -1 non-fatal_error (status message is logged)\n *  -2 skip\n *  -3 retry\n *  -4 batching\n *  -5 async output\n *\n */\nLSB_HEKA_EXPORT\nint lsb_heka_pm_output(lsb_heka_sandbox *hsb,\n                       lsb_heka_message *msg,\n                       void *sequence_id,\n                       bool profile);\n/**\n * Requests a long running input sandbox to stop. This call is not thread safe.\n *\n * @param hsb Heka sandbox to cleanly stop\n *\n * @return\n *\n */\nLSB_HEKA_EXPORT void\nlsb_heka_stop_sandbox_clean(lsb_heka_sandbox *hsb);\n\n/**\n * Aborts the running sandbox from a different thread of execution. A \"shutting\n * down\" termination message is generated. Used to abort long runnning sandboxes\n * such as an input sandbox.\n *\n * @param hsb Heka sandbox to forcibly stop\n *\n * @return\n *\n */\nLSB_HEKA_EXPORT void\nlsb_heka_stop_sandbox(lsb_heka_sandbox *hsb);\n\n/**\n * Terminates the sandbox as if it had a fatal error (not thread safe).\n *\n * @param hsb Heka sandbox to terminate\n * @param err Reason for termination\n */\nLSB_HEKA_EXPORT void\nlsb_heka_terminate_sandbox(lsb_heka_sandbox *hsb, const char *err);\n\n/**\n * Frees all memory associated with the sandbox; hsb cannont be used after this\n * point and the host should set it to NULL.\n *\n * @param hsb Heka sandbox to free\n *\n * @return NULL on success, pointer to an error message on failure that MUST BE\n * FREED by the caller.\n *\n */\nLSB_HEKA_EXPORT char*\nlsb_heka_destroy_sandbox(lsb_heka_sandbox *hsb);\n\n/**\n * Host access to the timer_event API\n *\n * @param hsb Heka sandbox\n * @param t Clock time of the timer_event execution\n * @param shutdown Flag indicating the Host is shutting down allowing the\n *                 sandbox to do any desired finialization)\n *\n * @return int 0 on success\n */\nLSB_HEKA_EXPORT\nint lsb_heka_timer_event(lsb_heka_sandbox *hsb, time_t t, bool shutdown);\n\n/**\n * Return the last error in human readable form.\n *\n * @param hsb Heka sandbox\n *\n * @return const char* error message\n */\nLSB_HEKA_EXPORT const char* lsb_heka_get_error(lsb_heka_sandbox *hsb);\n\n/**\n * Returns the filename of the Lua source.\n *\n * @param hsb Heka sandbox\n *\n * @return const char* filename.\n */\nLSB_HEKA_EXPORT const char* lsb_heka_get_lua_file(lsb_heka_sandbox *hsb);\n\n/**\n * Retrieve the sandbox profiling/monitoring statistics.  This call accesses\n * internal data and is not thread safe.\n *\n * @param hsb Heka sandbox\n *\n * @return lsb_heka_stats A copy of the stats structure\n */\nLSB_HEKA_EXPORT lsb_heka_stats lsb_heka_get_stats(lsb_heka_sandbox *hsb);\n\n/**\n * Convenience function to test if a sandbox is running.\n *\n * @param hsb Heka sandbox\n *\n * @return True if the sandbox has not been terminated\n */\nLSB_HEKA_EXPORT bool lsb_heka_is_running(lsb_heka_sandbox *hsb);\n\n/**\n * Queries the state of the sandbox.\n *\n * @param hsb\n *\n * @return lsb_state\n *\n */\nLSB_HEKA_EXPORT lsb_state lsb_heka_get_state(lsb_heka_sandbox *hsb);\n\n/**\n * Retrieve the currently active sandbox message.  This call returns a handle to\n * internal data and is not thread safe.\n * *\n * @param hsb Heka sandbox\n *\n * @return const lsb_heka_message* NULL if there is no active message\n */\nLSB_HEKA_EXPORT const lsb_heka_message*\nlsb_heka_get_message(lsb_heka_sandbox *hsb);\n\n/**\n * Retrieve the sandbox type.\n * *\n * @param hsb Heka sandbox\n *\n * @return char Heka sandbox type identifer\n */\nLSB_HEKA_EXPORT char lsb_heka_get_type(lsb_heka_sandbox *hsb);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/heka/stream_reader.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Hindsight Heka stream reader structures @file */\n\n#ifndef luasandbox_heka_stream_reader_h_\n#define luasandbox_heka_stream_reader_h_\n\n#include \"../util/heka_message.h\"\n#include \"../util/input_buffer.h\"\n\n#define LSB_HEKA_STREAM_READER \"lsb.heka_stream_reader\"\n\ntypedef struct heka_stream_reader\n{\n  char             *name;\n  lsb_heka_message msg;\n  lsb_input_buffer buf;\n} heka_stream_reader;\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/lauxlib.h",
    "content": "/*\n** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions for building Lua libraries\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lauxlib_h\n#define lauxlib_h\n\n\n#include <stddef.h>\n#include <stdio.h>\n\n#include \"lua.h\"\n\n\n#if defined(LUA_COMPAT_GETN)\nLUALIB_API int (luaL_getn) (lua_State *L, int t);\nLUALIB_API void (luaL_setn) (lua_State *L, int t, int n);\n#else\n#define luaL_getn(L,i)          ((int)lua_objlen(L, i))\n#define luaL_setn(L,i,j)        ((void)0)  /* no op! */\n#endif\n\n#if defined(LUA_COMPAT_OPENLIB)\n#define luaI_openlib\tluaL_openlib\n#endif\n\n\n/* extra error code for `luaL_load' */\n#define LUA_ERRFILE     (LUA_ERRERR+1)\n\n\ntypedef struct luaL_Reg {\n  const char *name;\n  lua_CFunction func;\n} luaL_Reg;\n\n\n\nLUALIB_API void (luaI_openlib) (lua_State *L, const char *libname,\n                                const luaL_Reg *l, int nup);\nLUALIB_API void (luaL_register) (lua_State *L, const char *libname,\n                                const luaL_Reg *l);\nLUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e);\nLUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e);\nLUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname);\nLUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg);\nLUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg,\n                                                          size_t *l);\nLUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg,\n                                          const char *def, size_t *l);\nLUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg);\nLUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def);\n\nLUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg);\nLUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg,\n                                          lua_Integer def);\n\nLUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg);\nLUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t);\nLUALIB_API void (luaL_checkany) (lua_State *L, int narg);\n\nLUALIB_API int   (luaL_newmetatable) (lua_State *L, const char *tname);\nLUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname);\n\nLUALIB_API void (luaL_where) (lua_State *L, int lvl);\nLUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...);\n\nLUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def,\n                                   const char *const lst[]);\n\nLUALIB_API int (luaL_ref) (lua_State *L, int t);\nLUALIB_API void (luaL_unref) (lua_State *L, int t, int ref);\n\nLUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename);\nLUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz,\n                                  const char *name);\nLUALIB_API int (luaL_loadstring) (lua_State *L, const char *s);\n\nLUALIB_API lua_State *(luaL_newstate) (void);\n\n\nLUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p,\n                                                  const char *r);\n\nLUALIB_API const char *(luaL_findtable) (lua_State *L, int idx,\n                                         const char *fname, int szhint);\n\n\n\n\n/*\n** ===============================================================\n** some useful macros\n** ===============================================================\n*/\n\n#define luaL_argcheck(L, cond,numarg,extramsg)\t\\\n\t\t((void)((cond) || luaL_argerror(L, (numarg), (extramsg))))\n#define luaL_checkstring(L,n)\t(luaL_checklstring(L, (n), NULL))\n#define luaL_optstring(L,n,d)\t(luaL_optlstring(L, (n), (d), NULL))\n#define luaL_checkint(L,n)\t((int)luaL_checkinteger(L, (n)))\n#define luaL_optint(L,n,d)\t((int)luaL_optinteger(L, (n), (d)))\n#define luaL_checklong(L,n)\t((long)luaL_checkinteger(L, (n)))\n#define luaL_optlong(L,n,d)\t((long)luaL_optinteger(L, (n), (d)))\n\n#define luaL_typename(L,i)\tlua_typename(L, lua_type(L,(i)))\n\n#define luaL_dofile(L, fn) \\\n\t(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))\n\n#define luaL_dostring(L, s) \\\n\t(luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0))\n\n#define luaL_getmetatable(L,n)\t(lua_getfield(L, LUA_REGISTRYINDEX, (n)))\n\n#define luaL_opt(L,f,n,d)\t(lua_isnoneornil(L,(n)) ? (d) : f(L,(n)))\n\n/*\n** {======================================================\n** Generic Buffer manipulation\n** =======================================================\n*/\n\n\n\ntypedef struct luaL_Buffer {\n  char *p;\t\t\t/* current position in buffer */\n  int lvl;  /* number of strings in the stack (level) */\n  lua_State *L;\n  char buffer[LUAL_BUFFERSIZE];\n} luaL_Buffer;\n\n#define luaL_addchar(B,c) \\\n  ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \\\n   (*(B)->p++ = (char)(c)))\n\n/* compatibility only */\n#define luaL_putchar(B,c)\tluaL_addchar(B,c)\n\n#define luaL_addsize(B,n)\t((B)->p += (n))\n\nLUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B);\nLUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B);\nLUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l);\nLUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s);\nLUALIB_API void (luaL_addvalue) (luaL_Buffer *B);\nLUALIB_API void (luaL_pushresult) (luaL_Buffer *B);\n\n\n/* }====================================================== */\n\n\n/* compatibility with ref system */\n\n/* pre-defined references */\n#define LUA_NOREF       (-2)\n#define LUA_REFNIL      (-1)\n\n#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \\\n      (lua_pushstring(L, \"unlocked references are obsolete\"), lua_error(L), 0))\n\n#define lua_unref(L,ref)        luaL_unref(L, LUA_REGISTRYINDEX, (ref))\n\n#define lua_getref(L,ref)       lua_rawgeti(L, LUA_REGISTRYINDEX, (ref))\n\n\n#define luaL_reg\tluaL_Reg\n\n#endif\n\n\n"
  },
  {
    "path": "include/luasandbox/lua.h",
    "content": "/*\n** $Id: lua.h,v 1.218.1.7 2012/01/13 20:36:20 roberto Exp $\n** Lua - An Extensible Extension Language\n** Lua.org, PUC-Rio, Brazil (http://www.lua.org)\n** See Copyright Notice at the end of this file\n*/\n\n\n#ifndef lua_h\n#define lua_h\n\n#include <stdarg.h>\n#include <stddef.h>\n\n\n#include \"luaconf.h\"\n\n\n#define LUA_VERSION\t\"Lua 5.1\"\n#define LUA_RELEASE\t\"Lua 5.1.5\"\n#define LUA_VERSION_NUM\t501\n#define LUA_COPYRIGHT\t\"Copyright (C) 1994-2012 Lua.org, PUC-Rio\"\n#define LUA_AUTHORS \t\"R. Ierusalimschy, L. H. de Figueiredo & W. Celes\"\n\n\n/* mark for precompiled code (`<esc>Lua') */\n#define\tLUA_SIGNATURE\t\"\\033Lua\"\n\n/* option for multiple returns in `lua_pcall' and `lua_call' */\n#define LUA_MULTRET\t(-1)\n\n\n/*\n** pseudo-indices\n*/\n#define LUA_REGISTRYINDEX\t(-10000)\n#define LUA_ENVIRONINDEX\t(-10001)\n#define LUA_GLOBALSINDEX\t(-10002)\n#define lua_upvalueindex(i)\t(LUA_GLOBALSINDEX-(i))\n\n\n/* thread status; 0 is OK */\n#define LUA_YIELD\t1\n#define LUA_ERRRUN\t2\n#define LUA_ERRSYNTAX\t3\n#define LUA_ERRMEM\t4\n#define LUA_ERRERR\t5\n\n\ntypedef struct lua_State lua_State;\n\ntypedef int (*lua_CFunction) (lua_State *L);\n\n\n/*\n** functions that read/write blocks when loading/dumping Lua chunks\n*/\ntypedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz);\n\ntypedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud);\n\n\n/*\n** prototype for memory-allocation functions\n*/\ntypedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize);\n\n\n/*\n** basic types\n*/\n#define LUA_TNONE\t\t(-1)\n\n#define LUA_TNIL\t\t0\n#define LUA_TBOOLEAN\t\t1\n#define LUA_TLIGHTUSERDATA\t2\n#define LUA_TNUMBER\t\t3\n#define LUA_TSTRING\t\t4\n#define LUA_TTABLE\t\t5\n#define LUA_TFUNCTION\t\t6\n#define LUA_TUSERDATA\t\t7\n#define LUA_TTHREAD\t\t8\n\n/*\n** table types\n*/\n#define LUA_TTEMPTY             0\n#define LUA_TTARRAY             1\n#define LUA_TTHASH              2\n#define LUA_TTMIXED             3\n\n\n/* minimum Lua stack available to a C function */\n#define LUA_MINSTACK\t20\n\n\n/*\n** generic extra include file\n*/\n#if defined(LUA_USER_H)\n#include LUA_USER_H\n#endif\n\n\n/* type of numbers in Lua */\ntypedef LUA_NUMBER lua_Number;\n\n\n/* type for integer functions */\ntypedef LUA_INTEGER lua_Integer;\n\n\n\n/*\n** state manipulation\n*/\nLUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud);\nLUA_API void       (lua_close) (lua_State *L);\nLUA_API lua_State *(lua_newthread) (lua_State *L);\n\nLUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf);\n\n\n/*\n** basic stack manipulation\n*/\nLUA_API int   (lua_gettop) (lua_State *L);\nLUA_API void  (lua_settop) (lua_State *L, int idx);\nLUA_API void  (lua_pushvalue) (lua_State *L, int idx);\nLUA_API void  (lua_remove) (lua_State *L, int idx);\nLUA_API void  (lua_insert) (lua_State *L, int idx);\nLUA_API void  (lua_replace) (lua_State *L, int idx);\nLUA_API int   (lua_checkstack) (lua_State *L, int sz);\n\nLUA_API void  (lua_xmove) (lua_State *from, lua_State *to, int n);\n\n\n/*\n** access functions (stack -> C)\n*/\n\nLUA_API int             (lua_tabletype) (lua_State *L, int idx);\nLUA_API int             (lua_isnumber) (lua_State *L, int idx);\nLUA_API int             (lua_isstring) (lua_State *L, int idx);\nLUA_API int             (lua_iscfunction) (lua_State *L, int idx);\nLUA_API int             (lua_isuserdata) (lua_State *L, int idx);\nLUA_API int             (lua_type) (lua_State *L, int idx);\nLUA_API const char     *(lua_typename) (lua_State *L, int tp);\n\nLUA_API int            (lua_equal) (lua_State *L, int idx1, int idx2);\nLUA_API int            (lua_rawequal) (lua_State *L, int idx1, int idx2);\nLUA_API int            (lua_lessthan) (lua_State *L, int idx1, int idx2);\n\nLUA_API lua_Number      (lua_tonumber) (lua_State *L, int idx);\nLUA_API lua_Integer     (lua_tointeger) (lua_State *L, int idx);\nLUA_API int             (lua_toboolean) (lua_State *L, int idx);\nLUA_API const char     *(lua_tolstring) (lua_State *L, int idx, size_t *len);\nLUA_API size_t          (lua_objlen) (lua_State *L, int idx);\nLUA_API lua_CFunction   (lua_tocfunction) (lua_State *L, int idx);\nLUA_API void\t       *(lua_touserdata) (lua_State *L, int idx);\nLUA_API lua_State      *(lua_tothread) (lua_State *L, int idx);\nLUA_API const void     *(lua_topointer) (lua_State *L, int idx);\n\n\n/*\n** push functions (C -> stack)\n*/\nLUA_API void  (lua_pushnil) (lua_State *L);\nLUA_API void  (lua_pushnumber) (lua_State *L, lua_Number n);\nLUA_API void  (lua_pushinteger) (lua_State *L, lua_Integer n);\nLUA_API void  (lua_pushlstring) (lua_State *L, const char *s, size_t l);\nLUA_API void  (lua_pushstring) (lua_State *L, const char *s);\nLUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt,\n                                                      va_list argp);\nLUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...);\nLUA_API void  (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n);\nLUA_API void  (lua_pushboolean) (lua_State *L, int b);\nLUA_API void  (lua_pushlightuserdata) (lua_State *L, void *p);\nLUA_API int   (lua_pushthread) (lua_State *L);\n\n\n/*\n** get functions (Lua -> stack)\n*/\nLUA_API void  (lua_gettable) (lua_State *L, int idx);\nLUA_API void  (lua_getfield) (lua_State *L, int idx, const char *k);\nLUA_API void  (lua_rawget) (lua_State *L, int idx);\nLUA_API void  (lua_rawgeti) (lua_State *L, int idx, int n);\nLUA_API void  (lua_createtable) (lua_State *L, int narr, int nrec);\nLUA_API void *(lua_newuserdata) (lua_State *L, size_t sz);\nLUA_API int   (lua_getmetatable) (lua_State *L, int objindex);\nLUA_API void  (lua_getfenv) (lua_State *L, int idx);\n\n\n/*\n** set functions (stack -> Lua)\n*/\nLUA_API void  (lua_settable) (lua_State *L, int idx);\nLUA_API void  (lua_setfield) (lua_State *L, int idx, const char *k);\nLUA_API void  (lua_rawset) (lua_State *L, int idx);\nLUA_API void  (lua_rawseti) (lua_State *L, int idx, int n);\nLUA_API int   (lua_setmetatable) (lua_State *L, int objindex);\nLUA_API int   (lua_setfenv) (lua_State *L, int idx);\n\n\n/*\n** `load' and `call' functions (load and run Lua code)\n*/\nLUA_API void  (lua_call) (lua_State *L, int nargs, int nresults);\nLUA_API int   (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc);\nLUA_API int   (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud);\nLUA_API int   (lua_load) (lua_State *L, lua_Reader reader, void *dt,\n                                        const char *chunkname);\n\nLUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data);\n\n\n/*\n** coroutine functions\n*/\nLUA_API int  (lua_yield) (lua_State *L, int nresults);\nLUA_API int  (lua_resume) (lua_State *L, int narg);\nLUA_API int  (lua_status) (lua_State *L);\n\n/*\n** garbage-collection function and options\n*/\n\n#define LUA_GCSTOP\t\t0\n#define LUA_GCRESTART\t\t1\n#define LUA_GCCOLLECT\t\t2\n#define LUA_GCCOUNT\t\t3\n#define LUA_GCCOUNTB\t\t4\n#define LUA_GCSTEP\t\t5\n#define LUA_GCSETPAUSE\t\t6\n#define LUA_GCSETSTEPMUL\t7\n\nLUA_API int (lua_gc) (lua_State *L, int what, int data);\n\n\n/*\n** miscellaneous functions\n*/\n\nLUA_API int   (lua_error) (lua_State *L);\n\nLUA_API int   (lua_next) (lua_State *L, int idx);\n\nLUA_API void  (lua_concat) (lua_State *L, int n);\n\nLUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud);\nLUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud);\n\n\n\n/* \n** ===============================================================\n** some useful macros\n** ===============================================================\n*/\n\n#define lua_pop(L,n)\t\tlua_settop(L, -(n)-1)\n\n#define lua_newtable(L)\t\tlua_createtable(L, 0, 0)\n\n#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n)))\n\n#define lua_pushcfunction(L,f)\tlua_pushcclosure(L, (f), 0)\n\n#define lua_strlen(L,i)\t\tlua_objlen(L, (i))\n\n#define lua_isfunction(L,n)\t(lua_type(L, (n)) == LUA_TFUNCTION)\n#define lua_istable(L,n)\t(lua_type(L, (n)) == LUA_TTABLE)\n#define lua_islightuserdata(L,n)\t(lua_type(L, (n)) == LUA_TLIGHTUSERDATA)\n#define lua_isnil(L,n)\t\t(lua_type(L, (n)) == LUA_TNIL)\n#define lua_isboolean(L,n)\t(lua_type(L, (n)) == LUA_TBOOLEAN)\n#define lua_isthread(L,n)\t(lua_type(L, (n)) == LUA_TTHREAD)\n#define lua_isnone(L,n)\t\t(lua_type(L, (n)) == LUA_TNONE)\n#define lua_isnoneornil(L, n)\t(lua_type(L, (n)) <= 0)\n\n#define lua_pushliteral(L, s)\t\\\n\tlua_pushlstring(L, \"\" s, (sizeof(s)/sizeof(char))-1)\n\n#define lua_setglobal(L,s)\tlua_setfield(L, LUA_GLOBALSINDEX, (s))\n#define lua_getglobal(L,s)\tlua_getfield(L, LUA_GLOBALSINDEX, (s))\n\n#define lua_tostring(L,i)\tlua_tolstring(L, (i), NULL)\n\n\n\n/*\n** compatibility macros and functions\n*/\n\n#define lua_open()\tluaL_newstate()\n\n#define lua_getregistry(L)\tlua_pushvalue(L, LUA_REGISTRYINDEX)\n\n#define lua_getgccount(L)\tlua_gc(L, LUA_GCCOUNT, 0)\n\n#define lua_Chunkreader\t\tlua_Reader\n#define lua_Chunkwriter\t\tlua_Writer\n\n\n/* hack */\nLUA_API void lua_setlevel\t(lua_State *from, lua_State *to);\n\n\n/*\n** {======================================================================\n** Debug API\n** =======================================================================\n*/\n\n\n/*\n** Event codes\n*/\n#define LUA_HOOKCALL\t0\n#define LUA_HOOKRET\t1\n#define LUA_HOOKLINE\t2\n#define LUA_HOOKCOUNT\t3\n#define LUA_HOOKTAILRET 4\n\n\n/*\n** Event masks\n*/\n#define LUA_MASKCALL\t(1 << LUA_HOOKCALL)\n#define LUA_MASKRET\t(1 << LUA_HOOKRET)\n#define LUA_MASKLINE\t(1 << LUA_HOOKLINE)\n#define LUA_MASKCOUNT\t(1 << LUA_HOOKCOUNT)\n\ntypedef struct lua_Debug lua_Debug;  /* activation record */\n\n\n/* Functions to be called by the debuger in specific events */\ntypedef void (*lua_Hook) (lua_State *L, lua_Debug *ar);\n\n\nLUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar);\nLUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);\nLUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n);\nLUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n);\nLUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n);\nLUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n);\n\nLUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count);\nLUA_API lua_Hook lua_gethook (lua_State *L);\nLUA_API int lua_gethookmask (lua_State *L);\nLUA_API int lua_gethookcount (lua_State *L);\nLUA_API int lua_gethookcountremaining (lua_State *L);\n\n\nstruct lua_Debug {\n  int event;\n  const char *name;\t/* (n) */\n  const char *namewhat;\t/* (n) `global', `local', `field', `method' */\n  const char *what;\t/* (S) `Lua', `C', `main', `tail' */\n  const char *source;\t/* (S) */\n  int currentline;\t/* (l) */\n  int nups;\t\t/* (u) number of upvalues */\n  int linedefined;\t/* (S) */\n  int lastlinedefined;\t/* (S) */\n  char short_src[LUA_IDSIZE]; /* (S) */\n  /* private part */\n  int i_ci;  /* active function */\n};\n\n/* }====================================================================== */\n\n\n/******************************************************************************\n* Copyright (C) 1994-2012 Lua.org, PUC-Rio.  All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining\n* a copy of this software and associated documentation files (the\n* \"Software\"), to deal in the Software without restriction, including\n* without limitation the rights to use, copy, modify, merge, publish,\n* distribute, sublicense, and/or sell copies of the Software, and to\n* permit persons to whom the Software is furnished to do so, subject to\n* the following conditions:\n*\n* The above copyright notice and this permission notice shall be\n* included in all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n******************************************************************************/\n\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/luaconf.h",
    "content": "/*\n** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $\n** Configuration file for Lua\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lconfig_h\n#define lconfig_h\n\n#include <limits.h>\n#include <stddef.h>\n\n\n/*\n** ==================================================================\n** Search for \"@@\" to find all configurable definitions.\n** ===================================================================\n*/\n\n\n/*\n@@ LUA_ANSI controls the use of non-ansi features.\n** CHANGE it (define it) if you want Lua to avoid the use of any\n** non-ansi feature or library.\n*/\n#if defined(__STRICT_ANSI__)\n#define LUA_ANSI\n#endif\n\n\n#if !defined(LUA_ANSI) && defined(_WIN32)\n#define LUA_WIN\n#endif\n\n#if defined(LUA_USE_LINUX)\n#define LUA_USE_POSIX\n#define LUA_USE_DLOPEN    /* needs an extra library: -ldl */\n#define LUA_USE_READLINE  /* needs some extra libraries */\n#endif\n\n#if defined(LUA_USE_MACOSX)\n#define LUA_USE_POSIX\n#define LUA_DL_DYLD   /* does not need extra library */\n#endif\n\n\n\n/*\n@@ LUA_USE_POSIX includes all functionallity listed as X/Open System\n@* Interfaces Extension (XSI).\n** CHANGE it (define it) if your system is XSI compatible.\n*/\n#if defined(LUA_USE_POSIX)\n#define LUA_USE_MKSTEMP\n#define LUA_USE_ISATTY\n#define LUA_USE_POPEN\n#define LUA_USE_ULONGJMP\n#endif\n\n\n/*\n@@ LUA_PATH and LUA_CPATH are the names of the environment variables that\n@* Lua check to set its paths.\n@@ LUA_INIT is the name of the environment variable that Lua\n@* checks for initialization code.\n** CHANGE them if you want different names.\n*/\n#define LUA_PATH        \"LUA_PATH\"\n#define LUA_CPATH       \"LUA_CPATH\"\n#define LUA_INIT  \"LUA_INIT\"\n\n\n/*\n@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for\n@* Lua libraries.\n@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for\n@* C libraries.\n** CHANGE them if your machine has a non-conventional directory\n** hierarchy or if you want to install your libraries in\n** non-conventional directories.\n*/\n#if defined(_WIN32)\n/*\n** In Windows, any exclamation mark ('!') in the path is replaced by the\n** path of the directory of the executable file of the current process.\n*/\n#define LUA_LDIR  \"!\\\\lua\\\\\"\n#define LUA_CDIR  \"!\\\\\"\n#define LUA_PATH_DEFAULT  \\\n    \".\\\\?.lua;\"  LUA_LDIR\"?.lua;\"  LUA_LDIR\"?\\\\init.lua;\" \\\n                 LUA_CDIR\"?.lua;\"  LUA_CDIR\"?\\\\init.lua\"\n#define LUA_CPATH_DEFAULT \\\n  \".\\\\?.dll;\"  LUA_CDIR\"?.dll;\" LUA_CDIR\"loadall.dll\"\n\n#else\n#define LUA_ROOT  \"/usr/local/\"\n#define LUA_LDIR  LUA_ROOT \"share/lua/5.1/\"\n#define LUA_CDIR  LUA_ROOT \"lib/lua/5.1/\"\n#define LUA_PATH_DEFAULT  \\\n    \"./?.lua;\"  LUA_LDIR\"?.lua;\"  LUA_LDIR\"?/init.lua;\" \\\n                LUA_CDIR\"?.lua;\"  LUA_CDIR\"?/init.lua\"\n#define LUA_CPATH_DEFAULT \\\n  \"./?.so;\"  LUA_CDIR\"?.so;\" LUA_CDIR\"loadall.so\"\n#endif\n\n\n/*\n@@ LUA_DIRSEP is the directory separator (for submodules).\n** CHANGE it if your machine does not use \"/\" as the directory separator\n** and is not Windows. (On Windows Lua automatically uses \"\\\".)\n*/\n#if defined(_WIN32)\n#define LUA_DIRSEP  \"\\\\\"\n#else\n#define LUA_DIRSEP  \"/\"\n#endif\n\n\n/*\n@@ LUA_PATHSEP is the character that separates templates in a path.\n@@ LUA_PATH_MARK is the string that marks the substitution points in a\n@* template.\n@@ LUA_EXECDIR in a Windows path is replaced by the executable's\n@* directory.\n@@ LUA_IGMARK is a mark to ignore all before it when bulding the\n@* luaopen_ function name.\n** CHANGE them if for some reason your system cannot use those\n** characters. (E.g., if one of those characters is a common character\n** in file/directory names.) Probably you do not need to change them.\n*/\n#define LUA_PATHSEP \";\"\n#define LUA_PATH_MARK \"?\"\n#define LUA_EXECDIR \"!\"\n#define LUA_IGMARK  \"-\"\n\n\n/*\n@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger.\n** CHANGE that if ptrdiff_t is not adequate on your machine. (On most\n** machines, ptrdiff_t gives a good choice between int or long.)\n*/\n#define LUA_INTEGER ptrdiff_t\n\n\n/*\n@@ LUA_API is a mark for all core API functions.\n@@ LUALIB_API is a mark for all standard library functions.\n** CHANGE them if you need to define those functions in some special way.\n** For instance, if you want to create one Windows DLL with the core and\n** the libraries, you may want to use the following definition (define\n** LUA_BUILD_AS_DLL to get it).\n*/\n#if defined(LUA_BUILD_AS_DLL)\n\n#if defined(LUA_CORE) || defined(LUA_LIB)\n#define LUA_API __declspec(dllexport)\n#else\n#define LUA_API __declspec(dllimport)\n#endif\n\n#else\n#if __GNUC__ >= 4\n#define LUA_API __attribute__ ((visibility (\"default\")))\n#else\n#define LUA_API\n#endif\n#endif\n\n/* more often than not the libs go together with the core */\n#define LUALIB_API  LUA_API\n\n\n/*\n@@ LUAI_FUNC is a mark for all extern functions that are not to be\n@* exported to outside modules.\n@@ LUAI_DATA is a mark for all extern (const) variables that are not to\n@* be exported to outside modules.\n** CHANGE them if you need to mark them in some special way. Elf/gcc\n** (versions 3.2 and later) mark them as \"hidden\" to optimize access\n** when Lua is compiled as a shared library.\n*/\n#if defined(luaall_c)\n#define LUAI_FUNC static\n#define LUAI_DATA /* empty */\n\n#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \\\n      defined(__ELF__)\n#define LUAI_FUNC __attribute__((visibility(\"hidden\"))) extern\n#define LUAI_DATA LUAI_FUNC\n\n#else\n#define LUAI_FUNC extern\n#define LUAI_DATA extern\n#endif\n\n\n\n/*\n@@ LUA_QL describes how error messages quote program elements.\n** CHANGE it if you want a different appearance.\n*/\n#define LUA_QL(x) \"'\" x \"'\"\n#define LUA_QS    LUA_QL(\"%s\")\n\n\n/*\n@@ LUA_IDSIZE gives the maximum size for the description of the source\n@* of a function in debug information.\n** CHANGE it if you want a different size.\n*/\n#define LUA_IDSIZE  60\n\n\n/*\n** {==================================================================\n** Stand-alone configuration\n** ===================================================================\n*/\n\n#if defined(lua_c) || defined(luaall_c)\n\n/*\n@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that\n@* is, whether we're running lua interactively).\n** CHANGE it if you have a better definition for non-POSIX/non-Windows\n** systems.\n*/\n#if defined(LUA_USE_ISATTY)\n#include <unistd.h>\n#define lua_stdin_is_tty()  isatty(0)\n#elif defined(LUA_WIN)\n#include <io.h>\n#include <stdio.h>\n#define lua_stdin_is_tty()  _isatty(_fileno(stdin))\n#else\n#define lua_stdin_is_tty()  1  /* assume stdin is a tty */\n#endif\n\n\n/*\n@@ LUA_PROMPT is the default prompt used by stand-alone Lua.\n@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua.\n** CHANGE them if you want different prompts. (You can also change the\n** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.)\n*/\n#define LUA_PROMPT    \"> \"\n#define LUA_PROMPT2   \">> \"\n\n\n/*\n@@ LUA_PROGNAME is the default name for the stand-alone Lua program.\n** CHANGE it if your stand-alone interpreter has a different name and\n** your system is not able to detect that name automatically.\n*/\n#define LUA_PROGNAME    \"lua\"\n\n\n/*\n@@ LUA_MAXINPUT is the maximum length for an input line in the\n@* stand-alone interpreter.\n** CHANGE it if you need longer lines.\n*/\n#define LUA_MAXINPUT  512\n\n\n/*\n@@ lua_readline defines how to show a prompt and then read a line from\n@* the standard input.\n@@ lua_saveline defines how to \"save\" a read line in a \"history\".\n@@ lua_freeline defines how to free a line read by lua_readline.\n** CHANGE them if you want to improve this functionality (e.g., by using\n** GNU readline and history facilities).\n*/\n#if defined(LUA_USE_READLINE)\n#include <stdio.h>\n#include <readline/readline.h>\n#include <readline/history.h>\n#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL)\n#define lua_saveline(L,idx) \\\n  if (lua_strlen(L,idx) > 0)  /* non-empty line? */ \\\n    add_history(lua_tostring(L, idx));  /* add it to history */\n#define lua_freeline(L,b) ((void)L, free(b))\n#else\n#define lua_readline(L,b,p) \\\n  ((void)L, fputs(p, stdout), fflush(stdout),  /* show prompt */ \\\n  fgets(b, LUA_MAXINPUT, stdin) != NULL)  /* get line */\n#define lua_saveline(L,idx) { (void)L; (void)idx; }\n#define lua_freeline(L,b) { (void)L; (void)b; }\n#endif\n\n#endif\n\n/* }================================================================== */\n\n\n/*\n@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles\n@* as a percentage.\n** CHANGE it if you want the GC to run faster or slower (higher values\n** mean larger pauses which mean slower collection.) You can also change\n** this value dynamically.\n*/\n#define LUAI_GCPAUSE  200  /* 200% (wait memory to double before next GC) */\n\n\n/*\n@@ LUAI_GCMUL defines the default speed of garbage collection relative to\n@* memory allocation as a percentage.\n** CHANGE it if you want to change the granularity of the garbage\n** collection. (Higher values mean coarser collections. 0 represents\n** infinity, where each step performs a full collection.) You can also\n** change this value dynamically.\n*/\n#define LUAI_GCMUL  200 /* GC runs 'twice the speed' of memory allocation */\n\n\n\n/*\n@@ LUA_COMPAT_GETN controls compatibility with old getn behavior.\n** CHANGE it (define it) if you want exact compatibility with the\n** behavior of setn/getn in Lua 5.0.\n*/\n#undef LUA_COMPAT_GETN\n\n/*\n@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib.\n** CHANGE it to undefined as soon as you do not need a global 'loadlib'\n** function (the function is still available as 'package.loadlib').\n*/\n#undef LUA_COMPAT_LOADLIB\n\n/*\n@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature.\n** CHANGE it to undefined as soon as your programs use only '...' to\n** access vararg parameters (instead of the old 'arg' table).\n*/\n#define LUA_COMPAT_VARARG\n\n/*\n@@ LUA_COMPAT_MOD controls compatibility with old math.mod function.\n** CHANGE it to undefined as soon as your programs use 'math.fmod' or\n** the new '%' operator instead of 'math.mod'.\n*/\n#define LUA_COMPAT_MOD\n\n/*\n@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting\n@* facility.\n** CHANGE it to 2 if you want the old behaviour, or undefine it to turn\n** off the advisory error when nesting [[...]].\n*/\n#define LUA_COMPAT_LSTR   1\n\n/*\n@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name.\n** CHANGE it to undefined as soon as you rename 'string.gfind' to\n** 'string.gmatch'.\n*/\n#define LUA_COMPAT_GFIND\n\n/*\n@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib'\n@* behavior.\n** CHANGE it to undefined as soon as you replace to 'luaL_register'\n** your uses of 'luaL_openlib'\n*/\n#define LUA_COMPAT_OPENLIB\n\n\n\n/*\n@@ luai_apicheck is the assert macro used by the Lua-C API.\n** CHANGE luai_apicheck if you want Lua to perform some checks in the\n** parameters it gets from API calls. This may slow down the interpreter\n** a bit, but may be quite useful when debugging C code that interfaces\n** with Lua. A useful redefinition is to use assert.h.\n*/\n#if defined(LUA_USE_APICHECK)\n#include <assert.h>\n#define luai_apicheck(L,o)  { (void)L; assert(o); }\n#else\n#define luai_apicheck(L,o)  { (void)L; }\n#endif\n\n\n/*\n@@ LUAI_BITSINT defines the number of bits in an int.\n** CHANGE here if Lua cannot automatically detect the number of bits of\n** your machine. Probably you do not need to change this.\n*/\n/* avoid overflows in comparison */\n#if INT_MAX-20 < 32760\n#define LUAI_BITSINT  16\n#elif INT_MAX > 2147483640L\n/* int has at least 32 bits */\n#define LUAI_BITSINT  32\n#else\n#error \"you must define LUA_BITSINT with number of bits in an integer\"\n#endif\n\n\n/*\n@@ LUAI_UINT32 is an unsigned integer with at least 32 bits.\n@@ LUAI_INT32 is an signed integer with at least 32 bits.\n@@ LUAI_UMEM is an unsigned integer big enough to count the total\n@* memory used by Lua.\n@@ LUAI_MEM is a signed integer big enough to count the total memory\n@* used by Lua.\n** CHANGE here if for some weird reason the default definitions are not\n** good enough for your machine. (The definitions in the 'else'\n** part always works, but may waste space on machines with 64-bit\n** longs.) Probably you do not need to change this.\n*/\n#if LUAI_BITSINT >= 32\n#define LUAI_UINT32 unsigned int\n#define LUAI_INT32  int\n#define LUAI_MAXINT32 INT_MAX\n#define LUAI_UMEM size_t\n#define LUAI_MEM  ptrdiff_t\n#else\n/* 16-bit ints */\n#define LUAI_UINT32 unsigned long\n#define LUAI_INT32  long\n#define LUAI_MAXINT32 LONG_MAX\n#define LUAI_UMEM unsigned long\n#define LUAI_MEM  long\n#endif\n\n\n/*\n@@ LUAI_MAXCALLS limits the number of nested calls.\n** CHANGE it if you need really deep recursive calls. This limit is\n** arbitrary; its only purpose is to stop infinite recursion before\n** exhausting memory.\n*/\n#define LUAI_MAXCALLS 20000\n\n\n/*\n@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function\n@* can use.\n** CHANGE it if you need lots of (Lua) stack space for your C\n** functions. This limit is arbitrary; its only purpose is to stop C\n** functions to consume unlimited stack space. (must be smaller than\n** -LUA_REGISTRYINDEX)\n*/\n#define LUAI_MAXCSTACK  8000\n\n\n\n/*\n** {==================================================================\n** CHANGE (to smaller values) the following definitions if your system\n** has a small C stack. (Or you may want to change them to larger\n** values if your system has a large C stack and these limits are\n** too rigid for you.) Some of these constants control the size of\n** stack-allocated arrays used by the compiler or the interpreter, while\n** others limit the maximum number of recursive calls that the compiler\n** or the interpreter can perform. Values too large may cause a C stack\n** overflow for some forms of deep constructs.\n** ===================================================================\n*/\n\n\n/*\n@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and\n@* syntactical nested non-terminals in a program.\n*/\n#define LUAI_MAXCCALLS    200\n\n\n/*\n@@ LUAI_MAXVARS is the maximum number of local variables per function\n@* (must be smaller than 250).\n*/\n#define LUAI_MAXVARS    200\n\n\n/*\n@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function\n@* (must be smaller than 250).\n*/\n#define LUAI_MAXUPVALUES  60\n\n\n/*\n@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system.\n*/\n#define LUAL_BUFFERSIZE   BUFSIZ\n\n/* }================================================================== */\n\n\n\n\n/*\n** {==================================================================\n@@ LUA_NUMBER is the type of numbers in Lua.\n** CHANGE the following definitions only if you want to build Lua\n** with a number type different from double. You may also need to\n** change lua_number2int & lua_number2integer.\n** ===================================================================\n*/\n\n#define LUA_NUMBER_DOUBLE\n#define LUA_NUMBER  double\n\n/*\n@@ LUAI_UACNUMBER is the result of an 'usual argument conversion'\n@* over a number.\n*/\n#define LUAI_UACNUMBER  double\n\n\n/*\n@@ LUA_NUMBER_SCAN is the format for reading numbers.\n@@ LUA_NUMBER_FMT is the format for writing numbers.\n@@ lua_number2str converts a number to a string.\n@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion.\n@@ lua_str2number converts a string to a number.\n*/\n#define LUA_NUMBER_SCAN   \"%lf\"\n#define LUA_NUMBER_FMT    \"%.14g\"\n#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n))\n#define LUAI_MAXNUMBER2STR  32 /* 16 digits, sign, point, and \\0 */\n#define lua_str2number(s,p) strtod((s), (p))\n\n\n/*\n@@ The luai_num* macros define the primitive operations over numbers.\n*/\n#if defined(LUA_CORE)\n#include <math.h>\n#define luai_numadd(a,b)  ((a)+(b))\n#define luai_numsub(a,b)  ((a)-(b))\n#define luai_nummul(a,b)  ((a)*(b))\n#define luai_numdiv(a,b)  ((a)/(b))\n#define luai_nummod(a,b)  ((a) - floor((a)/(b))*(b))\n#define luai_numpow(a,b)  (pow(a,b))\n#define luai_numunm(a)    (-(a))\n#define luai_numeq(a,b)   ((a)==(b))\n#define luai_numlt(a,b)   ((a)<(b))\n#define luai_numle(a,b)   ((a)<=(b))\n#define luai_numisnan(a)  (!luai_numeq((a), (a)))\n#endif\n\n\n/*\n@@ lua_number2int is a macro to convert lua_Number to int.\n@@ lua_number2integer is a macro to convert lua_Number to lua_Integer.\n** CHANGE them if you know a faster way to convert a lua_Number to\n** int (with any rounding method and without throwing errors) in your\n** system. In Pentium machines, a naive typecast from double to int\n** in C is extremely slow, so any alternative is worth trying.\n*/\n\n/* On a Pentium, resort to a trick */\n#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \\\n    (defined(__i386) || defined (_M_IX86) || defined(__i386__))\n\n/* On a Microsoft compiler, use assembler */\n#if defined(_MSC_VER)\n\n#define lua_number2int(i,d)   __asm fld d   __asm fistp i\n#define lua_number2integer(i,n)   lua_number2int(i, n)\n\n/* the next trick should work on any Pentium, but sometimes clashes\n   with a DirectX idiosyncrasy */\n#else\n\nunion luai_Cast { double l_d; long l_l; };\n#define lua_number2int(i,d) \\\n  { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; }\n#define lua_number2integer(i,n)   lua_number2int(i, n)\n\n#endif\n\n\n/* this option always works, but may be slow */\n#else\n#define lua_number2int(i,d) ((i)=(int)(d))\n#define lua_number2integer(i,d) ((i)=(lua_Integer)(d))\n\n#endif\n\n/* }================================================================== */\n\n\n/*\n@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment.\n** CHANGE it if your system requires alignments larger than double. (For\n** instance, if your system supports long doubles and they must be\n** aligned in 16-byte boundaries, then you should add long double in the\n** union.) Probably you do not need to change this.\n*/\n#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; }\n\n\n/*\n@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling.\n** CHANGE them if you prefer to use longjmp/setjmp even with C++\n** or if want/don't to use _longjmp/_setjmp instead of regular\n** longjmp/setjmp. By default, Lua handles errors with exceptions when\n** compiling as C++ code, with _longjmp/_setjmp when asked to use them,\n** and with longjmp/setjmp otherwise.\n*/\n#if defined(__cplusplus)\n/* C++ exceptions */\n#define LUAI_THROW(L,c) throw(c)\n#define LUAI_TRY(L,c,a) try { a } catch(...) \\\n  { if ((c)->status == 0) (c)->status = -1; }\n#define luai_jmpbuf int  /* dummy variable */\n\n#elif defined(LUA_USE_ULONGJMP)\n/* in Unix, try _longjmp/_setjmp (more efficient) */\n#define LUAI_THROW(L,c) _longjmp((c)->b, 1)\n#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a }\n#define luai_jmpbuf jmp_buf\n\n#else\n/* default handling with long jumps */\n#define LUAI_THROW(L,c) longjmp((c)->b, 1)\n#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a }\n#define luai_jmpbuf jmp_buf\n\n#endif\n\n\n/*\n@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern\n@* can do during pattern-matching.\n** CHANGE it if you need more captures. This limit is arbitrary.\n*/\n#define LUA_MAXCAPTURES   32\n\n\n/*\n@@ lua_tmpnam is the function that the OS library uses to create a\n@* temporary name.\n@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam.\n** CHANGE them if you have an alternative to tmpnam (which is considered\n** insecure) or if you want the original tmpnam anyway.  By default, Lua\n** uses tmpnam except when POSIX is available, where it uses mkstemp.\n*/\n#if defined(loslib_c) || defined(luaall_c)\n\n#if defined(LUA_USE_MKSTEMP)\n#include <unistd.h>\n#define LUA_TMPNAMBUFSIZE 32\n#define lua_tmpnam(b,e) { \\\n  strcpy(b, \"/tmp/lua_XXXXXX\"); \\\n  e = mkstemp(b); \\\n  if (e != -1) close(e); \\\n  e = (e == -1); }\n\n#else\n#define LUA_TMPNAMBUFSIZE L_tmpnam\n#define lua_tmpnam(b,e)   { e = (tmpnam(b) == NULL); }\n#endif\n\n#endif\n\n\n/*\n@@ lua_popen spawns a new process connected to the current one through\n@* the file streams.\n** CHANGE it if you have a way to implement it in your system.\n*/\n#if defined(LUA_USE_POPEN)\n\n#define lua_popen(L,c,m)  ((void)L, fflush(NULL), popen(c,m))\n#define lua_pclose(L,file)  ((void)L, (pclose(file) != -1))\n\n#elif defined(LUA_WIN)\n\n#define lua_popen(L,c,m)  ((void)L, _popen(c,m))\n#define lua_pclose(L,file)  ((void)L, (_pclose(file) != -1))\n\n#else\n\n#define lua_popen(L,c,m)  ((void)((void)c, m),  \\\n    luaL_error(L, LUA_QL(\"popen\") \" not supported\"), (FILE*)0)\n#define lua_pclose(L,file)    ((void)((void)L, file), 0)\n\n#endif\n\n/*\n@@ LUA_DL_* define which dynamic-library system Lua should use.\n** CHANGE here if Lua has problems choosing the appropriate\n** dynamic-library system for your platform (either Windows' DLL, Mac's\n** dyld, or Unix's dlopen). If your system is some kind of Unix, there\n** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for\n** it.  To use dlopen you also need to adapt the src/Makefile (probably\n** adding -ldl to the linker options), so Lua does not select it\n** automatically.  (When you change the makefile to add -ldl, you must\n** also add -DLUA_USE_DLOPEN.)\n** If you do not want any kind of dynamic library, undefine all these\n** options.\n** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD.\n*/\n#if defined(LUA_USE_DLOPEN)\n#define LUA_DL_DLOPEN\n#endif\n\n#if defined(LUA_WIN)\n#define LUA_DL_DLL\n#endif\n\n\n/*\n@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State\n@* (the data goes just *before* the lua_State pointer).\n** CHANGE (define) this if you really need that. This value must be\n** a multiple of the maximum alignment required for your machine.\n*/\n#define LUAI_EXTRASPACE   0\n\n\n/*\n@@ luai_userstate* allow user-specific actions on threads.\n** CHANGE them if you defined LUAI_EXTRASPACE and need to do something\n** extra when a thread is created/deleted/resumed/yielded.\n*/\n#define luai_userstateopen(L)   ((void)L)\n#define luai_userstateclose(L)    ((void)L)\n#define luai_userstatethread(L,L1)  ((void)L)\n#define luai_userstatefree(L)   ((void)L)\n#define luai_userstateresume(L,n) ((void)L)\n#define luai_userstateyield(L,n)  ((void)L)\n\n\n/*\n@@ LUA_INTFRMLEN is the length modifier for integer conversions\n@* in 'string.format'.\n@@ LUA_INTFRM_T is the integer type correspoding to the previous length\n@* modifier.\n** CHANGE them if your system supports long long or does not support long.\n*/\n\n#if defined(LUA_USELONGLONG)\n\n#define LUA_INTFRMLEN   \"ll\"\n#define LUA_INTFRM_T    long long\n\n#else\n\n#define LUA_INTFRMLEN   \"l\"\n#define LUA_INTFRM_T    long\n\n#endif\n\n\n\n/* =================================================================== */\n\n/*\n** Local configuration. You can use this space to add your redefinitions\n** without modifying the main part of the file.\n*/\n\n\n\n#endif\n\n"
  },
  {
    "path": "include/luasandbox/lualib.h",
    "content": "/*\n** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua standard libraries\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lualib_h\n#define lualib_h\n\n#include \"lua.h\"\n\n\n/* Key to file-handle type */\n#define LUA_FILEHANDLE    \"FILE*\"\n\n#define LUA_BASELIBNAME \"\"\nLUALIB_API int (luaopen_base) (lua_State *L);\n\n#define LUA_COLIBNAME \"coroutine\"\nLUALIB_API int (luaopen_coroutine) (lua_State *L);\n\n#define LUA_TABLIBNAME  \"table\"\nLUALIB_API int (luaopen_table) (lua_State *L);\n\n#define LUA_IOLIBNAME \"io\"\nLUALIB_API int (luaopen_io) (lua_State *L);\n\n#define LUA_OSLIBNAME \"os\"\nLUALIB_API int (luaopen_os) (lua_State *L);\n\n#define LUA_STRLIBNAME  \"string\"\nLUALIB_API int (luaopen_string) (lua_State *L);\n\n#define LUA_MATHLIBNAME \"math\"\nLUALIB_API int (luaopen_math) (lua_State *L);\n\n#define LUA_DBLIBNAME \"debug\"\nLUALIB_API int (luaopen_debug) (lua_State *L);\n\n#define LUA_LOADLIBNAME \"package\"\nLUALIB_API int (luaopen_package) (lua_State *L);\n\n\n/* open all previous libraries */\nLUALIB_API void (luaL_openlibs) (lua_State *L);\n\n\n\n#ifndef lua_assert\n#define lua_assert(x) ((void)0)\n#endif\n\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/test/mu_test.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Unit test macros and global data @file */\n\n#ifndef luasandbox_test_mu_test_h_\n#define luasandbox_test_mu_test_h_\n\n#include <stdio.h>\n\n#ifdef _WIN32\n#if _MSC_VER < 1900\n#define snprintf _snprintf\n#endif\n#endif\n\n#if defined(_MSC_VER)\n#define PRIuSIZE \"Iu\"\n#else\n#define PRIuSIZE \"zu\"\n#endif\n\n#define MU_ERR_LEN 1024\n\n#define mu_assert(cond, ...)                                                   \\\ndo {                                                                           \\\n  if (!(cond)) {                                                               \\\n    int cnt = snprintf(mu_err, MU_ERR_LEN, \"line: %d (%s) \", __LINE__, #cond); \\\n    if (cnt > 0 && cnt < MU_ERR_LEN) {                                         \\\n      cnt = snprintf(mu_err+cnt, MU_ERR_LEN-cnt, __VA_ARGS__);                 \\\n      if (cnt > 0 && cnt < MU_ERR_LEN) {                                       \\\n        return mu_err;                                                         \\\n      }                                                                        \\\n    }                                                                          \\\n    mu_err[MU_ERR_LEN - 1] = 0;                                                \\\n    return mu_err;                                                             \\\n  }                                                                            \\\n} while (0)\n\n#define mu_assert_rv(rv, fn)                                                   \\\ndo {                                                                           \\\n  int result = fn;                                                             \\\n  if (rv != result) {                                                          \\\n    int cnt = snprintf(mu_err, MU_ERR_LEN, \"line: %d %s expected: %d \"         \\\n    \" received: %d\", __LINE__, #fn, rv, result);                               \\\n    if (cnt > 0 && cnt < MU_ERR_LEN) {                                         \\\n      return mu_err;                                                           \\\n    }                                                                          \\\n    mu_err[MU_ERR_LEN - 1] = 0;                                                \\\n    return mu_err;                                                             \\\n  }                                                                            \\\n} while (0)\n\n#define mu_run_test(test)                                                      \\\ndo {                                                                           \\\n  char *message = test();                                                      \\\n  mu_tests_run++;                                                              \\\n  if (message)                                                                 \\\n    return message;                                                            \\\n} while (0)\n\nint mu_tests_run = 0;\nchar mu_err[MU_ERR_LEN] = { 0 };\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/test/sandbox.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Test interface for the generic lua sandbox @file */\n\n#ifndef luasandbox_test_sandbox_h_\n#define luasandbox_test_sandbox_h_\n\n#include <stddef.h>\n\n#include \"../../luasandbox.h\"\n#include \"../error.h\"\n\n#ifdef _WIN32\n#ifdef luasandboxtest_EXPORTS\n#define LSB_TEST_EXPORT __declspec(dllexport)\n#else\n#define LSB_TEST_EXPORT __declspec(dllimport)\n#endif\n#else\n#if __GNUC__ >= 4\n#define LSB_TEST_EXPORT __attribute__ ((visibility (\"default\")))\n#else\n#define LSB_TEST_EXPORT\n#endif\n#endif\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n#include \"../lua.h\"\n\n/**\n * Global variable to store the test output\n *\n */\nLSB_TEST_EXPORT extern const char *lsb_test_output;\n\n/**\n * Global variable storing the length of the current test output string\n *\n */\nLSB_TEST_EXPORT extern size_t lsb_test_output_len;\n\n/**\n * Generaly purpose stderr logger\n *\n */\nLSB_TEST_EXPORT extern lsb_logger lsb_test_logger;\n\n/**\n * Function to emulate processing data\n *\n * @param lsb Pointer to a lua sandbox\n * @param tc Test case number to control how the sandbox state is updated\n *\n * @return LSB_TEST_EXPORT int Status value returned from the sandbox\n */\nLSB_TEST_EXPORT int lsb_test_process(lsb_lua_sandbox *lsb, double tc);\n\n/**\n * Function to emulate outputting summary data\n *\n * @param lsb Pointer to a lua sandbox\n * @param tc Test case number to control what data is returned and how the state\n *           is updated\n *\n * @return LSB_TEST_EXPORT int 0 on success, 1 on failure\n */\nLSB_TEST_EXPORT int lsb_test_report(lsb_lua_sandbox *lsb, double tc);\n\n/**\n * Callback for collecting output, places a pointer to the results in the global\n * lsb_test_output variable )not thread safe)\n *\n * @param lua Lua state\n *\n * @return LSB_TEST_EXPORT int 0 or lua_error\n */\nLSB_TEST_EXPORT int lsb_test_write_output(lua_State *lua);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/util/heka_message.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Heka message representation @file */\n\n#ifndef luasandbox_util_heka_message_h_\n#define luasandbox_util_heka_message_h_\n\n#include <stdbool.h>\n#include <stddef.h>\n\n#include \"input_buffer.h\"\n#include \"output_buffer.h\"\n#include \"string.h\"\n#include \"util.h\"\n\n#define LSB_UUID_SIZE         16\n#define LSB_UUID_STR_SIZE     36\n#define LSB_HDR_FRAME_SIZE    3\n#define LSB_MIN_HDR_SIZE      14\n#define LSB_MAX_HDR_SIZE      (255 + LSB_HDR_FRAME_SIZE)\n\n#define LSB_UUID          \"Uuid\"\n#define LSB_TIMESTAMP     \"Timestamp\"\n#define LSB_TYPE          \"Type\"\n#define LSB_LOGGER        \"Logger\"\n#define LSB_SEVERITY      \"Severity\"\n#define LSB_PAYLOAD       \"Payload\"\n#define LSB_ENV_VERSION   \"EnvVersion\"\n#define LSB_PID           \"Pid\"\n#define LSB_HOSTNAME      \"Hostname\"\n#define LSB_FIELDS        \"Fields\"\n#define LSB_RAW           \"raw\"\n#define LSB_FRAMED        \"framed\"\n#define LSB_SIZE          \"size\"\n\ntypedef enum {\n  LSB_PB_UUID         = 1,\n  LSB_PB_TIMESTAMP    = 2,\n  LSB_PB_TYPE         = 3,\n  LSB_PB_LOGGER       = 4,\n  LSB_PB_SEVERITY     = 5,\n  LSB_PB_PAYLOAD      = 6,\n  LSB_PB_ENV_VERSION  = 7,\n  LSB_PB_PID          = 8,\n  LSB_PB_HOSTNAME     = 9,\n  LSB_PB_FIELDS       = 10\n} lsb_pb_message;\n\ntypedef enum {\n  LSB_PB_NAME           = 1,\n  LSB_PB_VALUE_TYPE     = 2,\n  LSB_PB_REPRESENTATION = 3,\n  LSB_PB_VALUE_STRING   = 4,\n  LSB_PB_VALUE_BYTES    = 5,\n  LSB_PB_VALUE_INTEGER  = 6,\n  LSB_PB_VALUE_DOUBLE   = 7,\n  LSB_PB_VALUE_BOOL     = 8\n} lsb_pb_field;\n\ntypedef enum {\n  LSB_PB_STRING   = 0,\n  LSB_PB_BYTES    = 1,\n  LSB_PB_INTEGER  = 2,\n  LSB_PB_DOUBLE   = 3,\n  LSB_PB_BOOL     = 4\n} lsb_pb_value_types;\n\ntypedef struct lsb_heka_field\n{\n  lsb_const_string    name;\n  lsb_const_string    representation;\n  lsb_const_string    value;\n  lsb_pb_value_types  value_type;\n} lsb_heka_field;\n\ntypedef struct lsb_heka_message\n{\n  lsb_const_string raw;\n  lsb_const_string uuid;\n  lsb_const_string type;\n  lsb_const_string logger;\n  lsb_const_string payload;\n  lsb_const_string env_version;\n  lsb_const_string hostname;\n\n  lsb_heka_field *fields;\n\n  long long timestamp;\n  int       severity;\n  int       pid;\n  int       fields_len;\n  int       fields_size;\n} lsb_heka_message;\n\ntypedef enum {\n  LSB_READ_NIL,\n  LSB_READ_NUMERIC,\n  LSB_READ_STRING,\n  LSB_READ_BOOL\n} lsb_read_type;\n\ntypedef struct {\n  union\n  {\n    lsb_const_string  s;\n    double            d;\n  } u;\n  lsb_read_type type;\n} lsb_read_value;\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n/**\n * Zero the structure and allocate memory for at least 'size' fields\n *\n * @param m Heka message structure\n * @param num_fields Preallocated number of fields (must be >0)\n *\n * @return lsb_err_value NULL on success error message on failure\n *\n */\nLSB_UTIL_EXPORT lsb_err_value\nlsb_init_heka_message(lsb_heka_message *m, int num_fields);\n\n/**\n * Frees the memory allocated for the message fields\n *\n * @param m Heka message structure\n *\n */\nLSB_UTIL_EXPORT void lsb_free_heka_message(lsb_heka_message *m);\n\n/**\n * Resets the message headers and fields zeroing the allocated memory\n *\n * @param m Heka message structure\n *\n */\nLSB_UTIL_EXPORT void lsb_clear_heka_message(lsb_heka_message *m);\n\n/**\n * Locates a framed Heka message in an input buffer\n *\n * @param m Heka message structure\n * @param ib Input buffer\n * @param decode True if the framed message should be protobuf decoded\n * @param discarded_bytes Used to track stream corruption\n * @param logger Logger structure (can be set to NULL to disable logging)\n *\n * @return bool True on success\n */\nLSB_UTIL_EXPORT bool lsb_find_heka_message(lsb_heka_message *m,\n                                           lsb_input_buffer *ib,\n                                           bool decode,\n                                           size_t *discarded_bytes,\n                                           lsb_logger *logger);\n\n/**\n * Decodes an array of bytes into a Heka message. The message structure is\n * cleared before decoding.\n *\n * @param m Heka message structure\n * @param buf Protobuf array\n * @param len Length of the protobuf array\n * @param logger Logger structure (can be set to NULL to disable logging)\n *\n * @return bool True on success\n *\n */\nLSB_UTIL_EXPORT bool lsb_decode_heka_message(lsb_heka_message *m,\n                                             const char *buf,\n                                             size_t len,\n                                             lsb_logger *logger);\n\n/**\n * Reads a dynamic field from the Heka message\n *\n * @param m Heka meassage structure\n * @param name Field name\n * @param fi Field index\n * @param ai Array index into the field\n * @param val Value structure to be populated by the read\n *\n * @return bool True on success\n */\nLSB_UTIL_EXPORT bool lsb_read_heka_field(const lsb_heka_message *m,\n                                         lsb_const_string *name,\n                                         int fi,\n                                         int ai,\n                                         lsb_read_value *val);\n\n/**\n * Writes a binary UUID to the output buffer\n *\n * @param ob Pointer to the output data buffer.\n * @param uuid Uuid string to output (can be NULL, binary, human readable UUID)\n * @param len Length of UUID (16 or 36 anything else will cause a new UUID to be\n *            created).\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value\nlsb_write_heka_uuid(lsb_output_buffer *ob, const char *uuid, size_t len);\n\n/**\n * Writes the Heka framing header to the specified buffer.\n *\n * @param buf Buffer to write the header to must be at least LSB_MIN_HDR_SIZE\n *            size.\n * @param len Length of the message to encode into the header\n *\n * @return LSB_UTIL_EXPORT size_t\n */\nLSB_UTIL_EXPORT size_t lsb_write_heka_header(char *buf, size_t len);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/util/heka_message_matcher.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Hindsight/Heka message matcher @file */\n\n#ifndef luasandbox_util_heka_message_matcher_h_\n#define luasandbox_util_heka_message_matcher_h_\n\n#include <stdbool.h>\n\n#include \"heka_message.h\"\n\ntypedef struct lsb_message_matcher lsb_message_matcher;\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n/**\n * Parses a message matcher expression and returns the matcher\n *\n * @param exp Expression to parse into a matcher\n *\n * @return lsb_message_matcher*\n */\nLSB_UTIL_EXPORT lsb_message_matcher*\nlsb_create_message_matcher(const char *exp);\n\n/**\n * Frees all memory associated with a message matcher instance\n *\n * @param mm Message matcher\n */\nLSB_UTIL_EXPORT void lsb_destroy_message_matcher(lsb_message_matcher *mm);\n\n/**\n * Evaluates the message matcher against the provided message\n *\n * @param mm Message matcher\n * @param m Heka message\n *\n * @return bool True if the message is a match\n */\nLSB_UTIL_EXPORT bool\nlsb_eval_message_matcher(lsb_message_matcher *mm, lsb_heka_message *m);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/util/input_buffer.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Data stream input buffer @file */\n\n#ifndef luasandbox_util_input_buffer_h_\n#define luasandbox_util_input_buffer_h_\n\n#include <stdbool.h>\n#include <stddef.h>\n\n#include \"util.h\"\n\ntypedef struct lsb_input_buffer\n{\n  char    *buf;\n  size_t  size;\n  size_t  maxsize;\n  size_t  readpos;\n  size_t  scanpos;\n  size_t  msglen;\n} lsb_input_buffer;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Initialize the provided input buffer\n *\n * @param b Input buffer\n * @param max_message_size The maximum message size the buffer will handle\n *                 before erroring (the internal buffer will contain extra space\n *                 for the header)\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value\nlsb_init_input_buffer(lsb_input_buffer *b, size_t max_message_size);\n\n/**\n * Frees the memory internally allocated by the buffer and resets the state\n *\n * @param b Input buffer\n */\nLSB_UTIL_EXPORT void lsb_free_input_buffer(lsb_input_buffer *b);\n\n/**\n * Expands the input buffer (if necessary) to accomadate the requested number of\n * bytes. The expansion happens in power of two increments up to the maxsize.\n * The buffer never shrinks in size.\n *\n * @param b Input buffer\n * @param len The length of the data being added to the buffer\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value\nlsb_expand_input_buffer(lsb_input_buffer *b, size_t len);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/util/output_buffer.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Data stream output buffer @file */\n\n#ifndef luasandbox_util_output_buffer_h_\n#define luasandbox_util_output_buffer_h_\n\n#include <stdbool.h>\n\n#include \"util.h\"\n\n#define LSB_OUTPUT_SIZE 1024\n\ntypedef struct lsb_output_buffer {\n  char          *buf;\n  size_t        maxsize;\n  size_t        size;\n  size_t        pos;\n} lsb_output_buffer;\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n/**\n * Initialize the provided input buffer\n *\n * @param b Output buffer\n * @param max_message_size The maximum message size the buffer will handle\n *                 before erroring\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value\nlsb_init_output_buffer(lsb_output_buffer *b, size_t max_message_size);\n\n/**\n * Frees the memory internally allocated by the buffer and resets the state\n *\n * @param b Output buffer\n */\nLSB_UTIL_EXPORT void lsb_free_output_buffer(lsb_output_buffer *b);\n\n/**\n * Resize the output buffer when more space is needed.\n *\n * @param b Output buffer to resize.\n * @param needed Number of additional bytes needed.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value lsb_expand_output_buffer(lsb_output_buffer *b,\n                                                       size_t needed);\n\n/**\n * Append a character to the output buffer.\n *\n * @param b Pointer the b buffer.\n * @param ch Character to append to the b.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value lsb_outputc(lsb_output_buffer *b, char ch);\n\n/**\n * Append a formatted string to the output buffer.\n *\n * @param b Pointer the b buffer.\n * @param fmt Printf format specifier.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value\nlsb_outputf(lsb_output_buffer *b, const char *fmt, ...);\n\n/**\n * Append a fixed string to the output buffer.\n *\n * @param b Pointer the b buffer.\n * @param str String to append to the b.\n * @param len Length of the string to append\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value\nlsb_outputs(lsb_output_buffer *b, const char *str, size_t len);\n\n/**\n * More efficient output of a double to a string. NaN/Inf check and then calls\n * lsb_outputfd.\n *\n * @param b Pointer the output buffer.\n * @param d Double value to convert to a string.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value lsb_outputd(lsb_output_buffer *b, double d);\n\n\n/**\n * More efficient output of a double to a string; no NaN or Inf outputs.\n *\n * @param b Pointer the output buffer.\n * @param d Double value to convert to a string.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value lsb_outputfd(lsb_output_buffer *b, double d);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/util/protobuf.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Generic protobuf utility functions @file */\n\n#ifndef luasandbox_util_protobuf_h_\n#define luasandbox_util_protobuf_h_\n\n#include <stddef.h>\n#include <stdbool.h>\n\n#include \"output_buffer.h\"\n#include \"util.h\"\n\n#define LSB_MAX_VARINT_BYTES  10\n\ntypedef enum {\n  LSB_PB_WT_VARINT  = 0,\n  LSB_PB_WT_FIXED64 = 1,\n  LSB_PB_WT_LENGTH  = 2,\n  LSB_PB_WT_SGROUP  = 3,\n  LSB_PB_WT_EGROUP  = 4,\n  LSB_PB_WT_FIXED32 = 5\n} lsb_pb_wire_types;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Extract the tag and wiretype from a protobuf key\n *\n * @param p Key\n * @param tag Tag Id\n * @param wiretype Wiretype Id\n *\n * @return LSB_EXPORT const char*\n */\nLSB_UTIL_EXPORT\nconst char* lsb_pb_read_key(const char *p, int *tag, int *wiretype);\n\n/**\n * Writes a field key (tag id/wire type) to the output buffer.\n *\n * @param ob Pointer to the output data buffer.\n * @param tag Field identifier.\n * @param wiretype Field wire type.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value\nlsb_pb_write_key(lsb_output_buffer *ob, unsigned char tag,\n                 unsigned char wiretype);\n\n/**\n * Reads the varint into the provided variable\n *\n * @param p Start of buffer\n * @param e End of buffer\n * @param vi Varint value\n *\n * @return const char* Position in the buffer after the varint\n */\nLSB_UTIL_EXPORT\nconst char* lsb_pb_read_varint(const char *p, const char *e, long long *vi);\n\n\n/**\n * Outputs the varint to an existing buffer\n *\n * @param buf Pointer to buffer with at least LSB_MAX_VARINT_BYTES available,\n * @param i Number to be encoded.\n *\n * @return int Number of bytes written\n */\nLSB_UTIL_EXPORT int lsb_pb_output_varint(char *buf, unsigned long long i);\n\n/**\n * Writes a varint encoded number to the output buffer.\n *\n * @param ob Pointer to the output data buffer.\n * @param i Number to be encoded.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value\nlsb_pb_write_varint(lsb_output_buffer *ob, unsigned long long i);\n\n/**\n * Writes a bool to the output buffer.\n *\n * @param ob Pointer to the output data buffer.\n * @param i Number to be encoded.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value lsb_pb_write_bool(lsb_output_buffer *ob, int i);\n\n/**\n * Writes a double to the output buffer.\n *\n * @param ob Pointer to the output data buffer.\n * @param i Double to be encoded.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value\nlsb_pb_write_double(lsb_output_buffer *ob, double i);\n\n/**\n * Writes a string to the output buffer.\n *\n * @param ob Pointer to the output data buffer.\n * @param tag Field identifier.\n * @param s  String to output.\n * @param len Length of s.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value\nlsb_pb_write_string(lsb_output_buffer *ob, char tag, const char *s, size_t len);\n\n/**\n * Updates the field length in the output buffer once the size is known, this\n * allows for single pass encoding.\n *\n * @param ob  Pointer to the output data buffer.\n * @param len_pos Position in the output buffer where the length should be\n *                written.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_UTIL_EXPORT lsb_err_value\nlsb_pb_update_field_length(lsb_output_buffer *ob, size_t len_pos);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/util/running_stats.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Calculates the running count, sum, mean, variance, and standard deviation\n *  @file */\n\n#ifndef lsb_util_running_stats_h_\n#define lsb_util_running_stats_h_\n\n#include \"util.h\"\n\ntypedef struct lsb_running_stats\n{\n  double count;\n  double mean;\n  double sum;\n} lsb_running_stats;\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Zeros out the stats counters\n *\n * @param s Stat structure to zero out\n */\nLSB_UTIL_EXPORT void lsb_init_running_stats(lsb_running_stats *s);\n\n/**\n * Value to add to the running stats\n *\n * @param s Stat structure\n * @param d Value to add\n */\nLSB_UTIL_EXPORT void lsb_update_running_stats(lsb_running_stats *s, double d);\n\n/**\n * Return the standard deviation of the stats\n *\n * @param s Stat structure\n *\n * @return double Standard deviation of the stats up to this point\n */\nLSB_UTIL_EXPORT double lsb_sd_running_stats(lsb_running_stats *s);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/util/string.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Heka message string @file */\n\n#ifndef luasandbox_util_string_h_\n#define luasandbox_util_string_h_\n\n#include \"util.h\"\n\ntypedef struct lsb_const_string\n{\n  const char  *s;\n  size_t      len;\n} lsb_const_string;\n\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n/**\n * Initializes the struct to zero.\n *\n * @param s Pointer to the struct\n *\n */\nLSB_UTIL_EXPORT void lsb_init_const_string(lsb_const_string *s);\n\n\n/**\n * Lua string unescape. The returned string is always NUL terminated, but can\n * contain other NULs in its body.\n *\n * @param d Pointer to the destination array where the content is to be\n *          unescaped.\n * @param s C string to be unescaped\n * @param dlen The length of the destination array (must be 1 byte larger than\n *            the source string (for inclusion of the NUL terminator).  After\n *            successful conversion the final length of the escaped string is\n *            written back to this value as it may not equal strlen(d).\n *\n * @return char* A pointer to d or NULL on error.\n */\nLSB_UTIL_EXPORT\nchar* lsb_lua_string_unescape(char *d, const char *s, size_t *dlen);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/util/string_matcher.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** C API for the Lua string pattern matcher @file */\n\n#ifndef luasandbox_util_string_matcher_h_\n#define luasandbox_util_string_matcher_h_\n\n#include <stdbool.h>\n#include <stddef.h>\n\n#include \"util.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n/**\n * Matches a string using a Lua string match pattern\n *\n * @param s String to match\n * @param len Length of the string\n * @param p Lua match pattern\n *          http://www.lua.org/manual/5.1/manual.html#pdf-string.match\n *\n * @return bool True if the string matches the pattern\n */\nLSB_UTIL_EXPORT bool lsb_string_match(const char *s, size_t len, const char *p);\n\n\n/**\n * Searches for a string literal within a string\n *\n * @param s String to search\n * @param ls Length of the string\n * @param p Literal match string\n * @param lp Length of the match string\n *\n * @return bool True if the string contains the literal\n */\nLSB_UTIL_EXPORT bool lsb_string_find(const char *s, size_t ls, const char *p, size_t lp);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox/util/util.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Shared types and structures @file */\n\n#ifndef luasandbox_util_util_h_\n#define luasandbox_util_util_h_\n\n#include <stdbool.h>\n#include <stddef.h>\n#include <stdint.h>\n\n#include \"../error.h\"\n\n#ifdef _WIN32\n#ifdef luasandboxutil_EXPORTS\n#define LSB_UTIL_EXPORT __declspec(dllexport)\n#else\n#define LSB_UTIL_EXPORT __declspec(dllimport)\n#endif\n#else\n#if __GNUC__ >= 4\n#define LSB_UTIL_EXPORT __attribute__ ((visibility (\"default\")))\n#else\n#define LSB_UTIL_EXPORT\n#endif\n#endif\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\nLSB_UTIL_EXPORT extern lsb_err_id LSB_ERR_UTIL_NULL;\nLSB_UTIL_EXPORT extern lsb_err_id LSB_ERR_UTIL_OOM;\nLSB_UTIL_EXPORT extern lsb_err_id LSB_ERR_UTIL_FULL;\nLSB_UTIL_EXPORT extern lsb_err_id LSB_ERR_UTIL_PRANGE;\n\n/**\n * Hacker's Delight - Henry S. Warren, Jr. page 48\n *\n * @param x\n *\n * @return size_t Least power of 2 greater than or equal to x\n */\nLSB_UTIL_EXPORT size_t lsb_lp2(unsigned long long x);\n\n/**\n * Read a file into a string\n *\n * @param fn Filename to read\n *\n * @return char* NULL on failure otherwise a pointer to the file contents (must\n *         be freed by the caller).\n */\nLSB_UTIL_EXPORT char* lsb_read_file(const char *fn);\n\n/**\n * Retrieves the highest resolution timer available converted to nanoseconds\n *\n * @return unsigned long long\n */\nLSB_UTIL_EXPORT unsigned long long lsb_get_time();\n\n/**\n * Retrieves the highest resolution time since Jan 1, 1970 converted to\n * nanoseconds\n *\n * @return unsigned long long (time_ns)\n */\nLSB_UTIL_EXPORT long long lsb_get_timestamp();\n\n/**\n * Sets the timezone environment variable for the time conversion functions\n *\n * @param tz Timezone string (if NULL uses UTC)\n *\n * @return bool True if the environment variable is successfully set\n */\nLSB_UTIL_EXPORT bool lsb_set_tz(const char *tz);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Generic Lua sandbox for dynamic data analysis  @file */\n\n#ifndef luasandbox_h_\n#define luasandbox_h_\n\n#include \"luasandbox/error.h\"\n\n#ifdef _WIN32\n#ifdef luasandbox_EXPORTS\n#define LSB_EXPORT __declspec(dllexport)\n#else\n#define LSB_EXPORT __declspec(dllimport)\n#endif\n#else\n#if __GNUC__ >= 4\n#define LSB_EXPORT __attribute__ ((visibility (\"default\")))\n#else\n#define LSB_EXPORT\n#endif\n#endif\n\n#define LSB_ERROR_SIZE 256\n\n#define LSB_SHUTTING_DOWN     \"shutting down\"\n#define LSB_CONFIG_TABLE      \"lsb_config\"\n#define LSB_THIS_PTR          \"lsb_this_ptr\"\n#define LSB_MEMORY_LIMIT      \"memory_limit\"\n#define LSB_INSTRUCTION_LIMIT \"instruction_limit\"\n#define LSB_INPUT_LIMIT       \"input_limit\"\n#define LSB_OUTPUT_LIMIT      \"output_limit\"\n#define LSB_LOG_LEVEL         \"log_level\"\n#define LSB_LUA_PATH          \"path\"\n#define LSB_LUA_CPATH         \"cpath\"\n#define LSB_NIL_ERROR         \"<nil error message>\"\n\ntypedef enum {\n  LSB_UNKNOWN     = 0,\n  LSB_RUNNING     = 1,\n  LSB_TERMINATED  = 2,\n  LSB_STOP        = 3\n} lsb_state;\n\ntypedef enum {\n  LSB_US_LIMIT    = 0,\n  LSB_US_CURRENT  = 1,\n  LSB_US_MAXIMUM  = 2,\n\n  LSB_US_MAX\n} lsb_usage_stat;\n\ntypedef enum {\n  LSB_UT_MEMORY       = 0,\n  LSB_UT_INSTRUCTION  = 1,\n  LSB_UT_OUTPUT       = 2,\n\n  LSB_UT_MAX\n} lsb_usage_type;\n\ntypedef struct lsb_lua_sandbox lsb_lua_sandbox;\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n#include \"luasandbox/lua.h\"\n\nLSB_EXPORT extern lsb_err_id LSB_ERR_INIT;\nLSB_EXPORT extern lsb_err_id LSB_ERR_LUA;\nLSB_EXPORT extern lsb_err_id LSB_ERR_TERMINATED;\n\n/**\n * Allocates and initializes the structure around the Lua sandbox allowing\n * full specification of the sandbox configuration using a Lua configuration\n * string.\n * memory_limit = 1024*1024*1\n * instruction_limit = 10000\n * output_limit = 64*1024\n * path = '/modules/?.lua'\n * cpath = '/modules/?.so'\n * remove_entries = {\n * [''] =\n * {'collectgarbage','coroutine','dofile','load','loadfile','loadstring',\n * 'newproxy','print'},\n * os = {'getenv','execute','exit','remove','rename','setlocale','tmpname'}\n * }\n * disable_modules = {io = 1}\n *\n *\n * @param parent Pointer to associate the owner to this sandbox.\n * @param lua_file Filename of the Lua script to run in this sandbox.\n * @param cfg Lua structure defining the full sandbox restrictions (may contain\n *            optional host configuration options, everything is available to\n *            the sandbox through the read_config API.\n * @param logger Struct for error reporting/debug printing (NULL to disable)\n * @return lsb_lua_sandbox Sandbox pointer or NULL on failure.\n */\nLSB_EXPORT lsb_lua_sandbox*\nlsb_create(void *parent, const char *lua_file, const char *cfg,\n           lsb_logger *logger);\n\n/**\n * Initializes the Lua sandbox and loads/runs the Lua script that was specified\n * in lua_create_sandbox.\n *\n * @param lsb Pointer to the sandbox.\n * @param state_file Filename where the global data is read. Use a NULL or empty\n *                   string for no data restoration.  The global\n *                   _PRESERVATION_VERSION variable will be examined during\n *                   restoration; if the previous version does not match the\n *                   current version the restoration will be aborted and the\n *                   sandbox will start cleanly. _PRESERVATION_VERSION should be\n *                   incremented any time an incompatible change is made to the\n *                   global data schema. If no version is set the check will\n *                   always succeed and a version of zero is assigned.\n *\n * @return lsb_err_value NULL on success error message on failure\n *\n */\nLSB_EXPORT lsb_err_value\nlsb_init(lsb_lua_sandbox *lsb, const char *state_file);\n\n/**\n * Changes the sandbox state to LSB_STOP to allow for a clean exit. This call is\n * not thread safe.\n *\n * @param lsb sandbox to clean stop\n *\n * @return\n *\n */\nLSB_EXPORT void lsb_stop_sandbox_clean(lsb_lua_sandbox *lsb);\n\n/**\n * Aborts the running sandbox from a different thread of execution. A \"shutting\n * down\" Lua error message is generated.\n *\n * @param lsb sandbox to abort\n *\n * @return\n *\n */\nLSB_EXPORT void lsb_stop_sandbox(lsb_lua_sandbox *lsb);\n\n/**\n * Frees the memory associated with the sandbox.\n *\n * @param lsb        Sandbox pointer to discard.\n *\n * @return NULL on success, pointer to an error message on failure that MUST BE\n * FREED by the caller.\n */\nLSB_EXPORT char* lsb_destroy(lsb_lua_sandbox *lsb);\n\n/**\n * Retrieve the sandbox usage statistics.\n *\n * @param lsb Pointer to the sandbox.\n * @param utype Type of statistic to retrieve i.e. memory.\n * @param ustat Type of statistic to retrieve i.e. current.\n *\n * @return size_t Count or number of bytes depending on the statistic.\n */\nLSB_EXPORT size_t lsb_usage(lsb_lua_sandbox *lsb,\n                            lsb_usage_type utype,\n                            lsb_usage_stat ustat);\n/**\n * Retrieve the current sandbox status.\n *\n * @param lsb    Pointer to the sandbox.\n *\n * @return lsb_state code\n */\nLSB_EXPORT lsb_state lsb_get_state(lsb_lua_sandbox *lsb);\n\n/**\n * Return the last error in human readable form.\n *\n * @param lsb Pointer to the sandbox.\n *\n * @return const char* error message\n */\nLSB_EXPORT const char* lsb_get_error(lsb_lua_sandbox *lsb);\n\n/**\n * Sets the last error string.\n *\n * @param lsb Pointer to the sandbox.\n * @param err Error message.\n *\n * @return const char* error message\n */\nLSB_EXPORT void lsb_set_error(lsb_lua_sandbox *lsb, const char *err);\n\n/**\n * Access the Lua pointer.\n *\n * @param lsb Pointer to the sandbox.\n *\n * @return lua_State* The lua_State pointer.\n */\nLSB_EXPORT lua_State* lsb_get_lua(lsb_lua_sandbox *lsb);\n\n/**\n * Returns the filename of the Lua source.\n *\n * @param lsb Pointer to the sandbox.\n *\n * @return const char* filename.\n */\nLSB_EXPORT const char* lsb_get_lua_file(lsb_lua_sandbox *lsb);\n\n/**\n * Access the parent pointer stored in the sandbox.\n *\n * @param lsb Pointer to the sandbox.\n *\n * @return void* The parent pointer passed to init.\n */\nLSB_EXPORT void* lsb_get_parent(lsb_lua_sandbox *lsb);\n\n/**\n * Access the logger struct stored in the sandbox. The logger callback is only\n * available to modules in debug mode (same as print).\n *\n * @param lsb Pointer to the sandbox.\n *\n * @return lsb_logger Pointer to the logger struct\n *\n */\nLSB_EXPORT const lsb_logger* lsb_get_logger(lsb_lua_sandbox *lsb);\n\n/**\n * Create a CFunction for use by the Sandbox. The Lua sandbox pointer is pushed\n * to upvalue index 1.\n *\n * @param lsb Pointer to the sandbox.\n * @param func Lua CFunction pointer.\n * @param func_name Function name exposed to the Lua sandbox.\n */\nLSB_EXPORT void lsb_add_function(lsb_lua_sandbox *lsb,\n                                 lua_CFunction func,\n                                 const char *func_name);\n\n/**\n * Helper function to load the Lua function and set the instruction limits\n *\n * @param lsb Pointer to the sandbox.\n * @param func_name Name of the function to load\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_EXPORT lsb_err_value\nlsb_pcall_setup(lsb_lua_sandbox *lsb, const char *func_name);\n\n/**\n * Helper function to update the statistics after the call\n *\n * @param lsb Pointer to the sandbox.\n */\nLSB_EXPORT void lsb_pcall_teardown(lsb_lua_sandbox *lsb);\n\n/**\n * Change the sandbox state to LSB_TERMINATED due to a fatal error.\n *\n * @param lsb Pointer to the sandbox.\n * @param err Reason for termination\n */\nLSB_EXPORT void lsb_terminate(lsb_lua_sandbox *lsb, const char *err);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox_output.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Lua sandbox output generation/retrieval functions @file */\n\n#ifndef luasandbox_output_h_\n#define luasandbox_output_h_\n\n#include <stdio.h>\n\n#include \"luasandbox.h\"\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n#include \"luasandbox/lua.h\"\n\n/**\n * Add a output function to the environment table. The environment table must be\n * on the top of the stack. This function will receive the userdata and\n * lsb_output_buffer struct as pointers on the Lua stack.\n *\n * lsb_output_buffer* output = (output_data*)lua_touserdata(lua, -1);\n * ud_object* ud = (ud_object*)lua_touserdata(lua, -2);\n *\n * @param lua Pointer the Lua state.\n * @param fp Function pointer to the outputter.\n *\n * @return int Zero on success, non-zero on failure.\n */\nLSB_EXPORT void lsb_add_output_function(lua_State *lua, lua_CFunction fp);\n\n/**\n * Utility function to retrieve a user data output function\n *\n * @param lua\n * @param index\n *\n * @return lua_CFunction\n */\nLSB_EXPORT lua_CFunction lsb_get_output_function(lua_State *lua, int index);\n\n/**\n * Add a zero copy function to the environment table. The environment table must\n * be on the top of the stack. This function will receive the userdata as a\n * pointer on the Lua stack.\n *\n * ud_object* ud = (ud_object*)lua_touserdata(lua, -1);\n *\n * @param lua Pointer the Lua state.\n * @param fp Function pointer to the zero copy function.\n *\n * @return int Number of segments (pointer and length for each)\n */\nLSB_EXPORT void lsb_add_zero_copy_function(lua_State *lua, lua_CFunction fp);\n\n\n/**\n * Utility function to retrieve a user data zero copy function\n *\n * @param lua\n * @param index\n *\n * @return lua_CFunction\n */\nLSB_EXPORT lua_CFunction lsb_get_zero_copy_function(lua_State *lua, int index);\n\n/**\n * Write an array of variables on the Lua stack to the output buffer.\n *\n * @param lsb Pointer to the sandbox.\n * @param start Lua stack index of first variable.\n * @param end Lua stack index of the last variable.\n * @param append 0 to overwrite the output buffer, 1 to append the output to it\n *\n */\nLSB_EXPORT void\nlsb_output(lsb_lua_sandbox *lsb, int start, int end, int append);\n\n/**\n * Write an array of variables on the Lua stack to the output buffer. After\n * adding support for coroutines we need an extra variable to specify the\n * correct Lua state.\n *\n * @param lsb Pointer to the sandbox.\n * @param lua Pointer the Lua state\n * @param start Lua stack index of first variable.\n * @param end Lua stack index of the last variable.\n * @param append 0 to overwrite the output buffer, 1 to append the output to it\n *\n */\nLSB_EXPORT void\nlsb_output_coroutine(lsb_lua_sandbox *lsb, lua_State *lua, int start,\n                     int end, int append);\n\n/**\n * Retrieve the data in the output buffer and reset the buffer. The returned\n * output string will remain valid until additional sandbox output is performed.\n * The output should be copied if the application needs to hold onto it.\n *\n * @param lsb Pointer to the sandbox.\n * @param len If len is not NULL, it will be set to the length of the string.\n *\n * @return const char* Pointer to the output buffer.\n */\nLSB_EXPORT const char* lsb_get_output(lsb_lua_sandbox *lsb, size_t *len);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "include/luasandbox_serialize.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Lua sandbox serialization @file */\n\n#ifndef luasandbox_serialize_h_\n#define luasandbox_serialize_h_\n\n#include <stdio.h>\n\n#include \"luasandbox/util/output_buffer.h\"\n#include \"luasandbox_output.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n#include \"luasandbox/lua.h\"\n\n/**\n * Add a serialization function to the environment table. The environment table\n * must be on the top of the stack. This function will receive the userdata,\n * fully qualified variable name, and lsb_output_buffer struct as pointers on the\n * Lua stack.\n *\n * lsb_output_buffer* output = (output_data*)lua_touserdata(lua, -1);\n * const char *key = (const char*)lua_touserdata(lua, -2);\n * ud_object* ud = (ud_object*)lua_touserdata(lua, -3);\n *\n * @param lua Pointer the Lua state.\n * @param fp Function pointer to the serializer.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_EXPORT void\nlsb_add_serialize_function(lua_State *lua, lua_CFunction fp);\n\n/**\n * Serializes a binary data to a Lua string.\n *\n * @param output Pointer the output buffer.\n * @param src Pointer to the binary data.\n * @param len Length in bytes of the data to output.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_EXPORT lsb_err_value\nlsb_serialize_binary(lsb_output_buffer *output, const void *src, size_t len);\n\n/**\n * More efficient serialization of a double to a string\n *\n * @param output Pointer the output buffer.\n * @param d Double value to convert to a string.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nLSB_EXPORT lsb_err_value\nlsb_serialize_double(lsb_output_buffer *output, double d);\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nif(MSVC)\n\tadd_definitions(\n\t-DLUA_BUILD_AS_DLL\n\t-D_CRT_SECURE_NO_WARNINGS\n\t)\nelse()\n\tadd_definitions(\n\t-DLUA_USE_POSIX \n\t-DLUA_USE_DLOPEN \n\t-DLUA_USE_STRTODHEX\n\t-DLUA_USE_LONGLONG \n\t-DLUA_USE_GMTIME_R\n\t)\nendif()\n\nset(LUA_SRC\nlua/lapi.c\nlua/lauxlib.c\nlua/lbaselib.c\nlua/lcode.c\nlua/ldblib.c\nlua/ldebug.c\nlua/ldo.c\nlua/ldump.c\nlua/lfunc.c \nlua/lgc.c\nlua/linit.c\nlua/liolib.c\nlua/llex.c\nlua/lmathlib.c\nlua/lmem.c\nlua/loadlib.c \nlua/lobject.c\nlua/lopcodes.c\nlua/loslib.c\nlua/lparser.c\nlua/lstate.c\nlua/lstring.c\nlua/lstrlib.c\nlua/ltable.c\nlua/ltablib.c\nlua/ltm.c\nlua/lundump.c\nlua/lvm.c\nlua/lzio.c\n)\n\nset(LUA_SANDBOX_SRC\nluasandbox.c\nluasandbox_output.c\nluasandbox_serialize.c\n)\n\nadd_library(luasandbox SHARED ${LUA_SANDBOX_SRC} ${LUA_SRC})\nset_target_properties(luasandbox PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION 0)\ntarget_link_libraries(luasandbox luasandboxutil ${CMAKE_DL_LIBS})\nif(LIBM_LIBRARY)\n  target_link_libraries(luasandbox ${LIBM_LIBRARY})\nendif()\ninstall(TARGETS luasandbox DESTINATION ${CMAKE_INSTALL_LIBDIR})\n\nadd_subdirectory(util)\nadd_subdirectory(heka)\nif(NOT WIN32) # todo need to add getopt support for Windows\n  add_subdirectory(cli)\nendif()\nadd_subdirectory(test)\n"
  },
  {
    "path": "src/cli/CMakeLists.txt",
    "content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nadd_executable(lsb_heka_cat lsb_heka_cat)\ntarget_link_libraries(lsb_heka_cat luasandboxutil)\n\nif(LIBM_LIBRARY)\n  target_link_libraries(lsb_heka_cat ${LIBM_LIBRARY})\nendif()\n\ninstall(TARGETS lsb_heka_cat DESTINATION ${CMAKE_INSTALL_BINDIR})\n"
  },
  {
    "path": "src/cli/lsb_heka_cat.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief lua_sandbox Heka file stream cat @file */\n\n#include <ctype.h>\n#include <limits.h>\n#include <math.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n#include <unistd.h>\n\n#include \"luasandbox/util/heka_message.h\"\n#include \"luasandbox/util/heka_message_matcher.h\"\n#include \"luasandbox/util/input_buffer.h\"\n#include \"luasandbox/util/protobuf.h\"\n#include \"luasandbox/util/util.h\"\n\ntypedef void (*output_function)(lsb_heka_message *msg);\n\nstatic void\nlog_cb(void *context, const char *component, int level, const char *fmt, ...)\n{\n  (void)context;\n  (void)component;\n  (void)level;\n  va_list args;\n  va_start(args, fmt);\n  vfprintf(stderr, fmt, args);\n  va_end(args);\n  fwrite(\"\\n\", 1, 1, stderr);\n}\nstatic lsb_logger logger = { .context = NULL, .cb = log_cb };\n\n\n// todo this function is duplicated in util/heka_message.c\n// we may want to add it to the API if it is generally useful\nstatic const char*\nread_string(int wiretype, const char *p, const char *e, lsb_const_string *s)\n{\n  if (wiretype != LSB_PB_WT_LENGTH) {\n    return NULL;\n  }\n\n  long long vi;\n  p = lsb_pb_read_varint(p, e, &vi);\n  if (!p || vi < 0 || vi > e - p) {\n    return NULL;\n  }\n  s->s = p;\n  s->len = (size_t)vi;\n  return p + vi;\n}\n\n\nstatic void output_cs(const char *key, lsb_const_string *cs, bool eol)\n{\n  if (cs->s) {\n    fprintf(stdout, \"%s: %.*s\", key, (int)cs->len, cs->s);\n  } else {\n    fprintf(stdout, \"%s: <nil>\", key);\n  }\n  if (eol) {\n    fprintf(stdout, \"\\n\");\n  }\n}\n\n\nstatic void output_text(lsb_heka_message *msg)\n{\n  static char tstr[64];\n  if (!msg->raw.s) return;\n\n  fprintf(stdout, \":Uuid: %02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx\"\n          \"-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\\n\",\n          msg->uuid.s[0], msg->uuid.s[1], msg->uuid.s[2], msg->uuid.s[3],\n          msg->uuid.s[4], msg->uuid.s[5], msg->uuid.s[6], msg->uuid.s[7],\n          msg->uuid.s[8], msg->uuid.s[9], msg->uuid.s[10], msg->uuid.s[11],\n          msg->uuid.s[12], msg->uuid.s[13], msg->uuid.s[14], msg->uuid.s[15]);\n  fprintf(stdout, \":Timestamp: \");\n\n  time_t t = floor(msg->timestamp / 1e9);\n  double frac = msg->timestamp - t * 1e9;\n  struct tm *tms = gmtime(&t);\n  strftime(tstr, sizeof(tstr) - 1, \"%Y-%m-%dT%H:%M:%S\", tms);\n  fprintf(stdout, \"%s.%09lldZ\\n\", tstr, (long long)frac);\n  output_cs(\":Type\", &msg->type, true);\n  output_cs(\":Logger\", &msg->logger, true);\n  fprintf(stdout, \":Severity: %d\\n\", msg->severity);\n  output_cs(\":Payload\", &msg->payload, true);\n  output_cs(\":EnvVersion\", &msg->env_version, true);\n  if (msg->pid == INT_MIN) {\n    fprintf(stdout, \":Pid: <nil>\\n\");\n  } else {\n    fprintf(stdout, \":Pid: %d\\n\", msg->pid);\n  }\n  output_cs(\":Hostname\", &msg->hostname, true);\n  fprintf(stdout, \":Fields:\\n\");\n  for (int i = 0; i < msg->fields_len; ++i) {\n    fprintf(stdout, \"    | name: %.*s type: %d \", (int)msg->fields[i].name.len,\n            msg->fields[i].name.s, msg->fields[i].value_type);\n    output_cs(\"representation\", &msg->fields[i].representation, false);\n    fprintf(stdout, \" value: \");\n    const char *p = msg->fields[i].value.s;\n    const char *e = msg->fields[i].value.s + msg->fields[i].value.len;\n    switch (msg->fields[i].value_type) {\n    case LSB_PB_STRING:\n      {\n        lsb_const_string cs;\n        int tag = 0;\n        int wiretype = 0;\n        while (p && p < e) {\n          p = lsb_pb_read_key(p, &tag, &wiretype);\n          p = read_string(wiretype, p, e, &cs);\n          if (p) {\n            fprintf(stdout, \"%.*s\", (int)cs.len, cs.s);\n            if (p < e) fprintf(stdout, \"|\");\n          }\n        }\n      }\n      break;\n    case LSB_PB_BYTES:\n      {\n        lsb_const_string cs;\n        int tag = 0;\n        int wiretype = 0;\n        while (p && p < e) {\n          p = lsb_pb_read_key(p, &tag, &wiretype);\n          p = read_string(wiretype, p, e, &cs);\n          if (p) {\n            for (size_t i = 0; i < cs.len; ++i) {\n              if (isprint(cs.s[i])) {\n                if (cs.s[i] == '\\\\') {\n                  fwrite(\"\\\\\\\\\", 2, 1, stdout);\n                } else {\n                  putchar(cs.s[i]);\n                }\n              } else {\n                fprintf(stdout, \"\\\\x%02hhx\", (unsigned char)cs.s[i]);\n              }\n            }\n            if (p < e) fprintf(stdout, \"|\");\n          }\n        }\n      }\n      break;\n    case LSB_PB_INTEGER:\n      {\n        long long ll = 0;\n        while (p && p < e) {\n          p = lsb_pb_read_varint(p, e, &ll);\n          if (p) {\n            fprintf(stdout, \"%lld\", ll);\n            if (p < e) fprintf(stdout, \"|\");\n          }\n        }\n      }\n      break;\n    case LSB_PB_DOUBLE:\n      {\n        double d;\n        for (int i = 0; p <= (e - sizeof(double)); p += sizeof(double), ++i) {\n          memcpy(&d, p, sizeof(double));\n          if (i > 0) fprintf(stdout, \"|\");\n          fprintf(stdout, \"%.17g\", d);\n        }\n      }\n      break;\n    case LSB_PB_BOOL:\n      {\n        long long ll = 0;\n        while (p && p < e) {\n          p = lsb_pb_read_varint(p, e, &ll);\n          if (p) {\n            fprintf(stdout, \"%s\", ll == 0 ? \"false\" : \"true\");\n            if (p < e) fprintf(stdout, \"|\");\n          }\n        }\n      }\n      break;\n    }\n    fprintf(stdout, \"\\n\");\n  }\n  fprintf(stdout, \"\\n\");\n  return;\n}\n\n\nstatic void output_heka(lsb_heka_message *msg)\n{\n  static char header[LSB_MIN_HDR_SIZE];\n  size_t hlen = lsb_write_heka_header(header, msg->raw.len);\n  if (fwrite(header, hlen, 1, stdout) != 1) {\n    log_cb(NULL, NULL, 0, \"error outputting header\");\n    exit(1);\n  }\n  if (fwrite(msg->raw.s, msg->raw.len, 1, stdout) != 1) {\n    log_cb(NULL, NULL, 0, \"error outputting message\");\n    exit(1);\n  }\n  return;\n}\n\n\nstatic size_t read_file(FILE *fh, lsb_input_buffer *ib)\n{\n  size_t need;\n  if (ib->msglen) {\n    need = ib->msglen + (size_t)ib->buf[ib->scanpos + 1] + LSB_HDR_FRAME_SIZE\n        - (ib->readpos - ib->scanpos);\n  } else {\n    need = ib->scanpos + ib->size - ib->readpos;\n  }\n\n  if (lsb_expand_input_buffer(ib, need)) {\n    log_cb(NULL, NULL, 0, \"buffer reallocation failed\");\n    exit(EXIT_FAILURE);\n  }\n  size_t cnt = ib->size - ib->readpos;\n  size_t nread = fread(ib->buf + ib->readpos,\n                       1,\n                       cnt,\n                       fh);\n  ib->readpos += nread;\n  if (cnt != nread) {\n    clearerr(fh);\n  }\n  return nread;\n}\n\n\nstatic int find_header(const char *cur, int clen, const char *prev, int num)\n{\n  static int cnt = 0;\n  for (int i = clen - 1; i >= 0; --i) {\n    if (cur[i] == 0x1e) {\n      unsigned char hlen;\n      if (i + 1 < clen) {\n        hlen = (unsigned char)cur[i + 1];\n      } else {\n        hlen = (unsigned char)prev[0];\n      }\n\n      char flag;\n      int hend = i + 2;\n      if (hend < clen) {\n        flag = cur[hend];\n      } else {\n        flag = prev[hend - clen];\n      }\n\n      if (flag != 0x08) {\n        continue;\n      }\n\n      hend += hlen;\n      if (hend < clen) {\n        flag = cur[hend];\n      } else {\n        flag = prev[hend - clen];\n      }\n\n      if (flag == 0x1f) {\n        if (++cnt == num) {\n          return i;\n        }\n      }\n    }\n  }\n  return -1;\n}\n\n\nstatic void move_to_offset(FILE *fh, int num)\n{\n  char buf[2][BUFSIZ];\n  memset(buf, 0, sizeof(buf));\n  char *cur = buf[0];\n  char *prev = buf[1];\n  char *tmp;\n\n  fseek(fh, 0, SEEK_END);\n  long len = ftell(fh);\n  if (len < 0) {\n    log_cb(NULL, NULL, 0, \"ftell failed\");\n  }\n  size_t consume = len > BUFSIZ ? BUFSIZ : len;\n  size_t pos = len - consume;\n  while (consume > 0) {\n    if (fseek(fh, pos, SEEK_SET)) {\n      log_cb(NULL, NULL, 0, \"fseek failed (reading)\");\n      break;\n    }\n    if (fread(cur, consume, 1, fh) != 1) {\n      log_cb(NULL, NULL, 0, \"fread failed\");\n      break;\n    }\n\n    int loc = find_header(cur, consume, prev, num);\n    if (loc >= 0) {\n      if (fseek(fh, -(consume - loc), SEEK_CUR)) {\n        log_cb(NULL, NULL, 0, \"fseek failed (find position)\");\n      }\n      return;\n    }\n\n    if (pos >= consume) {\n      pos -= consume;\n    } else {\n      consume = pos;\n      pos = 0;\n    }\n\n    tmp = cur;\n    cur = prev;\n    prev = tmp;\n  }\n  fseek(fh, 0, SEEK_SET);\n}\n\n\nint main(int argc, char **argv)\n{\n  bool argerr     = false;\n  bool follow     = false;\n  bool use_stdin  = false;\n  long num        = -1;\n  char *matcher   = \"TRUE\";\n  char *filename  = NULL;\n\n  output_function ofn = output_text;\n\n  int c;\n  while ((c = getopt(argc, argv, \"tchfn:m:\")) != -1) {\n    switch (c) {\n    case 't':\n      ofn = output_text;\n      break;\n    case 'c':\n      ofn = NULL;\n      break;\n    case 'h':\n      ofn = output_heka;\n      break;\n    case 'f':\n      follow = true;\n      break;\n    case 'n':\n      num = strtol(optarg, NULL, 10);\n      if (num < 0) argerr = true;\n      break;\n    case 'm':\n      matcher = optarg;\n      break;\n    default:\n      argerr = true;\n      break;\n    }\n  }\n\n  if (argc - optind == 1) {\n    filename = argv[optind];\n    use_stdin = strcmp(\"-\", filename) == 0;\n  } else {\n    argerr = true;\n  }\n\n  if (argerr) {\n    log_cb(NULL, NULL, 0,\n           \"usage: %s [-t|-c|-h] [-m message_matcher] [-f] [-n #] <FILE>\\n\"\n           \"description:\\n\"\n           \"  -t output the messages in text format (default)\\n\"\n           \"  -c only output the message count\\n\"\n           \"  -h output the messages as a Heka protobuf stream\\n\"\n           \"  -f output appended data as the file grows\\n\"\n           \"  -n output the last # of messages (simple header check so not \"\n           \"100%% accurate)\\n\"\n           \"  -m message_matcher expression (default \\\"TRUE\\\")\\n\"\n           \"  FILE name of the file to cat or '-' for stdin\\n\"\n           \"notes:\\n\"\n           \"  All output is written to stdout and all log/error messages are \"\n           \"written to stderr.\\n\",\n           argv[0]);\n    return EXIT_FAILURE;\n  }\n\n  char ms[strlen(matcher) + 1];\n  size_t len = sizeof(ms);\n  lsb_message_matcher *mm = lsb_create_message_matcher(\n      lsb_lua_string_unescape(ms, matcher, &len));\n  if (!mm) {\n    log_cb(NULL, NULL, 0, \"invalid message matcher: %s\", matcher);\n    return EXIT_FAILURE;\n  }\n\n  FILE *fh = stdin;\n  if (!use_stdin) {\n    fh = fopen(filename, \"r\");\n    if (!fh) {\n      log_cb(NULL, NULL, 0, \"error opening: %s\", filename);\n      return EXIT_FAILURE;\n    }\n    if (num >= 0) {\n      move_to_offset(fh, num);\n    }\n  }\n\n  size_t discarded_bytes;\n  size_t bytes_read = 0;\n  size_t pcnt = 0;\n  size_t mcnt = 0;\n\n  lsb_input_buffer ib;\n  lsb_init_input_buffer(&ib, 1024 * 1024 * 1024);\n  lsb_heka_message msg;\n  lsb_init_heka_message(&msg, 8);\n\n  do {\n    if (lsb_find_heka_message(&msg, &ib, true, &discarded_bytes, &logger)) {\n      if (lsb_eval_message_matcher(mm, &msg)) {\n        if (ofn) {\n          ofn(&msg);\n        }\n        ++mcnt;\n      }\n      ++pcnt;\n    } else {\n      bytes_read = read_file(fh, &ib);\n    }\n    if (bytes_read == 0 && follow && !use_stdin) {\n      sleep(1);\n    }\n  } while (bytes_read > 0 || follow);\n\n  lsb_free_heka_message(&msg);\n  lsb_free_input_buffer(&ib);\n  lsb_destroy_message_matcher(mm);\n  if (!use_stdin) {\n    fclose(fh);\n  }\n\n  if (ofn) {\n    log_cb(NULL, NULL, 0, \"Processed: %zu, matched: %zu messages\\n\", pcnt,\n           mcnt);\n  } else {\n    printf(\"Processed: %zu, matched: %zu messages\\n\", pcnt, mcnt);\n  }\n}\n"
  },
  {
    "path": "src/heka/CMakeLists.txt",
    "content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nset(HEKA_SRC\nmessage.c\nread_message_zc.c\nsandbox.c\nstream_reader.c\n)\n\nadd_library(luasandboxheka SHARED ${HEKA_SRC})\nset_target_properties(luasandboxheka PROPERTIES VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} SOVERSION 0)\ntarget_compile_definitions(luasandboxheka PRIVATE -Dluasandboxheka_EXPORTS)\ntarget_link_libraries(luasandboxheka luasandbox)\nif(WIN32)\n  target_link_libraries(luasandboxheka ws2_32)\nendif()\n\nif(LIBM_LIBRARY)\n  target_link_libraries(luasandboxheka ${LIBM_LIBRARY})\nendif()\n\ninstall(TARGETS luasandboxheka DESTINATION ${CMAKE_INSTALL_LIBDIR})\nadd_subdirectory(test)\n"
  },
  {
    "path": "src/heka/message.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Lua sandbox Heka protobuf serialization/deserialization @file */\n\n#include \"message_impl.h\"\n\n#include <limits.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include \"../luasandbox_impl.h\" // todo the API should change so this doesn't\n// need access to the impl\n\n#include \"luasandbox.h\"\n#include \"luasandbox/lauxlib.h\"\n#include \"luasandbox_output.h\"\n#include \"sandbox_impl.h\"\n#include \"luasandbox/util/heka_message.h\"\n#include \"luasandbox/util/output_buffer.h\"\n#include \"luasandbox/util/protobuf.h\"\n#include \"../luasandbox_defines.h\"\n\n\nstatic void set_missing_headers(lua_State *lua, int idx, lsb_heka_sandbox *hsb)\n{\n  lua_getfield(lua, idx, LSB_LOGGER);\n  int t = lua_type(lua, -1);\n  lua_pop(lua, 1);\n  if (t == LUA_TNIL && hsb->name) {\n    lua_pushstring(lua, hsb->name);\n    lua_setfield(lua, idx, LSB_LOGGER);\n  }\n\n  lua_getfield(lua, idx, LSB_HOSTNAME);\n  t = lua_type(lua, -1);\n  lua_pop(lua, 1);\n  if (t == LUA_TNIL && hsb->hostname) {\n    lua_pushstring(lua, hsb->hostname);\n    lua_setfield(lua, idx, LSB_HOSTNAME);\n  }\n\n  lua_getfield(lua, idx, LSB_PID);\n  t = lua_type(lua, -1);\n  lua_pop(lua, 1);\n  if (t == LUA_TNIL) {\n    lua_pushinteger(lua, hsb->pid);\n    lua_setfield(lua, idx, LSB_PID);\n  }\n}\n\n\nstatic const char* read_string(lua_State *lua,\n                               int wiretype,\n                               const char *p,\n                               const char *e)\n{\n  if (wiretype != LSB_PB_WT_LENGTH) {\n    return NULL;\n  }\n\n  long long len = 0;\n  p = lsb_pb_read_varint(p, e, &len);\n  if (!p || len < 0 || len > e - p) {\n    return NULL;\n  }\n  lua_pushlstring(lua, p, (size_t)len);\n  p += len;\n  return p;\n}\n\n\nstatic const char* process_varint(lua_State *lua,\n                                  const char *name,\n                                  int wiretype,\n                                  int stack_index,\n                                  const char *p,\n                                  const char *e)\n{\n  if (wiretype != LSB_PB_WT_VARINT) {\n    return NULL;\n  }\n  long long val = 0;\n  p = lsb_pb_read_varint(p, e, &val);\n  if (!p) {\n    return NULL;\n  }\n  lua_pushnumber(lua, (lua_Number)val);\n  lua_setfield(lua, stack_index, name);\n  return p;\n}\n\n\nstatic const char* process_fields(lua_State *lua, const char *p, const char *e)\n{\n  int tag = 0;\n  int wiretype = 0;\n  int has_name = 0;\n  int value_count = 0;\n  long long len = 0;\n\n  p = lsb_pb_read_varint(p, e, &len);\n  if (!p || len < 0 || len > e - p) {\n    return NULL;\n  }\n  e = p + len; // only process to the end of the current field record\n\n  lua_newtable(lua); // Table to be added to the Fields array index 4\n  lua_newtable(lua); // Table to hold the value(s) index 5\n  do {\n    p = lsb_pb_read_key(p, &tag, &wiretype);\n\n    switch (tag) {\n    case 1:\n      p = read_string(lua, wiretype, p, e);\n      if (p) {\n        lua_setfield(lua, 4, \"name\");\n        has_name = 1;\n      }\n      break;\n\n    case 2:\n      p = process_varint(lua, \"value_type\", wiretype, 4, p, e);\n      break;\n\n    case 3:\n      p = read_string(lua, wiretype, p, e);\n      if (p) {\n        lua_setfield(lua, 4, \"representation\");\n      }\n      break;\n\n    case 4: // value_string\n    case 5: // value_bytes\n      p = read_string(lua, wiretype, p, e);\n      if (p) {\n        lua_rawseti(lua, 5, ++value_count);\n      }\n      break;\n\n    case 6: // value_integer\n      {\n        long long val = 0;\n        switch (wiretype) {\n        case 0:\n          p = lsb_pb_read_varint(p, p + len, &val);\n          if (!p) break;\n          lua_pushnumber(lua, (lua_Number)val);\n          lua_rawseti(lua, 5, ++value_count);\n          break;\n        case 2:\n          p = lsb_pb_read_varint(p, e, &len);\n          if (!p || len < 0 || len > e - p) {\n            p = NULL;\n            break;\n          }\n          do {\n            p = lsb_pb_read_varint(p, p + len, &val);\n            if (!p) break;\n            lua_pushnumber(lua, (lua_Number)val);\n            lua_rawseti(lua, 5, ++value_count);\n          } while (p < e);\n          break;\n        default:\n          p = NULL;\n          break;\n        }\n      }\n      break;\n\n    case 7: // value_double\n      {\n        double val = 0;\n        switch (wiretype) {\n        case 1:\n          if (p + sizeof(double) > e) {\n            p = NULL;\n            break;\n          }\n          memcpy(&val, p, sizeof(double));\n          p += sizeof(double);\n          lua_pushnumber(lua, val);\n          lua_rawseti(lua, 5, ++value_count);\n          break;\n        case 2:\n          p = lsb_pb_read_varint(p, e, &len);\n          if (!p || len < 0 || len > e - p || len % sizeof(double) != 0) {\n            p = NULL;\n            break;\n          }\n          do {\n            memcpy(&val, p, sizeof(double));\n            p += sizeof(double);\n            lua_pushnumber(lua, val);\n            lua_rawseti(lua, 5, ++value_count);\n          } while (p < e);\n          break;\n        default:\n          p = NULL;\n          break;\n        }\n      }\n      break;\n\n    case 8: // value_bool\n      {\n        long long val = 0;\n        switch (wiretype) {\n        case 0:\n          p = lsb_pb_read_varint(p, p + len, &val);\n          if (!p) break;\n          lua_pushboolean(lua, (int)val);\n          lua_rawseti(lua, 5, ++value_count);\n          break;\n        case 2:\n          p = lsb_pb_read_varint(p, e, &len);\n          if (!p || len < 0 || len > e - p) {\n            p = NULL;\n            break;\n          }\n          do {\n            p = lsb_pb_read_varint(p, p + len, &val);\n            if (!p) break;\n            lua_pushboolean(lua, (int)val);\n            lua_rawseti(lua, 5, ++value_count);\n          } while (p < e);\n          break;\n        default:\n          p = NULL;\n          break;\n        }\n      }\n      break;\n    default:\n      p = NULL; // don't allow unknown tags\n      break;\n    }\n  } while (p && p < e);\n\n  lua_setfield(lua, 4, \"value\");\n\n  return has_name ? p : NULL;\n}\n\n\n/**\n * Retrieve the string value for a Lua table entry (the table should be on top\n * of the stack).  If the entry is not found or not a string nothing is encoded.\n *\n * @param lua Pointer to the lua_State.\n * @param ob  Pointer to the output data buffer.\n * @param tag Field identifier.\n * @param name Key used for the Lua table entry lookup.\n * @param index Lua stack index of the table.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nstatic lsb_err_value\nencode_string(lua_State *lua, lsb_output_buffer *ob, char tag, const char *name,\n              int index)\n{\n  lsb_err_value ret = NULL;\n  lua_getfield(lua, index, name);\n  if (lua_isstring(lua, -1)) {\n    size_t len;\n    const char *s = lua_tolstring(lua, -1, &len);\n    ret = lsb_pb_write_string(ob, tag, s, len);\n  }\n  lua_pop(lua, 1);\n  return ret;\n}\n\n\n/**\n * Retrieve the numeric value for a Lua table entry (the table should be on top\n * of the stack).  If the entry is not found or not a number nothing is encoded,\n * otherwise the number is varint encoded.\n *\n * @param lua Pointer to the lua_State.\n * @param ob  Pointer to the output data buffer.\n * @param tag Field identifier.\n * @param name Key used for the Lua table entry lookup.\n * @param index Lua stack index of the table.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nstatic lsb_err_value\nencode_int(lua_State *lua, lsb_output_buffer *ob, char tag, const char *name,\n           int index)\n{\n  lsb_err_value ret = NULL;\n  lua_getfield(lua, index, name);\n  if (lua_isnumber(lua, -1)) {\n    unsigned long long i = (unsigned long long)lua_tonumber(lua, -1);\n    ret = lsb_pb_write_key(ob, tag, LSB_PB_WT_VARINT);\n    if (!ret) ret = lsb_pb_write_varint(ob, i);\n  }\n  lua_pop(lua, 1);\n  return ret;\n}\n\n\n/**\n * Encodes the field value.\n *\n * @param lsb  Pointer to the sandbox.\n * @param lua Pointer to the lua_State.\n * @param ob  Pointer to the output data buffer.\n * @param first Flag set on the first field value to add\n *              additional protobuf data in the correct order.\n *              In the case of arrays the value should contain\n *              the number of items in the array.\n * @param representation String representation of the field\n *                       i.e., \"ms\"\n * @param value_type Protobuf value type\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nstatic lsb_err_value\nencode_field_value(lsb_lua_sandbox *lsb, lua_State *lua, lsb_output_buffer *ob,\n                   int first, const char *representation, int value_type);\n\n\n/**\n * Encodes a field that has an array of values.\n *\n * @param lsb  Pointer to the sandbox.\n * @param lua Pointer to the lua_State.\n * @param ob  Pointer to the output data buffer.\n * @param t Lua type of the array values.\n * @param representation String representation of the field i.e., \"ms\"\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nstatic lsb_err_value\nencode_field_array(lsb_lua_sandbox *lsb, lua_State *lua, lsb_output_buffer *ob,\n                   int t, const char *representation, int value_type)\n{\n  int alen = (int)lua_objlen(lua, -2);\n  lsb_err_value ret = encode_field_value(lsb, lua, ob, alen, representation,\n                                         value_type);\n  size_t len_pos = ob->pos;\n  lua_pop(lua, 1);\n  for (int idx = 2; !ret && idx <= alen; ++idx) {\n    lua_rawgeti(lua, -1, idx);\n    if (lua_type(lua, -1) != t) {\n      snprintf(lsb->error_message, LSB_ERROR_SIZE, \"array has mixed types\");\n      return LSB_ERR_HEKA_INPUT;\n    }\n    ret = encode_field_value(lsb, lua, ob, 0, representation, value_type);\n    lua_pop(lua, 1);\n  }\n  if (!ret && alen > 1 && value_type == LSB_PB_INTEGER) {\n    // fix up the varint packed length\n    size_t i = len_pos - 2;\n    int y = 0;\n    // find the length byte\n    while (ob->buf[i] != 0 && y < LSB_MAX_VARINT_BYTES) {\n      --i;\n      ++y;\n    }\n    if (y == LSB_MAX_VARINT_BYTES) {\n      snprintf(lsb->error_message, LSB_ERROR_SIZE,\n               \"unable set the length of the packed integer array\");\n      return LSB_ERR_LUA;\n    }\n    ret = lsb_pb_update_field_length(ob, i);\n  }\n  return ret;\n}\n\n\n/**\n * Encodes a field that contains metadata in addition to its value.\n *\n * @param lsb  Pointer to the sandbox.\n * @param lua Pointer to the lua_State.\n * @param ob  Pointer to the output data buffer.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nstatic lsb_err_value\nencode_field_object(lsb_lua_sandbox *lsb, lua_State *lua, lsb_output_buffer *ob)\n{\n  const char *representation = NULL;\n  lua_getfield(lua, -1, \"representation\");\n  if (lua_isstring(lua, -1)) {\n    representation = lua_tostring(lua, -1);\n  }\n\n  int value_type = -1;\n  lua_getfield(lua, -2, \"value_type\");\n  if (lua_isnumber(lua, -1)) {\n    value_type = (int)lua_tointeger(lua, -1);\n  }\n\n  lua_getfield(lua, -3, \"value\");\n  lsb_err_value ret = encode_field_value(lsb, lua, ob, 1, representation,\n                                         value_type);\n  lua_pop(lua, 3); // remove representation, value_type and  value\n  return ret;\n}\n\n\nstatic lsb_err_value\nencode_field_value(lsb_lua_sandbox *lsb, lua_State *lua, lsb_output_buffer *ob,\n                   int first, const char *representation, int value_type)\n{\n  lsb_err_value ret = NULL;\n  size_t len;\n  const char *s;\n\n  int t = lua_type(lua, -1);\n  switch (t) {\n  case LUA_TSTRING:\n    switch (value_type) {\n    case -1: // not specified defaults to string\n      value_type = 0;\n    case 0:\n    case 1:\n      break;\n    default:\n      snprintf(lsb->error_message, LSB_ERROR_SIZE,\n               \"invalid string value_type: %d\", value_type);\n      return LSB_ERR_HEKA_INPUT;\n    }\n    if (first) { // this uglyness keeps the protobuf fields in order without\n                 // additional lookups\n      if (value_type == LSB_PB_BYTES) {\n        ret = lsb_pb_write_key(ob, LSB_PB_VALUE_TYPE, LSB_PB_WT_VARINT);\n        if (!ret) ret = lsb_pb_write_varint(ob, value_type);\n        if (ret) return ret;\n      }\n      if (representation) {\n        ret = lsb_pb_write_string(ob, LSB_PB_REPRESENTATION, representation,\n                                  strlen(representation));\n        if (ret) return ret;\n      }\n    }\n    s = lua_tolstring(lua, -1, &len);\n    if (value_type == LSB_PB_BYTES) {\n      ret = lsb_pb_write_string(ob, LSB_PB_VALUE_BYTES, s, len);\n      if (ret) return ret;\n    } else {\n      ret = lsb_pb_write_string(ob, LSB_PB_VALUE_STRING, s, len);\n      if (ret) return ret;\n    }\n    break;\n  case LUA_TNUMBER:\n    switch (value_type) {\n    case -1: // not specified defaults to double\n      value_type = 3;\n    case 2:\n    case 3:\n      break;\n    default:\n      snprintf(lsb->error_message, LSB_ERROR_SIZE,\n               \"invalid numeric value_type: %d\", value_type);\n      return LSB_ERR_HEKA_INPUT;\n    }\n    if (first) {\n      ret = lsb_pb_write_key(ob, LSB_PB_VALUE_TYPE, LSB_PB_WT_VARINT);\n      if (!ret) ret = lsb_pb_write_varint(ob, value_type);\n      if (ret) return ret;\n\n      if (representation) {\n        ret = lsb_pb_write_string(ob, LSB_PB_REPRESENTATION, representation,\n                                  strlen(representation));\n        if (ret) return ret;\n      }\n      if (1 == first) {\n        if (value_type == LSB_PB_INTEGER) {\n          ret = lsb_pb_write_key(ob, LSB_PB_VALUE_INTEGER, LSB_PB_WT_VARINT);\n        } else {\n          ret = lsb_pb_write_key(ob, LSB_PB_VALUE_DOUBLE, LSB_PB_WT_FIXED64);\n        }\n        if (ret) return ret;\n      } else { // pack array\n        if (value_type == LSB_PB_INTEGER) {\n          ret = lsb_pb_write_key(ob, LSB_PB_VALUE_INTEGER, LSB_PB_WT_LENGTH);\n          if (!ret) ret = lsb_pb_write_varint(ob, 0); // length tbd later\n        } else {\n          ret = lsb_pb_write_key(ob, LSB_PB_VALUE_DOUBLE, LSB_PB_WT_LENGTH);\n          if (!ret) ret = lsb_pb_write_varint(ob, first * sizeof(double));\n        }\n        if (ret) return ret;\n      }\n    }\n    if (value_type == LSB_PB_INTEGER) {\n      ret = lsb_pb_write_varint(ob, lua_tointeger(lua, -1));\n    } else {\n      ret = lsb_pb_write_double(ob, lua_tonumber(lua, -1));\n    }\n    if (ret) return ret;\n    break;\n\n  case LUA_TBOOLEAN:\n    if (value_type != -1 && value_type != LSB_PB_BOOL) {\n      snprintf(lsb->error_message, LSB_ERROR_SIZE,\n               \"invalid boolean value_type: %d\", value_type);\n      return LSB_ERR_HEKA_INPUT;\n    }\n    if (first) {\n      ret = lsb_pb_write_key(ob, LSB_PB_VALUE_TYPE, LSB_PB_WT_VARINT);\n      if (!ret) ret = lsb_pb_write_varint(ob, LSB_PB_BOOL);\n      if (ret) return ret;\n\n      if (representation) {\n        ret = lsb_pb_write_string(ob, LSB_PB_REPRESENTATION, representation,\n                                  strlen(representation));\n        if (ret) return ret;\n      }\n      if (1 == first) {\n        ret = lsb_pb_write_key(ob, LSB_PB_VALUE_BOOL, LSB_PB_WT_VARINT);\n      } else {\n        ret = lsb_pb_write_key(ob, LSB_PB_VALUE_BOOL, LSB_PB_WT_LENGTH);\n        if (!ret) ret = lsb_pb_write_varint(ob, first);\n      }\n      if (ret) return ret;\n    }\n    ret = lsb_pb_write_bool(ob, lua_toboolean(lua, -1));\n    break;\n\n  case LUA_TTABLE:\n    {\n      lua_rawgeti(lua, -1, 1);\n      int t = lua_type(lua, -1);\n      switch (t) {\n      case LUA_TNIL:\n        lua_pop(lua, 1); // remove the array test value\n        ret = encode_field_object(lsb, lua, ob);\n        break;\n      case LUA_TNUMBER:\n      case LUA_TSTRING:\n      case LUA_TBOOLEAN:\n        ret = encode_field_array(lsb, lua, ob, t, representation, value_type);\n        break;\n      default:\n        lua_pop(lua, 1); // remove the array test value\n        snprintf(lsb->error_message, LSB_ERROR_SIZE,\n                 \"unsupported array type: %s\", lua_typename(lua, t));\n        return LSB_ERR_LUA;\n      }\n    }\n    break;\n\n  case LUA_TLIGHTUSERDATA:\n    lua_getfield(lua, -4, \"userdata\");\n    if (lua_type(lua, -1) != LUA_TUSERDATA) {\n      snprintf(lsb->error_message, LSB_ERROR_SIZE,\n               \"a lightuserdata output must also specify a userdata value\");\n      return LSB_ERR_LUA;\n    }\n    // fall thru\n\n  case LUA_TUSERDATA:\n    {\n      lua_CFunction fp = lsb_get_output_function(lua, -1);\n      size_t len_pos = 0;\n      if (!fp) {\n        snprintf(lsb->error_message, LSB_ERROR_SIZE,\n                 \"userdata object does not implement lsb_output\");\n        return LSB_ERR_LUA;\n      }\n      if (first) {\n        ret = lsb_pb_write_key(ob, LSB_PB_VALUE_TYPE, LSB_PB_WT_VARINT);\n        if (ret) return ret;\n\n        // encode userdata as a byte array\n        ret = lsb_pb_write_varint(ob, LSB_PB_BYTES);\n        if (ret) return ret;\n\n        if (representation) {\n          ret = lsb_pb_write_string(ob, LSB_PB_REPRESENTATION, representation,\n                                    strlen(representation));\n          if (ret) return ret;\n        }\n      }\n\n      ret = lsb_pb_write_key(ob, LSB_PB_VALUE_BYTES, LSB_PB_WT_LENGTH);\n      if (ret) return ret;\n\n      len_pos = ob->pos;\n      ret = lsb_pb_write_varint(ob, 0);  // length tbd later\n      if (ret) return ret;\n\n      lua_pushlightuserdata(lua, ob);\n      int result = fp(lua);\n      lua_pop(lua, 1); // remove output function\n      if (result) {\n        snprintf(lsb->error_message, LSB_ERROR_SIZE,\n                 \"userdata output callback failed: %d\", result);\n        return LSB_ERR_LUA;\n      }\n      ret = lsb_pb_update_field_length(ob, len_pos);\n    }\n    if (t == LUA_TLIGHTUSERDATA) lua_pop(lua, 1); // remove the userdata\n    break;\n\n  default:\n    snprintf(lsb->error_message, LSB_ERROR_SIZE, \"unsupported type: %s\",\n             lua_typename(lua, t));\n    return LSB_ERR_LUA;\n  }\n  return ret;\n}\n\n\n/**\n * Iterates over the specified Lua table encoding the contents as user defined\n * message fields.\n *\n * @param lsb  Pointer to the sandbox.\n * @param lua Pointer to the lua_State\n * @param ob  Pointer to the output data buffer.\n * @param tag Field identifier.\n * @param name Key used for the Lua table entry lookup.\n * @param index Lua stack index of the table.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nstatic lsb_err_value\nencode_fields(lsb_lua_sandbox *lsb, lua_State *lua, lsb_output_buffer *ob,\n              char tag, const char *name, int index)\n{\n  lsb_err_value ret = NULL;\n  lua_getfield(lua, index, name);\n  if (!lua_istable(lua, -1)) {\n    return ret;\n  }\n\n  lua_rawgeti(lua, -1, 1); // test for the array notation\n  size_t len_pos, len;\n  if (lua_istable(lua, -1)) {\n    int i = 1;\n    do {\n      ret = lsb_pb_write_key(ob, tag, LSB_PB_WT_LENGTH);\n      if (ret) return ret;\n\n      len_pos = ob->pos;\n      ret = lsb_pb_write_varint(ob, 0);  // length tbd later\n      if (ret) return ret;\n\n      lua_getfield(lua, -1, \"name\");\n      if (lua_isstring(lua, -1)) {\n        const char *s = lua_tolstring(lua, -1, &len);\n        ret = lsb_pb_write_string(ob, LSB_PB_NAME, s, len);\n      } else {\n        snprintf(lsb->error_message, LSB_ERROR_SIZE,\n                 \"field name must be a string\");\n        ret = LSB_ERR_HEKA_INPUT;\n      }\n      lua_pop(lua, 1); // remove the name\n      if (ret) return ret;\n\n      ret = encode_field_object(lsb, lua, ob);\n      if (!ret) ret = lsb_pb_update_field_length(ob, len_pos);\n      if (ret) return ret;\n\n      lua_pop(lua, 1); // remove the current field object\n      lua_rawgeti(lua, -1, ++i); // grab the next field object\n    } while (!ret && !lua_isnil(lua, -1));\n  } else {\n    lua_pop(lua, 1); // remove the array test value\n    lua_checkstack(lua, 2);\n    lua_pushnil(lua);\n    while (lua_next(lua, -2) != 0) {\n      ret = lsb_pb_write_key(ob, tag, LSB_PB_WT_LENGTH);\n      if (ret) return ret;\n\n      len_pos = ob->pos;\n      ret = lsb_pb_write_varint(ob, 0);  // length tbd later\n      if (ret) return ret;\n\n      if (lua_isstring(lua, -2)) {\n        const char *s = lua_tolstring(lua, -2, &len);\n        ret = lsb_pb_write_string(ob, LSB_PB_NAME, s, len);\n      } else {\n        snprintf(lsb->error_message, LSB_ERROR_SIZE,\n                 \"field name must be a string\");\n        ret = LSB_ERR_HEKA_INPUT;\n      }\n      if (ret) return ret;\n\n      ret = encode_field_value(lsb, lua, ob, 1, NULL, -1);\n      if (!ret) ret = lsb_pb_update_field_length(ob, len_pos);\n      if (ret) return ret;\n\n      lua_pop(lua, 1); // Remove the value leaving the key on top for\n                       // the next interation.\n    }\n  }\n  lua_pop(lua, 1); // remove the fields table\n  return ret;\n}\n\n\nint heka_decode_message(lua_State *lua)\n{\n  int n = lua_gettop(lua);\n  luaL_argcheck(lua, n == 1, n, \"incorrect number of arguments\");\n\n  size_t len;\n  const char *pbstr;\n  int t = lua_type(lua, 1);\n  if (t == LUA_TSTRING) {\n    pbstr = lua_tolstring(lua, 1, &len);\n  } else if (t == LUA_TUSERDATA) {\n    lua_CFunction fp = lsb_get_zero_copy_function(lua, 1);\n    if (!fp) {\n      return luaL_argerror(lua, 1, \"no zero copy support\");\n    }\n    int results = fp(lua);\n    if (results != 2 || lua_type(lua, 2) != LUA_TLIGHTUSERDATA) {\n      return luaL_error(lua, \"invalid zero copy return\");\n    }\n    pbstr = lua_touserdata(lua, 2);\n    len = (size_t)lua_tointeger(lua, 3);\n    lua_pop(lua, results);\n  } else {\n    return luaL_typerror(lua, 1, \"string or userdata\");\n  }\n\n  if (!pbstr || len < 20) {\n    return luaL_error(lua, \"invalid message, too short\");\n  }\n\n  const char *p = pbstr;\n  const char *lp = p;\n  const char *e = pbstr + len;\n  int wiretype = 0;\n  int tag = 0;\n  int has_uuid = 0;\n  int has_timestamp = 0;\n  int field_count = 0;\n\n  lua_newtable(lua); // message table index 2\n  do {\n    p = lsb_pb_read_key(p, &tag, &wiretype);\n\n    switch (tag) {\n    case 1:\n      p = read_string(lua, wiretype, p, e);\n      if (p && p - lp == 18) {\n        lua_setfield(lua, 2, \"Uuid\");\n        has_uuid = 1;\n      } else {\n        p = NULL;\n      }\n      break;\n\n    case 2:\n      p = process_varint(lua, \"Timestamp\", wiretype, 2, p, e);\n      if (p) {\n        has_timestamp = 1;\n      }\n      break;\n\n    case 3:\n      p = read_string(lua, wiretype, p, e);\n      if (p) {\n        lua_setfield(lua, 2, \"Type\");\n      }\n      break;\n\n    case 4:\n      p = read_string(lua, wiretype, p, e);\n      if (p) {\n        lua_setfield(lua, 2, \"Logger\");\n      }\n      break;\n\n    case 5:\n      p = process_varint(lua, \"Severity\", wiretype, 2, p, e);\n      break;\n\n    case 6:\n      p = read_string(lua, wiretype, p, e);\n      if (p) {\n        lua_setfield(lua, 2, \"Payload\");\n      }\n      break;\n\n    case 7:\n      p = read_string(lua, wiretype, p, e);\n      if (p) {\n        lua_setfield(lua, 2, \"EnvVersion\");\n      }\n      break;\n\n    case 8:\n      p = process_varint(lua, \"Pid\", wiretype, 2, p, e);\n      break;\n\n    case 9:\n      p = read_string(lua, wiretype, p, e);\n      if (p) {\n        lua_setfield(lua, 2, \"Hostname\");\n      }\n      break;\n\n    case 10:\n      if (wiretype != 2) {\n        p = NULL;\n        break;\n      }\n      if (field_count == 0) {\n        lua_newtable(lua); // Fields table index 3\n      }\n      p = process_fields(lua, p, e);\n      if (p) {\n        lua_rawseti(lua, 3, ++field_count);\n      }\n      break;\n\n    default:\n      p = NULL; // don't allow unknown tags\n      break;\n    }\n    if (p) lp = p;\n  } while (p && p < e);\n\n  if (!p) {\n    return luaL_error(lua, \"error in tag: %d wiretype: %d offset: %d\", tag,\n                      wiretype, (const char *)lp - pbstr);\n  }\n\n  if (!has_uuid || !has_timestamp) {\n    return luaL_error(lua, \"missing required field uuid: %s timestamp: %s\",\n                      has_uuid ? \"found\" : \"not found\",\n                      has_timestamp ? \"found\" : \"not found\");\n  }\n\n  if (field_count) {\n    lua_setfield(lua, 2, \"Fields\");\n  }\n\n  return 1;\n}\n\n\nint heka_encode_message(lua_State *lua)\n{\n  int n = lua_gettop(lua);\n  bool framed = false;\n\n  switch (n) {\n  case 2:\n    luaL_checktype(lua, 2, LUA_TBOOLEAN);\n    framed = lua_toboolean(lua, 2);\n    // fall thru\n  case 1:\n    luaL_checktype(lua, 1, LUA_TTABLE);\n    break;\n  default:\n    return luaL_argerror(lua, n, \"incorrect number of arguments\");\n  }\n\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_THIS_PTR);\n  lsb_lua_sandbox *lsb = lua_touserdata(lua, -1);\n  lua_pop(lua, 1); // remove this ptr\n  if (!lsb) return luaL_error(lua, \"encode_message() invalid \" LSB_THIS_PTR);\n\n  lsb->output.pos = 0;\n  lsb_err_value ret = heka_encode_message_table(lsb, lua, 1);\n  if (ret) {\n    const char *err = lsb_get_error(lsb);\n    if (strlen(err) == 0) err = ret;\n    return luaL_error(lua, \"encode_message() failed: %s\", err);\n  }\n\n  size_t len = 0;\n  const char *output = lsb_get_output(lsb, &len);\n  lsb->usage[LSB_UT_OUTPUT][LSB_US_CURRENT] = len;\n\n  if (framed) {\n    char header[LSB_MIN_HDR_SIZE];\n    size_t hlen = lsb_write_heka_header(header, len);\n    lsb->usage[LSB_UT_OUTPUT][LSB_US_CURRENT] = len + hlen;\n    luaL_Buffer b;\n    luaL_buffinit(lua, &b);\n    luaL_addlstring(&b, header, hlen);\n    luaL_addlstring(&b, output, len);\n    luaL_pushresult(&b);\n  } else {\n    lua_pushlstring(lua, output, len);\n  }\n\n  if (lsb->usage[LSB_UT_OUTPUT][LSB_US_CURRENT]\n      > lsb->usage[LSB_UT_OUTPUT][LSB_US_MAXIMUM]) {\n    lsb->usage[LSB_UT_OUTPUT][LSB_US_MAXIMUM] =\n        lsb->usage[LSB_UT_OUTPUT][LSB_US_CURRENT];\n  }\n  return 1;\n}\n\n\nlsb_err_value\nheka_encode_message_table(lsb_lua_sandbox *lsb, lua_State *lua, int idx)\n{\n  lsb_heka_sandbox *hsb = lsb_get_parent(lsb);\n  lsb_err_value ret = NULL;\n  lsb_output_buffer *ob = &lsb->output;\n  ob->pos = 0;\n\n  long long ts;\n  if (hsb->restricted_headers) {\n    ret = lsb_write_heka_uuid(ob, NULL, 0);\n    if (ret) return ret;\n    ts = lsb_get_timestamp();\n    lua_pushstring(lua, hsb->name);\n    lua_setfield(lua, idx, LSB_LOGGER);\n    lua_pushstring(lua, hsb->hostname);\n    lua_setfield(lua, idx, LSB_HOSTNAME);\n    lua_pushinteger(lua, hsb->pid);\n    lua_setfield(lua, idx, LSB_PID);\n  } else {\n    lua_getfield(lua, idx, LSB_UUID);\n    size_t len;\n    const char *uuid = lua_tolstring(lua, -1, &len);\n    ret = lsb_write_heka_uuid(ob, uuid, len);\n    lua_pop(lua, 1); // remove uuid\n\n    lua_getfield(lua, idx, LSB_TIMESTAMP);\n    if (lua_isnumber(lua, -1)) {\n      ts = (long long)lua_tonumber(lua, -1);\n    } else {\n      ts = lsb_get_timestamp();\n    }\n    lua_pop(lua, 1); // remove timestamp\n    set_missing_headers(lua, idx, hsb);\n  }\n\n  ret = lsb_pb_write_key(ob, LSB_PB_TIMESTAMP, LSB_PB_WT_VARINT);\n  if (!ret) ret = lsb_pb_write_varint(ob, ts);\n  if (!ret) ret = encode_string(lua, ob, LSB_PB_TYPE, LSB_TYPE, idx);\n  if (!ret) ret = encode_string(lua, ob, LSB_PB_LOGGER, LSB_LOGGER, idx);\n  if (!ret) ret = encode_int(lua, ob, LSB_PB_SEVERITY, LSB_SEVERITY, idx);\n  if (!ret) ret = encode_string(lua, ob, LSB_PB_PAYLOAD, LSB_PAYLOAD, idx);\n  if (!ret) ret = encode_string(lua, ob, LSB_PB_ENV_VERSION, LSB_ENV_VERSION,\n                                idx);\n  if (!ret) ret = encode_int(lua, ob, LSB_PB_PID, LSB_PID, idx);\n  if (!ret) ret = encode_string(lua, ob, LSB_PB_HOSTNAME, LSB_HOSTNAME, idx);\n  if (!ret) ret = encode_fields(lsb, lua, ob, LSB_PB_FIELDS, LSB_FIELDS, idx);\n  if (!ret) ret = lsb_expand_output_buffer(ob, 1);\n  ob->buf[ob->pos] = 0; // prevent possible overrun if treated as a string\n  return ret;\n}\n\n\nint heka_read_message(lua_State *lua, lsb_heka_message *m)\n{\n  int n = lua_gettop(lua);\n  if (n < 1 || n > 3) {\n    return luaL_error(lua, \"%s() incorrect number of arguments\", __func__);\n  }\n  size_t field_len;\n  const char *field = luaL_checklstring(lua, 1, &field_len);\n  int fi = luaL_optint(lua, 2, 0);\n  luaL_argcheck(lua, fi >= 0, 2, \"field index must be >= 0\");\n  int ai = luaL_optint(lua, 3, 0);\n  luaL_argcheck(lua, ai >= 0, 3, \"array index must be >= 0\");\n\n  if (!m || !m->raw.s) {\n    lua_pushnil(lua);\n    return 1;\n  }\n\n  if (strcmp(field, LSB_UUID) == 0) {\n    if (m->uuid.s) {\n      lua_pushlstring(lua, m->uuid.s, m->uuid.len);\n    } else {\n      lua_pushnil(lua);\n    }\n  } else if (strcmp(field, LSB_TIMESTAMP) == 0) {\n    lua_pushnumber(lua, (lua_Number)m->timestamp);\n  } else if (strcmp(field, LSB_TYPE) == 0) {\n    if (m->type.s) {\n      lua_pushlstring(lua, m->type.s, m->type.len);\n    } else {\n      lua_pushnil(lua);\n    }\n  } else if (strcmp(field, LSB_LOGGER) == 0) {\n    if (m->logger.s) {\n      lua_pushlstring(lua, m->logger.s, m->logger.len);\n    } else {\n      lua_pushnil(lua);\n    }\n  } else if (strcmp(field, LSB_SEVERITY) == 0) {\n    lua_pushinteger(lua, m->severity);\n  } else if (strcmp(field, LSB_PAYLOAD) == 0) {\n    if (m->payload.s) {\n      lua_pushlstring(lua, m->payload.s, m->payload.len);\n    } else {\n      lua_pushnil(lua);\n    }\n  } else if (strcmp(field, LSB_ENV_VERSION) == 0) {\n    if (m->env_version.s) {\n      lua_pushlstring(lua, m->env_version.s, m->env_version.len);\n    } else {\n      lua_pushnil(lua);\n    }\n  } else if (strcmp(field, LSB_PID) == 0) {\n    if (m->pid == INT_MIN) {\n      lua_pushnil(lua);\n    } else {\n      lua_pushinteger(lua, m->pid);\n    }\n  } else if (strcmp(field, LSB_HOSTNAME) == 0) {\n    if (m->hostname.s) {\n      lua_pushlstring(lua, m->hostname.s, m->hostname.len);\n    } else {\n      lua_pushnil(lua);\n    }\n  } else if (strcmp(field, \"raw\") == 0) {\n    lua_pushlstring(lua, m->raw.s, m->raw.len);\n  } else if (strcmp(field, \"framed\") == 0) {\n    {\n      char header[LSB_MIN_HDR_SIZE];\n      size_t hlen = lsb_write_heka_header(header, m->raw.len);\n      luaL_Buffer b;\n      luaL_buffinit(lua, &b);\n      luaL_addlstring(&b, header, hlen);\n      luaL_addlstring(&b, m->raw.s, m->raw.len);\n      luaL_pushresult(&b);\n    }\n  } else if (strcmp(field, \"size\") == 0) {\n    lua_pushnumber(lua, (lua_Number)m->raw.len);\n  } else {\n    if (field_len >= 8\n        && memcmp(field, LSB_FIELDS \"[\", 7) == 0\n        && field[field_len - 1] == ']') {\n      lsb_read_value v;\n      lsb_const_string f = { .s = field + 7, .len = field_len - 8 };\n      lsb_read_heka_field(m, &f, fi, ai, &v);\n      switch (v.type) {\n      case LSB_READ_STRING:\n        lua_pushlstring(lua, v.u.s.s, v.u.s.len);\n        break;\n      case LSB_READ_NUMERIC:\n        lua_pushnumber(lua, v.u.d);\n        break;\n      case LSB_READ_BOOL:\n        lua_pushboolean(lua, v.u.d ? 1 : 0);\n        break;\n      default:\n        lua_pushnil(lua);\n        break;\n      }\n    } else {\n      luaL_error(lua, \"%s() field: '%s' not supported/recognized\", __func__,\n                 field);\n    }\n  }\n  return 1;\n}\n"
  },
  {
    "path": "src/heka/message_impl.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Hindsight/Heka message matcher @file */\n\n#ifndef luasandbox_heka_sandbox_message_impl_h_\n#define luasandbox_heka_sandbox_message_impl_h_\n\n#include <stdbool.h>\n\n#include \"luasandbox.h\"\n#include \"luasandbox/util/heka_message.h\"\n\n// these functions are intentionally not exported\n\n/**\n * Deserialize a Heka message protobuf string into a Lua table structure.\n *\n * @param lua Pointer the Lua state.\n *\n * @return int Number of items on the stack (1  table) or throws an error on\n *         failure\n */\nint heka_decode_message(lua_State *lua);\n\n/**\n * Serialize a Lua table structure into a Heka message protobuf string.\n *\n * @param lua Pointer the Lua state.\n *\n * @return int Number of items on the stack (1  string) or throws an error on\n *         failure\n */\nint heka_encode_message(lua_State *lua);\n\n/**\n * Serialize a Lua table structure into a Heka message protobuf (using the\n * sandbox output buffer, Called indirectly from inject_message so the output\n * buffer can be used without round tripping the resulting data back to the\n * sandbox with heka_encode_message.\n *\n * @param lsb Pointer to the sandbox.\n * @param lua Pointer to the lua_State.\n * @param idx Lua stack index of the message table.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nlsb_err_value\nheka_encode_message_table(lsb_lua_sandbox *lsb, lua_State *lua, int idx);\n\n\n/**\n * Breakout of the common code for the read_message API\n *\n * @param lua Pointer to the lua_State\n * @param m Heka message to extract the data from\n *\n * @return int Number of items on the stack (1 value) or throws an error on\n *         failure\n */\nint heka_read_message(lua_State *lua, lsb_heka_message *m);\n\n#endif\n"
  },
  {
    "path": "src/heka/read_message_zc.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Lua Heka read message zero copy references @file */\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"../luasandbox_defines.h\"\n#include \"lauxlib.h\"\n#include \"lua.h\"\n#include \"lualib.h\"\n#include \"luasandbox/heka/sandbox.h\"\n#include \"luasandbox/util/heka_message.h\"\n#include \"luasandbox_output.h\"\n#include \"luasandbox_serialize.h\"\n\nstatic const char *metatable_name = \"lsb.read_message_zc\";\n\ntypedef struct read_message_zc\n{\n  lsb_const_string name;\n  int              fi;\n  int              ai;\n  char             field[];\n} read_message_zc;\n\n\nstatic const lsb_heka_message* get_heka_message(lua_State *lua)\n{\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_HEKA_THIS_PTR);\n  lsb_heka_sandbox *hsb = lua_touserdata(lua, -1);\n  lua_pop(lua, 1); // remove this ptr\n  if (!hsb) {\n    luaL_error(lua, \"invalid \" LSB_HEKA_THIS_PTR);\n  }\n  return lsb_heka_get_message(hsb);\n}\n\n\nstatic lsb_const_string read_message(lua_State *lua, read_message_zc *zc)\n{\n  lsb_const_string ret = { NULL, 0 };\n  const lsb_heka_message *m = get_heka_message(lua);\n  if (!m || !m->raw.s) {\n    return ret;\n  }\n\n  if (strcmp(zc->name.s, LSB_RAW) == 0) {\n    if (m->raw.s) ret = m->raw;\n  } else if (strcmp(zc->name.s, LSB_PAYLOAD) == 0) {\n    if (m->payload.s) ret = m->payload;\n  } else if (strcmp(zc->name.s, LSB_LOGGER) == 0) {\n    if (m->logger.s) ret = m->logger;\n  } else if (strcmp(zc->name.s, LSB_TYPE) == 0) {\n    if (m->type.s) ret = m->type;\n  } else if (strcmp(zc->name.s, LSB_ENV_VERSION) == 0) {\n    if (m->env_version.s) ret = m->env_version;\n  } else if (strcmp(zc->name.s, LSB_HOSTNAME) == 0) {\n    if (m->hostname.s) ret = m->hostname;\n  } else if (strcmp(zc->name.s, LSB_UUID) == 0) {\n    if (m->uuid.s) ret = m->uuid;\n  } else if (zc->name.len >= 8\n             && memcmp(zc->name.s, LSB_FIELDS \"[\", 7) == 0\n             && zc->name.s[zc->name.len - 1] == ']') {\n    lsb_read_value v;\n    lsb_const_string f = { zc->name.s + 7, zc->name.len - 8 };\n    lsb_read_heka_field(m, &f, zc->fi, zc->ai, &v);\n    if (v.type == LSB_READ_STRING) {\n      ret = v.u.s;\n    } else if (v.type != LSB_READ_NIL) {\n      luaL_error(lua, \"%s() zc->name.s: '%s' contains an unsupported type\",\n                 __func__, zc->name.s);\n    }\n  } else {\n    luaL_error(lua, \"%s() zc->name.s: '%s' not supported/recognized\", __func__,\n               zc->name.s);\n  }\n  return ret;\n}\n\n\nstatic int zc_output(lua_State *lua)\n{\n  lsb_output_buffer *ob = lua_touserdata(lua, -1);\n  if (!ob) {return 1;}\n  read_message_zc *zc = luaL_checkudata(lua, -2, metatable_name);\n  lsb_const_string f = read_message(lua, zc);\n  if (!f.s) return 0;\n\n  if (strcmp(zc->field, LSB_FRAMED) == 0) {\n    char header[LSB_MIN_HDR_SIZE];\n    size_t hlen = lsb_write_heka_header(header, f.len);\n    if (lsb_outputs(ob, header, hlen)) return 1;\n  }\n  if (lsb_outputs(ob, f.s, f.len)) return 1;\n  return 0;\n}\n\n\nstatic int zc_return(lua_State *lua)\n{\n  read_message_zc *zc = luaL_checkudata(lua, -1, metatable_name);\n  lua_checkstack(lua, 3);\n  int cnt = 2;\n  lsb_const_string f = read_message(lua, zc);\n  if (strcmp(zc->field, LSB_FRAMED) == 0) {\n    char header[LSB_MIN_HDR_SIZE];\n    size_t hlen = lsb_write_heka_header(header, f.len);\n    lua_pushlstring(lua, header, hlen);\n    ++cnt;\n  }\n  lua_pushlightuserdata(lua, (void *)f.s);\n  lua_pushinteger(lua, (int)f.len);\n  return cnt;\n}\n\n\nstatic int zc_tostring(lua_State *lua)\n{\n  read_message_zc *zc = luaL_checkudata(lua, -1, metatable_name);\n  lsb_const_string f = read_message(lua, zc);\n  if (f.s) {\n    if (strcmp(zc->field, LSB_FRAMED) == 0) {\n      char header[LSB_MIN_HDR_SIZE];\n      size_t hlen = lsb_write_heka_header(header, f.len);\n      lua_pushlstring(lua, header, hlen);\n      lua_pushlstring(lua, f.s, f.len);\n      lua_concat(lua, 2);\n    } else {\n      lua_pushlstring(lua, f.s, f.len);\n    }\n  } else {\n    lua_pushnil(lua);\n  }\n  return 1;\n}\n\n\nstatic const struct luaL_reg zclib_m[] =\n{\n  { \"__tostring\", zc_tostring },\n  { NULL, NULL }\n};\n\n\nint heka_create_read_message_zc(lua_State *lua)\n{\n  size_t len;\n  const char *field = luaL_checklstring(lua, 1, &len);\n  int fi = luaL_optint(lua, 2, 0);\n  luaL_argcheck(lua, fi >= 0, 2, \"field index must be >= 0\");\n  int ai = luaL_optint(lua, 3, 0);\n  luaL_argcheck(lua, ai >= 0, 3, \"array index must be >= 0\");\n\n  if (!(strcmp(field, LSB_UUID) == 0\n        || strcmp(field, LSB_TYPE) == 0\n        || strcmp(field, LSB_LOGGER) == 0\n        || strcmp(field, LSB_PAYLOAD) == 0\n        || strcmp(field, LSB_ENV_VERSION) == 0\n        || strcmp(field, LSB_HOSTNAME) == 0\n        || strcmp(field, LSB_RAW) == 0\n        || strcmp(field, LSB_FRAMED) == 0\n        || (len >= 8\n            && memcmp(field, LSB_FIELDS \"[\", 7) == 0\n            && field[len - 1] == ']'))) {\n    luaL_error(lua, \"%s() field: '%s' not supported/recognized\", __func__,\n               field);\n  }\n\n  if (luaL_newmetatable(lua, metatable_name) == 1) {\n    lua_newtable(lua);\n    lsb_add_output_function(lua, zc_output);\n    lsb_add_zero_copy_function(lua, zc_return);\n    lua_replace(lua, LUA_ENVIRONINDEX);\n\n    lua_pushvalue(lua, -1);\n    lua_setfield(lua, -2, \"__index\");\n    luaL_register(lua, NULL, zclib_m);\n  }\n\n  read_message_zc *zc = lua_newuserdata(lua, sizeof(read_message_zc) + len + 1);\n  zc->fi = fi;\n  zc->ai = ai;\n  memcpy(zc->field, field, len + 1);\n  if (strcmp(field, LSB_FRAMED) == 0) {\n    zc->name.s = LSB_RAW;\n    zc->name.len = sizeof(LSB_RAW) - 1;\n  } else {\n    zc->name.s = zc->field;\n    zc->name.len = len;\n  }\n\n  lua_pushvalue(lua, -2);\n  lua_setmetatable(lua, -2);\n  return 1;\n}\n"
  },
  {
    "path": "src/heka/sandbox.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Heka sandbox implementation @file */\n\n#include \"luasandbox/heka/sandbox.h\"\n\n#include <errno.h>\n#include <math.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../luasandbox_defines.h\"\n#include \"../luasandbox_impl.h\"\n#include \"luasandbox.h\"\n#include \"luasandbox/lualib.h\"\n#include \"luasandbox/heka/stream_reader.h\"\n#include \"luasandbox/util/heka_message_matcher.h\"\n#include \"luasandbox/util/protobuf.h\"\n#include \"luasandbox/util/running_stats.h\"\n#include \"luasandbox_output.h\"\n#include \"message_impl.h\"\n#include \"sandbox_impl.h\"\n\n#ifdef _WIN32\n#include <winsock2.h>\n#else\n#include <unistd.h>\n#endif\n\nlsb_err_id LSB_ERR_HEKA_INPUT = \"invalid input\";\n\nstatic const char *pm_func_name = \"process_message\";\nstatic const char *im_func_name = \"inject_message\";\nstatic const char *lsb_heka_message_matcher = \"lsb.heka_message_matcher\";\n\nint heka_create_stream_reader(lua_State *lua);\nint heka_create_read_message_zc(lua_State *lua);\n\n\nstatic int is_running(lua_State *lua)\n{\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_HEKA_THIS_PTR);\n  lsb_heka_sandbox *hsb = lua_touserdata(lua, -1);\n  lua_pop(lua, 1); // remove this ptr\n  if (!hsb) {\n    return luaL_error(lua, \"%s() invalid \" LSB_HEKA_THIS_PTR, __func__);\n  }\n  // call inject_message with a NULL message/checkpoint (special case\n  // synchronization point)\n  if (hsb->cb.iim(hsb->parent, NULL, 0, NAN, NULL) != 0) {\n    return luaL_error(lua, \"%s() failed: rejected by the callback\", __func__);\n  }\n  lua_pushboolean(lua, lsb_heka_is_running(hsb));\n  return 1;\n}\n\n\nstatic int read_message(lua_State *lua)\n{\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_HEKA_THIS_PTR);\n  lsb_heka_sandbox *hsb = lua_touserdata(lua, -1);\n  lua_pop(lua, 1); // remove this ptr\n  if (!hsb) {\n    return luaL_error(lua, \"%s() invalid \" LSB_HEKA_THIS_PTR, __func__);\n  }\n  if (lua_gettop(lua) == 4) {\n    luaL_checktype(lua, 4, LUA_TBOOLEAN);\n    if (lua_toboolean(lua, 4)) {\n      return heka_create_read_message_zc(lua);\n    }\n    lua_pop(lua, 1); // remove the zc flag\n  }\n  return heka_read_message(lua, hsb->msg);\n}\n\n\nstatic lsb_message_matcher* mm_check(lua_State *lua)\n{\n  lsb_message_matcher **ppmm = luaL_checkudata(lua, 1,\n                                               lsb_heka_message_matcher);\n  return *ppmm;\n}\n\n\nstatic int mm_gc(lua_State *lua)\n{\n  lsb_message_matcher *mm = mm_check(lua);\n  lsb_destroy_message_matcher(mm);\n  return 0;\n}\n\n\nstatic int mm_eval(lua_State *lua)\n{\n  lsb_message_matcher *mm = mm_check(lua);\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_HEKA_THIS_PTR);\n  lsb_heka_sandbox *hsb = lua_touserdata(lua, -1);\n  lua_pop(lua, 1); // remove this ptr\n  if (!hsb) {\n    return luaL_error(lua, \"%s() invalid \" LSB_HEKA_THIS_PTR, __func__);\n  }\n  if (!hsb->msg || !hsb->msg->raw.s) {\n    return luaL_error(lua, \"no active message\");\n  }\n  lua_pushboolean(lua, lsb_eval_message_matcher(mm, hsb->msg));\n  return 1;\n}\n\n\nstatic int mm_create(lua_State *lua)\n{\n  const char *exp = luaL_checkstring(lua, 1);\n  lsb_message_matcher **ppmm = lua_newuserdata(lua, sizeof*ppmm);\n  if (luaL_newmetatable(lua, lsb_heka_message_matcher) == 1) {\n    lua_pushvalue(lua, -1);\n    lua_setfield(lua, -2, \"__index\");\n    lua_pushcfunction(lua, mm_gc);\n    lua_setfield(lua, -2, \"__gc\");\n    lua_pushcfunction(lua, mm_eval);\n    lua_setfield(lua, -2, \"eval\");\n  }\n  lua_setmetatable(lua, -2);\n\n  *ppmm = lsb_create_message_matcher(exp);\n  if (!*ppmm) {\n    return luaL_error(lua, \"invalid message matcher expression\");\n  }\n  return 1;\n}\n\n\nstatic int inject_message_input(lua_State *lua)\n{\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_THIS_PTR);\n  lsb_lua_sandbox *lsb = lua_touserdata(lua, -1);\n  lua_pop(lua, 1); // remove this ptr\n  if (!lsb) {\n    return luaL_error(lua, \"%s() invalid \" LSB_THIS_PTR, im_func_name);\n  }\n\n  const char *scp =  NULL;\n  double ncp = NAN;\n  int t = lua_type(lua, 2);\n  switch (t) {\n  case LUA_TNUMBER:\n    ncp = lua_tonumber(lua, 2);\n    break;\n  case LUA_TSTRING:\n    scp = lua_tostring(lua, 2);\n    break;\n  case LUA_TNONE:\n  case LUA_TNIL:\n    break;\n  default:\n    return luaL_error(lua, \"%s() unsupported checkpoint type: %s\", im_func_name,\n                      lua_typename(lua, t));\n  }\n\n  lsb_const_string output;\n  t = lua_type(lua, 1);\n  switch (t) {\n  case LUA_TUSERDATA:\n    {\n      heka_stream_reader *hsr = luaL_checkudata(lua, 1,\n                                                LSB_HEKA_STREAM_READER);\n      if (hsr->msg.raw.s) {\n        output.len = hsr->msg.raw.len;\n        output.s = hsr->msg.raw.s;\n      } else {\n        return luaL_error(lua, \"%s() attempted to inject a nil message\",\n                          im_func_name);\n      }\n    }\n    break;\n  case LUA_TSTRING:\n    {\n      lsb_heka_message m;\n      lsb_init_heka_message(&m, 8);\n      output.s = lua_tolstring(lua, 1, &output.len);\n      bool ok = lsb_decode_heka_message(&m, output.s, output.len, NULL);\n      lsb_free_heka_message(&m);\n      if (!ok) {\n        return luaL_error(lua, \"%s() attempted to inject a invalid protobuf \"\n                          \"string\", im_func_name);\n      }\n    }\n    break;\n  case LUA_TTABLE:\n    if (heka_encode_message_table(lsb, lua, 1)) {\n      const char *err = lsb_get_error(lsb);\n      if (strlen(err) == 0) err = \"exceeded output_limit\";\n      return luaL_error(lua, \"%s() failed: %s\", im_func_name, err);\n    }\n    output.len = 0;\n    output.s = lsb_get_output(lsb, &output.len);\n    break;\n  case LUA_TNIL:\n    if (lua_isnoneornil(lua, 2)) {\n      return luaL_error(lua, \"%s() message cannot be nil without a checkpoint\"\n                        \" update\", im_func_name);\n    }\n    output.len = 0;\n    output.s = NULL;\n    break;\n  default:\n    return luaL_error(lua, \"%s() unsupported message type: %s\",\n                      im_func_name, lua_typename(lua, t));\n  }\n\n  lsb_heka_sandbox *hsb = lsb_get_parent(lsb);\n  int rv = hsb->cb.iim(hsb->parent, output.s, output.len, ncp, scp);\n  switch (rv) {\n  case LSB_HEKA_IM_SUCCESS:\n    break;\n  case LSB_HEKA_IM_CHECKPOINT:\n    return luaL_error(lua, \"%s() failed: checkpoint update\",\n                      im_func_name);\n  case LSB_HEKA_IM_ERROR:\n    // fall through\n  default:\n    return luaL_error(lua, \"%s() failed: rejected by the callback rv: %d\",\n                      im_func_name, rv);\n  }\n  if (output.s) {\n    ++hsb->stats.im_cnt;\n    hsb->stats.im_bytes += output.len;\n  }\n  return 0;\n}\n\n\nstatic int inject_message_analysis(lua_State *lua)\n{\n  luaL_checktype(lua, 1, LUA_TTABLE);\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_THIS_PTR);\n  lsb_lua_sandbox *lsb = lua_touserdata(lua, -1);\n  lua_pop(lua, 1); // remove this ptr\n  if (!lsb) return luaL_error(lua, \"%s() invalid \" LSB_THIS_PTR, im_func_name);\n\n  if (heka_encode_message_table(lsb, lua, 1)) {\n    return luaL_error(lua, \"%s() failed: %s\", im_func_name, lsb_get_error(lsb));\n  }\n\n  size_t output_len = 0;\n  const char *output = lsb_get_output(lsb, &output_len);\n  lsb_heka_sandbox *hsb = lsb_get_parent(lsb);\n  int rv = hsb->cb.aim(hsb->parent, output, output_len);\n  switch (rv) {\n  case LSB_HEKA_IM_SUCCESS:\n    break;\n  case LSB_HEKA_IM_LIMIT:\n    return luaL_error(lua, \"%s() failed: injection limit exceeded\",\n                      im_func_name);\n  case LSB_HEKA_IM_ERROR:\n    // fall through\n  default:\n    return luaL_error(lua, \"%s() failed: rejected by the callback rv: %d\",\n                      im_func_name, rv);\n  }\n  ++hsb->stats.im_cnt;\n  hsb->stats.im_bytes += output_len;\n  return 0;\n}\n\n\nstatic int inject_payload(lua_State *lua)\n{\n  static const char *default_type = \"txt\";\n\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_THIS_PTR);\n  lsb_lua_sandbox *lsb = lua_touserdata(lua, -1);\n  lua_pop(lua, 1); // remove this ptr\n  if (!lsb) return luaL_error(lua, \"%s() invalid \" LSB_THIS_PTR, __func__);\n\n  int n = lua_gettop(lua);\n\n  if (n > 0) {\n    if (lua_type(lua, 1) != LUA_TSTRING) {\n      return luaL_error(lua, \"%s() payload_type argument must be a string\",\n                        __func__);\n    }\n  }\n\n  if (n > 1) {\n    if (lua_type(lua, 2) != LUA_TSTRING) {\n      return luaL_error(lua, \"%s() payload_name argument must be a string\",\n                        __func__);\n    }\n  }\n\n  if (n > 2) {\n    lsb_output_coroutine(lsb, lua, 3, n, 1);\n    lua_pop(lua, n - 2);\n  }\n  size_t len = 0;\n  const char *output = lsb_get_output(lsb, &len);\n  if (!len) return 0;\n\n  // build up a heka message table\n  lua_createtable(lua, 0, 2); // message\n  lua_createtable(lua, 0, 2); // Fields\n  if (n > 0) {\n    lua_pushvalue(lua, 1);\n  } else {\n    lua_pushstring(lua, default_type);\n  }\n  lua_setfield(lua, -2, \"payload_type\");\n\n  if (n > 1) {\n    lua_pushvalue(lua, 2);\n    lua_setfield(lua, -2, \"payload_name\");\n  }\n  lua_setfield(lua, -2, LSB_FIELDS);\n  lua_pushstring(lua, \"inject_payload\");\n  lua_setfield(lua, -2, LSB_TYPE);\n  lua_pushlstring(lua, output, len);\n  lua_setfield(lua, -2, LSB_PAYLOAD);\n  if (lua_gettop(lua) > 1) lua_replace(lua, 1);\n\n  inject_message_analysis(lua);\n  return 0;\n}\n\n\nstatic int update_checkpoint(lua_State *lua)\n{\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_HEKA_THIS_PTR);\n  lsb_heka_sandbox *hsb = lua_touserdata(lua, -1);\n  lua_pop(lua, 1); // remove this ptr\n  if (!hsb) {\n    return luaL_error(lua, \"%s() invalid \" LSB_HEKA_THIS_PTR, __func__);\n  }\n\n  int result = 0;\n  int n = lua_gettop(lua);\n  switch (n) {\n  case 2: // async case\n    luaL_checktype(lua, 2, LUA_TNUMBER);\n    hsb->stats.pm_failures += (unsigned long long)lua_tonumber(lua, 2);\n    // fall thru\n  case 1:\n    luaL_checktype(lua, 1, LUA_TLIGHTUSERDATA);\n    result = hsb->ucp(hsb->parent, lua_touserdata(lua, 1));\n    break;\n  case 0: // batch case\n    result = hsb->ucp(hsb->parent, NULL);\n    break;\n  default:\n    return luaL_error(lua, \"%s() invalid number of args: %d\", __func__, n);\n  }\n  if (result) {\n    return luaL_error(lua, \"%s() failed: rejected by the callback\", __func__);\n  }\n  return result;\n}\n\n\nstatic void set_restrictions(lua_State *lua, lsb_heka_sandbox *hsb)\n{\n  static const char *io[] = {\n    NULL, \"\", \"dofile\", \"load\", \"loadfile\", \"loadstring\", \"newproxy\",\n    NULL, \"os\", \"exit\", \"setlocale\",\n    NULL, \"string\", \"dump\"\n  };\n\n  static const char *analysis[] = {\n    NULL, \"\", \"collectgarbage\", \"dofile\", \"load\", \"loadfile\", \"loadstring\",\n    \"newproxy\", \"print\",\n    NULL, \"os\", \"getenv\", \"execute\", \"exit\", \"remove\", \"rename\", \"setlocale\",\n    \"tmpname\",\n    NULL, \"string\", \"dump\"\n  };\n\n  const char **list;\n  size_t list_size;\n\n  lua_pushlightuserdata(lua, hsb);\n  lua_setfield(lua, LUA_REGISTRYINDEX, LSB_HEKA_THIS_PTR);\n\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_CONFIG_TABLE);\n  switch (hsb->type) {\n  case 'i':\n  case 'o':\n    list_size = sizeof(io) / sizeof(*io);\n    list = io;\n    break;\n  default:\n    list_size = sizeof(analysis) / sizeof(*analysis);\n    list = analysis;\n    lua_newtable(lua);\n    lua_pushboolean(lua, true);\n    lua_setfield(lua, -2, LUA_IOLIBNAME);\n    lua_pushboolean(lua, true);\n    lua_setfield(lua, -2, LUA_COLIBNAME);\n    lua_setfield(lua, 1, \"disable_modules\");\n    break;\n  }\n\n  lua_newtable(lua);\n  for (unsigned i = 0, j = 1; i < list_size; ++i) {\n    if (list[i]) {\n      lua_pushstring(lua, list[i]);\n      lua_rawseti(lua, -2, j++);\n    } else {\n      if (lua_gettop(lua) == 3) lua_pop(lua, 1); // remove the previous list\n      lua_newtable(lua);\n      lua_pushvalue(lua, -1);\n      lua_setfield(lua, -3, list[++i]);\n      j = 1;\n    }\n  }\n  lua_pop(lua, 1); // remove the last list\n  lua_setfield(lua, 1, \"remove_entries\");\n\n  lua_getfield(lua, 1, LSB_HEKA_MAX_MESSAGE_SIZE);\n  if (lua_type(lua, -1) != LUA_TNUMBER || lua_tointeger(lua, -1) <= 0) {\n    lua_pushnumber(lua, 64 * 1024);\n    lua_setfield(lua, 1, LSB_HEKA_MAX_MESSAGE_SIZE);\n  }\n  lua_pop(lua, 1); // remove max_message_size\n\n  lua_getfield(lua, 1, LSB_LOGGER);\n  size_t len;\n  const char *tmp = lua_tolstring(lua, -1, &len);\n  if (tmp) {\n    hsb->name = malloc(len + 1);\n    if (hsb->name) strcpy(hsb->name, tmp);\n  }\n  lua_pop(lua, 1); // remove the Logger\n\n  lua_getfield(lua, 1, LSB_HOSTNAME);\n  tmp = lua_tolstring(lua, -1, &len);\n  if (tmp) {\n    hsb->hostname = malloc(len + 1);\n    if (hsb->hostname) strcpy(hsb->hostname, tmp);\n  } else {\n    char hostname[256] = { 0 };\n    if (gethostname(hostname, sizeof hostname)) {\n      hostname[sizeof hostname - 1] = 0;\n    }\n    len = strlen(hostname);\n    hsb->hostname = malloc(len + 1);\n    if (hsb->hostname) strcpy(hsb->hostname, hostname);\n  }\n  lua_pop(lua, 1); // remove the Hostname\n\n  lua_getfield(lua, 1, LSB_PID);\n  hsb->pid = (int)lua_tointeger(lua, -1);\n  lua_pop(lua, 1);\n\n  lua_getfield(lua, 1, \"restricted_headers\");\n  if (lua_type(lua, -1) == LUA_TBOOLEAN) {\n    hsb->restricted_headers = lua_toboolean(lua, -1);\n  }\n  lua_pop(lua, 1); // remove the restricted_headers boolean\n\n  lua_pop(lua, 1); // remove the lsb_config table\n}\n\n\nlsb_heka_sandbox* lsb_heka_create_input(void *parent,\n                                        const char *lua_file,\n                                        const char *state_file,\n                                        const char *lsb_cfg,\n                                        lsb_logger *logger,\n                                        lsb_heka_im_input im)\n{\n  if (!lua_file) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 3, \"lua_file must be specified\");\n    }\n    return NULL;\n  }\n\n  if (!im) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 3, \"inject_message callback must \"\n                 \"be specified\");\n    }\n    return NULL;\n  }\n\n  lsb_heka_sandbox *hsb = calloc(1, sizeof(lsb_heka_sandbox));\n  if (!hsb) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 3, \"memory allocation failed\");\n    }\n    return NULL;\n  }\n\n  hsb->type = 'i';\n  hsb->parent = parent;\n  hsb->msg = NULL;\n  hsb->cb.iim = im;\n  hsb->name = NULL;\n  hsb->hostname = NULL;\n\n  hsb->lsb = lsb_create(hsb, lua_file, lsb_cfg, logger);\n  if (!hsb->lsb) {\n    free(hsb);\n    return NULL;\n  }\n\n  lua_State *lua = lsb_get_lua(hsb->lsb);\n  set_restrictions(lua, hsb);\n\n  lsb_add_function(hsb->lsb, heka_decode_message, \"decode_message\");\n  lsb_add_function(hsb->lsb, inject_message_input, \"inject_message\");\n// inject_payload is intentionally excluded from input plugins\n// you can construct whatever you need with inject_message\n  lsb_add_function(hsb->lsb, heka_create_stream_reader, \"create_stream_reader\");\n  lsb_add_function(hsb->lsb, is_running, \"is_running\");\n\n  if (lsb_init(hsb->lsb, state_file)) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, hsb->name, 3, \"%s\", lsb_get_error(hsb->lsb));\n    }\n    lsb_destroy(hsb->lsb);\n    free(hsb->hostname);\n    free(hsb->name);\n    free(hsb);\n    return NULL;\n  }\n\n// remove output function\n  lua_pushnil(lua);\n  lua_setglobal(lua, \"output\");\n\n  return hsb;\n}\n\n\nstatic int process_message(lsb_heka_sandbox *hsb, lsb_heka_message *msg,\n                           lua_State *lua, int nargs, bool profile)\n{\n  unsigned long long start, end;\n\n  hsb->msg = msg;\n  if (profile) {\n    start = lsb_get_time();\n  }\n  if (lua_pcall(lua, nargs, 2, 0) != 0) {\n    char err[LSB_ERROR_SIZE];\n    const char *em = lua_tostring(lua, -1);\n    if (hsb->type == 'i' && em && strcmp(em, LSB_SHUTTING_DOWN) == 0) {\n      return 0;\n    }\n    size_t len = snprintf(err, LSB_ERROR_SIZE, \"%s() %s\", pm_func_name,\n                          em ? em : LSB_NIL_ERROR);\n    if (len >= LSB_ERROR_SIZE) {\n      err[LSB_ERROR_SIZE - 1] = 0;\n    }\n    lsb_terminate(hsb->lsb, err);\n    return 1;\n  }\n  if (profile) {\n    end = lsb_get_time();\n    lsb_update_running_stats(&hsb->stats.pm, (double)(end - start));\n  }\n  hsb->msg = NULL;\n\n  if (lua_type(lua, 1) != LUA_TNUMBER) {\n    char err[LSB_ERROR_SIZE];\n    size_t len = snprintf(err, LSB_ERROR_SIZE,\n                          \"%s() must return a numeric status code\",\n                          pm_func_name);\n    if (len >= LSB_ERROR_SIZE) {\n      err[LSB_ERROR_SIZE - 1] = 0;\n    }\n    lsb_terminate(hsb->lsb, err);\n    return 1;\n  }\n\n  int status = (int)lua_tointeger(lua, 1);\n  switch (lua_type(lua, 2)) {\n  case LUA_TNIL:\n    lsb_set_error(hsb->lsb, NULL);\n    break;\n  case LUA_TSTRING:\n    lsb_set_error(hsb->lsb, lua_tostring(lua, 2));\n    break;\n  default:\n    {\n      char err[LSB_ERROR_SIZE];\n      int len = snprintf(err, LSB_ERROR_SIZE,\n                         \"%s() must return a nil or string error message\",\n                         pm_func_name);\n      if (len >= LSB_ERROR_SIZE || len < 0) {\n        err[LSB_ERROR_SIZE - 1] = 0;\n      }\n      lsb_terminate(hsb->lsb, err);\n      return 1;\n    }\n    break;\n  }\n  lua_pop(lua, 2);\n  lsb_pcall_teardown(hsb->lsb);\n\n  if (status > 0) {\n    char err[LSB_ERROR_SIZE];\n    size_t len = snprintf(err, LSB_ERROR_SIZE,\n                          \"%s() received a termination status code\",\n                          pm_func_name);\n    if (len >= LSB_ERROR_SIZE) {\n      err[LSB_ERROR_SIZE - 1] = 0;\n    }\n    lsb_terminate(hsb->lsb, err);\n    return 1;\n  } else if (status == LSB_HEKA_PM_FAIL) {\n    ++hsb->stats.pm_cnt;\n    ++hsb->stats.pm_failures;\n  } else  if (hsb->type != 'o' || status != LSB_HEKA_PM_RETRY) {\n    ++hsb->stats.pm_cnt;\n  }\n  return status;\n}\n\n\nint lsb_heka_pm_input(lsb_heka_sandbox *hsb,\n                      double cp_numeric,\n                      const char *cp_string,\n                      bool profile)\n{\n  if (!hsb || hsb->type != 'i') {\n    return 1;\n  }\n\n  lsb_err_value ret = lsb_pcall_setup(hsb->lsb, pm_func_name);\n  if (ret) {\n    if (ret != LSB_ERR_TERMINATED) {\n      char err[LSB_ERROR_SIZE];\n      snprintf(err, LSB_ERROR_SIZE, \"%s() function was not found\",\n               pm_func_name);\n      lsb_terminate(hsb->lsb, err);\n    }\n    return 1;\n  }\n\n  lua_State *lua = lsb_get_lua(hsb->lsb);\n  if (!lua) return 1;\n\n  if (!isnan(cp_numeric)) {\n    lua_pushnumber(lua, cp_numeric);\n  } else if (cp_string) {\n    lua_pushstring(lua, cp_string);\n  } else {\n    lua_pushnil(lua);\n  }\n  return process_message(hsb, NULL, lua, 1, profile);\n}\n\n\nlsb_heka_sandbox* lsb_heka_create_analysis(void *parent,\n                                           const char *lua_file,\n                                           const char *state_file,\n                                           const char *lsb_cfg,\n                                           lsb_logger *logger,\n                                           lsb_heka_im_analysis im)\n{\n  if (!lua_file) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 3, \"lua_file must be specified\");\n    }\n    return NULL;\n  }\n\n  if (!im) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 3, \"inject_message callback must \"\n                 \"be specified\");\n    }\n    return NULL;\n  }\n\n\n  lsb_heka_sandbox *hsb = calloc(1, sizeof(lsb_heka_sandbox));\n  if (!hsb) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 3, \"memory allocation failed\");\n    }\n    return NULL;\n  }\n\n  hsb->type = 'a';\n  hsb->parent = parent;\n  hsb->msg = NULL;\n  hsb->cb.aim = im;\n  hsb->name = NULL;\n  hsb->hostname = NULL;\n  hsb->restricted_headers = true;\n\n  hsb->lsb = lsb_create(hsb, lua_file, lsb_cfg, logger);\n  if (!hsb->lsb) {\n    free(hsb);\n    return NULL;\n  }\n\n  lua_State *lua = lsb_get_lua(hsb->lsb);\n  set_restrictions(lua, hsb);\n\n  lsb_add_function(hsb->lsb, heka_decode_message, \"decode_message\");\n  lsb_add_function(hsb->lsb, read_message, \"read_message\");\n  lsb_add_function(hsb->lsb, inject_message_analysis, \"inject_message\");\n  lsb_add_function(hsb->lsb, inject_payload, \"inject_payload\");\n  // rename output to add_to_payload\n  lua_getglobal(lua, \"output\");\n  lua_setglobal(lua, \"add_to_payload\");\n  lua_pushnil(lua);\n  lua_setglobal(lua, \"output\");\n\n  if (lsb_init(hsb->lsb, state_file)) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, hsb->name, 3, \"%s\", lsb_get_error(hsb->lsb));\n    }\n    lsb_destroy(hsb->lsb);\n    free(hsb->hostname);\n    free(hsb->name);\n    free(hsb);\n    return NULL;\n  }\n  return hsb;\n}\n\n\nint lsb_heka_pm_analysis(lsb_heka_sandbox *hsb,\n                         lsb_heka_message *msg,\n                         bool profile)\n{\n  if (!hsb || !msg || hsb->type != 'a') return 1;\n\n  if (lsb_pcall_setup(hsb->lsb, pm_func_name)) {\n    char err[LSB_ERROR_SIZE];\n    snprintf(err, LSB_ERROR_SIZE, \"%s() function was not found\", pm_func_name);\n    lsb_terminate(hsb->lsb, err);\n    return 1;\n  }\n\n  lua_State *lua = lsb_get_lua(hsb->lsb);\n  if (!lua) return 1;\n  return process_message(hsb, msg, lua, 0, profile);\n}\n\n\n// IO write zero copy replacement\nstatic int pushresult(lua_State *lua, int i, const char *filename)\n{\n  int en = errno;  /* calls to Lua API may change this value */\n  if (i) {\n    lua_pushboolean(lua, 1);\n    return 1;\n  } else {\n    lua_pushnil(lua);\n    if (filename) lua_pushfstring(lua, \"%s: %s\", filename, strerror(en));\n    else lua_pushfstring(lua, \"%s\", strerror(en));\n    lua_pushinteger(lua, en);\n    return 3;\n  }\n}\n\n\nstatic int zc_write(lua_State *lua, FILE *f, int arg)\n{\n  int n =  lua_gettop(lua);\n  int nargs = n - 1;\n  int status = 1;\n  for (; nargs--; arg++) {\n    switch (lua_type(lua, arg)) {\n    case LUA_TNUMBER:\n      /* optimization: could be done exactly as for strings */\n      status = status &&\n          fprintf(f, LUA_NUMBER_FMT, lua_tonumber(lua, arg)) > 0;\n      break;\n    case LUA_TSTRING:\n      {\n        size_t l;\n        const char *s = luaL_checklstring(lua, arg, &l);\n        status = status && (fwrite(s, sizeof(char), l, f) == l);\n      }\n      break;\n    case LUA_TUSERDATA:\n      {\n        lua_CFunction fp = lsb_get_zero_copy_function(lua, arg);\n        if (!fp) {\n          return luaL_argerror(lua, arg, \"no zero copy support\");\n        }\n        lua_pushvalue(lua, arg);\n        int results = fp(lua);\n        int start = n + 2;\n        int end = start + results;\n        size_t len;\n        const char *s;\n        for (int i = start; i < end; ++i) {\n          switch (lua_type(lua, i)) {\n          case LUA_TSTRING:\n            s = lua_tolstring(lua, i, &len);\n            if (s && len > 0) {\n              status = status && (fwrite(s, sizeof(char), len, f) == len);\n            }\n            break;\n          case LUA_TLIGHTUSERDATA:\n            s = lua_touserdata(lua, i++);\n            len = (size_t)lua_tointeger(lua, i);\n            if (s && len > 0) {\n              status = status && (fwrite(s, sizeof(char), len, f) == len);\n            }\n            break;\n          default:\n            return luaL_error(lua, \"invalid zero copy return\");\n          }\n        }\n        lua_pop(lua, results + 1); // remove the returns values and\n                                   // the copy of the userdata\n      }\n      break;\n    default:\n      return luaL_typerror(lua, arg, \"number, string or userdata\");\n    }\n  }\n  return pushresult(lua, status, NULL);\n}\n\nstatic FILE* getiofile(lua_State *lua, int findex)\n{\n  static const char *const fnames[] = { \"input\", \"output\" };\n  FILE *f;\n  lua_rawgeti(lua, LUA_ENVIRONINDEX, findex);\n  f = *(FILE **)lua_touserdata(lua, -1);\n  if (f == NULL) luaL_error(lua, \"standard %s file is closed\",\n                            fnames[findex - 1]);\n  return f;\n}\n\n\nstatic int zc_io_write(lua_State *lua)\n{\n  return zc_write(lua, getiofile(lua, 2), 1);\n}\n\n\nstatic FILE* tofile(lua_State *lua)\n{\n  FILE **f = (FILE **)luaL_checkudata(lua, 1, LUA_FILEHANDLE);\n  if (*f == NULL) luaL_error(lua, \"attempt to use a closed file\");\n  return *f;\n}\n\n\nstatic int zc_f_write(lua_State *lua)\n{\n  return zc_write(lua, tofile(lua), 2);\n}\n\n\nstatic int zc_luaopen_io(lua_State *lua)\n{\n  luaopen_io(lua);\n  lua_pushcclosure(lua, zc_io_write, 0);\n  lua_setfield(lua, -2, \"write\");\n\n  luaL_getmetatable(lua, LUA_FILEHANDLE);\n  lua_pushcclosure(lua, zc_f_write, 0);\n  lua_setfield(lua, -2, \"write\");\n  lua_pop(lua, 1); // remove the metatable\n  return 1;\n}\n// End IO write zero copy replacement\n\n\nlsb_heka_sandbox* lsb_heka_create_output(void *parent,\n                                         const char *lua_file,\n                                         const char *state_file,\n                                         const char *lsb_cfg,\n                                         lsb_logger *logger,\n                                         lsb_heka_update_checkpoint ucp)\n{\n  return lsb_heka_create_output_im(parent, lua_file, state_file, lsb_cfg,\n                                   logger, ucp, NULL);\n}\n\n\nlsb_heka_sandbox* lsb_heka_create_output_im(void *parent,\n                                         const char *lua_file,\n                                         const char *state_file,\n                                         const char *lsb_cfg,\n                                         lsb_logger *logger,\n                                         lsb_heka_update_checkpoint ucp,\n                                         lsb_heka_im_analysis im)\n{\n  if (!lua_file) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 3, \"lua_file must be specified\");\n    }\n    return NULL;\n  }\n\n  if (!ucp) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 3, LSB_HEKA_UPDATE_CHECKPOINT\n                 \" callback must be specified\");\n    }\n    return NULL;\n  }\n\n  lsb_heka_sandbox *hsb = calloc(1, sizeof(lsb_heka_sandbox));\n  if (!hsb) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 3, \"memory allocation failed\");\n    }\n    return NULL;\n  }\n\n  hsb->type = 'o';\n  hsb->parent = parent;\n  hsb->msg = NULL;\n  hsb->ucp = ucp;\n  hsb->cb.aim = im;\n  hsb->name = NULL;\n  hsb->hostname = NULL;\n\n  hsb->lsb = lsb_create(hsb, lua_file, lsb_cfg, logger);\n  if (!hsb->lsb) {\n    free(hsb);\n    return NULL;\n  }\n\n  lua_State *lua = lsb_get_lua(hsb->lsb);\n  set_restrictions(lua, hsb);\n\n  lsb_add_function(hsb->lsb, read_message, \"read_message\");\n  lsb_add_function(hsb->lsb, heka_decode_message, \"decode_message\");\n  lsb_add_function(hsb->lsb, heka_encode_message, \"encode_message\");\n  lsb_add_function(hsb->lsb, update_checkpoint, LSB_HEKA_UPDATE_CHECKPOINT);\n  lsb_add_function(hsb->lsb, mm_create, \"create_message_matcher\");\n  if (im) {\n    lsb_add_function(hsb->lsb, inject_message_analysis, \"inject_message\");\n    // inject_payload is intentionally excluded from output plugins\n    // you can construct whatever you need with inject_message\n  }\n\n  // start io.write override with zero copy functionality\n  lua_getfield(lua, LUA_REGISTRYINDEX, \"_PRELOADED\");\n  lua_pushstring(lua, LUA_IOLIBNAME);\n  lua_pushcfunction(lua, zc_luaopen_io);\n  lua_rawset(lua, -3);\n  lua_pop(lua, 1);\n  // end io.write override\n\n  if (lsb_init(hsb->lsb, state_file)) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, hsb->name, 3, \"%s\", lsb_get_error(hsb->lsb));\n    }\n    lsb_destroy(hsb->lsb);\n    free(hsb->hostname);\n    free(hsb->name);\n    free(hsb);\n    return NULL;\n  }\n\n// remove output function\n  lua_pushnil(lua);\n  lua_setglobal(lua, \"output\");\n\n  return hsb;\n}\n\n\n\nvoid lsb_heka_stop_sandbox_clean(lsb_heka_sandbox *hsb)\n{\n  lsb_stop_sandbox_clean(hsb->lsb);\n}\n\n\nvoid lsb_heka_stop_sandbox(lsb_heka_sandbox *hsb)\n{\n  lsb_stop_sandbox(hsb->lsb);\n}\n\n\n\nvoid lsb_heka_terminate_sandbox(lsb_heka_sandbox *hsb, const char *err)\n{\n  lsb_terminate(hsb->lsb, err);\n}\n\n\nchar* lsb_heka_destroy_sandbox(lsb_heka_sandbox *hsb)\n{\n  if (!hsb) return NULL;\n\n  char *msg = lsb_destroy(hsb->lsb);\n  free(hsb->hostname);\n  free(hsb->name);\n  free(hsb);\n  return msg;\n}\n\n\nint lsb_heka_pm_output(lsb_heka_sandbox *hsb,\n                       lsb_heka_message *msg,\n                       void *sequence_id,\n                       bool profile)\n{\n  if (!hsb || !msg || hsb->type != 'o') return 1;\n\n  if (lsb_pcall_setup(hsb->lsb, pm_func_name)) {\n    char err[LSB_ERROR_SIZE];\n    snprintf(err, LSB_ERROR_SIZE, \"%s() function was not found\", pm_func_name);\n    lsb_terminate(hsb->lsb, err);\n    return 1;\n  }\n\n  lua_State *lua = lsb_get_lua(hsb->lsb);\n  if (!lua) return 1;\n\n  int nargs = 0;\n  if (sequence_id) {\n    nargs = 1;\n    lua_pushlightuserdata(lua, sequence_id);\n  }\n  return process_message(hsb, msg, lua, nargs, profile);\n}\n\n\nint lsb_heka_timer_event(lsb_heka_sandbox *hsb, time_t t, bool shutdown)\n{\n  static const char *func_name = \"timer_event\";\n\n  if (!hsb || (hsb->type != 'o' && hsb->type != 'a')) {\n    return 1;\n  }\n\n  lua_State *lua = lsb_get_lua(hsb->lsb);\n  if (!lua) return 1;\n\n  if (lsb_pcall_setup(hsb->lsb, func_name)) {\n    char err[LSB_ERROR_SIZE];\n    snprintf(err, LSB_ERROR_SIZE, \"%s() function was not found\", func_name);\n    lsb_terminate(hsb->lsb, err);\n    return 1;\n  }\n  lua_pushnumber(lua, t * 1e9);\n  lua_pushboolean(lua, shutdown);\n\n  unsigned long long start, end;\n  start = lsb_get_time();\n  if (lua_pcall(lua, 2, 0, 0) != 0) {\n    char err[LSB_ERROR_SIZE];\n    const char *em = lua_tostring(lua, -1);\n    size_t len = snprintf(err, LSB_ERROR_SIZE, \"%s() %s\", func_name,\n                          em ? em : LSB_NIL_ERROR);\n    if (len >= LSB_ERROR_SIZE) {\n      err[LSB_ERROR_SIZE - 1] = 0;\n    }\n    lsb_terminate(hsb->lsb, err);\n    return 1;\n  }\n  end = lsb_get_time();\n  lsb_update_running_stats(&hsb->stats.te, (double)(end - start));\n  lsb_pcall_teardown(hsb->lsb);\n  lua_gc(lua, LUA_GCCOLLECT, 0);\n  return 0;\n}\n\n\nconst char* lsb_heka_get_error(lsb_heka_sandbox *hsb)\n{\n  return hsb ? lsb_get_error(hsb->lsb) : \"\";\n}\n\n\nconst char* lsb_heka_get_lua_file(lsb_heka_sandbox *hsb)\n{\n  return hsb ? lsb_get_lua_file(hsb->lsb) : NULL;\n}\n\n\nlsb_heka_stats lsb_heka_get_stats(lsb_heka_sandbox *hsb)\n{\n  if (!hsb) return (struct lsb_heka_stats){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };\n\n  return (struct lsb_heka_stats){\n    .mem_cur      = lsb_usage(hsb->lsb, LSB_UT_MEMORY, LSB_US_CURRENT),\n    .mem_max      = lsb_usage(hsb->lsb, LSB_UT_MEMORY, LSB_US_MAXIMUM),\n    .out_max      = lsb_usage(hsb->lsb, LSB_UT_OUTPUT, LSB_US_MAXIMUM),\n    .ins_max      = lsb_usage(hsb->lsb, LSB_UT_INSTRUCTION, LSB_US_MAXIMUM),\n    .im_cnt       = hsb->stats.im_cnt,\n    .im_bytes     = hsb->stats.im_bytes,\n    .pm_cnt       = hsb->stats.pm_cnt,\n    .pm_failures  = hsb->stats.pm_failures,\n    .pm_avg       = hsb->stats.pm.mean,\n    .pm_sd        = lsb_sd_running_stats(&hsb->stats.pm),\n    .te_avg       = hsb->stats.te.mean,\n    .te_sd        = lsb_sd_running_stats(&hsb->stats.te)\n  };\n}\n\n\nbool lsb_heka_is_running(lsb_heka_sandbox *hsb)\n{\n  if (!hsb) return false;\n  if (lsb_get_state(hsb->lsb) == LSB_RUNNING) return true;\n  return false;\n}\n\n\nlsb_state lsb_heka_get_state(lsb_heka_sandbox *hsb)\n{\n  if (!hsb) return LSB_UNKNOWN;\n  return lsb_get_state(hsb->lsb);\n}\n\n\nconst lsb_heka_message* lsb_heka_get_message(lsb_heka_sandbox *hsb)\n{\n  if (!hsb) return NULL;\n  return hsb->msg;\n}\n\n\nchar lsb_heka_get_type(lsb_heka_sandbox *hsb)\n{\n  if (!hsb) return '\\0';\n  return hsb->type;\n}\n"
  },
  {
    "path": "src/heka/sandbox_impl.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Hindsight Heka sandbox private implementation @file */\n\n#ifndef luasandbox_heka_sandbox_impl_h_\n#define luasandbox_heka_sandbox_impl_h_\n\n#include \"luasandbox.h\"\n#include \"luasandbox/heka/sandbox.h\"\n#include \"luasandbox/util/heka_message.h\"\n#include \"luasandbox/util/running_stats.h\"\n\nstruct heka_stats {\n  unsigned long long im_cnt;\n  unsigned long long im_bytes;\n\n  unsigned long long pm_cnt;\n  unsigned long long pm_failures;\n\n  lsb_running_stats pm;\n  lsb_running_stats te;\n};\n\n\nstruct lsb_heka_sandbox {\n  void                              *parent;\n  lsb_lua_sandbox                   *lsb;\n  lsb_heka_message                  *msg;\n  char                              *name;\n  char                              *hostname;\n  union {\n    lsb_heka_im_input           iim; // used in input plugins only\n    lsb_heka_im_analysis        aim; // used in analysis and output plugins\n  } cb;\n  struct heka_stats                 stats;\n  char                              type;\n  bool                              restricted_headers;\n  int                               pid;\n  lsb_heka_update_checkpoint        ucp; // used in output plugins only\n};\n\n#endif\n"
  },
  {
    "path": "src/heka/stream_reader.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Hindsight Heka stream reader implementation @file */\n\n#include \"luasandbox/heka/stream_reader.h\"\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"luasandbox/heka/sandbox.h\"\n#include \"message_impl.h\"\n#include \"luasandbox/lauxlib.h\"\n\nstatic heka_stream_reader* check_hsr(lua_State *lua, int args)\n{\n  heka_stream_reader *hsr = luaL_checkudata(lua, 1, LSB_HEKA_STREAM_READER);\n  luaL_argcheck(lua, args == lua_gettop(lua), 0,\n                \"incorrect number of arguments\");\n  return hsr;\n}\n\n\nstatic int hsr_decode_message(lua_State *lua)\n{\n  heka_stream_reader *hsr = check_hsr(lua, 2);\n  lsb_input_buffer *b = &hsr->buf;\n  b->readpos = b->scanpos = b->msglen = 0;\n\n  size_t len;\n  if (lua_type(lua, 2) == LUA_TSTRING) {\n    const char *s = lua_tolstring(lua, 2, &len);\n    if (len > 0) {\n      if (lsb_expand_input_buffer(b, len)) {\n        return luaL_error(lua, \"buffer reallocation failed\\tname:%s\",\n                          hsr->name);\n      }\n      memcpy(b->buf, s, len);\n    } else {\n      return luaL_error(lua, \"empty protobuf string\");\n    }\n  } else {\n    return luaL_error(lua, \"buffer must be string\");\n  }\n\n  if (!lsb_decode_heka_message(&hsr->msg, b->buf, len, NULL)) {\n    return luaL_error(lua, \"invalid protobuf string\");\n  }\n  return 0;\n}\n\n\nstatic int hsr_find_message(lua_State *lua)\n{\n  int n = lua_gettop(lua);\n  luaL_argcheck(lua, n > 1 && n < 4, 0, \"incorrect number of arguments\");\n  heka_stream_reader *hsr = luaL_checkudata(lua, 1, LSB_HEKA_STREAM_READER);\n  lsb_input_buffer *b = &hsr->buf;\n\n  FILE *fh = NULL;\n  switch (lua_type(lua, 2)) {\n  case LUA_TNIL: // scan the existing buffer\n    break;\n  case LUA_TSTRING: // add data to the buffer\n    {\n      size_t len;\n      const char *s = lua_tolstring(lua, 2, &len);\n      if (len > 0) {\n        if (lsb_expand_input_buffer(b, len)) {\n          return luaL_error(lua, \"buffer reallocation failed\\tname:%s\",\n                            hsr->name);\n        }\n        memcpy(b->buf + b->readpos, s, len);\n        b->readpos += len;\n      }\n    }\n    break;\n  case LUA_TUSERDATA: // add data from the provided file handle to the buffer\n    fh = *(FILE **)luaL_checkudata(lua, 2, \"FILE*\");\n    if (!fh) luaL_error(lua, \"attempt to use a closed file\");\n    break;\n  default:\n    return luaL_error(lua, \"buffer must be a nil, string, userdata (FILE*)\");\n  }\n\n  bool decode = true;\n  if (n == 3) {\n    luaL_checktype(lua, 3, LUA_TBOOLEAN);\n    decode = (bool)lua_toboolean(lua, 3);\n  }\n\n  size_t pos_r = b->readpos;\n  size_t pos_s = b->scanpos;\n  size_t discarded = 0;\n  bool found = lsb_find_heka_message(&hsr->msg, b, decode, &discarded, NULL);\n\n  size_t need = b->size;\n  if (found) {\n    lua_pushboolean(lua, 1); // found\n    lua_pushinteger(lua, b->scanpos - pos_s); // consumed\n  } else {\n    lua_pushboolean(lua, 0); // not found\n    if (b->readpos == 0) {\n      lua_pushinteger(lua, pos_r - pos_s); // consumed everything in the buf\n    } else {\n      lua_pushinteger(lua, b->scanpos - pos_s);\n    }\n    if (b->msglen) {\n      need = b->msglen + (size_t)b->buf[b->scanpos + 1] + LSB_HDR_FRAME_SIZE -\n          (b->readpos - b->scanpos);\n    } else {\n      need = b->scanpos + b->size - b->readpos;\n    }\n  }\n\n  if (fh) { // update bytes read\n    if (found) {\n      lua_pushinteger(lua, 0);\n    } else {\n      if (lsb_expand_input_buffer(b, need)) {\n        return luaL_error(lua, \"buffer reallocation failed\\tname:%s\",\n                          hsr->name);\n      }\n      size_t nread = fread(b->buf + b->readpos,\n                           1,\n                           b->size - b->readpos,\n                           fh);\n      b->readpos += nread;\n      lua_pushnumber(lua, (lua_Number)nread);\n    }\n  } else { // update bytes needed\n    if (found && b->scanpos != b->readpos) need = 0;\n    lua_pushinteger(lua, need);\n  }\n  return 3;\n}\n\n\nstatic int hsr_read_message(lua_State *lua)\n{\n  int n = lua_gettop(lua);\n  if (n < 1 || n > 4) {\n    return luaL_error(lua, \"read_message() incorrect number of arguments\");\n  }\n  heka_stream_reader *hsr = check_hsr(lua, n);\n  lua_remove(lua, 1); // remove the hsr user data\n  return heka_read_message(lua, &hsr->msg);\n}\n\n\nstatic int hsr_gc(lua_State *lua)\n{\n  heka_stream_reader *hsr = check_hsr(lua, 1);\n  free(hsr->name);\n  lsb_free_heka_message(&hsr->msg);\n  lsb_free_input_buffer(&hsr->buf);\n  return 0;\n}\n\n\nstatic const struct luaL_reg heka_stream_readerlib_m[] =\n{\n  { \"find_message\", hsr_find_message },\n  { \"decode_message\", hsr_decode_message },\n  { \"read_message\", hsr_read_message },\n  { \"__gc\", hsr_gc },\n  { NULL, NULL }\n};\n\n\nint heka_create_stream_reader(lua_State *lua)\n{\n  int n = lua_gettop(lua);\n  luaL_argcheck(lua, n == 1, 0, \"incorrect number of arguments\");\n  size_t len;\n  const char *name = luaL_checklstring(lua, 1, &len);\n  luaL_argcheck(lua, len < 255, 1, \"name is too long\");\n\n  size_t nbytes = sizeof(heka_stream_reader);\n  heka_stream_reader *hsr = lua_newuserdata(lua, nbytes);\n\n  if (luaL_newmetatable(lua, LSB_HEKA_STREAM_READER) == 1) {\n    lua_pushvalue(lua, -1);\n    lua_setfield(lua, -2, \"__index\");\n    luaL_register(lua, NULL, heka_stream_readerlib_m);\n  }\n  lua_setmetatable(lua, -2);\n\n  size_t mms = 0;\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_CONFIG_TABLE);\n  if (lua_type(lua, -1) == LUA_TTABLE) {\n    lua_getfield(lua, -1, LSB_HEKA_MAX_MESSAGE_SIZE);\n    mms = (size_t)lua_tointeger(lua, -1);\n    lua_pop(lua, 1); // remove limit\n  } else {\n    free(hsr);\n    return luaL_error(lua, LSB_CONFIG_TABLE \" is missing\");\n  }\n  lua_pop(lua, 1); // remove config\n\n  if (lsb_init_heka_message(&hsr->msg, 8)) {\n    free(hsr);\n    return luaL_error(lua, \"failed to init the message struct\");\n  }\n  if (lsb_init_input_buffer(&hsr->buf, mms)) {\n    lsb_free_heka_message(&hsr->msg);\n    free(hsr);\n    return luaL_error(lua, \"failed to init the input buffer\");\n  }\n  hsr->name = malloc(len + 1);\n  if (!hsr->name) {\n    lsb_free_input_buffer(&hsr->buf);\n    lsb_free_heka_message(&hsr->msg);\n    free(hsr);\n    return luaL_error(lua, \"memory allocation failed\");\n  }\n  strcpy(hsr->name, name);\n  return 1;\n}\n"
  },
  {
    "path": "src/heka/test/CMakeLists.txt",
    "content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nconfigure_file(test.h.in test.h ESCAPE_QUOTES)\ninclude_directories(${CMAKE_CURRENT_BINARY_DIR})\nset(LIBRARY_PATHS \"${CMAKE_BINARY_DIR}/src;${CMAKE_BINARY_DIR}/src/util;${CMAKE_BINARY_DIR}/src;${CMAKE_BINARY_DIR}/src/heka\")\n\nadd_test(NAME test_move_heka_sandbox_tests COMMAND cmake -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})\n\nadd_executable(test_heka_sandbox test_heka_sandbox.c)\ntarget_link_libraries(test_heka_sandbox luasandboxheka)\nadd_test(NAME test_heka_sandbox COMMAND test_heka_sandbox)\n\nif(WIN32)\n   STRING(REPLACE \";\" \"\\\\\\\\;\" LIBRARY_PATHS \"${LIBRARY_PATHS}\")\n   set_tests_properties(test_heka_sandbox PROPERTIES ENVIRONMENT PATH=${LIBRARY_PATHS})\nendif()\n"
  },
  {
    "path": "src/heka/test/lua/aim.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nrequire \"string\"\n\n-- Table tests\nlocal msgs = {\n    {Pid = 0, Timestamp = 0, Uuid = \"\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\"},\n    {Pid = 0, Uuid = \"\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\", Logger = \"ignore\", Hostname = \"spoof\"},\n}\n\nlocal err_msgs = {\n    {err = \"bad argument #1 to '?' (table expected, got nil)\"},\n}\n\nfor i, v in ipairs(msgs) do\n    inject_message(v)\nend\n\nfor i, v in ipairs(err_msgs) do\n    local ok, err = pcall(inject_message, v.msg)\n    if ok then error(string.format(\"test: %d should have failed\", i)) end\n    assert(v.err == err, string.format(\"test: %d expected: %s received: %s\", i, v.err, err))\nend\n\nadd_to_payload(\"foo bar\")\ninject_payload()\n\nadd_to_payload(\"foo\")\ninject_payload(\"dat\", \"test\", \" bar\")\n\nlocal ok, err = pcall(add_to_payload, add_to_payload)\nif ok then error(\"cannot output functions\") end\nlocal eerr = \"bad argument #1 to '?' (unsupported type)\"\nassert(eerr == err, string.format(\"expected: %s received: %s\", eerr, err))\n\nok, err = pcall(inject_payload, \"txt\", \"name\", add_to_payload)\nif ok then error(\"cannot output functions\") end\neerr = \"bad argument #3 to '?' (unsupported type)\"\nassert(eerr == err, string.format(\"expected: %s received: %s\", eerr, err))\n\nok, err = pcall(inject_payload, true, \"name\", \"data\")\nassert(not ok)\nassert(\"inject_payload() payload_type argument must be a string\" == err, string.format(\"received: %s\", err))\n\nok, err = pcall(inject_payload, \"txt\", true, \"data\")\nassert(not ok)\nassert(\"inject_payload() payload_name argument must be a string\" == err, string.format(\"received: %s\", err))\n\nok, err = pcall(inject_payload, nil)\nassert(not ok)\nassert(\"inject_payload() payload_type argument must be a string\" == err, string.format(\"received: %s\", err))\n\nok, err = pcall(inject_payload, \"\", nil)\nassert(not ok)\nassert(\"inject_payload() payload_name argument must be a string\" == err, string.format(\"received: %s\", err))\n\nok, err = pcall(inject_message, {Fields = {foo = {value = {\"s\", true}}}})\nassert(not ok)\nassert(\"inject_message() failed: array has mixed types\" == err, string.format(\"received: %s\", err))\n\nok, err = pcall(inject_message, {})\nassert(not ok)\nassert(\"inject_message() failed: rejected by the callback rv: 99\" == err, string.format(\"received: %s\", err))\n\nok, err = pcall(inject_message, {})\nassert(not ok)\nassert(\"inject_message() failed: injection limit exceeded\" == err, string.format(\"received: %s\", err))\n"
  },
  {
    "path": "src/heka/test/lua/analysis.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nassert(read_config)\nassert(read_message)\nassert(decode_message)\nassert(inject_message)\nassert(add_to_payload)\nassert(inject_payload)\nassert(not encode_message)\nassert(not update_checkpoint)\n\nfunction process_message()\n    return 0\nend\n\nlocal work_cnt = 1\nfunction timer_event(ns, shutdown)\n    local cnt = 0\n    for i=1, work_cnt * 1000 do\n        cnt = cnt + 1\n    end\n    work_cnt = work_cnt + 1\n\n    if ns == 1e9 then\n        assert(shutdown, \"not shutting down\")\n        return\n    end\n\n    local uuid = read_message(\"Uuid\")\n    assert(not uuid)\n\n    if ns == 2e9 then error(\"boom\") end\n\n    if shutdown then error(\"should not have a shutdown signal\") end\nend\n\n"
  },
  {
    "path": "src/heka/test/lua/decode_message.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\n-- minimal message, required fields only\nlocal test = \"\\010\\016\\233\\213\\137\\149\\106\\254\\064\\066\\175\\098\\058\\163\\017\\067\\202\\068\\016\\000\"\nlocal msg = decode_message(test)\nassert(msg.Timestamp == 0)\n\n-- message headers only\nlocal test = \"\\010\\016\\233\\213\\137\\149\\106\\254\\064\\066\\175\\098\\058\\163\\017\\067\\202\\068\\016\\128\\148\\235\\220\\003\\026\\004type\\034\\006logger\\040\\009\\050\\007payload\\058\\011env_version\\074\\008hostname\"\nmsg = decode_message(test)\nassert(msg.Timestamp == 1e9)\nassert(msg.Type == \"type\")\nassert(msg.Logger == \"logger\")\nassert(msg.Payload == \"payload\")\nassert(msg.EnvVersion == \"env_version\")\nassert(msg.Hostname == \"hostname\")\nassert(msg.Severity == 9)\n\n-- repeated unpacked doubles\ntest = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\\016\\128\\148\\235\\220\\003\\082\\027\\010\\005count\\016\\003\\057\\000\\000\\000\\000\\000\\000\\240\\063\\057\\000\\000\\000\\000\\000\\000\\240\\063\"\nmsg = decode_message(test)\nassert(msg.Timestamp == 1e9)\nassert(msg.Fields[1].name == \"count\")\nassert(msg.Fields[1].value_type == 3)\nassert(#msg.Fields[1].value == 2)\nassert(msg.Fields[1].value[1] == 1)\nassert(msg.Fields[1].value[2] == 1)\n\n-- repeated packed doubles\ntest = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\\016\\128\\148\\235\\220\\003\\082\\027\\010\\005count\\016\\003\\058\\016\\000\\000\\000\\000\\000\\000\\240\\063\\000\\000\\000\\000\\000\\000\\240\\063\"\nmsg = decode_message(test)\nassert(msg.Timestamp == 1e9)\nassert(msg.Fields[1].name == \"count\")\nassert(msg.Fields[1].value_type == 3)\nassert(#msg.Fields[1].value == 2)\nassert(msg.Fields[1].value[1] == 1)\nassert(msg.Fields[1].value[2] == 1)\n\n-- repeated unpacked ints\ntest = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\\016\\128\\148\\235\\220\\003\\082\\013\\010\\005count\\016\\002\\048\\001\\048\\001\"\nmsg = decode_message(test)\nassert(msg.Timestamp == 1e9)\nassert(msg.Fields[1].name == \"count\")\nassert(msg.Fields[1].value_type == 2)\nassert(#msg.Fields[1].value == 2)\nassert(msg.Fields[1].value[1] == 1)\nassert(msg.Fields[1].value[2] == 1)\n\n-- repeated packed ints\ntest = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\\016\\128\\148\\235\\220\\003\\082\\013\\010\\005count\\016\\002\\050\\002\\001\\001\"\nmsg = decode_message(test)\nassert(msg.Timestamp == 1e9)\nassert(msg.Fields[1].name == \"count\")\nassert(msg.Fields[1].value_type == 2)\nassert(#msg.Fields[1].value == 2)\nassert(msg.Fields[1].value[1] == 1)\nassert(msg.Fields[1].value[2] == 1)\n\n-- repeated unpacked bools\ntest = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\\016\\128\\148\\235\\220\\003\\082\\013\\010\\005count\\016\\004\\064\\001\\064\\000\"\nmsg = decode_message(test)\nassert(msg.Timestamp == 1e9)\nassert(msg.Fields[1].name == \"count\")\nassert(msg.Fields[1].value_type == 4)\nassert(#msg.Fields[1].value == 2)\nassert(msg.Fields[1].value[1] == true)\nassert(msg.Fields[1].value[2] == false)\n\n-- repeated packed bools\ntest = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\\016\\128\\148\\235\\220\\003\\082\\013\\010\\005count\\016\\004\\066\\002\\001\\000\"\nmsg = decode_message(test)\nassert(msg.Timestamp == 1e9)\nassert(msg.Fields[1].name == \"count\")\nassert(msg.Fields[1].value_type == 4)\nassert(#msg.Fields[1].value == 2)\nassert(msg.Fields[1].value[1] == true)\nassert(msg.Fields[1].value[2] == false)\n\n-- repeated strings\ntest = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\\016\\128\\148\\235\\220\\003\\082\\023\\010\\005names\\016\\000\\034\\002s1\\034\\002s2\\026\\004keys\"\nmsg = decode_message(test)\nassert(msg.Timestamp == 1e9)\nassert(msg.Fields[1].name == \"names\")\nassert(msg.Fields[1].representation == \"keys\")\nassert(msg.Fields[1].value_type == 0)\nassert(#msg.Fields[1].value == 2)\nassert(msg.Fields[1].value[1] == \"s1\")\nassert(msg.Fields[1].value[2] == \"s2\")\n\n-- repeated bytes\ntest = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\\016\\128\\148\\235\\220\\003\\082\\023\\010\\005names\\016\\001\\042\\002s1\\042\\002s2\\026\\004keys\"\nmsg = decode_message(test)\nassert(msg.Timestamp == 1e9)\nassert(msg.Fields[1].name == \"names\")\nassert(msg.Fields[1].representation == \"keys\")\nassert(msg.Fields[1].value_type == 1)\nassert(#msg.Fields[1].value == 2)\nassert(msg.Fields[1].value[1] == \"s1\")\nassert(msg.Fields[1].value[2] == \"s2\")\n\n-- recent timestamp\ntest = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\\016\\128\\152\\141\\135\\236\\222\\200\\233\\19\"\nmsg = decode_message(test)\nassert(msg.Timestamp == 1428523950000000000)\n\n-- benchmark message\ntest = \"\\010\\016\\096\\006\\214\\155\\119\\188\\078\\023\\172\\076\\081\\127\\129\\143\\250\\040\\016\\128\\148\\235\\220\\003\\082\\019\\010\\006\\110\\117\\109\\098\\101\\114\\016\\003\\057\\000\\000\\000\\000\\000\\000\\240\\063\\082\\044\\010\\007\\110\\117\\109\\098\\101\\114\\115\\016\\003\\026\\005\\099\\111\\117\\110\\116\\058\\024\\000\\000\\000\\000\\000\\000\\240\\063\\000\\000\\000\\000\\000\\000\\000\\064\\000\\000\\000\\000\\000\\000\\008\\064\\082\\014\\010\\005\\098\\111\\111\\108\\115\\016\\004\\066\\003\\001\\000\\000\\082\\010\\010\\004\\098\\111\\111\\108\\016\\004\\064\\001\\082\\016\\010\\006\\115\\116\\114\\105\\110\\103\\034\\006\\115\\116\\114\\105\\110\\103\\082\\021\\010\\007\\115\\116\\114\\105\\110\\103\\115\\034\\002\\115\\049\\034\\002\\115\\050\\034\\002\\115\\051\"\nmsg = decode_message(test)\nassert(msg.Timestamp == 1e9)\nassert(#msg.Fields == 6)\n\nassert(#msg.Fields[1].value == 1)\nassert(msg.Fields[1].name == \"number\")\nassert(msg.Fields[1].value_type == 3)\nassert(msg.Fields[1].value[1] == 1)\n\nassert(msg.Fields[2].name == \"numbers\")\nassert(msg.Fields[2].value_type == 3)\nassert(#msg.Fields[2].value == 3)\nassert(msg.Fields[2].value[1] == 1)\nassert(msg.Fields[2].value[2] == 2)\nassert(msg.Fields[2].value[3] == 3)\nassert(msg.Fields[2].representation == \"count\")\n\nassert(#msg.Fields[3].value == 3)\nassert(msg.Fields[3].name == \"bools\")\nassert(msg.Fields[3].value[1])\nassert(msg.Fields[3].value[2] == false)\nassert(msg.Fields[3].value[3] == false)\n\nassert(#msg.Fields[4].value == 1)\nassert(msg.Fields[4].name == \"bool\")\nassert(msg.Fields[4].value[1])\n\nassert(#msg.Fields[5].value == 1)\nassert(msg.Fields[5].name == \"string\")\nassert(msg.Fields[5].value[1] == \"string\")\n\nassert(msg.Fields[6].name == \"strings\")\nassert(#msg.Fields[6].value == 3)\nassert(msg.Fields[6].value[1] ==\"s1\")\nassert(msg.Fields[6].value[2] ==\"s2\")\nassert(msg.Fields[6].value[3] ==\"s3\")\n\n-- test negative varint headers\ntest = \"\\010\\016\\243\\083\\052\\234\\016\\052\\066\\236\\160\\084\\236\\003\\227\\231\\170\\203\\016\\255\\255\\255\\255\\255\\255\\255\\255\\255\\001\\040\\255\\255\\255\\255\\255\\255\\255\\255\\255\\001\\064\\255\\255\\255\\255\\255\\255\\255\\255\\255\\001\"\nmsg = decode_message(test)\nassert(msg.Timestamp == -1)\nassert(msg.Pid == -1)\nassert(msg.Severity == -1)\n\n-- multi byte length\ntest = \"\\010\\016\\104\\183\\062\\106\\120\\227\\073\\248\\173\\168\\122\\019\\057\\236\\124\\025\\016\\128\\148\\235\\220\\003\\082\\141\\001\\010\\006\\115\\116\\114\\105\\110\\103\\034\\130\\001\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\\048\\049\\050\\051\\052\\053\\054\\055\\056\\057\"\nmsg = decode_message(test)\nassert(msg.Fields[1].value[1] == \"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\")\n\n\n--[[\nParse Errors\n--]]\n\n-- too short\ntest = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\"\nok, msg = pcall(decode_message, test)\nassert(not ok)\nassert(msg == \"invalid message, too short\", msg)\n\n-- no uuid\ntest = \"\\016\\128\\148\\235\\220\\003\\082\\023\\010\\005names\\016\\001\\042\\002s1\\042\\002s2\\026\\004keys\"\nok, msg = pcall(decode_message, test)\nassert(not ok)\nassert(msg == \"missing required field uuid: not found timestamp: found\", msg)\n\n-- no timestamp\nlocal test = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\\082\\023\\010\\005names\\016\\001\\042\\002s1\\042\\002s2\\026\\004keys\"\nok, msg = pcall(decode_message, test)\nassert(not ok)\nassert(msg == \"missing required field uuid: found timestamp: not found\", msg)\n\n-- missing field name\ntest = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\\016\\128\\148\\235\\220\\003\\082\\020\\016\\003\\057\\000\\000\\000\\000\\000\\000\\240\\063\\057\\000\\000\\000\\000\\000\\000\\240\\063\"\nok, msg = pcall(decode_message, test)\nassert(not ok)\nassert(msg == \"error in tag: 10 wiretype: 2 offset: 24\", msg)\n\n-- random string\ntest = \"this is a test item over twenty bytes long\"\nok, msg = pcall(decode_message, test)\nassert(not ok)\nassert(msg == \"error in tag: 14 wiretype: 4 offset: 0\", msg)\n\n-- repeated packed with ints invalid length\ntest = \"\\010\\016\\111\\021\\235\\034\\090\\107\\077\\120\\169\\175\\058\\232\\153\\002\\231\\132\\016\\128\\148\\235\\220\\003\\082\\013\\010\\005count\\016\\002\\050\\003\\001\\001\"\nok, msg = pcall(decode_message, test)\nassert(not ok)\nassert(msg == \"error in tag: 10 wiretype: 2 offset: 24\", msg)\n\n-- invalid timestamp varint encoding\nlocal test = \"\\010\\016\\233\\213\\137\\149\\106\\254\\064\\066\\175\\098\\058\\163\\017\\067\\202\\068\\016\\128\\148\\235\\220\\220\\220\\220\\220\\220\\220\"\nok, msg = pcall(decode_message, test)\nassert(not ok)\nassert(msg == \"error in tag: 2 wiretype: 0 offset: 18\", msg)\n\n-- invalid length encoding\nlocal test = \"\\010\\016\\233\\213\\137\\149\\106\\254\\064\\066\\175\\098\\058\\163\\017\\067\\202\\068\\016\\128\\148\\235\\220\\003\\026\\128\\148\\235\\220\\220\\220\\220\\220\\220\\220type\"\nok, msg = pcall(decode_message, test)\nassert(not ok)\nassert(msg == \"error in tag: 3 wiretype: 2 offset: 24\", msg)\n\n\nfunction process_message()\n    msg = decode_message(read_message(\"raw\", nil, nil, true))\n    assert(msg.Timestamp == 1e9)\n    assert(#msg.Fields == 6)\n    return 0\nend\n"
  },
  {
    "path": "src/heka/test/lua/decode_message_benchmark.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nlocal test = \"\\010\\016\\096\\006\\214\\155\\119\\188\\078\\023\\172\\076\\081\\127\\129\\143\\250\\040\\016\\128\\148\\235\\220\\003\\082\\019\\010\\006\\110\\117\\109\\098\\101\\114\\016\\003\\057\\000\\000\\000\\000\\000\\000\\240\\063\\082\\044\\010\\007\\110\\117\\109\\098\\101\\114\\115\\016\\003\\026\\005\\099\\111\\117\\110\\116\\058\\024\\000\\000\\000\\000\\000\\000\\240\\063\\000\\000\\000\\000\\000\\000\\000\\064\\000\\000\\000\\000\\000\\000\\008\\064\\082\\014\\010\\005\\098\\111\\111\\108\\115\\016\\004\\066\\003\\001\\000\\000\\082\\010\\010\\004\\098\\111\\111\\108\\016\\004\\064\\001\\082\\016\\010\\006\\115\\116\\114\\105\\110\\103\\034\\006\\115\\116\\114\\105\\110\\103\\082\\021\\010\\007\\115\\116\\114\\105\\110\\103\\115\\034\\002\\115\\049\\034\\002\\115\\050\\034\\002\\115\\051\"\n\nfunction process_message()\n    local msg = decode_message(test)\n    return 0\nend\n"
  },
  {
    "path": "src/heka/test/lua/encode_message.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nrequire \"string\"\nrequire \"table\"\n\nlocal msgs = {\n    {\n        msg = {Timestamp = 0, Uuid = \"\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\"},\n        rv = \"\\010\\016\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\016\\000\\034\\002sl@\\000\\074\\002\\sh\"\n    },\n    {\n        msg = {Timestamp = 0, Uuid = \"\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\", Logger = \"l\", Hostname = \"h\"},\n        rv = \"\\010\\016\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\016\\000\\034\\001l@\\000\\074\\001\\h\"\n    },\n    {\n        msg = {Timestamp = 0, Uuid = \"\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\"},\n        rv = \"\\030\\002\\008\\030\\031\\010\\016\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\016\\000\\034\\002sl@\\000\\074\\002\\sh\",\n        framed = true,\n    },\n    {\n        msg = {Timestamp = 0, Uuid = \"\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\", Logger = \"l\", Hostname = \"h\",\n            Fields = {\n                number  = 1,\n                numbers = {value = {1,2,3}, representation = \"count\"},\n                string  = \"string\",\n                strings = {\"s1\",\"s2\",\"s3\"},\n                bool    = true,\n                bools   = {true,false,false}}},\n        rv = \"\\10\\16\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\16\\0\\34\\1\\108@\\0\\74\\1\\104\\82\\19\\10\\6\\110\\117\\109\\98\\101\\114\\16\\3\\57\\0\\0\\0\\0\\0\\0\\240\\63\\82\\44\\10\\7\\110\\117\\109\\98\\101\\114\\115\\16\\3\\26\\5\\99\\111\\117\\110\\116\\58\\24\\0\\0\\0\\0\\0\\0\\240\\63\\0\\0\\0\\0\\0\\0\\0\\64\\0\\0\\0\\0\\0\\0\\8\\64\\82\\14\\10\\5\\98\\111\\111\\108\\115\\16\\4\\66\\3\\1\\0\\0\\82\\10\\10\\4\\98\\111\\111\\108\\16\\4\\64\\1\\82\\16\\10\\6\\115\\116\\114\\105\\110\\103\\34\\6\\115\\116\\114\\105\\110\\103\\82\\21\\10\\7\\115\\116\\114\\105\\110\\103\\115\\34\\2\\115\\49\\34\\2\\115\\50\\34\\2\\115\\51\"\n    },\n    {\n        msg = {Timestamp = 0, Uuid = \"\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\", Logger = \"l\", Hostname = \"h\",\n            Fields = {\n                {name = \"number\"    ,value = 1},\n                {name = \"numbers\"   ,value = {1,2,3}, representation=\"count\"},\n                {name = \"string\"    ,value = \"string\"},\n                {name = \"strings\"   ,value = {\"s1\",\"s2\",\"s3\"}},\n                {name = \"bool\"      ,value = true},\n                {name = \"bools\"     ,value = {true,false,false}}}\n            },\n        rv = \"\\10\\16\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\16\\0\\34\\1\\108@\\0\\74\\1\\104\\82\\19\\10\\6\\110\\117\\109\\98\\101\\114\\16\\3\\57\\0\\0\\0\\0\\0\\0\\240\\63\\82\\44\\10\\7\\110\\117\\109\\98\\101\\114\\115\\16\\3\\26\\5\\99\\111\\117\\110\\116\\58\\24\\0\\0\\0\\0\\0\\0\\240\\63\\0\\0\\0\\0\\0\\0\\0\\64\\0\\0\\0\\0\\0\\0\\8\\64\\82\\16\\10\\6\\115\\116\\114\\105\\110\\103\\34\\6\\115\\116\\114\\105\\110\\103\\82\\21\\10\\7\\115\\116\\114\\105\\110\\103\\115\\34\\2\\115\\49\\34\\2\\115\\50\\34\\2\\115\\51\\82\\10\\10\\4\\98\\111\\111\\108\\16\\4\\64\\1\\82\\14\\10\\5\\98\\111\\111\\108\\115\\16\\4\\66\\3\\1\\0\\0\"\n    },\n    {\n        msg = {Timestamp = 0, Uuid = string.rep(\"\\0\", 16), Fields = {key = {value = \"value\", value_type = 0, representation = \"widget\"}}}, -- string\n        rv = \"\\10\\16\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\16\\0\\34\\2\\115\\108@\\0\\74\\2\\115\\104\\82\\20\\10\\3\\107\\101\\121\\26\\6\\119\\105\\100\\103\\101\\116\\34\\5\\118\\97\\108\\117\\101\",\n    },\n    {\n        msg = {Timestamp = 0, Uuid = string.rep(\"\\0\", 16), Fields = {key = {value = \"value\", value_type = 1, representation = \"widget\"}}}, -- bytes\n        rv = \"\\10\\16\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\16\\0\\34\\2\\115\\108@\\0\\74\\2\\115\\104\\82\\22\\10\\3\\107\\101\\121\\16\\1\\26\\6\\119\\105\\100\\103\\101\\116\\42\\5\\118\\97\\108\\117\\101\",\n    },\n    {\n        msg = {Timestamp = 0, Uuid = string.rep(\"\\0\", 16), Fields = {key = {value = 34, value_type = 2, representation = \"widget\"}}}, -- int\n        rv = \"\\10\\16\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\16\\0\\34\\2\\115\\108@\\0\\74\\2\\115\\104\\82\\17\\10\\3\\107\\101\\121\\16\\2\\26\\6\\119\\105\\100\\103\\101\\116\\48\\34\",\n    },\n    {\n        msg = {Timestamp = 0, Uuid = string.rep(\"\\0\", 16), Fields = {key = {value = 34, value_type = 3, representation = \"widget\"}}}, -- double\n        rv = \"\\10\\16\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\16\\0\\34\\2\\115\\108@\\0\\74\\2\\115\\104\\82\\24\\10\\3\\107\\101\\121\\16\\3\\26\\6\\119\\105\\100\\103\\101\\116\\57\\0\\0\\0\\0\\0\\0\\65\\64\",\n    },\n    {\n        msg = {Timestamp = 0, Uuid = string.rep(\"\\0\", 16), Fields = {key = {value = true, value_type = 4, representation = \"widget\"}}}, -- bool\n        rv = \"\\10\\16\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\16\\0\\34\\2\\115\\108@\\0\\74\\2\\115\\104\\82\\17\\10\\3\\107\\101\\121\\16\\4\\26\\6\\119\\105\\100\\103\\101\\116\\64\\1\",\n    },\n    {\n        msg = {Timestamp = 0, Uuid = string.rep(\"\\0\", 16), Fields = {key = {value = {1,2,3}, value_type = 2, representation = \"widget\"}}}, -- int\n        rv = \"\\10\\16\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\0\\16\\0\\34\\2\\115\\108@\\0\\74\\2\\115\\104\\82\\20\\10\\3\\107\\101\\121\\16\\2\\26\\6\\119\\105\\100\\103\\101\\116\\50\\3\\1\\2\\3\",\n    },\n}\n\nfor i, v in ipairs(msgs) do\n    local rv\n    if v.framed then\n        rv = encode_message(v.msg, v.framed)\n    else\n        rv = encode_message(v.msg)\n    end\n\n    if v.rv ~= rv then\n        --local et = {string.byte(v.rv, 1, -1)}\n        local rt = {string.byte(rv, 1, -1)}\n        assert(v.rv == rv, string.format(\"test: %d received: %s\", i, table.concat(rt, \" \")))\n    end\n\nend\n\nlocal ok, err = pcall(encode_message, \"foo\")\nif ok then error(\"encode_message should not accept a string\") end\nlocal eerr = \"bad argument #1 to '?' (table expected, got string)\"\nassert(eerr == err, string.format(\"expected: %s received: %s\", eerr, err))\n\nok, err = pcall(encode_message, \"\", true, \"extra\")\nassert(not ok)\nassert(\"bad argument #3 to '?' (incorrect number of arguments)\" == err, string.format(\"received: %s\", err))\n\nok, err = pcall(encode_message, {Fields = {foo = {value = {\"s\", true}}}})\nassert(not ok)\nassert(\"encode_message() failed: array has mixed types\" == err, string.format(\"received: %s\", err))\n\nok, err = pcall(encode_message, {Fields = { {noname = \"foo\", value = 1}} })\nassert(not ok)\nassert(\"encode_message() failed: field name must be a string\" == err, string.format(\"received: %s\", err))\n"
  },
  {
    "path": "src/heka/test/lua/iim.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nrequire \"string\"\nrequire \"io\"\n\n-- Table tests\nlocal msgs = {\n    {{Timestamp = 0, Uuid = \"\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\"}, nil},\n    {{Timestamp = 1, Uuid = \"00000000-0000-0000-0000-000000000000\"}, nil},\n    {{Timestamp = 2, Uuid = \"00000000-0000-0000-0000-000000000000\", Logger = \"logger\", Hostname = \"hostname\", Type = \"type\", Payload = \"payload\", EnvVersion = \"envversion\", Pid = 99, Severity = 5}, 99},\n    {{Timestamp = 3, Uuid = \"00000000-0000-0000-0000-000000000000\", Fields = {number=1,numbers={value={1,2,3}, representation=\"count\"},string=\"string\",strings={\"s1\",\"s2\",\"s3\"}, bool=true, bools={true,false,false}}}, \"foo.log:123\"},\n    {nil, \"foo.log:123\"},\n    {nil, 123},\n}\n\nlocal err_msgs = {\n    {msg = {Timestamp = 1e9, Fields = {counts={2,\"ten\",4}}}, err = \"inject_message() failed: array has mixed types\"},\n    {msg = {Timestamp = 1e9, Fields = {counts={}}}, err = \"inject_message() failed: unsupported type: nil\"},\n    {err = \"inject_message() message cannot be nil without a checkpoint update\"},\n    {msg = {Timestamp = 1e9, Fields = {counts={{1},{2}}}}, err = \"inject_message() failed: unsupported array type: table\"},\n    {msg = {Timestamp = 1e9, Fields = {counts={value=\"s\", value_type=2}}}, err = \"inject_message() failed: invalid string value_type: 2\"},\n    {msg = {Timestamp = 1e9, Fields = {counts={value=\"s\", value_type=3}}}, err = \"inject_message() failed: invalid string value_type: 3\"},\n    {msg = {Timestamp = 1e9, Fields = {counts={value=\"s\", value_type=4}}}, err = \"inject_message() failed: invalid string value_type: 4\"},\n    {msg = {Timestamp = 1e9, Fields = {counts={value=1, value_type=0}}}, err = \"inject_message() failed: invalid numeric value_type: 0\"},\n    {msg = {Timestamp = 1e9, Fields = {counts={value=1, value_type=1}}}, err = \"inject_message() failed: invalid numeric value_type: 1\"},\n    {msg = {Timestamp = 1e9, Fields = {counts={value=1, value_type=4}}}, err = \"inject_message() failed: invalid numeric value_type: 4\"},\n    {msg = {Timestamp = 1e9, Fields = {counts={value=true, value_type=0}}}, err = \"inject_message() failed: invalid boolean value_type: 0\"},\n    {msg = {Timestamp = 1e9, Fields = {counts={value=true, value_type=1}}}, err = \"inject_message() failed: invalid boolean value_type: 1\"},\n    {msg = {Timestamp = 1e9, Fields = {counts={value=true, value_type=2}}}, err = \"inject_message() failed: invalid boolean value_type: 2\"},\n    {msg = {Timestamp = 1e9, Fields = {counts={value=true, value_type=2}}}, err = \"inject_message() failed: invalid boolean value_type: 2\"},\n    {msg = {Timestamp = 1e9, Fields = {bf = {value=io.stdin, representation=\"bf\"}}}, err = \"inject_message() failed: userdata object does not implement lsb_output\"},\n}\n\nfor i, v in ipairs(msgs) do\n    local ok, err = pcall(inject_message, v[1], v[2])\n    assert(ok, string.format(\"test: %d err: %s\", i, tostring(err)))\nend\n\nfor i, v in ipairs(err_msgs) do\n    local ok, err = pcall(inject_message, v.msg)\n    if ok then error(string.format(\"test: %d should have failed\", i)) end\n    assert(v.err == err, string.format(\"test: %d expected: %s received: %s\", i, v.err, err))\nend\n\n-- Stream Reader tests\nrequire \"io\"\nlocal hsr = create_stream_reader(\"test\")\nok, err = pcall(inject_message, hsr)\nlocal eerr = \"inject_message() attempted to inject a nil message\"\nassert(eerr == err, string.format(\"expected: %s received: %s\", eerr, err))\nok, err = pcall(hsr.decode_message, hsr, true)\nassert(not ok)\nassert(\"buffer must be string\" == err, string.format(\"received: %s\", err))\nok, err = pcall(hsr.decode_message, hsr, \"\")\nassert(not ok)\nassert(\"empty protobuf string\" == err, string.format(\"received: %s\", err))\n\nhsr:decode_message(\"\\010\\016\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\016\\004\")\ninject_message(hsr)\nlocal ts = hsr:read_message(\"Timestamp\")\nassert(4 == ts, string.format(\"received: %g\", ts))\n\nlocal framed = \"\\030\\002\\008\\020\\031\\010\\016\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\016\\006\"\nlocal fh = assert(io.open(\"hekamsg.pb\", \"w+\"))\nfh:write(framed)\nfh:seek(\"set\")\nlocal found, consumed, read = hsr:find_message(fh)\nassert(not found)\nassert(0 == consumed, string.format(\"expected: 0 received %d\", consumed))\nassert(25 == read, string.format(\"expected: 25 received: %d\", read))\nfound, consumed, read = hsr:find_message(fh)\nassert(found)\nassert(25 == consumed, string.format(\"expected: 25 received %d\", consumed))\nassert(0 == read, string.format(\"expected: >0 received: %d\", read))\nfh:close()\n\nlocal found, consumed, need = hsr:find_message(framed)\nassert(true == found)\nassert(25 == consumed, string.format(\"expected: 25 received %d\", consumed))\nassert(0 < need, string.format(\"expected: >0 received: %d\", need))\n\nfound, consumed, need = hsr:find_message(\"\\0\\0\\0\\0\\0\\030\\002\\008\\020\\031\")\nassert(false == found)\nassert(5 == consumed, string.format(\"expected: 5 received %d\", consumed))\nassert(20 == need, string.format(\"expected: 20 received: %d\", need))\n\nlocal found, consumed, need = hsr:find_message(\"\")\nassert(not found)\n\nok, err = pcall(hsr.find_message, hsr, assert)\nassert(not ok, \"accepted function as second arg\")\n\nok, err = pcall(hsr.find_message, hsr, nil, \"str\")\nassert(not ok, \"accepted string as third arg\")\n\nok, err = pcall(hsr.find_message, hsr, hsr)\nassert(not ok, \"accepted non FILE userdata\")\n\nfh = assert(io.open(\"lua/iim.lua\"))\nfound, consumed, read = hsr:find_message(fh)\nfh:close()\nassert(false == found)\nassert(0 == consumed, string.format(\"expected: 0 received %d\", consumed))\nassert(0 < need, string.format(\"expected: >0 received: %d\", need))\n\nok, err = pcall(hsr.read_message)\nassert(not ok)\nassert(\"read_message() incorrect number of arguments\" == err, string.format(\"received: %s\", err))\n\nok, err = pcall(hsr.read_message, hsr, 1, 2, 3, 4)\nassert(not ok)\nassert(\"read_message() incorrect number of arguments\" == err, string.format(\"received: %s\", err))\n\nok, err = pcall(hsr.read_message, 1, 2)\nassert(not ok)\nassert(\"bad argument #1 to '?' (lsb.heka_stream_reader expected, got number)\" == err, string.format(\"received: %s\", err))\n\n\n-- String tests\nlocal pbstr = \"\\010\\016\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\016\\005\"\ninject_message(pbstr)\n\nok, err = pcall(inject_message, pbstr, 2)\nif ok then error(string.format(\"test should have failed\")) end\neerr = \"inject_message() failed: checkpoint update\"\nassert(eerr == err, string.format(\"expected: %s received: %s\", eerr, err))\n\nok, err = pcall(inject_message, \"\\000\")\nif ok then error(string.format(\"string test should have failed\")) end\nlocal eerr = \"inject_message() attempted to inject a invalid protobuf string\"\nassert(eerr == err, string.format(\"expected: %s received: %s\", eerr, err))\n\nok, err = pcall(inject_message, {})\nif ok then error(string.format(\"test should have failed\")) end\neerr = \"inject_message() failed: rejected by the callback rv: 1\"\nassert(eerr == err, string.format(\"expected: %s received: %s\", eerr, err))\n"
  },
  {
    "path": "src/heka/test/lua/input.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nassert(read_config)\nassert(decode_message)\nassert(inject_message)\nassert(create_stream_reader)\nassert(is_running)\nassert(not read_message)\nassert(not encode_message)\nassert(not update_checkpoint)\nassert(not add_to_payload)\nassert(not inject_payload)\n\nrequire \"string\"\nmsg = {Timestamp = 8}\n\nlocal work_cnt = 1\nlocal function add_work()\n    local cnt = 0\n    for i = 1, work_cnt * 1000 do\n        cnt = cnt + 1\n    end\n    work_cnt = work_cnt + 1\nend\n\nfunction process_message(cp)\n    if cp == 0 then\n        add_work()\n        return -2, \"host specific failure\"\n    elseif cp == 1 then\n        add_work()\n        return -1, \"failed\"\n    elseif cp == 2 then\n        add_work()\n        return 0, \"ok\"\n    elseif cp == 3 then\n        error(\"boom\")\n    elseif cp == 4 then\n        return 0, msg\n    elseif cp == 5 then\n        return msg\n    elseif cp == 6 then\n        error(string.rep(\"a\", 255))\n    elseif cp == \"string\" then\n        add_work()\n        return 0, \"string\"\n    elseif cp == 7 then\n        error(nil)\n    elseif cp == 8 then\n        assert(is_running(), \"running\")\n    elseif cp == 9 then\n        assert(not is_running(), \"not running\")\n    end\n    add_work()\n    return 0, \"no cp\"\nend\n"
  },
  {
    "path": "src/heka/test/lua/oim.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nrequire \"string\"\n\n-- Table tests\nlocal msgs = {\n    {Timestamp = 1, Uuid = \"\\001\\002\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\"},\n    {Pid = 2, Timestamp = 3, Uuid = \"\\004\\005\\006\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\", Logger = \"ignore\", Hostname = \"spoof\"},\n}\n\nlocal err_msgs = {\n    {err = \"bad argument #1 to '?' (table expected, got nil)\"},\n}\n\nfor i, v in ipairs(msgs) do\n    inject_message(v)\nend\n\nfor i, v in ipairs(err_msgs) do\n    local ok, err = pcall(inject_message, v.msg)\n    if ok then error(string.format(\"test: %d should have failed\", i)) end\n    assert(v.err == err, string.format(\"test: %d expected: %s received: %s\", i, v.err, err))\nend\n"
  },
  {
    "path": "src/heka/test/lua/output.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nlocal sid\n\nassert(read_config)\nassert(read_message)\nassert(decode_message)\nassert(encode_message)\nassert(update_checkpoint)\nassert(create_message_matcher)\nassert(not inject_message)\nassert(not add_to_payload)\nassert(not inject_payload)\n\nfunction process_message(sequence_id)\n    if not sequence_id then\n        update_checkpoint()\n        local ok, err = pcall(update_checkpoint, 1, 2, 3)\n        assert(not ok)\n        return 0\n    else\n        if not sid then\n            update_checkpoint(sequence_id, 7)\n            update_checkpoint(sequence_id)\n            local ok, err = pcall(update_checkpoint, true)\n            assert(not ok)\n            ok, err = pcall(update_checkpoint, sequence_id, \"foo\")\n            assert(not ok)\n            sid = sequence_id\n            return -5\n        else\n            local ok, mm = pcall(create_message_matcher, \"Type == 'type'\")\n            assert(ok, mm)\n            assert(mm:eval())\n\n            ok, mm = pcall(create_message_matcher, \"Type == 'foo'\")\n            assert(ok, mm)\n            assert(not mm:eval())\n\n            ok, err = pcall(create_message_matcher, \"Widget == 'foo'\")\n            assert(not ok)\n\n            ok, err = pcall(update_checkpoint, sequence_id)\n            assert(not ok)\n\n            return -3 -- retry\n        end\n    end\n    return 0\nend\n\nfunction timer_event(ns, shutdown)\n    local ok, mm = pcall(create_message_matcher, \"Type == 'foo'\");\n    assert(ok, mm)\n    ok, err = pcall(mm.eval, mm)\n    assert(err == \"no active message\")\nend\n"
  },
  {
    "path": "src/heka/test/lua/pm_no_return.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nfunction process_message()\nend\n\n"
  },
  {
    "path": "src/heka/test/lua/read_message.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nrequire \"string\"\n\nlocal tests = {\n    {\"Timestamp\", 1e9},\n    {\"Uuid\", \"abcdefghijklmnop\"},\n    {\"Type\", \"type\"},\n    {\"Logger\", \"logger\"},\n    {\"Payload\", \"payload\"},\n    {\"EnvVersion\", \"env_version\"},\n    {\"Hostname\", \"hostname\"},\n    {\"Severity\", 9},\n    {\"Pid\", nil},\n    {\"raw\", 208},\n    {\"size\", 208},\n    {\"framed\", 214},\n    {\"Fields[string]\", \"string\"},\n    {\"Fields[notfound]\", nil},\n}\n\nlocal fields = {\n    {{\"Fields[number]\"   , 0 , 0 }, 1},\n    {{\"Fields[number]\"   , 0 , 0, false }, 1},\n    {{\"Fields[numbers]\"  , 0 , 2 }, 3},\n    {{\"Fields[bool]\"     , 0 , 0 }, true},\n    {{\"Fields[bools]\"    , 0 , 1 }, false},\n    {{\"Fields[strings]\"  , 0 , 0 }, \"s1\"},\n    {{\"Fields[strings]\"  , 0 , 2 }, \"s3\"},\n    {{\"Fields[strings]\"  , 10, 0 }, nil},\n    {{\"Fields[strings]\"  , 0 , 10}, nil},\n    {{\"Fields[notfound]\" , 0 , 0 }, nil},\n}\n\nlocal errors = {\n    {\"Fields[string\"},\n    {\"morethan8\"},\n    {\"lt8\"},\n    {\"Fields[string]\", -1, 0},\n    {\"Fields[string]\", 0, -1},\n    {\"Fields[string]\", \"a\", 0},\n    {\"Fields[string]\", 0, \"a\"},\n    {\"Fields[string]\", 0, 0, \"str\"},\n}\n\n\nfunction process_message()\n    for i, v in ipairs(tests) do\n        local r = read_message(v[1])\n        if v[1] == \"raw\" or v[1] == \"framed\" then\n            assert(v[2] == string.len(r), string.format(\"test: %d expected: %d received: %d\", i, string.len(v[2]), string.len(r)))\n        elseif v[1] == \"size\" then\n            assert(v[2] == r, string.format(\"test: %d expected: %d received: %d\", i, v[2], r))\n        else\n            assert(v[2] == r, string.format(\"test: %d expected: %s received: %s\", i, tostring(v[2]), tostring(r)))\n        end\n    end\n\n    for i, v in ipairs(fields) do\n        local r = read_message(unpack(v[1]))\n        assert(v[2] == r, string.format(\"test: %d expected: %s received: %s\", i, tostring(v[2]), tostring(r)))\n    end\n\n    for i, v in ipairs(errors) do\n        local ok, r = pcall(read_message, unpack(v))\n        assert(not ok, string.format(\"test: %d should have errored\", i))\n    end\n\n    return 0\nend\n"
  },
  {
    "path": "src/heka/test/lua/read_message_zc.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nrequire \"string\"\n\nlocal tests = {\n    {read_message(\"Uuid\", 0, 0, true), \"abcdefghijklmnop\"},\n    {read_message(\"Type\", nil, nil, true), \"type\"},\n    {read_message(\"Logger\", 0, 0, true), \"logger\"},\n    {read_message(\"Payload\", 0, 0, true), \"payload\"},\n    {read_message(\"EnvVersion\", 0, 0, true), \"env_version\"},\n    {read_message(\"Hostname\", 0, 0, true), \"hostname\"},\n    {read_message(\"Fields[string]\"  , 0 , 0 , true), \"string\"},\n    {read_message(\"Fields[notfound]\", 0 , 0 , true), nil},\n    {read_message(\"Fields[strings]\" , 0 , 0 , true), \"s1\"},\n    {read_message(\"Fields[strings]\" , 0 , 2 , true), \"s3\"},\n    {read_message(\"Fields[strings]\" , 10, 0 , true), nil},\n    {read_message(\"Fields[strings]\" , 0 , 10, true), nil},\n    {read_message(\"Fields[notfound]\", 0 , 0 , true), nil},\n}\n\nlocal tests_size = {\n    {read_message(\"raw\", 0 , 0 , true), 208},\n    {read_message(\"framed\", 0 , 0 , true), 214},\n}\n\nlocal creation_errors = {\n    {\"Timestamp\", 0, 0, true},\n    {\"Severity\", 0, 0, true},\n    {\"Pid\", 0, 0, true},\n    {\"size\", 0, 0, true},\n    {\"Fields[string\", 0, 0, true},\n    {\"morethan8\", 0, 0, true},\n    {\"lt8\", 0, 0, true},\n    {\"Fields[string]\", -1, 0, true},\n    {\"Fields[string]\", 0, -1, true},\n    {\"Fields[string]\", \"a\", 0, true},\n    {\"Fields[string]\", 0, \"a\", true},\n    {\"Fields[string]\", 0, 0, true, 0},\n}\n\nlocal fetch_errors = {\n    read_message(\"Fields[bool]\", 0, 0, true),\n    read_message(\"Fields[number]\", 0, 0, true),\n}\n\nfunction process_message()\n    for i, v in ipairs(tests) do\n        local r = read_message_zc(v[1])\n        assert(v[2] == r, string.format(\"test: %d expected: %s received: %s\", i, tostring(v[2]), tostring(r)))\n    end\n\n    for i, v in ipairs(tests) do\n        local r = tostring(v[1])\n        assert(v[2] == r, string.format(\"test: %d expected: %s received: %s\", i, tostring(v[2]), tostring(r)))\n    end\n\n    add_to_payload(read_message(\"Uuid\", 0, 0, true))\n    add_to_payload(read_message(\"framed\", 0, 0, true))\n    inject_payload()\n\n    for i, v in ipairs(tests_size) do\n        local r = read_message_zc(v[1])\n        assert(v[2] == #r, string.format(\"test: %d expected: %d received: %d\", i, tostring(v[2]), tostring(#r)))\n    end\n\n    for i, v in ipairs(tests_size) do\n        local r = tostring(v[1])\n        assert(v[2] == #r, string.format(\"test: %d expected: %d received: %d\", i, tostring(v[2]), tostring(#r)))\n    end\n\n    for i, v in ipairs(creation_errors) do\n        local ok, r = pcall(read_message, unpack(v))\n        assert(not ok, string.format(\"test: %d creation should have errored\", i))\n    end\n\n    for i, v in ipairs(fetch_errors) do\n        local ok, r = pcall(read_message_zc, v)\n        assert(not ok, string.format(\"test: %d fetch should have errored\", i))\n    end\n    return 0\nend\n"
  },
  {
    "path": "src/heka/test/test.h.in",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Unit test setup @file */\n\n#ifndef test_h_\n#define test_h_\n\n#include \"luasandbox/test/mu_test.h\"\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define TEST_LUA_PATH \"${CMAKE_SOURCE_DIR}/modules/?.lua\"\n#define TEST_BASE_CPATH \"${CMAKE_BINARY_DIR}/ep_base/inst/lib/luasandbox/\"\n\n#ifdef _WIN32\n#define TEST_LUA_CPATH TEST_BASE_CPATH \"modules/?.dll;\" TEST_BASE_CPATH \"io_modules/?.dll\"\n#else\n#define TEST_LUA_CPATH TEST_BASE_CPATH \"modules/?.so;\" TEST_BASE_CPATH \"io_modules/?.so\"\n#endif\n\n#endif\n"
  },
  {
    "path": "src/heka/test/test_heka_sandbox.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Heka sandbox unit tests @file */\n\n#include \"test.h\"\n\n#include <ctype.h>\n#include <errno.h>\n#include <math.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../sandbox_impl.h\"\n#include \"luasandbox/heka/sandbox.h\"\n#include \"luasandbox_output.h\"\n\nstatic unsigned long long clockres = 1;\n\n// {Uuid=\"\" Timestamp = 1e9, Type=\"type\", Logger=\"logger\", Payload=\"payload\", EnvVersion=\"env_version\", Hostname=\"hostname\", Severity=9, Fields = {number=1,numbers={value={1,2,3}, representation=\"count\"},string=\"string\",strings={\"s1\",\"s2\",\"s3\"}, bool=true, bools={true,false,false}}}\nstatic char pb[] = \"\\x0a\\x10\" \"abcdefghijklmnop\" \"\\x10\\x80\\x94\\xeb\\xdc\\x03\\x1a\\x04\\x74\\x79\\x70\\x65\\x22\\x06\\x6c\\x6f\\x67\\x67\\x65\\x72\\x28\\x09\\x32\\x07\\x70\\x61\\x79\\x6c\\x6f\\x61\\x64\\x3a\\x0b\\x65\\x6e\\x76\\x5f\\x76\\x65\\x72\\x73\\x69\\x6f\\x6e\\x4a\\x08\\x68\\x6f\\x73\\x74\\x6e\\x61\\x6d\\x65\\x52\\x13\\x0a\\x06\\x6e\\x75\\x6d\\x62\\x65\\x72\\x10\\x03\\x39\\x00\\x00\\x00\\x00\\x00\\x00\\xf0\\x3f\\x52\\x2c\\x0a\\x07\\x6e\\x75\\x6d\\x62\\x65\\x72\\x73\\x10\\x03\\x1a\\x05\\x63\\x6f\\x75\\x6e\\x74\\x3a\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\xf0\\x3f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x40\\x52\\x0e\\x0a\\x05\\x62\\x6f\\x6f\\x6c\\x73\\x10\\x04\\x42\\x03\\x01\\x00\\x00\\x52\\x0a\\x0a\\x04\\x62\\x6f\\x6f\\x6c\\x10\\x04\\x40\\x01\\x52\\x10\\x0a\\x06\\x73\\x74\\x72\\x69\\x6e\\x67\\x22\\x06\\x73\\x74\\x72\\x69\\x6e\\x67\\x52\\x15\\x0a\\x07\\x73\\x74\\x72\\x69\\x6e\\x67\\x73\\x22\\x02\\x73\\x31\\x22\\x02\\x73\\x32\\x22\\x02\\x73\\x33\";\n\nchar *e = NULL;\n\nvoid dlog(void *context, const char *component, int level, const char *fmt, ...)\n{\n  (void)context;\n  va_list args;\n  va_start(args, fmt);\n  fprintf(stderr, \"%lld [%d] %s \", (long long)time(NULL), level,\n          component ? component : \"unnamed\");\n  vfprintf(stderr, fmt, args);\n  fwrite(\"\\n\", 1, 1, stderr);\n  va_end(args);\n}\nstatic lsb_logger logger = { .context = NULL, .cb = dlog };\n\n\nstatic int iim(void *parent, const char *pb, size_t pb_len, double cp_numeric,\n               const char *cp_string)\n{\n  if (!pb) {\n    return LSB_HEKA_IM_SUCCESS;\n  }\n\n  static int cnt = 0;\n  struct im_result {\n    const char  *pb;\n    size_t      pb_len;\n    double      cp_numeric;\n    const char  *cp_string;\n  };\n\n  struct im_result results[] = {\n    { .pb = \"\\x0a\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x00\\x22\\x03iim\\x40\\x00\\x4a\\x02hn\", .pb_len = 31, .cp_numeric = NAN, .cp_string = NULL },\n    { .pb = \"\\x0a\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x01\\x22\\x03iim\\x40\\x00\\x4a\\x02hn\", .pb_len = 31, .cp_numeric = NAN, .cp_string = NULL },\n    { .pb = \"\\x0a\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x02\\x1a\\x04\\x74\\x79\\x70\\x65\\x22\\x06\\x6c\\x6f\\x67\\x67\\x65\\x72\\x28\\x05\\x32\\x07\\x70\\x61\\x79\\x6c\\x6f\\x61\\x64\\x3a\\x0a\\x65\\x6e\\x76\\x76\\x65\\x72\\x73\\x69\\x6f\\x6e\\x40\\x63\\x4a\\x08\\x68\\x6f\\x73\\x74\\x6e\\x61\\x6d\\x65\", .pb_len = 69, .cp_numeric = 99, .cp_string = NULL },\n    { .pb = \"\\x0a\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x03\\x22\\x03iim\\x40\\x00\\x4a\\x02hn\\x52\\x13\\x0a\\x06\\x6e\\x75\\x6d\\x62\\x65\\x72\\x10\\x03\\x39\\x00\\x00\\x00\\x00\\x00\\x00\\xf0\\x3f\\x52\\x2c\\x0a\\x07\\x6e\\x75\\x6d\\x62\\x65\\x72\\x73\\x10\\x03\\x1a\\x05\\x63\\x6f\\x75\\x6e\\x74\\x3a\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\xf0\\x3f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x40\\x52\\x0e\\x0a\\x05\\x62\\x6f\\x6f\\x6c\\x73\\x10\\x04\\x42\\x03\\x01\\x00\\x00\\x52\\x0a\\x0a\\x04\\x62\\x6f\\x6f\\x6c\\x10\\x04\\x40\\x01\\x52\\x10\\x0a\\x06\\x73\\x74\\x72\\x69\\x6e\\x67\\x22\\x06\\x73\\x74\\x72\\x69\\x6e\\x67\\x52\\x15\\x0a\\x07\\x73\\x74\\x72\\x69\\x6e\\x67\\x73\\x22\\x02\\x73\\x31\\x22\\x02\\x73\\x32\\x22\\x02\\x73\\x33\", .pb_len = 167, .cp_numeric = NAN, .cp_string = \"foo.log:123\" },\n    { .pb = \"\\x0a\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x04\", .pb_len = 20, .cp_numeric = NAN, .cp_string = NULL },\n    { .pb = \"\\x0a\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x05\", .pb_len = 20, .cp_numeric = NAN, .cp_string = NULL },\n    { .pb = \"\\x0a\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x05\", .pb_len = 20, .cp_numeric = NAN, .cp_string = NULL },\n  };\n\n  if (cnt >= (int)(sizeof results / sizeof results[0])) {\n    fprintf(stderr, \"tests and results are mis-matched\\n\");\n    return LSB_HEKA_IM_ERROR;\n  }\n\n  if (parent) {\n    fprintf(stderr, \"test: %d parent set\\n\", cnt);\n  }\n\n  if (pb_len != results[cnt].pb_len) {\n    fprintf(stderr, \"test: %d pb len expected: %\" PRIuSIZE \" received: %\"\n            PRIuSIZE \"\\n\", cnt, results[cnt].pb_len, pb_len);\n    return 1;\n  }\n\n  if (memcmp(pb, results[cnt].pb, pb_len)) {\n    fprintf(stderr, \"test: %d\\nexpected: \", cnt);\n    for (size_t i = 0; i < results[cnt].pb_len; ++i) {\n      fprintf(stderr, \"\\\\x%02hhx\", results[cnt].pb[i]);\n    }\n    fprintf(stderr, \"\\nreceived: \");\n    for (size_t i = 0; i < pb_len; ++i) {\n      fprintf(stderr, \"\\\\x%02hhx\", pb[i]);\n    }\n    fprintf(stderr, \"\\n\");\n    return 1;\n  }\n\n  bool ncp_failed = false;\n  if (isnan(results[cnt].cp_numeric)) {\n    if (!isnan(cp_numeric)) {\n      ncp_failed = true;\n    }\n  } else if (results[cnt].cp_numeric != cp_numeric) {\n    ncp_failed = true;\n  }\n  if (ncp_failed) {\n    fprintf(stderr, \"test: %d cp_numeric expected: %g received: %g\\n\", cnt,\n            results[cnt].cp_numeric, cp_numeric);\n    return LSB_HEKA_IM_CHECKPOINT;\n  }\n\n  bool ncs_failed = false;\n  if (!results[cnt].cp_string) {\n    if (cp_string) {\n      ncs_failed = true;\n    }\n  } else if (!cp_string || strcmp(results[cnt].cp_string, cp_string)) {\n    ncs_failed = true;\n  }\n  if (ncs_failed) {\n    fprintf(stderr, \"test: %d cp_string expected: %s received: %s\\n\", cnt,\n            results[cnt].cp_string ? results[cnt].cp_string : \"NULL\",\n            cp_string ? cp_string : \"NULL\");\n    return LSB_HEKA_IM_CHECKPOINT;\n  }\n  cnt++;\n  return LSB_HEKA_IM_SUCCESS;\n}\n\n\nstatic int aim(void *parent, const char *pb, size_t pb_len)\n{\n  static int offset = 28; // skip Uuid and Timestamp\n  static int cnt = 0;\n  struct im_result {\n    const char  *pb;\n    size_t      pb_len;\n  };\n\n  struct im_result results[] = {\n    { .pb = \"\\x0a\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x8e\\xa8\\xf3\\xde\\x88\\xb5\\xb7\\x93\\x15\\x22\\x03\\x61\\x69\\x6d\\x40\\x00\\x4a\\x07\\x66\\x6f\\x6f\\x2e\\x63\\x6f\\x6d\", .pb_len = 44},\n    { .pb = \"\\x0a\\x10\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\xbf\\x97\\x9c\\xcc\\xbe\\xc2\\xb7\\x93\\x15\\x22\\x03\\x61\\x69\\x6d\\x40\\x00\\x4a\\x07\\x66\\x6f\\x6f\\x2e\\x63\\x6f\\x6d\\x00\\x00\\x00\\x00\\x0a\\x10\\x00\\x00\", .pb_len = 44},\n    { .pb = \"\\x0a\\x10\\xea\\x95\\xd4\\xfc\\x7c\\x10\\x40\\x95\\xa8\\x17\\xcb\\x56\\x26\\x91\\x8c\\x47\\x10\\xba\\xf6\\xd5\\xf9\\xfd\\xce\\xb7\\x93\\x15\\x1a\\x0e\\x69\\x6e\\x6a\\x65\\x63\\x74\\x5f\\x70\\x61\\x79\\x6c\\x6f\\x61\\x64\\x22\\x03\\x61\\x69\\x6d\\x32\\x07\\x66\\x6f\\x6f\\x20\\x62\\x61\\x72\\x40\\x00\\x4a\\x07\\x66\\x6f\\x6f\\x2e\\x63\\x6f\\x6d\\x52\\x13\\x0a\\x0c\\x70\\x61\\x79\\x6c\\x6f\\x61\\x64\\x5f\\x74\\x79\\x70\\x65\\x22\\x03\\x74\\x78\\x74\", .pb_len = 90},\n    { .pb = \"\\x0a\\x10\\xfd\\x49\\x92\\x77\\x02\\x37\\x4b\\xf0\\xaf\\x86\\x6f\\x9b\\x80\\x26\\xf4\\x35\\x10\\xaf\\xec\\x9e\\xa4\\xd8\\xcf\\xb7\\x93\\x15\\x1a\\x0e\\x69\\x6e\\x6a\\x65\\x63\\x74\\x5f\\x70\\x61\\x79\\x6c\\x6f\\x61\\x64\\x22\\x03\\x61\\x69\\x6d\\x32\\x07\\x66\\x6f\\x6f\\x20\\x62\\x61\\x72\\x40\\x00\\x4a\\x07\\x66\\x6f\\x6f\\x2e\\x63\\x6f\\x6d\\x52\\x13\\x0a\\x0c\\x70\\x61\\x79\\x6c\\x6f\\x61\\x64\\x5f\\x74\\x79\\x70\\x65\\x22\\x03\\x64\\x61\\x74\\x52\\x14\\x0a\\x0c\\x70\\x61\\x79\\x6c\\x6f\\x61\\x64\\x5f\\x6e\\x61\\x6d\\x65\\x22\\x04\\x74\\x65\\x73\\x74\", .pb_len = 112},\n    { .pb = \"\\x0a\\x10\\x7c\\x32\\xd6\\x23\\x98\\xe8\\x49\\x9e\\xa2\\xe8\\x0d\\x78\\x84\\x8e\\x75\\xb2\\x10\\xf7\\xf5\\xdb\\x89\\x88\\xe4\\xb7\\x93\\x15\\x22\\x03\\x61\\x69\\x6d\\x40\\x00\\x4a\\x07\\x66\\x6f\\x6f\\x2e\\x63\\x6f\\x6d\", .pb_len = 0},  }; // intentionally fail on size to to test the custom return value\n\n  if (cnt >= (int)(sizeof results / sizeof results[0])) {\n    fprintf(stderr, \"tests and results are mis-matched\\n\");\n    return LSB_HEKA_IM_LIMIT;\n  }\n\n  if (parent) {\n    fprintf(stderr, \"test: %d parent set\\n\", cnt);\n  }\n\n  if (pb_len != results[cnt].pb_len) {\n    fprintf(stderr, \"test: %d pb len expected: %\" PRIuSIZE \" received: %\"\n            PRIuSIZE \"\\n\", cnt, results[cnt].pb_len, pb_len);\n    cnt++;\n    return 99;\n  }\n\n  if (memcmp(pb + offset, results[cnt].pb + offset, pb_len - offset)) {\n    fprintf(stderr, \"test: %d\\nexpected: \", cnt);\n    for (size_t i = offset; i < results[cnt].pb_len; ++i) {\n      fprintf(stderr, \"\\\\x%02hhx\", results[cnt].pb[i]);\n    }\n    fprintf(stderr, \"\\nreceived: \");\n    for (size_t i = offset; i < pb_len; ++i) {\n      fprintf(stderr, \"\\\\x%02hhx\", pb[i]);\n    }\n    fprintf(stderr, \"\\n\");\n    return 1;\n  }\n  cnt++;\n  return LSB_HEKA_IM_SUCCESS;\n}\n\nstatic int aim1(void *parent, const char *pb, size_t pb_len)\n{\n  if (parent) {\n    fprintf(stderr, \"parent set\\n\");\n    return 1;\n  }\n  if (!pb) {\n    fprintf(stderr, \"pb null set\\n\");\n    return 1;\n  }\n  size_t expected = 308;\n  if (pb_len != expected) {\n    fprintf(stderr, \"pb_len expected: %\" PRIuSIZE \" received: %\" PRIuSIZE \"\\n\",\n            expected, pb_len);\n\n    for (size_t i = 0; i < pb_len; ++i) {\n      if (isprint(pb[i])) {\n        fprintf(stderr, \"%c\", pb[i]);\n      } else {\n        fprintf(stderr, \"\\\\x%02hhx\", pb[i]);\n      }\n    }\n    fprintf(stderr, \"\\n\");\n    return 1;\n  }\n  return LSB_HEKA_IM_SUCCESS;\n}\n\n\nstatic int ucp(void *parent, void *sequence_id)\n{\n  static int cnt = 0;\n  if (parent) return 1;\n  void *results[] = { NULL, (void *)99, (void *)99 };\n\n  if (cnt >= (int)(sizeof results / sizeof results[0])) {\n    fprintf(stderr, \"tests and results are mis-matched\\n\");\n    return 1;\n  }\n\n  if (results[cnt] != sequence_id) {\n    fprintf(stderr, \"expected: %p received: %p\\n\", results[cnt], sequence_id);\n    return 1;\n  }\n  cnt++;\n  return 0;\n}\n\n\nstatic int oim(void *parent, const char *pb, size_t pb_len)\n{\n  static int cnt = 0;\n  struct im_result {\n    const char  *pb;\n    size_t      pb_len;\n  };\n\n  struct im_result results[] = {\n    { .pb = \"\\x0a\\x10\\x01\\x02\\x03\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x01\\x22\\x03\\x6f\\x69\\x6d\\x40\\x00\\x4a\\x04\\x74\\x65\\x73\\x74\", .pb_len = 33 },\n    { .pb = \"\\x0a\\x10\\x04\\x05\\x06\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x10\\x03\\x22\\x06\\x69\\x67\\x6e\\x6f\\x72\\x65\\x40\\x02\\x4a\\x05\\x73\\x70\\x6f\\x6f\\x66\", .pb_len = 37 },  };\n\n  if (cnt >= (int)(sizeof results / sizeof results[0])) {\n    fprintf(stderr, \"tests and results are mis-matched\\n\");\n    return LSB_HEKA_IM_LIMIT;\n  }\n\n  if (parent) {\n    fprintf(stderr, \"test: %d parent set\\n\", cnt);\n  }\n\n  if (pb_len != results[cnt].pb_len) {\n    fprintf(stderr, \"test: %d pb len expected: %\" PRIuSIZE \" received: %\"\n            PRIuSIZE \"\\n\", cnt, results[cnt].pb_len, pb_len);\n    cnt++;\n    return 99;\n  }\n\n  if (memcmp(pb, results[cnt].pb, pb_len)) {\n    fprintf(stderr, \"test: %d\\nexpected: \", cnt);\n    for (size_t i = 0; i < results[cnt].pb_len; ++i) {\n      fprintf(stderr, \"\\\\x%02hhx\", results[cnt].pb[i]);\n    }\n    fprintf(stderr, \"\\nreceived: \");\n    for (size_t i = 0; i < pb_len; ++i) {\n      fprintf(stderr, \"\\\\x%02hhx\", pb[i]);\n    }\n    fprintf(stderr, \"\\n\");\n    return 1;\n  }\n  cnt++;\n  return LSB_HEKA_IM_SUCCESS;\n}\n\n\nstatic char* test_api_assertion()\n{\n  lsb_heka_message m;\n  mu_assert(!lsb_init_heka_message(&m, 1), \"failed to init message\");\n\n  lsb_heka_sandbox * isb,*asb,*osb;\n  isb = lsb_heka_create_input(NULL, \"lua/input.lua\", NULL, NULL, &logger, iim);\n  asb = lsb_heka_create_analysis(NULL, \"lua/analysis.lua\", NULL, NULL, &logger, aim);\n  osb = lsb_heka_create_output(NULL, \"lua/output.lua\", NULL, NULL, &logger, ucp);\n\n  mu_assert(isb, \"lsb_heka_create_input failed\");\n  mu_assert_rv(1, lsb_heka_pm_input(NULL, 0, NULL, false));\n  mu_assert_rv(1, lsb_heka_timer_event(isb, 0, false));\n\n  mu_assert(isb, \"lsb_heka_create_analysis failed\");\n  mu_assert_rv(1, lsb_heka_pm_analysis(NULL, NULL, false));\n  mu_assert_rv(1, lsb_heka_pm_analysis(asb, NULL, false));\n  mu_assert_rv(1, lsb_heka_timer_event(NULL, 0, false));\n  mu_assert_rv(1, lsb_heka_pm_analysis(isb, &m, false));\n\n  mu_assert(isb, \"lsb_heka_create_output failed\");\n  mu_assert_rv(1, lsb_heka_pm_output(NULL, NULL, NULL, false));\n  mu_assert_rv(1, lsb_heka_pm_output(osb, NULL, NULL, false));\n  mu_assert_rv(1, lsb_heka_pm_output(asb, &m, NULL, false));\n\n  lsb_heka_destroy_sandbox(isb);\n  lsb_heka_destroy_sandbox(asb);\n  lsb_heka_destroy_sandbox(osb);\n  lsb_free_heka_message(&m);\n\n  mu_assert(strcmp(lsb_heka_get_error(NULL), \"\") == 0, \"not empty\");\n  mu_assert(lsb_heka_get_lua_file(NULL) == NULL, \"not null\");\n  lsb_heka_stats stats = lsb_heka_get_stats(NULL);\n  mu_assert(0 == stats.mem_cur, \"received: %llu\", stats.mem_cur);\n  mu_assert(!lsb_heka_is_running(NULL), \"running is true\");\n  int state = lsb_heka_get_state(NULL);\n  mu_assert(LSB_UNKNOWN == state, \"received: %d\", state);\n  return NULL;\n}\n\n\nstatic char* test_create_input_sandbox()\n{\n  static const char *lua_file = \"lua/input.lua\";\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_input(NULL, lua_file, NULL, NULL, &logger, iim);\n  mu_assert(hsb, \"lsb_heka_create_input failed\");\n  const char *lfn = lsb_heka_get_lua_file(hsb);\n  mu_assert(strcmp(lua_file, lfn) == 0, \"expected %s received %s\", lua_file,\n            lfn);\n  e = lsb_heka_destroy_sandbox(hsb);\n\n  hsb = lsb_heka_create_input(NULL, \"notfourd.lua\", NULL, NULL, NULL,\n                              iim);\n  mu_assert(!hsb, \"lsb_heka_create_input succeeded\");\n\n  hsb = lsb_heka_create_input(NULL, NULL, NULL, NULL, NULL, iim);\n  mu_assert(!hsb, \"lsb_heka_create_input succeeded\");\n\n  hsb = lsb_heka_create_input(NULL, \"lua/input.lua\", NULL, NULL, NULL, NULL);\n  mu_assert(!hsb, \"lsb_heka_create_input succeeded\");\n  e = lsb_heka_destroy_sandbox(hsb); // test NULL\n\n  hsb = lsb_heka_create_input(NULL, lua_file, NULL, NULL, &logger, iim);\n  mu_assert(hsb, \"lsb_heka_create_input failed\");\n  lsb_heka_terminate_sandbox(hsb, \"boom\");\n  const char *err =  lsb_heka_get_error(hsb);\n  mu_assert(strcmp(\"boom\", err) == 0, \"received: %s\", err);\n  e = lsb_heka_destroy_sandbox(hsb);\n  mu_assert(!e, \"received %s\", e);\n  return NULL;\n}\n\n\nstatic char* test_create_analysis_sandbox()\n{\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_analysis(NULL, \"lua/analysis.lua\", NULL, NULL, &logger, aim);\n  mu_assert(hsb, \"lsb_heka_create_analysis failed\");\n  e = lsb_heka_destroy_sandbox(hsb);\n\n  hsb = lsb_heka_create_analysis(NULL, \"notfound.lua\", NULL, NULL, NULL, aim);\n  mu_assert(!hsb, \"lsb_heka_create_analysis succeeded\");\n\n  hsb = lsb_heka_create_analysis(NULL, NULL, NULL, NULL, NULL, aim);\n  mu_assert(!hsb, \"lsb_heka_create_analysis succeeded\");\n\n  hsb = lsb_heka_create_analysis(NULL, \"lua/analysis.lua\", NULL, NULL, NULL,\n                                 NULL);\n  mu_assert(!hsb, \"lsb_heka_create_analysis succeeded\");\n  return NULL;\n}\n\n\nstatic char* test_create_output_sandbox()\n{\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_output(NULL, \"lua/output.lua\", NULL, NULL, &logger, ucp);\n  mu_assert(hsb, \"lsb_heka_create_output failed\");\n  lsb_heka_destroy_sandbox(hsb);\n\n  hsb = lsb_heka_create_output(NULL, \"notfound.lua\", NULL, NULL, NULL, ucp);\n  mu_assert(!hsb, \"lsb_heka_create_output succeeded\");\n\n  hsb = lsb_heka_create_output(NULL, NULL, NULL, NULL, NULL, ucp);\n  mu_assert(!hsb, \"lsb_heka_create_output succeeded\");\n\n  hsb = lsb_heka_create_output(NULL, \"lua/output.lua\", NULL, NULL, NULL, NULL);\n  mu_assert(!hsb, \"lsb_heka_create_output succeeded\");\n  return NULL;\n}\n\n\nstatic char* test_timer_event()\n{\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_analysis(NULL, \"lua/analysis.lua\", NULL, NULL, &logger, aim);\n  mu_assert(hsb, \"lsb_heka_create_analysis failed\");\n  lsb_heka_stats stats = lsb_heka_get_stats(hsb);\n  mu_assert(0 < stats.mem_cur, \"received %llu\", stats.mem_cur);\n  mu_assert(0 < stats.mem_max, \"received %llu\", stats.mem_max);\n  mu_assert(0 == stats.out_max, \"received %llu\", stats.out_max);\n  mu_assert(0 < stats.ins_max, \"received %llu\", stats.ins_max);\n  mu_assert(0 == stats.pm_cnt, \"received %llu\", stats.pm_cnt);\n  mu_assert(0 == stats.pm_failures, \"received %llu\", stats.pm_failures);\n  mu_assert(0 == stats.pm_avg, \"received %g\", stats.pm_avg);\n  mu_assert(0 == stats.pm_sd, \"received %g\", stats.pm_sd);\n  mu_assert(0 == stats.te_avg, \"received %g\", stats.te_avg);\n  mu_assert(0 == stats.te_sd, \"received %g\", stats.te_sd);\n  mu_assert(true == lsb_heka_is_running(hsb), \"not running\");\n  int state = lsb_heka_get_state(hsb);\n  mu_assert(LSB_RUNNING == state, \"received: %d\", state);\n\n  mu_assert(0 == lsb_heka_timer_event(hsb, 0, false), \"err: %s\",\n            lsb_heka_get_error(hsb));\n  mu_assert(0 == lsb_heka_timer_event(hsb, 1, true), \"err: %s\",\n            lsb_heka_get_error(hsb));\n  mu_assert(1 == lsb_heka_timer_event(hsb, 2, false), \"err: %s\",\n            lsb_heka_get_error(hsb));\n  mu_assert(false == lsb_heka_is_running(hsb), \"not running\");\n  state = lsb_heka_get_state(hsb);\n  mu_assert(LSB_TERMINATED == state, \"received: %d\", state);\n\n  stats = lsb_heka_get_stats(hsb);\n  mu_assert(0 == stats.im_cnt, \"received %llu\", stats.im_cnt);\n  mu_assert(0 == stats.im_bytes, \"received %llu\", stats.im_bytes);\n  mu_assert(0 == stats.pm_cnt, \"received %llu\", stats.pm_cnt);\n  mu_assert(0 == stats.pm_failures, \"received %llu\", stats.pm_failures);\n  mu_assert(0 == stats.pm_avg, \"received %g\", stats.pm_avg);\n  mu_assert(0 == stats.pm_sd, \"received %g\", stats.pm_sd);\n  if (clockres <= 100) {\n    mu_assert(0 < stats.te_avg, \"received %g res %llu\", stats.te_avg, clockres);\n    mu_assert(0 < stats.te_sd, \"received %g\", stats.te_sd);\n  }\n\n  e = lsb_heka_destroy_sandbox(hsb);\n\n  hsb = lsb_heka_create_analysis(NULL, \"lua/pm_no_return.lua\", NULL, NULL, NULL, aim);\n  mu_assert(hsb, \"lsb_heka_create_analysis succeeded\");\n  mu_assert_rv(1, lsb_heka_timer_event(hsb, 0, false));\n  const char *err = lsb_heka_get_error(hsb);\n  mu_assert(strcmp(\"timer_event() function was not found\", err) == 0,\n            \"received: %s\", err);\n  e = lsb_heka_destroy_sandbox(hsb);\n  return NULL;\n}\n\n\nstatic char* test_clean_stop_input()\n{\n  static const char *state_file = \"stop.data\";\n  remove(state_file);\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_input(NULL, \"lua/input.lua\", state_file, NULL, &logger, iim);\n  mu_assert(hsb, \"lsb_heka_create_input failed\");\n\n  mu_assert(true == lsb_heka_is_running(hsb), \"running\");\n  int rv = lsb_heka_pm_input(hsb, 8, NULL, true);\n  const char *err = lsb_heka_get_error(hsb);\n  mu_assert(rv == 0, \"error: %s expected: %d received: %d\", err, 0, rv);\n  mu_assert(true == lsb_heka_is_running(hsb), \"running\");\n\n  lsb_heka_stop_sandbox_clean(hsb);\n  rv = lsb_heka_pm_input(hsb, 9, NULL, true);\n  err = lsb_heka_get_error(hsb);\n  mu_assert(rv == 0, \"error: %s expected: %d received: %d\", err, 0, rv);\n  mu_assert(false == lsb_heka_is_running(hsb), \"not running\");\n\n  e = lsb_heka_destroy_sandbox(hsb);\n  mu_assert(!e, \"received %s\", e);\n  return NULL;\n}\n\n\nstatic char* test_stop_input()\n{\n  static const char *state_file = \"stop.data\";\n  remove(state_file);\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_input(NULL, \"lua/input.lua\", state_file, NULL, &logger, iim);\n  mu_assert(hsb, \"lsb_heka_create_input failed\");\n  lsb_heka_stop_sandbox(hsb);\n  e = lsb_heka_destroy_sandbox(hsb);\n  mu_assert(!e, \"received %s\", e);\n  return NULL;\n}\n\n\nstatic char* test_pm_input()\n{\n  struct pm_result {\n    double      ncp;\n    const char  *scp;\n    int         rv;\n    const char  *err;\n  };\n\n  struct pm_result results[] = {\n    { .ncp = 0, .scp = NULL, .rv = -2, .err = \"host specific failure\" },\n    { .ncp = 1, .scp = NULL, .rv = -1, .err = \"failed\" },\n    { .ncp = 2, .scp = NULL, .rv = 0,  .err = \"ok\" },\n    { .ncp = NAN, .scp = \"string\", .rv = 0,  .err = \"string\" },\n    { .ncp = NAN, .scp = NULL, .rv = 0,  .err = \"no cp\" },\n  };\n\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_input(NULL, \"lua/input.lua\", NULL, NULL, &logger, iim);\n  mu_assert(hsb, \"lsb_heka_create_input failed\");\n  for (unsigned i = 0; i < sizeof results / sizeof results[0];++i){\n    int rv = lsb_heka_pm_input(hsb, results[i].ncp, results[i].scp, true);\n    const char *err = lsb_heka_get_error(hsb);\n    mu_assert(strcmp(results[i].err, err) == 0, \"expected: %s received: %s\",\n              results[i].err, err);\n    mu_assert(results[i].rv == rv, \"test: %u expected: %d received: %d\", i,\n              results[i].rv,\n              rv);\n  }\n  lsb_heka_stats stats = lsb_heka_get_stats(hsb);\n  mu_assert(5 == stats.pm_cnt, \"expected %llu\", stats.pm_cnt);\n  mu_assert(1 == stats.pm_failures, \"expected %llu\", stats.pm_failures);\n  mu_assert(0 < stats.mem_cur, \"expected %llu\", stats.mem_cur);\n  if (clockres <= 100) {\n    mu_assert(0 < stats.pm_avg, \"received %g res %llu\", stats.pm_avg, clockres);\n    mu_assert(0 < stats.pm_sd, \"received %g\", stats.pm_sd);\n  }\n  e = lsb_heka_destroy_sandbox(hsb);\n  return NULL;\n}\n\nstatic char* test_pm_error()\n{\n  struct pm_result {\n    double      ncp;\n    const char  *scp;\n    int         rv;\n    const char  *err;\n  };\n\n  struct pm_result results[] = {\n    { .ncp = 3, .scp = NULL, .rv = 1,  .err = \"process_message() lua/input.lua:39: boom\" },\n    { .ncp = 4, .scp = NULL, .rv = 1,  .err = \"process_message() must return a nil or string error message\" },\n    { .ncp = 5, .scp = NULL, .rv = 1,  .err = \"process_message() must return a numeric status code\" },\n    { .ncp = 6, .scp = NULL, .rv = 1,  .err = \"process_message() lua/input.lua:45: aaaaaaaaaaaaaaaaaaaaaaaaa\"\n      \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n      \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\"\n    }, // >max error message\n    { .ncp = 7, .scp = NULL, .rv = 1,  .err = \"process_message() <nil error message>\" },\n  };\n\n  lsb_heka_sandbox *hsb;\n  for (unsigned i = 0; i < sizeof results / sizeof results[0];++i){\n    hsb = lsb_heka_create_input(NULL, \"lua/input.lua\", NULL, NULL, &logger, iim);\n    mu_assert(hsb, \"lsb_heka_create_input failed\");\n    int rv = lsb_heka_pm_input(hsb, results[i].ncp, results[i].scp, true);\n    const char *err = lsb_heka_get_error(hsb);\n    mu_assert(strcmp(results[i].err, err) == 0, \"expected: %s received: %s\",\n              results[i].err, err);\n    mu_assert(results[i].rv == rv, \"test: %u expected: %d received: %d\", i,\n              results[i].rv,\n              rv);\n    e = lsb_heka_destroy_sandbox(hsb);\n  }\n  return NULL;\n}\n\n\nstatic char* test_pm_analysis()\n{\n  lsb_heka_message m;\n  mu_assert(!lsb_init_heka_message(&m, 1), \"failed to init message\");\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_analysis(NULL, \"lua/analysis.lua\", NULL, NULL, &logger, aim);\n  mu_assert(hsb, \"lsb_heka_create_analysis failed\");\n  mu_assert_rv(0, lsb_heka_pm_analysis(hsb, &m, false));\n  const char *err = lsb_heka_get_error(hsb);\n  const char *eerr = \"\";\n  mu_assert(strcmp(eerr, err) == 0, \"expected: %s received: %s\", eerr, err);\n  lsb_heka_stats stats = lsb_heka_get_stats(hsb);\n  mu_assert(1 == stats.pm_cnt, \"expected %llu\", stats.pm_cnt);\n  mu_assert(0 == stats.pm_failures, \"expected %llu\", stats.pm_failures);\n  mu_assert(0 == stats.pm_avg, \"received %g\", stats.pm_avg);\n  mu_assert(0 == stats.pm_sd, \"received %g\", stats.pm_sd);\n  e = lsb_heka_destroy_sandbox(hsb);\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_pm_no_return()\n{\n  lsb_heka_message m;\n  mu_assert(!lsb_init_heka_message(&m, 1), \"failed to init message\");\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_analysis(NULL, \"lua/pm_no_return.lua\", NULL, NULL, &logger, aim);\n  mu_assert_rv(1, lsb_heka_pm_analysis(hsb, &m, false));\n  const char *err = lsb_heka_get_error(hsb);\n  const char *eerr = \"process_message() must return a numeric status code\";\n  mu_assert(strcmp(eerr, err) == 0, \"expected: %s received: %s\", eerr, err);\n  e = lsb_heka_destroy_sandbox(hsb);\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_pm_output()\n{\n  lsb_heka_message m;\n  mu_assert(!lsb_init_heka_message(&m, 1), \"failed to init message\");\n  mu_assert(lsb_decode_heka_message(&m, pb, sizeof(pb) - 1, &logger), \"failed\");\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_output(NULL, \"lua/output.lua\", NULL,\n                               \"path = [[\" TEST_LUA_PATH \"]]\\n\"\n                               \"cpath = [[\" TEST_LUA_CPATH \"]]\\n\", &logger, ucp);\n  mu_assert(hsb, \"lsb_heka_create_output failed\");\n\n  mu_assert_rv(0, lsb_heka_pm_output(hsb, &m, NULL, false));\n  const char *err = lsb_heka_get_error(hsb);\n  const char *eerr = \"\";\n  mu_assert(strcmp(eerr, err) == 0, \"expected: %s received: %s\", eerr, err);\n  lsb_heka_stats stats = lsb_heka_get_stats(hsb);\n  mu_assert(0 == stats.pm_failures, \"expected %llu\", stats.pm_failures);\n\n  mu_assert_rv(-5, lsb_heka_pm_output(hsb, &m, (void *)99, false));\n  mu_assert(strcmp(eerr, err) == 0, \"expected: %s received: %s\", eerr, err);\n\n  stats = lsb_heka_get_stats(hsb);\n  mu_assert(2 == stats.pm_cnt, \"expected %llu\", stats.pm_cnt);\n  mu_assert(7 == stats.pm_failures, \"expected %llu\", stats.pm_failures);\n\n  mu_assert_rv(-3, lsb_heka_pm_output(hsb, &m, (void *)100, false));\n  mu_assert(strcmp(eerr, err) == 0, \"expected: %s received: %s\", eerr, err);\n  stats = lsb_heka_get_stats(hsb);\n  mu_assert(2 == stats.pm_cnt, \"expected %llu\", stats.pm_cnt);\n  mu_assert(7 == stats.pm_failures, \"expected %llu\", stats.pm_failures);\n\n  mu_assert_rv(0, lsb_heka_timer_event(hsb, 0, false));\n\n  e = lsb_heka_destroy_sandbox(hsb);\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_im_input()\n{\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_input(NULL, \"lua/iim.lua\", NULL,\n                              \"path = [[\" TEST_LUA_PATH \"]]\\n\"\n                              \"cpath = [[\" TEST_LUA_CPATH \"]]\\n\"\n                              \"Hostname = 'hn'\\n\"\n                              \"Logger = 'iim'\\n\",\n                              &logger, iim);\n  lsb_heka_stats stats = lsb_heka_get_stats(hsb);\n  mu_assert(6 == stats.im_cnt, \"received %llu\", stats.im_cnt);\n  mu_assert(338 == stats.im_bytes, \"received %llu\", stats.im_bytes);\n  mu_assert(hsb, \"lsb_heka_create_input failed\");\n  e = lsb_heka_destroy_sandbox(hsb);\n  return NULL;\n}\n\n\nstatic char* test_im_analysis()\n{\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_analysis(NULL, \"lua/aim.lua\", NULL,\n                                 \"Hostname = 'foo.com';Logger = 'aim'\",\n                                 &logger, aim);\n  lsb_heka_stats stats = lsb_heka_get_stats(hsb);\n  mu_assert(4 == stats.im_cnt, \"expected %llu\", stats.im_cnt);\n  mu_assert(290 == stats.im_bytes, \"expected %llu\", stats.im_bytes);\n  mu_assert(hsb, \"lsb_heka_create_analysis failed\");\n  e = lsb_heka_destroy_sandbox(hsb);\n  return NULL;\n}\n\n\nstatic char* test_im_output()\n{\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_output_im(NULL, \"lua/oim.lua\", NULL,\n                                  \"Hostname = 'test';Logger = 'oim'\",\n                               &logger, ucp, oim);\n  lsb_heka_stats stats = lsb_heka_get_stats(hsb);\n  mu_assert(2 == stats.im_cnt, \"received %llu\", stats.im_cnt);\n  mu_assert(70 == stats.im_bytes, \"received %llu\", stats.im_bytes);\n  mu_assert(hsb, \"lsb_heka_create_input failed\");\n  e = lsb_heka_destroy_sandbox(hsb);\n  return NULL;\n}\n\n\nstatic char* test_encode_message()\n{\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_output(NULL, \"lua/encode_message.lua\", NULL,\n                               \"path = [[\" TEST_LUA_PATH \"]]\\n\"\n                               \"cpath = [[\" TEST_LUA_CPATH \"]]\\n\"\n                               \"Hostname = 'sh'\\n\"\n                               \"Logger = 'sl'\\n\"\n                               \"Pid = 0\\n\",\n                               &logger, ucp);\n  mu_assert(hsb, \"lsb_heka_create_output failed\");\n  lsb_heka_stats stats = lsb_heka_get_stats(hsb);\n  mu_assert(164 == stats.out_max, \"received %llu\", stats.out_max);\n  e = lsb_heka_destroy_sandbox(hsb);\n  return NULL;\n}\n\n\nstatic char* test_decode_message()\n{\n  lsb_heka_message m;\n  mu_assert(!lsb_init_heka_message(&m, 1), \"failed to init message\");\n  mu_assert(lsb_decode_heka_message(&m, pb, sizeof(pb) - 1, &logger), \"failed\");\n\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_output(NULL, \"lua/decode_message.lua\", NULL, NULL, &logger, ucp);\n  mu_assert(hsb, \"lsb_heka_create_output failed\");\n  int rv = lsb_heka_pm_output(hsb, &m, NULL, false);\n  mu_assert(0 == rv, \"expected: %d received: %d %s\", 0, rv,\n            lsb_heka_get_error(hsb));\n  e = lsb_heka_destroy_sandbox(hsb);\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_read_message()\n{\n  lsb_heka_message m;\n  mu_assert(!lsb_init_heka_message(&m, 1), \"failed to init message\");\n  mu_assert(lsb_decode_heka_message(&m, pb, sizeof(pb) - 1, &logger), \"failed\");\n\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_analysis(NULL, \"lua/read_message.lua\", NULL, NULL, &logger, aim);\n  mu_assert(hsb, \"lsb_heka_create_analysis failed\");\n  int rv = lsb_heka_pm_analysis(hsb, &m, false);\n  mu_assert(0 == rv, \"expected: %d received: %d %s\", 0, rv,\n            lsb_heka_get_error(hsb));\n  e = lsb_heka_destroy_sandbox(hsb);\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic int rm_zc(lua_State *lua)\n{\n  int n = lua_gettop(lua);\n  luaL_argcheck(lua, n == 1, n, \"incorrect number of arguments\");\n  luaL_checktype(lua, 1, LUA_TUSERDATA);\n  lua_CFunction fp = lsb_get_zero_copy_function(lua, 1);\n  if (!fp) {\n    return luaL_argerror(lua, 1, \"no zero copy support\");\n  }\n  int results = fp(lua);\n  int start = n + 1;\n  int end = start + results;\n  int cnt = 0;\n  for (int i = start; i < end; ++i) {\n    switch (lua_type(lua, i)) {\n    case LUA_TSTRING:\n      lua_pushvalue(lua, i);\n      ++cnt;\n      break;\n    case LUA_TLIGHTUSERDATA:\n      {\n        const char *s = lua_touserdata(lua, i++);\n        size_t len = (size_t)lua_tointeger(lua, i);\n        if (s && len > 0) {\n          lua_pushlstring(lua, s, len);\n          ++cnt;\n        }\n      }\n      break;\n    default:\n      return luaL_error(lua, \"invalid zero copy return\");\n    }\n  }\n  if (cnt) {\n    lua_concat(lua, cnt);\n  } else {\n    lua_pushnil(lua);\n  }\n  return 1;\n}\n\n\nstatic char* test_read_message_zc()\n{\n  lsb_heka_message m;\n  mu_assert(!lsb_init_heka_message(&m, 1), \"failed to init message\");\n  mu_assert(lsb_decode_heka_message(&m, pb, sizeof(pb) - 1, &logger), \"failed\");\n\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_analysis(NULL, \"lua/read_message_zc.lua\", NULL, \"Hostname = 'ubuntu'\", &logger, aim1);\n  mu_assert(hsb, \"lsb_heka_create_analysis failed\");\n\n  lsb_add_function(hsb->lsb, rm_zc, \"read_message_zc\");\n  int rv = lsb_heka_pm_analysis(hsb, &m, false);\n  mu_assert(0 == rv, \"expected: %d received: %d %s\", 0, rv,\n            lsb_heka_get_error(hsb));\n  e = lsb_heka_destroy_sandbox(hsb);\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_get_message()\n{\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_analysis(NULL, \"lua/read_message.lua\", NULL, NULL, &logger, aim);\n  mu_assert(lsb_heka_get_message(NULL) == NULL, \"non NULL\");\n  mu_assert(lsb_heka_get_message(hsb) == NULL, \"non NULL\");\n  e = lsb_heka_destroy_sandbox(hsb);\n  return NULL;\n}\n\n\nstatic char* test_get_type()\n{\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_analysis(NULL, \"lua/read_message.lua\", NULL, NULL, &logger, aim);\n  char t = lsb_heka_get_type(NULL);\n  mu_assert(t == '\\0', \"received %c\", t);\n  t = lsb_heka_get_type(hsb);\n  mu_assert(t == 'a', \"received %c\", t);\n  e = lsb_heka_destroy_sandbox(hsb);\n  return NULL;\n}\n\n\nstatic char* benchmark_decode_message()\n{\n  int iter = 100000;\n\n  lsb_heka_message m;\n  mu_assert(!lsb_init_heka_message(&m, 1), \"failed to init message\");\n  lsb_heka_sandbox *hsb;\n  hsb = lsb_heka_create_output(NULL, \"lua/decode_message_benchmark.lua\", NULL,\n                               NULL, &logger, ucp);\n  clock_t t = clock();\n  for (int x = 0; x < iter; ++x) {\n    mu_assert(0 == lsb_heka_pm_output(hsb, &m, NULL, false), \"%s\",\n              lsb_heka_get_error(hsb));\n  }\n  t = clock() - t;\n  printf(\"benchmark_decode_message() %g seconds\\n\", ((double)t)\n         / CLOCKS_PER_SEC / iter);\n\n  mu_assert(hsb, \"lsb_heka_create_output failed\");\n  e = lsb_heka_destroy_sandbox(hsb);\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* all_tests()\n{\n#ifdef HAVE_CLOCK_GETTIME\n  struct timespec ts;\n  clock_getres(CLOCK_MONOTONIC, &ts);\n  clockres = ts.tv_sec * 1000000000ULL + ts.tv_nsec;\n#endif\n\n  mu_run_test(test_api_assertion);\n  mu_run_test(test_create_input_sandbox);\n  mu_run_test(test_create_analysis_sandbox);\n  mu_run_test(test_create_output_sandbox);\n  mu_run_test(test_timer_event);\n  mu_run_test(test_clean_stop_input);\n  mu_run_test(test_stop_input);\n  mu_run_test(test_pm_input);\n  mu_run_test(test_pm_error);\n  mu_run_test(test_pm_analysis);\n  mu_run_test(test_pm_no_return);\n  mu_run_test(test_pm_output);\n  mu_run_test(test_im_input);\n  mu_run_test(test_im_analysis);\n  mu_run_test(test_im_output);\n  mu_run_test(test_encode_message);\n  mu_run_test(test_decode_message);\n  mu_run_test(test_read_message);\n  mu_run_test(test_read_message_zc);\n  mu_run_test(test_get_message);\n  mu_run_test(test_get_type);\n\n  mu_run_test(benchmark_decode_message);\n  return NULL;\n}\n\n\nint main()\n{\n  char *result = all_tests();\n  if (result) {\n    printf(\"%s\\n\", result);\n  } else {\n    printf(\"ALL TESTS PASSED\\n\");\n  }\n  printf(\"Tests run: %d\\n\", mu_tests_run);\n  free(e);\n\n  return result != 0;\n}\n"
  },
  {
    "path": "src/lua/lapi.c",
    "content": "/*\n** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $\n** Lua API\n** See Copyright Notice in lua.h\n*/\n\n\n#include <assert.h>\n#include <math.h>\n#include <stdarg.h>\n#include <string.h>\n\n#define lapi_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lapi.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lundump.h\"\n#include \"lvm.h\"\n\n\n\nconst char lua_ident[] =\n  \"$Lua: \" LUA_RELEASE \" \" LUA_COPYRIGHT \" $\\n\"\n  \"$Authors: \" LUA_AUTHORS \" $\\n\"\n  \"$URL: www.lua.org $\\n\";\n\n\n\n#define api_checknelems(L, n)\tapi_check(L, (n) <= (L->top - L->base))\n\n#define api_checkvalidindex(L, i)\tapi_check(L, (i) != luaO_nilobject)\n\n#define api_incr_top(L)   {api_check(L, L->top < L->ci->top); L->top++;}\n\n\n\nstatic TValue *index2adr (lua_State *L, int idx) {\n  if (idx > 0) {\n    TValue *o = L->base + (idx - 1);\n    api_check(L, idx <= L->ci->top - L->base);\n    if (o >= L->top) return cast(TValue *, luaO_nilobject);\n    else return o;\n  }\n  else if (idx > LUA_REGISTRYINDEX) {\n    api_check(L, idx != 0 && -idx <= L->top - L->base);\n    return L->top + idx;\n  }\n  else switch (idx) {  /* pseudo-indices */\n    case LUA_REGISTRYINDEX: return registry(L);\n    case LUA_ENVIRONINDEX: {\n      Closure *func = curr_func(L);\n      sethvalue(L, &L->env, func->c.env);\n      return &L->env;\n    }\n    case LUA_GLOBALSINDEX: return gt(L);\n    default: {\n      Closure *func = curr_func(L);\n      idx = LUA_GLOBALSINDEX - idx;\n      return (idx <= func->c.nupvalues)\n                ? &func->c.upvalue[idx-1]\n                : cast(TValue *, luaO_nilobject);\n    }\n  }\n}\n\n\nstatic Table *getcurrenv (lua_State *L) {\n  if (L->ci == L->base_ci)  /* no enclosing function? */\n    return hvalue(gt(L));  /* use global table as environment */\n  else {\n    Closure *func = curr_func(L);\n    return func->c.env;\n  }\n}\n\n\nvoid luaA_pushobject (lua_State *L, const TValue *o) {\n  setobj2s(L, L->top, o);\n  api_incr_top(L);\n}\n\n\nLUA_API int lua_checkstack (lua_State *L, int size) {\n  int res = 1;\n  lua_lock(L);\n  if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK)\n    res = 0;  /* stack overflow */\n  else if (size > 0) {\n    luaD_checkstack(L, size);\n    if (L->ci->top < L->top + size)\n      L->ci->top = L->top + size;\n  }\n  lua_unlock(L);\n  return res;\n}\n\n\nLUA_API void lua_xmove (lua_State *from, lua_State *to, int n) {\n  int i;\n  if (from == to) return;\n  lua_lock(to);\n  api_checknelems(from, n);\n  api_check(from, G(from) == G(to));\n  api_check(from, to->ci->top - to->top >= n);\n  from->top -= n;\n  for (i = 0; i < n; i++) {\n    setobj2s(to, to->top++, from->top + i);\n  }\n  lua_unlock(to);\n}\n\n\nLUA_API void lua_setlevel (lua_State *from, lua_State *to) {\n  to->nCcalls = from->nCcalls;\n}\n\n\nLUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) {\n  lua_CFunction old;\n  lua_lock(L);\n  old = G(L)->panic;\n  G(L)->panic = panicf;\n  lua_unlock(L);\n  return old;\n}\n\n\nLUA_API lua_State *lua_newthread (lua_State *L) {\n  lua_State *L1;\n  lua_lock(L);\n  luaC_checkGC(L);\n  L1 = luaE_newthread(L);\n  setthvalue(L, L->top, L1);\n  api_incr_top(L);\n  lua_unlock(L);\n  luai_userstatethread(L, L1);\n  return L1;\n}\n\n\n\n/*\n** basic stack manipulation\n*/\n\n\nLUA_API int lua_gettop (lua_State *L) {\n  return cast_int(L->top - L->base);\n}\n\n\nLUA_API void lua_settop (lua_State *L, int idx) {\n  lua_lock(L);\n  if (idx >= 0) {\n    api_check(L, idx <= L->stack_last - L->base);\n    while (L->top < L->base + idx)\n      setnilvalue(L->top++);\n    L->top = L->base + idx;\n  }\n  else {\n    api_check(L, -(idx+1) <= (L->top - L->base));\n    L->top += idx+1;  /* `subtract' index (index is negative) */\n  }\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_remove (lua_State *L, int idx) {\n  StkId p;\n  lua_lock(L);\n  p = index2adr(L, idx);\n  api_checkvalidindex(L, p);\n  while (++p < L->top) setobjs2s(L, p-1, p);\n  L->top--;\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_insert (lua_State *L, int idx) {\n  StkId p;\n  StkId q;\n  lua_lock(L);\n  p = index2adr(L, idx);\n  api_checkvalidindex(L, p);\n  for (q = L->top; q>p; q--) setobjs2s(L, q, q-1);\n  setobjs2s(L, p, L->top);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_replace (lua_State *L, int idx) {\n  StkId o;\n  lua_lock(L);\n  /* explicit test for incompatible code */\n  if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci)\n    luaG_runerror(L, \"no calling environment\");\n  api_checknelems(L, 1);\n  o = index2adr(L, idx);\n  api_checkvalidindex(L, o);\n  if (idx == LUA_ENVIRONINDEX) {\n    Closure *func = curr_func(L);\n    api_check(L, ttistable(L->top - 1)); \n    func->c.env = hvalue(L->top - 1);\n    luaC_barrier(L, func, L->top - 1);\n  }\n  else {\n    setobj(L, o, L->top - 1);\n    if (idx < LUA_GLOBALSINDEX)  /* function upvalue? */\n      luaC_barrier(L, curr_func(L), L->top - 1);\n  }\n  L->top--;\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushvalue (lua_State *L, int idx) {\n  lua_lock(L);\n  setobj2s(L, L->top, index2adr(L, idx));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\n\n/*\n** access functions (stack -> C)\n*/\n\n\nLUA_API int lua_type (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return (o == luaO_nilobject) ? LUA_TNONE : ttype(o);\n}\n\n\nLUA_API const char *lua_typename (lua_State *L, int t) {\n  UNUSED(L);\n  return (t == LUA_TNONE) ? \"no value\" : luaT_typenames[t];\n}\n\n\nLUA_API int lua_iscfunction (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return iscfunction(o);\n}\n\n\nLUA_API int lua_tabletype (lua_State *L, int idx) {\n  StkId t;\n  int tt;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  tt = luaH_type(hvalue(t));\n  lua_unlock(L);\n  return tt;\n}\n\n\nLUA_API int lua_isnumber (lua_State *L, int idx) {\n  TValue n;\n  const TValue *o = index2adr(L, idx);\n  return tonumber(o, &n);\n}\n\n\nLUA_API int lua_isstring (lua_State *L, int idx) {\n  int t = lua_type(L, idx);\n  return (t == LUA_TSTRING || t == LUA_TNUMBER);\n}\n\n\nLUA_API int lua_isuserdata (lua_State *L, int idx) {\n  const TValue *o = index2adr(L, idx);\n  return (ttisuserdata(o) || ttislightuserdata(o));\n}\n\n\nLUA_API int lua_rawequal (lua_State *L, int index1, int index2) {\n  StkId o1 = index2adr(L, index1);\n  StkId o2 = index2adr(L, index2);\n  return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0\n         : luaO_rawequalObj(o1, o2);\n}\n\n\nLUA_API int lua_equal (lua_State *L, int index1, int index2) {\n  StkId o1, o2;\n  int i;\n  lua_lock(L);  /* may call tag method */\n  o1 = index2adr(L, index1);\n  o2 = index2adr(L, index2);\n  i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2);\n  lua_unlock(L);\n  return i;\n}\n\n\nLUA_API int lua_lessthan (lua_State *L, int index1, int index2) {\n  StkId o1, o2;\n  int i;\n  lua_lock(L);  /* may call tag method */\n  o1 = index2adr(L, index1);\n  o2 = index2adr(L, index2);\n  i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0\n       : luaV_lessthan(L, o1, o2);\n  lua_unlock(L);\n  return i;\n}\n\n\n\nLUA_API lua_Number lua_tonumber (lua_State *L, int idx) {\n  TValue n;\n  const TValue *o = index2adr(L, idx);\n  if (tonumber(o, &n))\n    return nvalue(o);\n  else\n    return 0;\n}\n\n\nLUA_API lua_Integer lua_tointeger (lua_State *L, int idx) {\n  TValue n;\n  const TValue *o = index2adr(L, idx);\n  if (tonumber(o, &n)) {\n    lua_Integer res;\n    lua_Number num = nvalue(o);\n    lua_number2integer(res, num);\n    return res;\n  }\n  else\n    return 0;\n}\n\n\nLUA_API int lua_toboolean (lua_State *L, int idx) {\n  const TValue *o = index2adr(L, idx);\n  return !l_isfalse(o);\n}\n\n\nLUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {\n  StkId o = index2adr(L, idx);\n  if (!ttisstring(o)) {\n    lua_lock(L);  /* `luaV_tostring' may create a new string */\n    if (!luaV_tostring(L, o)) {  /* conversion failed? */\n      if (len != NULL) *len = 0;\n      lua_unlock(L);\n      return NULL;\n    }\n    luaC_checkGC(L);\n    o = index2adr(L, idx);  /* previous call may reallocate the stack */\n    lua_unlock(L);\n  }\n  if (len != NULL) *len = tsvalue(o)->len;\n  return svalue(o);\n}\n\n\nLUA_API size_t lua_objlen (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  switch (ttype(o)) {\n    case LUA_TSTRING: return tsvalue(o)->len;\n    case LUA_TUSERDATA: return uvalue(o)->len;\n    case LUA_TTABLE: return luaH_getn(hvalue(o));\n    case LUA_TNUMBER: {\n      size_t l;\n      lua_lock(L);  /* `luaV_tostring' may create a new string */\n      l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0);\n      lua_unlock(L);\n      return l;\n    }\n    default: return 0;\n  }\n}\n\n\nLUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return (!iscfunction(o)) ? NULL : clvalue(o)->c.f;\n}\n\n\nLUA_API void *lua_touserdata (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  switch (ttype(o)) {\n    case LUA_TUSERDATA: return (rawuvalue(o) + 1);\n    case LUA_TLIGHTUSERDATA: return pvalue(o);\n    default: return NULL;\n  }\n}\n\n\nLUA_API lua_State *lua_tothread (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  return (!ttisthread(o)) ? NULL : thvalue(o);\n}\n\n\nLUA_API const void *lua_topointer (lua_State *L, int idx) {\n  StkId o = index2adr(L, idx);\n  switch (ttype(o)) {\n    case LUA_TTABLE: return hvalue(o);\n    case LUA_TFUNCTION: return clvalue(o);\n    case LUA_TTHREAD: return thvalue(o);\n    case LUA_TUSERDATA:\n    case LUA_TLIGHTUSERDATA:\n      return lua_touserdata(L, idx);\n    default: return NULL;\n  }\n}\n\n\n\n/*\n** push functions (C -> stack)\n*/\n\n\nLUA_API void lua_pushnil (lua_State *L) {\n  lua_lock(L);\n  setnilvalue(L->top);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushnumber (lua_State *L, lua_Number n) {\n  lua_lock(L);\n  setnvalue(L->top, n);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushinteger (lua_State *L, lua_Integer n) {\n  lua_lock(L);\n  setnvalue(L->top, cast_num(n));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) {\n  lua_lock(L);\n  luaC_checkGC(L);\n  setsvalue2s(L, L->top, luaS_newlstr(L, s, len));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushstring (lua_State *L, const char *s) {\n  if (s == NULL)\n    lua_pushnil(L);\n  else\n    lua_pushlstring(L, s, strlen(s));\n}\n\n\nLUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt,\n                                      va_list argp) {\n  const char *ret;\n  lua_lock(L);\n  luaC_checkGC(L);\n  ret = luaO_pushvfstring(L, fmt, argp);\n  lua_unlock(L);\n  return ret;\n}\n\n\nLUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) {\n  const char *ret;\n  va_list argp;\n  lua_lock(L);\n  luaC_checkGC(L);\n  va_start(argp, fmt);\n  ret = luaO_pushvfstring(L, fmt, argp);\n  va_end(argp);\n  lua_unlock(L);\n  return ret;\n}\n\n\nLUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {\n  Closure *cl;\n  lua_lock(L);\n  luaC_checkGC(L);\n  api_checknelems(L, n);\n  cl = luaF_newCclosure(L, n, getcurrenv(L));\n  cl->c.f = fn;\n  L->top -= n;\n  while (n--)\n    setobj2n(L, &cl->c.upvalue[n], L->top+n);\n  setclvalue(L, L->top, cl);\n  lua_assert(iswhite(obj2gco(cl)));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushboolean (lua_State *L, int b) {\n  lua_lock(L);\n  setbvalue(L->top, (b != 0));  /* ensure that true is 1 */\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_pushlightuserdata (lua_State *L, void *p) {\n  lua_lock(L);\n  setpvalue(L->top, p);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API int lua_pushthread (lua_State *L) {\n  lua_lock(L);\n  setthvalue(L, L->top, L);\n  api_incr_top(L);\n  lua_unlock(L);\n  return (G(L)->mainthread == L);\n}\n\n\n\n/*\n** get functions (Lua -> stack)\n*/\n\n\nLUA_API void lua_gettable (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  luaV_gettable(L, t, L->top - 1, L->top - 1);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_getfield (lua_State *L, int idx, const char *k) {\n  StkId t;\n  TValue key;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  setsvalue(L, &key, luaS_new(L, k));\n  luaV_gettable(L, t, &key, L->top);\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawget (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1));\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawgeti (lua_State *L, int idx, int n) {\n  StkId o;\n  lua_lock(L);\n  o = index2adr(L, idx);\n  api_check(L, ttistable(o));\n  setobj2s(L, L->top, luaH_getnum(hvalue(o), n));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_createtable (lua_State *L, int narray, int nrec) {\n  lua_lock(L);\n  luaC_checkGC(L);\n  sethvalue(L, L->top, luaH_new(L, narray, nrec));\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\nLUA_API int lua_getmetatable (lua_State *L, int objindex) {\n  const TValue *obj;\n  Table *mt = NULL;\n  int res;\n  lua_lock(L);\n  obj = index2adr(L, objindex);\n  switch (ttype(obj)) {\n    case LUA_TTABLE:\n      mt = hvalue(obj)->metatable;\n      break;\n    case LUA_TUSERDATA:\n      mt = uvalue(obj)->metatable;\n      break;\n    default:\n      mt = G(L)->mt[ttype(obj)];\n      break;\n  }\n  if (mt == NULL)\n    res = 0;\n  else {\n    sethvalue(L, L->top, mt);\n    api_incr_top(L);\n    res = 1;\n  }\n  lua_unlock(L);\n  return res;\n}\n\n\nLUA_API void lua_getfenv (lua_State *L, int idx) {\n  StkId o;\n  lua_lock(L);\n  o = index2adr(L, idx);\n  api_checkvalidindex(L, o);\n  switch (ttype(o)) {\n    case LUA_TFUNCTION:\n      sethvalue(L, L->top, clvalue(o)->c.env);\n      break;\n    case LUA_TUSERDATA:\n      sethvalue(L, L->top, uvalue(o)->env);\n      break;\n    case LUA_TTHREAD:\n      setobj2s(L, L->top,  gt(thvalue(o)));\n      break;\n    default:\n      setnilvalue(L->top);\n      break;\n  }\n  api_incr_top(L);\n  lua_unlock(L);\n}\n\n\n/*\n** set functions (stack -> Lua)\n*/\n\n\nLUA_API void lua_settable (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  api_checknelems(L, 2);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  luaV_settable(L, t, L->top - 2, L->top - 1);\n  L->top -= 2;  /* pop index and value */\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_setfield (lua_State *L, int idx, const char *k) {\n  StkId t;\n  TValue key;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  t = index2adr(L, idx);\n  api_checkvalidindex(L, t);\n  setsvalue(L, &key, luaS_new(L, k));\n  luaV_settable(L, t, &key, L->top - 1);\n  L->top--;  /* pop value */\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawset (lua_State *L, int idx) {\n  StkId t;\n  lua_lock(L);\n  api_checknelems(L, 2);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);\n  luaC_barriert(L, hvalue(t), L->top-1);\n  L->top -= 2;\n  lua_unlock(L);\n}\n\n\nLUA_API void lua_rawseti (lua_State *L, int idx, int n) {\n  StkId o;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  o = index2adr(L, idx);\n  api_check(L, ttistable(o));\n  setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);\n  luaC_barriert(L, hvalue(o), L->top-1);\n  L->top--;\n  lua_unlock(L);\n}\n\n\nLUA_API int lua_setmetatable (lua_State *L, int objindex) {\n  TValue *obj;\n  Table *mt;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  obj = index2adr(L, objindex);\n  api_checkvalidindex(L, obj);\n  if (ttisnil(L->top - 1))\n    mt = NULL;\n  else {\n    api_check(L, ttistable(L->top - 1));\n    mt = hvalue(L->top - 1);\n  }\n  switch (ttype(obj)) {\n    case LUA_TTABLE: {\n      hvalue(obj)->metatable = mt;\n      if (mt)\n        luaC_objbarriert(L, hvalue(obj), mt);\n      break;\n    }\n    case LUA_TUSERDATA: {\n      uvalue(obj)->metatable = mt;\n      if (mt)\n        luaC_objbarrier(L, rawuvalue(obj), mt);\n      break;\n    }\n    default: {\n      G(L)->mt[ttype(obj)] = mt;\n      break;\n    }\n  }\n  L->top--;\n  lua_unlock(L);\n  return 1;\n}\n\n\nLUA_API int lua_setfenv (lua_State *L, int idx) {\n  StkId o;\n  int res = 1;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  o = index2adr(L, idx);\n  api_checkvalidindex(L, o);\n  api_check(L, ttistable(L->top - 1));\n  switch (ttype(o)) {\n    case LUA_TFUNCTION:\n      clvalue(o)->c.env = hvalue(L->top - 1);\n      break;\n    case LUA_TUSERDATA:\n      uvalue(o)->env = hvalue(L->top - 1);\n      break;\n    case LUA_TTHREAD:\n      sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1));\n      break;\n    default:\n      res = 0;\n      break;\n  }\n  if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1));\n  L->top--;\n  lua_unlock(L);\n  return res;\n}\n\n\n/*\n** `load' and `call' functions (run Lua code)\n*/\n\n\n#define adjustresults(L,nres) \\\n    { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; }\n\n\n#define checkresults(L,na,nr) \\\n     api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)))\n\t\n\nLUA_API void lua_call (lua_State *L, int nargs, int nresults) {\n  StkId func;\n  lua_lock(L);\n  api_checknelems(L, nargs+1);\n  checkresults(L, nargs, nresults);\n  func = L->top - (nargs+1);\n  luaD_call(L, func, nresults);\n  adjustresults(L, nresults);\n  lua_unlock(L);\n}\n\n\n\n/*\n** Execute a protected call.\n*/\nstruct CallS {  /* data to `f_call' */\n  StkId func;\n  int nresults;\n};\n\n\nstatic void f_call (lua_State *L, void *ud) {\n  struct CallS *c = cast(struct CallS *, ud);\n  luaD_call(L, c->func, c->nresults);\n}\n\n\n\nLUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) {\n  struct CallS c;\n  int status;\n  ptrdiff_t func;\n  lua_lock(L);\n  api_checknelems(L, nargs+1);\n  checkresults(L, nargs, nresults);\n  if (errfunc == 0)\n    func = 0;\n  else {\n    StkId o = index2adr(L, errfunc);\n    api_checkvalidindex(L, o);\n    func = savestack(L, o);\n  }\n  c.func = L->top - (nargs+1);  /* function to be called */\n  c.nresults = nresults;\n  status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func);\n  adjustresults(L, nresults);\n  lua_unlock(L);\n  return status;\n}\n\n\n/*\n** Execute a protected C call.\n*/\nstruct CCallS {  /* data to `f_Ccall' */\n  lua_CFunction func;\n  void *ud;\n};\n\n\nstatic void f_Ccall (lua_State *L, void *ud) {\n  struct CCallS *c = cast(struct CCallS *, ud);\n  Closure *cl;\n  cl = luaF_newCclosure(L, 0, getcurrenv(L));\n  cl->c.f = c->func;\n  setclvalue(L, L->top, cl);  /* push function */\n  api_incr_top(L);\n  setpvalue(L->top, c->ud);  /* push only argument */\n  api_incr_top(L);\n  luaD_call(L, L->top - 2, 0);\n}\n\n\nLUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) {\n  struct CCallS c;\n  int status;\n  lua_lock(L);\n  c.func = func;\n  c.ud = ud;\n  status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0);\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,\n                      const char *chunkname) {\n  ZIO z;\n  int status;\n  lua_lock(L);\n  if (!chunkname) chunkname = \"?\";\n  luaZ_init(L, &z, reader, data);\n  status = luaD_protectedparser(L, &z, chunkname);\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) {\n  int status;\n  TValue *o;\n  lua_lock(L);\n  api_checknelems(L, 1);\n  o = L->top - 1;\n  if (isLfunction(o))\n    status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0);\n  else\n    status = 1;\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int  lua_status (lua_State *L) {\n  return L->status;\n}\n\n\n/*\n** Garbage-collection function\n*/\n\nLUA_API int lua_gc (lua_State *L, int what, int data) {\n  int res = 0;\n  global_State *g;\n  lua_lock(L);\n  g = G(L);\n  switch (what) {\n    case LUA_GCSTOP: {\n      g->GCthreshold = MAX_LUMEM;\n      break;\n    }\n    case LUA_GCRESTART: {\n      g->GCthreshold = g->totalbytes;\n      break;\n    }\n    case LUA_GCCOLLECT: {\n      luaC_fullgc(L);\n      break;\n    }\n    case LUA_GCCOUNT: {\n      /* GC values are expressed in Kbytes: #bytes/2^10 */\n      res = cast_int(g->totalbytes >> 10);\n      break;\n    }\n    case LUA_GCCOUNTB: {\n      res = cast_int(g->totalbytes & 0x3ff);\n      break;\n    }\n    case LUA_GCSTEP: {\n      lu_mem a = (cast(lu_mem, data) << 10);\n      if (a <= g->totalbytes)\n        g->GCthreshold = g->totalbytes - a;\n      else\n        g->GCthreshold = 0;\n      while (g->GCthreshold <= g->totalbytes) {\n        luaC_step(L);\n        if (g->gcstate == GCSpause) {  /* end of cycle? */\n          res = 1;  /* signal it */\n          break;\n        }\n      }\n      break;\n    }\n    case LUA_GCSETPAUSE: {\n      res = g->gcpause;\n      g->gcpause = data;\n      break;\n    }\n    case LUA_GCSETSTEPMUL: {\n      res = g->gcstepmul;\n      g->gcstepmul = data;\n      break;\n    }\n    default: res = -1;  /* invalid option */\n  }\n  lua_unlock(L);\n  return res;\n}\n\n\n\n/*\n** miscellaneous functions\n*/\n\n\nLUA_API int lua_error (lua_State *L) {\n  lua_lock(L);\n  api_checknelems(L, 1);\n  luaG_errormsg(L);\n  lua_unlock(L);\n  return 0;  /* to avoid warnings */\n}\n\n\nLUA_API int lua_next (lua_State *L, int idx) {\n  StkId t;\n  int more;\n  lua_lock(L);\n  t = index2adr(L, idx);\n  api_check(L, ttistable(t));\n  more = luaH_next(L, hvalue(t), L->top - 1);\n  if (more) {\n    api_incr_top(L);\n  }\n  else  /* no more elements */\n    L->top -= 1;  /* remove key */\n  lua_unlock(L);\n  return more;\n}\n\n\nLUA_API void lua_concat (lua_State *L, int n) {\n  lua_lock(L);\n  api_checknelems(L, n);\n  if (n >= 2) {\n    luaC_checkGC(L);\n    luaV_concat(L, n, cast_int(L->top - L->base) - 1);\n    L->top -= (n-1);\n  }\n  else if (n == 0) {  /* push empty string */\n    setsvalue2s(L, L->top, luaS_newlstr(L, \"\", 0));\n    api_incr_top(L);\n  }\n  /* else n == 1; nothing to do */\n  lua_unlock(L);\n}\n\n\nLUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) {\n  lua_Alloc f;\n  lua_lock(L);\n  if (ud) *ud = G(L)->ud;\n  f = G(L)->frealloc;\n  lua_unlock(L);\n  return f;\n}\n\n\nLUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) {\n  lua_lock(L);\n  G(L)->ud = ud;\n  G(L)->frealloc = f;\n  lua_unlock(L);\n}\n\n\nLUA_API void *lua_newuserdata (lua_State *L, size_t size) {\n  Udata *u;\n  lua_lock(L);\n  luaC_checkGC(L);\n  u = luaS_newudata(L, size, getcurrenv(L));\n  setuvalue(L, L->top, u);\n  api_incr_top(L);\n  lua_unlock(L);\n  return u + 1;\n}\n\n\n\n\nstatic const char *aux_upvalue (StkId fi, int n, TValue **val) {\n  Closure *f;\n  if (!ttisfunction(fi)) return NULL;\n  f = clvalue(fi);\n  if (f->c.isC) {\n    if (!(1 <= n && n <= f->c.nupvalues)) return NULL;\n    *val = &f->c.upvalue[n-1];\n    return \"\";\n  }\n  else {\n    Proto *p = f->l.p;\n    if (!(1 <= n && n <= p->sizeupvalues)) return NULL;\n    *val = f->l.upvals[n-1]->v;\n    return getstr(p->upvalues[n-1]);\n  }\n}\n\n\nLUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) {\n  const char *name;\n  TValue *val;\n  lua_lock(L);\n  name = aux_upvalue(index2adr(L, funcindex), n, &val);\n  if (name) {\n    setobj2s(L, L->top, val);\n    api_incr_top(L);\n  }\n  lua_unlock(L);\n  return name;\n}\n\n\nLUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) {\n  const char *name;\n  TValue *val;\n  StkId fi;\n  lua_lock(L);\n  fi = index2adr(L, funcindex);\n  api_checknelems(L, 1);\n  name = aux_upvalue(fi, n, &val);\n  if (name) {\n    L->top--;\n    setobj(L, val, L->top);\n    luaC_barrier(L, clvalue(fi), L->top);\n  }\n  lua_unlock(L);\n  return name;\n}\n\n"
  },
  {
    "path": "src/lua/lapi.h",
    "content": "/*\n** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions from Lua API\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lapi_h\n#define lapi_h\n\n\n#include \"lobject.h\"\n\n\nLUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o);\n\n#endif\n"
  },
  {
    "path": "src/lua/lauxlib.c",
    "content": "/*\n** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $\n** Auxiliary functions for building Lua libraries\n** See Copyright Notice in lua.h\n*/\n\n\n#include <ctype.h>\n#include <errno.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n\n/* This file uses only the official API of Lua.\n** Any function declared here could be written as an application function.\n*/\n\n#define lauxlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n\n\n#define FREELIST_REF\t0\t/* free list of references */\n\n\n/* convert a stack index to positive */\n#define abs_index(L, i)\t\t((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \\\n\t\t\t\t\tlua_gettop(L) + (i) + 1)\n\n\n/*\n** {======================================================\n** Error-report functions\n** =======================================================\n*/\n\n\nLUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {\n  lua_Debug ar;\n  if (!lua_getstack(L, 0, &ar))  /* no stack frame? */\n    return luaL_error(L, \"bad argument #%d (%s)\", narg, extramsg);\n  lua_getinfo(L, \"n\", &ar);\n  if (strcmp(ar.namewhat, \"method\") == 0) {\n    narg--;  /* do not count `self' */\n    if (narg == 0)  /* error is in the self argument itself? */\n      return luaL_error(L, \"calling \" LUA_QS \" on bad self (%s)\",\n                           ar.name, extramsg);\n  }\n  if (ar.name == NULL)\n    ar.name = \"?\";\n  return luaL_error(L, \"bad argument #%d to \" LUA_QS \" (%s)\",\n                        narg, ar.name, extramsg);\n}\n\n\nLUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) {\n  const char *msg = lua_pushfstring(L, \"%s expected, got %s\",\n                                    tname, luaL_typename(L, narg));\n  return luaL_argerror(L, narg, msg);\n}\n\n\nstatic void tag_error (lua_State *L, int narg, int tag) {\n  luaL_typerror(L, narg, lua_typename(L, tag));\n}\n\n\nLUALIB_API void luaL_where (lua_State *L, int level) {\n  lua_Debug ar;\n  if (lua_getstack(L, level, &ar)) {  /* check function at level */\n    lua_getinfo(L, \"Sl\", &ar);  /* get info about it */\n    if (ar.currentline > 0) {  /* is there info? */\n      lua_pushfstring(L, \"%s:%d: \", ar.short_src, ar.currentline);\n      return;\n    }\n  }\n  lua_pushliteral(L, \"\");  /* else, no information available... */\n}\n\n\nLUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {\n  va_list argp;\n  va_start(argp, fmt);\n  luaL_where(L, 1);\n  lua_pushvfstring(L, fmt, argp);\n  va_end(argp);\n  lua_concat(L, 2);\n  return lua_error(L);\n}\n\n/* }====================================================== */\n\n\nLUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,\n                                 const char *const lst[]) {\n  const char *name = (def) ? luaL_optstring(L, narg, def) :\n                             luaL_checkstring(L, narg);\n  int i;\n  for (i=0; lst[i]; i++)\n    if (strcmp(lst[i], name) == 0)\n      return i;\n  return luaL_argerror(L, narg,\n                       lua_pushfstring(L, \"invalid option \" LUA_QS, name));\n}\n\n\nLUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {\n  lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get registry.name */\n  if (!lua_isnil(L, -1))  /* name already in use? */\n    return 0;  /* leave previous value on top, but return 0 */\n  lua_pop(L, 1);\n  lua_newtable(L);  /* create metatable */\n  lua_pushvalue(L, -1);\n  lua_setfield(L, LUA_REGISTRYINDEX, tname);  /* registry.name = metatable */\n  return 1;\n}\n\n\nLUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {\n  void *p = lua_touserdata(L, ud);\n  if (p != NULL) {  /* value is a userdata? */\n    if (lua_getmetatable(L, ud)) {  /* does it have a metatable? */\n      lua_getfield(L, LUA_REGISTRYINDEX, tname);  /* get correct metatable */\n      if (lua_rawequal(L, -1, -2)) {  /* does it have the correct mt? */\n        lua_pop(L, 2);  /* remove both metatables */\n        return p;\n      }\n    }\n  }\n  luaL_typerror(L, ud, tname);  /* else error */\n  return NULL;  /* to avoid warnings */\n}\n\n\nLUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {\n  if (!lua_checkstack(L, space))\n    luaL_error(L, \"stack overflow (%s)\", mes);\n}\n\n\nLUALIB_API void luaL_checktype (lua_State *L, int narg, int t) {\n  if (lua_type(L, narg) != t)\n    tag_error(L, narg, t);\n}\n\n\nLUALIB_API void luaL_checkany (lua_State *L, int narg) {\n  if (lua_type(L, narg) == LUA_TNONE)\n    luaL_argerror(L, narg, \"value expected\");\n}\n\n\nLUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) {\n  const char *s = lua_tolstring(L, narg, len);\n  if (!s) tag_error(L, narg, LUA_TSTRING);\n  return s;\n}\n\n\nLUALIB_API const char *luaL_optlstring (lua_State *L, int narg,\n                                        const char *def, size_t *len) {\n  if (lua_isnoneornil(L, narg)) {\n    if (len)\n      *len = (def ? strlen(def) : 0);\n    return def;\n  }\n  else return luaL_checklstring(L, narg, len);\n}\n\n\nLUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) {\n  lua_Number d = lua_tonumber(L, narg);\n  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */\n    tag_error(L, narg, LUA_TNUMBER);\n  return d;\n}\n\n\nLUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) {\n  return luaL_opt(L, luaL_checknumber, narg, def);\n}\n\n\nLUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) {\n  lua_Integer d = lua_tointeger(L, narg);\n  if (d == 0 && !lua_isnumber(L, narg))  /* avoid extra test when d is not 0 */\n    tag_error(L, narg, LUA_TNUMBER);\n  return d;\n}\n\n\nLUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,\n                                                      lua_Integer def) {\n  return luaL_opt(L, luaL_checkinteger, narg, def);\n}\n\n\nLUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {\n  if (!lua_getmetatable(L, obj))  /* no metatable? */\n    return 0;\n  lua_pushstring(L, event);\n  lua_rawget(L, -2);\n  if (lua_isnil(L, -1)) {\n    lua_pop(L, 2);  /* remove metatable and metafield */\n    return 0;\n  }\n  else {\n    lua_remove(L, -2);  /* remove only metatable */\n    return 1;\n  }\n}\n\n\nLUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {\n  obj = abs_index(L, obj);\n  if (!luaL_getmetafield(L, obj, event))  /* no metafield? */\n    return 0;\n  lua_pushvalue(L, obj);\n  lua_call(L, 1, 1);\n  return 1;\n}\n\n\nLUALIB_API void (luaL_register) (lua_State *L, const char *libname,\n                                const luaL_Reg *l) {\n  luaI_openlib(L, libname, l, 0);\n}\n\n\nstatic int libsize (const luaL_Reg *l) {\n  int size = 0;\n  for (; l->name; l++) size++;\n  return size;\n}\n\n\nLUALIB_API void luaI_openlib (lua_State *L, const char *libname,\n                              const luaL_Reg *l, int nup) {\n  if (libname) {\n    int size = libsize(l);\n    /* check whether lib already exists */\n    luaL_findtable(L, LUA_REGISTRYINDEX, \"_LOADED\", 1);\n    lua_getfield(L, -1, libname);  /* get _LOADED[libname] */\n    if (!lua_istable(L, -1)) {  /* not found? */\n      lua_pop(L, 1);  /* remove previous result */\n      /* try global variable (and create one if it does not exist) */\n      if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)\n        luaL_error(L, \"name conflict for module \" LUA_QS, libname);\n      lua_pushvalue(L, -1);\n      lua_setfield(L, -3, libname);  /* _LOADED[libname] = new table */\n    }\n    lua_remove(L, -2);  /* remove _LOADED table */\n    lua_insert(L, -(nup+1));  /* move library table to below upvalues */\n  }\n  for (; l->name; l++) {\n    int i;\n    for (i=0; i<nup; i++)  /* copy upvalues to the top */\n      lua_pushvalue(L, -nup);\n    lua_pushcclosure(L, l->func, nup);\n    lua_setfield(L, -(nup+2), l->name);\n  }\n  lua_pop(L, nup);  /* remove upvalues */\n}\n\n\n\n/*\n** {======================================================\n** getn-setn: size for arrays\n** =======================================================\n*/\n\n#if defined(LUA_COMPAT_GETN)\n\nstatic int checkint (lua_State *L, int topop) {\n  int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1;\n  lua_pop(L, topop);\n  return n;\n}\n\n\nstatic void getsizes (lua_State *L) {\n  lua_getfield(L, LUA_REGISTRYINDEX, \"LUA_SIZES\");\n  if (lua_isnil(L, -1)) {  /* no `size' table? */\n    lua_pop(L, 1);  /* remove nil */\n    lua_newtable(L);  /* create it */\n    lua_pushvalue(L, -1);  /* `size' will be its own metatable */\n    lua_setmetatable(L, -2);\n    lua_pushliteral(L, \"kv\");\n    lua_setfield(L, -2, \"__mode\");  /* metatable(N).__mode = \"kv\" */\n    lua_pushvalue(L, -1);\n    lua_setfield(L, LUA_REGISTRYINDEX, \"LUA_SIZES\");  /* store in register */\n  }\n}\n\n\nLUALIB_API void luaL_setn (lua_State *L, int t, int n) {\n  t = abs_index(L, t);\n  lua_pushliteral(L, \"n\");\n  lua_rawget(L, t);\n  if (checkint(L, 1) >= 0) {  /* is there a numeric field `n'? */\n    lua_pushliteral(L, \"n\");  /* use it */\n    lua_pushinteger(L, n);\n    lua_rawset(L, t);\n  }\n  else {  /* use `sizes' */\n    getsizes(L);\n    lua_pushvalue(L, t);\n    lua_pushinteger(L, n);\n    lua_rawset(L, -3);  /* sizes[t] = n */\n    lua_pop(L, 1);  /* remove `sizes' */\n  }\n}\n\n\nLUALIB_API int luaL_getn (lua_State *L, int t) {\n  int n;\n  t = abs_index(L, t);\n  lua_pushliteral(L, \"n\");  /* try t.n */\n  lua_rawget(L, t);\n  if ((n = checkint(L, 1)) >= 0) return n;\n  getsizes(L);  /* else try sizes[t] */\n  lua_pushvalue(L, t);\n  lua_rawget(L, -2);\n  if ((n = checkint(L, 2)) >= 0) return n;\n  return (int)lua_objlen(L, t);\n}\n\n#endif\n\n/* }====================================================== */\n\n\n\nLUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,\n                                                               const char *r) {\n  const char *wild;\n  size_t l = strlen(p);\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  while ((wild = strstr(s, p)) != NULL) {\n    luaL_addlstring(&b, s, wild - s);  /* push prefix */\n    luaL_addstring(&b, r);  /* push replacement in place of pattern */\n    s = wild + l;  /* continue after `p' */\n  }\n  luaL_addstring(&b, s);  /* push last suffix */\n  luaL_pushresult(&b);\n  return lua_tostring(L, -1);\n}\n\n\nLUALIB_API const char *luaL_findtable (lua_State *L, int idx,\n                                       const char *fname, int szhint) {\n  const char *e;\n  lua_pushvalue(L, idx);\n  do {\n    e = strchr(fname, '.');\n    if (e == NULL) e = fname + strlen(fname);\n    lua_pushlstring(L, fname, e - fname);\n    lua_rawget(L, -2);\n    if (lua_isnil(L, -1)) {  /* no such field? */\n      lua_pop(L, 1);  /* remove this nil */\n      lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */\n      lua_pushlstring(L, fname, e - fname);\n      lua_pushvalue(L, -2);\n      lua_settable(L, -4);  /* set new table into field */\n    }\n    else if (!lua_istable(L, -1)) {  /* field has a non-table value? */\n      lua_pop(L, 2);  /* remove table and value */\n      return fname;  /* return problematic part of the name */\n    }\n    lua_remove(L, -2);  /* remove previous table */\n    fname = e + 1;\n  } while (*e == '.');\n  return NULL;\n}\n\n\n\n/*\n** {======================================================\n** Generic Buffer manipulation\n** =======================================================\n*/\n\n\n#define bufflen(B)\t((B)->p - (B)->buffer)\n#define bufffree(B)\t((size_t)(LUAL_BUFFERSIZE - bufflen(B)))\n\n#define LIMIT\t(LUA_MINSTACK/2)\n\n\nstatic int emptybuffer (luaL_Buffer *B) {\n  size_t l = bufflen(B);\n  if (l == 0) return 0;  /* put nothing on stack */\n  else {\n    lua_pushlstring(B->L, B->buffer, l);\n    B->p = B->buffer;\n    B->lvl++;\n    return 1;\n  }\n}\n\n\nstatic void adjuststack (luaL_Buffer *B) {\n  if (B->lvl > 1) {\n    lua_State *L = B->L;\n    int toget = 1;  /* number of levels to concat */\n    size_t toplen = lua_strlen(L, -1);\n    do {\n      size_t l = lua_strlen(L, -(toget+1));\n      if (B->lvl - toget + 1 >= LIMIT || toplen > l) {\n        toplen += l;\n        toget++;\n      }\n      else break;\n    } while (toget < B->lvl);\n    lua_concat(L, toget);\n    B->lvl = B->lvl - toget + 1;\n  }\n}\n\n\nLUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) {\n  if (emptybuffer(B))\n    adjuststack(B);\n  return B->buffer;\n}\n\n\nLUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) {\n  while (l--)\n    luaL_addchar(B, *s++);\n}\n\n\nLUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {\n  luaL_addlstring(B, s, strlen(s));\n}\n\n\nLUALIB_API void luaL_pushresult (luaL_Buffer *B) {\n  emptybuffer(B);\n  lua_concat(B->L, B->lvl);\n  B->lvl = 1;\n}\n\n\nLUALIB_API void luaL_addvalue (luaL_Buffer *B) {\n  lua_State *L = B->L;\n  size_t vl;\n  const char *s = lua_tolstring(L, -1, &vl);\n  if (vl <= bufffree(B)) {  /* fit into buffer? */\n    memcpy(B->p, s, vl);  /* put it there */\n    B->p += vl;\n    lua_pop(L, 1);  /* remove from stack */\n  }\n  else {\n    if (emptybuffer(B))\n      lua_insert(L, -2);  /* put buffer before new value */\n    B->lvl++;  /* add new value into B stack */\n    adjuststack(B);\n  }\n}\n\n\nLUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {\n  B->L = L;\n  B->p = B->buffer;\n  B->lvl = 0;\n}\n\n/* }====================================================== */\n\n\nLUALIB_API int luaL_ref (lua_State *L, int t) {\n  int ref;\n  t = abs_index(L, t);\n  if (lua_isnil(L, -1)) {\n    lua_pop(L, 1);  /* remove from stack */\n    return LUA_REFNIL;  /* `nil' has a unique fixed reference */\n  }\n  lua_rawgeti(L, t, FREELIST_REF);  /* get first free element */\n  ref = (int)lua_tointeger(L, -1);  /* ref = t[FREELIST_REF] */\n  lua_pop(L, 1);  /* remove it from stack */\n  if (ref != 0) {  /* any free element? */\n    lua_rawgeti(L, t, ref);  /* remove it from list */\n    lua_rawseti(L, t, FREELIST_REF);  /* (t[FREELIST_REF] = t[ref]) */\n  }\n  else {  /* no free elements */\n    ref = (int)lua_objlen(L, t);\n    ref++;  /* create new reference */\n  }\n  lua_rawseti(L, t, ref);\n  return ref;\n}\n\n\nLUALIB_API void luaL_unref (lua_State *L, int t, int ref) {\n  if (ref >= 0) {\n    t = abs_index(L, t);\n    lua_rawgeti(L, t, FREELIST_REF);\n    lua_rawseti(L, t, ref);  /* t[ref] = t[FREELIST_REF] */\n    lua_pushinteger(L, ref);\n    lua_rawseti(L, t, FREELIST_REF);  /* t[FREELIST_REF] = ref */\n  }\n}\n\n\n\n/*\n** {======================================================\n** Load functions\n** =======================================================\n*/\n\ntypedef struct LoadF {\n  int extraline;\n  FILE *f;\n  char buff[LUAL_BUFFERSIZE];\n} LoadF;\n\n\nstatic const char *getF (lua_State *L, void *ud, size_t *size) {\n  LoadF *lf = (LoadF *)ud;\n  (void)L;\n  if (lf->extraline) {\n    lf->extraline = 0;\n    *size = 1;\n    return \"\\n\";\n  }\n  if (feof(lf->f)) return NULL;\n  *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f);\n  return (*size > 0) ? lf->buff : NULL;\n}\n\n\nstatic int errfile (lua_State *L, const char *what, int fnameindex) {\n  const char *serr = strerror(errno);\n  const char *filename = lua_tostring(L, fnameindex) + 1;\n  lua_pushfstring(L, \"cannot %s %s: %s\", what, filename, serr);\n  lua_remove(L, fnameindex);\n  return LUA_ERRFILE;\n}\n\n\nLUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {\n  LoadF lf;\n  int status, readstatus;\n  int c;\n  int fnameindex = lua_gettop(L) + 1;  /* index of filename on the stack */\n  lf.extraline = 0;\n  if (filename == NULL) {\n    lua_pushliteral(L, \"=stdin\");\n    lf.f = stdin;\n  }\n  else {\n    lua_pushfstring(L, \"@%s\", filename);\n    lf.f = fopen(filename, \"r\");\n    if (lf.f == NULL) return errfile(L, \"open\", fnameindex);\n  }\n  c = getc(lf.f);\n  if (c == '#') {  /* Unix exec. file? */\n    lf.extraline = 1;\n    while ((c = getc(lf.f)) != EOF && c != '\\n') ;  /* skip first line */\n    if (c == '\\n') c = getc(lf.f);\n  }\n  if (c == LUA_SIGNATURE[0] && filename) {  /* binary file? */\n    lf.f = freopen(filename, \"rb\", lf.f);  /* reopen in binary mode */\n    if (lf.f == NULL) return errfile(L, \"reopen\", fnameindex);\n    /* skip eventual `#!...' */\n   while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0])\n   ;\n    lf.extraline = 0;\n  }\n  ungetc(c, lf.f);\n  status = lua_load(L, getF, &lf, lua_tostring(L, -1));\n  readstatus = ferror(lf.f);\n  if (filename) fclose(lf.f);  /* close file (even in case of errors) */\n  if (readstatus) {\n    lua_settop(L, fnameindex);  /* ignore results from `lua_load' */\n    return errfile(L, \"read\", fnameindex);\n  }\n  lua_remove(L, fnameindex);\n  return status;\n}\n\n\ntypedef struct LoadS {\n  const char *s;\n  size_t size;\n} LoadS;\n\n\nstatic const char *getS (lua_State *L, void *ud, size_t *size) {\n  LoadS *ls = (LoadS *)ud;\n  (void)L;\n  if (ls->size == 0) return NULL;\n  *size = ls->size;\n  ls->size = 0;\n  return ls->s;\n}\n\n\nLUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size,\n                                const char *name) {\n  LoadS ls;\n  ls.s = buff;\n  ls.size = size;\n  return lua_load(L, getS, &ls, name);\n}\n\n\nLUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) {\n  return luaL_loadbuffer(L, s, strlen(s), s);\n}\n\n\n\n/* }====================================================== */\n\n\nstatic void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {\n  (void)ud;\n  (void)osize;\n  if (nsize == 0) {\n    free(ptr);\n    return NULL;\n  }\n  else\n    return realloc(ptr, nsize);\n}\n\n\nstatic int panic (lua_State *L) {\n  (void)L;  /* to avoid warnings */\n  fprintf(stderr, \"PANIC: unprotected error in call to Lua API (%s)\\n\",\n                   lua_tostring(L, -1));\n  return 0;\n}\n\n\nLUALIB_API lua_State *luaL_newstate (void) {\n  lua_State *L = lua_newstate(l_alloc, NULL);\n  if (L) lua_atpanic(L, &panic);\n  return L;\n}\n\n"
  },
  {
    "path": "src/lua/lbaselib.c",
    "content": "/*\n** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $\n** Basic library\n** See Copyright Notice in lua.h\n*/\n\n\n\n#include <ctype.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lbaselib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\n\n/*\n** If your system does not support `stdout', you can just remove this function.\n** If you need, you can define your own `print' function, following this\n** model but changing `fputs' to put the strings at a proper place\n** (a console window or a log file, for instance).\n*/\nstatic int luaB_print (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  int i;\n  lua_getglobal(L, \"tostring\");\n  for (i=1; i<=n; i++) {\n    const char *s;\n    lua_pushvalue(L, -1);  /* function to be called */\n    lua_pushvalue(L, i);   /* value to print */\n    lua_call(L, 1, 1);\n    s = lua_tostring(L, -1);  /* get result */\n    if (s == NULL)\n      return luaL_error(L, LUA_QL(\"tostring\") \" must return a string to \"\n                           LUA_QL(\"print\"));\n    if (i>1) fputs(\"\\t\", stdout);\n    fputs(s, stdout);\n    lua_pop(L, 1);  /* pop result */\n  }\n  fputs(\"\\n\", stdout);\n  return 0;\n}\n\n\nstatic int luaB_tonumber (lua_State *L) {\n  int base = luaL_optint(L, 2, 10);\n  if (base == 10) {  /* standard conversion */\n    luaL_checkany(L, 1);\n    if (lua_isnumber(L, 1)) {\n      lua_pushnumber(L, lua_tonumber(L, 1));\n      return 1;\n    }\n  }\n  else {\n    const char *s1 = luaL_checkstring(L, 1);\n    char *s2;\n    unsigned long n;\n    luaL_argcheck(L, 2 <= base && base <= 36, 2, \"base out of range\");\n    n = strtoul(s1, &s2, base);\n    if (s1 != s2) {  /* at least one valid digit? */\n      while (isspace((unsigned char)(*s2))) s2++;  /* skip trailing spaces */\n      if (*s2 == '\\0') {  /* no invalid trailing characters? */\n        lua_pushnumber(L, (lua_Number)n);\n        return 1;\n      }\n    }\n  }\n  lua_pushnil(L);  /* else not a number */\n  return 1;\n}\n\n\nstatic int luaB_error (lua_State *L) {\n  int level = luaL_optint(L, 2, 1);\n  lua_settop(L, 1);\n  if (lua_isstring(L, 1) && level > 0) {  /* add extra information? */\n    luaL_where(L, level);\n    lua_pushvalue(L, 1);\n    lua_concat(L, 2);\n  }\n  return lua_error(L);\n}\n\n\nstatic int luaB_getmetatable (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (!lua_getmetatable(L, 1)) {\n    lua_pushnil(L);\n    return 1;  /* no metatable */\n  }\n  luaL_getmetafield(L, 1, \"__metatable\");\n  return 1;  /* returns either __metatable field (if present) or metatable */\n}\n\n\nstatic int luaB_setmetatable (lua_State *L) {\n  int t = lua_type(L, 2);\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,\n                    \"nil or table expected\");\n  if (luaL_getmetafield(L, 1, \"__metatable\"))\n    luaL_error(L, \"cannot change a protected metatable\");\n  lua_settop(L, 2);\n  lua_setmetatable(L, 1);\n  return 1;\n}\n\n\nstatic void getfunc (lua_State *L, int opt) {\n  if (lua_isfunction(L, 1)) lua_pushvalue(L, 1);\n  else {\n    lua_Debug ar;\n    int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1);\n    luaL_argcheck(L, level >= 0, 1, \"level must be non-negative\");\n    if (lua_getstack(L, level, &ar) == 0)\n      luaL_argerror(L, 1, \"invalid level\");\n    lua_getinfo(L, \"f\", &ar);\n    if (lua_isnil(L, -1))\n      luaL_error(L, \"no function environment for tail call at level %d\",\n                    level);\n  }\n}\n\n\nstatic int luaB_getfenv (lua_State *L) {\n  getfunc(L, 1);\n  if (lua_iscfunction(L, -1))  /* is a C function? */\n    lua_pushvalue(L, LUA_GLOBALSINDEX);  /* return the thread's global env. */\n  else\n    lua_getfenv(L, -1);\n  return 1;\n}\n\n\nstatic int luaB_setfenv (lua_State *L) {\n  luaL_checktype(L, 2, LUA_TTABLE);\n  getfunc(L, 0);\n  lua_pushvalue(L, 2);\n  if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) {\n    /* change environment of current thread */\n    lua_pushthread(L);\n    lua_insert(L, -2);\n    lua_setfenv(L, -2);\n    return 0;\n  }\n  else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0)\n    luaL_error(L,\n          LUA_QL(\"setfenv\") \" cannot change environment of given object\");\n  return 1;\n}\n\n\nstatic int luaB_rawequal (lua_State *L) {\n  luaL_checkany(L, 1);\n  luaL_checkany(L, 2);\n  lua_pushboolean(L, lua_rawequal(L, 1, 2));\n  return 1;\n}\n\n\nstatic int luaB_rawget (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_checkany(L, 2);\n  lua_settop(L, 2);\n  lua_rawget(L, 1);\n  return 1;\n}\n\nstatic int luaB_rawset (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_checkany(L, 2);\n  luaL_checkany(L, 3);\n  lua_settop(L, 3);\n  lua_rawset(L, 1);\n  return 1;\n}\n\n\nstatic int luaB_gcinfo (lua_State *L) {\n  lua_pushinteger(L, lua_getgccount(L));\n  return 1;\n}\n\n\nstatic int luaB_collectgarbage (lua_State *L) {\n  static const char *const opts[] = {\"stop\", \"restart\", \"collect\",\n    \"count\", \"step\", \"setpause\", \"setstepmul\", NULL};\n  static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,\n    LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL};\n  int o = luaL_checkoption(L, 1, \"collect\", opts);\n  int ex = luaL_optint(L, 2, 0);\n  int res = lua_gc(L, optsnum[o], ex);\n  switch (optsnum[o]) {\n    case LUA_GCCOUNT: {\n      int b = lua_gc(L, LUA_GCCOUNTB, 0);\n      lua_pushnumber(L, res + ((lua_Number)b/1024));\n      return 1;\n    }\n    case LUA_GCSTEP: {\n      lua_pushboolean(L, res);\n      return 1;\n    }\n    default: {\n      lua_pushnumber(L, res);\n      return 1;\n    }\n  }\n}\n\n\nstatic int luaB_type (lua_State *L) {\n  luaL_checkany(L, 1);\n  lua_pushstring(L, luaL_typename(L, 1));\n  return 1;\n}\n\n\nstatic int luaB_next (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_settop(L, 2);  /* create a 2nd argument if there isn't one */\n  if (lua_next(L, 1))\n    return 2;\n  else {\n    lua_pushnil(L);\n    return 1;\n  }\n}\n\n\nstatic int luaB_pairs (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */\n  lua_pushvalue(L, 1);  /* state, */\n  lua_pushnil(L);  /* and initial value */\n  return 3;\n}\n\n\nstatic int ipairsaux (lua_State *L) {\n  int i = luaL_checkint(L, 2);\n  luaL_checktype(L, 1, LUA_TTABLE);\n  i++;  /* next value */\n  lua_pushinteger(L, i);\n  lua_rawgeti(L, 1, i);\n  return (lua_isnil(L, -1)) ? 0 : 2;\n}\n\n\nstatic int luaB_ipairs (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_pushvalue(L, lua_upvalueindex(1));  /* return generator, */\n  lua_pushvalue(L, 1);  /* state, */\n  lua_pushinteger(L, 0);  /* and initial value */\n  return 3;\n}\n\n\nstatic int load_aux (lua_State *L, int status) {\n  if (status == 0)  /* OK? */\n    return 1;\n  else {\n    lua_pushnil(L);\n    lua_insert(L, -2);  /* put before error message */\n    return 2;  /* return nil plus error message */\n  }\n}\n\n\nstatic int luaB_loadstring (lua_State *L) {\n  size_t l;\n  const char *s = luaL_checklstring(L, 1, &l);\n  const char *chunkname = luaL_optstring(L, 2, s);\n  return load_aux(L, luaL_loadbuffer(L, s, l, chunkname));\n}\n\n\nstatic int luaB_loadfile (lua_State *L) {\n  const char *fname = luaL_optstring(L, 1, NULL);\n  return load_aux(L, luaL_loadfile(L, fname));\n}\n\n\n/*\n** Reader for generic `load' function: `lua_load' uses the\n** stack for internal stuff, so the reader cannot change the\n** stack top. Instead, it keeps its resulting string in a\n** reserved slot inside the stack.\n*/\nstatic const char *generic_reader (lua_State *L, void *ud, size_t *size) {\n  (void)ud;  /* to avoid warnings */\n  luaL_checkstack(L, 2, \"too many nested functions\");\n  lua_pushvalue(L, 1);  /* get function */\n  lua_call(L, 0, 1);  /* call it */\n  if (lua_isnil(L, -1)) {\n    *size = 0;\n    return NULL;\n  }\n  else if (lua_isstring(L, -1)) {\n    lua_replace(L, 3);  /* save string in a reserved stack slot */\n    return lua_tolstring(L, 3, size);\n  }\n  else luaL_error(L, \"reader function must return a string\");\n  return NULL;  /* to avoid warnings */\n}\n\n\nstatic int luaB_load (lua_State *L) {\n  int status;\n  const char *cname = luaL_optstring(L, 2, \"=(load)\");\n  luaL_checktype(L, 1, LUA_TFUNCTION);\n  lua_settop(L, 3);  /* function, eventual name, plus one reserved slot */\n  status = lua_load(L, generic_reader, NULL, cname);\n  return load_aux(L, status);\n}\n\n\nstatic int luaB_dofile (lua_State *L) {\n  const char *fname = luaL_optstring(L, 1, NULL);\n  int n = lua_gettop(L);\n  if (luaL_loadfile(L, fname) != 0) lua_error(L);\n  lua_call(L, 0, LUA_MULTRET);\n  return lua_gettop(L) - n;\n}\n\n\nstatic int luaB_assert (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (!lua_toboolean(L, 1))\n    return luaL_error(L, \"%s\", luaL_optstring(L, 2, \"assertion failed!\"));\n  return lua_gettop(L);\n}\n\n\nstatic int luaB_unpack (lua_State *L) {\n  int i, e, n;\n  luaL_checktype(L, 1, LUA_TTABLE);\n  i = luaL_optint(L, 2, 1);\n  e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1));\n  if (i > e) return 0;  /* empty range */\n  n = e - i + 1;  /* number of elements */\n  if (n <= 0 || !lua_checkstack(L, n))  /* n <= 0 means arith. overflow */\n    return luaL_error(L, \"too many results to unpack\");\n  lua_rawgeti(L, 1, i);  /* push arg[i] (avoiding overflow problems) */\n  while (i++ < e)  /* push arg[i + 1...e] */\n    lua_rawgeti(L, 1, i);\n  return n;\n}\n\n\nstatic int luaB_select (lua_State *L) {\n  int n = lua_gettop(L);\n  if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {\n    lua_pushinteger(L, n-1);\n    return 1;\n  }\n  else {\n    int i = luaL_checkint(L, 1);\n    if (i < 0) i = n + i;\n    else if (i > n) i = n;\n    luaL_argcheck(L, 1 <= i, 1, \"index out of range\");\n    return n - i;\n  }\n}\n\n\nstatic int luaB_pcall (lua_State *L) {\n  int status;\n  luaL_checkany(L, 1);\n  status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0);\n  lua_pushboolean(L, (status == 0));\n  lua_insert(L, 1);\n  return lua_gettop(L);  /* return status + all results */\n}\n\n\nstatic int luaB_xpcall (lua_State *L) {\n  int status;\n  luaL_checkany(L, 2);\n  lua_settop(L, 2);\n  lua_insert(L, 1);  /* put error function under function to be called */\n  status = lua_pcall(L, 0, LUA_MULTRET, 1);\n  lua_pushboolean(L, (status == 0));\n  lua_replace(L, 1);\n  return lua_gettop(L);  /* return status + all results */\n}\n\n\nstatic int luaB_tostring (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (luaL_callmeta(L, 1, \"__tostring\"))  /* is there a metafield? */\n    return 1;  /* use its value */\n  switch (lua_type(L, 1)) {\n    case LUA_TNUMBER:\n      lua_pushstring(L, lua_tostring(L, 1));\n      break;\n    case LUA_TSTRING:\n      lua_pushvalue(L, 1);\n      break;\n    case LUA_TBOOLEAN:\n      lua_pushstring(L, (lua_toboolean(L, 1) ? \"true\" : \"false\"));\n      break;\n    case LUA_TNIL:\n      lua_pushliteral(L, \"nil\");\n      break;\n    default:\n      lua_pushfstring(L, \"%s: %p\", luaL_typename(L, 1), lua_topointer(L, 1));\n      break;\n  }\n  return 1;\n}\n\n\nstatic int luaB_newproxy (lua_State *L) {\n  lua_settop(L, 1);\n  lua_newuserdata(L, 0);  /* create proxy */\n  if (lua_toboolean(L, 1) == 0)\n    return 1;  /* no metatable */\n  else if (lua_isboolean(L, 1)) {\n    lua_newtable(L);  /* create a new metatable `m' ... */\n    lua_pushvalue(L, -1);  /* ... and mark `m' as a valid metatable */\n    lua_pushboolean(L, 1);\n    lua_rawset(L, lua_upvalueindex(1));  /* weaktable[m] = true */\n  }\n  else {\n    int validproxy = 0;  /* to check if weaktable[metatable(u)] == true */\n    if (lua_getmetatable(L, 1)) {\n      lua_rawget(L, lua_upvalueindex(1));\n      validproxy = lua_toboolean(L, -1);\n      lua_pop(L, 1);  /* remove value */\n    }\n    luaL_argcheck(L, validproxy, 1, \"boolean or proxy expected\");\n    lua_getmetatable(L, 1);  /* metatable is valid; get it */\n  }\n  lua_setmetatable(L, 2);\n  return 1;\n}\n\n\nstatic const luaL_Reg base_funcs[] = {\n  {\"assert\", luaB_assert},\n  {\"collectgarbage\", luaB_collectgarbage},\n  {\"dofile\", luaB_dofile},\n  {\"error\", luaB_error},\n  {\"gcinfo\", luaB_gcinfo},\n  {\"getfenv\", luaB_getfenv},\n  {\"getmetatable\", luaB_getmetatable},\n  {\"loadfile\", luaB_loadfile},\n  {\"load\", luaB_load},\n  {\"loadstring\", luaB_loadstring},\n  {\"next\", luaB_next},\n  {\"pcall\", luaB_pcall},\n  {\"print\", luaB_print},\n  {\"rawequal\", luaB_rawequal},\n  {\"rawget\", luaB_rawget},\n  {\"rawset\", luaB_rawset},\n  {\"select\", luaB_select},\n  {\"setfenv\", luaB_setfenv},\n  {\"setmetatable\", luaB_setmetatable},\n  {\"tonumber\", luaB_tonumber},\n  {\"tostring\", luaB_tostring},\n  {\"type\", luaB_type},\n  {\"unpack\", luaB_unpack},\n  {\"xpcall\", luaB_xpcall},\n  {NULL, NULL}\n};\n\n\n/*\n** {======================================================\n** Coroutine library\n** =======================================================\n*/\n\n#define CO_RUN  0 /* running */\n#define CO_SUS  1 /* suspended */\n#define CO_NOR  2 /* 'normal' (it resumed another coroutine) */\n#define CO_DEAD 3\n\nstatic const char *const statnames[] =\n    {\"running\", \"suspended\", \"normal\", \"dead\"};\n\nstatic int costatus (lua_State *L, lua_State *co) {\n  if (L == co) return CO_RUN;\n  switch (lua_status(co)) {\n    case LUA_YIELD:\n      return CO_SUS;\n    case 0: {\n      lua_Debug ar;\n      if (lua_getstack(co, 0, &ar) > 0)  /* does it have frames? */\n        return CO_NOR;  /* it is running */\n      else if (lua_gettop(co) == 0)\n          return CO_DEAD;\n      else\n        return CO_SUS;  /* initial state */\n    }\n    default:  /* some error occured */\n      return CO_DEAD;\n  }\n}\n\n\nstatic int luaB_costatus (lua_State *L) {\n  lua_State *co = lua_tothread(L, 1);\n  luaL_argcheck(L, co, 1, \"coroutine expected\");\n  lua_pushstring(L, statnames[costatus(L, co)]);\n  return 1;\n}\n\n\nstatic int auxresume (lua_State *L, lua_State *co, int narg) {\n  int status = costatus(L, co);\n  if (!lua_checkstack(co, narg))\n    luaL_error(L, \"too many arguments to resume\");\n  if (status != CO_SUS) {\n    lua_pushfstring(L, \"cannot resume %s coroutine\", statnames[status]);\n    return -1;  /* error flag */\n  }\n  lua_xmove(L, co, narg);\n  lua_setlevel(L, co);\n  status = lua_resume(co, narg);\n  if (status == 0 || status == LUA_YIELD) {\n    int nres = lua_gettop(co);\n    if (!lua_checkstack(L, nres + 1))\n      luaL_error(L, \"too many results to resume\");\n    lua_xmove(co, L, nres);  /* move yielded values */\n    return nres;\n  }\n  else {\n    lua_xmove(co, L, 1);  /* move error message */\n    return -1;  /* error flag */\n  }\n}\n\n\nstatic int luaB_coresume (lua_State *L) {\n  lua_State *co = lua_tothread(L, 1);\n  int r;\n  luaL_argcheck(L, co, 1, \"coroutine expected\");\n  r = auxresume(L, co, lua_gettop(L) - 1);\n  if (r < 0) {\n    lua_pushboolean(L, 0);\n    lua_insert(L, -2);\n    return 2;  /* return false + error message */\n  }\n  else {\n    lua_pushboolean(L, 1);\n    lua_insert(L, -(r + 1));\n    return r + 1;  /* return true + `resume' returns */\n  }\n}\n\n\nstatic int luaB_auxwrap (lua_State *L) {\n  lua_State *co = lua_tothread(L, lua_upvalueindex(1));\n  int r = auxresume(L, co, lua_gettop(L));\n  if (r < 0) {\n    if (lua_isstring(L, -1)) {  /* error object is a string? */\n      luaL_where(L, 1);  /* add extra info */\n      lua_insert(L, -2);\n      lua_concat(L, 2);\n    }\n    lua_error(L);  /* propagate error */\n  }\n  return r;\n}\n\n\nstatic int luaB_cocreate (lua_State *L) {\n  lua_State *NL = lua_newthread(L);\n  luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1,\n    \"Lua function expected\");\n  lua_pushvalue(L, 1);  /* move function to top */\n  lua_xmove(L, NL, 1);  /* move function from L to NL */\n  return 1;\n}\n\n\nstatic int luaB_cowrap (lua_State *L) {\n  luaB_cocreate(L);\n  lua_pushcclosure(L, luaB_auxwrap, 1);\n  return 1;\n}\n\n\nstatic int luaB_yield (lua_State *L) {\n  return lua_yield(L, lua_gettop(L));\n}\n\n\nstatic int luaB_corunning (lua_State *L) {\n  if (lua_pushthread(L))\n    lua_pushnil(L);  /* main thread is not a coroutine */\n  return 1;\n}\n\n\nstatic const luaL_Reg co_funcs[] = {\n  {\"create\", luaB_cocreate},\n  {\"resume\", luaB_coresume},\n  {\"running\", luaB_corunning},\n  {\"status\", luaB_costatus},\n  {\"wrap\", luaB_cowrap},\n  {\"yield\", luaB_yield},\n  {NULL, NULL}\n};\n\n/* }====================================================== */\n\n\nstatic void auxopen (lua_State *L, const char *name,\n                     lua_CFunction f, lua_CFunction u) {\n  lua_pushcfunction(L, u);\n  lua_pushcclosure(L, f, 1);\n  lua_setfield(L, -2, name);\n}\n\n\nstatic void base_open (lua_State *L) {\n  /* set global _G */\n  lua_pushvalue(L, LUA_GLOBALSINDEX);\n  lua_setglobal(L, \"_G\");\n  /* open lib into global table */\n  luaL_register(L, \"_G\", base_funcs);\n  lua_pushliteral(L, LUA_VERSION);\n  lua_setglobal(L, \"_VERSION\");  /* set global _VERSION */\n  /* `ipairs' and `pairs' need auxiliary functions as upvalues */\n  auxopen(L, \"ipairs\", luaB_ipairs, ipairsaux);\n  auxopen(L, \"pairs\", luaB_pairs, luaB_next);\n  /* `newproxy' needs a weaktable as upvalue */\n  lua_createtable(L, 0, 1);  /* new table `w' */\n  lua_pushvalue(L, -1);  /* `w' will be its own metatable */\n  lua_setmetatable(L, -2);\n  lua_pushliteral(L, \"kv\");\n  lua_setfield(L, -2, \"__mode\");  /* metatable(w).__mode = \"kv\" */\n  lua_pushcclosure(L, luaB_newproxy, 1);\n  lua_setglobal(L, \"newproxy\");  /* set global `newproxy' */\n}\n\n\nLUALIB_API int luaopen_base (lua_State *L) {\n  base_open(L);\n  return 1;\n}\n\nLUALIB_API int luaopen_coroutine (lua_State *L) {\n  luaL_register(L, LUA_COLIBNAME, co_funcs);\n  return 1;\n}\n\n"
  },
  {
    "path": "src/lua/lcode.c",
    "content": "/*\n** $Id: lcode.c,v 2.25.1.5 2011/01/31 14:53:16 roberto Exp $\n** Code generator for Lua\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdlib.h>\n\n#define lcode_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lcode.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lgc.h\"\n#include \"llex.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n#include \"ltable.h\"\n\n\n#define hasjumps(e)\t((e)->t != (e)->f)\n\n\nstatic int isnumeral(expdesc *e) {\n  return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP);\n}\n\n\nvoid luaK_nil (FuncState *fs, int from, int n) {\n  Instruction *previous;\n  if (fs->pc > fs->lasttarget) {  /* no jumps to current position? */\n    if (fs->pc == 0) {  /* function start? */\n      if (from >= fs->nactvar)\n        return;  /* positions are already clean */\n    }\n    else {\n      previous = &fs->f->code[fs->pc-1];\n      if (GET_OPCODE(*previous) == OP_LOADNIL) {\n        int pfrom = GETARG_A(*previous);\n        int pto = GETARG_B(*previous);\n        if (pfrom <= from && from <= pto+1) {  /* can connect both? */\n          if (from+n-1 > pto)\n            SETARG_B(*previous, from+n-1);\n          return;\n        }\n      }\n    }\n  }\n  luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0);  /* else no optimization */\n}\n\n\nint luaK_jump (FuncState *fs) {\n  int jpc = fs->jpc;  /* save list of jumps to here */\n  int j;\n  fs->jpc = NO_JUMP;\n  j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP);\n  luaK_concat(fs, &j, jpc);  /* keep them on hold */\n  return j;\n}\n\n\nvoid luaK_ret (FuncState *fs, int first, int nret) {\n  luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);\n}\n\n\nstatic int condjump (FuncState *fs, OpCode op, int A, int B, int C) {\n  luaK_codeABC(fs, op, A, B, C);\n  return luaK_jump(fs);\n}\n\n\nstatic void fixjump (FuncState *fs, int pc, int dest) {\n  Instruction *jmp = &fs->f->code[pc];\n  int offset = dest-(pc+1);\n  lua_assert(dest != NO_JUMP);\n  if (abs(offset) > MAXARG_sBx)\n    luaX_syntaxerror(fs->ls, \"control structure too long\");\n  SETARG_sBx(*jmp, offset);\n}\n\n\n/*\n** returns current `pc' and marks it as a jump target (to avoid wrong\n** optimizations with consecutive instructions not in the same basic block).\n*/\nint luaK_getlabel (FuncState *fs) {\n  fs->lasttarget = fs->pc;\n  return fs->pc;\n}\n\n\nstatic int getjump (FuncState *fs, int pc) {\n  int offset = GETARG_sBx(fs->f->code[pc]);\n  if (offset == NO_JUMP)  /* point to itself represents end of list */\n    return NO_JUMP;  /* end of list */\n  else\n    return (pc+1)+offset;  /* turn offset into absolute position */\n}\n\n\nstatic Instruction *getjumpcontrol (FuncState *fs, int pc) {\n  Instruction *pi = &fs->f->code[pc];\n  if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1))))\n    return pi-1;\n  else\n    return pi;\n}\n\n\n/*\n** check whether list has any jump that do not produce a value\n** (or produce an inverted value)\n*/\nstatic int need_value (FuncState *fs, int list) {\n  for (; list != NO_JUMP; list = getjump(fs, list)) {\n    Instruction i = *getjumpcontrol(fs, list);\n    if (GET_OPCODE(i) != OP_TESTSET) return 1;\n  }\n  return 0;  /* not found */\n}\n\n\nstatic int patchtestreg (FuncState *fs, int node, int reg) {\n  Instruction *i = getjumpcontrol(fs, node);\n  if (GET_OPCODE(*i) != OP_TESTSET)\n    return 0;  /* cannot patch other instructions */\n  if (reg != NO_REG && reg != GETARG_B(*i))\n    SETARG_A(*i, reg);\n  else  /* no register to put value or register already has the value */\n    *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i));\n\n  return 1;\n}\n\n\nstatic void removevalues (FuncState *fs, int list) {\n  for (; list != NO_JUMP; list = getjump(fs, list))\n      patchtestreg(fs, list, NO_REG);\n}\n\n\nstatic void patchlistaux (FuncState *fs, int list, int vtarget, int reg,\n                          int dtarget) {\n  while (list != NO_JUMP) {\n    int next = getjump(fs, list);\n    if (patchtestreg(fs, list, reg))\n      fixjump(fs, list, vtarget);\n    else\n      fixjump(fs, list, dtarget);  /* jump to default target */\n    list = next;\n  }\n}\n\n\nstatic void dischargejpc (FuncState *fs) {\n  patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc);\n  fs->jpc = NO_JUMP;\n}\n\n\nvoid luaK_patchlist (FuncState *fs, int list, int target) {\n  if (target == fs->pc)\n    luaK_patchtohere(fs, list);\n  else {\n    lua_assert(target < fs->pc);\n    patchlistaux(fs, list, target, NO_REG, target);\n  }\n}\n\n\nvoid luaK_patchtohere (FuncState *fs, int list) {\n  luaK_getlabel(fs);\n  luaK_concat(fs, &fs->jpc, list);\n}\n\n\nvoid luaK_concat (FuncState *fs, int *l1, int l2) {\n  if (l2 == NO_JUMP) return;\n  else if (*l1 == NO_JUMP)\n    *l1 = l2;\n  else {\n    int list = *l1;\n    int next;\n    while ((next = getjump(fs, list)) != NO_JUMP)  /* find last element */\n      list = next;\n    fixjump(fs, list, l2);\n  }\n}\n\n\nvoid luaK_checkstack (FuncState *fs, int n) {\n  int newstack = fs->freereg + n;\n  if (newstack > fs->f->maxstacksize) {\n    if (newstack >= MAXSTACK)\n      luaX_syntaxerror(fs->ls, \"function or expression too complex\");\n    fs->f->maxstacksize = cast_byte(newstack);\n  }\n}\n\n\nvoid luaK_reserveregs (FuncState *fs, int n) {\n  luaK_checkstack(fs, n);\n  fs->freereg += n;\n}\n\n\nstatic void freereg (FuncState *fs, int reg) {\n  if (!ISK(reg) && reg >= fs->nactvar) {\n    fs->freereg--;\n    lua_assert(reg == fs->freereg);\n  }\n}\n\n\nstatic void freeexp (FuncState *fs, expdesc *e) {\n  if (e->k == VNONRELOC)\n    freereg(fs, e->u.s.info);\n}\n\n\nstatic int addk (FuncState *fs, TValue *k, TValue *v) {\n  lua_State *L = fs->L;\n  TValue *idx = luaH_set(L, fs->h, k);\n  Proto *f = fs->f;\n  int oldsize = f->sizek;\n  if (ttisnumber(idx)) {\n    lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v));\n    return cast_int(nvalue(idx));\n  }\n  else {  /* constant not found; create a new entry */\n    setnvalue(idx, cast_num(fs->nk));\n    luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,\n                    MAXARG_Bx, \"constant table overflow\");\n    while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);\n    setobj(L, &f->k[fs->nk], v);\n    luaC_barrier(L, f, v);\n    return fs->nk++;\n  }\n}\n\n\nint luaK_stringK (FuncState *fs, TString *s) {\n  TValue o;\n  setsvalue(fs->L, &o, s);\n  return addk(fs, &o, &o);\n}\n\n\nint luaK_numberK (FuncState *fs, lua_Number r) {\n  TValue o;\n  setnvalue(&o, r);\n  return addk(fs, &o, &o);\n}\n\n\nstatic int boolK (FuncState *fs, int b) {\n  TValue o;\n  setbvalue(&o, b);\n  return addk(fs, &o, &o);\n}\n\n\nstatic int nilK (FuncState *fs) {\n  TValue k, v;\n  setnilvalue(&v);\n  /* cannot use nil as key; instead use table itself to represent nil */\n  sethvalue(fs->L, &k, fs->h);\n  return addk(fs, &k, &v);\n}\n\n\nvoid luaK_setreturns (FuncState *fs, expdesc *e, int nresults) {\n  if (e->k == VCALL) {  /* expression is an open function call? */\n    SETARG_C(getcode(fs, e), nresults+1);\n  }\n  else if (e->k == VVARARG) {\n    SETARG_B(getcode(fs, e), nresults+1);\n    SETARG_A(getcode(fs, e), fs->freereg);\n    luaK_reserveregs(fs, 1);\n  }\n}\n\n\nvoid luaK_setoneret (FuncState *fs, expdesc *e) {\n  if (e->k == VCALL) {  /* expression is an open function call? */\n    e->k = VNONRELOC;\n    e->u.s.info = GETARG_A(getcode(fs, e));\n  }\n  else if (e->k == VVARARG) {\n    SETARG_B(getcode(fs, e), 2);\n    e->k = VRELOCABLE;  /* can relocate its simple result */\n  }\n}\n\n\nvoid luaK_dischargevars (FuncState *fs, expdesc *e) {\n  switch (e->k) {\n    case VLOCAL: {\n      e->k = VNONRELOC;\n      break;\n    }\n    case VUPVAL: {\n      e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0);\n      e->k = VRELOCABLE;\n      break;\n    }\n    case VGLOBAL: {\n      e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info);\n      e->k = VRELOCABLE;\n      break;\n    }\n    case VINDEXED: {\n      freereg(fs, e->u.s.aux);\n      freereg(fs, e->u.s.info);\n      e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux);\n      e->k = VRELOCABLE;\n      break;\n    }\n    case VVARARG:\n    case VCALL: {\n      luaK_setoneret(fs, e);\n      break;\n    }\n    default: break;  /* there is one value available (somewhere) */\n  }\n}\n\n\nstatic int code_label (FuncState *fs, int A, int b, int jump) {\n  luaK_getlabel(fs);  /* those instructions may be jump targets */\n  return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump);\n}\n\n\nstatic void discharge2reg (FuncState *fs, expdesc *e, int reg) {\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VNIL: {\n      luaK_nil(fs, reg, 1);\n      break;\n    }\n    case VFALSE:  case VTRUE: {\n      luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0);\n      break;\n    }\n    case VK: {\n      luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info);\n      break;\n    }\n    case VKNUM: {\n      luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval));\n      break;\n    }\n    case VRELOCABLE: {\n      Instruction *pc = &getcode(fs, e);\n      SETARG_A(*pc, reg);\n      break;\n    }\n    case VNONRELOC: {\n      if (reg != e->u.s.info)\n        luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0);\n      break;\n    }\n    default: {\n      lua_assert(e->k == VVOID || e->k == VJMP);\n      return;  /* nothing to do... */\n    }\n  }\n  e->u.s.info = reg;\n  e->k = VNONRELOC;\n}\n\n\nstatic void discharge2anyreg (FuncState *fs, expdesc *e) {\n  if (e->k != VNONRELOC) {\n    luaK_reserveregs(fs, 1);\n    discharge2reg(fs, e, fs->freereg-1);\n  }\n}\n\n\nstatic void exp2reg (FuncState *fs, expdesc *e, int reg) {\n  discharge2reg(fs, e, reg);\n  if (e->k == VJMP)\n    luaK_concat(fs, &e->t, e->u.s.info);  /* put this jump in `t' list */\n  if (hasjumps(e)) {\n    int final;  /* position after whole expression */\n    int p_f = NO_JUMP;  /* position of an eventual LOAD false */\n    int p_t = NO_JUMP;  /* position of an eventual LOAD true */\n    if (need_value(fs, e->t) || need_value(fs, e->f)) {\n      int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs);\n      p_f = code_label(fs, reg, 0, 1);\n      p_t = code_label(fs, reg, 1, 0);\n      luaK_patchtohere(fs, fj);\n    }\n    final = luaK_getlabel(fs);\n    patchlistaux(fs, e->f, final, reg, p_f);\n    patchlistaux(fs, e->t, final, reg, p_t);\n  }\n  e->f = e->t = NO_JUMP;\n  e->u.s.info = reg;\n  e->k = VNONRELOC;\n}\n\n\nvoid luaK_exp2nextreg (FuncState *fs, expdesc *e) {\n  luaK_dischargevars(fs, e);\n  freeexp(fs, e);\n  luaK_reserveregs(fs, 1);\n  exp2reg(fs, e, fs->freereg - 1);\n}\n\n\nint luaK_exp2anyreg (FuncState *fs, expdesc *e) {\n  luaK_dischargevars(fs, e);\n  if (e->k == VNONRELOC) {\n    if (!hasjumps(e)) return e->u.s.info;  /* exp is already in a register */\n    if (e->u.s.info >= fs->nactvar) {  /* reg. is not a local? */\n      exp2reg(fs, e, e->u.s.info);  /* put value on it */\n      return e->u.s.info;\n    }\n  }\n  luaK_exp2nextreg(fs, e);  /* default */\n  return e->u.s.info;\n}\n\n\nvoid luaK_exp2val (FuncState *fs, expdesc *e) {\n  if (hasjumps(e))\n    luaK_exp2anyreg(fs, e);\n  else\n    luaK_dischargevars(fs, e);\n}\n\n\nint luaK_exp2RK (FuncState *fs, expdesc *e) {\n  luaK_exp2val(fs, e);\n  switch (e->k) {\n    case VKNUM:\n    case VTRUE:\n    case VFALSE:\n    case VNIL: {\n      if (fs->nk <= MAXINDEXRK) {  /* constant fit in RK operand? */\n        e->u.s.info = (e->k == VNIL)  ? nilK(fs) :\n                      (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) :\n                                        boolK(fs, (e->k == VTRUE));\n        e->k = VK;\n        return RKASK(e->u.s.info);\n      }\n      else break;\n    }\n    case VK: {\n      if (e->u.s.info <= MAXINDEXRK)  /* constant fit in argC? */\n        return RKASK(e->u.s.info);\n      else break;\n    }\n    default: break;\n  }\n  /* not a constant in the right range: put it in a register */\n  return luaK_exp2anyreg(fs, e);\n}\n\n\nvoid luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) {\n  switch (var->k) {\n    case VLOCAL: {\n      freeexp(fs, ex);\n      exp2reg(fs, ex, var->u.s.info);\n      return;\n    }\n    case VUPVAL: {\n      int e = luaK_exp2anyreg(fs, ex);\n      luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0);\n      break;\n    }\n    case VGLOBAL: {\n      int e = luaK_exp2anyreg(fs, ex);\n      luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info);\n      break;\n    }\n    case VINDEXED: {\n      int e = luaK_exp2RK(fs, ex);\n      luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e);\n      break;\n    }\n    default: {\n      lua_assert(0);  /* invalid var kind to store */\n      break;\n    }\n  }\n  freeexp(fs, ex);\n}\n\n\nvoid luaK_self (FuncState *fs, expdesc *e, expdesc *key) {\n  int func;\n  luaK_exp2anyreg(fs, e);\n  freeexp(fs, e);\n  func = fs->freereg;\n  luaK_reserveregs(fs, 2);\n  luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key));\n  freeexp(fs, key);\n  e->u.s.info = func;\n  e->k = VNONRELOC;\n}\n\n\nstatic void invertjump (FuncState *fs, expdesc *e) {\n  Instruction *pc = getjumpcontrol(fs, e->u.s.info);\n  lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET &&\n                                           GET_OPCODE(*pc) != OP_TEST);\n  SETARG_A(*pc, !(GETARG_A(*pc)));\n}\n\n\nstatic int jumponcond (FuncState *fs, expdesc *e, int cond) {\n  if (e->k == VRELOCABLE) {\n    Instruction ie = getcode(fs, e);\n    if (GET_OPCODE(ie) == OP_NOT) {\n      fs->pc--;  /* remove previous OP_NOT */\n      return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond);\n    }\n    /* else go through */\n  }\n  discharge2anyreg(fs, e);\n  freeexp(fs, e);\n  return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond);\n}\n\n\nvoid luaK_goiftrue (FuncState *fs, expdesc *e) {\n  int pc;  /* pc of last jump */\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VK: case VKNUM: case VTRUE: {\n      pc = NO_JUMP;  /* always true; do nothing */\n      break;\n    }\n    case VJMP: {\n      invertjump(fs, e);\n      pc = e->u.s.info;\n      break;\n    }\n    default: {\n      pc = jumponcond(fs, e, 0);\n      break;\n    }\n  }\n  luaK_concat(fs, &e->f, pc);  /* insert last jump in `f' list */\n  luaK_patchtohere(fs, e->t);\n  e->t = NO_JUMP;\n}\n\n\nstatic void luaK_goiffalse (FuncState *fs, expdesc *e) {\n  int pc;  /* pc of last jump */\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VNIL: case VFALSE: {\n      pc = NO_JUMP;  /* always false; do nothing */\n      break;\n    }\n    case VJMP: {\n      pc = e->u.s.info;\n      break;\n    }\n    default: {\n      pc = jumponcond(fs, e, 1);\n      break;\n    }\n  }\n  luaK_concat(fs, &e->t, pc);  /* insert last jump in `t' list */\n  luaK_patchtohere(fs, e->f);\n  e->f = NO_JUMP;\n}\n\n\nstatic void codenot (FuncState *fs, expdesc *e) {\n  luaK_dischargevars(fs, e);\n  switch (e->k) {\n    case VNIL: case VFALSE: {\n      e->k = VTRUE;\n      break;\n    }\n    case VK: case VKNUM: case VTRUE: {\n      e->k = VFALSE;\n      break;\n    }\n    case VJMP: {\n      invertjump(fs, e);\n      break;\n    }\n    case VRELOCABLE:\n    case VNONRELOC: {\n      discharge2anyreg(fs, e);\n      freeexp(fs, e);\n      e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0);\n      e->k = VRELOCABLE;\n      break;\n    }\n    default: {\n      lua_assert(0);  /* cannot happen */\n      break;\n    }\n  }\n  /* interchange true and false lists */\n  { int temp = e->f; e->f = e->t; e->t = temp; }\n  removevalues(fs, e->f);\n  removevalues(fs, e->t);\n}\n\n\nvoid luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) {\n  t->u.s.aux = luaK_exp2RK(fs, k);\n  t->k = VINDEXED;\n}\n\n\nstatic int constfolding (OpCode op, expdesc *e1, expdesc *e2) {\n  lua_Number v1, v2, r;\n  if (!isnumeral(e1) || !isnumeral(e2)) return 0;\n  v1 = e1->u.nval;\n  v2 = e2->u.nval;\n  switch (op) {\n    case OP_ADD: r = luai_numadd(v1, v2); break;\n    case OP_SUB: r = luai_numsub(v1, v2); break;\n    case OP_MUL: r = luai_nummul(v1, v2); break;\n    case OP_DIV:\n      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */\n      r = luai_numdiv(v1, v2); break;\n    case OP_MOD:\n      if (v2 == 0) return 0;  /* do not attempt to divide by 0 */\n      r = luai_nummod(v1, v2); break;\n    case OP_POW: r = luai_numpow(v1, v2); break;\n    case OP_UNM: r = luai_numunm(v1); break;\n    case OP_LEN: return 0;  /* no constant folding for 'len' */\n    default: lua_assert(0); r = 0; break;\n  }\n  if (luai_numisnan(r)) return 0;  /* do not attempt to produce NaN */\n  e1->u.nval = r;\n  return 1;\n}\n\n\nstatic void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) {\n  if (constfolding(op, e1, e2))\n    return;\n  else {\n    int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0;\n    int o1 = luaK_exp2RK(fs, e1);\n    if (o1 > o2) {\n      freeexp(fs, e1);\n      freeexp(fs, e2);\n    }\n    else {\n      freeexp(fs, e2);\n      freeexp(fs, e1);\n    }\n    e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2);\n    e1->k = VRELOCABLE;\n  }\n}\n\n\nstatic void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1,\n                                                          expdesc *e2) {\n  int o1 = luaK_exp2RK(fs, e1);\n  int o2 = luaK_exp2RK(fs, e2);\n  freeexp(fs, e2);\n  freeexp(fs, e1);\n  if (cond == 0 && op != OP_EQ) {\n    int temp;  /* exchange args to replace by `<' or `<=' */\n    temp = o1; o1 = o2; o2 = temp;  /* o1 <==> o2 */\n    cond = 1;\n  }\n  e1->u.s.info = condjump(fs, op, cond, o1, o2);\n  e1->k = VJMP;\n}\n\n\nvoid luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) {\n  expdesc e2;\n  e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0;\n  switch (op) {\n    case OPR_MINUS: {\n      if (!isnumeral(e))\n        luaK_exp2anyreg(fs, e);  /* cannot operate on non-numeric constants */\n      codearith(fs, OP_UNM, e, &e2);\n      break;\n    }\n    case OPR_NOT: codenot(fs, e); break;\n    case OPR_LEN: {\n      luaK_exp2anyreg(fs, e);  /* cannot operate on constants */\n      codearith(fs, OP_LEN, e, &e2);\n      break;\n    }\n    default: lua_assert(0);\n  }\n}\n\n\nvoid luaK_infix (FuncState *fs, BinOpr op, expdesc *v) {\n  switch (op) {\n    case OPR_AND: {\n      luaK_goiftrue(fs, v);\n      break;\n    }\n    case OPR_OR: {\n      luaK_goiffalse(fs, v);\n      break;\n    }\n    case OPR_CONCAT: {\n      luaK_exp2nextreg(fs, v);  /* operand must be on the `stack' */\n      break;\n    }\n    case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV:\n    case OPR_MOD: case OPR_POW: {\n      if (!isnumeral(v)) luaK_exp2RK(fs, v);\n      break;\n    }\n    default: {\n      luaK_exp2RK(fs, v);\n      break;\n    }\n  }\n}\n\n\nvoid luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) {\n  switch (op) {\n    case OPR_AND: {\n      lua_assert(e1->t == NO_JUMP);  /* list must be closed */\n      luaK_dischargevars(fs, e2);\n      luaK_concat(fs, &e2->f, e1->f);\n      *e1 = *e2;\n      break;\n    }\n    case OPR_OR: {\n      lua_assert(e1->f == NO_JUMP);  /* list must be closed */\n      luaK_dischargevars(fs, e2);\n      luaK_concat(fs, &e2->t, e1->t);\n      *e1 = *e2;\n      break;\n    }\n    case OPR_CONCAT: {\n      luaK_exp2val(fs, e2);\n      if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) {\n        lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1);\n        freeexp(fs, e1);\n        SETARG_B(getcode(fs, e2), e1->u.s.info);\n        e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info;\n      }\n      else {\n        luaK_exp2nextreg(fs, e2);  /* operand must be on the 'stack' */\n        codearith(fs, OP_CONCAT, e1, e2);\n      }\n      break;\n    }\n    case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break;\n    case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break;\n    case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break;\n    case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break;\n    case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break;\n    case OPR_POW: codearith(fs, OP_POW, e1, e2); break;\n    case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break;\n    case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break;\n    case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break;\n    case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break;\n    case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break;\n    case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break;\n    default: lua_assert(0);\n  }\n}\n\n\nvoid luaK_fixline (FuncState *fs, int line) {\n  fs->f->lineinfo[fs->pc - 1] = line;\n}\n\n\nstatic int luaK_code (FuncState *fs, Instruction i, int line) {\n  Proto *f = fs->f;\n  dischargejpc(fs);  /* `pc' will change */\n  /* put new instruction in code array */\n  luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction,\n                  MAX_INT, \"code size overflow\");\n  f->code[fs->pc] = i;\n  /* save corresponding line information */\n  luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int,\n                  MAX_INT, \"code size overflow\");\n  f->lineinfo[fs->pc] = line;\n  return fs->pc++;\n}\n\n\nint luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) {\n  lua_assert(getOpMode(o) == iABC);\n  lua_assert(getBMode(o) != OpArgN || b == 0);\n  lua_assert(getCMode(o) != OpArgN || c == 0);\n  return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline);\n}\n\n\nint luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) {\n  lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx);\n  lua_assert(getCMode(o) == OpArgN);\n  return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline);\n}\n\n\nvoid luaK_setlist (FuncState *fs, int base, int nelems, int tostore) {\n  int c =  (nelems - 1)/LFIELDS_PER_FLUSH + 1;\n  int b = (tostore == LUA_MULTRET) ? 0 : tostore;\n  lua_assert(tostore != 0);\n  if (c <= MAXARG_C)\n    luaK_codeABC(fs, OP_SETLIST, base, b, c);\n  else {\n    luaK_codeABC(fs, OP_SETLIST, base, b, 0);\n    luaK_code(fs, cast(Instruction, c), fs->ls->lastline);\n  }\n  fs->freereg = base + 1;  /* free registers with list values */\n}\n\n"
  },
  {
    "path": "src/lua/lcode.h",
    "content": "/*\n** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $\n** Code generator for Lua\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lcode_h\n#define lcode_h\n\n#include \"llex.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n\n\n/*\n** Marks the end of a patch list. It is an invalid value both as an absolute\n** address, and as a list link (would link an element to itself).\n*/\n#define NO_JUMP (-1)\n\n\n/*\n** grep \"ORDER OPR\" if you change these enums\n*/\ntypedef enum BinOpr {\n  OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW,\n  OPR_CONCAT,\n  OPR_NE, OPR_EQ,\n  OPR_LT, OPR_LE, OPR_GT, OPR_GE,\n  OPR_AND, OPR_OR,\n  OPR_NOBINOPR\n} BinOpr;\n\n\ntypedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr;\n\n\n#define getcode(fs,e)\t((fs)->f->code[(e)->u.s.info])\n\n#define luaK_codeAsBx(fs,o,A,sBx)\tluaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx)\n\n#define luaK_setmultret(fs,e)\tluaK_setreturns(fs, e, LUA_MULTRET)\n\nLUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx);\nLUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C);\nLUAI_FUNC void luaK_fixline (FuncState *fs, int line);\nLUAI_FUNC void luaK_nil (FuncState *fs, int from, int n);\nLUAI_FUNC void luaK_reserveregs (FuncState *fs, int n);\nLUAI_FUNC void luaK_checkstack (FuncState *fs, int n);\nLUAI_FUNC int luaK_stringK (FuncState *fs, TString *s);\nLUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r);\nLUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e);\nLUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e);\nLUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key);\nLUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k);\nLUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e);\nLUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e);\nLUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults);\nLUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e);\nLUAI_FUNC int luaK_jump (FuncState *fs);\nLUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret);\nLUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target);\nLUAI_FUNC void luaK_patchtohere (FuncState *fs, int list);\nLUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2);\nLUAI_FUNC int luaK_getlabel (FuncState *fs);\nLUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v);\nLUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v);\nLUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2);\nLUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore);\n\n\n#endif\n"
  },
  {
    "path": "src/lua/ldblib.c",
    "content": "/*\n** $Id: ldblib.c,v 1.104.1.4 2009/08/04 18:50:18 roberto Exp $\n** Interface from Lua to its debug API\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define ldblib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\nstatic int db_getregistry (lua_State *L) {\n  lua_pushvalue(L, LUA_REGISTRYINDEX);\n  return 1;\n}\n\n\nstatic int db_getmetatable (lua_State *L) {\n  luaL_checkany(L, 1);\n  if (!lua_getmetatable(L, 1)) {\n    lua_pushnil(L);  /* no metatable */\n  }\n  return 1;\n}\n\n\nstatic int db_setmetatable (lua_State *L) {\n  int t = lua_type(L, 2);\n  luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,\n                    \"nil or table expected\");\n  lua_settop(L, 2);\n  lua_pushboolean(L, lua_setmetatable(L, 1));\n  return 1;\n}\n\n\nstatic int db_getfenv (lua_State *L) {\n  luaL_checkany(L, 1);\n  lua_getfenv(L, 1);\n  return 1;\n}\n\n\nstatic int db_setfenv (lua_State *L) {\n  luaL_checktype(L, 2, LUA_TTABLE);\n  lua_settop(L, 2);\n  if (lua_setfenv(L, 1) == 0)\n    luaL_error(L, LUA_QL(\"setfenv\")\n                  \" cannot change environment of given object\");\n  return 1;\n}\n\n\nstatic void settabss (lua_State *L, const char *i, const char *v) {\n  lua_pushstring(L, v);\n  lua_setfield(L, -2, i);\n}\n\n\nstatic void settabsi (lua_State *L, const char *i, int v) {\n  lua_pushinteger(L, v);\n  lua_setfield(L, -2, i);\n}\n\n\nstatic lua_State *getthread (lua_State *L, int *arg) {\n  if (lua_isthread(L, 1)) {\n    *arg = 1;\n    return lua_tothread(L, 1);\n  }\n  else {\n    *arg = 0;\n    return L;\n  }\n}\n\n\nstatic void treatstackoption (lua_State *L, lua_State *L1, const char *fname) {\n  if (L == L1) {\n    lua_pushvalue(L, -2);\n    lua_remove(L, -3);\n  }\n  else\n    lua_xmove(L1, L, 1);\n  lua_setfield(L, -2, fname);\n}\n\n\nstatic int db_getinfo (lua_State *L) {\n  lua_Debug ar;\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  const char *options = luaL_optstring(L, arg+2, \"flnSu\");\n  if (lua_isnumber(L, arg+1)) {\n    if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) {\n      lua_pushnil(L);  /* level out of range */\n      return 1;\n    }\n  }\n  else if (lua_isfunction(L, arg+1)) {\n    lua_pushfstring(L, \">%s\", options);\n    options = lua_tostring(L, -1);\n    lua_pushvalue(L, arg+1);\n    lua_xmove(L, L1, 1);\n  }\n  else\n    return luaL_argerror(L, arg+1, \"function or level expected\");\n  if (!lua_getinfo(L1, options, &ar))\n    return luaL_argerror(L, arg+2, \"invalid option\");\n  lua_createtable(L, 0, 2);\n  if (strchr(options, 'S')) {\n    settabss(L, \"source\", ar.source);\n    settabss(L, \"short_src\", ar.short_src);\n    settabsi(L, \"linedefined\", ar.linedefined);\n    settabsi(L, \"lastlinedefined\", ar.lastlinedefined);\n    settabss(L, \"what\", ar.what);\n  }\n  if (strchr(options, 'l'))\n    settabsi(L, \"currentline\", ar.currentline);\n  if (strchr(options, 'u'))\n    settabsi(L, \"nups\", ar.nups);\n  if (strchr(options, 'n')) {\n    settabss(L, \"name\", ar.name);\n    settabss(L, \"namewhat\", ar.namewhat);\n  }\n  if (strchr(options, 'L'))\n    treatstackoption(L, L1, \"activelines\");\n  if (strchr(options, 'f'))\n    treatstackoption(L, L1, \"func\");\n  return 1;  /* return table */\n}\n    \n\nstatic int db_getlocal (lua_State *L) {\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  lua_Debug ar;\n  const char *name;\n  if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */\n    return luaL_argerror(L, arg+1, \"level out of range\");\n  name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2));\n  if (name) {\n    lua_xmove(L1, L, 1);\n    lua_pushstring(L, name);\n    lua_pushvalue(L, -2);\n    return 2;\n  }\n  else {\n    lua_pushnil(L);\n    return 1;\n  }\n}\n\n\nstatic int db_setlocal (lua_State *L) {\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  lua_Debug ar;\n  if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar))  /* out of range? */\n    return luaL_argerror(L, arg+1, \"level out of range\");\n  luaL_checkany(L, arg+3);\n  lua_settop(L, arg+3);\n  lua_xmove(L, L1, 1);\n  lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2)));\n  return 1;\n}\n\n\nstatic int auxupvalue (lua_State *L, int get) {\n  const char *name;\n  int n = luaL_checkint(L, 2);\n  luaL_checktype(L, 1, LUA_TFUNCTION);\n  if (lua_iscfunction(L, 1)) return 0;  /* cannot touch C upvalues from Lua */\n  name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);\n  if (name == NULL) return 0;\n  lua_pushstring(L, name);\n  lua_insert(L, -(get+1));\n  return get + 1;\n}\n\n\nstatic int db_getupvalue (lua_State *L) {\n  return auxupvalue(L, 1);\n}\n\n\nstatic int db_setupvalue (lua_State *L) {\n  luaL_checkany(L, 3);\n  return auxupvalue(L, 0);\n}\n\n\n\nstatic const char KEY_HOOK = 'h';\n\n\nstatic void hookf (lua_State *L, lua_Debug *ar) {\n  static const char *const hooknames[] =\n    {\"call\", \"return\", \"line\", \"count\", \"tail return\"};\n  lua_pushlightuserdata(L, (void *)&KEY_HOOK);\n  lua_rawget(L, LUA_REGISTRYINDEX);\n  lua_pushlightuserdata(L, L);\n  lua_rawget(L, -2);\n  if (lua_isfunction(L, -1)) {\n    lua_pushstring(L, hooknames[(int)ar->event]);\n    if (ar->currentline >= 0)\n      lua_pushinteger(L, ar->currentline);\n    else lua_pushnil(L);\n    lua_assert(lua_getinfo(L, \"lS\", ar));\n    lua_call(L, 2, 0);\n  }\n}\n\n\nstatic int makemask (const char *smask, int count) {\n  int mask = 0;\n  if (strchr(smask, 'c')) mask |= LUA_MASKCALL;\n  if (strchr(smask, 'r')) mask |= LUA_MASKRET;\n  if (strchr(smask, 'l')) mask |= LUA_MASKLINE;\n  if (count > 0) mask |= LUA_MASKCOUNT;\n  return mask;\n}\n\n\nstatic char *unmakemask (int mask, char *smask) {\n  int i = 0;\n  if (mask & LUA_MASKCALL) smask[i++] = 'c';\n  if (mask & LUA_MASKRET) smask[i++] = 'r';\n  if (mask & LUA_MASKLINE) smask[i++] = 'l';\n  smask[i] = '\\0';\n  return smask;\n}\n\n\nstatic void gethooktable (lua_State *L) {\n  lua_pushlightuserdata(L, (void *)&KEY_HOOK);\n  lua_rawget(L, LUA_REGISTRYINDEX);\n  if (!lua_istable(L, -1)) {\n    lua_pop(L, 1);\n    lua_createtable(L, 0, 1);\n    lua_pushlightuserdata(L, (void *)&KEY_HOOK);\n    lua_pushvalue(L, -2);\n    lua_rawset(L, LUA_REGISTRYINDEX);\n  }\n}\n\n\nstatic int db_sethook (lua_State *L) {\n  int arg, mask, count;\n  lua_Hook func;\n  lua_State *L1 = getthread(L, &arg);\n  if (lua_isnoneornil(L, arg+1)) {\n    lua_settop(L, arg+1);\n    func = NULL; mask = 0; count = 0;  /* turn off hooks */\n  }\n  else {\n    const char *smask = luaL_checkstring(L, arg+2);\n    luaL_checktype(L, arg+1, LUA_TFUNCTION);\n    count = luaL_optint(L, arg+3, 0);\n    func = hookf; mask = makemask(smask, count);\n  }\n  gethooktable(L);\n  lua_pushlightuserdata(L, L1);\n  lua_pushvalue(L, arg+1);\n  lua_rawset(L, -3);  /* set new hook */\n  lua_pop(L, 1);  /* remove hook table */\n  lua_sethook(L1, func, mask, count);  /* set hooks */\n  return 0;\n}\n\n\nstatic int db_gethook (lua_State *L) {\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  char buff[5];\n  int mask = lua_gethookmask(L1);\n  lua_Hook hook = lua_gethook(L1);\n  if (hook != NULL && hook != hookf)  /* external hook? */\n    lua_pushliteral(L, \"external hook\");\n  else {\n    gethooktable(L);\n    lua_pushlightuserdata(L, L1);\n    lua_rawget(L, -2);   /* get hook */\n    lua_remove(L, -2);  /* remove hook table */\n  }\n  lua_pushstring(L, unmakemask(mask, buff));\n  lua_pushinteger(L, lua_gethookcount(L1));\n  return 3;\n}\n\n\nstatic int db_debug (lua_State *L) {\n  for (;;) {\n    char buffer[250];\n    fputs(\"lua_debug> \", stderr);\n    if (fgets(buffer, sizeof(buffer), stdin) == 0 ||\n        strcmp(buffer, \"cont\\n\") == 0)\n      return 0;\n    if (luaL_loadbuffer(L, buffer, strlen(buffer), \"=(debug command)\") ||\n        lua_pcall(L, 0, 0, 0)) {\n      fputs(lua_tostring(L, -1), stderr);\n      fputs(\"\\n\", stderr);\n    }\n    lua_settop(L, 0);  /* remove eventual returns */\n  }\n}\n\n\n#define LEVELS1\t12\t/* size of the first part of the stack */\n#define LEVELS2\t10\t/* size of the second part of the stack */\n\nstatic int db_errorfb (lua_State *L) {\n  int level;\n  int firstpart = 1;  /* still before eventual `...' */\n  int arg;\n  lua_State *L1 = getthread(L, &arg);\n  lua_Debug ar;\n  if (lua_isnumber(L, arg+2)) {\n    level = (int)lua_tointeger(L, arg+2);\n    lua_pop(L, 1);\n  }\n  else\n    level = (L == L1) ? 1 : 0;  /* level 0 may be this own function */\n  if (lua_gettop(L) == arg)\n    lua_pushliteral(L, \"\");\n  else if (!lua_isstring(L, arg+1)) return 1;  /* message is not a string */\n  else lua_pushliteral(L, \"\\n\");\n  lua_pushliteral(L, \"stack traceback:\");\n  while (lua_getstack(L1, level++, &ar)) {\n    if (level > LEVELS1 && firstpart) {\n      /* no more than `LEVELS2' more levels? */\n      if (!lua_getstack(L1, level+LEVELS2, &ar))\n        level--;  /* keep going */\n      else {\n        lua_pushliteral(L, \"\\n\\t...\");  /* too many levels */\n        while (lua_getstack(L1, level+LEVELS2, &ar))  /* find last levels */\n          level++;\n      }\n      firstpart = 0;\n      continue;\n    }\n    lua_pushliteral(L, \"\\n\\t\");\n    lua_getinfo(L1, \"Snl\", &ar);\n    lua_pushfstring(L, \"%s:\", ar.short_src);\n    if (ar.currentline > 0)\n      lua_pushfstring(L, \"%d:\", ar.currentline);\n    if (*ar.namewhat != '\\0')  /* is there a name? */\n        lua_pushfstring(L, \" in function \" LUA_QS, ar.name);\n    else {\n      if (*ar.what == 'm')  /* main? */\n        lua_pushfstring(L, \" in main chunk\");\n      else if (*ar.what == 'C' || *ar.what == 't')\n        lua_pushliteral(L, \" ?\");  /* C function or tail call */\n      else\n        lua_pushfstring(L, \" in function <%s:%d>\",\n                           ar.short_src, ar.linedefined);\n    }\n    lua_concat(L, lua_gettop(L) - arg);\n  }\n  lua_concat(L, lua_gettop(L) - arg);\n  return 1;\n}\n\n\nstatic const luaL_Reg dblib[] = {\n  {\"debug\", db_debug},\n  {\"getfenv\", db_getfenv},\n  {\"gethook\", db_gethook},\n  {\"getinfo\", db_getinfo},\n  {\"getlocal\", db_getlocal},\n  {\"getregistry\", db_getregistry},\n  {\"getmetatable\", db_getmetatable},\n  {\"getupvalue\", db_getupvalue},\n  {\"setfenv\", db_setfenv},\n  {\"sethook\", db_sethook},\n  {\"setlocal\", db_setlocal},\n  {\"setmetatable\", db_setmetatable},\n  {\"setupvalue\", db_setupvalue},\n  {\"traceback\", db_errorfb},\n  {NULL, NULL}\n};\n\n\nLUALIB_API int luaopen_debug (lua_State *L) {\n  luaL_register(L, LUA_DBLIBNAME, dblib);\n  return 1;\n}\n\n"
  },
  {
    "path": "src/lua/ldebug.c",
    "content": "/*\n** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $\n** Debug Interface\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdarg.h>\n#include <stddef.h>\n#include <string.h>\n\n\n#define ldebug_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lapi.h\"\n#include \"lcode.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lvm.h\"\n\n\n\nstatic const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);\n\n\nstatic int currentpc (lua_State *L, CallInfo *ci) {\n  if (!isLua(ci)) return -1;  /* function is not a Lua function? */\n  if (ci == L->ci)\n    ci->savedpc = L->savedpc;\n  return pcRel(ci->savedpc, ci_func(ci)->l.p);\n}\n\n\nstatic int currentline (lua_State *L, CallInfo *ci) {\n  int pc = currentpc(L, ci);\n  if (pc < 0)\n    return -1;  /* only active lua functions have current-line information */\n  else\n    return getline(ci_func(ci)->l.p, pc);\n}\n\n\n/*\n** this function can be called asynchronous (e.g. during a signal)\n*/\nLUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) {\n  if (func == NULL || mask == 0) {  /* turn off hooks? */\n    mask = 0;\n    func = NULL;\n  }\n  L->hook = func;\n  L->basehookcount = count;\n  resethookcount(L);\n  L->hookmask = cast_byte(mask);\n  return 1;\n}\n\n\nLUA_API lua_Hook lua_gethook (lua_State *L) {\n  return L->hook;\n}\n\n\nLUA_API int lua_gethookmask (lua_State *L) {\n  return L->hookmask;\n}\n\n\nLUA_API int lua_gethookcount (lua_State *L) {\n  return L->basehookcount;\n}\n\nLUA_API int lua_gethookcountremaining (lua_State *L) {\n  return L->hookcount;\n}\n\n\nLUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) {\n  int status;\n  CallInfo *ci;\n  lua_lock(L);\n  for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) {\n    level--;\n    if (f_isLua(ci))  /* Lua function? */\n      level -= ci->tailcalls;  /* skip lost tail calls */\n  }\n  if (level == 0 && ci > L->base_ci) {  /* level found? */\n    status = 1;\n    ar->i_ci = cast_int(ci - L->base_ci);\n  }\n  else if (level < 0) {  /* level is of a lost tail call? */\n    status = 1;\n    ar->i_ci = 0;\n  }\n  else status = 0;  /* no such level */\n  lua_unlock(L);\n  return status;\n}\n\n\nstatic Proto *getluaproto (CallInfo *ci) {\n  return (isLua(ci) ? ci_func(ci)->l.p : NULL);\n}\n\n\nstatic const char *findlocal (lua_State *L, CallInfo *ci, int n) {\n  const char *name;\n  Proto *fp = getluaproto(ci);\n  if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL)\n    return name;  /* is a local variable in a Lua function */\n  else {\n    StkId limit = (ci == L->ci) ? L->top : (ci+1)->func;\n    if (limit - ci->base >= n && n > 0)  /* is 'n' inside 'ci' stack? */\n      return \"(*temporary)\";\n    else\n      return NULL;\n  }\n}\n\n\nLUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) {\n  CallInfo *ci = L->base_ci + ar->i_ci;\n  const char *name = findlocal(L, ci, n);\n  lua_lock(L);\n  if (name)\n      luaA_pushobject(L, ci->base + (n - 1));\n  lua_unlock(L);\n  return name;\n}\n\n\nLUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) {\n  CallInfo *ci = L->base_ci + ar->i_ci;\n  const char *name = findlocal(L, ci, n);\n  lua_lock(L);\n  if (name)\n      setobjs2s(L, ci->base + (n - 1), L->top - 1);\n  L->top--;  /* pop value */\n  lua_unlock(L);\n  return name;\n}\n\n\nstatic void funcinfo (lua_Debug *ar, Closure *cl) {\n  if (cl->c.isC) {\n    ar->source = \"=[C]\";\n    ar->linedefined = -1;\n    ar->lastlinedefined = -1;\n    ar->what = \"C\";\n  }\n  else {\n    ar->source = getstr(cl->l.p->source);\n    ar->linedefined = cl->l.p->linedefined;\n    ar->lastlinedefined = cl->l.p->lastlinedefined;\n    ar->what = (ar->linedefined == 0) ? \"main\" : \"Lua\";\n  }\n  luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);\n}\n\n\nstatic void info_tailcall (lua_Debug *ar) {\n  ar->name = ar->namewhat = \"\";\n  ar->what = \"tail\";\n  ar->lastlinedefined = ar->linedefined = ar->currentline = -1;\n  ar->source = \"=(tail call)\";\n  luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE);\n  ar->nups = 0;\n}\n\n\nstatic void collectvalidlines (lua_State *L, Closure *f) {\n  if (f == NULL || f->c.isC) {\n    setnilvalue(L->top);\n  }\n  else {\n    Table *t = luaH_new(L, 0, 0);\n    int *lineinfo = f->l.p->lineinfo;\n    int i;\n    for (i=0; i<f->l.p->sizelineinfo; i++)\n      setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);\n    sethvalue(L, L->top, t); \n  }\n  incr_top(L);\n}\n\n\nstatic int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,\n                    Closure *f, CallInfo *ci) {\n  int status = 1;\n  if (f == NULL) {\n    info_tailcall(ar);\n    return status;\n  }\n  for (; *what; what++) {\n    switch (*what) {\n      case 'S': {\n        funcinfo(ar, f);\n        break;\n      }\n      case 'l': {\n        ar->currentline = (ci) ? currentline(L, ci) : -1;\n        break;\n      }\n      case 'u': {\n        ar->nups = f->c.nupvalues;\n        break;\n      }\n      case 'n': {\n        ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL;\n        if (ar->namewhat == NULL) {\n          ar->namewhat = \"\";  /* not found */\n          ar->name = NULL;\n        }\n        break;\n      }\n      case 'L':\n      case 'f':  /* handled by lua_getinfo */\n        break;\n      default: status = 0;  /* invalid option */\n    }\n  }\n  return status;\n}\n\n\nLUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) {\n  int status;\n  Closure *f = NULL;\n  CallInfo *ci = NULL;\n  lua_lock(L);\n  if (*what == '>') {\n    StkId func = L->top - 1;\n    luai_apicheck(L, ttisfunction(func));\n    what++;  /* skip the '>' */\n    f = clvalue(func);\n    L->top--;  /* pop function */\n  }\n  else if (ar->i_ci != 0) {  /* no tail call? */\n    ci = L->base_ci + ar->i_ci;\n    lua_assert(ttisfunction(ci->func));\n    f = clvalue(ci->func);\n  }\n  status = auxgetinfo(L, what, ar, f, ci);\n  if (strchr(what, 'f')) {\n    if (f == NULL) setnilvalue(L->top);\n    else setclvalue(L, L->top, f);\n    incr_top(L);\n  }\n  if (strchr(what, 'L'))\n    collectvalidlines(L, f);\n  lua_unlock(L);\n  return status;\n}\n\n\n/*\n** {======================================================\n** Symbolic Execution and code checker\n** =======================================================\n*/\n\n#define check(x)\t\tif (!(x)) return 0;\n\n#define checkjump(pt,pc)\tcheck(0 <= pc && pc < pt->sizecode)\n\n#define checkreg(pt,reg)\tcheck((reg) < (pt)->maxstacksize)\n\n\n\nstatic int precheck (const Proto *pt) {\n  check(pt->maxstacksize <= MAXSTACK);\n  check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize);\n  check(!(pt->is_vararg & VARARG_NEEDSARG) ||\n              (pt->is_vararg & VARARG_HASARG));\n  check(pt->sizeupvalues <= pt->nups);\n  check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0);\n  check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN);\n  return 1;\n}\n\n\n#define checkopenop(pt,pc)\tluaG_checkopenop((pt)->code[(pc)+1])\n\nint luaG_checkopenop (Instruction i) {\n  switch (GET_OPCODE(i)) {\n    case OP_CALL:\n    case OP_TAILCALL:\n    case OP_RETURN:\n    case OP_SETLIST: {\n      check(GETARG_B(i) == 0);\n      return 1;\n    }\n    default: return 0;  /* invalid instruction after an open call */\n  }\n}\n\n\nstatic int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) {\n  switch (mode) {\n    case OpArgN: check(r == 0); break;\n    case OpArgU: break;\n    case OpArgR: checkreg(pt, r); break;\n    case OpArgK:\n      check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize);\n      break;\n  }\n  return 1;\n}\n\n\nstatic Instruction symbexec (const Proto *pt, int lastpc, int reg) {\n  int pc;\n  int last;  /* stores position of last instruction that changed `reg' */\n  last = pt->sizecode-1;  /* points to final return (a `neutral' instruction) */\n  check(precheck(pt));\n  for (pc = 0; pc < lastpc; pc++) {\n    Instruction i = pt->code[pc];\n    OpCode op = GET_OPCODE(i);\n    int a = GETARG_A(i);\n    int b = 0;\n    int c = 0;\n    check(op < NUM_OPCODES);\n    checkreg(pt, a);\n    switch (getOpMode(op)) {\n      case iABC: {\n        b = GETARG_B(i);\n        c = GETARG_C(i);\n        check(checkArgMode(pt, b, getBMode(op)));\n        check(checkArgMode(pt, c, getCMode(op)));\n        break;\n      }\n      case iABx: {\n        b = GETARG_Bx(i);\n        if (getBMode(op) == OpArgK) check(b < pt->sizek);\n        break;\n      }\n      case iAsBx: {\n        b = GETARG_sBx(i);\n        if (getBMode(op) == OpArgR) {\n          int dest = pc+1+b;\n          check(0 <= dest && dest < pt->sizecode);\n          if (dest > 0) {\n            int j;\n            /* check that it does not jump to a setlist count; this\n               is tricky, because the count from a previous setlist may\n               have the same value of an invalid setlist; so, we must\n               go all the way back to the first of them (if any) */\n            for (j = 0; j < dest; j++) {\n              Instruction d = pt->code[dest-1-j];\n              if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break;\n            }\n            /* if 'j' is even, previous value is not a setlist (even if\n               it looks like one) */\n            check((j&1) == 0);\n          }\n        }\n        break;\n      }\n    }\n    if (testAMode(op)) {\n      if (a == reg) last = pc;  /* change register `a' */\n    }\n    if (testTMode(op)) {\n      check(pc+2 < pt->sizecode);  /* check skip */\n      check(GET_OPCODE(pt->code[pc+1]) == OP_JMP);\n    }\n    switch (op) {\n      case OP_LOADBOOL: {\n        if (c == 1) {  /* does it jump? */\n          check(pc+2 < pt->sizecode);  /* check its jump */\n          check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST ||\n                GETARG_C(pt->code[pc+1]) != 0);\n        }\n        break;\n      }\n      case OP_LOADNIL: {\n        if (a <= reg && reg <= b)\n          last = pc;  /* set registers from `a' to `b' */\n        break;\n      }\n      case OP_GETUPVAL:\n      case OP_SETUPVAL: {\n        check(b < pt->nups);\n        break;\n      }\n      case OP_GETGLOBAL:\n      case OP_SETGLOBAL: {\n        check(ttisstring(&pt->k[b]));\n        break;\n      }\n      case OP_SELF: {\n        checkreg(pt, a+1);\n        if (reg == a+1) last = pc;\n        break;\n      }\n      case OP_CONCAT: {\n        check(b < c);  /* at least two operands */\n        break;\n      }\n      case OP_TFORLOOP: {\n        check(c >= 1);  /* at least one result (control variable) */\n        checkreg(pt, a+2+c);  /* space for results */\n        if (reg >= a+2) last = pc;  /* affect all regs above its base */\n        break;\n      }\n      case OP_FORLOOP:\n      case OP_FORPREP:\n        checkreg(pt, a+3);\n        /* FALLTHRU */\n      case OP_JMP: {\n        int dest = pc+1+b;\n        /* not full check and jump is forward and do not skip `lastpc'? */\n        if (reg != NO_REG && pc < dest && dest <= lastpc)\n          pc += b;  /* do the jump */\n        break;\n      }\n      case OP_CALL:\n      case OP_TAILCALL: {\n        if (b != 0) {\n          checkreg(pt, a+b-1);\n        }\n        c--;  /* c = num. returns */\n        if (c == LUA_MULTRET) {\n          check(checkopenop(pt, pc));\n        }\n        else if (c != 0)\n          checkreg(pt, a+c-1);\n        if (reg >= a) last = pc;  /* affect all registers above base */\n        break;\n      }\n      case OP_RETURN: {\n        b--;  /* b = num. returns */\n        if (b > 0) checkreg(pt, a+b-1);\n        break;\n      }\n      case OP_SETLIST: {\n        if (b > 0) checkreg(pt, a + b);\n        if (c == 0) {\n          pc++;\n          check(pc < pt->sizecode - 1);\n        }\n        break;\n      }\n      case OP_CLOSURE: {\n        int nup, j;\n        check(b < pt->sizep);\n        nup = pt->p[b]->nups;\n        check(pc + nup < pt->sizecode);\n        for (j = 1; j <= nup; j++) {\n          OpCode op1 = GET_OPCODE(pt->code[pc + j]);\n          check(op1 == OP_GETUPVAL || op1 == OP_MOVE);\n        }\n        if (reg != NO_REG)  /* tracing? */\n          pc += nup;  /* do not 'execute' these pseudo-instructions */\n        break;\n      }\n      case OP_VARARG: {\n        check((pt->is_vararg & VARARG_ISVARARG) &&\n             !(pt->is_vararg & VARARG_NEEDSARG));\n        b--;\n        if (b == LUA_MULTRET) check(checkopenop(pt, pc));\n        checkreg(pt, a+b-1);\n        break;\n      }\n      default: break;\n    }\n  }\n  return pt->code[last];\n}\n\n#undef check\n#undef checkjump\n#undef checkreg\n\n/* }====================================================== */\n\n\nint luaG_checkcode (const Proto *pt) {\n  return (symbexec(pt, pt->sizecode, NO_REG) != 0);\n}\n\n\nstatic const char *kname (Proto *p, int c) {\n  if (ISK(c) && ttisstring(&p->k[INDEXK(c)]))\n    return svalue(&p->k[INDEXK(c)]);\n  else\n    return \"?\";\n}\n\n\nstatic const char *getobjname (lua_State *L, CallInfo *ci, int stackpos,\n                               const char **name) {\n  if (isLua(ci)) {  /* a Lua function? */\n    Proto *p = ci_func(ci)->l.p;\n    int pc = currentpc(L, ci);\n    Instruction i;\n    *name = luaF_getlocalname(p, stackpos+1, pc);\n    if (*name)  /* is a local? */\n      return \"local\";\n    i = symbexec(p, pc, stackpos);  /* try symbolic execution */\n    lua_assert(pc != -1);\n    switch (GET_OPCODE(i)) {\n      case OP_GETGLOBAL: {\n        int g = GETARG_Bx(i);  /* global index */\n        lua_assert(ttisstring(&p->k[g]));\n        *name = svalue(&p->k[g]);\n        return \"global\";\n      }\n      case OP_MOVE: {\n        int a = GETARG_A(i);\n        int b = GETARG_B(i);  /* move from `b' to `a' */\n        if (b < a)\n          return getobjname(L, ci, b, name);  /* get name for `b' */\n        break;\n      }\n      case OP_GETTABLE: {\n        int k = GETARG_C(i);  /* key index */\n        *name = kname(p, k);\n        return \"field\";\n      }\n      case OP_GETUPVAL: {\n        int u = GETARG_B(i);  /* upvalue index */\n        *name = p->upvalues ? getstr(p->upvalues[u]) : \"?\";\n        return \"upvalue\";\n      }\n      case OP_SELF: {\n        int k = GETARG_C(i);  /* key index */\n        *name = kname(p, k);\n        return \"method\";\n      }\n      default: break;\n    }\n  }\n  return NULL;  /* no useful name found */\n}\n\n\nstatic const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {\n  Instruction i;\n  if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1))\n    return NULL;  /* calling function is not Lua (or is unknown) */\n  ci--;  /* calling function */\n  i = ci_func(ci)->l.p->code[currentpc(L, ci)];\n  if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL ||\n      GET_OPCODE(i) == OP_TFORLOOP)\n    return getobjname(L, ci, GETARG_A(i), name);\n  else\n    return NULL;  /* no useful name can be found */\n}\n\n\n/* only ANSI way to check whether a pointer points to an array */\nstatic int isinstack (CallInfo *ci, const TValue *o) {\n  StkId p;\n  for (p = ci->base; p < ci->top; p++)\n    if (o == p) return 1;\n  return 0;\n}\n\n\nvoid luaG_typeerror (lua_State *L, const TValue *o, const char *op) {\n  const char *name = NULL;\n  const char *t = luaT_typenames[ttype(o)];\n  const char *kind = (isinstack(L->ci, o)) ?\n                         getobjname(L, L->ci, cast_int(o - L->base), &name) :\n                         NULL;\n  if (kind)\n    luaG_runerror(L, \"attempt to %s %s \" LUA_QS \" (a %s value)\",\n                op, kind, name, t);\n  else\n    luaG_runerror(L, \"attempt to %s a %s value\", op, t);\n}\n\n\nvoid luaG_concaterror (lua_State *L, StkId p1, StkId p2) {\n  if (ttisstring(p1) || ttisnumber(p1)) p1 = p2;\n  lua_assert(!ttisstring(p1) && !ttisnumber(p1));\n  luaG_typeerror(L, p1, \"concatenate\");\n}\n\n\nvoid luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) {\n  TValue temp;\n  if (luaV_tonumber(p1, &temp) == NULL)\n    p2 = p1;  /* first operand is wrong */\n  luaG_typeerror(L, p2, \"perform arithmetic on\");\n}\n\n\nint luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) {\n  const char *t1 = luaT_typenames[ttype(p1)];\n  const char *t2 = luaT_typenames[ttype(p2)];\n  if (t1[2] == t2[2])\n    luaG_runerror(L, \"attempt to compare two %s values\", t1);\n  else\n    luaG_runerror(L, \"attempt to compare %s with %s\", t1, t2);\n  return 0;\n}\n\n\nstatic void addinfo (lua_State *L, const char *msg) {\n  CallInfo *ci = L->ci;\n  if (isLua(ci)) {  /* is Lua code? */\n    char buff[LUA_IDSIZE];  /* add file:line information */\n    int line = currentline(L, ci);\n    luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE);\n    luaO_pushfstring(L, \"%s:%d: %s\", buff, line, msg);\n  }\n}\n\n\nvoid luaG_errormsg (lua_State *L) {\n  if (L->errfunc != 0) {  /* is there an error handling function? */\n    StkId errfunc = restorestack(L, L->errfunc);\n    if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR);\n    setobjs2s(L, L->top, L->top - 1);  /* move argument */\n    setobjs2s(L, L->top - 1, errfunc);  /* push function */\n    incr_top(L);\n    luaD_call(L, L->top - 2, 1);  /* call it */\n  }\n  luaD_throw(L, LUA_ERRRUN);\n}\n\n\nvoid luaG_runerror (lua_State *L, const char *fmt, ...) {\n  va_list argp;\n  va_start(argp, fmt);\n  addinfo(L, luaO_pushvfstring(L, fmt, argp));\n  va_end(argp);\n  luaG_errormsg(L);\n}\n\n"
  },
  {
    "path": "src/lua/ldebug.h",
    "content": "/*\n** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions from Debug Interface module\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ldebug_h\n#define ldebug_h\n\n\n#include \"lstate.h\"\n\n\n#define pcRel(pc, p)\t(cast(int, (pc) - (p)->code) - 1)\n\n#define getline(f,pc)\t(((f)->lineinfo) ? (f)->lineinfo[pc] : 0)\n\n#define resethookcount(L)\t(L->hookcount = L->basehookcount)\n\n\nLUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o,\n                                             const char *opname);\nLUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2);\nLUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1,\n                                              const TValue *p2);\nLUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1,\n                                             const TValue *p2);\nLUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...);\nLUAI_FUNC void luaG_errormsg (lua_State *L);\nLUAI_FUNC int luaG_checkcode (const Proto *pt);\nLUAI_FUNC int luaG_checkopenop (Instruction i);\n\n#endif\n"
  },
  {
    "path": "src/lua/ldo.c",
    "content": "/*\n** $Id: ldo.c,v 2.38.1.4 2012/01/18 02:27:10 roberto Exp $\n** Stack and Call structure of Lua\n** See Copyright Notice in lua.h\n*/\n\n\n#include <setjmp.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define ldo_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lundump.h\"\n#include \"lvm.h\"\n#include \"lzio.h\"\n\n\n\n\n/*\n** {======================================================\n** Error-recovery functions\n** =======================================================\n*/\n\n\n/* chain list of long jump buffers */\nstruct lua_longjmp {\n  struct lua_longjmp *previous;\n  luai_jmpbuf b;\n  volatile int status;  /* error code */\n};\n\n\nvoid luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) {\n  switch (errcode) {\n    case LUA_ERRMEM: {\n      setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG));\n      break;\n    }\n    case LUA_ERRERR: {\n      setsvalue2s(L, oldtop, luaS_newliteral(L, \"error in error handling\"));\n      break;\n    }\n    case LUA_ERRSYNTAX:\n    case LUA_ERRRUN: {\n      setobjs2s(L, oldtop, L->top - 1);  /* error message on current top */\n      break;\n    }\n  }\n  L->top = oldtop + 1;\n}\n\n\nstatic void restore_stack_limit (lua_State *L) {\n  lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);\n  if (L->size_ci > LUAI_MAXCALLS) {  /* there was an overflow? */\n    int inuse = cast_int(L->ci - L->base_ci);\n    if (inuse + 1 < LUAI_MAXCALLS)  /* can `undo' overflow? */\n      luaD_reallocCI(L, LUAI_MAXCALLS);\n  }\n}\n\n\nstatic void resetstack (lua_State *L, int status) {\n  L->ci = L->base_ci;\n  L->base = L->ci->base;\n  luaF_close(L, L->base);  /* close eventual pending closures */\n  luaD_seterrorobj(L, status, L->base);\n  L->nCcalls = L->baseCcalls;\n  L->allowhook = 1;\n  restore_stack_limit(L);\n  L->errfunc = 0;\n  L->errorJmp = NULL;\n}\n\n\nvoid luaD_throw (lua_State *L, int errcode) {\n  if (L->errorJmp) {\n    L->errorJmp->status = errcode;\n    LUAI_THROW(L, L->errorJmp);\n  }\n  else {\n    L->status = cast_byte(errcode);\n    if (G(L)->panic) {\n      resetstack(L, errcode);\n      lua_unlock(L);\n      G(L)->panic(L);\n    }\n    exit(EXIT_FAILURE);\n  }\n}\n\n\nint luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {\n  struct lua_longjmp lj;\n  lj.status = 0;\n  lj.previous = L->errorJmp;  /* chain new error handler */\n  L->errorJmp = &lj;\n  LUAI_TRY(L, &lj,\n    (*f)(L, ud);\n  );\n  L->errorJmp = lj.previous;  /* restore old error handler */\n  return lj.status;\n}\n\n/* }====================================================== */\n\n\nstatic void correctstack (lua_State *L, TValue *oldstack) {\n  CallInfo *ci;\n  GCObject *up;\n  L->top = (L->top - oldstack) + L->stack;\n  for (up = L->openupval; up != NULL; up = up->gch.next)\n    gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack;\n  for (ci = L->base_ci; ci <= L->ci; ci++) {\n    ci->top = (ci->top - oldstack) + L->stack;\n    ci->base = (ci->base - oldstack) + L->stack;\n    ci->func = (ci->func - oldstack) + L->stack;\n  }\n  L->base = (L->base - oldstack) + L->stack;\n}\n\n\nvoid luaD_reallocstack (lua_State *L, int newsize) {\n  TValue *oldstack = L->stack;\n  int realsize = newsize + 1 + EXTRA_STACK;\n  lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1);\n  luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue);\n  L->stacksize = realsize;\n  L->stack_last = L->stack+newsize;\n  correctstack(L, oldstack);\n}\n\n\nvoid luaD_reallocCI (lua_State *L, int newsize) {\n  CallInfo *oldci = L->base_ci;\n  luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo);\n  L->size_ci = newsize;\n  L->ci = (L->ci - oldci) + L->base_ci;\n  L->end_ci = L->base_ci + L->size_ci - 1;\n}\n\n\nvoid luaD_growstack (lua_State *L, int n) {\n  if (n <= L->stacksize)  /* double size is enough? */\n    luaD_reallocstack(L, 2*L->stacksize);\n  else\n    luaD_reallocstack(L, L->stacksize + n);\n}\n\n\nstatic CallInfo *growCI (lua_State *L) {\n  if (L->size_ci > LUAI_MAXCALLS)  /* overflow while handling overflow? */\n    luaD_throw(L, LUA_ERRERR);\n  else {\n    luaD_reallocCI(L, 2*L->size_ci);\n    if (L->size_ci > LUAI_MAXCALLS)\n      luaG_runerror(L, \"stack overflow\");\n  }\n  return ++L->ci;\n}\n\n\nvoid luaD_callhook (lua_State *L, int event, int line) {\n  lua_Hook hook = L->hook;\n  if (hook && L->allowhook) {\n    ptrdiff_t top = savestack(L, L->top);\n    ptrdiff_t ci_top = savestack(L, L->ci->top);\n    lua_Debug ar;\n    ar.event = event;\n    ar.currentline = line;\n    if (event == LUA_HOOKTAILRET)\n      ar.i_ci = 0;  /* tail call; no debug information about it */\n    else\n      ar.i_ci = cast_int(L->ci - L->base_ci);\n    luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */\n    L->ci->top = L->top + LUA_MINSTACK;\n    lua_assert(L->ci->top <= L->stack_last);\n    L->allowhook = 0;  /* cannot call hooks inside a hook */\n    lua_unlock(L);\n    (*hook)(L, &ar);\n    lua_lock(L);\n    lua_assert(!L->allowhook);\n    L->allowhook = 1;\n    L->ci->top = restorestack(L, ci_top);\n    L->top = restorestack(L, top);\n  }\n}\n\n\nstatic StkId adjust_varargs (lua_State *L, Proto *p, int actual) {\n  int i;\n  int nfixargs = p->numparams;\n  Table *htab = NULL;\n  StkId base, fixed;\n  for (; actual < nfixargs; ++actual)\n    setnilvalue(L->top++);\n#if defined(LUA_COMPAT_VARARG)\n  if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */\n    int nvar = actual - nfixargs;  /* number of extra arguments */\n    lua_assert(p->is_vararg & VARARG_HASARG);\n    luaC_checkGC(L);\n    luaD_checkstack(L, p->maxstacksize);\n    htab = luaH_new(L, nvar, 1);  /* create `arg' table */\n    for (i=0; i<nvar; i++)  /* put extra arguments into `arg' table */\n      setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);\n    /* store counter in field `n' */\n    setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, \"n\")), cast_num(nvar));\n  }\n#endif\n  /* move fixed parameters to final position */\n  fixed = L->top - actual;  /* first fixed argument */\n  base = L->top;  /* final position of first argument */\n  for (i=0; i<nfixargs; i++) {\n    setobjs2s(L, L->top++, fixed+i);\n    setnilvalue(fixed+i);\n  }\n  /* add `arg' parameter */\n  if (htab) {\n    sethvalue(L, L->top++, htab);\n    lua_assert(iswhite(obj2gco(htab)));\n  }\n  return base;\n}\n\n\nstatic StkId tryfuncTM (lua_State *L, StkId func) {\n  const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL);\n  StkId p;\n  ptrdiff_t funcr = savestack(L, func);\n  if (!ttisfunction(tm))\n    luaG_typeerror(L, func, \"call\");\n  /* Open a hole inside the stack at `func' */\n  for (p = L->top; p > func; p--) setobjs2s(L, p, p-1);\n  incr_top(L);\n  func = restorestack(L, funcr);  /* previous call may change stack */\n  setobj2s(L, func, tm);  /* tag method is the new function to be called */\n  return func;\n}\n\n\n\n#define inc_ci(L) \\\n  ((L->ci == L->end_ci) ? growCI(L) : \\\n   (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci))\n\n\nint luaD_precall (lua_State *L, StkId func, int nresults) {\n  LClosure *cl;\n  ptrdiff_t funcr;\n  if (!ttisfunction(func)) /* `func' is not a function? */\n    func = tryfuncTM(L, func);  /* check the `function' tag method */\n  funcr = savestack(L, func);\n  cl = &clvalue(func)->l;\n  L->ci->savedpc = L->savedpc;\n  if (!cl->isC) {  /* Lua function? prepare its call */\n    CallInfo *ci;\n    StkId st, base;\n    Proto *p = cl->p;\n    luaD_checkstack(L, p->maxstacksize + p->numparams);\n    func = restorestack(L, funcr);\n    if (!p->is_vararg) {  /* no varargs? */\n      base = func + 1;\n      if (L->top > base + p->numparams)\n        L->top = base + p->numparams;\n    }\n    else {  /* vararg function */\n      int nargs = cast_int(L->top - func) - 1;\n      base = adjust_varargs(L, p, nargs);\n      func = restorestack(L, funcr);  /* previous call may change the stack */\n    }\n    ci = inc_ci(L);  /* now `enter' new function */\n    ci->func = func;\n    L->base = ci->base = base;\n    ci->top = L->base + p->maxstacksize;\n    lua_assert(ci->top <= L->stack_last);\n    L->savedpc = p->code;  /* starting point */\n    ci->tailcalls = 0;\n    ci->nresults = nresults;\n    for (st = L->top; st < ci->top; st++)\n      setnilvalue(st);\n    L->top = ci->top;\n    if (L->hookmask & LUA_MASKCALL) {\n      L->savedpc++;  /* hooks assume 'pc' is already incremented */\n      luaD_callhook(L, LUA_HOOKCALL, -1);\n      L->savedpc--;  /* correct 'pc' */\n    }\n    return PCRLUA;\n  }\n  else {  /* if is a C function, call it */\n    CallInfo *ci;\n    int n;\n    luaD_checkstack(L, LUA_MINSTACK);  /* ensure minimum stack size */\n    ci = inc_ci(L);  /* now `enter' new function */\n    ci->func = restorestack(L, funcr);\n    L->base = ci->base = ci->func + 1;\n    ci->top = L->top + LUA_MINSTACK;\n    lua_assert(ci->top <= L->stack_last);\n    ci->nresults = nresults;\n    if (L->hookmask & LUA_MASKCALL)\n      luaD_callhook(L, LUA_HOOKCALL, -1);\n    lua_unlock(L);\n    n = (*curr_func(L)->c.f)(L);  /* do the actual call */\n    lua_lock(L);\n    if (n < 0)  /* yielding? */\n      return PCRYIELD;\n    else {\n      luaD_poscall(L, L->top - n);\n      return PCRC;\n    }\n  }\n}\n\n\nstatic StkId callrethooks (lua_State *L, StkId firstResult) {\n  ptrdiff_t fr = savestack(L, firstResult);  /* next call may change stack */\n  luaD_callhook(L, LUA_HOOKRET, -1);\n  if (f_isLua(L->ci)) {  /* Lua function? */\n    while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */\n      luaD_callhook(L, LUA_HOOKTAILRET, -1);\n  }\n  return restorestack(L, fr);\n}\n\n\nint luaD_poscall (lua_State *L, StkId firstResult) {\n  StkId res;\n  int wanted, i;\n  CallInfo *ci;\n  if (L->hookmask & LUA_MASKRET)\n    firstResult = callrethooks(L, firstResult);\n  ci = L->ci--;\n  res = ci->func;  /* res == final position of 1st result */\n  wanted = ci->nresults;\n  L->base = (ci - 1)->base;  /* restore base */\n  L->savedpc = (ci - 1)->savedpc;  /* restore savedpc */\n  /* move results to correct place */\n  for (i = wanted; i != 0 && firstResult < L->top; i--)\n    setobjs2s(L, res++, firstResult++);\n  while (i-- > 0)\n    setnilvalue(res++);\n  L->top = res;\n  return (wanted - LUA_MULTRET);  /* 0 iff wanted == LUA_MULTRET */\n}\n\n\n/*\n** Call a function (C or Lua). The function to be called is at *func.\n** The arguments are on the stack, right after the function.\n** When returns, all the results are on the stack, starting at the original\n** function position.\n*/ \nvoid luaD_call (lua_State *L, StkId func, int nResults) {\n  if (++L->nCcalls >= LUAI_MAXCCALLS) {\n    if (L->nCcalls == LUAI_MAXCCALLS)\n      luaG_runerror(L, \"C stack overflow\");\n    else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3)))\n      luaD_throw(L, LUA_ERRERR);  /* error while handing stack error */\n  }\n  if (luaD_precall(L, func, nResults) == PCRLUA)  /* is a Lua function? */\n    luaV_execute(L, 1);  /* call it */\n  L->nCcalls--;\n  luaC_checkGC(L);\n}\n\n\nstatic void resume (lua_State *L, void *ud) {\n  StkId firstArg = cast(StkId, ud);\n  CallInfo *ci = L->ci;\n  if (L->status == 0) {  /* start coroutine? */\n    lua_assert(ci == L->base_ci && firstArg > L->base);\n    if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA)\n      return;\n  }\n  else {  /* resuming from previous yield */\n    lua_assert(L->status == LUA_YIELD);\n    L->status = 0;\n    if (!f_isLua(ci)) {  /* `common' yield? */\n      /* finish interrupted execution of `OP_CALL' */\n      lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL ||\n                 GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL);\n      if (luaD_poscall(L, firstArg))  /* complete it... */\n        L->top = L->ci->top;  /* and correct top if not multiple results */\n    }\n    else  /* yielded inside a hook: just continue its execution */\n      L->base = L->ci->base;\n  }\n  luaV_execute(L, cast_int(L->ci - L->base_ci));\n}\n\n\nstatic int resume_error (lua_State *L, const char *msg) {\n  L->top = L->ci->base;\n  setsvalue2s(L, L->top, luaS_new(L, msg));\n  incr_top(L);\n  lua_unlock(L);\n  return LUA_ERRRUN;\n}\n\n\nLUA_API int lua_resume (lua_State *L, int nargs) {\n  int status;\n  lua_lock(L);\n  if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci))\n      return resume_error(L, \"cannot resume non-suspended coroutine\");\n  if (L->nCcalls >= LUAI_MAXCCALLS)\n    return resume_error(L, \"C stack overflow\");\n  luai_userstateresume(L, nargs);\n  lua_assert(L->errfunc == 0);\n  L->baseCcalls = ++L->nCcalls;\n  status = luaD_rawrunprotected(L, resume, L->top - nargs);\n  if (status != 0) {  /* error? */\n    L->status = cast_byte(status);  /* mark thread as `dead' */\n    luaD_seterrorobj(L, status, L->top);\n    L->ci->top = L->top;\n  }\n  else {\n    lua_assert(L->nCcalls == L->baseCcalls);\n    status = L->status;\n  }\n  --L->nCcalls;\n  lua_unlock(L);\n  return status;\n}\n\n\nLUA_API int lua_yield (lua_State *L, int nresults) {\n  luai_userstateyield(L, nresults);\n  lua_lock(L);\n  if (L->nCcalls > L->baseCcalls)\n    luaG_runerror(L, \"attempt to yield across metamethod/C-call boundary\");\n  L->base = L->top - nresults;  /* protect stack slots below */\n  L->status = LUA_YIELD;\n  lua_unlock(L);\n  return -1;\n}\n\n\nint luaD_pcall (lua_State *L, Pfunc func, void *u,\n                ptrdiff_t old_top, ptrdiff_t ef) {\n  int status;\n  unsigned short oldnCcalls = L->nCcalls;\n  ptrdiff_t old_ci = saveci(L, L->ci);\n  lu_byte old_allowhooks = L->allowhook;\n  ptrdiff_t old_errfunc = L->errfunc;\n  L->errfunc = ef;\n  status = luaD_rawrunprotected(L, func, u);\n  if (status != 0) {  /* an error occurred? */\n    StkId oldtop = restorestack(L, old_top);\n    luaF_close(L, oldtop);  /* close eventual pending closures */\n    luaD_seterrorobj(L, status, oldtop);\n    L->nCcalls = oldnCcalls;\n    L->ci = restoreci(L, old_ci);\n    L->base = L->ci->base;\n    L->savedpc = L->ci->savedpc;\n    L->allowhook = old_allowhooks;\n    restore_stack_limit(L);\n  }\n  L->errfunc = old_errfunc;\n  return status;\n}\n\n\n\n/*\n** Execute a protected parser.\n*/\nstruct SParser {  /* data to `f_parser' */\n  ZIO *z;\n  Mbuffer buff;  /* buffer to be used by the scanner */\n  const char *name;\n};\n\nstatic void f_parser (lua_State *L, void *ud) {\n  int i;\n  Proto *tf;\n  Closure *cl;\n  struct SParser *p = cast(struct SParser *, ud);\n  int c = luaZ_lookahead(p->z);\n  luaC_checkGC(L);\n  tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,\n                                                             &p->buff, p->name);\n  cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));\n  cl->l.p = tf;\n  for (i = 0; i < tf->nups; i++)  /* initialize eventual upvalues */\n    cl->l.upvals[i] = luaF_newupval(L);\n  setclvalue(L, L->top, cl);\n  incr_top(L);\n}\n\n\nint luaD_protectedparser (lua_State *L, ZIO *z, const char *name) {\n  struct SParser p;\n  int status;\n  p.z = z; p.name = name;\n  luaZ_initbuffer(L, &p.buff);\n  status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);\n  luaZ_freebuffer(L, &p.buff);\n  return status;\n}\n\n\n"
  },
  {
    "path": "src/lua/ldo.h",
    "content": "/*\n** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $\n** Stack and Call structure of Lua\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ldo_h\n#define ldo_h\n\n\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lzio.h\"\n\n\n#define luaD_checkstack(L,n)\t\\\n  if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \\\n    luaD_growstack(L, n); \\\n  else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1));\n\n\n#define incr_top(L) {luaD_checkstack(L,1); L->top++;}\n\n#define savestack(L,p)\t\t((char *)(p) - (char *)L->stack)\n#define restorestack(L,n)\t((TValue *)((char *)L->stack + (n)))\n\n#define saveci(L,p)\t\t((char *)(p) - (char *)L->base_ci)\n#define restoreci(L,n)\t\t((CallInfo *)((char *)L->base_ci + (n)))\n\n\n/* results from luaD_precall */\n#define PCRLUA\t\t0\t/* initiated a call to a Lua function */\n#define PCRC\t\t1\t/* did a call to a C function */\n#define PCRYIELD\t2\t/* C funtion yielded */\n\n\n/* type of protected functions, to be ran by `runprotected' */\ntypedef void (*Pfunc) (lua_State *L, void *ud);\n\nLUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name);\nLUAI_FUNC void luaD_callhook (lua_State *L, int event, int line);\nLUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults);\nLUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults);\nLUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,\n                                        ptrdiff_t oldtop, ptrdiff_t ef);\nLUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult);\nLUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize);\nLUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);\nLUAI_FUNC void luaD_growstack (lua_State *L, int n);\n\nLUAI_FUNC void luaD_throw (lua_State *L, int errcode);\nLUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);\n\nLUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop);\n\n#endif\n\n"
  },
  {
    "path": "src/lua/ldump.c",
    "content": "/*\n** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $\n** save precompiled Lua chunks\n** See Copyright Notice in lua.h\n*/\n\n#include <stddef.h>\n\n#define ldump_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lundump.h\"\n\ntypedef struct {\n lua_State* L;\n lua_Writer writer;\n void* data;\n int strip;\n int status;\n} DumpState;\n\n#define DumpMem(b,n,size,D)\tDumpBlock(b,(n)*(size),D)\n#define DumpVar(x,D)\t \tDumpMem(&x,1,sizeof(x),D)\n\nstatic void DumpBlock(const void* b, size_t size, DumpState* D)\n{\n if (D->status==0)\n {\n  lua_unlock(D->L);\n  D->status=(*D->writer)(D->L,b,size,D->data);\n  lua_lock(D->L);\n }\n}\n\nstatic void DumpChar(int y, DumpState* D)\n{\n char x=(char)y;\n DumpVar(x,D);\n}\n\nstatic void DumpInt(int x, DumpState* D)\n{\n DumpVar(x,D);\n}\n\nstatic void DumpNumber(lua_Number x, DumpState* D)\n{\n DumpVar(x,D);\n}\n\nstatic void DumpVector(const void* b, int n, size_t size, DumpState* D)\n{\n DumpInt(n,D);\n DumpMem(b,n,size,D);\n}\n\nstatic void DumpString(const TString* s, DumpState* D)\n{\n if (s==NULL || getstr(s)==NULL)\n {\n  size_t size=0;\n  DumpVar(size,D);\n }\n else\n {\n  size_t size=s->tsv.len+1;\t\t/* include trailing '\\0' */\n  DumpVar(size,D);\n  DumpBlock(getstr(s),size,D);\n }\n}\n\n#define DumpCode(f,D)\t DumpVector(f->code,f->sizecode,sizeof(Instruction),D)\n\nstatic void DumpFunction(const Proto* f, const TString* p, DumpState* D);\n\nstatic void DumpConstants(const Proto* f, DumpState* D)\n{\n int i,n=f->sizek;\n DumpInt(n,D);\n for (i=0; i<n; i++)\n {\n  const TValue* o=&f->k[i];\n  DumpChar(ttype(o),D);\n  switch (ttype(o))\n  {\n   case LUA_TNIL:\n\tbreak;\n   case LUA_TBOOLEAN:\n\tDumpChar(bvalue(o),D);\n\tbreak;\n   case LUA_TNUMBER:\n\tDumpNumber(nvalue(o),D);\n\tbreak;\n   case LUA_TSTRING:\n\tDumpString(rawtsvalue(o),D);\n\tbreak;\n   default:\n\tlua_assert(0);\t\t\t/* cannot happen */\n\tbreak;\n  }\n }\n n=f->sizep;\n DumpInt(n,D);\n for (i=0; i<n; i++) DumpFunction(f->p[i],f->source,D);\n}\n\nstatic void DumpDebug(const Proto* f, DumpState* D)\n{\n int i,n;\n n= (D->strip) ? 0 : f->sizelineinfo;\n DumpVector(f->lineinfo,n,sizeof(int),D);\n n= (D->strip) ? 0 : f->sizelocvars;\n DumpInt(n,D);\n for (i=0; i<n; i++)\n {\n  DumpString(f->locvars[i].varname,D);\n  DumpInt(f->locvars[i].startpc,D);\n  DumpInt(f->locvars[i].endpc,D);\n }\n n= (D->strip) ? 0 : f->sizeupvalues;\n DumpInt(n,D);\n for (i=0; i<n; i++) DumpString(f->upvalues[i],D);\n}\n\nstatic void DumpFunction(const Proto* f, const TString* p, DumpState* D)\n{\n DumpString((f->source==p || D->strip) ? NULL : f->source,D);\n DumpInt(f->linedefined,D);\n DumpInt(f->lastlinedefined,D);\n DumpChar(f->nups,D);\n DumpChar(f->numparams,D);\n DumpChar(f->is_vararg,D);\n DumpChar(f->maxstacksize,D);\n DumpCode(f,D);\n DumpConstants(f,D);\n DumpDebug(f,D);\n}\n\nstatic void DumpHeader(DumpState* D)\n{\n char h[LUAC_HEADERSIZE];\n luaU_header(h);\n DumpBlock(h,LUAC_HEADERSIZE,D);\n}\n\n/*\n** dump Lua function as precompiled chunk\n*/\nint luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip)\n{\n DumpState D;\n D.L=L;\n D.writer=w;\n D.data=data;\n D.strip=strip;\n D.status=0;\n DumpHeader(&D);\n DumpFunction(f,NULL,&D);\n return D.status;\n}\n"
  },
  {
    "path": "src/lua/lfunc.c",
    "content": "/*\n** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $\n** Auxiliary functions to manipulate prototypes and closures\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define lfunc_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n\n\n\nClosure *luaF_newCclosure (lua_State *L, int nelems, Table *e) {\n  Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems)));\n  luaC_link(L, obj2gco(c), LUA_TFUNCTION);\n  c->c.isC = 1;\n  c->c.env = e;\n  c->c.nupvalues = cast_byte(nelems);\n  return c;\n}\n\n\nClosure *luaF_newLclosure (lua_State *L, int nelems, Table *e) {\n  Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems)));\n  luaC_link(L, obj2gco(c), LUA_TFUNCTION);\n  c->l.isC = 0;\n  c->l.env = e;\n  c->l.nupvalues = cast_byte(nelems);\n  while (nelems--) c->l.upvals[nelems] = NULL;\n  return c;\n}\n\n\nUpVal *luaF_newupval (lua_State *L) {\n  UpVal *uv = luaM_new(L, UpVal);\n  luaC_link(L, obj2gco(uv), LUA_TUPVAL);\n  uv->v = &uv->u.value;\n  setnilvalue(uv->v);\n  return uv;\n}\n\n\nUpVal *luaF_findupval (lua_State *L, StkId level) {\n  global_State *g = G(L);\n  GCObject **pp = &L->openupval;\n  UpVal *p;\n  UpVal *uv;\n  while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) {\n    lua_assert(p->v != &p->u.value);\n    if (p->v == level) {  /* found a corresponding upvalue? */\n      if (isdead(g, obj2gco(p)))  /* is it dead? */\n        changewhite(obj2gco(p));  /* ressurect it */\n      return p;\n    }\n    pp = &p->next;\n  }\n  uv = luaM_new(L, UpVal);  /* not found: create a new one */\n  uv->tt = LUA_TUPVAL;\n  uv->marked = luaC_white(g);\n  uv->v = level;  /* current value lives in the stack */\n  uv->next = *pp;  /* chain it in the proper position */\n  *pp = obj2gco(uv);\n  uv->u.l.prev = &g->uvhead;  /* double link it in `uvhead' list */\n  uv->u.l.next = g->uvhead.u.l.next;\n  uv->u.l.next->u.l.prev = uv;\n  g->uvhead.u.l.next = uv;\n  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);\n  return uv;\n}\n\n\nstatic void unlinkupval (UpVal *uv) {\n  lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);\n  uv->u.l.next->u.l.prev = uv->u.l.prev;  /* remove from `uvhead' list */\n  uv->u.l.prev->u.l.next = uv->u.l.next;\n}\n\n\nvoid luaF_freeupval (lua_State *L, UpVal *uv) {\n  if (uv->v != &uv->u.value)  /* is it open? */\n    unlinkupval(uv);  /* remove from open list */\n  luaM_free(L, uv);  /* free upvalue */\n}\n\n\nvoid luaF_close (lua_State *L, StkId level) {\n  UpVal *uv;\n  global_State *g = G(L);\n  while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) {\n    GCObject *o = obj2gco(uv);\n    lua_assert(!isblack(o) && uv->v != &uv->u.value);\n    L->openupval = uv->next;  /* remove from `open' list */\n    if (isdead(g, o))\n      luaF_freeupval(L, uv);  /* free upvalue */\n    else {\n      unlinkupval(uv);\n      setobj(L, &uv->u.value, uv->v);\n      uv->v = &uv->u.value;  /* now current value lives here */\n      luaC_linkupval(L, uv);  /* link upvalue into `gcroot' list */\n    }\n  }\n}\n\n\nProto *luaF_newproto (lua_State *L) {\n  Proto *f = luaM_new(L, Proto);\n  luaC_link(L, obj2gco(f), LUA_TPROTO);\n  f->k = NULL;\n  f->sizek = 0;\n  f->p = NULL;\n  f->sizep = 0;\n  f->code = NULL;\n  f->sizecode = 0;\n  f->sizelineinfo = 0;\n  f->sizeupvalues = 0;\n  f->nups = 0;\n  f->upvalues = NULL;\n  f->numparams = 0;\n  f->is_vararg = 0;\n  f->maxstacksize = 0;\n  f->lineinfo = NULL;\n  f->sizelocvars = 0;\n  f->locvars = NULL;\n  f->linedefined = 0;\n  f->lastlinedefined = 0;\n  f->source = NULL;\n  return f;\n}\n\n\nvoid luaF_freeproto (lua_State *L, Proto *f) {\n  luaM_freearray(L, f->code, f->sizecode, Instruction);\n  luaM_freearray(L, f->p, f->sizep, Proto *);\n  luaM_freearray(L, f->k, f->sizek, TValue);\n  luaM_freearray(L, f->lineinfo, f->sizelineinfo, int);\n  luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar);\n  luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *);\n  luaM_free(L, f);\n}\n\n\nvoid luaF_freeclosure (lua_State *L, Closure *c) {\n  int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) :\n                          sizeLclosure(c->l.nupvalues);\n  luaM_freemem(L, c, size);\n}\n\n\n/*\n** Look for n-th local variable at line `line' in function `func'.\n** Returns NULL if not found.\n*/\nconst char *luaF_getlocalname (const Proto *f, int local_number, int pc) {\n  int i;\n  for (i = 0; i<f->sizelocvars && f->locvars[i].startpc <= pc; i++) {\n    if (pc < f->locvars[i].endpc) {  /* is variable active? */\n      local_number--;\n      if (local_number == 0)\n        return getstr(f->locvars[i].varname);\n    }\n  }\n  return NULL;  /* not found */\n}\n\n"
  },
  {
    "path": "src/lua/lfunc.h",
    "content": "/*\n** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $\n** Auxiliary functions to manipulate prototypes and closures\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lfunc_h\n#define lfunc_h\n\n\n#include \"lobject.h\"\n\n\n#define sizeCclosure(n)\t(cast(int, sizeof(CClosure)) + \\\n                         cast(int, sizeof(TValue)*((n)-1)))\n\n#define sizeLclosure(n)\t(cast(int, sizeof(LClosure)) + \\\n                         cast(int, sizeof(TValue *)*((n)-1)))\n\n\nLUAI_FUNC Proto *luaF_newproto (lua_State *L);\nLUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e);\nLUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e);\nLUAI_FUNC UpVal *luaF_newupval (lua_State *L);\nLUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level);\nLUAI_FUNC void luaF_close (lua_State *L, StkId level);\nLUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f);\nLUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c);\nLUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv);\nLUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number,\n                                         int pc);\n\n\n#endif\n"
  },
  {
    "path": "src/lua/lgc.c",
    "content": "/*\n** $Id: lgc.c,v 2.38.1.2 2011/03/18 18:05:38 roberto Exp $\n** Garbage Collector\n** See Copyright Notice in lua.h\n*/\n\n#include <string.h>\n\n#define lgc_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n\n\n#define GCSTEPSIZE\t1024u\n#define GCSWEEPMAX\t40\n#define GCSWEEPCOST\t10\n#define GCFINALIZECOST\t100\n\n\n#define maskmarks\tcast_byte(~(bitmask(BLACKBIT)|WHITEBITS))\n\n#define makewhite(g,x)\t\\\n   ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g)))\n\n#define white2gray(x)\treset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)\n#define black2gray(x)\tresetbit((x)->gch.marked, BLACKBIT)\n\n#define stringmark(s)\treset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT)\n\n\n#define isfinalized(u)\t\ttestbit((u)->marked, FINALIZEDBIT)\n#define markfinalized(u)\tl_setbit((u)->marked, FINALIZEDBIT)\n\n\n#define KEYWEAK         bitmask(KEYWEAKBIT)\n#define VALUEWEAK       bitmask(VALUEWEAKBIT)\n\n\n\n#define markvalue(g,o) { checkconsistency(o); \\\n  if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); }\n\n#define markobject(g,t) { if (iswhite(obj2gco(t))) \\\n\t\treallymarkobject(g, obj2gco(t)); }\n\n\n#define setthreshold(g)  (g->GCthreshold = (g->estimate/100) * g->gcpause)\n\n\nstatic void removeentry (Node *n) {\n  lua_assert(ttisnil(gval(n)));\n  if (iscollectable(gkey(n)))\n    setttype(gkey(n), LUA_TDEADKEY);  /* dead key; remove it */\n}\n\n\nstatic void reallymarkobject (global_State *g, GCObject *o) {\n  lua_assert(iswhite(o) && !isdead(g, o));\n  white2gray(o);\n  switch (o->gch.tt) {\n    case LUA_TSTRING: {\n      return;\n    }\n    case LUA_TUSERDATA: {\n      Table *mt = gco2u(o)->metatable;\n      gray2black(o);  /* udata are never gray */\n      if (mt) markobject(g, mt);\n      markobject(g, gco2u(o)->env);\n      return;\n    }\n    case LUA_TUPVAL: {\n      UpVal *uv = gco2uv(o);\n      markvalue(g, uv->v);\n      if (uv->v == &uv->u.value)  /* closed? */\n        gray2black(o);  /* open upvalues are never black */\n      return;\n    }\n    case LUA_TFUNCTION: {\n      gco2cl(o)->c.gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    case LUA_TTABLE: {\n      gco2h(o)->gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    case LUA_TTHREAD: {\n      gco2th(o)->gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    case LUA_TPROTO: {\n      gco2p(o)->gclist = g->gray;\n      g->gray = o;\n      break;\n    }\n    default: lua_assert(0);\n  }\n}\n\n\nstatic void marktmu (global_State *g) {\n  GCObject *u = g->tmudata;\n  if (u) {\n    do {\n      u = u->gch.next;\n      makewhite(g, u);  /* may be marked, if left from previous GC */\n      reallymarkobject(g, u);\n    } while (u != g->tmudata);\n  }\n}\n\n\n/* move `dead' udata that need finalization to list `tmudata' */\nsize_t luaC_separateudata (lua_State *L, int all) {\n  global_State *g = G(L);\n  size_t deadmem = 0;\n  GCObject **p = &g->mainthread->next;\n  GCObject *curr;\n  while ((curr = *p) != NULL) {\n    if (!(iswhite(curr) || all) || isfinalized(gco2u(curr)))\n      p = &curr->gch.next;  /* don't bother with them */\n    else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) {\n      markfinalized(gco2u(curr));  /* don't need finalization */\n      p = &curr->gch.next;\n    }\n    else {  /* must call its gc method */\n      deadmem += sizeudata(gco2u(curr));\n      markfinalized(gco2u(curr));\n      *p = curr->gch.next;\n      /* link `curr' at the end of `tmudata' list */\n      if (g->tmudata == NULL)  /* list is empty? */\n        g->tmudata = curr->gch.next = curr;  /* creates a circular list */\n      else {\n        curr->gch.next = g->tmudata->gch.next;\n        g->tmudata->gch.next = curr;\n        g->tmudata = curr;\n      }\n    }\n  }\n  return deadmem;\n}\n\n\nstatic int traversetable (global_State *g, Table *h) {\n  int i;\n  int weakkey = 0;\n  int weakvalue = 0;\n  const TValue *mode;\n  if (h->metatable)\n    markobject(g, h->metatable);\n  mode = gfasttm(g, h->metatable, TM_MODE);\n  if (mode && ttisstring(mode)) {  /* is there a weak mode? */\n    weakkey = (strchr(svalue(mode), 'k') != NULL);\n    weakvalue = (strchr(svalue(mode), 'v') != NULL);\n    if (weakkey || weakvalue) {  /* is really weak? */\n      h->marked &= ~(KEYWEAK | VALUEWEAK);  /* clear bits */\n      h->marked |= cast_byte((weakkey << KEYWEAKBIT) |\n                             (weakvalue << VALUEWEAKBIT));\n      h->gclist = g->weak;  /* must be cleared after GC, ... */\n      g->weak = obj2gco(h);  /* ... so put in the appropriate list */\n    }\n  }\n  if (weakkey && weakvalue) return 1;\n  if (!weakvalue) {\n    i = h->sizearray;\n    while (i--)\n      markvalue(g, &h->array[i]);\n  }\n  i = sizenode(h);\n  while (i--) {\n    Node *n = gnode(h, i);\n    lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n)));\n    if (ttisnil(gval(n)))\n      removeentry(n);  /* remove empty entries */\n    else {\n      lua_assert(!ttisnil(gkey(n)));\n      if (!weakkey) markvalue(g, gkey(n));\n      if (!weakvalue) markvalue(g, gval(n));\n    }\n  }\n  return weakkey || weakvalue;\n}\n\n\n/*\n** All marks are conditional because a GC may happen while the\n** prototype is still being created\n*/\nstatic void traverseproto (global_State *g, Proto *f) {\n  int i;\n  if (f->source) stringmark(f->source);\n  for (i=0; i<f->sizek; i++)  /* mark literals */\n    markvalue(g, &f->k[i]);\n  for (i=0; i<f->sizeupvalues; i++) {  /* mark upvalue names */\n    if (f->upvalues[i])\n      stringmark(f->upvalues[i]);\n  }\n  for (i=0; i<f->sizep; i++) {  /* mark nested protos */\n    if (f->p[i])\n      markobject(g, f->p[i]);\n  }\n  for (i=0; i<f->sizelocvars; i++) {  /* mark local-variable names */\n    if (f->locvars[i].varname)\n      stringmark(f->locvars[i].varname);\n  }\n}\n\n\n\nstatic void traverseclosure (global_State *g, Closure *cl) {\n  markobject(g, cl->c.env);\n  if (cl->c.isC) {\n    int i;\n    for (i=0; i<cl->c.nupvalues; i++)  /* mark its upvalues */\n      markvalue(g, &cl->c.upvalue[i]);\n  }\n  else {\n    int i;\n    lua_assert(cl->l.nupvalues == cl->l.p->nups);\n    markobject(g, cl->l.p);\n    for (i=0; i<cl->l.nupvalues; i++)  /* mark its upvalues */\n      markobject(g, cl->l.upvals[i]);\n  }\n}\n\n\nstatic void checkstacksizes (lua_State *L, StkId max) {\n  int ci_used = cast_int(L->ci - L->base_ci);  /* number of `ci' in use */\n  int s_used = cast_int(max - L->stack);  /* part of stack in use */\n  if (L->size_ci > LUAI_MAXCALLS)  /* handling overflow? */\n    return;  /* do not touch the stacks */\n  if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci)\n    luaD_reallocCI(L, L->size_ci/2);  /* still big enough... */\n  condhardstacktests(luaD_reallocCI(L, ci_used + 1));\n  if (4*s_used < L->stacksize &&\n      2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize)\n    luaD_reallocstack(L, L->stacksize/2);  /* still big enough... */\n  condhardstacktests(luaD_reallocstack(L, s_used));\n}\n\n\nstatic void traversestack (global_State *g, lua_State *l) {\n  StkId o, lim;\n  CallInfo *ci;\n  markvalue(g, gt(l));\n  lim = l->top;\n  for (ci = l->base_ci; ci <= l->ci; ci++) {\n    lua_assert(ci->top <= l->stack_last);\n    if (lim < ci->top) lim = ci->top;\n  }\n  for (o = l->stack; o < l->top; o++)\n    markvalue(g, o);\n  for (; o <= lim; o++)\n    setnilvalue(o);\n  checkstacksizes(l, lim);\n}\n\n\n/*\n** traverse one gray object, turning it to black.\n** Returns `quantity' traversed.\n*/\nstatic l_mem propagatemark (global_State *g) {\n  GCObject *o = g->gray;\n  lua_assert(isgray(o));\n  gray2black(o);\n  switch (o->gch.tt) {\n    case LUA_TTABLE: {\n      Table *h = gco2h(o);\n      g->gray = h->gclist;\n      if (traversetable(g, h))  /* table is weak? */\n        black2gray(o);  /* keep it gray */\n      return sizeof(Table) + sizeof(TValue) * h->sizearray +\n                             sizeof(Node) * (size_t)sizenode(h);\n    }\n    case LUA_TFUNCTION: {\n      Closure *cl = gco2cl(o);\n      g->gray = cl->c.gclist;\n      traverseclosure(g, cl);\n      return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) :\n                           sizeLclosure(cl->l.nupvalues);\n    }\n    case LUA_TTHREAD: {\n      lua_State *th = gco2th(o);\n      g->gray = th->gclist;\n      th->gclist = g->grayagain;\n      g->grayagain = o;\n      black2gray(o);\n      traversestack(g, th);\n      return sizeof(lua_State) + sizeof(TValue) * th->stacksize +\n                                 sizeof(CallInfo) * th->size_ci;\n    }\n    case LUA_TPROTO: {\n      Proto *p = gco2p(o);\n      g->gray = p->gclist;\n      traverseproto(g, p);\n      return sizeof(Proto) + sizeof(Instruction) * p->sizecode +\n                             sizeof(Proto *) * p->sizep +\n                             sizeof(TValue) * p->sizek + \n                             sizeof(int) * p->sizelineinfo +\n                             sizeof(LocVar) * p->sizelocvars +\n                             sizeof(TString *) * p->sizeupvalues;\n    }\n    default: lua_assert(0); return 0;\n  }\n}\n\n\nstatic size_t propagateall (global_State *g) {\n  size_t m = 0;\n  while (g->gray) m += propagatemark(g);\n  return m;\n}\n\n\n/*\n** The next function tells whether a key or value can be cleared from\n** a weak table. Non-collectable objects are never removed from weak\n** tables. Strings behave as `values', so are never removed too. for\n** other objects: if really collected, cannot keep them; for userdata\n** being finalized, keep them in keys, but not in values\n*/\nstatic int iscleared (const TValue *o, int iskey) {\n  if (!iscollectable(o)) return 0;\n  if (ttisstring(o)) {\n    stringmark(rawtsvalue(o));  /* strings are `values', so are never weak */\n    return 0;\n  }\n  return iswhite(gcvalue(o)) ||\n    (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o))));\n}\n\n\n/*\n** clear collected entries from weaktables\n*/\nstatic void cleartable (GCObject *l) {\n  while (l) {\n    Table *h = gco2h(l);\n    int i = h->sizearray;\n    lua_assert(testbit(h->marked, VALUEWEAKBIT) ||\n               testbit(h->marked, KEYWEAKBIT));\n    if (testbit(h->marked, VALUEWEAKBIT)) {\n      while (i--) {\n        TValue *o = &h->array[i];\n        if (iscleared(o, 0))  /* value was collected? */\n          setnilvalue(o);  /* remove value */\n      }\n    }\n    i = sizenode(h);\n    while (i--) {\n      Node *n = gnode(h, i);\n      if (!ttisnil(gval(n)) &&  /* non-empty entry? */\n          (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) {\n        setnilvalue(gval(n));  /* remove value ... */\n        removeentry(n);  /* remove entry from table */\n      }\n    }\n    l = h->gclist;\n  }\n}\n\n\nstatic void freeobj (lua_State *L, GCObject *o) {\n  switch (o->gch.tt) {\n    case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break;\n    case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break;\n    case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break;\n    case LUA_TTABLE: luaH_free(L, gco2h(o)); break;\n    case LUA_TTHREAD: {\n      lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread);\n      luaE_freethread(L, gco2th(o));\n      break;\n    }\n    case LUA_TSTRING: {\n      G(L)->strt.nuse--;\n      luaM_freemem(L, o, sizestring(gco2ts(o)));\n      break;\n    }\n    case LUA_TUSERDATA: {\n      luaM_freemem(L, o, sizeudata(gco2u(o)));\n      break;\n    }\n    default: lua_assert(0);\n  }\n}\n\n\n\n#define sweepwholelist(L,p)\tsweeplist(L,p,MAX_LUMEM)\n\n\nstatic GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) {\n  GCObject *curr;\n  global_State *g = G(L);\n  int deadmask = otherwhite(g);\n  while ((curr = *p) != NULL && count-- > 0) {\n    if (curr->gch.tt == LUA_TTHREAD)  /* sweep open upvalues of each thread */\n      sweepwholelist(L, &gco2th(curr)->openupval);\n    if ((curr->gch.marked ^ WHITEBITS) & deadmask) {  /* not dead? */\n      lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT));\n      makewhite(g, curr);  /* make it white (for next cycle) */\n      p = &curr->gch.next;\n    }\n    else {  /* must erase `curr' */\n      lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT));\n      *p = curr->gch.next;\n      if (curr == g->rootgc)  /* is the first element of the list? */\n        g->rootgc = curr->gch.next;  /* adjust first */\n      freeobj(L, curr);\n    }\n  }\n  return p;\n}\n\n\nstatic void checkSizes (lua_State *L) {\n  global_State *g = G(L);\n  /* check size of string hash */\n  if (g->strt.nuse < cast(lu_int32, g->strt.size/4) &&\n      g->strt.size > MINSTRTABSIZE*2)\n    luaS_resize(L, g->strt.size/2);  /* table is too big */\n  /* check size of buffer */\n  if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) {  /* buffer too big? */\n    size_t newsize = luaZ_sizebuffer(&g->buff) / 2;\n    luaZ_resizebuffer(L, &g->buff, newsize);\n  }\n}\n\n\nstatic void GCTM (lua_State *L) {\n  global_State *g = G(L);\n  GCObject *o = g->tmudata->gch.next;  /* get first element */\n  Udata *udata = rawgco2u(o);\n  const TValue *tm;\n  /* remove udata from `tmudata' */\n  if (o == g->tmudata)  /* last element? */\n    g->tmudata = NULL;\n  else\n    g->tmudata->gch.next = udata->uv.next;\n  udata->uv.next = g->mainthread->next;  /* return it to `root' list */\n  g->mainthread->next = o;\n  makewhite(g, o);\n  tm = fasttm(L, udata->uv.metatable, TM_GC);\n  if (tm != NULL) {\n    lu_byte oldah = L->allowhook;\n    lu_mem oldt = g->GCthreshold;\n    L->allowhook = 0;  /* stop debug hooks during GC tag method */\n    g->GCthreshold = 2*g->totalbytes;  /* avoid GC steps */\n    setobj2s(L, L->top, tm);\n    setuvalue(L, L->top+1, udata);\n    L->top += 2;\n    luaD_call(L, L->top - 2, 0);\n    L->allowhook = oldah;  /* restore hooks */\n    g->GCthreshold = oldt;  /* restore threshold */\n  }\n}\n\n\n/*\n** Call all GC tag methods\n*/\nvoid luaC_callGCTM (lua_State *L) {\n  while (G(L)->tmudata)\n    GCTM(L);\n}\n\n\nvoid luaC_freeall (lua_State *L) {\n  global_State *g = G(L);\n  int i;\n  g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT);  /* mask to collect all elements */\n  sweepwholelist(L, &g->rootgc);\n  for (i = 0; i < g->strt.size; i++)  /* free all string lists */\n    sweepwholelist(L, &g->strt.hash[i]);\n}\n\n\nstatic void markmt (global_State *g) {\n  int i;\n  for (i=0; i<NUM_TAGS; i++)\n    if (g->mt[i]) markobject(g, g->mt[i]);\n}\n\n\n/* mark root set */\nstatic void markroot (lua_State *L) {\n  global_State *g = G(L);\n  g->gray = NULL;\n  g->grayagain = NULL;\n  g->weak = NULL;\n  markobject(g, g->mainthread);\n  /* make global table be traversed before main stack */\n  markvalue(g, gt(g->mainthread));\n  markvalue(g, registry(L));\n  markmt(g);\n  g->gcstate = GCSpropagate;\n}\n\n\nstatic void remarkupvals (global_State *g) {\n  UpVal *uv;\n  for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) {\n    lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv);\n    if (isgray(obj2gco(uv)))\n      markvalue(g, uv->v);\n  }\n}\n\n\nstatic void atomic (lua_State *L) {\n  global_State *g = G(L);\n  size_t udsize;  /* total size of userdata to be finalized */\n  /* remark occasional upvalues of (maybe) dead threads */\n  remarkupvals(g);\n  /* traverse objects cautch by write barrier and by 'remarkupvals' */\n  propagateall(g);\n  /* remark weak tables */\n  g->gray = g->weak;\n  g->weak = NULL;\n  lua_assert(!iswhite(obj2gco(g->mainthread)));\n  markobject(g, L);  /* mark running thread */\n  markmt(g);  /* mark basic metatables (again) */\n  propagateall(g);\n  /* remark gray again */\n  g->gray = g->grayagain;\n  g->grayagain = NULL;\n  propagateall(g);\n  udsize = luaC_separateudata(L, 0);  /* separate userdata to be finalized */\n  marktmu(g);  /* mark `preserved' userdata */\n  udsize += propagateall(g);  /* remark, to propagate `preserveness' */\n  cleartable(g->weak);  /* remove collected objects from weak tables */\n  /* flip current white */\n  g->currentwhite = cast_byte(otherwhite(g));\n  g->sweepstrgc = 0;\n  g->sweepgc = &g->rootgc;\n  g->gcstate = GCSsweepstring;\n  g->estimate = g->totalbytes - udsize;  /* first estimate */\n}\n\n\nstatic l_mem singlestep (lua_State *L) {\n  global_State *g = G(L);\n  /*lua_checkmemory(L);*/\n  switch (g->gcstate) {\n    case GCSpause: {\n      markroot(L);  /* start a new collection */\n      return 0;\n    }\n    case GCSpropagate: {\n      if (g->gray)\n        return propagatemark(g);\n      else {  /* no more `gray' objects */\n        atomic(L);  /* finish mark phase */\n        return 0;\n      }\n    }\n    case GCSsweepstring: {\n      lu_mem old = g->totalbytes;\n      sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]);\n      if (g->sweepstrgc >= g->strt.size)  /* nothing more to sweep? */\n        g->gcstate = GCSsweep;  /* end sweep-string phase */\n      lua_assert(old >= g->totalbytes);\n      g->estimate -= old - g->totalbytes;\n      return GCSWEEPCOST;\n    }\n    case GCSsweep: {\n      lu_mem old = g->totalbytes;\n      g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX);\n      if (*g->sweepgc == NULL) {  /* nothing more to sweep? */\n        checkSizes(L);\n        g->gcstate = GCSfinalize;  /* end sweep phase */\n      }\n      lua_assert(old >= g->totalbytes);\n      g->estimate -= old - g->totalbytes;\n      return GCSWEEPMAX*GCSWEEPCOST;\n    }\n    case GCSfinalize: {\n      if (g->tmudata) {\n        GCTM(L);\n        if (g->estimate > GCFINALIZECOST)\n          g->estimate -= GCFINALIZECOST;\n        return GCFINALIZECOST;\n      }\n      else {\n        g->gcstate = GCSpause;  /* end collection */\n        g->gcdept = 0;\n        return 0;\n      }\n    }\n    default: lua_assert(0); return 0;\n  }\n}\n\n\nvoid luaC_step (lua_State *L) {\n  global_State *g = G(L);\n  l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul;\n  if (lim == 0)\n    lim = (MAX_LUMEM-1)/2;  /* no limit */\n  g->gcdept += g->totalbytes - g->GCthreshold;\n  do {\n    lim -= singlestep(L);\n    if (g->gcstate == GCSpause)\n      break;\n  } while (lim > 0);\n  if (g->gcstate != GCSpause) {\n    if (g->gcdept < GCSTEPSIZE)\n      g->GCthreshold = g->totalbytes + GCSTEPSIZE;  /* - lim/g->gcstepmul;*/\n    else {\n      g->gcdept -= GCSTEPSIZE;\n      g->GCthreshold = g->totalbytes;\n    }\n  }\n  else {\n    setthreshold(g);\n  }\n}\n\n\nvoid luaC_fullgc (lua_State *L) {\n  global_State *g = G(L);\n  if (g->gcstate <= GCSpropagate) {\n    /* reset sweep marks to sweep all elements (returning them to white) */\n    g->sweepstrgc = 0;\n    g->sweepgc = &g->rootgc;\n    /* reset other collector lists */\n    g->gray = NULL;\n    g->grayagain = NULL;\n    g->weak = NULL;\n    g->gcstate = GCSsweepstring;\n  }\n  lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate);\n  /* finish any pending sweep phase */\n  while (g->gcstate != GCSfinalize) {\n    lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep);\n    singlestep(L);\n  }\n  markroot(L);\n  while (g->gcstate != GCSpause) {\n    singlestep(L);\n  }\n  setthreshold(g);\n}\n\n\nvoid luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) {\n  global_State *g = G(L);\n  lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));\n  lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);\n  lua_assert(ttype(&o->gch) != LUA_TTABLE);\n  /* must keep invariant? */\n  if (g->gcstate == GCSpropagate)\n    reallymarkobject(g, v);  /* restore invariant */\n  else  /* don't mind */\n    makewhite(g, o);  /* mark as white just to avoid other barriers */\n}\n\n\nvoid luaC_barrierback (lua_State *L, Table *t) {\n  global_State *g = G(L);\n  GCObject *o = obj2gco(t);\n  lua_assert(isblack(o) && !isdead(g, o));\n  lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);\n  black2gray(o);  /* make table gray (again) */\n  t->gclist = g->grayagain;\n  g->grayagain = o;\n}\n\n\nvoid luaC_link (lua_State *L, GCObject *o, lu_byte tt) {\n  global_State *g = G(L);\n  o->gch.next = g->rootgc;\n  g->rootgc = o;\n  o->gch.marked = luaC_white(g);\n  o->gch.tt = tt;\n}\n\n\nvoid luaC_linkupval (lua_State *L, UpVal *uv) {\n  global_State *g = G(L);\n  GCObject *o = obj2gco(uv);\n  o->gch.next = g->rootgc;  /* link upvalue into `rootgc' list */\n  g->rootgc = o;\n  if (isgray(o)) { \n    if (g->gcstate == GCSpropagate) {\n      gray2black(o);  /* closed upvalues need barrier */\n      luaC_barrier(L, uv, uv->v);\n    }\n    else {  /* sweep phase: sweep it (turning it into white) */\n      makewhite(g, o);\n      lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause);\n    }\n  }\n}\n\n"
  },
  {
    "path": "src/lua/lgc.h",
    "content": "/*\n** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $\n** Garbage Collector\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lgc_h\n#define lgc_h\n\n\n#include \"lobject.h\"\n\n\n/*\n** Possible states of the Garbage Collector\n*/\n#define GCSpause\t0\n#define GCSpropagate\t1\n#define GCSsweepstring\t2\n#define GCSsweep\t3\n#define GCSfinalize\t4\n\n\n/*\n** some userful bit tricks\n*/\n#define resetbits(x,m)\t((x) &= cast(lu_byte, ~(m)))\n#define setbits(x,m)\t((x) |= (m))\n#define testbits(x,m)\t((x) & (m))\n#define bitmask(b)\t(1<<(b))\n#define bit2mask(b1,b2)\t(bitmask(b1) | bitmask(b2))\n#define l_setbit(x,b)\tsetbits(x, bitmask(b))\n#define resetbit(x,b)\tresetbits(x, bitmask(b))\n#define testbit(x,b)\ttestbits(x, bitmask(b))\n#define set2bits(x,b1,b2)\tsetbits(x, (bit2mask(b1, b2)))\n#define reset2bits(x,b1,b2)\tresetbits(x, (bit2mask(b1, b2)))\n#define test2bits(x,b1,b2)\ttestbits(x, (bit2mask(b1, b2)))\n\n\n\n/*\n** Layout for bit use in `marked' field:\n** bit 0 - object is white (type 0)\n** bit 1 - object is white (type 1)\n** bit 2 - object is black\n** bit 3 - for userdata: has been finalized\n** bit 3 - for tables: has weak keys\n** bit 4 - for tables: has weak values\n** bit 5 - object is fixed (should not be collected)\n** bit 6 - object is \"super\" fixed (only the main thread)\n*/\n\n\n#define WHITE0BIT\t0\n#define WHITE1BIT\t1\n#define BLACKBIT\t2\n#define FINALIZEDBIT\t3\n#define KEYWEAKBIT\t3\n#define VALUEWEAKBIT\t4\n#define FIXEDBIT\t5\n#define SFIXEDBIT\t6\n#define WHITEBITS\tbit2mask(WHITE0BIT, WHITE1BIT)\n\n\n#define iswhite(x)      test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT)\n#define isblack(x)      testbit((x)->gch.marked, BLACKBIT)\n#define isgray(x)\t(!isblack(x) && !iswhite(x))\n\n#define otherwhite(g)\t(g->currentwhite ^ WHITEBITS)\n#define isdead(g,v)\t((v)->gch.marked & otherwhite(g) & WHITEBITS)\n\n#define changewhite(x)\t((x)->gch.marked ^= WHITEBITS)\n#define gray2black(x)\tl_setbit((x)->gch.marked, BLACKBIT)\n\n#define valiswhite(x)\t(iscollectable(x) && iswhite(gcvalue(x)))\n\n#define luaC_white(g)\tcast(lu_byte, (g)->currentwhite & WHITEBITS)\n\n\n#define luaC_checkGC(L) { \\\n  condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \\\n  if (G(L)->totalbytes >= G(L)->GCthreshold) \\\n\tluaC_step(L); }\n\n\n#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p)))  \\\n\tluaC_barrierf(L,obj2gco(p),gcvalue(v)); }\n\n#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t)))  \\\n\tluaC_barrierback(L,t); }\n\n#define luaC_objbarrier(L,p,o)  \\\n\t{ if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \\\n\t\tluaC_barrierf(L,obj2gco(p),obj2gco(o)); }\n\n#define luaC_objbarriert(L,t,o)  \\\n   { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); }\n\nLUAI_FUNC size_t luaC_separateudata (lua_State *L, int all);\nLUAI_FUNC void luaC_callGCTM (lua_State *L);\nLUAI_FUNC void luaC_freeall (lua_State *L);\nLUAI_FUNC void luaC_step (lua_State *L);\nLUAI_FUNC void luaC_fullgc (lua_State *L);\nLUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt);\nLUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv);\nLUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v);\nLUAI_FUNC void luaC_barrierback (lua_State *L, Table *t);\n\n\n#endif\n"
  },
  {
    "path": "src/lua/linit.c",
    "content": "/*\n** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $\n** Initialization of libraries for lua.c\n** See Copyright Notice in lua.h\n*/\n\n\n#define linit_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lualib.h\"\n#include \"lauxlib.h\"\n\n\nstatic const luaL_Reg lualibs[] = {\n  {\"\", luaopen_base},\n  {LUA_LOADLIBNAME, luaopen_package},\n  {LUA_TABLIBNAME, luaopen_table},\n  {LUA_IOLIBNAME, luaopen_io},\n  {LUA_OSLIBNAME, luaopen_os},\n  {LUA_STRLIBNAME, luaopen_string},\n  {LUA_MATHLIBNAME, luaopen_math},\n  {LUA_DBLIBNAME, luaopen_debug},\n  {NULL, NULL}\n};\n\n\nLUALIB_API void luaL_openlibs (lua_State *L) {\n  const luaL_Reg *lib = lualibs;\n  for (; lib->func; lib++) {\n    lua_pushcfunction(L, lib->func);\n    lua_pushstring(L, lib->name);\n    lua_call(L, 1, 0);\n  }\n}\n\n"
  },
  {
    "path": "src/lua/liolib.c",
    "content": "/*\n** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $\n** Standard I/O (and system) library\n** See Copyright Notice in lua.h\n*/\n\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define liolib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n\n#define IO_INPUT\t1\n#define IO_OUTPUT\t2\n\n\nstatic const char *const fnames[] = {\"input\", \"output\"};\n\n\nstatic int pushresult (lua_State *L, int i, const char *filename) {\n  int en = errno;  /* calls to Lua API may change this value */\n  if (i) {\n    lua_pushboolean(L, 1);\n    return 1;\n  }\n  else {\n    lua_pushnil(L);\n    if (filename)\n      lua_pushfstring(L, \"%s: %s\", filename, strerror(en));\n    else\n      lua_pushfstring(L, \"%s\", strerror(en));\n    lua_pushinteger(L, en);\n    return 3;\n  }\n}\n\n\nstatic void fileerror (lua_State *L, int arg, const char *filename) {\n  lua_pushfstring(L, \"%s: %s\", filename, strerror(errno));\n  luaL_argerror(L, arg, lua_tostring(L, -1));\n}\n\n\n#define tofilep(L)\t((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))\n\n\nstatic int io_type (lua_State *L) {\n  void *ud;\n  luaL_checkany(L, 1);\n  ud = lua_touserdata(L, 1);\n  lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);\n  if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))\n    lua_pushnil(L);  /* not a file */\n  else if (*((FILE **)ud) == NULL)\n    lua_pushliteral(L, \"closed file\");\n  else\n    lua_pushliteral(L, \"file\");\n  return 1;\n}\n\n\nstatic FILE *tofile (lua_State *L) {\n  FILE **f = tofilep(L);\n  if (*f == NULL)\n    luaL_error(L, \"attempt to use a closed file\");\n  return *f;\n}\n\n\n\n/*\n** When creating file handles, always creates a `closed' file handle\n** before opening the actual file; so, if there is a memory error, the\n** file is not left opened.\n*/\nstatic FILE **newfile (lua_State *L) {\n  FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));\n  *pf = NULL;  /* file handle is currently `closed' */\n  luaL_getmetatable(L, LUA_FILEHANDLE);\n  lua_setmetatable(L, -2);\n  return pf;\n}\n\n\n/*\n** function to (not) close the standard files stdin, stdout, and stderr\n*/\nstatic int io_noclose (lua_State *L) {\n  lua_pushnil(L);\n  lua_pushliteral(L, \"cannot close standard file\");\n  return 2;\n}\n\n\n/*\n** function to close 'popen' files\n*/\nstatic int io_pclose (lua_State *L) {\n  FILE **p = tofilep(L);\n  int ok = lua_pclose(L, *p);\n  *p = NULL;\n  return pushresult(L, ok, NULL);\n}\n\n\n/*\n** function to close regular files\n*/\nstatic int io_fclose (lua_State *L) {\n  FILE **p = tofilep(L);\n  int ok = (fclose(*p) == 0);\n  *p = NULL;\n  return pushresult(L, ok, NULL);\n}\n\n\nstatic int aux_close (lua_State *L) {\n  lua_getfenv(L, 1);\n  lua_getfield(L, -1, \"__close\");\n  return (lua_tocfunction(L, -1))(L);\n}\n\n\nstatic int io_close (lua_State *L) {\n  if (lua_isnone(L, 1))\n    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);\n  tofile(L);  /* make sure argument is a file */\n  return aux_close(L);\n}\n\n\nstatic int io_gc (lua_State *L) {\n  FILE *f = *tofilep(L);\n  /* ignore closed files */\n  if (f != NULL)\n    aux_close(L);\n  return 0;\n}\n\n\nstatic int io_tostring (lua_State *L) {\n  FILE *f = *tofilep(L);\n  if (f == NULL)\n    lua_pushliteral(L, \"file (closed)\");\n  else\n    lua_pushfstring(L, \"file (%p)\", f);\n  return 1;\n}\n\n\nstatic int io_open (lua_State *L) {\n  const char *filename = luaL_checkstring(L, 1);\n  const char *mode = luaL_optstring(L, 2, \"r\");\n  FILE **pf = newfile(L);\n  *pf = fopen(filename, mode);\n  return (*pf == NULL) ? pushresult(L, 0, filename) : 1;\n}\n\n\n/*\n** this function has a separated environment, which defines the\n** correct __close for 'popen' files\n*/\nstatic int io_popen (lua_State *L) {\n  const char *filename = luaL_checkstring(L, 1);\n  const char *mode = luaL_optstring(L, 2, \"r\");\n  FILE **pf = newfile(L);\n  *pf = lua_popen(L, filename, mode);\n  return (*pf == NULL) ? pushresult(L, 0, filename) : 1;\n}\n\n\nstatic int io_tmpfile (lua_State *L) {\n  FILE **pf = newfile(L);\n  *pf = tmpfile();\n  return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;\n}\n\n\nstatic FILE *getiofile (lua_State *L, int findex) {\n  FILE *f;\n  lua_rawgeti(L, LUA_ENVIRONINDEX, findex);\n  f = *(FILE **)lua_touserdata(L, -1);\n  if (f == NULL)\n    luaL_error(L, \"standard %s file is closed\", fnames[findex - 1]);\n  return f;\n}\n\n\nstatic int g_iofile (lua_State *L, int f, const char *mode) {\n  if (!lua_isnoneornil(L, 1)) {\n    const char *filename = lua_tostring(L, 1);\n    if (filename) {\n      FILE **pf = newfile(L);\n      *pf = fopen(filename, mode);\n      if (*pf == NULL)\n        fileerror(L, 1, filename);\n    }\n    else {\n      tofile(L);  /* check that it's a valid file handle */\n      lua_pushvalue(L, 1);\n    }\n    lua_rawseti(L, LUA_ENVIRONINDEX, f);\n  }\n  /* return current value */\n  lua_rawgeti(L, LUA_ENVIRONINDEX, f);\n  return 1;\n}\n\n\nstatic int io_input (lua_State *L) {\n  return g_iofile(L, IO_INPUT, \"r\");\n}\n\n\nstatic int io_output (lua_State *L) {\n  return g_iofile(L, IO_OUTPUT, \"w\");\n}\n\n\nstatic int io_readline (lua_State *L);\n\n\nstatic void aux_lines (lua_State *L, int idx, int toclose) {\n  lua_pushvalue(L, idx);\n  lua_pushboolean(L, toclose);  /* close/not close file when finished */\n  lua_pushcclosure(L, io_readline, 2);\n}\n\n\nstatic int f_lines (lua_State *L) {\n  tofile(L);  /* check that it's a valid file handle */\n  aux_lines(L, 1, 0);\n  return 1;\n}\n\n\nstatic int io_lines (lua_State *L) {\n  if (lua_isnoneornil(L, 1)) {  /* no arguments? */\n    /* will iterate over default input */\n    lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);\n    return f_lines(L);\n  }\n  else {\n    const char *filename = luaL_checkstring(L, 1);\n    FILE **pf = newfile(L);\n    *pf = fopen(filename, \"r\");\n    if (*pf == NULL)\n      fileerror(L, 1, filename);\n    aux_lines(L, lua_gettop(L), 1);\n    return 1;\n  }\n}\n\n\n/*\n** {======================================================\n** READ\n** =======================================================\n*/\n\n\nstatic int read_number (lua_State *L, FILE *f) {\n  lua_Number d;\n  if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {\n    lua_pushnumber(L, d);\n    return 1;\n  }\n  else {\n    lua_pushnil(L);  /* \"result\" to be removed */\n    return 0;  /* read fails */\n  }\n}\n\n\nstatic int test_eof (lua_State *L, FILE *f) {\n  int c = getc(f);\n  ungetc(c, f);\n  lua_pushlstring(L, NULL, 0);\n  return (c != EOF);\n}\n\n\nstatic int read_line (lua_State *L, FILE *f) {\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  for (;;) {\n    size_t l;\n    char *p = luaL_prepbuffer(&b);\n    if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {  /* eof? */\n      luaL_pushresult(&b);  /* close buffer */\n      return (lua_objlen(L, -1) > 0);  /* check whether read something */\n    }\n    l = strlen(p);\n    if (l == 0 || p[l-1] != '\\n')\n      luaL_addsize(&b, l);\n    else {\n      luaL_addsize(&b, l - 1);  /* do not include `eol' */\n      luaL_pushresult(&b);  /* close buffer */\n      return 1;  /* read at least an `eol' */\n    }\n  }\n}\n\n\nstatic int read_chars (lua_State *L, FILE *f, size_t n) {\n  size_t rlen;  /* how much to read */\n  size_t nr;  /* number of chars actually read */\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  rlen = LUAL_BUFFERSIZE;  /* try to read that much each time */\n  do {\n    char *p = luaL_prepbuffer(&b);\n    if (rlen > n) rlen = n;  /* cannot read more than asked */\n    nr = fread(p, sizeof(char), rlen, f);\n    luaL_addsize(&b, nr);\n    n -= nr;  /* still have to read `n' chars */\n  } while (n > 0 && nr == rlen);  /* until end of count or eof */\n  luaL_pushresult(&b);  /* close buffer */\n  return (n == 0 || lua_objlen(L, -1) > 0);\n}\n\n\nstatic int g_read (lua_State *L, FILE *f, int first) {\n  int nargs = lua_gettop(L) - 1;\n  int success;\n  int n;\n  clearerr(f);\n  if (nargs == 0) {  /* no arguments? */\n    success = read_line(L, f);\n    n = first+1;  /* to return 1 result */\n  }\n  else {  /* ensure stack space for all results and for auxlib's buffer */\n    luaL_checkstack(L, nargs+LUA_MINSTACK, \"too many arguments\");\n    success = 1;\n    for (n = first; nargs-- && success; n++) {\n      if (lua_type(L, n) == LUA_TNUMBER) {\n        size_t l = (size_t)lua_tointeger(L, n);\n        success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);\n      }\n      else {\n        const char *p = lua_tostring(L, n);\n        luaL_argcheck(L, p && p[0] == '*', n, \"invalid option\");\n        switch (p[1]) {\n          case 'n':  /* number */\n            success = read_number(L, f);\n            break;\n          case 'l':  /* line */\n            success = read_line(L, f);\n            break;\n          case 'a':  /* file */\n            read_chars(L, f, ~((size_t)0));  /* read MAX_SIZE_T chars */\n            success = 1; /* always success */\n            break;\n          default:\n            return luaL_argerror(L, n, \"invalid format\");\n        }\n      }\n    }\n  }\n  if (ferror(f))\n    return pushresult(L, 0, NULL);\n  if (!success) {\n    lua_pop(L, 1);  /* remove last result */\n    lua_pushnil(L);  /* push nil instead */\n  }\n  return n - first;\n}\n\n\nstatic int io_read (lua_State *L) {\n  return g_read(L, getiofile(L, IO_INPUT), 1);\n}\n\n\nstatic int f_read (lua_State *L) {\n  return g_read(L, tofile(L), 2);\n}\n\n\nstatic int io_readline (lua_State *L) {\n  FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));\n  int sucess;\n  if (f == NULL)  /* file is already closed? */\n    luaL_error(L, \"file is already closed\");\n  sucess = read_line(L, f);\n  if (ferror(f))\n    return luaL_error(L, \"%s\", strerror(errno));\n  if (sucess) return 1;\n  else {  /* EOF */\n    if (lua_toboolean(L, lua_upvalueindex(2))) {  /* generator created file? */\n      lua_settop(L, 0);\n      lua_pushvalue(L, lua_upvalueindex(1));\n      aux_close(L);  /* close it */\n    }\n    return 0;\n  }\n}\n\n/* }====================================================== */\n\n\nstatic int g_write (lua_State *L, FILE *f, int arg) {\n  int nargs = lua_gettop(L) - 1;\n  int status = 1;\n  for (; nargs--; arg++) {\n    if (lua_type(L, arg) == LUA_TNUMBER) {\n      /* optimization: could be done exactly as for strings */\n      status = status &&\n          fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;\n    }\n    else {\n      size_t l;\n      const char *s = luaL_checklstring(L, arg, &l);\n      status = status && (fwrite(s, sizeof(char), l, f) == l);\n    }\n  }\n  return pushresult(L, status, NULL);\n}\n\n\nstatic int io_write (lua_State *L) {\n  return g_write(L, getiofile(L, IO_OUTPUT), 1);\n}\n\n\nstatic int f_write (lua_State *L) {\n  return g_write(L, tofile(L), 2);\n}\n\n\nstatic int f_seek (lua_State *L) {\n  static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};\n  static const char *const modenames[] = {\"set\", \"cur\", \"end\", NULL};\n  FILE *f = tofile(L);\n  int op = luaL_checkoption(L, 2, \"cur\", modenames);\n  long offset = luaL_optlong(L, 3, 0);\n  op = fseek(f, offset, mode[op]);\n  if (op)\n    return pushresult(L, 0, NULL);  /* error */\n  else {\n    lua_pushinteger(L, ftell(f));\n    return 1;\n  }\n}\n\n\nstatic int f_setvbuf (lua_State *L) {\n  static const int mode[] = {_IONBF, _IOFBF, _IOLBF};\n  static const char *const modenames[] = {\"no\", \"full\", \"line\", NULL};\n  FILE *f = tofile(L);\n  int op = luaL_checkoption(L, 2, NULL, modenames);\n  lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);\n  int res = setvbuf(f, NULL, mode[op], sz);\n  return pushresult(L, res == 0, NULL);\n}\n\n\n\nstatic int io_flush (lua_State *L) {\n  return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);\n}\n\n\nstatic int f_flush (lua_State *L) {\n  return pushresult(L, fflush(tofile(L)) == 0, NULL);\n}\n\n\nstatic const luaL_Reg iolib[] = {\n  {\"close\", io_close},\n  {\"flush\", io_flush},\n  {\"input\", io_input},\n  {\"lines\", io_lines},\n  {\"open\", io_open},\n  {\"output\", io_output},\n  {\"popen\", io_popen},\n  {\"read\", io_read},\n  {\"tmpfile\", io_tmpfile},\n  {\"type\", io_type},\n  {\"write\", io_write},\n  {NULL, NULL}\n};\n\n\nstatic const luaL_Reg flib[] = {\n  {\"close\", io_close},\n  {\"flush\", f_flush},\n  {\"lines\", f_lines},\n  {\"read\", f_read},\n  {\"seek\", f_seek},\n  {\"setvbuf\", f_setvbuf},\n  {\"write\", f_write},\n  {\"__gc\", io_gc},\n  {\"__tostring\", io_tostring},\n  {NULL, NULL}\n};\n\n\nstatic void createmeta (lua_State *L) {\n  luaL_newmetatable(L, LUA_FILEHANDLE);  /* create metatable for file handles */\n  lua_pushvalue(L, -1);  /* push metatable */\n  lua_setfield(L, -2, \"__index\");  /* metatable.__index = metatable */\n  luaL_register(L, NULL, flib);  /* file methods */\n}\n\n\nstatic void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {\n  *newfile(L) = f;\n  if (k > 0) {\n    lua_pushvalue(L, -1);\n    lua_rawseti(L, LUA_ENVIRONINDEX, k);\n  }\n  lua_pushvalue(L, -2);  /* copy environment */\n  lua_setfenv(L, -2);  /* set it */\n  lua_setfield(L, -3, fname);\n}\n\n\nstatic void newfenv (lua_State *L, lua_CFunction cls) {\n  lua_createtable(L, 0, 1);\n  lua_pushcfunction(L, cls);\n  lua_setfield(L, -2, \"__close\");\n}\n\n\nLUALIB_API int luaopen_io (lua_State *L) {\n  createmeta(L);\n  /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */\n  newfenv(L, io_fclose);\n  lua_replace(L, LUA_ENVIRONINDEX);\n  /* open library */\n  luaL_register(L, LUA_IOLIBNAME, iolib);\n  /* create (and set) default files */\n  newfenv(L, io_noclose);  /* close function for default files */\n  createstdfile(L, stdin, IO_INPUT, \"stdin\");\n  createstdfile(L, stdout, IO_OUTPUT, \"stdout\");\n  createstdfile(L, stderr, 0, \"stderr\");\n  lua_pop(L, 1);  /* pop environment for default files */\n  lua_getfield(L, -1, \"popen\");\n  newfenv(L, io_pclose);  /* create environment for 'popen' */\n  lua_setfenv(L, -2);  /* set fenv for 'popen' */\n  lua_pop(L, 1);  /* pop 'popen' */\n  return 1;\n}\n\n"
  },
  {
    "path": "src/lua/llex.c",
    "content": "/*\n** $Id: llex.c,v 2.20.1.2 2009/11/23 14:58:22 roberto Exp $\n** Lexical Analyzer\n** See Copyright Notice in lua.h\n*/\n\n\n#include <ctype.h>\n#include <locale.h>\n#include <string.h>\n\n#define llex_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldo.h\"\n#include \"llex.h\"\n#include \"lobject.h\"\n#include \"lparser.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"lzio.h\"\n\n\n\n#define next(ls) (ls->current = zgetc(ls->z))\n\n\n\n\n#define currIsNewline(ls)\t(ls->current == '\\n' || ls->current == '\\r')\n\n\n/* ORDER RESERVED */\nconst char *const luaX_tokens [] = {\n    \"and\", \"break\", \"do\", \"else\", \"elseif\",\n    \"end\", \"false\", \"for\", \"function\", \"if\",\n    \"in\", \"local\", \"nil\", \"not\", \"or\", \"repeat\",\n    \"return\", \"then\", \"true\", \"until\", \"while\",\n    \"..\", \"...\", \"==\", \">=\", \"<=\", \"~=\",\n    \"<number>\", \"<name>\", \"<string>\", \"<eof>\",\n    NULL\n};\n\n\n#define save_and_next(ls) (save(ls, ls->current), next(ls))\n\n\nstatic void save (LexState *ls, int c) {\n  Mbuffer *b = ls->buff;\n  if (b->n + 1 > b->buffsize) {\n    size_t newsize;\n    if (b->buffsize >= MAX_SIZET/2)\n      luaX_lexerror(ls, \"lexical element too long\", 0);\n    newsize = b->buffsize * 2;\n    luaZ_resizebuffer(ls->L, b, newsize);\n  }\n  b->buffer[b->n++] = cast(char, c);\n}\n\n\nvoid luaX_init (lua_State *L) {\n  int i;\n  for (i=0; i<NUM_RESERVED; i++) {\n    TString *ts = luaS_new(L, luaX_tokens[i]);\n    luaS_fix(ts);  /* reserved words are never collected */\n    lua_assert(strlen(luaX_tokens[i])+1 <= TOKEN_LEN);\n    ts->tsv.reserved = cast_byte(i+1);  /* reserved word */\n  }\n}\n\n\n#define MAXSRC          80\n\n\nconst char *luaX_token2str (LexState *ls, int token) {\n  if (token < FIRST_RESERVED) {\n    lua_assert(token == cast(unsigned char, token));\n    return (iscntrl(token)) ? luaO_pushfstring(ls->L, \"char(%d)\", token) :\n                              luaO_pushfstring(ls->L, \"%c\", token);\n  }\n  else\n    return luaX_tokens[token-FIRST_RESERVED];\n}\n\n\nstatic const char *txtToken (LexState *ls, int token) {\n  switch (token) {\n    case TK_NAME:\n    case TK_STRING:\n    case TK_NUMBER:\n      save(ls, '\\0');\n      return luaZ_buffer(ls->buff);\n    default:\n      return luaX_token2str(ls, token);\n  }\n}\n\n\nvoid luaX_lexerror (LexState *ls, const char *msg, int token) {\n  char buff[MAXSRC];\n  luaO_chunkid(buff, getstr(ls->source), MAXSRC);\n  msg = luaO_pushfstring(ls->L, \"%s:%d: %s\", buff, ls->linenumber, msg);\n  if (token)\n    luaO_pushfstring(ls->L, \"%s near \" LUA_QS, msg, txtToken(ls, token));\n  luaD_throw(ls->L, LUA_ERRSYNTAX);\n}\n\n\nvoid luaX_syntaxerror (LexState *ls, const char *msg) {\n  luaX_lexerror(ls, msg, ls->t.token);\n}\n\n\nTString *luaX_newstring (LexState *ls, const char *str, size_t l) {\n  lua_State *L = ls->L;\n  TString *ts = luaS_newlstr(L, str, l);\n  TValue *o = luaH_setstr(L, ls->fs->h, ts);  /* entry for `str' */\n  if (ttisnil(o)) {\n    setbvalue(o, 1);  /* make sure `str' will not be collected */\n    luaC_checkGC(L);\n  }\n  return ts;\n}\n\n\nstatic void inclinenumber (LexState *ls) {\n  int old = ls->current;\n  lua_assert(currIsNewline(ls));\n  next(ls);  /* skip `\\n' or `\\r' */\n  if (currIsNewline(ls) && ls->current != old)\n    next(ls);  /* skip `\\n\\r' or `\\r\\n' */\n  if (++ls->linenumber >= MAX_INT)\n    luaX_syntaxerror(ls, \"chunk has too many lines\");\n}\n\n\nvoid luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) {\n  ls->decpoint = '.';\n  ls->L = L;\n  ls->lookahead.token = TK_EOS;  /* no look-ahead token */\n  ls->z = z;\n  ls->fs = NULL;\n  ls->linenumber = 1;\n  ls->lastline = 1;\n  ls->source = source;\n  luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER);  /* initialize buffer */\n  next(ls);  /* read first char */\n}\n\n\n\n/*\n** =======================================================\n** LEXICAL ANALYZER\n** =======================================================\n*/\n\n\n\nstatic int check_next (LexState *ls, const char *set) {\n  if (!strchr(set, ls->current))\n    return 0;\n  save_and_next(ls);\n  return 1;\n}\n\n\nstatic void buffreplace (LexState *ls, char from, char to) {\n  size_t n = luaZ_bufflen(ls->buff);\n  char *p = luaZ_buffer(ls->buff);\n  while (n--)\n    if (p[n] == from) p[n] = to;\n}\n\n\nstatic void trydecpoint (LexState *ls, SemInfo *seminfo) {\n  /* format error: try to update decimal point separator */\n  struct lconv *cv = localeconv();\n  char old = ls->decpoint;\n  ls->decpoint = (cv ? cv->decimal_point[0] : '.');\n  buffreplace(ls, old, ls->decpoint);  /* try updated decimal separator */\n  if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) {\n    /* format error with correct decimal point: no more options */\n    buffreplace(ls, ls->decpoint, '.');  /* undo change (for error message) */\n    luaX_lexerror(ls, \"malformed number\", TK_NUMBER);\n  }\n}\n\n\n/* LUA_NUMBER */\nstatic void read_numeral (LexState *ls, SemInfo *seminfo) {\n  lua_assert(isdigit(ls->current));\n  do {\n    save_and_next(ls);\n  } while (isdigit(ls->current) || ls->current == '.');\n  if (check_next(ls, \"Ee\"))  /* `E'? */\n    check_next(ls, \"+-\");  /* optional exponent sign */\n  while (isalnum(ls->current) || ls->current == '_')\n    save_and_next(ls);\n  save(ls, '\\0');\n  buffreplace(ls, '.', ls->decpoint);  /* follow locale for decimal point */\n  if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r))  /* format error? */\n    trydecpoint(ls, seminfo); /* try to update decimal point separator */\n}\n\n\nstatic int skip_sep (LexState *ls) {\n  int count = 0;\n  int s = ls->current;\n  lua_assert(s == '[' || s == ']');\n  save_and_next(ls);\n  while (ls->current == '=') {\n    save_and_next(ls);\n    count++;\n  }\n  return (ls->current == s) ? count : (-count) - 1;\n}\n\n\nstatic void read_long_string (LexState *ls, SemInfo *seminfo, int sep) {\n  int cont = 0;\n  (void)(cont);  /* avoid warnings when `cont' is not used */\n  save_and_next(ls);  /* skip 2nd `[' */\n  if (currIsNewline(ls))  /* string starts with a newline? */\n    inclinenumber(ls);  /* skip it */\n  for (;;) {\n    switch (ls->current) {\n      case EOZ:\n        luaX_lexerror(ls, (seminfo) ? \"unfinished long string\" :\n                                   \"unfinished long comment\", TK_EOS);\n        break;  /* to avoid warnings */\n#if defined(LUA_COMPAT_LSTR)\n      case '[': {\n        if (skip_sep(ls) == sep) {\n          save_and_next(ls);  /* skip 2nd `[' */\n          cont++;\n#if LUA_COMPAT_LSTR == 1\n          if (sep == 0)\n            luaX_lexerror(ls, \"nesting of [[...]] is deprecated\", '[');\n#endif\n        }\n        break;\n      }\n#endif\n      case ']': {\n        if (skip_sep(ls) == sep) {\n          save_and_next(ls);  /* skip 2nd `]' */\n#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2\n          cont--;\n          if (sep == 0 && cont >= 0) break;\n#endif\n          goto endloop;\n        }\n        break;\n      }\n      case '\\n':\n      case '\\r': {\n        save(ls, '\\n');\n        inclinenumber(ls);\n        if (!seminfo) luaZ_resetbuffer(ls->buff);  /* avoid wasting space */\n        break;\n      }\n      default: {\n        if (seminfo) save_and_next(ls);\n        else next(ls);\n      }\n    }\n  } endloop:\n  if (seminfo)\n    seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep),\n                                     luaZ_bufflen(ls->buff) - 2*(2 + sep));\n}\n\n\nstatic void read_string (LexState *ls, int del, SemInfo *seminfo) {\n  save_and_next(ls);\n  while (ls->current != del) {\n    switch (ls->current) {\n      case EOZ:\n        luaX_lexerror(ls, \"unfinished string\", TK_EOS);\n        continue;  /* to avoid warnings */\n      case '\\n':\n      case '\\r':\n        luaX_lexerror(ls, \"unfinished string\", TK_STRING);\n        continue;  /* to avoid warnings */\n      case '\\\\': {\n        int c;\n        next(ls);  /* do not save the `\\' */\n        switch (ls->current) {\n          case 'a': c = '\\a'; break;\n          case 'b': c = '\\b'; break;\n          case 'f': c = '\\f'; break;\n          case 'n': c = '\\n'; break;\n          case 'r': c = '\\r'; break;\n          case 't': c = '\\t'; break;\n          case 'v': c = '\\v'; break;\n          case '\\n':  /* go through */\n          case '\\r': save(ls, '\\n'); inclinenumber(ls); continue;\n          case EOZ: continue;  /* will raise an error next loop */\n          default: {\n            if (!isdigit(ls->current))\n              save_and_next(ls);  /* handles \\\\, \\\", \\', and \\? */\n            else {  /* \\xxx */\n              int i = 0;\n              c = 0;\n              do {\n                c = 10*c + (ls->current-'0');\n                next(ls);\n              } while (++i<3 && isdigit(ls->current));\n              if (c > UCHAR_MAX)\n                luaX_lexerror(ls, \"escape sequence too large\", TK_STRING);\n              save(ls, c);\n            }\n            continue;\n          }\n        }\n        save(ls, c);\n        next(ls);\n        continue;\n      }\n      default:\n        save_and_next(ls);\n    }\n  }\n  save_and_next(ls);  /* skip delimiter */\n  seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1,\n                                   luaZ_bufflen(ls->buff) - 2);\n}\n\n\nstatic int llex (LexState *ls, SemInfo *seminfo) {\n  luaZ_resetbuffer(ls->buff);\n  for (;;) {\n    switch (ls->current) {\n      case '\\n':\n      case '\\r': {\n        inclinenumber(ls);\n        continue;\n      }\n      case '-': {\n        next(ls);\n        if (ls->current != '-') return '-';\n        /* else is a comment */\n        next(ls);\n        if (ls->current == '[') {\n          int sep = skip_sep(ls);\n          luaZ_resetbuffer(ls->buff);  /* `skip_sep' may dirty the buffer */\n          if (sep >= 0) {\n            read_long_string(ls, NULL, sep);  /* long comment */\n            luaZ_resetbuffer(ls->buff);\n            continue;\n          }\n        }\n        /* else short comment */\n        while (!currIsNewline(ls) && ls->current != EOZ)\n          next(ls);\n        continue;\n      }\n      case '[': {\n        int sep = skip_sep(ls);\n        if (sep >= 0) {\n          read_long_string(ls, seminfo, sep);\n          return TK_STRING;\n        }\n        else if (sep == -1) return '[';\n        else luaX_lexerror(ls, \"invalid long string delimiter\", TK_STRING);\n        return 0; /* never reached but will silence the FALLTHRU compiler warning */\n      }\n      case '=': {\n        next(ls);\n        if (ls->current != '=') return '=';\n        else { next(ls); return TK_EQ; }\n      }\n      case '<': {\n        next(ls);\n        if (ls->current != '=') return '<';\n        else { next(ls); return TK_LE; }\n      }\n      case '>': {\n        next(ls);\n        if (ls->current != '=') return '>';\n        else { next(ls); return TK_GE; }\n      }\n      case '~': {\n        next(ls);\n        if (ls->current != '=') return '~';\n        else { next(ls); return TK_NE; }\n      }\n      case '\"':\n      case '\\'': {\n        read_string(ls, ls->current, seminfo);\n        return TK_STRING;\n      }\n      case '.': {\n        save_and_next(ls);\n        if (check_next(ls, \".\")) {\n          if (check_next(ls, \".\"))\n            return TK_DOTS;   /* ... */\n          else return TK_CONCAT;   /* .. */\n        }\n        else if (!isdigit(ls->current)) return '.';\n        else {\n          read_numeral(ls, seminfo);\n          return TK_NUMBER;\n        }\n      }\n      case EOZ: {\n        return TK_EOS;\n      }\n      default: {\n        if (isspace(ls->current)) {\n          lua_assert(!currIsNewline(ls));\n          next(ls);\n          continue;\n        }\n        else if (isdigit(ls->current)) {\n          read_numeral(ls, seminfo);\n          return TK_NUMBER;\n        }\n        else if (isalpha(ls->current) || ls->current == '_') {\n          /* identifier or reserved word */\n          TString *ts;\n          do {\n            save_and_next(ls);\n          } while (isalnum(ls->current) || ls->current == '_');\n          ts = luaX_newstring(ls, luaZ_buffer(ls->buff),\n                                  luaZ_bufflen(ls->buff));\n          if (ts->tsv.reserved > 0)  /* reserved word? */\n            return ts->tsv.reserved - 1 + FIRST_RESERVED;\n          else {\n            seminfo->ts = ts;\n            return TK_NAME;\n          }\n        }\n        else {\n          int c = ls->current;\n          next(ls);\n          return c;  /* single-char tokens (+ - / ...) */\n        }\n      }\n    }\n  }\n}\n\n\nvoid luaX_next (LexState *ls) {\n  ls->lastline = ls->linenumber;\n  if (ls->lookahead.token != TK_EOS) {  /* is there a look-ahead token? */\n    ls->t = ls->lookahead;  /* use this one */\n    ls->lookahead.token = TK_EOS;  /* and discharge it */\n  }\n  else\n    ls->t.token = llex(ls, &ls->t.seminfo);  /* read next token */\n}\n\n\nvoid luaX_lookahead (LexState *ls) {\n  lua_assert(ls->lookahead.token == TK_EOS);\n  ls->lookahead.token = llex(ls, &ls->lookahead.seminfo);\n}\n\n"
  },
  {
    "path": "src/lua/llex.h",
    "content": "/*\n** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lexical Analyzer\n** See Copyright Notice in lua.h\n*/\n\n#ifndef llex_h\n#define llex_h\n\n#include \"lobject.h\"\n#include \"lzio.h\"\n\n\n#define FIRST_RESERVED\t257\n\n/* maximum length of a reserved word */\n#define TOKEN_LEN\t(sizeof(\"function\")/sizeof(char))\n\n\n/*\n* WARNING: if you change the order of this enumeration,\n* grep \"ORDER RESERVED\"\n*/\nenum RESERVED {\n  /* terminal symbols denoted by reserved words */\n  TK_AND = FIRST_RESERVED, TK_BREAK,\n  TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,\n  TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,\n  TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,\n  /* other terminal symbols */\n  TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,\n  TK_NAME, TK_STRING, TK_EOS\n};\n\n/* number of reserved words */\n#define NUM_RESERVED\t(cast(int, TK_WHILE-FIRST_RESERVED+1))\n\n\n/* array with token `names' */\nLUAI_DATA const char *const luaX_tokens [];\n\n\ntypedef union {\n  lua_Number r;\n  TString *ts;\n} SemInfo;  /* semantics information */\n\n\ntypedef struct Token {\n  int token;\n  SemInfo seminfo;\n} Token;\n\n\ntypedef struct LexState {\n  int current;  /* current character (charint) */\n  int linenumber;  /* input line counter */\n  int lastline;  /* line of last token `consumed' */\n  Token t;  /* current token */\n  Token lookahead;  /* look ahead token */\n  struct FuncState *fs;  /* `FuncState' is private to the parser */\n  struct lua_State *L;\n  ZIO *z;  /* input stream */\n  Mbuffer *buff;  /* buffer for tokens */\n  TString *source;  /* current source name */\n  char decpoint;  /* locale decimal point */\n} LexState;\n\n\nLUAI_FUNC void luaX_init (lua_State *L);\nLUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z,\n                              TString *source);\nLUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l);\nLUAI_FUNC void luaX_next (LexState *ls);\nLUAI_FUNC void luaX_lookahead (LexState *ls);\nLUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token);\nLUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s);\nLUAI_FUNC const char *luaX_token2str (LexState *ls, int token);\n\n\n#endif\n"
  },
  {
    "path": "src/lua/llimits.h",
    "content": "/*\n** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $\n** Limits, basic types, and some other `installation-dependent' definitions\n** See Copyright Notice in lua.h\n*/\n\n#ifndef llimits_h\n#define llimits_h\n\n\n#include <limits.h>\n#include <stddef.h>\n\n\n#include \"lua.h\"\n\n\ntypedef LUAI_UINT32 lu_int32;\n\ntypedef LUAI_UMEM lu_mem;\n\ntypedef LUAI_MEM l_mem;\n\n\n\n/* chars used as small naturals (so that `char' is reserved for characters) */\ntypedef unsigned char lu_byte;\n\n\n#define MAX_SIZET\t((size_t)(~(size_t)0)-2)\n\n#define MAX_LUMEM\t((lu_mem)(~(lu_mem)0)-2)\n\n\n#define MAX_INT (INT_MAX-2)  /* maximum value of an int (-2 for safety) */\n\n/*\n** conversion of pointer to integer\n** this is for hashing only; there is no problem if the integer\n** cannot hold the whole pointer value\n*/\n#define IntPoint(p)  ((unsigned int)(lu_mem)(p))\n\n\n\n/* type to ensure maximum alignment */\ntypedef LUAI_USER_ALIGNMENT_T L_Umaxalign;\n\n\n/* result of a `usual argument conversion' over lua_Number */\ntypedef LUAI_UACNUMBER l_uacNumber;\n\n\n/* internal assertions for in-house debugging */\n#ifdef lua_assert\n\n#define check_exp(c,e)\t\t(lua_assert(c), (e))\n#define api_check(l,e)\t\tlua_assert(e)\n\n#else\n\n#define lua_assert(c)\t\t((void)0)\n#define check_exp(c,e)\t\t(e)\n#define api_check\t\tluai_apicheck\n\n#endif\n\n\n#ifndef UNUSED\n#define UNUSED(x)\t((void)(x))\t/* to avoid warnings */\n#endif\n\n\n#ifndef cast\n#define cast(t, exp)\t((t)(exp))\n#endif\n\n#define cast_byte(i)\tcast(lu_byte, (i))\n#define cast_num(i)\tcast(lua_Number, (i))\n#define cast_int(i)\tcast(int, (i))\n\n\n\n/*\n** type for virtual-machine instructions\n** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h)\n*/\ntypedef lu_int32 Instruction;\n\n\n\n/* maximum stack for a Lua function */\n#define MAXSTACK\t250\n\n\n\n/* minimum size for the string table (must be power of 2) */\n#ifndef MINSTRTABSIZE\n#define MINSTRTABSIZE\t32\n#endif\n\n\n/* minimum size for string buffer */\n#ifndef LUA_MINBUFFER\n#define LUA_MINBUFFER\t32\n#endif\n\n\n#ifndef lua_lock\n#define lua_lock(L)     ((void) 0) \n#define lua_unlock(L)   ((void) 0)\n#endif\n\n#ifndef luai_threadyield\n#define luai_threadyield(L)     {lua_unlock(L); lua_lock(L);}\n#endif\n\n\n/*\n** macro to control inclusion of some hard tests on stack reallocation\n*/ \n#ifndef HARDSTACKTESTS\n#define condhardstacktests(x)\t((void)0)\n#else\n#define condhardstacktests(x)\tx\n#endif\n\n#endif\n"
  },
  {
    "path": "src/lua/lmathlib.c",
    "content": "/*\n** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $\n** Standard mathematical library\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdlib.h>\n#include <math.h>\n\n#define lmathlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n#undef PI\n#define PI (3.14159265358979323846)\n#define RADIANS_PER_DEGREE (PI/180.0)\n\n\n\nstatic int math_abs (lua_State *L) {\n  lua_pushnumber(L, fabs(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_sin (lua_State *L) {\n  lua_pushnumber(L, sin(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_sinh (lua_State *L) {\n  lua_pushnumber(L, sinh(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_cos (lua_State *L) {\n  lua_pushnumber(L, cos(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_cosh (lua_State *L) {\n  lua_pushnumber(L, cosh(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_tan (lua_State *L) {\n  lua_pushnumber(L, tan(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_tanh (lua_State *L) {\n  lua_pushnumber(L, tanh(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_asin (lua_State *L) {\n  lua_pushnumber(L, asin(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_acos (lua_State *L) {\n  lua_pushnumber(L, acos(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_atan (lua_State *L) {\n  lua_pushnumber(L, atan(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_atan2 (lua_State *L) {\n  lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));\n  return 1;\n}\n\nstatic int math_ceil (lua_State *L) {\n  lua_pushnumber(L, ceil(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_floor (lua_State *L) {\n  lua_pushnumber(L, floor(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_fmod (lua_State *L) {\n  lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));\n  return 1;\n}\n\nstatic int math_modf (lua_State *L) {\n  double ip;\n  double fp = modf(luaL_checknumber(L, 1), &ip);\n  lua_pushnumber(L, ip);\n  lua_pushnumber(L, fp);\n  return 2;\n}\n\nstatic int math_sqrt (lua_State *L) {\n  lua_pushnumber(L, sqrt(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_pow (lua_State *L) {\n  lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2)));\n  return 1;\n}\n\nstatic int math_log (lua_State *L) {\n  lua_pushnumber(L, log(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_log10 (lua_State *L) {\n  lua_pushnumber(L, log10(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_exp (lua_State *L) {\n  lua_pushnumber(L, exp(luaL_checknumber(L, 1)));\n  return 1;\n}\n\nstatic int math_deg (lua_State *L) {\n  lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE);\n  return 1;\n}\n\nstatic int math_rad (lua_State *L) {\n  lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE);\n  return 1;\n}\n\nstatic int math_frexp (lua_State *L) {\n  int e;\n  lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e));\n  lua_pushinteger(L, e);\n  return 2;\n}\n\nstatic int math_ldexp (lua_State *L) {\n  lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2)));\n  return 1;\n}\n\n\n\nstatic int math_min (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  lua_Number dmin = luaL_checknumber(L, 1);\n  int i;\n  for (i=2; i<=n; i++) {\n    lua_Number d = luaL_checknumber(L, i);\n    if (d < dmin)\n      dmin = d;\n  }\n  lua_pushnumber(L, dmin);\n  return 1;\n}\n\n\nstatic int math_max (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  lua_Number dmax = luaL_checknumber(L, 1);\n  int i;\n  for (i=2; i<=n; i++) {\n    lua_Number d = luaL_checknumber(L, i);\n    if (d > dmax)\n      dmax = d;\n  }\n  lua_pushnumber(L, dmax);\n  return 1;\n}\n\n\nstatic int math_random (lua_State *L) {\n  /* the `%' avoids the (rare) case of r==1, and is needed also because on\n     some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */\n  lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX;\n  switch (lua_gettop(L)) {  /* check number of arguments */\n    case 0: {  /* no arguments */\n      lua_pushnumber(L, r);  /* Number between 0 and 1 */\n      break;\n    }\n    case 1: {  /* only upper limit */\n      int u = luaL_checkint(L, 1);\n      luaL_argcheck(L, 1<=u, 1, \"interval is empty\");\n      lua_pushnumber(L, floor(r*u)+1);  /* int between 1 and `u' */\n      break;\n    }\n    case 2: {  /* lower and upper limits */\n      int l = luaL_checkint(L, 1);\n      int u = luaL_checkint(L, 2);\n      luaL_argcheck(L, l<=u, 2, \"interval is empty\");\n      lua_pushnumber(L, floor(r*(u-l+1))+l);  /* int between `l' and `u' */\n      break;\n    }\n    default: return luaL_error(L, \"wrong number of arguments\");\n  }\n  return 1;\n}\n\n\nstatic int math_randomseed (lua_State *L) {\n  srand(luaL_checkint(L, 1));\n  return 0;\n}\n\n\nstatic int math_erf (lua_State *L) {\n  lua_pushnumber(L, erf(luaL_checknumber(L, 1)));\n  return 1;\n}\n\n\nstatic int math_erfc (lua_State *L) {\n  lua_pushnumber(L, erfc(luaL_checknumber(L, 1)));\n  return 1;\n}\n\n\nstatic const luaL_Reg mathlib[] = {\n  {\"abs\",   math_abs},\n  {\"acos\",  math_acos},\n  {\"asin\",  math_asin},\n  {\"atan2\", math_atan2},\n  {\"atan\",  math_atan},\n  {\"ceil\",  math_ceil},\n  {\"cosh\",   math_cosh},\n  {\"cos\",   math_cos},\n  {\"deg\",   math_deg},\n  {\"erf\",   math_erf},\n  {\"erfc\",   math_erfc},\n  {\"exp\",   math_exp},\n  {\"floor\", math_floor},\n  {\"fmod\",   math_fmod},\n  {\"frexp\", math_frexp},\n  {\"ldexp\", math_ldexp},\n  {\"log10\", math_log10},\n  {\"log\",   math_log},\n  {\"max\",   math_max},\n  {\"min\",   math_min},\n  {\"modf\",   math_modf},\n  {\"pow\",   math_pow},\n  {\"rad\",   math_rad},\n  {\"random\",     math_random},\n  {\"randomseed\", math_randomseed},\n  {\"sinh\",   math_sinh},\n  {\"sin\",   math_sin},\n  {\"sqrt\",  math_sqrt},\n  {\"tanh\",   math_tanh},\n  {\"tan\",   math_tan},\n  {NULL, NULL}\n};\n\n\n/*\n** Open math library\n*/\nLUALIB_API int luaopen_math (lua_State *L) {\n  luaL_register(L, LUA_MATHLIBNAME, mathlib);\n  lua_pushnumber(L, PI);\n  lua_setfield(L, -2, \"pi\");\n  lua_pushnumber(L, HUGE_VAL);\n  lua_setfield(L, -2, \"huge\");\n#if defined(LUA_COMPAT_MOD)\n  lua_getfield(L, -1, \"fmod\");\n  lua_setfield(L, -2, \"mod\");\n#endif\n  return 1;\n}\n\n"
  },
  {
    "path": "src/lua/lmem.c",
    "content": "/*\n** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $\n** Interface to Memory Manager\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define lmem_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n\n\n\n/*\n** About the realloc function:\n** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);\n** (`osize' is the old size, `nsize' is the new size)\n**\n** Lua ensures that (ptr == NULL) iff (osize == 0).\n**\n** * frealloc(ud, NULL, 0, x) creates a new block of size `x'\n**\n** * frealloc(ud, p, x, 0) frees the block `p'\n** (in this specific case, frealloc must return NULL).\n** particularly, frealloc(ud, NULL, 0, 0) does nothing\n** (which is equivalent to free(NULL) in ANSI C)\n**\n** frealloc returns NULL if it cannot create or reallocate the area\n** (any reallocation to an equal or smaller size cannot fail!)\n*/\n\n\n\n#define MINSIZEARRAY\t4\n\n\nvoid *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,\n                     int limit, const char *errormsg) {\n  void *newblock;\n  int newsize;\n  if (*size >= limit/2) {  /* cannot double it? */\n    if (*size >= limit)  /* cannot grow even a little? */\n      luaG_runerror(L, errormsg);\n    newsize = limit;  /* still have at least one free place */\n  }\n  else {\n    newsize = (*size)*2;\n    if (newsize < MINSIZEARRAY)\n      newsize = MINSIZEARRAY;  /* minimum size */\n  }\n  newblock = luaM_reallocv(L, block, *size, newsize, size_elems);\n  *size = newsize;  /* update only when everything else is OK */\n  return newblock;\n}\n\n\nvoid *luaM_toobig (lua_State *L) {\n  luaG_runerror(L, \"memory allocation error: block too big\");\n  return NULL;  /* to avoid warnings */\n}\n\n\n\n/*\n** generic allocation routine.\n*/\nvoid *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {\n  global_State *g = G(L);\n  lua_assert((osize == 0) == (block == NULL));\n  block = (*g->frealloc)(g->ud, block, osize, nsize);\n  if (block == NULL && nsize > 0)\n    luaD_throw(L, LUA_ERRMEM);\n  lua_assert((nsize == 0) == (block == NULL));\n  g->totalbytes = (g->totalbytes - osize) + nsize;\n  return block;\n}\n\n"
  },
  {
    "path": "src/lua/lmem.h",
    "content": "/*\n** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $\n** Interface to Memory Manager\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lmem_h\n#define lmem_h\n\n\n#include <stddef.h>\n\n#include \"llimits.h\"\n#include \"lua.h\"\n\n#define MEMERRMSG\t\"not enough memory\"\n\n\n#define luaM_reallocv(L,b,on,n,e) \\\n\t((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ?  /* +1 to avoid warnings */ \\\n\t\tluaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \\\n\t\tluaM_toobig(L))\n\n#define luaM_freemem(L, b, s)\tluaM_realloc_(L, (b), (s), 0)\n#define luaM_free(L, b)\t\tluaM_realloc_(L, (b), sizeof(*(b)), 0)\n#define luaM_freearray(L, b, n, t)   luaM_reallocv(L, (b), n, 0, sizeof(t))\n\n#define luaM_malloc(L,t)\tluaM_realloc_(L, NULL, 0, (t))\n#define luaM_new(L,t)\t\tcast(t *, luaM_malloc(L, sizeof(t)))\n#define luaM_newvector(L,n,t) \\\n\t\tcast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t)))\n\n#define luaM_growvector(L,v,nelems,size,t,limit,e) \\\n          if ((nelems)+1 > (size)) \\\n            ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e)))\n\n#define luaM_reallocvector(L, v,oldn,n,t) \\\n   ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t))))\n\n\nLUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,\n                                                          size_t size);\nLUAI_FUNC void *luaM_toobig (lua_State *L);\nLUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size,\n                               size_t size_elem, int limit,\n                               const char *errormsg);\n\n#endif\n\n"
  },
  {
    "path": "src/lua/loadlib.c",
    "content": "/*\n** $Id: loadlib.c,v 1.52.1.4 2009/09/09 13:17:16 roberto Exp $\n** Dynamic library loader for Lua\n** See Copyright Notice in lua.h\n**\n** This module contains an implementation of loadlib for Unix systems\n** that have dlfcn, an implementation for Darwin (Mac OS X), an\n** implementation for Windows, and a stub for other systems.\n*/\n\n\n#include <ctype.h>\n#include <stdlib.h>\n#include <string.h>\n\n\n#define loadlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n/* prefix for open functions in C libraries */\n#define LUA_POF   \"luaopen_\"\n\n/* separator for open functions in C libraries */\n#define LUA_OFSEP \"_\"\n\n\n#define LIBPREFIX \"LOADLIB: \"\n\n#define POF   LUA_POF\n#define LIB_FAIL  \"open\"\n\n\n/* error codes for ll_loadfunc */\n#define ERRLIB    1\n#define ERRFUNC   2\n\n\n#define LSB_CONFIG \"lsb_config\"\n\nstatic void ll_unloadlib (void *lib);\nstatic void *ll_load (lua_State *L, const char *path);\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym);\n\n\n\n#if defined(LUA_DL_DLOPEN)\n/*\n** {========================================================================\n** This is an implementation of loadlib based on the dlfcn interface.\n** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD,\n** NetBSD, AIX 4.2, HPUX 11, and  probably most other Unix flavors, at least\n** as an emulation layer on top of native functions.\n** =========================================================================\n*/\n\n#include <dlfcn.h>\n\nstatic void ll_unloadlib (void *lib) {\n  dlclose(lib);\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  void *lib = dlopen(path, RTLD_NOW);\n  if (lib == NULL) lua_pushstring(L, dlerror());\n  return lib;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  lua_CFunction f;\n  *(void **)(&f)= dlsym(lib, sym);\n  if (f == NULL) lua_pushstring(L, dlerror());\n  return f;\n}\n\n/* }====================================================== */\n\n\n\n#elif defined(LUA_DL_DLL)\n/*\n** {======================================================================\n** This is an implementation of loadlib for Windows using native functions.\n** =======================================================================\n*/\n\n#include <windows.h>\n\nstatic void pusherror (lua_State *L) {\n  int error = GetLastError();\n  char buffer[128];\n  if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,\n      NULL, error, 0, buffer, sizeof(buffer), NULL))\n    lua_pushstring(L, buffer);\n  else\n    lua_pushfstring(L, \"system error %d\\n\", error);\n}\n\nstatic void ll_unloadlib (void *lib) {\n  FreeLibrary((HINSTANCE)lib);\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  HINSTANCE lib = LoadLibraryA(path);\n  if (lib == NULL) pusherror(L);\n  return lib;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym);\n  if (f == NULL) pusherror(L);\n  return f;\n}\n\n/* }====================================================== */\n\n\n\n#elif defined(LUA_DL_DYLD)\n/*\n** {======================================================================\n** Native Mac OS X / Darwin Implementation\n** =======================================================================\n*/\n\n#include <mach-o/dyld.h>\n\n\n/* Mac appends a `_' before C function names */\n#undef POF\n#define POF \"_\" LUA_POF\n\n\nstatic void pusherror (lua_State *L) {\n  const char *err_str;\n  const char *err_file;\n  NSLinkEditErrors err;\n  int err_num;\n  NSLinkEditError(&err, &err_num, &err_file, &err_str);\n  lua_pushstring(L, err_str);\n}\n\n\nstatic const char *errorfromcode (NSObjectFileImageReturnCode ret) {\n  switch (ret) {\n    case NSObjectFileImageInappropriateFile:\n      return \"file is not a bundle\";\n    case NSObjectFileImageArch:\n      return \"library is for wrong CPU type\";\n    case NSObjectFileImageFormat:\n      return \"bad format\";\n    case NSObjectFileImageAccess:\n      return \"cannot access file\";\n    case NSObjectFileImageFailure:\n    default:\n      return \"unable to load library\";\n  }\n}\n\n\nstatic void ll_unloadlib (void *lib) {\n  NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES);\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  NSObjectFileImage img;\n  NSObjectFileImageReturnCode ret;\n  /* this would be a rare case, but prevents crashing if it happens */\n  if(!_dyld_present()) {\n    lua_pushliteral(L, \"dyld not present\");\n    return NULL;\n  }\n  ret = NSCreateObjectFileImageFromFile(path, &img);\n  if (ret == NSObjectFileImageSuccess) {\n    NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE |\n                       NSLINKMODULE_OPTION_RETURN_ON_ERROR);\n    NSDestroyObjectFileImage(img);\n    if (mod == NULL) pusherror(L);\n    return mod;\n  }\n  lua_pushstring(L, errorfromcode(ret));\n  return NULL;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym);\n  if (nss == NULL) {\n    lua_pushfstring(L, \"symbol \" LUA_QS \" not found\", sym);\n    return NULL;\n  }\n  return (lua_CFunction)NSAddressOfSymbol(nss);\n}\n\n/* }====================================================== */\n\n\n\n#else\n/*\n** {======================================================\n** Fallback for other systems\n** =======================================================\n*/\n\n#undef LIB_FAIL\n#define LIB_FAIL  \"absent\"\n\n\n#define DLMSG \"dynamic libraries not enabled; check your Lua installation\"\n\n\nstatic void ll_unloadlib (void *lib) {\n  (void)lib;  /* to avoid warnings */\n}\n\n\nstatic void *ll_load (lua_State *L, const char *path) {\n  (void)path;  /* to avoid warnings */\n  lua_pushliteral(L, DLMSG);\n  return NULL;\n}\n\n\nstatic lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) {\n  (void)lib; (void)sym;  /* to avoid warnings */\n  lua_pushliteral(L, DLMSG);\n  return NULL;\n}\n\n/* }====================================================== */\n#endif\n\n\n\nstatic void **ll_register (lua_State *L, const char *path) {\n  void **plib;\n  lua_pushfstring(L, \"%s%s\", LIBPREFIX, path);\n  lua_gettable(L, LUA_REGISTRYINDEX);  /* check library in registry? */\n  if (!lua_isnil(L, -1))  /* is there an entry? */\n    plib = (void **)lua_touserdata(L, -1);\n  else {  /* no entry yet; create one */\n    lua_pop(L, 1);\n    plib = (void **)lua_newuserdata(L, sizeof(const void *));\n    *plib = NULL;\n    luaL_getmetatable(L, \"_LOADLIB\");\n    lua_setmetatable(L, -2);\n    lua_pushfstring(L, \"%s%s\", LIBPREFIX, path);\n    lua_pushvalue(L, -2);\n    lua_settable(L, LUA_REGISTRYINDEX);\n  }\n  return plib;\n}\n\n\n/*\n** __gc tag method: calls library's `ll_unloadlib' function with the lib\n** handle\n*/\nstatic int gctm (lua_State *L) {\n  void **lib = (void **)luaL_checkudata(L, 1, \"_LOADLIB\");\n  if (*lib) ll_unloadlib(*lib);\n  *lib = NULL;  /* mark library as closed */\n  return 0;\n}\n\n\nstatic int ll_loadfunc (lua_State *L, const char *path, const char *sym) {\n  void **reg = ll_register(L, path);\n  if (*reg == NULL) *reg = ll_load(L, path);\n  if (*reg == NULL)\n    return ERRLIB;  /* unable to load library */\n  else {\n    lua_CFunction f = ll_sym(L, *reg, sym);\n    if (f == NULL)\n      return ERRFUNC;  /* unable to find function */\n    lua_pushcfunction(L, f);\n    return 0;  /* return function */\n  }\n}\n\n\n/*\n** {======================================================\n** 'require' function\n** =======================================================\n*/\n\n\nstatic int readable (const char *filename) {\n  FILE *f = fopen(filename, \"r\");  /* try to open file */\n  if (f == NULL) return 0;  /* open failed */\n  fclose(f);\n  return 1;\n}\n\n\nstatic const char *pushnexttemplate (lua_State *L, const char *path) {\n  const char *l;\n  while (*path == *LUA_PATHSEP) path++;  /* skip separators */\n  if (*path == '\\0') return NULL;  /* no more templates */\n  l = strchr(path, *LUA_PATHSEP);  /* find next separator */\n  if (l == NULL) l = path + strlen(path);\n  lua_pushlstring(L, path, l - path);  /* template */\n  return l;\n}\n\n\nstatic const char *findfile (lua_State *L, const char *name,\n                                           const char *pname) {\n  const char *path;\n  int i = 0;\n  while (name[i]) {\n    if (!isalnum(name[i]) && name[i] != '_' && name[i] != '.') {\n      luaL_error(L, \"invalid module name '%s'\", name);\n      return NULL; // never reached, just silences the compiler\n    }\n    ++i;\n  }\n  lua_getfield(L, LUA_REGISTRYINDEX, LSB_CONFIG);\n  if (lua_type(L, -1) != LUA_TTABLE) {\n    return NULL;\n  }\n  name = luaL_gsub(L, name, \".\", LUA_DIRSEP);\n  lua_getfield(L, -2, pname);\n  path = lua_tostring(L, -1);\n  if (path == NULL)\n    luaL_error(L, \"no '%s' configuration was specified for the sandbox; \"\n                  \"external modules have been disabled\", pname);\n  lua_pushliteral(L, \"\");  /* error accumulator */\n  while ((path = pushnexttemplate(L, path)) != NULL) {\n    const char *filename;\n    filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name);\n    lua_remove(L, -2);  /* remove path template */\n    if (readable(filename))  /* does file exist and is readable? */\n      return filename;  /* return that file name */\n    lua_pushfstring(L, \"\\n\\tno file \" LUA_QS, filename);\n    lua_remove(L, -2);  /* remove file name */\n    lua_concat(L, 2);  /* add entry to possible error message */\n  }\n  return NULL;  /* not found */\n}\n\n\nstatic void loaderror (lua_State *L, const char *filename) {\n  luaL_error(L, \"error loading module \" LUA_QS \" from file \" LUA_QS \":\\n\\t%s\",\n                lua_tostring(L, 1), filename, lua_tostring(L, -1));\n}\n\n\nstatic int loader_Lua (lua_State *L) {\n  const char *filename;\n  const char *name = luaL_checkstring(L, 1);\n  filename = findfile(L, name, \"path\");\n  if (filename == NULL) return 1;  /* library not found in this path */\n  if (luaL_loadfile(L, filename) != 0)\n    loaderror(L, filename);\n  return 1;  /* library loaded successfully */\n}\n\n\nstatic const char *mkfuncname (lua_State *L, const char *modname) {\n  const char *funcname;\n  const char *mark = strchr(modname, *LUA_IGMARK);\n  if (mark) modname = mark + 1;\n  funcname = luaL_gsub(L, modname, \".\", LUA_OFSEP);\n  funcname = lua_pushfstring(L, POF\"%s\", funcname);\n  lua_remove(L, -2);  /* remove 'gsub' result */\n  return funcname;\n}\n\n\nstatic int loader_C (lua_State *L) {\n  const char *funcname;\n  const char *name = luaL_checkstring(L, 1);\n  const char *filename = findfile(L, name, \"cpath\");\n  if (filename == NULL) return 1;  /* library not found in this path */\n  funcname = mkfuncname(L, name);\n  if (ll_loadfunc(L, filename, funcname) != 0)\n    loaderror(L, filename);\n  return 1;  /* library loaded successfully */\n}\n\n\nstatic int loader_Croot (lua_State *L) {\n  const char *funcname;\n  const char *filename;\n  const char *name = luaL_checkstring(L, 1);\n  const char *p = strchr(name, '.');\n  int stat;\n  if (p == NULL) return 0;  /* is root */\n  lua_pushlstring(L, name, p - name);\n  filename = findfile(L, lua_tostring(L, -1), \"cpath\");\n  if (filename == NULL) return 1;  /* root not found */\n  funcname = mkfuncname(L, name);\n  if ((stat = ll_loadfunc(L, filename, funcname)) != 0) {\n    if (stat != ERRFUNC) loaderror(L, filename);  /* real error */\n    lua_pushfstring(L, \"\\n\\tno module \" LUA_QS \" in file \" LUA_QS,\n                       name, filename);\n    return 1;  /* function not found */\n  }\n  return 1;\n}\n\n\nstatic int loader_preload (lua_State *L) {\n  const char *name = luaL_checkstring(L, 1);\n  lua_getfield(L, LUA_ENVIRONINDEX, \"preload\");\n  if (!lua_istable(L, -1))\n    luaL_error(L, LUA_QL(\"preload\") \" must be a table\");\n  lua_getfield(L, -1, name);\n  return 1;\n}\n\n// If necessary, add an empty metatable to flag the table as non-data\n// during preservation.\nstatic void add_empty_metatable(lua_State* L)\n{\n  if (lua_getmetatable(L, -1) == 0) {\n    lua_newtable(L);\n    lua_setmetatable(L, -2);\n  } else {\n    lua_pop(L, 1);\n  }\n}\n\n\nstatic void remove_entries(lua_State* L, const char* name)\n{\n  lua_getfield(L, LUA_REGISTRYINDEX, LSB_CONFIG);\n  if (lua_type(L, -1) != LUA_TTABLE) {\n    lua_pop(L, 1);\n    return;\n  }\n  lua_getfield(L, -1, \"remove_entries\");\n  if (lua_type(L, -1) != LUA_TTABLE) {\n    lua_pop(L, 2);\n    return;\n  }\n  lua_getfield(L, -1, name);\n  if (lua_type(L, -1) != LUA_TTABLE) {\n    lua_pop(L, 3);\n    return;\n  }\n  int n = 1;\n  while (1) {\n    lua_rawgeti(L, -1, n);\n    if (lua_type(L, -1) == LUA_TNIL) {\n      lua_pop(L, 1);\n      break;\n    }\n    lua_pushnil(L);\n    lua_settable(L, -6);\n    ++n;\n  }\n  lua_pop(L, 3);\n}\n\n\nstatic int is_disabled(lua_State* L, const char* name)\n{\n  int status = 0;\n  lua_getfield(L, LUA_REGISTRYINDEX, LSB_CONFIG);\n  if (lua_type(L, -1) != LUA_TTABLE) {\n    lua_pop(L, 1);\n    return status;\n  }\n  lua_getfield(L, -1, \"disable_modules\");\n  if (lua_type(L, -1) != LUA_TTABLE) {\n    lua_pop(L, 2);\n    return status;\n  }\n  lua_getfield(L, -1, name);\n  if (lua_type(L, -1) != LUA_TNIL) {\n    status = 1;\n  }\n  lua_pop(L, 3);\n  return status;\n}\n\n\nstatic const int sentinel_ = 0;\n#define sentinel  ((void *)&sentinel_)\n\n\nstatic int ll_require (lua_State *L) {\n  const char *name = luaL_checkstring(L, 1);\n  if (is_disabled(L, name)) {\n    luaL_error(L, \"module \" LUA_QS \" disabled\", name);\n  }\n  int i;\n  lua_settop(L, 1);  /* _LOADED table will be at index 2 */\n  lua_getfield(L, LUA_REGISTRYINDEX, \"_LOADED\");\n  lua_getfield(L, 2, name);\n  if (lua_toboolean(L, -1)) {  /* is it there? */\n    if (lua_touserdata(L, -1) == sentinel)  /* check loops */\n      luaL_error(L, \"loop or previous error loading module \" LUA_QS, name);\n    return 1;  /* package is already loaded */\n  }\n  /* else must load it; iterate over available loaders */\n  lua_getfield(L, LUA_ENVIRONINDEX, \"loaders\");\n  if (!lua_istable(L, -1))\n    luaL_error(L, LUA_QL(\"loaders\") \" must be a table\");\n  lua_pushliteral(L, \"\");  /* error message accumulator */\n  for (i=1; ; i++) {\n    lua_rawgeti(L, -2, i);  /* get a loader */\n    if (lua_isnil(L, -1))\n      luaL_error(L, \"module \" LUA_QS \" not found:%s\",\n                    name, lua_tostring(L, -2));\n    lua_pushstring(L, name);\n    lua_call(L, 1, 1);  /* call it */\n    if (lua_isfunction(L, -1))  /* did it find module? */\n      break;  /* module loaded successfully */\n    else if (lua_isstring(L, -1))  /* loader returned error message? */\n      lua_concat(L, 2);  /* accumulate it */\n    else\n      lua_pop(L, 1);\n  }\n  lua_pushlightuserdata(L, sentinel);\n  lua_setfield(L, 2, name);  /* _LOADED[name] = sentinel */\n  lua_pushstring(L, name);  /* pass name as argument to module */\n  lua_call(L, 1, 1);  /* run loaded module */\n  if (!lua_isnil(L, -1))  /* non-nil return? */\n    lua_setfield(L, 2, name);  /* _LOADED[name] = returned value */\n  lua_getfield(L, 2, name);\n  if (lua_touserdata(L, -1) == sentinel) {   /* module did not set a value? */\n    lua_pushboolean(L, 1);  /* use true as result */\n    lua_pushvalue(L, -1);  /* extra copy to be returned */\n    lua_setfield(L, 2, name);  /* _LOADED[name] = true */\n  }\n  add_empty_metatable(L);\n  remove_entries(L, name);\n  return 1;\n}\n\n/* }====================================================== */\n\n\n\n/*\n** {======================================================\n** 'module' function\n** =======================================================\n*/\n\n\nstatic void setfenv (lua_State *L) {\n  lua_Debug ar;\n  if (lua_getstack(L, 1, &ar) == 0 ||\n      lua_getinfo(L, \"f\", &ar) == 0 ||  /* get calling function */\n      lua_iscfunction(L, -1))\n    luaL_error(L, LUA_QL(\"module\") \" not called from a Lua function\");\n  lua_pushvalue(L, -2);\n  lua_setfenv(L, -2);\n  lua_pop(L, 1);\n}\n\n\nstatic void dooptions (lua_State *L, int n) {\n  int i;\n  for (i = 2; i <= n; i++) {\n    lua_pushvalue(L, i);  /* get option (a function) */\n    lua_pushvalue(L, -2);  /* module */\n    lua_call(L, 1, 0);\n  }\n}\n\n\nstatic void modinit (lua_State *L, const char *modname) {\n  const char *dot;\n  lua_pushvalue(L, -1);\n  lua_setfield(L, -2, \"_M\");  /* module._M = module */\n  lua_pushstring(L, modname);\n  lua_setfield(L, -2, \"_NAME\");\n  dot = strrchr(modname, '.');  /* look for last dot in module name */\n  if (dot == NULL) dot = modname;\n  else dot++;\n  /* set _PACKAGE as package name (full module name minus last part) */\n  lua_pushlstring(L, modname, dot - modname);\n  lua_setfield(L, -2, \"_PACKAGE\");\n}\n\n\nstatic int ll_module (lua_State *L) {\n  const char *modname = luaL_checkstring(L, 1);\n  int loaded = lua_gettop(L) + 1;  /* index of _LOADED table */\n  lua_getfield(L, LUA_REGISTRYINDEX, \"_LOADED\");\n  lua_getfield(L, loaded, modname);  /* get _LOADED[modname] */\n  if (!lua_istable(L, -1)) {  /* not found? */\n    lua_pop(L, 1);  /* remove previous result */\n    /* try global variable (and create one if it does not exist) */\n    if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL)\n      return luaL_error(L, \"name conflict for module \" LUA_QS, modname);\n    lua_pushvalue(L, -1);\n    lua_setfield(L, loaded, modname);  /* _LOADED[modname] = new table */\n  }\n  /* check whether table already has a _NAME field */\n  lua_getfield(L, -1, \"_NAME\");\n  if (!lua_isnil(L, -1))  /* is table an initialized module? */\n    lua_pop(L, 1);\n  else {  /* no; initialize it */\n    lua_pop(L, 1);\n    modinit(L, modname);\n  }\n  lua_pushvalue(L, -1);\n  setfenv(L);\n  dooptions(L, loaded - 1);\n  return 0;\n}\n\n\nstatic int ll_seeall (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  if (!lua_getmetatable(L, 1)) {\n    lua_createtable(L, 0, 1); /* create new metatable */\n    lua_pushvalue(L, -1);\n    lua_setmetatable(L, 1);\n  }\n  lua_pushvalue(L, LUA_GLOBALSINDEX);\n  lua_setfield(L, -2, \"__index\");  /* mt.__index = _G */\n  return 0;\n}\n\n\n/* }====================================================== */\n\n\n\nstatic const luaL_Reg pk_funcs[] = {\n  {\"seeall\", ll_seeall},\n  {NULL, NULL}\n};\n\n\nstatic const luaL_Reg ll_funcs[] = {\n  {\"module\", ll_module},\n  {\"require\", ll_require},\n  {NULL, NULL}\n};\n\n\nstatic const lua_CFunction loaders[] =\n  {loader_preload, loader_Lua, loader_C, loader_Croot, NULL};\n\n\nLUALIB_API int luaopen_package (lua_State *L) {\n  int i;\n  /* create new type _LOADLIB */\n  luaL_newmetatable(L, \"_LOADLIB\");\n  lua_pushcfunction(L, gctm);\n  lua_setfield(L, -2, \"__gc\");\n  /* create `package' environment table (not exposed to Lua) */\n  lua_newtable(L);\n  lua_pushvalue(L, -1);\n  lua_replace(L, LUA_ENVIRONINDEX);\n  /* create `loaders' table */\n  lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0);\n  /* fill it with pre-defined loaders */\n  for (i=0; loaders[i] != NULL; i++) {\n    lua_pushcfunction(L, loaders[i]);\n    lua_rawseti(L, -2, i+1);\n  }\n  lua_setfield(L, -2, \"loaders\");  /* put it in field `loaders' */\n\n  /* set field `preload' */\n  luaL_findtable(L, LUA_REGISTRYINDEX, \"_PRELOADED\", 0);\n  lua_setfield(L, -2, \"preload\");\n\n  /* open lib into global table */\n  lua_pushvalue(L, LUA_GLOBALSINDEX);\n  luaL_register(L, NULL, ll_funcs);\n  lua_pop(L, 1);\n\n  luaL_register(L, LUA_LOADLIBNAME, pk_funcs);\n  return 1;  /* return 'package' table */\n}\n"
  },
  {
    "path": "src/lua/lobject.c",
    "content": "/*\n** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $\n** Some generic functions over Lua objects\n** See Copyright Notice in lua.h\n*/\n\n#include <ctype.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lobject_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldo.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"lvm.h\"\n\n\n\nconst TValue luaO_nilobject_ = {{NULL}, LUA_TNIL};\n\n\n/*\n** converts an integer to a \"floating point byte\", represented as\n** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if\n** eeeee != 0 and (xxx) otherwise.\n*/\nint luaO_int2fb (unsigned int x) {\n  int e = 0;  /* expoent */\n  while (x >= 16) {\n    x = (x+1) >> 1;\n    e++;\n  }\n  if (x < 8) return x;\n  else return ((e+1) << 3) | (cast_int(x) - 8);\n}\n\n\n/* converts back */\nint luaO_fb2int (int x) {\n  int e = (x >> 3) & 31;\n  if (e == 0) return x;\n  else return ((x & 7)+8) << (e - 1);\n}\n\n\nint luaO_log2 (unsigned int x) {\n  static const lu_byte log_2[256] = {\n    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,\n    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,\n    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,\n    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,\n    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,\n    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,\n    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,\n    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\n  };\n  int l = -1;\n  while (x >= 256) { l += 8; x >>= 8; }\n  return l + log_2[x];\n\n}\n\n\nint luaO_rawequalObj (const TValue *t1, const TValue *t2) {\n  if (ttype(t1) != ttype(t2)) return 0;\n  else switch (ttype(t1)) {\n    case LUA_TNIL:\n      return 1;\n    case LUA_TNUMBER:\n      return luai_numeq(nvalue(t1), nvalue(t2));\n    case LUA_TBOOLEAN:\n      return bvalue(t1) == bvalue(t2);  /* boolean true must be 1 !! */\n    case LUA_TLIGHTUSERDATA:\n      return pvalue(t1) == pvalue(t2);\n    default:\n      lua_assert(iscollectable(t1));\n      return gcvalue(t1) == gcvalue(t2);\n  }\n}\n\n\nint luaO_str2d (const char *s, lua_Number *result) {\n  char *endptr;\n  *result = lua_str2number(s, &endptr);\n  if (endptr == s) return 0;  /* conversion failed */\n  if (*endptr == 'x' || *endptr == 'X')  /* maybe an hexadecimal constant? */\n    *result = cast_num(strtoul(s, &endptr, 16));\n  if (*endptr == '\\0') return 1;  /* most common case */\n  while (isspace(cast(unsigned char, *endptr))) endptr++;\n  if (*endptr != '\\0') return 0;  /* invalid trailing characters? */\n  return 1;\n}\n\n\n\nstatic void pushstr (lua_State *L, const char *str) {\n  setsvalue2s(L, L->top, luaS_new(L, str));\n  incr_top(L);\n}\n\n\n/* this function handles only `%d', `%c', %f, %p, and `%s' formats */\nconst char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {\n  int n = 1;\n  pushstr(L, \"\");\n  for (;;) {\n    const char *e = strchr(fmt, '%');\n    if (e == NULL) break;\n    setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt));\n    incr_top(L);\n    switch (*(e+1)) {\n      case 's': {\n        const char *s = va_arg(argp, char *);\n        if (s == NULL) s = \"(null)\";\n        pushstr(L, s);\n        break;\n      }\n      case 'c': {\n        char buff[2];\n        buff[0] = cast(char, va_arg(argp, int));\n        buff[1] = '\\0';\n        pushstr(L, buff);\n        break;\n      }\n      case 'd': {\n        setnvalue(L->top, cast_num(va_arg(argp, int)));\n        incr_top(L);\n        break;\n      }\n      case 'f': {\n        setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber)));\n        incr_top(L);\n        break;\n      }\n      case 'p': {\n        char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */\n        sprintf(buff, \"%p\", va_arg(argp, void *));\n        pushstr(L, buff);\n        break;\n      }\n      case '%': {\n        pushstr(L, \"%\");\n        break;\n      }\n      default: {\n        char buff[3];\n        buff[0] = '%';\n        buff[1] = *(e+1);\n        buff[2] = '\\0';\n        pushstr(L, buff);\n        break;\n      }\n    }\n    n += 2;\n    fmt = e+2;\n  }\n  pushstr(L, fmt);\n  luaV_concat(L, n+1, cast_int(L->top - L->base) - 1);\n  L->top -= n;\n  return svalue(L->top - 1);\n}\n\n\nconst char *luaO_pushfstring (lua_State *L, const char *fmt, ...) {\n  const char *msg;\n  va_list argp;\n  va_start(argp, fmt);\n  msg = luaO_pushvfstring(L, fmt, argp);\n  va_end(argp);\n  return msg;\n}\n\n\nvoid luaO_chunkid (char *out, const char *source, size_t bufflen) {\n  if (*source == '=') {\n    strncpy(out, source+1, bufflen);  /* remove first char */\n    out[bufflen-1] = '\\0';  /* ensures null termination */\n  }\n  else {  /* out = \"source\", or \"...source\" */\n    if (*source == '@') {\n      size_t l;\n      source++;  /* skip the `@' */\n      bufflen -= sizeof(\" '...' \");\n      l = strlen(source);\n      strcpy(out, \"\");\n      if (l > bufflen) {\n        source += (l-bufflen);  /* get last part of file name */\n        strcat(out, \"...\");\n      }\n      strcat(out, source);\n    }\n    else {  /* out = [string \"string\"] */\n      size_t len = strcspn(source, \"\\n\\r\");  /* stop at first newline */\n      bufflen -= sizeof(\" [string \\\"...\\\"] \");\n      if (len > bufflen) len = bufflen;\n      strcpy(out, \"[string \\\"\");\n      if (source[len] != '\\0') {  /* must truncate? */\n        strncat(out, source, len);\n        strcat(out, \"...\");\n      }\n      else\n        strcat(out, source);\n      strcat(out, \"\\\"]\");\n    }\n  }\n}\n"
  },
  {
    "path": "src/lua/lobject.h",
    "content": "/*\n** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $\n** Type definitions for Lua objects\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lobject_h\n#define lobject_h\n\n\n#include <stdarg.h>\n\n\n#include \"llimits.h\"\n#include \"lua.h\"\n\n\n/* tags for values visible from Lua */\n#define LAST_TAG\tLUA_TTHREAD\n\n#define NUM_TAGS\t(LAST_TAG+1)\n\n\n/*\n** Extra tags for non-values\n*/\n#define LUA_TPROTO\t(LAST_TAG+1)\n#define LUA_TUPVAL\t(LAST_TAG+2)\n#define LUA_TDEADKEY\t(LAST_TAG+3)\n\n\n/*\n** Union of all collectable objects\n*/\ntypedef union GCObject GCObject;\n\n\n/*\n** Common Header for all collectable objects (in macro form, to be\n** included in other objects)\n*/\n#define CommonHeader\tGCObject *next; lu_byte tt; lu_byte marked\n\n\n/*\n** Common header in struct form\n*/\ntypedef struct GCheader {\n  CommonHeader;\n} GCheader;\n\n\n\n\n/*\n** Union of all Lua values\n*/\ntypedef union {\n  GCObject *gc;\n  void *p;\n  lua_Number n;\n  int b;\n} Value;\n\n\n/*\n** Tagged Values\n*/\n\n#define TValuefields\tValue value; int tt\n\ntypedef struct lua_TValue {\n  TValuefields;\n} TValue;\n\n\n/* Macros to test type */\n#define ttisnil(o)\t(ttype(o) == LUA_TNIL)\n#define ttisnumber(o)\t(ttype(o) == LUA_TNUMBER)\n#define ttisstring(o)\t(ttype(o) == LUA_TSTRING)\n#define ttistable(o)\t(ttype(o) == LUA_TTABLE)\n#define ttisfunction(o)\t(ttype(o) == LUA_TFUNCTION)\n#define ttisboolean(o)\t(ttype(o) == LUA_TBOOLEAN)\n#define ttisuserdata(o)\t(ttype(o) == LUA_TUSERDATA)\n#define ttisthread(o)\t(ttype(o) == LUA_TTHREAD)\n#define ttislightuserdata(o)\t(ttype(o) == LUA_TLIGHTUSERDATA)\n\n/* Macros to access values */\n#define ttype(o)\t((o)->tt)\n#define gcvalue(o)\tcheck_exp(iscollectable(o), (o)->value.gc)\n#define pvalue(o)\tcheck_exp(ttislightuserdata(o), (o)->value.p)\n#define nvalue(o)\tcheck_exp(ttisnumber(o), (o)->value.n)\n#define rawtsvalue(o)\tcheck_exp(ttisstring(o), &(o)->value.gc->ts)\n#define tsvalue(o)\t(&rawtsvalue(o)->tsv)\n#define rawuvalue(o)\tcheck_exp(ttisuserdata(o), &(o)->value.gc->u)\n#define uvalue(o)\t(&rawuvalue(o)->uv)\n#define clvalue(o)\tcheck_exp(ttisfunction(o), &(o)->value.gc->cl)\n#define hvalue(o)\tcheck_exp(ttistable(o), &(o)->value.gc->h)\n#define bvalue(o)\tcheck_exp(ttisboolean(o), (o)->value.b)\n#define thvalue(o)\tcheck_exp(ttisthread(o), &(o)->value.gc->th)\n\n#define l_isfalse(o)\t(ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0))\n\n/*\n** for internal debug only\n*/\n#define checkconsistency(obj) \\\n  lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt))\n\n#define checkliveness(g,obj) \\\n  lua_assert(!iscollectable(obj) || \\\n  ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc)))\n\n\n/* Macros to set values */\n#define setnilvalue(obj) ((obj)->tt=LUA_TNIL)\n\n#define setnvalue(obj,x) \\\n  { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; }\n\n#define setpvalue(obj,x) \\\n  { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; }\n\n#define setbvalue(obj,x) \\\n  { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; }\n\n#define setsvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \\\n    checkliveness(G(L),i_o); }\n\n#define setuvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \\\n    checkliveness(G(L),i_o); }\n\n#define setthvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \\\n    checkliveness(G(L),i_o); }\n\n#define setclvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \\\n    checkliveness(G(L),i_o); }\n\n#define sethvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \\\n    checkliveness(G(L),i_o); }\n\n#define setptvalue(L,obj,x) \\\n  { TValue *i_o=(obj); \\\n    i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \\\n    checkliveness(G(L),i_o); }\n\n\n\n\n#define setobj(L,obj1,obj2) \\\n  { const TValue *o2=(obj2); TValue *o1=(obj1); \\\n    o1->value = o2->value; o1->tt=o2->tt; \\\n    checkliveness(G(L),o1); }\n\n\n/*\n** different types of sets, according to destination\n*/\n\n/* from stack to (same) stack */\n#define setobjs2s\tsetobj\n/* to stack (not from same stack) */\n#define setobj2s\tsetobj\n#define setsvalue2s\tsetsvalue\n#define sethvalue2s\tsethvalue\n#define setptvalue2s\tsetptvalue\n/* from table to same table */\n#define setobjt2t\tsetobj\n/* to table */\n#define setobj2t\tsetobj\n/* to new object */\n#define setobj2n\tsetobj\n#define setsvalue2n\tsetsvalue\n\n#define setttype(obj, tt) (ttype(obj) = (tt))\n\n\n#define iscollectable(o)\t(ttype(o) >= LUA_TSTRING)\n\n\n\ntypedef TValue *StkId;  /* index to stack elements */\n\n\n/*\n** String headers for string table\n*/\ntypedef union TString {\n  L_Umaxalign dummy;  /* ensures maximum alignment for strings */\n  struct {\n    CommonHeader;\n    lu_byte reserved;\n    unsigned int hash;\n    size_t len;\n  } tsv;\n} TString;\n\n\n#define getstr(ts)\tcast(const char *, (ts) + 1)\n#define svalue(o)       getstr(rawtsvalue(o))\n\n\n\ntypedef union Udata {\n  L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */\n  struct {\n    CommonHeader;\n    struct Table *metatable;\n    struct Table *env;\n    size_t len;\n  } uv;\n} Udata;\n\n\n\n\n/*\n** Function Prototypes\n*/\ntypedef struct Proto {\n  CommonHeader;\n  TValue *k;  /* constants used by the function */\n  Instruction *code;\n  struct Proto **p;  /* functions defined inside the function */\n  int *lineinfo;  /* map from opcodes to source lines */\n  struct LocVar *locvars;  /* information about local variables */\n  TString **upvalues;  /* upvalue names */\n  TString  *source;\n  int sizeupvalues;\n  int sizek;  /* size of `k' */\n  int sizecode;\n  int sizelineinfo;\n  int sizep;  /* size of `p' */\n  int sizelocvars;\n  int linedefined;\n  int lastlinedefined;\n  GCObject *gclist;\n  lu_byte nups;  /* number of upvalues */\n  lu_byte numparams;\n  lu_byte is_vararg;\n  lu_byte maxstacksize;\n} Proto;\n\n\n/* masks for new-style vararg */\n#define VARARG_HASARG\t\t1\n#define VARARG_ISVARARG\t\t2\n#define VARARG_NEEDSARG\t\t4\n\n\ntypedef struct LocVar {\n  TString *varname;\n  int startpc;  /* first point where variable is active */\n  int endpc;    /* first point where variable is dead */\n} LocVar;\n\n\n\n/*\n** Upvalues\n*/\n\ntypedef struct UpVal {\n  CommonHeader;\n  TValue *v;  /* points to stack or to its own value */\n  union {\n    TValue value;  /* the value (when closed) */\n    struct {  /* double linked list (when open) */\n      struct UpVal *prev;\n      struct UpVal *next;\n    } l;\n  } u;\n} UpVal;\n\n\n/*\n** Closures\n*/\n\n#define ClosureHeader \\\n\tCommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \\\n\tstruct Table *env\n\ntypedef struct CClosure {\n  ClosureHeader;\n  lua_CFunction f;\n  TValue upvalue[1];\n} CClosure;\n\n\ntypedef struct LClosure {\n  ClosureHeader;\n  struct Proto *p;\n  UpVal *upvals[1];\n} LClosure;\n\n\ntypedef union Closure {\n  CClosure c;\n  LClosure l;\n} Closure;\n\n\n#define iscfunction(o)\t(ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC)\n#define isLfunction(o)\t(ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC)\n\n\n/*\n** Tables\n*/\n\ntypedef union TKey {\n  struct {\n    TValuefields;\n    struct Node *next;  /* for chaining */\n  } nk;\n  TValue tvk;\n} TKey;\n\n\ntypedef struct Node {\n  TValue i_val;\n  TKey i_key;\n} Node;\n\n\ntypedef struct Table {\n  CommonHeader;\n  lu_byte flags;  /* 1<<p means tagmethod(p) is not present */ \n  lu_byte lsizenode;  /* log2 of size of `node' array */\n  struct Table *metatable;\n  TValue *array;  /* array part */\n  Node *node;\n  Node *lastfree;  /* any free position is before this position */\n  GCObject *gclist;\n  int sizearray;  /* size of `array' array */\n} Table;\n\n\n\n/*\n** `module' operation for hashing (size is always a power of 2)\n*/\n#define lmod(s,size) \\\n\t(check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1)))))\n\n\n#define twoto(x)\t(1<<(x))\n#define sizenode(t)\t(twoto((t)->lsizenode))\n\n\n#define luaO_nilobject\t\t(&luaO_nilobject_)\n\nLUAI_DATA const TValue luaO_nilobject_;\n\n#define ceillog2(x)\t(luaO_log2((x)-1) + 1)\n\nLUAI_FUNC int luaO_log2 (unsigned int x);\nLUAI_FUNC int luaO_int2fb (unsigned int x);\nLUAI_FUNC int luaO_fb2int (int x);\nLUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2);\nLUAI_FUNC int luaO_str2d (const char *s, lua_Number *result);\nLUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt,\n                                                       va_list argp);\nLUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...);\nLUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len);\n\n\n#endif\n\n"
  },
  {
    "path": "src/lua/lopcodes.c",
    "content": "/*\n** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $\n** See Copyright Notice in lua.h\n*/\n\n\n#define lopcodes_c\n#define LUA_CORE\n\n\n#include \"lopcodes.h\"\n\n\n/* ORDER OP */\n\nconst char *const luaP_opnames[NUM_OPCODES+1] = {\n  \"MOVE\",\n  \"LOADK\",\n  \"LOADBOOL\",\n  \"LOADNIL\",\n  \"GETUPVAL\",\n  \"GETGLOBAL\",\n  \"GETTABLE\",\n  \"SETGLOBAL\",\n  \"SETUPVAL\",\n  \"SETTABLE\",\n  \"NEWTABLE\",\n  \"SELF\",\n  \"ADD\",\n  \"SUB\",\n  \"MUL\",\n  \"DIV\",\n  \"MOD\",\n  \"POW\",\n  \"UNM\",\n  \"NOT\",\n  \"LEN\",\n  \"CONCAT\",\n  \"JMP\",\n  \"EQ\",\n  \"LT\",\n  \"LE\",\n  \"TEST\",\n  \"TESTSET\",\n  \"CALL\",\n  \"TAILCALL\",\n  \"RETURN\",\n  \"FORLOOP\",\n  \"FORPREP\",\n  \"TFORLOOP\",\n  \"SETLIST\",\n  \"CLOSE\",\n  \"CLOSURE\",\n  \"VARARG\",\n  NULL\n};\n\n\n#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))\n\nconst lu_byte luaP_opmodes[NUM_OPCODES] = {\n/*       T  A    B       C     mode\t\t   opcode\t*/\n  opmode(0, 1, OpArgR, OpArgN, iABC) \t\t/* OP_MOVE */\n ,opmode(0, 1, OpArgK, OpArgN, iABx)\t\t/* OP_LOADK */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_LOADBOOL */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_LOADNIL */\n ,opmode(0, 1, OpArgU, OpArgN, iABC)\t\t/* OP_GETUPVAL */\n ,opmode(0, 1, OpArgK, OpArgN, iABx)\t\t/* OP_GETGLOBAL */\n ,opmode(0, 1, OpArgR, OpArgK, iABC)\t\t/* OP_GETTABLE */\n ,opmode(0, 0, OpArgK, OpArgN, iABx)\t\t/* OP_SETGLOBAL */\n ,opmode(0, 0, OpArgU, OpArgN, iABC)\t\t/* OP_SETUPVAL */\n ,opmode(0, 0, OpArgK, OpArgK, iABC)\t\t/* OP_SETTABLE */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_NEWTABLE */\n ,opmode(0, 1, OpArgR, OpArgK, iABC)\t\t/* OP_SELF */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_ADD */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_SUB */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_MUL */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_DIV */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_MOD */\n ,opmode(0, 1, OpArgK, OpArgK, iABC)\t\t/* OP_POW */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_UNM */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_NOT */\n ,opmode(0, 1, OpArgR, OpArgN, iABC)\t\t/* OP_LEN */\n ,opmode(0, 1, OpArgR, OpArgR, iABC)\t\t/* OP_CONCAT */\n ,opmode(0, 0, OpArgR, OpArgN, iAsBx)\t\t/* OP_JMP */\n ,opmode(1, 0, OpArgK, OpArgK, iABC)\t\t/* OP_EQ */\n ,opmode(1, 0, OpArgK, OpArgK, iABC)\t\t/* OP_LT */\n ,opmode(1, 0, OpArgK, OpArgK, iABC)\t\t/* OP_LE */\n ,opmode(1, 1, OpArgR, OpArgU, iABC)\t\t/* OP_TEST */\n ,opmode(1, 1, OpArgR, OpArgU, iABC)\t\t/* OP_TESTSET */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_CALL */\n ,opmode(0, 1, OpArgU, OpArgU, iABC)\t\t/* OP_TAILCALL */\n ,opmode(0, 0, OpArgU, OpArgN, iABC)\t\t/* OP_RETURN */\n ,opmode(0, 1, OpArgR, OpArgN, iAsBx)\t\t/* OP_FORLOOP */\n ,opmode(0, 1, OpArgR, OpArgN, iAsBx)\t\t/* OP_FORPREP */\n ,opmode(1, 0, OpArgN, OpArgU, iABC)\t\t/* OP_TFORLOOP */\n ,opmode(0, 0, OpArgU, OpArgU, iABC)\t\t/* OP_SETLIST */\n ,opmode(0, 0, OpArgN, OpArgN, iABC)\t\t/* OP_CLOSE */\n ,opmode(0, 1, OpArgU, OpArgN, iABx)\t\t/* OP_CLOSURE */\n ,opmode(0, 1, OpArgU, OpArgN, iABC)\t\t/* OP_VARARG */\n};\n\n"
  },
  {
    "path": "src/lua/lopcodes.h",
    "content": "/*\n** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $\n** Opcodes for Lua virtual machine\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lopcodes_h\n#define lopcodes_h\n\n#include \"llimits.h\"\n\n\n/*===========================================================================\n  We assume that instructions are unsigned numbers.\n  All instructions have an opcode in the first 6 bits.\n  Instructions can have the following fields:\n\t`A' : 8 bits\n\t`B' : 9 bits\n\t`C' : 9 bits\n\t`Bx' : 18 bits (`B' and `C' together)\n\t`sBx' : signed Bx\n\n  A signed argument is represented in excess K; that is, the number\n  value is the unsigned value minus K. K is exactly the maximum value\n  for that argument (so that -max is represented by 0, and +max is\n  represented by 2*max), which is half the maximum for the corresponding\n  unsigned argument.\n===========================================================================*/\n\n\nenum OpMode {iABC, iABx, iAsBx};  /* basic instruction format */\n\n\n/*\n** size and position of opcode arguments.\n*/\n#define SIZE_C\t\t9\n#define SIZE_B\t\t9\n#define SIZE_Bx\t\t(SIZE_C + SIZE_B)\n#define SIZE_A\t\t8\n\n#define SIZE_OP\t\t6\n\n#define POS_OP\t\t0\n#define POS_A\t\t(POS_OP + SIZE_OP)\n#define POS_C\t\t(POS_A + SIZE_A)\n#define POS_B\t\t(POS_C + SIZE_C)\n#define POS_Bx\t\tPOS_C\n\n\n/*\n** limits for opcode arguments.\n** we use (signed) int to manipulate most arguments,\n** so they must fit in LUAI_BITSINT-1 bits (-1 for sign)\n*/\n#if SIZE_Bx < LUAI_BITSINT-1\n#define MAXARG_Bx        ((1<<SIZE_Bx)-1)\n#define MAXARG_sBx        (MAXARG_Bx>>1)         /* `sBx' is signed */\n#else\n#define MAXARG_Bx        MAX_INT\n#define MAXARG_sBx        MAX_INT\n#endif\n\n\n#define MAXARG_A        ((1<<SIZE_A)-1)\n#define MAXARG_B        ((1<<SIZE_B)-1)\n#define MAXARG_C        ((1<<SIZE_C)-1)\n\n\n/* creates a mask with `n' 1 bits at position `p' */\n#define MASK1(n,p)\t((~((~(Instruction)0)<<n))<<p)\n\n/* creates a mask with `n' 0 bits at position `p' */\n#define MASK0(n,p)\t(~MASK1(n,p))\n\n/*\n** the following macros help to manipulate instructions\n*/\n\n#define GET_OPCODE(i)\t(cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0)))\n#define SET_OPCODE(i,o)\t((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \\\n\t\t((cast(Instruction, o)<<POS_OP)&MASK1(SIZE_OP,POS_OP))))\n\n#define GETARG_A(i)\t(cast(int, ((i)>>POS_A) & MASK1(SIZE_A,0)))\n#define SETARG_A(i,u)\t((i) = (((i)&MASK0(SIZE_A,POS_A)) | \\\n\t\t((cast(Instruction, u)<<POS_A)&MASK1(SIZE_A,POS_A))))\n\n#define GETARG_B(i)\t(cast(int, ((i)>>POS_B) & MASK1(SIZE_B,0)))\n#define SETARG_B(i,b)\t((i) = (((i)&MASK0(SIZE_B,POS_B)) | \\\n\t\t((cast(Instruction, b)<<POS_B)&MASK1(SIZE_B,POS_B))))\n\n#define GETARG_C(i)\t(cast(int, ((i)>>POS_C) & MASK1(SIZE_C,0)))\n#define SETARG_C(i,b)\t((i) = (((i)&MASK0(SIZE_C,POS_C)) | \\\n\t\t((cast(Instruction, b)<<POS_C)&MASK1(SIZE_C,POS_C))))\n\n#define GETARG_Bx(i)\t(cast(int, ((i)>>POS_Bx) & MASK1(SIZE_Bx,0)))\n#define SETARG_Bx(i,b)\t((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \\\n\t\t((cast(Instruction, b)<<POS_Bx)&MASK1(SIZE_Bx,POS_Bx))))\n\n#define GETARG_sBx(i)\t(GETARG_Bx(i)-MAXARG_sBx)\n#define SETARG_sBx(i,b)\tSETARG_Bx((i),cast(unsigned int, (b)+MAXARG_sBx))\n\n\n#define CREATE_ABC(o,a,b,c)\t((cast(Instruction, o)<<POS_OP) \\\n\t\t\t| (cast(Instruction, a)<<POS_A) \\\n\t\t\t| (cast(Instruction, b)<<POS_B) \\\n\t\t\t| (cast(Instruction, c)<<POS_C))\n\n#define CREATE_ABx(o,a,bc)\t((cast(Instruction, o)<<POS_OP) \\\n\t\t\t| (cast(Instruction, a)<<POS_A) \\\n\t\t\t| (cast(Instruction, bc)<<POS_Bx))\n\n\n/*\n** Macros to operate RK indices\n*/\n\n/* this bit 1 means constant (0 means register) */\n#define BITRK\t\t(1 << (SIZE_B - 1))\n\n/* test whether value is a constant */\n#define ISK(x)\t\t((x) & BITRK)\n\n/* gets the index of the constant */\n#define INDEXK(r)\t((int)(r) & ~BITRK)\n\n#define MAXINDEXRK\t(BITRK - 1)\n\n/* code a constant index as a RK value */\n#define RKASK(x)\t((x) | BITRK)\n\n\n/*\n** invalid register that fits in 8 bits\n*/\n#define NO_REG\t\tMAXARG_A\n\n\n/*\n** R(x) - register\n** Kst(x) - constant (in constant table)\n** RK(x) == if ISK(x) then Kst(INDEXK(x)) else R(x)\n*/\n\n\n/*\n** grep \"ORDER OP\" if you change these enums\n*/\n\ntypedef enum {\n/*----------------------------------------------------------------------\nname\t\targs\tdescription\n------------------------------------------------------------------------*/\nOP_MOVE,/*\tA B\tR(A) := R(B)\t\t\t\t\t*/\nOP_LOADK,/*\tA Bx\tR(A) := Kst(Bx)\t\t\t\t\t*/\nOP_LOADBOOL,/*\tA B C\tR(A) := (Bool)B; if (C) pc++\t\t\t*/\nOP_LOADNIL,/*\tA B\tR(A) := ... := R(B) := nil\t\t\t*/\nOP_GETUPVAL,/*\tA B\tR(A) := UpValue[B]\t\t\t\t*/\n\nOP_GETGLOBAL,/*\tA Bx\tR(A) := Gbl[Kst(Bx)]\t\t\t\t*/\nOP_GETTABLE,/*\tA B C\tR(A) := R(B)[RK(C)]\t\t\t\t*/\n\nOP_SETGLOBAL,/*\tA Bx\tGbl[Kst(Bx)] := R(A)\t\t\t\t*/\nOP_SETUPVAL,/*\tA B\tUpValue[B] := R(A)\t\t\t\t*/\nOP_SETTABLE,/*\tA B C\tR(A)[RK(B)] := RK(C)\t\t\t\t*/\n\nOP_NEWTABLE,/*\tA B C\tR(A) := {} (size = B,C)\t\t\t\t*/\n\nOP_SELF,/*\tA B C\tR(A+1) := R(B); R(A) := R(B)[RK(C)]\t\t*/\n\nOP_ADD,/*\tA B C\tR(A) := RK(B) + RK(C)\t\t\t\t*/\nOP_SUB,/*\tA B C\tR(A) := RK(B) - RK(C)\t\t\t\t*/\nOP_MUL,/*\tA B C\tR(A) := RK(B) * RK(C)\t\t\t\t*/\nOP_DIV,/*\tA B C\tR(A) := RK(B) / RK(C)\t\t\t\t*/\nOP_MOD,/*\tA B C\tR(A) := RK(B) % RK(C)\t\t\t\t*/\nOP_POW,/*\tA B C\tR(A) := RK(B) ^ RK(C)\t\t\t\t*/\nOP_UNM,/*\tA B\tR(A) := -R(B)\t\t\t\t\t*/\nOP_NOT,/*\tA B\tR(A) := not R(B)\t\t\t\t*/\nOP_LEN,/*\tA B\tR(A) := length of R(B)\t\t\t\t*/\n\nOP_CONCAT,/*\tA B C\tR(A) := R(B).. ... ..R(C)\t\t\t*/\n\nOP_JMP,/*\tsBx\tpc+=sBx\t\t\t\t\t*/\n\nOP_EQ,/*\tA B C\tif ((RK(B) == RK(C)) ~= A) then pc++\t\t*/\nOP_LT,/*\tA B C\tif ((RK(B) <  RK(C)) ~= A) then pc++  \t\t*/\nOP_LE,/*\tA B C\tif ((RK(B) <= RK(C)) ~= A) then pc++  \t\t*/\n\nOP_TEST,/*\tA C\tif not (R(A) <=> C) then pc++\t\t\t*/ \nOP_TESTSET,/*\tA B C\tif (R(B) <=> C) then R(A) := R(B) else pc++\t*/ \n\nOP_CALL,/*\tA B C\tR(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */\nOP_TAILCALL,/*\tA B C\treturn R(A)(R(A+1), ... ,R(A+B-1))\t\t*/\nOP_RETURN,/*\tA B\treturn R(A), ... ,R(A+B-2)\t(see note)\t*/\n\nOP_FORLOOP,/*\tA sBx\tR(A)+=R(A+2);\n\t\t\tif R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/\nOP_FORPREP,/*\tA sBx\tR(A)-=R(A+2); pc+=sBx\t\t\t\t*/\n\nOP_TFORLOOP,/*\tA C\tR(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2)); \n                        if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++\t*/ \nOP_SETLIST,/*\tA B C\tR(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B\t*/\n\nOP_CLOSE,/*\tA \tclose all variables in the stack up to (>=) R(A)*/\nOP_CLOSURE,/*\tA Bx\tR(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))\t*/\n\nOP_VARARG/*\tA B\tR(A), R(A+1), ..., R(A+B-1) = vararg\t\t*/\n} OpCode;\n\n\n#define NUM_OPCODES\t(cast(int, OP_VARARG) + 1)\n\n\n\n/*===========================================================================\n  Notes:\n  (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1,\n      and can be 0: OP_CALL then sets `top' to last_result+1, so\n      next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'.\n\n  (*) In OP_VARARG, if (B == 0) then use actual number of varargs and\n      set top (like in OP_CALL with C == 0).\n\n  (*) In OP_RETURN, if (B == 0) then return up to `top'\n\n  (*) In OP_SETLIST, if (B == 0) then B = `top';\n      if (C == 0) then next `instruction' is real C\n\n  (*) For comparisons, A specifies what condition the test should accept\n      (true or false).\n\n  (*) All `skips' (pc++) assume that next instruction is a jump\n===========================================================================*/\n\n\n/*\n** masks for instruction properties. The format is:\n** bits 0-1: op mode\n** bits 2-3: C arg mode\n** bits 4-5: B arg mode\n** bit 6: instruction set register A\n** bit 7: operator is a test\n*/  \n\nenum OpArgMask {\n  OpArgN,  /* argument is not used */\n  OpArgU,  /* argument is used */\n  OpArgR,  /* argument is a register or a jump offset */\n  OpArgK   /* argument is a constant or register/constant */\n};\n\nLUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES];\n\n#define getOpMode(m)\t(cast(enum OpMode, luaP_opmodes[m] & 3))\n#define getBMode(m)\t(cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3))\n#define getCMode(m)\t(cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3))\n#define testAMode(m)\t(luaP_opmodes[m] & (1 << 6))\n#define testTMode(m)\t(luaP_opmodes[m] & (1 << 7))\n\n\nLUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1];  /* opcode names */\n\n\n/* number of list items to accumulate before a SETLIST instruction */\n#define LFIELDS_PER_FLUSH\t50\n\n\n#endif\n"
  },
  {
    "path": "src/lua/loslib.c",
    "content": "/*\n** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $\n** Standard Operating System library\n** See Copyright Notice in lua.h\n*/\n\n\n#include <errno.h>\n#include <locale.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#define loslib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\nstatic int os_pushresult (lua_State *L, int i, const char *filename) {\n  int en = errno;  /* calls to Lua API may change this value */\n  if (i) {\n    lua_pushboolean(L, 1);\n    return 1;\n  }\n  else {\n    lua_pushnil(L);\n    lua_pushfstring(L, \"%s: %s\", filename, strerror(en));\n    lua_pushinteger(L, en);\n    return 3;\n  }\n}\n/*\n** list of valid conversion specifiers for the 'strftime' function\n*/\n#if !defined(LUA_STRFTIMEOPTIONS)\n\n#if !defined(LUA_USE_POSIX)\n#define LUA_STRFTIMEOPTIONS\t{ \"aAbBcdHIjmMpSUwWxXyYzZ%\", \"\" }\n#else\n#define LUA_STRFTIMEOPTIONS \\\n\t{ \"aAbBcCdDeFgGhHIjklmMnprRSstTuUVwWxXyYzZ%\", \"\" \\\n\t  \"\", \"E\", \"cCxXyY\",  \\\n\t  \"O\", \"deHImMSuUVwWy\" }\n#endif\n\n#endif\n\n\n\n/*\n** By default, Lua uses tmpnam except when POSIX is available, where it\n** uses mkstemp.\n*/\n#if defined(LUA_USE_MKSTEMP)\n#include <unistd.h>\n#define LUA_TMPNAMBUFSIZE\t32\n#define lua_tmpnam(b,e) { \\\n        strcpy(b, \"/tmp/lua_XXXXXX\"); \\\n        e = mkstemp(b); \\\n        if (e != -1) close(e); \\\n        e = (e == -1); }\n\n#elif !defined(lua_tmpnam)\n\n#define LUA_TMPNAMBUFSIZE\tL_tmpnam\n#define lua_tmpnam(b,e)\t\t{ e = (tmpnam(b) == NULL); }\n\n#endif\n\n\n/*\n** By default, Lua uses gmtime/localtime, except when POSIX is available,\n** where it uses gmtime_r/localtime_r\n*/\n#if defined(LUA_USE_GMTIME_R)\n\n#define l_gmtime(t,r)\t\tgmtime_r(t,r)\n#define l_localtime(t,r)\tlocaltime_r(t,r)\n\n#elif !defined(l_gmtime)\n\n#define l_gmtime(t,r)\t\t((void)r, gmtime(t))\n#define l_localtime(t,r)  \t((void)r, localtime(t))\n\n#endif\n\n\n\nstatic int os_execute (lua_State *L) {\n  lua_pushinteger(L, system(luaL_optstring(L, 1, NULL)));\n  return 1;\n}\n\n\nstatic int os_remove (lua_State *L) {\n  const char *filename = luaL_checkstring(L, 1);\n  return os_pushresult(L, remove(filename) == 0, filename);\n}\n\n\nstatic int os_rename (lua_State *L) {\n  const char *fromname = luaL_checkstring(L, 1);\n  const char *toname = luaL_checkstring(L, 2);\n  return os_pushresult(L, rename(fromname, toname) == 0, fromname);\n}\n\n\nstatic int os_tmpname (lua_State *L) {\n  char buff[LUA_TMPNAMBUFSIZE];\n  int err;\n  lua_tmpnam(buff, err);\n  if (err)\n    return luaL_error(L, \"unable to generate a unique filename\");\n  lua_pushstring(L, buff);\n  return 1;\n}\n\n\nstatic int os_getenv (lua_State *L) {\n  lua_pushstring(L, getenv(luaL_checkstring(L, 1)));  /* if NULL push nil */\n  return 1;\n}\n\n\nstatic int os_clock (lua_State *L) {\n  lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC);\n  return 1;\n}\n\n\n/*\n** {======================================================\n** Time/Date operations\n** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S,\n**   wday=%w+1, yday=%j, isdst=? }\n** =======================================================\n*/\n\nstatic void setfield (lua_State *L, const char *key, int value) {\n  lua_pushinteger(L, value);\n  lua_setfield(L, -2, key);\n}\n\nstatic void setboolfield (lua_State *L, const char *key, int value) {\n  if (value < 0)  /* undefined? */\n    return;  /* does not set field */\n  lua_pushboolean(L, value);\n  lua_setfield(L, -2, key);\n}\n\nstatic int getboolfield (lua_State *L, const char *key) {\n  int res;\n  lua_getfield(L, -1, key);\n  res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1);\n  lua_pop(L, 1);\n  return res;\n}\n\n\nstatic int getfield (lua_State *L, const char *key, int d) {\n  int res;\n  lua_getfield(L, -1, key);\n  if (lua_isnumber(L, -1))\n    res = (int)lua_tointeger(L, -1);\n  else {\n    if (d < 0)\n      return luaL_error(L, \"field \" LUA_QS \" missing in date table\", key);\n    res = d;\n  }\n  lua_pop(L, 1);\n  return res;\n}\n\n\nstatic const char *checkoption (lua_State *L, const char *conv, char *buff) {\n  static const char *const options[] = LUA_STRFTIMEOPTIONS;\n  unsigned int i;\n  for (i = 0; i < sizeof(options)/sizeof(options[0]); i += 2) {\n    if (*conv != '\\0' && strchr(options[i], *conv) != NULL) {\n      buff[1] = *conv;\n      if (*options[i + 1] == '\\0') {  /* one-char conversion specifier? */\n        buff[2] = '\\0';  /* end buffer */\n        return conv + 1;\n      }\n      else if (*(conv + 1) != '\\0' &&\n               strchr(options[i + 1], *(conv + 1)) != NULL) {\n        buff[2] = *(conv + 1);  /* valid two-char conversion specifier */\n        buff[3] = '\\0';  /* end buffer */\n        return conv + 2;\n      }\n    }\n  }\n  luaL_argerror(L, 1,\n    lua_pushfstring(L, \"invalid conversion specifier '%%%s'\", conv));\n  return conv;  /* to avoid warnings */\n}\n\n\nstatic int os_date (lua_State *L) {\n  const char *s = luaL_optstring(L, 1, \"%c\");\n  time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL));\n  struct tm tmr, *stm;\n  if (*s == '!') {  /* UTC? */\n    stm = l_gmtime(&t, &tmr);\n    s++;  /* skip `!' */\n  }\n  else\n    stm = l_localtime(&t, &tmr);\n  if (stm == NULL)  /* invalid date? */\n    lua_pushnil(L);\n  else if (strcmp(s, \"*t\") == 0) {\n    lua_createtable(L, 0, 9);  /* 9 = number of fields */\n    setfield(L, \"sec\", stm->tm_sec);\n    setfield(L, \"min\", stm->tm_min);\n    setfield(L, \"hour\", stm->tm_hour);\n    setfield(L, \"day\", stm->tm_mday);\n    setfield(L, \"month\", stm->tm_mon+1);\n    setfield(L, \"year\", stm->tm_year+1900);\n    setfield(L, \"wday\", stm->tm_wday+1);\n    setfield(L, \"yday\", stm->tm_yday+1);\n    setboolfield(L, \"isdst\", stm->tm_isdst);\n  }\n  else {\n    char cc[4];\n    luaL_Buffer b;\n    cc[0] = '%';\n    luaL_buffinit(L, &b);\n    while (*s) {\n      if (*s != '%')  /* no conversion specifier? */\n        luaL_addchar(&b, *s++);\n      else {\n        size_t reslen;\n        char buff[200];  /* should be big enough for any conversion result */\n        s = checkoption(L, s + 1, cc);\n        reslen = strftime(buff, sizeof(buff), cc, stm);\n        luaL_addlstring(&b, buff, reslen);\n      }\n    }\n    luaL_pushresult(&b);\n  }\n  return 1;\n}\n\n\nstatic int os_time (lua_State *L) {\n  time_t t;\n  if (lua_isnoneornil(L, 1))  /* called without args? */\n    t = time(NULL);  /* get current time */\n  else {\n    struct tm ts;\n    luaL_checktype(L, 1, LUA_TTABLE);\n    lua_settop(L, 1);  /* make sure table is at the top */\n    ts.tm_sec = getfield(L, \"sec\", 0);\n    ts.tm_min = getfield(L, \"min\", 0);\n    ts.tm_hour = getfield(L, \"hour\", 12);\n    ts.tm_mday = getfield(L, \"day\", -1);\n    ts.tm_mon = getfield(L, \"month\", -1) - 1;\n    ts.tm_year = getfield(L, \"year\", -1) - 1900;\n    ts.tm_isdst = getboolfield(L, \"isdst\");\n    t = mktime(&ts);\n  }\n  if (t == (time_t)(-1))\n    lua_pushnil(L);\n  else\n    lua_pushnumber(L, (lua_Number)t);\n  return 1;\n}\n\n\nstatic int os_difftime (lua_State *L) {\n  lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)),\n                             (time_t)(luaL_optnumber(L, 2, 0))));\n  return 1;\n}\n\n/* }====================================================== */\n\n\nstatic int os_setlocale (lua_State *L) {\n  static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,\n                      LC_NUMERIC, LC_TIME};\n  static const char *const catnames[] = {\"all\", \"collate\", \"ctype\", \"monetary\",\n     \"numeric\", \"time\", NULL};\n  const char *l = luaL_optstring(L, 1, NULL);\n  int op = luaL_checkoption(L, 2, \"all\", catnames);\n  lua_pushstring(L, setlocale(cat[op], l));\n  return 1;\n}\n\n\nstatic int os_exit (lua_State *L) {\n  exit(luaL_optint(L, 1, EXIT_SUCCESS));\n}\n\nstatic const luaL_Reg syslib[] = {\n  {\"clock\",     os_clock},\n  {\"date\",      os_date},\n  {\"difftime\",  os_difftime},\n  {\"execute\",   os_execute},\n  {\"exit\",      os_exit},\n  {\"getenv\",    os_getenv},\n  {\"remove\",    os_remove},\n  {\"rename\",    os_rename},\n  {\"setlocale\", os_setlocale},\n  {\"time\",      os_time},\n  {\"tmpname\",   os_tmpname},\n  {NULL, NULL}\n};\n\n/* }====================================================== */\n\n\n\nLUALIB_API int luaopen_os (lua_State *L) {\n  luaL_register(L, LUA_OSLIBNAME, syslib);\n  return 1;\n}\n\n"
  },
  {
    "path": "src/lua/lparser.c",
    "content": "/*\n** $Id: lparser.c,v 2.42.1.4 2011/10/21 19:31:42 roberto Exp $\n** Lua Parser\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define lparser_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lcode.h\"\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"llex.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lparser.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n\n\n\n#define hasmultret(k)\t\t((k) == VCALL || (k) == VVARARG)\n\n#define getlocvar(fs, i)\t((fs)->f->locvars[(fs)->actvar[i]])\n\n#define luaY_checklimit(fs,v,l,m)\tif ((v)>(l)) errorlimit(fs,l,m)\n\n\n/*\n** nodes for block list (list of active blocks)\n*/\ntypedef struct BlockCnt {\n  struct BlockCnt *previous;  /* chain */\n  int breaklist;  /* list of jumps out of this loop */\n  lu_byte nactvar;  /* # active locals outside the breakable structure */\n  lu_byte upval;  /* true if some variable in the block is an upvalue */\n  lu_byte isbreakable;  /* true if `block' is a loop */\n} BlockCnt;\n\n\n\n/*\n** prototypes for recursive non-terminal functions\n*/\nstatic void chunk (LexState *ls);\nstatic void expr (LexState *ls, expdesc *v);\n\n\nstatic void anchor_token (LexState *ls) {\n  if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) {\n    TString *ts = ls->t.seminfo.ts;\n    luaX_newstring(ls, getstr(ts), ts->tsv.len);\n  }\n}\n\n\nstatic void error_expected (LexState *ls, int token) {\n  luaX_syntaxerror(ls,\n      luaO_pushfstring(ls->L, LUA_QS \" expected\", luaX_token2str(ls, token)));\n}\n\n\nstatic void errorlimit (FuncState *fs, int limit, const char *what) {\n  const char *msg = (fs->f->linedefined == 0) ?\n    luaO_pushfstring(fs->L, \"main function has more than %d %s\", limit, what) :\n    luaO_pushfstring(fs->L, \"function at line %d has more than %d %s\",\n                            fs->f->linedefined, limit, what);\n  luaX_lexerror(fs->ls, msg, 0);\n}\n\n\nstatic int testnext (LexState *ls, int c) {\n  if (ls->t.token == c) {\n    luaX_next(ls);\n    return 1;\n  }\n  else return 0;\n}\n\n\nstatic void check (LexState *ls, int c) {\n  if (ls->t.token != c)\n    error_expected(ls, c);\n}\n\nstatic void checknext (LexState *ls, int c) {\n  check(ls, c);\n  luaX_next(ls);\n}\n\n\n#define check_condition(ls,c,msg)\t{ if (!(c)) luaX_syntaxerror(ls, msg); }\n\n\n\nstatic void check_match (LexState *ls, int what, int who, int where) {\n  if (!testnext(ls, what)) {\n    if (where == ls->linenumber)\n      error_expected(ls, what);\n    else {\n      luaX_syntaxerror(ls, luaO_pushfstring(ls->L,\n             LUA_QS \" expected (to close \" LUA_QS \" at line %d)\",\n              luaX_token2str(ls, what), luaX_token2str(ls, who), where));\n    }\n  }\n}\n\n\nstatic TString *str_checkname (LexState *ls) {\n  TString *ts;\n  check(ls, TK_NAME);\n  ts = ls->t.seminfo.ts;\n  luaX_next(ls);\n  return ts;\n}\n\n\nstatic void init_exp (expdesc *e, expkind k, int i) {\n  e->f = e->t = NO_JUMP;\n  e->k = k;\n  e->u.s.info = i;\n}\n\n\nstatic void codestring (LexState *ls, expdesc *e, TString *s) {\n  init_exp(e, VK, luaK_stringK(ls->fs, s));\n}\n\n\nstatic void checkname(LexState *ls, expdesc *e) {\n  codestring(ls, e, str_checkname(ls));\n}\n\n\nstatic int registerlocalvar (LexState *ls, TString *varname) {\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  int oldsize = f->sizelocvars;\n  luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars,\n                  LocVar, SHRT_MAX, \"too many local variables\");\n  while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL;\n  f->locvars[fs->nlocvars].varname = varname;\n  luaC_objbarrier(ls->L, f, varname);\n  return fs->nlocvars++;\n}\n\n\n#define new_localvarliteral(ls,v,n) \\\n  new_localvar(ls, luaX_newstring(ls, \"\" v, (sizeof(v)/sizeof(char))-1), n)\n\n\nstatic void new_localvar (LexState *ls, TString *name, int n) {\n  FuncState *fs = ls->fs;\n  luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, \"local variables\");\n  fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name));\n}\n\n\nstatic void adjustlocalvars (LexState *ls, int nvars) {\n  FuncState *fs = ls->fs;\n  fs->nactvar = cast_byte(fs->nactvar + nvars);\n  for (; nvars; nvars--) {\n    getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc;\n  }\n}\n\n\nstatic void removevars (LexState *ls, int tolevel) {\n  FuncState *fs = ls->fs;\n  while (fs->nactvar > tolevel)\n    getlocvar(fs, --fs->nactvar).endpc = fs->pc;\n}\n\n\nstatic int indexupvalue (FuncState *fs, TString *name, expdesc *v) {\n  int i;\n  Proto *f = fs->f;\n  int oldsize = f->sizeupvalues;\n  for (i=0; i<f->nups; i++) {\n    if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) {\n      lua_assert(f->upvalues[i] == name);\n      return i;\n    }\n  }\n  /* new one */\n  luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, \"upvalues\");\n  luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues,\n                  TString *, MAX_INT, \"\");\n  while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL;\n  f->upvalues[f->nups] = name;\n  luaC_objbarrier(fs->L, f, name);\n  lua_assert(v->k == VLOCAL || v->k == VUPVAL);\n  fs->upvalues[f->nups].k = cast_byte(v->k);\n  fs->upvalues[f->nups].info = cast_byte(v->u.s.info);\n  return f->nups++;\n}\n\n\nstatic int searchvar (FuncState *fs, TString *n) {\n  int i;\n  for (i=fs->nactvar-1; i >= 0; i--) {\n    if (n == getlocvar(fs, i).varname)\n      return i;\n  }\n  return -1;  /* not found */\n}\n\n\nstatic void markupval (FuncState *fs, int level) {\n  BlockCnt *bl = fs->bl;\n  while (bl && bl->nactvar > level) bl = bl->previous;\n  if (bl) bl->upval = 1;\n}\n\n\nstatic int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {\n  if (fs == NULL) {  /* no more levels? */\n    init_exp(var, VGLOBAL, NO_REG);  /* default is global variable */\n    return VGLOBAL;\n  }\n  else {\n    int v = searchvar(fs, n);  /* look up at current level */\n    if (v >= 0) {\n      init_exp(var, VLOCAL, v);\n      if (!base)\n        markupval(fs, v);  /* local will be used as an upval */\n      return VLOCAL;\n    }\n    else {  /* not found at current level; try upper one */\n      if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL)\n        return VGLOBAL;\n      var->u.s.info = indexupvalue(fs, n, var);  /* else was LOCAL or UPVAL */\n      var->k = VUPVAL;  /* upvalue in this level */\n      return VUPVAL;\n    }\n  }\n}\n\n\nstatic void singlevar (LexState *ls, expdesc *var) {\n  TString *varname = str_checkname(ls);\n  FuncState *fs = ls->fs;\n  if (singlevaraux(fs, varname, var, 1) == VGLOBAL)\n    var->u.s.info = luaK_stringK(fs, varname);  /* info points to global name */\n}\n\n\nstatic void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {\n  FuncState *fs = ls->fs;\n  int extra = nvars - nexps;\n  if (hasmultret(e->k)) {\n    extra++;  /* includes call itself */\n    if (extra < 0) extra = 0;\n    luaK_setreturns(fs, e, extra);  /* last exp. provides the difference */\n    if (extra > 1) luaK_reserveregs(fs, extra-1);\n  }\n  else {\n    if (e->k != VVOID) luaK_exp2nextreg(fs, e);  /* close last expression */\n    if (extra > 0) {\n      int reg = fs->freereg;\n      luaK_reserveregs(fs, extra);\n      luaK_nil(fs, reg, extra);\n    }\n  }\n}\n\n\nstatic void enterlevel (LexState *ls) {\n  if (++ls->L->nCcalls > LUAI_MAXCCALLS)\n\tluaX_lexerror(ls, \"chunk has too many syntax levels\", 0);\n}\n\n\n#define leavelevel(ls)\t((ls)->L->nCcalls--)\n\n\nstatic void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) {\n  bl->breaklist = NO_JUMP;\n  bl->isbreakable = isbreakable;\n  bl->nactvar = fs->nactvar;\n  bl->upval = 0;\n  bl->previous = fs->bl;\n  fs->bl = bl;\n  lua_assert(fs->freereg == fs->nactvar);\n}\n\n\nstatic void leaveblock (FuncState *fs) {\n  BlockCnt *bl = fs->bl;\n  fs->bl = bl->previous;\n  removevars(fs->ls, bl->nactvar);\n  if (bl->upval)\n    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);\n  /* a block either controls scope or breaks (never both) */\n  lua_assert(!bl->isbreakable || !bl->upval);\n  lua_assert(bl->nactvar == fs->nactvar);\n  fs->freereg = fs->nactvar;  /* free registers */\n  luaK_patchtohere(fs, bl->breaklist);\n}\n\n\nstatic void pushclosure (LexState *ls, FuncState *func, expdesc *v) {\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  int oldsize = f->sizep;\n  int i;\n  luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *,\n                  MAXARG_Bx, \"constant table overflow\");\n  while (oldsize < f->sizep) f->p[oldsize++] = NULL;\n  f->p[fs->np++] = func->f;\n  luaC_objbarrier(ls->L, f, func->f);\n  init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1));\n  for (i=0; i<func->f->nups; i++) {\n    OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL;\n    luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0);\n  }\n}\n\n\nstatic void open_func (LexState *ls, FuncState *fs) {\n  lua_State *L = ls->L;\n  Proto *f = luaF_newproto(L);\n  fs->f = f;\n  fs->prev = ls->fs;  /* linked list of funcstates */\n  fs->ls = ls;\n  fs->L = L;\n  ls->fs = fs;\n  fs->pc = 0;\n  fs->lasttarget = -1;\n  fs->jpc = NO_JUMP;\n  fs->freereg = 0;\n  fs->nk = 0;\n  fs->np = 0;\n  fs->nlocvars = 0;\n  fs->nactvar = 0;\n  fs->bl = NULL;\n  f->source = ls->source;\n  f->maxstacksize = 2;  /* registers 0/1 are always valid */\n  fs->h = luaH_new(L, 0, 0);\n  /* anchor table of constants and prototype (to avoid being collected) */\n  sethvalue2s(L, L->top, fs->h);\n  incr_top(L);\n  setptvalue2s(L, L->top, f);\n  incr_top(L);\n}\n\n\nstatic void close_func (LexState *ls) {\n  lua_State *L = ls->L;\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  removevars(ls, 0);\n  luaK_ret(fs, 0, 0);  /* final return */\n  luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction);\n  f->sizecode = fs->pc;\n  luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int);\n  f->sizelineinfo = fs->pc;\n  luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue);\n  f->sizek = fs->nk;\n  luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *);\n  f->sizep = fs->np;\n  luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar);\n  f->sizelocvars = fs->nlocvars;\n  luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *);\n  f->sizeupvalues = f->nups;\n  lua_assert(luaG_checkcode(f));\n  lua_assert(fs->bl == NULL);\n  ls->fs = fs->prev;\n  /* last token read was anchored in defunct function; must reanchor it */\n  if (fs) anchor_token(ls);\n  L->top -= 2;  /* remove table and prototype from the stack */\n}\n\n\nProto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) {\n  struct LexState lexstate;\n  struct FuncState funcstate;\n  lexstate.buff = buff;\n  luaX_setinput(L, &lexstate, z, luaS_new(L, name));\n  open_func(&lexstate, &funcstate);\n  funcstate.f->is_vararg = VARARG_ISVARARG;  /* main func. is always vararg */\n  luaX_next(&lexstate);  /* read first token */\n  chunk(&lexstate);\n  check(&lexstate, TK_EOS);\n  close_func(&lexstate);\n  lua_assert(funcstate.prev == NULL);\n  lua_assert(funcstate.f->nups == 0);\n  lua_assert(lexstate.fs == NULL);\n  return funcstate.f;\n}\n\n\n\n/*============================================================*/\n/* GRAMMAR RULES */\n/*============================================================*/\n\n\nstatic void field (LexState *ls, expdesc *v) {\n  /* field -> ['.' | ':'] NAME */\n  FuncState *fs = ls->fs;\n  expdesc key;\n  luaK_exp2anyreg(fs, v);\n  luaX_next(ls);  /* skip the dot or colon */\n  checkname(ls, &key);\n  luaK_indexed(fs, v, &key);\n}\n\n\nstatic void yindex (LexState *ls, expdesc *v) {\n  /* index -> '[' expr ']' */\n  luaX_next(ls);  /* skip the '[' */\n  expr(ls, v);\n  luaK_exp2val(ls->fs, v);\n  checknext(ls, ']');\n}\n\n\n/*\n** {======================================================================\n** Rules for Constructors\n** =======================================================================\n*/\n\n\nstruct ConsControl {\n  expdesc v;  /* last list item read */\n  expdesc *t;  /* table descriptor */\n  int nh;  /* total number of `record' elements */\n  int na;  /* total number of array elements */\n  int tostore;  /* number of array elements pending to be stored */\n};\n\n\nstatic void recfield (LexState *ls, struct ConsControl *cc) {\n  /* recfield -> (NAME | `['exp1`]') = exp1 */\n  FuncState *fs = ls->fs;\n  int reg = ls->fs->freereg;\n  expdesc key, val;\n  int rkkey;\n  if (ls->t.token == TK_NAME) {\n    luaY_checklimit(fs, cc->nh, MAX_INT, \"items in a constructor\");\n    checkname(ls, &key);\n  }\n  else  /* ls->t.token == '[' */\n    yindex(ls, &key);\n  cc->nh++;\n  checknext(ls, '=');\n  rkkey = luaK_exp2RK(fs, &key);\n  expr(ls, &val);\n  luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val));\n  fs->freereg = reg;  /* free registers */\n}\n\n\nstatic void closelistfield (FuncState *fs, struct ConsControl *cc) {\n  if (cc->v.k == VVOID) return;  /* there is no list item */\n  luaK_exp2nextreg(fs, &cc->v);\n  cc->v.k = VVOID;\n  if (cc->tostore == LFIELDS_PER_FLUSH) {\n    luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);  /* flush */\n    cc->tostore = 0;  /* no more items pending */\n  }\n}\n\n\nstatic void lastlistfield (FuncState *fs, struct ConsControl *cc) {\n  if (cc->tostore == 0) return;\n  if (hasmultret(cc->v.k)) {\n    luaK_setmultret(fs, &cc->v);\n    luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET);\n    cc->na--;  /* do not count last expression (unknown number of elements) */\n  }\n  else {\n    if (cc->v.k != VVOID)\n      luaK_exp2nextreg(fs, &cc->v);\n    luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore);\n  }\n}\n\n\nstatic void listfield (LexState *ls, struct ConsControl *cc) {\n  expr(ls, &cc->v);\n  luaY_checklimit(ls->fs, cc->na, MAX_INT, \"items in a constructor\");\n  cc->na++;\n  cc->tostore++;\n}\n\n\nstatic void constructor (LexState *ls, expdesc *t) {\n  /* constructor -> ?? */\n  FuncState *fs = ls->fs;\n  int line = ls->linenumber;\n  int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);\n  struct ConsControl cc;\n  cc.na = cc.nh = cc.tostore = 0;\n  cc.t = t;\n  init_exp(t, VRELOCABLE, pc);\n  init_exp(&cc.v, VVOID, 0);  /* no value (yet) */\n  luaK_exp2nextreg(ls->fs, t);  /* fix it at stack top (for gc) */\n  checknext(ls, '{');\n  do {\n    lua_assert(cc.v.k == VVOID || cc.tostore > 0);\n    if (ls->t.token == '}') break;\n    closelistfield(fs, &cc);\n    switch(ls->t.token) {\n      case TK_NAME: {  /* may be listfields or recfields */\n        luaX_lookahead(ls);\n        if (ls->lookahead.token != '=')  /* expression? */\n          listfield(ls, &cc);\n        else\n          recfield(ls, &cc);\n        break;\n      }\n      case '[': {  /* constructor_item -> recfield */\n        recfield(ls, &cc);\n        break;\n      }\n      default: {  /* constructor_part -> listfield */\n        listfield(ls, &cc);\n        break;\n      }\n    }\n  } while (testnext(ls, ',') || testnext(ls, ';'));\n  check_match(ls, '}', '{', line);\n  lastlistfield(fs, &cc);\n  SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */\n  SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh));  /* set initial table size */\n}\n\n/* }====================================================================== */\n\n\n\nstatic void parlist (LexState *ls) {\n  /* parlist -> [ param { `,' param } ] */\n  FuncState *fs = ls->fs;\n  Proto *f = fs->f;\n  int nparams = 0;\n  f->is_vararg = 0;\n  if (ls->t.token != ')') {  /* is `parlist' not empty? */\n    do {\n      switch (ls->t.token) {\n        case TK_NAME: {  /* param -> NAME */\n          new_localvar(ls, str_checkname(ls), nparams++);\n          break;\n        }\n        case TK_DOTS: {  /* param -> `...' */\n          luaX_next(ls);\n#if defined(LUA_COMPAT_VARARG)\n          /* use `arg' as default name */\n          new_localvarliteral(ls, \"arg\", nparams++);\n          f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG;\n#endif\n          f->is_vararg |= VARARG_ISVARARG;\n          break;\n        }\n        default: luaX_syntaxerror(ls, \"<name> or \" LUA_QL(\"...\") \" expected\");\n      }\n    } while (!f->is_vararg && testnext(ls, ','));\n  }\n  adjustlocalvars(ls, nparams);\n  f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG));\n  luaK_reserveregs(fs, fs->nactvar);  /* reserve register for parameters */\n}\n\n\nstatic void body (LexState *ls, expdesc *e, int needself, int line) {\n  /* body ->  `(' parlist `)' chunk END */\n  FuncState new_fs;\n  open_func(ls, &new_fs);\n  new_fs.f->linedefined = line;\n  checknext(ls, '(');\n  if (needself) {\n    new_localvarliteral(ls, \"self\", 0);\n    adjustlocalvars(ls, 1);\n  }\n  parlist(ls);\n  checknext(ls, ')');\n  chunk(ls);\n  new_fs.f->lastlinedefined = ls->linenumber;\n  check_match(ls, TK_END, TK_FUNCTION, line);\n  close_func(ls);\n  pushclosure(ls, &new_fs, e);\n}\n\n\nstatic int explist1 (LexState *ls, expdesc *v) {\n  /* explist1 -> expr { `,' expr } */\n  int n = 1;  /* at least one expression */\n  expr(ls, v);\n  while (testnext(ls, ',')) {\n    luaK_exp2nextreg(ls->fs, v);\n    expr(ls, v);\n    n++;\n  }\n  return n;\n}\n\n\nstatic void funcargs (LexState *ls, expdesc *f) {\n  FuncState *fs = ls->fs;\n  expdesc args;\n  int base, nparams;\n  int line = ls->linenumber;\n  switch (ls->t.token) {\n    case '(': {  /* funcargs -> `(' [ explist1 ] `)' */\n      if (line != ls->lastline)\n        luaX_syntaxerror(ls,\"ambiguous syntax (function call x new statement)\");\n      luaX_next(ls);\n      if (ls->t.token == ')')  /* arg list is empty? */\n        args.k = VVOID;\n      else {\n        explist1(ls, &args);\n        luaK_setmultret(fs, &args);\n      }\n      check_match(ls, ')', '(', line);\n      break;\n    }\n    case '{': {  /* funcargs -> constructor */\n      constructor(ls, &args);\n      break;\n    }\n    case TK_STRING: {  /* funcargs -> STRING */\n      codestring(ls, &args, ls->t.seminfo.ts);\n      luaX_next(ls);  /* must use `seminfo' before `next' */\n      break;\n    }\n    default: {\n      luaX_syntaxerror(ls, \"function arguments expected\");\n      return;\n    }\n  }\n  lua_assert(f->k == VNONRELOC);\n  base = f->u.s.info;  /* base register for call */\n  if (hasmultret(args.k))\n    nparams = LUA_MULTRET;  /* open call */\n  else {\n    if (args.k != VVOID)\n      luaK_exp2nextreg(fs, &args);  /* close last argument */\n    nparams = fs->freereg - (base+1);\n  }\n  init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));\n  luaK_fixline(fs, line);\n  fs->freereg = base+1;  /* call remove function and arguments and leaves\n                            (unless changed) one result */\n}\n\n\n\n\n/*\n** {======================================================================\n** Expression parsing\n** =======================================================================\n*/\n\n\nstatic void prefixexp (LexState *ls, expdesc *v) {\n  /* prefixexp -> NAME | '(' expr ')' */\n  switch (ls->t.token) {\n    case '(': {\n      int line = ls->linenumber;\n      luaX_next(ls);\n      expr(ls, v);\n      check_match(ls, ')', '(', line);\n      luaK_dischargevars(ls->fs, v);\n      return;\n    }\n    case TK_NAME: {\n      singlevar(ls, v);\n      return;\n    }\n    default: {\n      luaX_syntaxerror(ls, \"unexpected symbol\");\n      return;\n    }\n  }\n}\n\n\nstatic void primaryexp (LexState *ls, expdesc *v) {\n  /* primaryexp ->\n        prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */\n  FuncState *fs = ls->fs;\n  prefixexp(ls, v);\n  for (;;) {\n    switch (ls->t.token) {\n      case '.': {  /* field */\n        field(ls, v);\n        break;\n      }\n      case '[': {  /* `[' exp1 `]' */\n        expdesc key;\n        luaK_exp2anyreg(fs, v);\n        yindex(ls, &key);\n        luaK_indexed(fs, v, &key);\n        break;\n      }\n      case ':': {  /* `:' NAME funcargs */\n        expdesc key;\n        luaX_next(ls);\n        checkname(ls, &key);\n        luaK_self(fs, v, &key);\n        funcargs(ls, v);\n        break;\n      }\n      case '(': case TK_STRING: case '{': {  /* funcargs */\n        luaK_exp2nextreg(fs, v);\n        funcargs(ls, v);\n        break;\n      }\n      default: return;\n    }\n  }\n}\n\n\nstatic void simpleexp (LexState *ls, expdesc *v) {\n  /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |\n                  constructor | FUNCTION body | primaryexp */\n  switch (ls->t.token) {\n    case TK_NUMBER: {\n      init_exp(v, VKNUM, 0);\n      v->u.nval = ls->t.seminfo.r;\n      break;\n    }\n    case TK_STRING: {\n      codestring(ls, v, ls->t.seminfo.ts);\n      break;\n    }\n    case TK_NIL: {\n      init_exp(v, VNIL, 0);\n      break;\n    }\n    case TK_TRUE: {\n      init_exp(v, VTRUE, 0);\n      break;\n    }\n    case TK_FALSE: {\n      init_exp(v, VFALSE, 0);\n      break;\n    }\n    case TK_DOTS: {  /* vararg */\n      FuncState *fs = ls->fs;\n      check_condition(ls, fs->f->is_vararg,\n                      \"cannot use \" LUA_QL(\"...\") \" outside a vararg function\");\n      fs->f->is_vararg &= ~VARARG_NEEDSARG;  /* don't need 'arg' */\n      init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));\n      break;\n    }\n    case '{': {  /* constructor */\n      constructor(ls, v);\n      return;\n    }\n    case TK_FUNCTION: {\n      luaX_next(ls);\n      body(ls, v, 0, ls->linenumber);\n      return;\n    }\n    default: {\n      primaryexp(ls, v);\n      return;\n    }\n  }\n  luaX_next(ls);\n}\n\n\nstatic UnOpr getunopr (int op) {\n  switch (op) {\n    case TK_NOT: return OPR_NOT;\n    case '-': return OPR_MINUS;\n    case '#': return OPR_LEN;\n    default: return OPR_NOUNOPR;\n  }\n}\n\n\nstatic BinOpr getbinopr (int op) {\n  switch (op) {\n    case '+': return OPR_ADD;\n    case '-': return OPR_SUB;\n    case '*': return OPR_MUL;\n    case '/': return OPR_DIV;\n    case '%': return OPR_MOD;\n    case '^': return OPR_POW;\n    case TK_CONCAT: return OPR_CONCAT;\n    case TK_NE: return OPR_NE;\n    case TK_EQ: return OPR_EQ;\n    case '<': return OPR_LT;\n    case TK_LE: return OPR_LE;\n    case '>': return OPR_GT;\n    case TK_GE: return OPR_GE;\n    case TK_AND: return OPR_AND;\n    case TK_OR: return OPR_OR;\n    default: return OPR_NOBINOPR;\n  }\n}\n\n\nstatic const struct {\n  lu_byte left;  /* left priority for each binary operator */\n  lu_byte right; /* right priority */\n} priority[] = {  /* ORDER OPR */\n   {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7},  /* `+' `-' `/' `%' */\n   {10, 9}, {5, 4},                 /* power and concat (right associative) */\n   {3, 3}, {3, 3},                  /* equality and inequality */\n   {3, 3}, {3, 3}, {3, 3}, {3, 3},  /* order */\n   {2, 2}, {1, 1}                   /* logical (and/or) */\n};\n\n#define UNARY_PRIORITY\t8  /* priority for unary operators */\n\n\n/*\n** subexpr -> (simpleexp | unop subexpr) { binop subexpr }\n** where `binop' is any binary operator with a priority higher than `limit'\n*/\nstatic BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {\n  BinOpr op;\n  UnOpr uop;\n  enterlevel(ls);\n  uop = getunopr(ls->t.token);\n  if (uop != OPR_NOUNOPR) {\n    luaX_next(ls);\n    subexpr(ls, v, UNARY_PRIORITY);\n    luaK_prefix(ls->fs, uop, v);\n  }\n  else simpleexp(ls, v);\n  /* expand while operators have priorities higher than `limit' */\n  op = getbinopr(ls->t.token);\n  while (op != OPR_NOBINOPR && priority[op].left > limit) {\n    expdesc v2;\n    BinOpr nextop;\n    luaX_next(ls);\n    luaK_infix(ls->fs, op, v);\n    /* read sub-expression with higher priority */\n    nextop = subexpr(ls, &v2, priority[op].right);\n    luaK_posfix(ls->fs, op, v, &v2);\n    op = nextop;\n  }\n  leavelevel(ls);\n  return op;  /* return first untreated operator */\n}\n\n\nstatic void expr (LexState *ls, expdesc *v) {\n  subexpr(ls, v, 0);\n}\n\n/* }==================================================================== */\n\n\n\n/*\n** {======================================================================\n** Rules for Statements\n** =======================================================================\n*/\n\n\nstatic int block_follow (int token) {\n  switch (token) {\n    case TK_ELSE: case TK_ELSEIF: case TK_END:\n    case TK_UNTIL: case TK_EOS:\n      return 1;\n    default: return 0;\n  }\n}\n\n\nstatic void block (LexState *ls) {\n  /* block -> chunk */\n  FuncState *fs = ls->fs;\n  BlockCnt bl;\n  enterblock(fs, &bl, 0);\n  chunk(ls);\n  lua_assert(bl.breaklist == NO_JUMP);\n  leaveblock(fs);\n}\n\n\n/*\n** structure to chain all variables in the left-hand side of an\n** assignment\n*/\nstruct LHS_assign {\n  struct LHS_assign *prev;\n  expdesc v;  /* variable (global, local, upvalue, or indexed) */\n};\n\n\n/*\n** check whether, in an assignment to a local variable, the local variable\n** is needed in a previous assignment (to a table). If so, save original\n** local value in a safe place and use this safe copy in the previous\n** assignment.\n*/\nstatic void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {\n  FuncState *fs = ls->fs;\n  int extra = fs->freereg;  /* eventual position to save local variable */\n  int conflict = 0;\n  for (; lh; lh = lh->prev) {\n    if (lh->v.k == VINDEXED) {\n      if (lh->v.u.s.info == v->u.s.info) {  /* conflict? */\n        conflict = 1;\n        lh->v.u.s.info = extra;  /* previous assignment will use safe copy */\n      }\n      if (lh->v.u.s.aux == v->u.s.info) {  /* conflict? */\n        conflict = 1;\n        lh->v.u.s.aux = extra;  /* previous assignment will use safe copy */\n      }\n    }\n  }\n  if (conflict) {\n    luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0);  /* make copy */\n    luaK_reserveregs(fs, 1);\n  }\n}\n\n\nstatic void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {\n  expdesc e;\n  check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,\n                      \"syntax error\");\n  if (testnext(ls, ',')) {  /* assignment -> `,' primaryexp assignment */\n    struct LHS_assign nv;\n    nv.prev = lh;\n    primaryexp(ls, &nv.v);\n    if (nv.v.k == VLOCAL)\n      check_conflict(ls, lh, &nv.v);\n    luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls,\n                    \"variables in assignment\");\n    assignment(ls, &nv, nvars+1);\n  }\n  else {  /* assignment -> `=' explist1 */\n    int nexps;\n    checknext(ls, '=');\n    nexps = explist1(ls, &e);\n    if (nexps != nvars) {\n      adjust_assign(ls, nvars, nexps, &e);\n      if (nexps > nvars)\n        ls->fs->freereg -= nexps - nvars;  /* remove extra values */\n    }\n    else {\n      luaK_setoneret(ls->fs, &e);  /* close last expression */\n      luaK_storevar(ls->fs, &lh->v, &e);\n      return;  /* avoid default */\n    }\n  }\n  init_exp(&e, VNONRELOC, ls->fs->freereg-1);  /* default assignment */\n  luaK_storevar(ls->fs, &lh->v, &e);\n}\n\n\nstatic int cond (LexState *ls) {\n  /* cond -> exp */\n  expdesc v;\n  expr(ls, &v);  /* read condition */\n  if (v.k == VNIL) v.k = VFALSE;  /* `falses' are all equal here */\n  luaK_goiftrue(ls->fs, &v);\n  return v.f;\n}\n\n\nstatic void breakstat (LexState *ls) {\n  FuncState *fs = ls->fs;\n  BlockCnt *bl = fs->bl;\n  int upval = 0;\n  while (bl && !bl->isbreakable) {\n    upval |= bl->upval;\n    bl = bl->previous;\n  }\n  if (!bl)\n    luaX_syntaxerror(ls, \"no loop to break\");\n  if (upval)\n    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);\n  luaK_concat(fs, &bl->breaklist, luaK_jump(fs));\n}\n\n\nstatic void whilestat (LexState *ls, int line) {\n  /* whilestat -> WHILE cond DO block END */\n  FuncState *fs = ls->fs;\n  int whileinit;\n  int condexit;\n  BlockCnt bl;\n  luaX_next(ls);  /* skip WHILE */\n  whileinit = luaK_getlabel(fs);\n  condexit = cond(ls);\n  enterblock(fs, &bl, 1);\n  checknext(ls, TK_DO);\n  block(ls);\n  luaK_patchlist(fs, luaK_jump(fs), whileinit);\n  check_match(ls, TK_END, TK_WHILE, line);\n  leaveblock(fs);\n  luaK_patchtohere(fs, condexit);  /* false conditions finish the loop */\n}\n\n\nstatic void repeatstat (LexState *ls, int line) {\n  /* repeatstat -> REPEAT block UNTIL cond */\n  int condexit;\n  FuncState *fs = ls->fs;\n  int repeat_init = luaK_getlabel(fs);\n  BlockCnt bl1, bl2;\n  enterblock(fs, &bl1, 1);  /* loop block */\n  enterblock(fs, &bl2, 0);  /* scope block */\n  luaX_next(ls);  /* skip REPEAT */\n  chunk(ls);\n  check_match(ls, TK_UNTIL, TK_REPEAT, line);\n  condexit = cond(ls);  /* read condition (inside scope block) */\n  if (!bl2.upval) {  /* no upvalues? */\n    leaveblock(fs);  /* finish scope */\n    luaK_patchlist(ls->fs, condexit, repeat_init);  /* close the loop */\n  }\n  else {  /* complete semantics when there are upvalues */\n    breakstat(ls);  /* if condition then break */\n    luaK_patchtohere(ls->fs, condexit);  /* else... */\n    leaveblock(fs);  /* finish scope... */\n    luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init);  /* and repeat */\n  }\n  leaveblock(fs);  /* finish loop */\n}\n\n\nstatic int exp1 (LexState *ls) {\n  expdesc e;\n  int k;\n  expr(ls, &e);\n  k = e.k;\n  luaK_exp2nextreg(ls->fs, &e);\n  return k;\n}\n\n\nstatic void forbody (LexState *ls, int base, int line, int nvars, int isnum) {\n  /* forbody -> DO block */\n  BlockCnt bl;\n  FuncState *fs = ls->fs;\n  int prep, endfor;\n  adjustlocalvars(ls, 3);  /* control variables */\n  checknext(ls, TK_DO);\n  prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);\n  enterblock(fs, &bl, 0);  /* scope for declared variables */\n  adjustlocalvars(ls, nvars);\n  luaK_reserveregs(fs, nvars);\n  block(ls);\n  leaveblock(fs);  /* end of scope for declared variables */\n  luaK_patchtohere(fs, prep);\n  endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :\n                     luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars);\n  luaK_fixline(fs, line);  /* pretend that `OP_FOR' starts the loop */\n  luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1);\n}\n\n\nstatic void fornum (LexState *ls, TString *varname, int line) {\n  /* fornum -> NAME = exp1,exp1[,exp1] forbody */\n  FuncState *fs = ls->fs;\n  int base = fs->freereg;\n  new_localvarliteral(ls, \"(for index)\", 0);\n  new_localvarliteral(ls, \"(for limit)\", 1);\n  new_localvarliteral(ls, \"(for step)\", 2);\n  new_localvar(ls, varname, 3);\n  checknext(ls, '=');\n  exp1(ls);  /* initial value */\n  checknext(ls, ',');\n  exp1(ls);  /* limit */\n  if (testnext(ls, ','))\n    exp1(ls);  /* optional step */\n  else {  /* default step = 1 */\n    luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));\n    luaK_reserveregs(fs, 1);\n  }\n  forbody(ls, base, line, 1, 1);\n}\n\n\nstatic void forlist (LexState *ls, TString *indexname) {\n  /* forlist -> NAME {,NAME} IN explist1 forbody */\n  FuncState *fs = ls->fs;\n  expdesc e;\n  int nvars = 0;\n  int line;\n  int base = fs->freereg;\n  /* create control variables */\n  new_localvarliteral(ls, \"(for generator)\", nvars++);\n  new_localvarliteral(ls, \"(for state)\", nvars++);\n  new_localvarliteral(ls, \"(for control)\", nvars++);\n  /* create declared variables */\n  new_localvar(ls, indexname, nvars++);\n  while (testnext(ls, ','))\n    new_localvar(ls, str_checkname(ls), nvars++);\n  checknext(ls, TK_IN);\n  line = ls->linenumber;\n  adjust_assign(ls, 3, explist1(ls, &e), &e);\n  luaK_checkstack(fs, 3);  /* extra space to call generator */\n  forbody(ls, base, line, nvars - 3, 0);\n}\n\n\nstatic void forstat (LexState *ls, int line) {\n  /* forstat -> FOR (fornum | forlist) END */\n  FuncState *fs = ls->fs;\n  TString *varname;\n  BlockCnt bl;\n  enterblock(fs, &bl, 1);  /* scope for loop and control variables */\n  luaX_next(ls);  /* skip `for' */\n  varname = str_checkname(ls);  /* first variable name */\n  switch (ls->t.token) {\n    case '=': fornum(ls, varname, line); break;\n    case ',': case TK_IN: forlist(ls, varname); break;\n    default: luaX_syntaxerror(ls, LUA_QL(\"=\") \" or \" LUA_QL(\"in\") \" expected\");\n  }\n  check_match(ls, TK_END, TK_FOR, line);\n  leaveblock(fs);  /* loop scope (`break' jumps to this point) */\n}\n\n\nstatic int test_then_block (LexState *ls) {\n  /* test_then_block -> [IF | ELSEIF] cond THEN block */\n  int condexit;\n  luaX_next(ls);  /* skip IF or ELSEIF */\n  condexit = cond(ls);\n  checknext(ls, TK_THEN);\n  block(ls);  /* `then' part */\n  return condexit;\n}\n\n\nstatic void ifstat (LexState *ls, int line) {\n  /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */\n  FuncState *fs = ls->fs;\n  int flist;\n  int escapelist = NO_JUMP;\n  flist = test_then_block(ls);  /* IF cond THEN block */\n  while (ls->t.token == TK_ELSEIF) {\n    luaK_concat(fs, &escapelist, luaK_jump(fs));\n    luaK_patchtohere(fs, flist);\n    flist = test_then_block(ls);  /* ELSEIF cond THEN block */\n  }\n  if (ls->t.token == TK_ELSE) {\n    luaK_concat(fs, &escapelist, luaK_jump(fs));\n    luaK_patchtohere(fs, flist);\n    luaX_next(ls);  /* skip ELSE (after patch, for correct line info) */\n    block(ls);  /* `else' part */\n  }\n  else\n    luaK_concat(fs, &escapelist, flist);\n  luaK_patchtohere(fs, escapelist);\n  check_match(ls, TK_END, TK_IF, line);\n}\n\n\nstatic void localfunc (LexState *ls) {\n  expdesc v, b;\n  FuncState *fs = ls->fs;\n  new_localvar(ls, str_checkname(ls), 0);\n  init_exp(&v, VLOCAL, fs->freereg);\n  luaK_reserveregs(fs, 1);\n  adjustlocalvars(ls, 1);\n  body(ls, &b, 0, ls->linenumber);\n  luaK_storevar(fs, &v, &b);\n  /* debug information will only see the variable after this point! */\n  getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;\n}\n\n\nstatic void localstat (LexState *ls) {\n  /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */\n  int nvars = 0;\n  int nexps;\n  expdesc e;\n  do {\n    new_localvar(ls, str_checkname(ls), nvars++);\n  } while (testnext(ls, ','));\n  if (testnext(ls, '='))\n    nexps = explist1(ls, &e);\n  else {\n    e.k = VVOID;\n    nexps = 0;\n  }\n  adjust_assign(ls, nvars, nexps, &e);\n  adjustlocalvars(ls, nvars);\n}\n\n\nstatic int funcname (LexState *ls, expdesc *v) {\n  /* funcname -> NAME {field} [`:' NAME] */\n  int needself = 0;\n  singlevar(ls, v);\n  while (ls->t.token == '.')\n    field(ls, v);\n  if (ls->t.token == ':') {\n    needself = 1;\n    field(ls, v);\n  }\n  return needself;\n}\n\n\nstatic void funcstat (LexState *ls, int line) {\n  /* funcstat -> FUNCTION funcname body */\n  int needself;\n  expdesc v, b;\n  luaX_next(ls);  /* skip FUNCTION */\n  needself = funcname(ls, &v);\n  body(ls, &b, needself, line);\n  luaK_storevar(ls->fs, &v, &b);\n  luaK_fixline(ls->fs, line);  /* definition `happens' in the first line */\n}\n\n\nstatic void exprstat (LexState *ls) {\n  /* stat -> func | assignment */\n  FuncState *fs = ls->fs;\n  struct LHS_assign v;\n  primaryexp(ls, &v.v);\n  if (v.v.k == VCALL)  /* stat -> func */\n    SETARG_C(getcode(fs, &v.v), 1);  /* call statement uses no results */\n  else {  /* stat -> assignment */\n    v.prev = NULL;\n    assignment(ls, &v, 1);\n  }\n}\n\n\nstatic void retstat (LexState *ls) {\n  /* stat -> RETURN explist */\n  FuncState *fs = ls->fs;\n  expdesc e;\n  int first, nret;  /* registers with returned values */\n  luaX_next(ls);  /* skip RETURN */\n  if (block_follow(ls->t.token) || ls->t.token == ';')\n    first = nret = 0;  /* return no values */\n  else {\n    nret = explist1(ls, &e);  /* optional return values */\n    if (hasmultret(e.k)) {\n      luaK_setmultret(fs, &e);\n      if (e.k == VCALL && nret == 1) {  /* tail call? */\n        SET_OPCODE(getcode(fs,&e), OP_TAILCALL);\n        lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);\n      }\n      first = fs->nactvar;\n      nret = LUA_MULTRET;  /* return all values */\n    }\n    else {\n      if (nret == 1)  /* only one single value? */\n        first = luaK_exp2anyreg(fs, &e);\n      else {\n        luaK_exp2nextreg(fs, &e);  /* values must go to the `stack' */\n        first = fs->nactvar;  /* return all `active' values */\n        lua_assert(nret == fs->freereg - first);\n      }\n    }\n  }\n  luaK_ret(fs, first, nret);\n}\n\n\nstatic int statement (LexState *ls) {\n  int line = ls->linenumber;  /* may be needed for error messages */\n  switch (ls->t.token) {\n    case TK_IF: {  /* stat -> ifstat */\n      ifstat(ls, line);\n      return 0;\n    }\n    case TK_WHILE: {  /* stat -> whilestat */\n      whilestat(ls, line);\n      return 0;\n    }\n    case TK_DO: {  /* stat -> DO block END */\n      luaX_next(ls);  /* skip DO */\n      block(ls);\n      check_match(ls, TK_END, TK_DO, line);\n      return 0;\n    }\n    case TK_FOR: {  /* stat -> forstat */\n      forstat(ls, line);\n      return 0;\n    }\n    case TK_REPEAT: {  /* stat -> repeatstat */\n      repeatstat(ls, line);\n      return 0;\n    }\n    case TK_FUNCTION: {\n      funcstat(ls, line);  /* stat -> funcstat */\n      return 0;\n    }\n    case TK_LOCAL: {  /* stat -> localstat */\n      luaX_next(ls);  /* skip LOCAL */\n      if (testnext(ls, TK_FUNCTION))  /* local function? */\n        localfunc(ls);\n      else\n        localstat(ls);\n      return 0;\n    }\n    case TK_RETURN: {  /* stat -> retstat */\n      retstat(ls);\n      return 1;  /* must be last statement */\n    }\n    case TK_BREAK: {  /* stat -> breakstat */\n      luaX_next(ls);  /* skip BREAK */\n      breakstat(ls);\n      return 1;  /* must be last statement */\n    }\n    default: {\n      exprstat(ls);\n      return 0;  /* to avoid warnings */\n    }\n  }\n}\n\n\nstatic void chunk (LexState *ls) {\n  /* chunk -> { stat [`;'] } */\n  int islast = 0;\n  enterlevel(ls);\n  while (!islast && !block_follow(ls->t.token)) {\n    islast = statement(ls);\n    testnext(ls, ';');\n    lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&\n               ls->fs->freereg >= ls->fs->nactvar);\n    ls->fs->freereg = ls->fs->nactvar;  /* free registers */\n  }\n  leavelevel(ls);\n}\n\n/* }====================================================================== */\n"
  },
  {
    "path": "src/lua/lparser.h",
    "content": "/*\n** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua Parser\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lparser_h\n#define lparser_h\n\n#include \"llimits.h\"\n#include \"lobject.h\"\n#include \"lzio.h\"\n\n\n/*\n** Expression descriptor\n*/\n\ntypedef enum {\n  VVOID,\t/* no value */\n  VNIL,\n  VTRUE,\n  VFALSE,\n  VK,\t\t/* info = index of constant in `k' */\n  VKNUM,\t/* nval = numerical value */\n  VLOCAL,\t/* info = local register */\n  VUPVAL,       /* info = index of upvalue in `upvalues' */\n  VGLOBAL,\t/* info = index of table; aux = index of global name in `k' */\n  VINDEXED,\t/* info = table register; aux = index register (or `k') */\n  VJMP,\t\t/* info = instruction pc */\n  VRELOCABLE,\t/* info = instruction pc */\n  VNONRELOC,\t/* info = result register */\n  VCALL,\t/* info = instruction pc */\n  VVARARG\t/* info = instruction pc */\n} expkind;\n\ntypedef struct expdesc {\n  expkind k;\n  union {\n    struct { int info, aux; } s;\n    lua_Number nval;\n  } u;\n  int t;  /* patch list of `exit when true' */\n  int f;  /* patch list of `exit when false' */\n} expdesc;\n\n\ntypedef struct upvaldesc {\n  lu_byte k;\n  lu_byte info;\n} upvaldesc;\n\n\nstruct BlockCnt;  /* defined in lparser.c */\n\n\n/* state needed to generate code for a given function */\ntypedef struct FuncState {\n  Proto *f;  /* current function header */\n  Table *h;  /* table to find (and reuse) elements in `k' */\n  struct FuncState *prev;  /* enclosing function */\n  struct LexState *ls;  /* lexical state */\n  struct lua_State *L;  /* copy of the Lua state */\n  struct BlockCnt *bl;  /* chain of current blocks */\n  int pc;  /* next position to code (equivalent to `ncode') */\n  int lasttarget;   /* `pc' of last `jump target' */\n  int jpc;  /* list of pending jumps to `pc' */\n  int freereg;  /* first free register */\n  int nk;  /* number of elements in `k' */\n  int np;  /* number of elements in `p' */\n  short nlocvars;  /* number of elements in `locvars' */\n  lu_byte nactvar;  /* number of active local variables */\n  upvaldesc upvalues[LUAI_MAXUPVALUES];  /* upvalues */\n  unsigned short actvar[LUAI_MAXVARS];  /* declared-variable stack */\n} FuncState;\n\n\nLUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,\n                                            const char *name);\n\n\n#endif\n"
  },
  {
    "path": "src/lua/lstate.c",
    "content": "/*\n** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $\n** Global State\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define lstate_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"llex.h\"\n#include \"lmem.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n\n\n#define state_size(x)\t(sizeof(x) + LUAI_EXTRASPACE)\n#define fromstate(l)\t(cast(lu_byte *, (l)) - LUAI_EXTRASPACE)\n#define tostate(l)   (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE))\n\n\n/*\n** Main thread combines a thread state and the global state\n*/\ntypedef struct LG {\n  lua_State l;\n  global_State g;\n} LG;\n  \n\n\nstatic void stack_init (lua_State *L1, lua_State *L) {\n  /* initialize CallInfo array */\n  L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);\n  L1->ci = L1->base_ci;\n  L1->size_ci = BASIC_CI_SIZE;\n  L1->end_ci = L1->base_ci + L1->size_ci - 1;\n  /* initialize stack array */\n  L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);\n  L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;\n  L1->top = L1->stack;\n  L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;\n  /* initialize first ci */\n  L1->ci->func = L1->top;\n  setnilvalue(L1->top++);  /* `function' entry for this `ci' */\n  L1->base = L1->ci->base = L1->top;\n  L1->ci->top = L1->top + LUA_MINSTACK;\n}\n\n\nstatic void freestack (lua_State *L, lua_State *L1) {\n  luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo);\n  luaM_freearray(L, L1->stack, L1->stacksize, TValue);\n}\n\n\n/*\n** open parts that may cause memory-allocation errors\n*/\nstatic void f_luaopen (lua_State *L, void *ud) {\n  global_State *g = G(L);\n  UNUSED(ud);\n  stack_init(L, L);  /* init stack */\n  sethvalue(L, gt(L), luaH_new(L, 0, 2));  /* table of globals */\n  sethvalue(L, registry(L), luaH_new(L, 0, 2));  /* registry */\n  luaS_resize(L, MINSTRTABSIZE);  /* initial size of string table */\n  luaT_init(L);\n  luaX_init(L);\n  luaS_fix(luaS_newliteral(L, MEMERRMSG));\n  g->GCthreshold = 4*g->totalbytes;\n}\n\n\nstatic void preinit_state (lua_State *L, global_State *g) {\n  G(L) = g;\n  L->stack = NULL;\n  L->stacksize = 0;\n  L->errorJmp = NULL;\n  L->hook = NULL;\n  L->hookmask = 0;\n  L->basehookcount = 0;\n  L->allowhook = 1;\n  resethookcount(L);\n  L->openupval = NULL;\n  L->size_ci = 0;\n  L->nCcalls = L->baseCcalls = 0;\n  L->status = 0;\n  L->base_ci = L->ci = NULL;\n  L->savedpc = NULL;\n  L->errfunc = 0;\n  setnilvalue(gt(L));\n}\n\n\nstatic void close_state (lua_State *L) {\n  global_State *g = G(L);\n  luaF_close(L, L->stack);  /* close all upvalues for this thread */\n  luaC_freeall(L);  /* collect all objects */\n  lua_assert(g->rootgc == obj2gco(L));\n  lua_assert(g->strt.nuse == 0);\n  luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);\n  luaZ_freebuffer(L, &g->buff);\n  freestack(L, L);\n  lua_assert(g->totalbytes == sizeof(LG));\n  (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0);\n}\n\n\nlua_State *luaE_newthread (lua_State *L) {\n  lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State)));\n  luaC_link(L, obj2gco(L1), LUA_TTHREAD);\n  preinit_state(L1, G(L));\n  stack_init(L1, L);  /* init stack */\n  setobj2n(L, gt(L1), gt(L));  /* share table of globals */\n  L1->hookmask = L->hookmask;\n  L1->basehookcount = L->basehookcount;\n  L1->hook = L->hook;\n  resethookcount(L1);\n  lua_assert(iswhite(obj2gco(L1)));\n  return L1;\n}\n\n\nvoid luaE_freethread (lua_State *L, lua_State *L1) {\n  luaF_close(L1, L1->stack);  /* close all upvalues for this thread */\n  lua_assert(L1->openupval == NULL);\n  luai_userstatefree(L1);\n  freestack(L, L1);\n  luaM_freemem(L, fromstate(L1), state_size(lua_State));\n}\n\n\nLUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {\n  int i;\n  lua_State *L;\n  global_State *g;\n  void *l = (*f)(ud, NULL, 0, state_size(LG));\n  if (l == NULL) return NULL;\n  L = tostate(l);\n  g = &((LG *)L)->g;\n  L->next = NULL;\n  L->tt = LUA_TTHREAD;\n  g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT);\n  L->marked = luaC_white(g);\n  set2bits(L->marked, FIXEDBIT, SFIXEDBIT);\n  preinit_state(L, g);\n  g->frealloc = f;\n  g->ud = ud;\n  g->mainthread = L;\n  g->uvhead.u.l.prev = &g->uvhead;\n  g->uvhead.u.l.next = &g->uvhead;\n  g->GCthreshold = 0;  /* mark it as unfinished state */\n  g->strt.size = 0;\n  g->strt.nuse = 0;\n  g->strt.hash = NULL;\n  setnilvalue(registry(L));\n  luaZ_initbuffer(L, &g->buff);\n  g->panic = NULL;\n  g->gcstate = GCSpause;\n  g->rootgc = obj2gco(L);\n  g->sweepstrgc = 0;\n  g->sweepgc = &g->rootgc;\n  g->gray = NULL;\n  g->grayagain = NULL;\n  g->weak = NULL;\n  g->tmudata = NULL;\n  g->totalbytes = sizeof(LG);\n  g->gcpause = LUAI_GCPAUSE;\n  g->gcstepmul = LUAI_GCMUL;\n  g->gcdept = 0;\n  for (i=0; i<NUM_TAGS; i++) g->mt[i] = NULL;\n  if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) {\n    /* memory allocation error: free partial state */\n    close_state(L);\n    L = NULL;\n  }\n  else\n    luai_userstateopen(L);\n  return L;\n}\n\n\nstatic void callallgcTM (lua_State *L, void *ud) {\n  UNUSED(ud);\n  luaC_callGCTM(L);  /* call GC metamethods for all udata */\n}\n\n\nLUA_API void lua_close (lua_State *L) {\n  L = G(L)->mainthread;  /* only the main thread can be closed */\n  lua_lock(L);\n  luaF_close(L, L->stack);  /* close all upvalues for this thread */\n  luaC_separateudata(L, 1);  /* separate udata that have GC metamethods */\n  L->errfunc = 0;  /* no error function during GC metamethods */\n  do {  /* repeat until no more errors */\n    L->ci = L->base_ci;\n    L->base = L->top = L->ci->base;\n    L->nCcalls = L->baseCcalls = 0;\n  } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0);\n  lua_assert(G(L)->tmudata == NULL);\n  luai_userstateclose(L);\n  close_state(L);\n}\n\n"
  },
  {
    "path": "src/lua/lstate.h",
    "content": "/*\n** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $\n** Global State\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lstate_h\n#define lstate_h\n\n#include \"lua.h\"\n\n#include \"lobject.h\"\n#include \"ltm.h\"\n#include \"lzio.h\"\n\n\n\nstruct lua_longjmp;  /* defined in ldo.c */\n\n\n/* table of globals */\n#define gt(L)\t(&L->l_gt)\n\n/* registry */\n#define registry(L)\t(&G(L)->l_registry)\n\n\n/* extra stack space to handle TM calls and some other extras */\n#define EXTRA_STACK   5\n\n\n#define BASIC_CI_SIZE           8\n\n#define BASIC_STACK_SIZE        (2*LUA_MINSTACK)\n\n\n\ntypedef struct stringtable {\n  GCObject **hash;\n  lu_int32 nuse;  /* number of elements */\n  int size;\n} stringtable;\n\n\n/*\n** informations about a call\n*/\ntypedef struct CallInfo {\n  StkId base;  /* base for this function */\n  StkId func;  /* function index in the stack */\n  StkId\ttop;  /* top for this function */\n  const Instruction *savedpc;\n  int nresults;  /* expected number of results from this function */\n  int tailcalls;  /* number of tail calls lost under this entry */\n} CallInfo;\n\n\n\n#define curr_func(L)\t(clvalue(L->ci->func))\n#define ci_func(ci)\t(clvalue((ci)->func))\n#define f_isLua(ci)\t(!ci_func(ci)->c.isC)\n#define isLua(ci)\t(ttisfunction((ci)->func) && f_isLua(ci))\n\n\n/*\n** `global state', shared by all threads of this state\n*/\ntypedef struct global_State {\n  stringtable strt;  /* hash table for strings */\n  lua_Alloc frealloc;  /* function to reallocate memory */\n  void *ud;         /* auxiliary data to `frealloc' */\n  lu_byte currentwhite;\n  lu_byte gcstate;  /* state of garbage collector */\n  int sweepstrgc;  /* position of sweep in `strt' */\n  GCObject *rootgc;  /* list of all collectable objects */\n  GCObject **sweepgc;  /* position of sweep in `rootgc' */\n  GCObject *gray;  /* list of gray objects */\n  GCObject *grayagain;  /* list of objects to be traversed atomically */\n  GCObject *weak;  /* list of weak tables (to be cleared) */\n  GCObject *tmudata;  /* last element of list of userdata to be GC */\n  Mbuffer buff;  /* temporary buffer for string concatentation */\n  lu_mem GCthreshold;\n  lu_mem totalbytes;  /* number of bytes currently allocated */\n  lu_mem estimate;  /* an estimate of number of bytes actually in use */\n  lu_mem gcdept;  /* how much GC is `behind schedule' */\n  int gcpause;  /* size of pause between successive GCs */\n  int gcstepmul;  /* GC `granularity' */\n  lua_CFunction panic;  /* to be called in unprotected errors */\n  TValue l_registry;\n  struct lua_State *mainthread;\n  UpVal uvhead;  /* head of double-linked list of all open upvalues */\n  struct Table *mt[NUM_TAGS];  /* metatables for basic types */\n  TString *tmname[TM_N];  /* array with tag-method names */\n} global_State;\n\n\n/*\n** `per thread' state\n*/\nstruct lua_State {\n  CommonHeader;\n  lu_byte status;\n  StkId top;  /* first free slot in the stack */\n  StkId base;  /* base of current function */\n  global_State *l_G;\n  CallInfo *ci;  /* call info for current function */\n  const Instruction *savedpc;  /* `savedpc' of current function */\n  StkId stack_last;  /* last free slot in the stack */\n  StkId stack;  /* stack base */\n  CallInfo *end_ci;  /* points after end of ci array*/\n  CallInfo *base_ci;  /* array of CallInfo's */\n  int stacksize;\n  int size_ci;  /* size of array `base_ci' */\n  unsigned short nCcalls;  /* number of nested C calls */\n  unsigned short baseCcalls;  /* nested C calls when resuming coroutine */\n  lu_byte hookmask;\n  lu_byte allowhook;\n  int basehookcount;\n  int hookcount;\n  lua_Hook hook;\n  TValue l_gt;  /* table of globals */\n  TValue env;  /* temporary place for environments */\n  GCObject *openupval;  /* list of open upvalues in this stack */\n  GCObject *gclist;\n  struct lua_longjmp *errorJmp;  /* current error recover point */\n  ptrdiff_t errfunc;  /* current error handling function (stack index) */\n};\n\n\n#define G(L)\t(L->l_G)\n\n\n/*\n** Union of all collectable objects\n*/\nunion GCObject {\n  GCheader gch;\n  union TString ts;\n  union Udata u;\n  union Closure cl;\n  struct Table h;\n  struct Proto p;\n  struct UpVal uv;\n  struct lua_State th;  /* thread */\n};\n\n\n/* macros to convert a GCObject into a specific value */\n#define rawgco2ts(o)\tcheck_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts))\n#define gco2ts(o)\t(&rawgco2ts(o)->tsv)\n#define rawgco2u(o)\tcheck_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u))\n#define gco2u(o)\t(&rawgco2u(o)->uv)\n#define gco2cl(o)\tcheck_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl))\n#define gco2h(o)\tcheck_exp((o)->gch.tt == LUA_TTABLE, &((o)->h))\n#define gco2p(o)\tcheck_exp((o)->gch.tt == LUA_TPROTO, &((o)->p))\n#define gco2uv(o)\tcheck_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv))\n#define ngcotouv(o) \\\n\tcheck_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv))\n#define gco2th(o)\tcheck_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th))\n\n/* macro to convert any Lua object into a GCObject */\n#define obj2gco(v)\t(cast(GCObject *, (v)))\n\n\nLUAI_FUNC lua_State *luaE_newthread (lua_State *L);\nLUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1);\n\n#endif\n\n"
  },
  {
    "path": "src/lua/lstring.c",
    "content": "/*\n** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $\n** String table (keeps all strings handled by Lua)\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define lstring_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n\n\n\nvoid luaS_resize (lua_State *L, int newsize) {\n  GCObject **newhash;\n  stringtable *tb;\n  int i;\n  if (G(L)->gcstate == GCSsweepstring)\n    return;  /* cannot resize during GC traverse */\n  newhash = luaM_newvector(L, newsize, GCObject *);\n  tb = &G(L)->strt;\n  for (i=0; i<newsize; i++) newhash[i] = NULL;\n  /* rehash */\n  for (i=0; i<tb->size; i++) {\n    GCObject *p = tb->hash[i];\n    while (p) {  /* for each node in the list */\n      GCObject *next = p->gch.next;  /* save next */\n      unsigned int h = gco2ts(p)->hash;\n      int h1 = lmod(h, newsize);  /* new position */\n      lua_assert(cast_int(h%newsize) == lmod(h, newsize));\n      p->gch.next = newhash[h1];  /* chain it */\n      newhash[h1] = p;\n      p = next;\n    }\n  }\n  luaM_freearray(L, tb->hash, tb->size, TString *);\n  tb->size = newsize;\n  tb->hash = newhash;\n}\n\n\nstatic TString *newlstr (lua_State *L, const char *str, size_t l,\n                                       unsigned int h) {\n  TString *ts;\n  stringtable *tb;\n  if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char))\n    luaM_toobig(L);\n  ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString)));\n  ts->tsv.len = l;\n  ts->tsv.hash = h;\n  ts->tsv.marked = luaC_white(G(L));\n  ts->tsv.tt = LUA_TSTRING;\n  ts->tsv.reserved = 0;\n  memcpy(ts+1, str, l*sizeof(char));\n  ((char *)(ts+1))[l] = '\\0';  /* ending 0 */\n  tb = &G(L)->strt;\n  h = lmod(h, tb->size);\n  ts->tsv.next = tb->hash[h];  /* chain new entry */\n  tb->hash[h] = obj2gco(ts);\n  tb->nuse++;\n  if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2)\n    luaS_resize(L, tb->size*2);  /* too crowded */\n  return ts;\n}\n\n\nTString *luaS_newlstr (lua_State *L, const char *str, size_t l) {\n  GCObject *o;\n  unsigned int h = cast(unsigned int, l);  /* seed */\n  size_t step = (l>>5)+1;  /* if string is too long, don't hash all its chars */\n  size_t l1;\n  for (l1=l; l1>=step; l1-=step)  /* compute hash */\n    h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1]));\n  for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)];\n       o != NULL;\n       o = o->gch.next) {\n    TString *ts = rawgco2ts(o);\n    if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) {\n      /* string may be dead */\n      if (isdead(G(L), o)) changewhite(o);\n      return ts;\n    }\n  }\n  return newlstr(L, str, l, h);  /* not found */\n}\n\n\nUdata *luaS_newudata (lua_State *L, size_t s, Table *e) {\n  Udata *u;\n  if (s > MAX_SIZET - sizeof(Udata))\n    luaM_toobig(L);\n  u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata)));\n  u->uv.marked = luaC_white(G(L));  /* is not finalized */\n  u->uv.tt = LUA_TUSERDATA;\n  u->uv.len = s;\n  u->uv.metatable = NULL;\n  u->uv.env = e;\n  /* chain it on udata list (after main thread) */\n  u->uv.next = G(L)->mainthread->next;\n  G(L)->mainthread->next = obj2gco(u);\n  return u;\n}\n\n"
  },
  {
    "path": "src/lua/lstring.h",
    "content": "/*\n** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $\n** String table (keep all strings handled by Lua)\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lstring_h\n#define lstring_h\n\n\n#include \"lgc.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n\n\n#define sizestring(s)\t(sizeof(union TString)+((s)->len+1)*sizeof(char))\n\n#define sizeudata(u)\t(sizeof(union Udata)+(u)->len)\n\n#define luaS_new(L, s)\t(luaS_newlstr(L, s, strlen(s)))\n#define luaS_newliteral(L, s)\t(luaS_newlstr(L, \"\" s, \\\n                                 (sizeof(s)/sizeof(char))-1))\n\n#define luaS_fix(s)\tl_setbit((s)->tsv.marked, FIXEDBIT)\n\nLUAI_FUNC void luaS_resize (lua_State *L, int newsize);\nLUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e);\nLUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);\n\n\n#endif\n"
  },
  {
    "path": "src/lua/lstrlib.c",
    "content": "/*\n** $Id: lstrlib.c,v 1.132.1.5 2010/05/14 15:34:19 roberto Exp $\n** Standard library for string operations and pattern-matching\n** See Copyright Notice in lua.h\n*/\n\n\n#include <ctype.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lstrlib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n/* macro to `unsign' a character */\n#define uchar(c)        ((unsigned char)(c))\n\n\n\nstatic int str_len (lua_State *L) {\n  size_t l;\n  luaL_checklstring(L, 1, &l);\n  lua_pushinteger(L, l);\n  return 1;\n}\n\n\nstatic ptrdiff_t posrelat (ptrdiff_t pos, size_t len) {\n  /* relative string position: negative means back from end */\n  if (pos < 0) pos += (ptrdiff_t)len + 1;\n  return (pos >= 0) ? pos : 0;\n}\n\n\nstatic int str_sub (lua_State *L) {\n  size_t l;\n  const char *s = luaL_checklstring(L, 1, &l);\n  ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l);\n  ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l);\n  if (start < 1) start = 1;\n  if (end > (ptrdiff_t)l) end = (ptrdiff_t)l;\n  if (start <= end)\n    lua_pushlstring(L, s+start-1, end-start+1);\n  else lua_pushliteral(L, \"\");\n  return 1;\n}\n\n\nstatic int str_reverse (lua_State *L) {\n  size_t l;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  luaL_buffinit(L, &b);\n  while (l--) luaL_addchar(&b, s[l]);\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int str_lower (lua_State *L) {\n  size_t l;\n  size_t i;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  luaL_buffinit(L, &b);\n  for (i=0; i<l; i++)\n    luaL_addchar(&b, tolower(uchar(s[i])));\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int str_upper (lua_State *L) {\n  size_t l;\n  size_t i;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  luaL_buffinit(L, &b);\n  for (i=0; i<l; i++)\n    luaL_addchar(&b, toupper(uchar(s[i])));\n  luaL_pushresult(&b);\n  return 1;\n}\n\nstatic int str_rep (lua_State *L) {\n  size_t l;\n  luaL_Buffer b;\n  const char *s = luaL_checklstring(L, 1, &l);\n  int n = luaL_checkint(L, 2);\n  luaL_buffinit(L, &b);\n  while (n-- > 0)\n    luaL_addlstring(&b, s, l);\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int str_byte (lua_State *L) {\n  size_t l;\n  const char *s = luaL_checklstring(L, 1, &l);\n  ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l);\n  ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l);\n  int n, i;\n  if (posi <= 0) posi = 1;\n  if ((size_t)pose > l) pose = l;\n  if (posi > pose) return 0;  /* empty interval; return no values */\n  n = (int)(pose -  posi + 1);\n  if (posi + n <= pose)  /* overflow? */\n    luaL_error(L, \"string slice too long\");\n  luaL_checkstack(L, n, \"string slice too long\");\n  for (i=0; i<n; i++)\n    lua_pushinteger(L, uchar(s[posi+i-1]));\n  return n;\n}\n\n\nstatic int str_char (lua_State *L) {\n  int n = lua_gettop(L);  /* number of arguments */\n  int i;\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  for (i=1; i<=n; i++) {\n    int c = luaL_checkint(L, i);\n    luaL_argcheck(L, uchar(c) == c, i, \"invalid value\");\n    luaL_addchar(&b, uchar(c));\n  }\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic int writer (lua_State *L, const void* b, size_t size, void* B) {\n  (void)L;\n  luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);\n  return 0;\n}\n\n\nstatic int str_dump (lua_State *L) {\n  luaL_Buffer b;\n  luaL_checktype(L, 1, LUA_TFUNCTION);\n  lua_settop(L, 1);\n  luaL_buffinit(L,&b);\n  if (lua_dump(L, writer, &b) != 0)\n    luaL_error(L, \"unable to dump given function\");\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\n\n/*\n** {======================================================\n** PATTERN MATCHING\n** =======================================================\n*/\n\n\n#define CAP_UNFINISHED\t(-1)\n#define CAP_POSITION\t(-2)\n\ntypedef struct MatchState {\n  const char *src_init;  /* init of source string */\n  const char *src_end;  /* end (`\\0') of source string */\n  lua_State *L;\n  int level;  /* total number of captures (finished or unfinished) */\n  struct {\n    const char *init;\n    ptrdiff_t len;\n  } capture[LUA_MAXCAPTURES];\n} MatchState;\n\n\n#define L_ESC\t\t'%'\n#define SPECIALS\t\"^$*+?.([%-\"\n\n\nstatic int check_capture (MatchState *ms, int l) {\n  l -= '1';\n  if (l < 0 || l >= ms->level || ms->capture[l].len == CAP_UNFINISHED)\n    return luaL_error(ms->L, \"invalid capture index\");\n  return l;\n}\n\n\nstatic int capture_to_close (MatchState *ms) {\n  int level = ms->level;\n  for (level--; level>=0; level--)\n    if (ms->capture[level].len == CAP_UNFINISHED) return level;\n  return luaL_error(ms->L, \"invalid pattern capture\");\n}\n\n\nstatic const char *classend (MatchState *ms, const char *p) {\n  switch (*p++) {\n    case L_ESC: {\n      if (*p == '\\0')\n        luaL_error(ms->L, \"malformed pattern (ends with \" LUA_QL(\"%%\") \")\");\n      return p+1;\n    }\n    case '[': {\n      if (*p == '^') p++;\n      do {  /* look for a `]' */\n        if (*p == '\\0')\n          luaL_error(ms->L, \"malformed pattern (missing \" LUA_QL(\"]\") \")\");\n        if (*(p++) == L_ESC && *p != '\\0')\n          p++;  /* skip escapes (e.g. `%]') */\n      } while (*p != ']');\n      return p+1;\n    }\n    default: {\n      return p;\n    }\n  }\n}\n\n\nstatic int match_class (int c, int cl) {\n  int res;\n  switch (tolower(cl)) {\n    case 'a' : res = isalpha(c); break;\n    case 'c' : res = iscntrl(c); break;\n    case 'd' : res = isdigit(c); break;\n    case 'l' : res = islower(c); break;\n    case 'p' : res = ispunct(c); break;\n    case 's' : res = isspace(c); break;\n    case 'u' : res = isupper(c); break;\n    case 'w' : res = isalnum(c); break;\n    case 'x' : res = isxdigit(c); break;\n    case 'z' : res = (c == 0); break;\n    default: return (cl == c);\n  }\n  return (islower(cl) ? res : !res);\n}\n\n\nstatic int matchbracketclass (int c, const char *p, const char *ec) {\n  int sig = 1;\n  if (*(p+1) == '^') {\n    sig = 0;\n    p++;  /* skip the `^' */\n  }\n  while (++p < ec) {\n    if (*p == L_ESC) {\n      p++;\n      if (match_class(c, uchar(*p)))\n        return sig;\n    }\n    else if ((*(p+1) == '-') && (p+2 < ec)) {\n      p+=2;\n      if (uchar(*(p-2)) <= c && c <= uchar(*p))\n        return sig;\n    }\n    else if (uchar(*p) == c) return sig;\n  }\n  return !sig;\n}\n\n\nstatic int singlematch (int c, const char *p, const char *ep) {\n  switch (*p) {\n    case '.': return 1;  /* matches any char */\n    case L_ESC: return match_class(c, uchar(*(p+1)));\n    case '[': return matchbracketclass(c, p, ep-1);\n    default:  return (uchar(*p) == c);\n  }\n}\n\n\nstatic const char *match (MatchState *ms, const char *s, const char *p);\n\n\nstatic const char *matchbalance (MatchState *ms, const char *s,\n                                   const char *p) {\n  if (*p == 0 || *(p+1) == 0)\n    luaL_error(ms->L, \"unbalanced pattern\");\n  if (*s != *p) return NULL;\n  else {\n    int b = *p;\n    int e = *(p+1);\n    int cont = 1;\n    while (++s < ms->src_end) {\n      if (*s == e) {\n        if (--cont == 0) return s+1;\n      }\n      else if (*s == b) cont++;\n    }\n  }\n  return NULL;  /* string ends out of balance */\n}\n\n\nstatic const char *max_expand (MatchState *ms, const char *s,\n                                 const char *p, const char *ep) {\n  ptrdiff_t i = 0;  /* counts maximum expand for item */\n  while ((s+i)<ms->src_end && singlematch(uchar(*(s+i)), p, ep))\n    i++;\n  /* keeps trying to match with the maximum repetitions */\n  while (i>=0) {\n    const char *res = match(ms, (s+i), ep+1);\n    if (res) return res;\n    i--;  /* else didn't match; reduce 1 repetition to try again */\n  }\n  return NULL;\n}\n\n\nstatic const char *min_expand (MatchState *ms, const char *s,\n                                 const char *p, const char *ep) {\n  for (;;) {\n    const char *res = match(ms, s, ep+1);\n    if (res != NULL)\n      return res;\n    else if (s<ms->src_end && singlematch(uchar(*s), p, ep))\n      s++;  /* try with one more repetition */\n    else return NULL;\n  }\n}\n\n\nstatic const char *start_capture (MatchState *ms, const char *s,\n                                    const char *p, int what) {\n  const char *res;\n  int level = ms->level;\n  if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, \"too many captures\");\n  ms->capture[level].init = s;\n  ms->capture[level].len = what;\n  ms->level = level+1;\n  if ((res=match(ms, s, p)) == NULL)  /* match failed? */\n    ms->level--;  /* undo capture */\n  return res;\n}\n\n\nstatic const char *end_capture (MatchState *ms, const char *s,\n                                  const char *p) {\n  int l = capture_to_close(ms);\n  const char *res;\n  ms->capture[l].len = s - ms->capture[l].init;  /* close capture */\n  if ((res = match(ms, s, p)) == NULL)  /* match failed? */\n    ms->capture[l].len = CAP_UNFINISHED;  /* undo capture */\n  return res;\n}\n\n\nstatic const char *match_capture (MatchState *ms, const char *s, int l) {\n  size_t len;\n  l = check_capture(ms, l);\n  len = ms->capture[l].len;\n  if ((size_t)(ms->src_end-s) >= len &&\n      memcmp(ms->capture[l].init, s, len) == 0)\n    return s+len;\n  else return NULL;\n}\n\n\nstatic const char *match (MatchState *ms, const char *s, const char *p) {\n  init: /* using goto's to optimize tail recursion */\n  switch (*p) {\n    case '(': {  /* start capture */\n      if (*(p+1) == ')')  /* position capture? */\n        return start_capture(ms, s, p+2, CAP_POSITION);\n      else\n        return start_capture(ms, s, p+1, CAP_UNFINISHED);\n    }\n    case ')': {  /* end capture */\n      return end_capture(ms, s, p+1);\n    }\n    case L_ESC: {\n      switch (*(p+1)) {\n        case 'b': {  /* balanced string? */\n          s = matchbalance(ms, s, p+2);\n          if (s == NULL) return NULL;\n          p+=4; goto init;  /* else return match(ms, s, p+4); */\n        }\n        case 'f': {  /* frontier? */\n          const char *ep; char previous;\n          p += 2;\n          if (*p != '[')\n            luaL_error(ms->L, \"missing \" LUA_QL(\"[\") \" after \"\n                               LUA_QL(\"%%f\") \" in pattern\");\n          ep = classend(ms, p);  /* points to what is next */\n          previous = (s == ms->src_init) ? '\\0' : *(s-1);\n          if (matchbracketclass(uchar(previous), p, ep-1) ||\n             !matchbracketclass(uchar(*s), p, ep-1)) return NULL;\n          p=ep; goto init;  /* else return match(ms, s, ep); */\n        }\n        default: {\n          if (isdigit(uchar(*(p+1)))) {  /* capture results (%0-%9)? */\n            s = match_capture(ms, s, uchar(*(p+1)));\n            if (s == NULL) return NULL;\n            p+=2; goto init;  /* else return match(ms, s, p+2) */\n          }\n          goto dflt;  /* case default */\n        }\n      }\n    }\n    case '\\0': {  /* end of pattern */\n      return s;  /* match succeeded */\n    }\n    case '$': {\n      if (*(p+1) == '\\0')  /* is the `$' the last char in pattern? */\n        return (s == ms->src_end) ? s : NULL;  /* check end of string */\n      else goto dflt;\n    }\n    default: dflt: {  /* it is a pattern item */\n      const char *ep = classend(ms, p);  /* points to what is next */\n      int m = s<ms->src_end && singlematch(uchar(*s), p, ep);\n      switch (*ep) {\n        case '?': {  /* optional */\n          const char *res;\n          if (m && ((res=match(ms, s+1, ep+1)) != NULL))\n            return res;\n          p=ep+1; goto init;  /* else return match(ms, s, ep+1); */\n        }\n        case '*': {  /* 0 or more repetitions */\n          return max_expand(ms, s, p, ep);\n        }\n        case '+': {  /* 1 or more repetitions */\n          return (m ? max_expand(ms, s+1, p, ep) : NULL);\n        }\n        case '-': {  /* 0 or more repetitions (minimum) */\n          return min_expand(ms, s, p, ep);\n        }\n        default: {\n          if (!m) return NULL;\n          s++; p=ep; goto init;  /* else return match(ms, s+1, ep); */\n        }\n      }\n    }\n  }\n}\n\n\n\nstatic const char *lmemfind (const char *s1, size_t l1,\n                               const char *s2, size_t l2) {\n  if (l2 == 0) return s1;  /* empty strings are everywhere */\n  else if (l2 > l1) return NULL;  /* avoids a negative `l1' */\n  else {\n    const char *init;  /* to search for a `*s2' inside `s1' */\n    l2--;  /* 1st char will be checked by `memchr' */\n    l1 = l1-l2;  /* `s2' cannot be found after that */\n    while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {\n      init++;   /* 1st char is already checked */\n      if (memcmp(init, s2+1, l2) == 0)\n        return init-1;\n      else {  /* correct `l1' and `s1' to try again */\n        l1 -= init-s1;\n        s1 = init;\n      }\n    }\n    return NULL;  /* not found */\n  }\n}\n\n\nstatic void push_onecapture (MatchState *ms, int i, const char *s,\n                                                    const char *e) {\n  if (i >= ms->level) {\n    if (i == 0)  /* ms->level == 0, too */\n      lua_pushlstring(ms->L, s, e - s);  /* add whole match */\n    else\n      luaL_error(ms->L, \"invalid capture index\");\n  }\n  else {\n    ptrdiff_t l = ms->capture[i].len;\n    if (l == CAP_UNFINISHED) luaL_error(ms->L, \"unfinished capture\");\n    if (l == CAP_POSITION)\n      lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1);\n    else\n      lua_pushlstring(ms->L, ms->capture[i].init, l);\n  }\n}\n\n\nstatic int push_captures (MatchState *ms, const char *s, const char *e) {\n  int i;\n  int nlevels = (ms->level == 0 && s) ? 1 : ms->level;\n  luaL_checkstack(ms->L, nlevels, \"too many captures\");\n  for (i = 0; i < nlevels; i++)\n    push_onecapture(ms, i, s, e);\n  return nlevels;  /* number of strings pushed */\n}\n\n\nstatic int str_find_aux (lua_State *L, int find) {\n  size_t l1, l2;\n  const char *s = luaL_checklstring(L, 1, &l1);\n  const char *p = luaL_checklstring(L, 2, &l2);\n  ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1;\n  if (init < 0) init = 0;\n  else if ((size_t)(init) > l1) init = (ptrdiff_t)l1;\n  if (find && (lua_toboolean(L, 4) ||  /* explicit request? */\n      strpbrk(p, SPECIALS) == NULL)) {  /* or no special characters? */\n    /* do a plain search */\n    const char *s2 = lmemfind(s+init, l1-init, p, l2);\n    if (s2) {\n      lua_pushinteger(L, s2-s+1);\n      lua_pushinteger(L, s2-s+l2);\n      return 2;\n    }\n  }\n  else {\n    MatchState ms;\n    int anchor = (*p == '^') ? (p++, 1) : 0;\n    const char *s1=s+init;\n    ms.L = L;\n    ms.src_init = s;\n    ms.src_end = s+l1;\n    do {\n      const char *res;\n      ms.level = 0;\n      if ((res=match(&ms, s1, p)) != NULL) {\n        if (find) {\n          lua_pushinteger(L, s1-s+1);  /* start */\n          lua_pushinteger(L, res-s);   /* end */\n          return push_captures(&ms, NULL, 0) + 2;\n        }\n        else\n          return push_captures(&ms, s1, res);\n      }\n    } while (s1++ < ms.src_end && !anchor);\n  }\n  lua_pushnil(L);  /* not found */\n  return 1;\n}\n\n\nstatic int str_find (lua_State *L) {\n  return str_find_aux(L, 1);\n}\n\n\nstatic int str_match (lua_State *L) {\n  return str_find_aux(L, 0);\n}\n\n\nstatic int gmatch_aux (lua_State *L) {\n  MatchState ms;\n  size_t ls;\n  const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);\n  const char *p = lua_tostring(L, lua_upvalueindex(2));\n  const char *src;\n  ms.L = L;\n  ms.src_init = s;\n  ms.src_end = s+ls;\n  for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3));\n       src <= ms.src_end;\n       src++) {\n    const char *e;\n    ms.level = 0;\n    if ((e = match(&ms, src, p)) != NULL) {\n      lua_Integer newstart = e-s;\n      if (e == src) newstart++;  /* empty match? go at least one position */\n      lua_pushinteger(L, newstart);\n      lua_replace(L, lua_upvalueindex(3));\n      return push_captures(&ms, src, e);\n    }\n  }\n  return 0;  /* not found */\n}\n\n\nstatic int gmatch (lua_State *L) {\n  luaL_checkstring(L, 1);\n  luaL_checkstring(L, 2);\n  lua_settop(L, 2);\n  lua_pushinteger(L, 0);\n  lua_pushcclosure(L, gmatch_aux, 3);\n  return 1;\n}\n\n\nstatic int gfind_nodef (lua_State *L) {\n  return luaL_error(L, LUA_QL(\"string.gfind\") \" was renamed to \"\n                       LUA_QL(\"string.gmatch\"));\n}\n\n\nstatic void add_s (MatchState *ms, luaL_Buffer *b, const char *s,\n                                                   const char *e) {\n  size_t l, i;\n  const char *news = lua_tolstring(ms->L, 3, &l);\n  for (i = 0; i < l; i++) {\n    if (news[i] != L_ESC)\n      luaL_addchar(b, news[i]);\n    else {\n      i++;  /* skip ESC */\n      if (!isdigit(uchar(news[i])))\n        luaL_addchar(b, news[i]);\n      else if (news[i] == '0')\n          luaL_addlstring(b, s, e - s);\n      else {\n        push_onecapture(ms, news[i] - '1', s, e);\n        luaL_addvalue(b);  /* add capture to accumulated result */\n      }\n    }\n  }\n}\n\n\nstatic void add_value (MatchState *ms, luaL_Buffer *b, const char *s,\n                                                       const char *e) {\n  lua_State *L = ms->L;\n  switch (lua_type(L, 3)) {\n    case LUA_TNUMBER:\n    case LUA_TSTRING: {\n      add_s(ms, b, s, e);\n      return;\n    }\n    case LUA_TFUNCTION: {\n      int n;\n      lua_pushvalue(L, 3);\n      n = push_captures(ms, s, e);\n      lua_call(L, n, 1);\n      break;\n    }\n    case LUA_TTABLE: {\n      push_onecapture(ms, 0, s, e);\n      lua_gettable(L, 3);\n      break;\n    }\n  }\n  if (!lua_toboolean(L, -1)) {  /* nil or false? */\n    lua_pop(L, 1);\n    lua_pushlstring(L, s, e - s);  /* keep original text */\n  }\n  else if (!lua_isstring(L, -1))\n    luaL_error(L, \"invalid replacement value (a %s)\", luaL_typename(L, -1)); \n  luaL_addvalue(b);  /* add result to accumulator */\n}\n\n\nstatic int str_gsub (lua_State *L) {\n  size_t srcl;\n  const char *src = luaL_checklstring(L, 1, &srcl);\n  const char *p = luaL_checkstring(L, 2);\n  int  tr = lua_type(L, 3);\n  int max_s = luaL_optint(L, 4, srcl+1);\n  int anchor = (*p == '^') ? (p++, 1) : 0;\n  int n = 0;\n  MatchState ms;\n  luaL_Buffer b;\n  luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING ||\n                   tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3,\n                      \"string/function/table expected\");\n  luaL_buffinit(L, &b);\n  ms.L = L;\n  ms.src_init = src;\n  ms.src_end = src+srcl;\n  while (n < max_s) {\n    const char *e;\n    ms.level = 0;\n    e = match(&ms, src, p);\n    if (e) {\n      n++;\n      add_value(&ms, &b, src, e);\n    }\n    if (e && e>src) /* non empty match? */\n      src = e;  /* skip it */\n    else if (src < ms.src_end)\n      luaL_addchar(&b, *src++);\n    else break;\n    if (anchor) break;\n  }\n  luaL_addlstring(&b, src, ms.src_end-src);\n  luaL_pushresult(&b);\n  lua_pushinteger(L, n);  /* number of substitutions */\n  return 2;\n}\n\n/* }====================================================== */\n\n\n/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */\n#define MAX_ITEM\t512\n/* valid flags in a format specification */\n#define FLAGS\t\"-+ #0\"\n/*\n** maximum size of each format specification (such as '%-099.99d')\n** (+10 accounts for %99.99x plus margin of error)\n*/\n#define MAX_FORMAT\t(sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10)\n\n\nstatic void addquoted (lua_State *L, luaL_Buffer *b, int arg) {\n  size_t l;\n  const char *s = luaL_checklstring(L, arg, &l);\n  luaL_addchar(b, '\"');\n  while (l--) {\n    switch (*s) {\n      case '\"': case '\\\\': case '\\n': {\n        luaL_addchar(b, '\\\\');\n        luaL_addchar(b, *s);\n        break;\n      }\n      case '\\r': {\n        luaL_addlstring(b, \"\\\\r\", 2);\n        break;\n      }\n      case '\\0': {\n        luaL_addlstring(b, \"\\\\000\", 4);\n        break;\n      }\n      default: {\n        luaL_addchar(b, *s);\n        break;\n      }\n    }\n    s++;\n  }\n  luaL_addchar(b, '\"');\n}\n\nstatic const char *scanformat (lua_State *L, const char *strfrmt, char *form) {\n  const char *p = strfrmt;\n  while (*p != '\\0' && strchr(FLAGS, *p) != NULL) p++;  /* skip flags */\n  if ((size_t)(p - strfrmt) >= sizeof(FLAGS))\n    luaL_error(L, \"invalid format (repeated flags)\");\n  if (isdigit(uchar(*p))) p++;  /* skip width */\n  if (isdigit(uchar(*p))) p++;  /* (2 digits at most) */\n  if (*p == '.') {\n    p++;\n    if (isdigit(uchar(*p))) p++;  /* skip precision */\n    if (isdigit(uchar(*p))) p++;  /* (2 digits at most) */\n  }\n  if (isdigit(uchar(*p)))\n    luaL_error(L, \"invalid format (width or precision too long)\");\n  *(form++) = '%';\n  strncpy(form, strfrmt, p - strfrmt + 1);\n  form += p - strfrmt + 1;\n  *form = '\\0';\n  return p;\n}\n\n\nstatic void addintlen (char *form) {\n  size_t l = strlen(form);\n  char spec = form[l - 1];\n  strcpy(form + l - 1, LUA_INTFRMLEN);\n  form[l + sizeof(LUA_INTFRMLEN) - 2] = spec;\n  form[l + sizeof(LUA_INTFRMLEN) - 1] = '\\0';\n}\n\n\nstatic int str_format (lua_State *L) {\n  int top = lua_gettop(L);\n  int arg = 1;\n  size_t sfl;\n  const char *strfrmt = luaL_checklstring(L, arg, &sfl);\n  const char *strfrmt_end = strfrmt+sfl;\n  luaL_Buffer b;\n  luaL_buffinit(L, &b);\n  while (strfrmt < strfrmt_end) {\n    if (*strfrmt != L_ESC)\n      luaL_addchar(&b, *strfrmt++);\n    else if (*++strfrmt == L_ESC)\n      luaL_addchar(&b, *strfrmt++);  /* %% */\n    else { /* format item */\n      char form[MAX_FORMAT];  /* to store the format (`%...') */\n      char buff[MAX_ITEM];  /* to store the formatted item */\n      if (++arg > top)\n        luaL_argerror(L, arg, \"no value\");\n      strfrmt = scanformat(L, strfrmt, form);\n      switch (*strfrmt++) {\n        case 'c': {\n          sprintf(buff, form, (int)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'd':  case 'i': {\n          addintlen(form);\n          sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'o':  case 'u':  case 'x':  case 'X': {\n          addintlen(form);\n          sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'e':  case 'E': case 'f':\n        case 'g': case 'G': {\n          sprintf(buff, form, (double)luaL_checknumber(L, arg));\n          break;\n        }\n        case 'q': {\n          addquoted(L, &b, arg);\n          continue;  /* skip the 'addsize' at the end */\n        }\n        case 's': {\n          size_t l;\n          const char *s = luaL_checklstring(L, arg, &l);\n          if (!strchr(form, '.') && l >= 100) {\n            /* no precision and string is too long to be formatted;\n               keep original string */\n            lua_pushvalue(L, arg);\n            luaL_addvalue(&b);\n            continue;  /* skip the `addsize' at the end */\n          }\n          else {\n            sprintf(buff, form, s);\n            break;\n          }\n        }\n        default: {  /* also treat cases `pnLlh' */\n          return luaL_error(L, \"invalid option \" LUA_QL(\"%%%c\") \" to \"\n                               LUA_QL(\"format\"), *(strfrmt - 1));\n        }\n      }\n      luaL_addlstring(&b, buff, strlen(buff));\n    }\n  }\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\nstatic const luaL_Reg strlib[] = {\n  {\"byte\", str_byte},\n  {\"char\", str_char},\n  {\"dump\", str_dump},\n  {\"find\", str_find},\n  {\"format\", str_format},\n  {\"gfind\", gfind_nodef},\n  {\"gmatch\", gmatch},\n  {\"gsub\", str_gsub},\n  {\"len\", str_len},\n  {\"lower\", str_lower},\n  {\"match\", str_match},\n  {\"rep\", str_rep},\n  {\"reverse\", str_reverse},\n  {\"sub\", str_sub},\n  {\"upper\", str_upper},\n  {NULL, NULL}\n};\n\n\nstatic void createmetatable (lua_State *L) {\n  lua_createtable(L, 0, 1);  /* create metatable for strings */\n  lua_pushliteral(L, \"\");  /* dummy string */\n  lua_pushvalue(L, -2);\n  lua_setmetatable(L, -2);  /* set string metatable */\n  lua_pop(L, 1);  /* pop dummy string */\n  lua_pushvalue(L, -2);  /* string library... */\n  lua_setfield(L, -2, \"__index\");  /* ...is the __index metamethod */\n  lua_pop(L, 1);  /* pop metatable */\n}\n\n\n/*\n** Open string library\n*/\nLUALIB_API int luaopen_string (lua_State *L) {\n  luaL_register(L, LUA_STRLIBNAME, strlib);\n#if defined(LUA_COMPAT_GFIND)\n  lua_getfield(L, -1, \"gmatch\");\n  lua_setfield(L, -2, \"gfind\");\n#endif\n  createmetatable(L);\n  return 1;\n}\n\n"
  },
  {
    "path": "src/lua/ltable.c",
    "content": "/*\n** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $\n** Lua tables (hash)\n** See Copyright Notice in lua.h\n*/\n\n\n/*\n** Implementation of tables (aka arrays, objects, or hash tables).\n** Tables keep its elements in two parts: an array part and a hash part.\n** Non-negative integer keys are all candidates to be kept in the array\n** part. The actual size of the array is the largest `n' such that at\n** least half the slots between 0 and n are in use.\n** Hash uses a mix of chained scatter table with Brent's variation.\n** A main invariant of these tables is that, if an element is not\n** in its main position (i.e. the `original' position that its hash gives\n** to it), then the colliding element is in its own main position.\n** Hence even when the load factor reaches 100%, performance remains good.\n*/\n\n#include <math.h>\n#include <string.h>\n\n#define ltable_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lgc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"ltable.h\"\n\n\n/*\n** max size of array part is 2^MAXBITS\n*/\n#if LUAI_BITSINT > 26\n#define MAXBITS\t\t26\n#else\n#define MAXBITS\t\t(LUAI_BITSINT-2)\n#endif\n\n#define MAXASIZE\t(1 << MAXBITS)\n\n\n#define hashpow2(t,n)      (gnode(t, lmod((n), sizenode(t))))\n  \n#define hashstr(t,str)  hashpow2(t, (str)->tsv.hash)\n#define hashboolean(t,p)        hashpow2(t, p)\n\n\n/*\n** for some types, it is better to avoid modulus by power of 2, as\n** they tend to have many 2 factors.\n*/\n#define hashmod(t,n)\t(gnode(t, ((n) % ((sizenode(t)-1)|1))))\n\n\n#define hashpointer(t,p)\thashmod(t, IntPoint(p))\n\n\n/*\n** number of ints inside a lua_Number\n*/\n#define numints\t\tcast_int(sizeof(lua_Number)/sizeof(int))\n\n\n\n#define dummynode\t\t(&dummynode_)\n\nstatic const Node dummynode_ = {\n  {{NULL}, LUA_TNIL},  /* value */\n  {{{NULL}, LUA_TNIL, NULL}}  /* key */\n};\n\n\n/*\n** hash for lua_Numbers\n*/\nstatic Node *hashnum (const Table *t, lua_Number n) {\n  unsigned int a[numints];\n  int i;\n  if (luai_numeq(n, 0))  /* avoid problems with -0 */\n    return gnode(t, 0);\n  memcpy(a, &n, sizeof(a));\n  for (i = 1; i < numints; i++) a[0] += a[i];\n  return hashmod(t, a[0]);\n}\n\n\n\n/*\n** returns the `main' position of an element in a table (that is, the index\n** of its hash value)\n*/\nstatic Node *mainposition (const Table *t, const TValue *key) {\n  switch (ttype(key)) {\n    case LUA_TNUMBER:\n      return hashnum(t, nvalue(key));\n    case LUA_TSTRING:\n      return hashstr(t, rawtsvalue(key));\n    case LUA_TBOOLEAN:\n      return hashboolean(t, bvalue(key));\n    case LUA_TLIGHTUSERDATA:\n      return hashpointer(t, pvalue(key));\n    default:\n      return hashpointer(t, gcvalue(key));\n  }\n}\n\n\n/*\n** returns the index for `key' if `key' is an appropriate key to live in\n** the array part of the table, -1 otherwise.\n*/\nstatic int arrayindex (const TValue *key) {\n  if (ttisnumber(key)) {\n    lua_Number n = nvalue(key);\n    int k;\n    lua_number2int(k, n);\n    if (luai_numeq(cast_num(k), n))\n      return k;\n  }\n  return -1;  /* `key' did not match some condition */\n}\n\n\n/*\n** returns the index of a `key' for table traversals. First goes all\n** elements in the array part, then elements in the hash part. The\n** beginning of a traversal is signalled by -1.\n*/\nstatic int findindex (lua_State *L, Table *t, StkId key) {\n  int i;\n  if (ttisnil(key)) return -1;  /* first iteration */\n  i = arrayindex(key);\n  if (0 < i && i <= t->sizearray)  /* is `key' inside array part? */\n    return i-1;  /* yes; that's the index (corrected to C) */\n  else {\n    Node *n = mainposition(t, key);\n    do {  /* check whether `key' is somewhere in the chain */\n      /* key may be dead already, but it is ok to use it in `next' */\n      if (luaO_rawequalObj(key2tval(n), key) ||\n            (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) &&\n             gcvalue(gkey(n)) == gcvalue(key))) {\n        i = cast_int(n - gnode(t, 0));  /* key index in hash table */\n        /* hash elements are numbered after array ones */\n        return i + t->sizearray;\n      }\n      else n = gnext(n);\n    } while (n);\n    luaG_runerror(L, \"invalid key to \" LUA_QL(\"next\"));  /* key not found */\n    return 0;  /* to avoid warnings */\n  }\n}\n\n\nint luaH_next (lua_State *L, Table *t, StkId key) {\n  int i = findindex(L, t, key);  /* find original element */\n  for (i++; i < t->sizearray; i++) {  /* try first array part */\n    if (!ttisnil(&t->array[i])) {  /* a non-nil value? */\n      setnvalue(key, cast_num(i+1));\n      setobj2s(L, key+1, &t->array[i]);\n      return 1;\n    }\n  }\n  for (i -= t->sizearray; i < sizenode(t); i++) {  /* then hash part */\n    if (!ttisnil(gval(gnode(t, i)))) {  /* a non-nil value? */\n      setobj2s(L, key, key2tval(gnode(t, i)));\n      setobj2s(L, key+1, gval(gnode(t, i)));\n      return 1;\n    }\n  }\n  return 0;  /* no more elements */\n}\n\n\n/*\n** {=============================================================\n** Rehash\n** ==============================================================\n*/\n\n\nstatic int computesizes (int nums[], int *narray) {\n  int i;\n  int twotoi;  /* 2^i */\n  int a = 0;  /* number of elements smaller than 2^i */\n  int na = 0;  /* number of elements to go to array part */\n  int n = 0;  /* optimal size for array part */\n  for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) {\n    if (nums[i] > 0) {\n      a += nums[i];\n      if (a > twotoi/2) {  /* more than half elements present? */\n        n = twotoi;  /* optimal size (till now) */\n        na = a;  /* all elements smaller than n will go to array part */\n      }\n    }\n    if (a == *narray) break;  /* all elements already counted */\n  }\n  *narray = n;\n  lua_assert(*narray/2 <= na && na <= *narray);\n  return na;\n}\n\n\nstatic int countint (const TValue *key, int *nums) {\n  int k = arrayindex(key);\n  if (0 < k && k <= MAXASIZE) {  /* is `key' an appropriate array index? */\n    nums[ceillog2(k)]++;  /* count as such */\n    return 1;\n  }\n  else\n    return 0;\n}\n\n\nstatic int numusearray (const Table *t, int *nums) {\n  int lg;\n  int ttlg;  /* 2^lg */\n  int ause = 0;  /* summation of `nums' */\n  int i = 1;  /* count to traverse all array keys */\n  for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) {  /* for each slice */\n    int lc = 0;  /* counter */\n    int lim = ttlg;\n    if (lim > t->sizearray) {\n      lim = t->sizearray;  /* adjust upper limit */\n      if (i > lim)\n        break;  /* no more elements to count */\n    }\n    /* count elements in range (2^(lg-1), 2^lg] */\n    for (; i <= lim; i++) {\n      if (!ttisnil(&t->array[i-1]))\n        lc++;\n    }\n    nums[lg] += lc;\n    ause += lc;\n  }\n  return ause;\n}\n\n\nstatic int numusehash (const Table *t, int *nums, int *pnasize) {\n  int totaluse = 0;  /* total number of elements */\n  int ause = 0;  /* summation of `nums' */\n  int i = sizenode(t);\n  while (i--) {\n    Node *n = &t->node[i];\n    if (!ttisnil(gval(n))) {\n      ause += countint(key2tval(n), nums);\n      totaluse++;\n    }\n  }\n  *pnasize += ause;\n  return totaluse;\n}\n\n\nstatic void setarrayvector (lua_State *L, Table *t, int size) {\n  int i;\n  luaM_reallocvector(L, t->array, t->sizearray, size, TValue);\n  for (i=t->sizearray; i<size; i++)\n     setnilvalue(&t->array[i]);\n  t->sizearray = size;\n}\n\n\nstatic void setnodevector (lua_State *L, Table *t, int size) {\n  int lsize;\n  if (size == 0) {  /* no elements to hash part? */\n    t->node = cast(Node *, dummynode);  /* use common `dummynode' */\n    lsize = 0;\n  }\n  else {\n    int i;\n    lsize = ceillog2(size);\n    if (lsize > MAXBITS)\n      luaG_runerror(L, \"table overflow\");\n    size = twoto(lsize);\n    t->node = luaM_newvector(L, size, Node);\n    for (i=0; i<size; i++) {\n      Node *n = gnode(t, i);\n      gnext(n) = NULL;\n      setnilvalue(gkey(n));\n      setnilvalue(gval(n));\n    }\n  }\n  t->lsizenode = cast_byte(lsize);\n  t->lastfree = gnode(t, size);  /* all positions are free */\n}\n\n\nstatic void resize (lua_State *L, Table *t, int nasize, int nhsize) {\n  int i;\n  int oldasize = t->sizearray;\n  int oldhsize = t->lsizenode;\n  Node *nold = t->node;  /* save old hash ... */\n  if (nasize > oldasize)  /* array part must grow? */\n    setarrayvector(L, t, nasize);\n  /* create new hash part with appropriate size */\n  setnodevector(L, t, nhsize);  \n  if (nasize < oldasize) {  /* array part must shrink? */\n    t->sizearray = nasize;\n    /* re-insert elements from vanishing slice */\n    for (i=nasize; i<oldasize; i++) {\n      if (!ttisnil(&t->array[i]))\n        setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);\n    }\n    /* shrink array */\n    luaM_reallocvector(L, t->array, oldasize, nasize, TValue);\n  }\n  /* re-insert elements from hash part */\n  for (i = twoto(oldhsize) - 1; i >= 0; i--) {\n    Node *old = nold+i;\n    if (!ttisnil(gval(old)))\n      setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));\n  }\n  if (nold != dummynode)\n    luaM_freearray(L, nold, (size_t)twoto(oldhsize), Node);  /* free old array */\n}\n\n\nvoid luaH_resizearray (lua_State *L, Table *t, int nasize) {\n  int nsize = (t->node == dummynode) ? 0 : sizenode(t);\n  resize(L, t, nasize, nsize);\n}\n\n\nstatic void rehash (lua_State *L, Table *t, const TValue *ek) {\n  int nasize, na;\n  int nums[MAXBITS+1];  /* nums[i] = number of keys between 2^(i-1) and 2^i */\n  int i;\n  int totaluse;\n  for (i=0; i<=MAXBITS; i++) nums[i] = 0;  /* reset counts */\n  nasize = numusearray(t, nums);  /* count keys in array part */\n  totaluse = nasize;  /* all those keys are integer keys */\n  totaluse += numusehash(t, nums, &nasize);  /* count keys in hash part */\n  /* count extra key */\n  nasize += countint(ek, nums);\n  totaluse++;\n  /* compute new size for array part */\n  na = computesizes(nums, &nasize);\n  /* resize the table to new computed sizes */\n  resize(L, t, nasize, totaluse - na);\n}\n\n\n\n/*\n** }=============================================================\n*/\n\n\nTable *luaH_new (lua_State *L, int narray, int nhash) {\n  Table *t = luaM_new(L, Table);\n  luaC_link(L, obj2gco(t), LUA_TTABLE);\n  t->metatable = NULL;\n  t->flags = cast_byte(~0);\n  /* temporary values (kept only if some malloc fails) */\n  t->array = NULL;\n  t->sizearray = 0;\n  t->lsizenode = 0;\n  t->node = cast(Node *, dummynode);\n  setarrayvector(L, t, narray);\n  setnodevector(L, t, nhash);\n  return t;\n}\n\n\nvoid luaH_free (lua_State *L, Table *t) {\n  if (t->node != dummynode)\n    luaM_freearray(L, t->node, (size_t)sizenode(t), Node);\n  luaM_freearray(L, t->array, t->sizearray, TValue);\n  luaM_free(L, t);\n}\n\n\nstatic Node *getfreepos (Table *t) {\n  while (t->lastfree-- > t->node) {\n    if (ttisnil(gkey(t->lastfree)))\n      return t->lastfree;\n  }\n  return NULL;  /* could not find a free place */\n}\n\n\n\n/*\n** inserts a new key into a hash table; first, check whether key's main \n** position is free. If not, check whether colliding node is in its main \n** position or not: if it is not, move colliding node to an empty place and \n** put new key in its main position; otherwise (colliding node is in its main \n** position), new key goes to an empty position. \n*/\nstatic TValue *newkey (lua_State *L, Table *t, const TValue *key) {\n  Node *mp = mainposition(t, key);\n  if (!ttisnil(gval(mp)) || mp == dummynode) {\n    Node *othern;\n    Node *n = getfreepos(t);  /* get a free place */\n    if (n == NULL) {  /* cannot find a free place? */\n      rehash(L, t, key);  /* grow table */\n      return luaH_set(L, t, key);  /* re-insert key into grown table */\n    }\n    lua_assert(n != dummynode);\n    othern = mainposition(t, key2tval(mp));\n    if (othern != mp) {  /* is colliding node out of its main position? */\n      /* yes; move colliding node into free position */\n      while (gnext(othern) != mp) othern = gnext(othern);  /* find previous */\n      gnext(othern) = n;  /* redo the chain with `n' in place of `mp' */\n      *n = *mp;  /* copy colliding node into free pos. (mp->next also goes) */\n      gnext(mp) = NULL;  /* now `mp' is free */\n      setnilvalue(gval(mp));\n    }\n    else {  /* colliding node is in its own main position */\n      /* new node will go into free position */\n      gnext(n) = gnext(mp);  /* chain new position */\n      gnext(mp) = n;\n      mp = n;\n    }\n  }\n  gkey(mp)->value = key->value; gkey(mp)->tt = key->tt;\n  luaC_barriert(L, t, key);\n  lua_assert(ttisnil(gval(mp)));\n  return gval(mp);\n}\n\n\n/*\n** search function for integers\n*/\nconst TValue *luaH_getnum (Table *t, int key) {\n  /* (1 <= key && key <= t->sizearray) */\n  if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray))\n    return &t->array[key-1];\n  else {\n    lua_Number nk = cast_num(key);\n    Node *n = hashnum(t, nk);\n    do {  /* check whether `key' is somewhere in the chain */\n      if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk))\n        return gval(n);  /* that's it */\n      else n = gnext(n);\n    } while (n);\n    return luaO_nilobject;\n  }\n}\n\n\n/*\n** search function for strings\n*/\nconst TValue *luaH_getstr (Table *t, TString *key) {\n  Node *n = hashstr(t, key);\n  do {  /* check whether `key' is somewhere in the chain */\n    if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key)\n      return gval(n);  /* that's it */\n    else n = gnext(n);\n  } while (n);\n  return luaO_nilobject;\n}\n\n\n/*\n** main search function\n*/\nconst TValue *luaH_get (Table *t, const TValue *key) {\n  switch (ttype(key)) {\n    case LUA_TNIL: return luaO_nilobject;\n    case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key));\n    case LUA_TNUMBER: {\n      int k;\n      lua_Number n = nvalue(key);\n      lua_number2int(k, n);\n      if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */\n        return luaH_getnum(t, k);  /* use specialized version */\n      /* else go through */\n    }\n    /* FALLTHRU */\n    default: {\n      Node *n = mainposition(t, key);\n      do {  /* check whether `key' is somewhere in the chain */\n        if (luaO_rawequalObj(key2tval(n), key))\n          return gval(n);  /* that's it */\n        else n = gnext(n);\n      } while (n);\n      return luaO_nilobject;\n    }\n  }\n}\n\n\nTValue *luaH_set (lua_State *L, Table *t, const TValue *key) {\n  const TValue *p = luaH_get(t, key);\n  t->flags = 0;\n  if (p != luaO_nilobject)\n    return cast(TValue *, p);\n  else {\n    if (ttisnil(key)) luaG_runerror(L, \"table index is nil\");\n    else if (ttisnumber(key) && luai_numisnan(nvalue(key)))\n      luaG_runerror(L, \"table index is NaN\");\n    return newkey(L, t, key);\n  }\n}\n\n\nTValue *luaH_setnum (lua_State *L, Table *t, int key) {\n  const TValue *p = luaH_getnum(t, key);\n  if (p != luaO_nilobject)\n    return cast(TValue *, p);\n  else {\n    TValue k;\n    setnvalue(&k, cast_num(key));\n    return newkey(L, t, &k);\n  }\n}\n\n\nTValue *luaH_setstr (lua_State *L, Table *t, TString *key) {\n  const TValue *p = luaH_getstr(t, key);\n  if (p != luaO_nilobject)\n    return cast(TValue *, p);\n  else {\n    TValue k;\n    setsvalue(L, &k, key);\n    return newkey(L, t, &k);\n  }\n}\n\n\nstatic int unbound_search (Table *t, unsigned int j) {\n  unsigned int i = j;  /* i is zero or a present index */\n  j++;\n  /* find `i' and `j' such that i is present and j is not */\n  while (!ttisnil(luaH_getnum(t, j))) {\n    i = j;\n    j *= 2;\n    if (j > cast(unsigned int, MAX_INT)) {  /* overflow? */\n      /* table was built with bad purposes: resort to linear search */\n      i = 1;\n      while (!ttisnil(luaH_getnum(t, i))) i++;\n      return i - 1;\n    }\n  }\n  /* now do a binary search between them */\n  while (j - i > 1) {\n    unsigned int m = (i+j)/2;\n    if (ttisnil(luaH_getnum(t, m))) j = m;\n    else i = m;\n  }\n  return i;\n}\n\n\n/*\n** Try to find a boundary in table `t'. A `boundary' is an integer index\n** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).\n*/\nint luaH_getn (Table *t) {\n  unsigned int j = t->sizearray;\n  if (j > 0 && ttisnil(&t->array[j - 1])) {\n    /* there is a boundary in the array part: (binary) search for it */\n    unsigned int i = 0;\n    while (j - i > 1) {\n      unsigned int m = (i+j)/2;\n      if (ttisnil(&t->array[m - 1])) j = m;\n      else i = m;\n    }\n    return i;\n  }\n  /* else must find a boundary in hash part */\n  else if (t->node == dummynode)  /* hash part is empty? */\n    return j;  /* that is easy... */\n  else return unbound_search(t, j);\n}\n\n\nint luaH_type (Table *t) {\n  if (t->sizearray == 0) {\n    return t->node == dummynode ? LUA_TTEMPTY : LUA_TTHASH;\n  }\n  return t->node == dummynode ? LUA_TTARRAY : LUA_TTMIXED;\n}\n\n\n#if defined(LUA_DEBUG)\n\nNode *luaH_mainposition (const Table *t, const TValue *key) {\n  return mainposition(t, key);\n}\n\nint luaH_isdummy (Node *n) { return n == dummynode; }\n\n#endif\n"
  },
  {
    "path": "src/lua/ltable.h",
    "content": "/*\n** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua tables (hash)\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ltable_h\n#define ltable_h\n\n#include \"lobject.h\"\n\n\n#define gnode(t,i)\t(&(t)->node[i])\n#define gkey(n)\t\t(&(n)->i_key.nk)\n#define gval(n)\t\t(&(n)->i_val)\n#define gnext(n)\t((n)->i_key.nk.next)\n\n#define key2tval(n)\t(&(n)->i_key.tvk)\n\n\nLUAI_FUNC const TValue *luaH_getnum (Table *t, int key);\nLUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);\nLUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);\nLUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);\nLUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);\nLUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);\nLUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);\nLUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);\nLUAI_FUNC void luaH_free (lua_State *L, Table *t);\nLUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key);\nLUAI_FUNC int luaH_getn (Table *t);\nLUAI_FUNC int luaH_type (Table *t);\n\n\n#if defined(LUA_DEBUG)\nLUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);\nLUAI_FUNC int luaH_isdummy (Node *n);\n#endif\n\n\n#endif\n"
  },
  {
    "path": "src/lua/ltablib.c",
    "content": "/*\n** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $\n** Library for Table Manipulation\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stddef.h>\n\n#define ltablib_c\n#define LUA_LIB\n\n#include \"lua.h\"\n\n#include \"lauxlib.h\"\n#include \"lualib.h\"\n\n\n#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n))\n\n\nstatic int foreachi (lua_State *L) {\n  int i;\n  int n = aux_getn(L, 1);\n  luaL_checktype(L, 2, LUA_TFUNCTION);\n  for (i=1; i <= n; i++) {\n    lua_pushvalue(L, 2);  /* function */\n    lua_pushinteger(L, i);  /* 1st argument */\n    lua_rawgeti(L, 1, i);  /* 2nd argument */\n    lua_call(L, 2, 1);\n    if (!lua_isnil(L, -1))\n      return 1;\n    lua_pop(L, 1);  /* remove nil result */\n  }\n  return 0;\n}\n\n\nstatic int foreach (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n  luaL_checktype(L, 2, LUA_TFUNCTION);\n  lua_pushnil(L);  /* first key */\n  while (lua_next(L, 1)) {\n    lua_pushvalue(L, 2);  /* function */\n    lua_pushvalue(L, -3);  /* key */\n    lua_pushvalue(L, -3);  /* value */\n    lua_call(L, 2, 1);\n    if (!lua_isnil(L, -1))\n      return 1;\n    lua_pop(L, 2);  /* remove value and result */\n  }\n  return 0;\n}\n\n\nstatic int maxn (lua_State *L) {\n  lua_Number max = 0;\n  luaL_checktype(L, 1, LUA_TTABLE);\n  lua_pushnil(L);  /* first key */\n  while (lua_next(L, 1)) {\n    lua_pop(L, 1);  /* remove value */\n    if (lua_type(L, -1) == LUA_TNUMBER) {\n      lua_Number v = lua_tonumber(L, -1);\n      if (v > max) max = v;\n    }\n  }\n  lua_pushnumber(L, max);\n  return 1;\n}\n\n\nstatic int getn (lua_State *L) {\n  lua_pushinteger(L, aux_getn(L, 1));\n  return 1;\n}\n\n\nstatic int setn (lua_State *L) {\n  luaL_checktype(L, 1, LUA_TTABLE);\n#ifndef luaL_setn\n  luaL_setn(L, 1, luaL_checkint(L, 2));\n#else\n  luaL_error(L, LUA_QL(\"setn\") \" is obsolete\");\n#endif\n  lua_pushvalue(L, 1);\n  return 1;\n}\n\n\nstatic int tinsert (lua_State *L) {\n  int e = aux_getn(L, 1) + 1;  /* first empty element */\n  int pos;  /* where to insert new element */\n  switch (lua_gettop(L)) {\n    case 2: {  /* called with only 2 arguments */\n      pos = e;  /* insert new element at the end */\n      break;\n    }\n    case 3: {\n      int i;\n      pos = luaL_checkint(L, 2);  /* 2nd argument is the position */\n      if (pos > e) e = pos;  /* `grow' array if necessary */\n      for (i = e; i > pos; i--) {  /* move up elements */\n        lua_rawgeti(L, 1, i-1);\n        lua_rawseti(L, 1, i);  /* t[i] = t[i-1] */\n      }\n      break;\n    }\n    default: {\n      return luaL_error(L, \"wrong number of arguments to \" LUA_QL(\"insert\"));\n    }\n  }\n  luaL_setn(L, 1, e);  /* new size */\n  lua_rawseti(L, 1, pos);  /* t[pos] = v */\n  return 0;\n}\n\n\nstatic int tremove (lua_State *L) {\n  int e = aux_getn(L, 1);\n  int pos = luaL_optint(L, 2, e);\n  if (!(1 <= pos && pos <= e))  /* position is outside bounds? */\n   return 0;  /* nothing to remove */\n  luaL_setn(L, 1, e - 1);  /* t.n = n-1 */\n  lua_rawgeti(L, 1, pos);  /* result = t[pos] */\n  for ( ;pos<e; pos++) {\n    lua_rawgeti(L, 1, pos+1);\n    lua_rawseti(L, 1, pos);  /* t[pos] = t[pos+1] */\n  }\n  lua_pushnil(L);\n  lua_rawseti(L, 1, e);  /* t[e] = nil */\n  return 1;\n}\n\n\nstatic void addfield (lua_State *L, luaL_Buffer *b, int i) {\n  lua_rawgeti(L, 1, i);\n  if (!lua_isstring(L, -1))\n    luaL_error(L, \"invalid value (%s) at index %d in table for \"\n                  LUA_QL(\"concat\"), luaL_typename(L, -1), i);\n  luaL_addvalue(b);\n}\n\n\nstatic int tconcat (lua_State *L) {\n  luaL_Buffer b;\n  size_t lsep;\n  int i, last;\n  const char *sep = luaL_optlstring(L, 2, \"\", &lsep);\n  luaL_checktype(L, 1, LUA_TTABLE);\n  i = luaL_optint(L, 3, 1);\n  last = luaL_opt(L, luaL_checkint, 4, luaL_getn(L, 1));\n  luaL_buffinit(L, &b);\n  for (; i < last; i++) {\n    addfield(L, &b, i);\n    luaL_addlstring(&b, sep, lsep);\n  }\n  if (i == last)  /* add last value (if interval was not empty) */\n    addfield(L, &b, i);\n  luaL_pushresult(&b);\n  return 1;\n}\n\n\n\n/*\n** {======================================================\n** Quicksort\n** (based on `Algorithms in MODULA-3', Robert Sedgewick;\n**  Addison-Wesley, 1993.)\n*/\n\n\nstatic void set2 (lua_State *L, int i, int j) {\n  lua_rawseti(L, 1, i);\n  lua_rawseti(L, 1, j);\n}\n\nstatic int sort_comp (lua_State *L, int a, int b) {\n  if (!lua_isnil(L, 2)) {  /* function? */\n    int res;\n    lua_pushvalue(L, 2);\n    lua_pushvalue(L, a-1);  /* -1 to compensate function */\n    lua_pushvalue(L, b-2);  /* -2 to compensate function and `a' */\n    lua_call(L, 2, 1);\n    res = lua_toboolean(L, -1);\n    lua_pop(L, 1);\n    return res;\n  }\n  else  /* a < b? */\n    return lua_lessthan(L, a, b);\n}\n\nstatic void auxsort (lua_State *L, int l, int u) {\n  while (l < u) {  /* for tail recursion */\n    int i, j;\n    /* sort elements a[l], a[(l+u)/2] and a[u] */\n    lua_rawgeti(L, 1, l);\n    lua_rawgeti(L, 1, u);\n    if (sort_comp(L, -1, -2))  /* a[u] < a[l]? */\n      set2(L, l, u);  /* swap a[l] - a[u] */\n    else\n      lua_pop(L, 2);\n    if (u-l == 1) break;  /* only 2 elements */\n    i = (l+u)/2;\n    lua_rawgeti(L, 1, i);\n    lua_rawgeti(L, 1, l);\n    if (sort_comp(L, -2, -1))  /* a[i]<a[l]? */\n      set2(L, i, l);\n    else {\n      lua_pop(L, 1);  /* remove a[l] */\n      lua_rawgeti(L, 1, u);\n      if (sort_comp(L, -1, -2))  /* a[u]<a[i]? */\n        set2(L, i, u);\n      else\n        lua_pop(L, 2);\n    }\n    if (u-l == 2) break;  /* only 3 elements */\n    lua_rawgeti(L, 1, i);  /* Pivot */\n    lua_pushvalue(L, -1);\n    lua_rawgeti(L, 1, u-1);\n    set2(L, i, u-1);\n    /* a[l] <= P == a[u-1] <= a[u], only need to sort from l+1 to u-2 */\n    i = l; j = u-1;\n    for (;;) {  /* invariant: a[l..i] <= P <= a[j..u] */\n      /* repeat ++i until a[i] >= P */\n      while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {\n        if (i>u) luaL_error(L, \"invalid order function for sorting\");\n        lua_pop(L, 1);  /* remove a[i] */\n      }\n      /* repeat --j until a[j] <= P */\n      while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {\n        if (j<l) luaL_error(L, \"invalid order function for sorting\");\n        lua_pop(L, 1);  /* remove a[j] */\n      }\n      if (j<i) {\n        lua_pop(L, 3);  /* pop pivot, a[i], a[j] */\n        break;\n      }\n      set2(L, i, j);\n    }\n    lua_rawgeti(L, 1, u-1);\n    lua_rawgeti(L, 1, i);\n    set2(L, u-1, i);  /* swap pivot (a[u-1]) with a[i] */\n    /* a[l..i-1] <= a[i] == P <= a[i+1..u] */\n    /* adjust so that smaller half is in [j..i] and larger one in [l..u] */\n    if (i-l < u-i) {\n      j=l; i=i-1; l=i+2;\n    }\n    else {\n      j=i+1; i=u; u=j-2;\n    }\n    auxsort(L, j, i);  /* call recursively the smaller one */\n  }  /* repeat the routine for the larger one */\n}\n\nstatic int sort (lua_State *L) {\n  int n = aux_getn(L, 1);\n  luaL_checkstack(L, 40, \"\");  /* assume array is smaller than 2^40 */\n  if (!lua_isnoneornil(L, 2))  /* is there a 2nd argument? */\n    luaL_checktype(L, 2, LUA_TFUNCTION);\n  lua_settop(L, 2);  /* make sure there is two arguments */\n  auxsort(L, 1, n);\n  return 0;\n}\n\n/* }====================================================== */\n\n\nstatic const luaL_Reg tab_funcs[] = {\n  {\"concat\", tconcat},\n  {\"foreach\", foreach},\n  {\"foreachi\", foreachi},\n  {\"getn\", getn},\n  {\"maxn\", maxn},\n  {\"insert\", tinsert},\n  {\"remove\", tremove},\n  {\"setn\", setn},\n  {\"sort\", sort},\n  {NULL, NULL}\n};\n\n\nLUALIB_API int luaopen_table (lua_State *L) {\n  luaL_register(L, LUA_TABLIBNAME, tab_funcs);\n  return 1;\n}\n\n"
  },
  {
    "path": "src/lua/ltm.c",
    "content": "/*\n** $Id: ltm.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $\n** Tag methods\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define ltm_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"lobject.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n\n\n\nconst char *const luaT_typenames[] = {\n  \"nil\", \"boolean\", \"userdata\", \"number\",\n  \"string\", \"table\", \"function\", \"userdata\", \"thread\",\n  \"proto\", \"upval\"\n};\n\n\nvoid luaT_init (lua_State *L) {\n  static const char *const luaT_eventname[] = {  /* ORDER TM */\n    \"__index\", \"__newindex\",\n    \"__gc\", \"__mode\", \"__eq\",\n    \"__add\", \"__sub\", \"__mul\", \"__div\", \"__mod\",\n    \"__pow\", \"__unm\", \"__len\", \"__lt\", \"__le\",\n    \"__concat\", \"__call\"\n  };\n  int i;\n  for (i=0; i<TM_N; i++) {\n    G(L)->tmname[i] = luaS_new(L, luaT_eventname[i]);\n    luaS_fix(G(L)->tmname[i]);  /* never collect these names */\n  }\n}\n\n\n/*\n** function to be used with macro \"fasttm\": optimized for absence of\n** tag methods\n*/\nconst TValue *luaT_gettm (Table *events, TMS event, TString *ename) {\n  const TValue *tm = luaH_getstr(events, ename);\n  lua_assert(event <= TM_EQ);\n  if (ttisnil(tm)) {  /* no tag method? */\n    events->flags |= cast_byte(1u<<event);  /* cache this fact */\n    return NULL;\n  }\n  else return tm;\n}\n\n\nconst TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, TMS event) {\n  Table *mt;\n  switch (ttype(o)) {\n    case LUA_TTABLE:\n      mt = hvalue(o)->metatable;\n      break;\n    case LUA_TUSERDATA:\n      mt = uvalue(o)->metatable;\n      break;\n    default:\n      mt = G(L)->mt[ttype(o)];\n  }\n  return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject);\n}\n\n"
  },
  {
    "path": "src/lua/ltm.h",
    "content": "/*\n** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $\n** Tag methods\n** See Copyright Notice in lua.h\n*/\n\n#ifndef ltm_h\n#define ltm_h\n\n\n#include \"lobject.h\"\n\n\n/*\n* WARNING: if you change the order of this enumeration,\n* grep \"ORDER TM\"\n*/\ntypedef enum {\n  TM_INDEX,\n  TM_NEWINDEX,\n  TM_GC,\n  TM_MODE,\n  TM_EQ,  /* last tag method with `fast' access */\n  TM_ADD,\n  TM_SUB,\n  TM_MUL,\n  TM_DIV,\n  TM_MOD,\n  TM_POW,\n  TM_UNM,\n  TM_LEN,\n  TM_LT,\n  TM_LE,\n  TM_CONCAT,\n  TM_CALL,\n  TM_N\t\t/* number of elements in the enum */\n} TMS;\n\n\n\n#define gfasttm(g,et,e) ((et) == NULL ? NULL : \\\n  ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e]))\n\n#define fasttm(l,et,e)\tgfasttm(G(l), et, e)\n\nLUAI_DATA const char *const luaT_typenames[];\n\n\nLUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename);\nLUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o,\n                                                       TMS event);\nLUAI_FUNC void luaT_init (lua_State *L);\n\n#endif\n"
  },
  {
    "path": "src/lua/lundump.c",
    "content": "/*\n** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $\n** load precompiled Lua chunks\n** See Copyright Notice in lua.h\n*/\n\n#include <string.h>\n\n#define lundump_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lmem.h\"\n#include \"lobject.h\"\n#include \"lstring.h\"\n#include \"lundump.h\"\n#include \"lzio.h\"\n\ntypedef struct {\n lua_State* L;\n ZIO* Z;\n Mbuffer* b;\n const char* name;\n} LoadState;\n\n#ifdef LUAC_TRUST_BINARIES\n#define IF(c,s)\n#define error(S,s)\n#else\n#define IF(c,s)\t\tif (c) error(S,s)\n\nstatic void error(LoadState* S, const char* why)\n{\n luaO_pushfstring(S->L,\"%s: %s in precompiled chunk\",S->name,why);\n luaD_throw(S->L,LUA_ERRSYNTAX);\n}\n#endif\n\n#define LoadMem(S,b,n,size)\tLoadBlock(S,b,(n)*(size))\n#define\tLoadByte(S)\t\t(lu_byte)LoadChar(S)\n#define LoadVar(S,x)\t\tLoadMem(S,&x,1,sizeof(x))\n#define LoadVector(S,b,n,size)\tLoadMem(S,b,n,size)\n\nstatic void LoadBlock(LoadState* S, void* b, size_t size)\n{\n size_t r=luaZ_read(S->Z,b,size);\n IF (r!=0, \"unexpected end\");\n}\n\nstatic int LoadChar(LoadState* S)\n{\n char x;\n LoadVar(S,x);\n return x;\n}\n\nstatic int LoadInt(LoadState* S)\n{\n int x;\n LoadVar(S,x);\n IF (x<0, \"bad integer\");\n return x;\n}\n\nstatic lua_Number LoadNumber(LoadState* S)\n{\n lua_Number x;\n LoadVar(S,x);\n return x;\n}\n\nstatic TString* LoadString(LoadState* S)\n{\n size_t size;\n LoadVar(S,size);\n if (size==0)\n  return NULL;\n else\n {\n  char* s=luaZ_openspace(S->L,S->b,size);\n  LoadBlock(S,s,size);\n  return luaS_newlstr(S->L,s,size-1);\t\t/* remove trailing '\\0' */\n }\n}\n\nstatic void LoadCode(LoadState* S, Proto* f)\n{\n int n=LoadInt(S);\n f->code=luaM_newvector(S->L,n,Instruction);\n f->sizecode=n;\n LoadVector(S,f->code,n,sizeof(Instruction));\n}\n\nstatic Proto* LoadFunction(LoadState* S, TString* p);\n\nstatic void LoadConstants(LoadState* S, Proto* f)\n{\n int i,n;\n n=LoadInt(S);\n f->k=luaM_newvector(S->L,n,TValue);\n f->sizek=n;\n for (i=0; i<n; i++) setnilvalue(&f->k[i]);\n for (i=0; i<n; i++)\n {\n  TValue* o=&f->k[i];\n  int t=LoadChar(S);\n  switch (t)\n  {\n   case LUA_TNIL:\n   \tsetnilvalue(o);\n\tbreak;\n   case LUA_TBOOLEAN:\n   \tsetbvalue(o,LoadChar(S)!=0);\n\tbreak;\n   case LUA_TNUMBER:\n\tsetnvalue(o,LoadNumber(S));\n\tbreak;\n   case LUA_TSTRING:\n\tsetsvalue2n(S->L,o,LoadString(S));\n\tbreak;\n   default:\n\terror(S,\"bad constant\");\n\tbreak;\n  }\n }\n n=LoadInt(S);\n f->p=luaM_newvector(S->L,n,Proto*);\n f->sizep=n;\n for (i=0; i<n; i++) f->p[i]=NULL;\n for (i=0; i<n; i++) f->p[i]=LoadFunction(S,f->source);\n}\n\nstatic void LoadDebug(LoadState* S, Proto* f)\n{\n int i,n;\n n=LoadInt(S);\n f->lineinfo=luaM_newvector(S->L,n,int);\n f->sizelineinfo=n;\n LoadVector(S,f->lineinfo,n,sizeof(int));\n n=LoadInt(S);\n f->locvars=luaM_newvector(S->L,n,LocVar);\n f->sizelocvars=n;\n for (i=0; i<n; i++) f->locvars[i].varname=NULL;\n for (i=0; i<n; i++)\n {\n  f->locvars[i].varname=LoadString(S);\n  f->locvars[i].startpc=LoadInt(S);\n  f->locvars[i].endpc=LoadInt(S);\n }\n n=LoadInt(S);\n f->upvalues=luaM_newvector(S->L,n,TString*);\n f->sizeupvalues=n;\n for (i=0; i<n; i++) f->upvalues[i]=NULL;\n for (i=0; i<n; i++) f->upvalues[i]=LoadString(S);\n}\n\nstatic Proto* LoadFunction(LoadState* S, TString* p)\n{\n Proto* f;\n if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,\"code too deep\");\n f=luaF_newproto(S->L);\n setptvalue2s(S->L,S->L->top,f); incr_top(S->L);\n f->source=LoadString(S); if (f->source==NULL) f->source=p;\n f->linedefined=LoadInt(S);\n f->lastlinedefined=LoadInt(S);\n f->nups=LoadByte(S);\n f->numparams=LoadByte(S);\n f->is_vararg=LoadByte(S);\n f->maxstacksize=LoadByte(S);\n LoadCode(S,f);\n LoadConstants(S,f);\n LoadDebug(S,f);\n IF (!luaG_checkcode(f), \"bad code\");\n S->L->top--;\n S->L->nCcalls--;\n return f;\n}\n\nstatic void LoadHeader(LoadState* S)\n{\n char h[LUAC_HEADERSIZE];\n char s[LUAC_HEADERSIZE];\n luaU_header(h);\n LoadBlock(S,s,LUAC_HEADERSIZE);\n IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, \"bad header\");\n}\n\n/*\n** load precompiled chunk\n*/\nProto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name)\n{\n LoadState S;\n if (*name=='@' || *name=='=')\n  S.name=name+1;\n else if (*name==LUA_SIGNATURE[0])\n  S.name=\"binary string\";\n else\n  S.name=name;\n S.L=L;\n S.Z=Z;\n S.b=buff;\n LoadHeader(&S);\n return LoadFunction(&S,luaS_newliteral(L,\"=?\"));\n}\n\n/*\n* make header\n*/\nvoid luaU_header (char* h)\n{\n int x=1;\n memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1);\n h+=sizeof(LUA_SIGNATURE)-1;\n *h++=(char)LUAC_VERSION;\n *h++=(char)LUAC_FORMAT;\n *h++=(char)*(char*)&x;\t\t\t\t/* endianness */\n *h++=(char)sizeof(int);\n *h++=(char)sizeof(size_t);\n *h++=(char)sizeof(Instruction);\n *h++=(char)sizeof(lua_Number);\n *h++=(char)(((lua_Number)0.5)==0);\t\t/* is lua_Number integral? */\n}\n"
  },
  {
    "path": "src/lua/lundump.h",
    "content": "/*\n** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $\n** load precompiled Lua chunks\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lundump_h\n#define lundump_h\n\n#include \"lobject.h\"\n#include \"lzio.h\"\n\n/* load one chunk; from lundump.c */\nLUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name);\n\n/* make header; from lundump.c */\nLUAI_FUNC void luaU_header (char* h);\n\n/* dump one chunk; from ldump.c */\nLUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip);\n\n#ifdef luac_c\n/* print one chunk; from print.c */\nLUAI_FUNC void luaU_print (const Proto* f, int full);\n#endif\n\n/* for header of binary files -- this is Lua 5.1 */\n#define LUAC_VERSION\t\t0x51\n\n/* for header of binary files -- this is the official format */\n#define LUAC_FORMAT\t\t0\n\n/* size of header of binary files */\n#define LUAC_HEADERSIZE\t\t12\n\n#endif\n"
  },
  {
    "path": "src/lua/lvm.c",
    "content": "/*\n** $Id: lvm.c,v 2.63.1.5 2011/08/17 20:43:11 roberto Exp $\n** Lua virtual machine\n** See Copyright Notice in lua.h\n*/\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#define lvm_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"ldebug.h\"\n#include \"ldo.h\"\n#include \"lfunc.h\"\n#include \"lgc.h\"\n#include \"lobject.h\"\n#include \"lopcodes.h\"\n#include \"lstate.h\"\n#include \"lstring.h\"\n#include \"ltable.h\"\n#include \"ltm.h\"\n#include \"lvm.h\"\n\n\n\n/* limit for table tag-method chains (to avoid loops) */\n#define MAXTAGLOOP\t100\n\n\nconst TValue *luaV_tonumber (const TValue *obj, TValue *n) {\n  lua_Number num;\n  if (ttisnumber(obj)) return obj;\n  if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) {\n    setnvalue(n, num);\n    return n;\n  }\n  else\n    return NULL;\n}\n\n\nint luaV_tostring (lua_State *L, StkId obj) {\n  if (!ttisnumber(obj))\n    return 0;\n  else {\n    char s[LUAI_MAXNUMBER2STR];\n    lua_Number n = nvalue(obj);\n    lua_number2str(s, n);\n    setsvalue2s(L, obj, luaS_new(L, s));\n    return 1;\n  }\n}\n\n\nstatic void traceexec (lua_State *L, const Instruction *pc) {\n  lu_byte mask = L->hookmask;\n  const Instruction *oldpc = L->savedpc;\n  L->savedpc = pc;\n  if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) {\n    resethookcount(L);\n    luaD_callhook(L, LUA_HOOKCOUNT, -1);\n  }\n  if (mask & LUA_MASKLINE) {\n    Proto *p = ci_func(L->ci)->l.p;\n    int npc = pcRel(pc, p);\n    int newline = getline(p, npc);\n    /* call linehook when enter a new function, when jump back (loop),\n       or when enter a new line */\n    if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p)))\n      luaD_callhook(L, LUA_HOOKLINE, newline);\n  }\n}\n\n\nstatic void callTMres (lua_State *L, StkId res, const TValue *f,\n                        const TValue *p1, const TValue *p2) {\n  ptrdiff_t result = savestack(L, res);\n  setobj2s(L, L->top, f);  /* push function */\n  setobj2s(L, L->top+1, p1);  /* 1st argument */\n  setobj2s(L, L->top+2, p2);  /* 2nd argument */\n  luaD_checkstack(L, 3);\n  L->top += 3;\n  luaD_call(L, L->top - 3, 1);\n  res = restorestack(L, result);\n  L->top--;\n  setobjs2s(L, res, L->top);\n}\n\n\n\nstatic void callTM (lua_State *L, const TValue *f, const TValue *p1,\n                    const TValue *p2, const TValue *p3) {\n  setobj2s(L, L->top, f);  /* push function */\n  setobj2s(L, L->top+1, p1);  /* 1st argument */\n  setobj2s(L, L->top+2, p2);  /* 2nd argument */\n  setobj2s(L, L->top+3, p3);  /* 3th argument */\n  luaD_checkstack(L, 4);\n  L->top += 4;\n  luaD_call(L, L->top - 4, 0);\n}\n\n\nvoid luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) {\n  int loop;\n  for (loop = 0; loop < MAXTAGLOOP; loop++) {\n    const TValue *tm;\n    if (ttistable(t)) {  /* `t' is a table? */\n      Table *h = hvalue(t);\n      const TValue *res = luaH_get(h, key); /* do a primitive get */\n      if (!ttisnil(res) ||  /* result is no nil? */\n          (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */\n        setobj2s(L, val, res);\n        return;\n      }\n      /* else will try the tag method */\n    }\n    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX)))\n      luaG_typeerror(L, t, \"index\");\n    if (ttisfunction(tm)) {\n      callTMres(L, val, tm, t, key);\n      return;\n    }\n    t = tm;  /* else repeat with `tm' */ \n  }\n  luaG_runerror(L, \"loop in gettable\");\n}\n\n\nvoid luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {\n  int loop;\n  TValue temp;\n  for (loop = 0; loop < MAXTAGLOOP; loop++) {\n    const TValue *tm;\n    if (ttistable(t)) {  /* `t' is a table? */\n      Table *h = hvalue(t);\n      TValue *oldval = luaH_set(L, h, key); /* do a primitive set */\n      if (!ttisnil(oldval) ||  /* result is no nil? */\n          (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */\n        setobj2t(L, oldval, val);\n        h->flags = 0;\n        luaC_barriert(L, h, val);\n        return;\n      }\n      /* else will try the tag method */\n    }\n    else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))\n      luaG_typeerror(L, t, \"index\");\n    if (ttisfunction(tm)) {\n      callTM(L, tm, t, key, val);\n      return;\n    }\n    /* else repeat with `tm' */\n    setobj(L, &temp, tm);  /* avoid pointing inside table (may rehash) */\n    t = &temp;\n  }\n  luaG_runerror(L, \"loop in settable\");\n}\n\n\nstatic int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,\n                       StkId res, TMS event) {\n  const TValue *tm = luaT_gettmbyobj(L, p1, event);  /* try first operand */\n  if (ttisnil(tm))\n    tm = luaT_gettmbyobj(L, p2, event);  /* try second operand */\n  if (ttisnil(tm)) return 0;\n  callTMres(L, res, tm, p1, p2);\n  return 1;\n}\n\n\nstatic const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2,\n                                  TMS event) {\n  const TValue *tm1 = fasttm(L, mt1, event);\n  const TValue *tm2;\n  if (tm1 == NULL) return NULL;  /* no metamethod */\n  if (mt1 == mt2) return tm1;  /* same metatables => same metamethods */\n  tm2 = fasttm(L, mt2, event);\n  if (tm2 == NULL) return NULL;  /* no metamethod */\n  if (luaO_rawequalObj(tm1, tm2))  /* same metamethods? */\n    return tm1;\n  return NULL;\n}\n\n\nstatic int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2,\n                         TMS event) {\n  const TValue *tm1 = luaT_gettmbyobj(L, p1, event);\n  const TValue *tm2;\n  if (ttisnil(tm1)) return -1;  /* no metamethod? */\n  tm2 = luaT_gettmbyobj(L, p2, event);\n  if (!luaO_rawequalObj(tm1, tm2))  /* different metamethods? */\n    return -1;\n  callTMres(L, L->top, tm1, p1, p2);\n  return !l_isfalse(L->top);\n}\n\n\nstatic int l_strcmp (const TString *ls, const TString *rs) {\n  const char *l = getstr(ls);\n  size_t ll = ls->tsv.len;\n  const char *r = getstr(rs);\n  size_t lr = rs->tsv.len;\n  for (;;) {\n    int temp = strcoll(l, r);\n    if (temp != 0) return temp;\n    else {  /* strings are equal up to a `\\0' */\n      size_t len = strlen(l);  /* index of first `\\0' in both strings */\n      if (len == lr)  /* r is finished? */\n        return (len == ll) ? 0 : 1;\n      else if (len == ll)  /* l is finished? */\n        return -1;  /* l is smaller than r (because r is not finished) */\n      /* both strings longer than `len'; go on comparing (after the `\\0') */\n      len++;\n      l += len; ll -= len; r += len; lr -= len;\n    }\n  }\n}\n\n\nint luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) {\n  int res;\n  if (ttype(l) != ttype(r))\n    return luaG_ordererror(L, l, r);\n  else if (ttisnumber(l))\n    return luai_numlt(nvalue(l), nvalue(r));\n  else if (ttisstring(l))\n    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0;\n  else if ((res = call_orderTM(L, l, r, TM_LT)) != -1)\n    return res;\n  return luaG_ordererror(L, l, r);\n}\n\n\nstatic int lessequal (lua_State *L, const TValue *l, const TValue *r) {\n  int res;\n  if (ttype(l) != ttype(r))\n    return luaG_ordererror(L, l, r);\n  else if (ttisnumber(l))\n    return luai_numle(nvalue(l), nvalue(r));\n  else if (ttisstring(l))\n    return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0;\n  else if ((res = call_orderTM(L, l, r, TM_LE)) != -1)  /* first try `le' */\n    return res;\n  else if ((res = call_orderTM(L, r, l, TM_LT)) != -1)  /* else try `lt' */\n    return !res;\n  return luaG_ordererror(L, l, r);\n}\n\n\nint luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) {\n  const TValue *tm;\n  lua_assert(ttype(t1) == ttype(t2));\n  switch (ttype(t1)) {\n    case LUA_TNIL: return 1;\n    case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2));\n    case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2);  /* true must be 1 !! */\n    case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2);\n    case LUA_TUSERDATA: {\n      if (uvalue(t1) == uvalue(t2)) return 1;\n      tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable,\n                         TM_EQ);\n      break;  /* will try TM */\n    }\n    case LUA_TTABLE: {\n      if (hvalue(t1) == hvalue(t2)) return 1;\n      tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ);\n      break;  /* will try TM */\n    }\n    default: return gcvalue(t1) == gcvalue(t2);\n  }\n  if (tm == NULL) return 0;  /* no TM? */\n  callTMres(L, L->top, tm, t1, t2);  /* call TM */\n  return !l_isfalse(L->top);\n}\n\n\nvoid luaV_concat (lua_State *L, int total, int last) {\n  do {\n    StkId top = L->base + last + 1;\n    int n = 2;  /* number of elements handled in this pass (at least 2) */\n    if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) {\n      if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT))\n        luaG_concaterror(L, top-2, top-1);\n    } else if (tsvalue(top-1)->len == 0)  /* second op is empty? */\n      (void)tostring(L, top - 2);  /* result is first op (as string) */\n    else {\n      /* at least two string values; get as many as possible */\n      size_t tl = tsvalue(top-1)->len;\n      char *buffer;\n      int i;\n      /* collect total length */\n      for (n = 1; n < total && tostring(L, top-n-1); n++) {\n        size_t l = tsvalue(top-n-1)->len;\n        if (l >= MAX_SIZET - tl) luaG_runerror(L, \"string length overflow\");\n        tl += l;\n      }\n      buffer = luaZ_openspace(L, &G(L)->buff, tl);\n      tl = 0;\n      for (i=n; i>0; i--) {  /* concat all strings */\n        size_t l = tsvalue(top-i)->len;\n        memcpy(buffer+tl, svalue(top-i), l);\n        tl += l;\n      }\n      setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl));\n    }\n    total -= n-1;  /* got `n' strings to create 1 new */\n    last -= n-1;\n  } while (total > 1);  /* repeat until only 1 result left */\n}\n\n\nstatic void Arith (lua_State *L, StkId ra, const TValue *rb,\n                   const TValue *rc, TMS op) {\n  TValue tempb, tempc;\n  const TValue *b, *c;\n  if ((b = luaV_tonumber(rb, &tempb)) != NULL &&\n      (c = luaV_tonumber(rc, &tempc)) != NULL) {\n    lua_Number nb = nvalue(b), nc = nvalue(c);\n    switch (op) {\n      case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;\n      case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;\n      case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;\n      case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;\n      case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;\n      case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;\n      case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;\n      default: lua_assert(0); break;\n    }\n  }\n  else if (!call_binTM(L, rb, rc, ra, op))\n    luaG_aritherror(L, rb, rc);\n}\n\n\n\n/*\n** some macros for common tasks in `luaV_execute'\n*/\n\n#define runtime_check(L, c)\t{ if (!(c)) break; }\n\n#define RA(i)\t(base+GETARG_A(i))\n/* to be used after possible stack reallocation */\n#define RB(i)\tcheck_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))\n#define RC(i)\tcheck_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))\n#define RKB(i)\tcheck_exp(getBMode(GET_OPCODE(i)) == OpArgK, \\\n\tISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))\n#define RKC(i)\tcheck_exp(getCMode(GET_OPCODE(i)) == OpArgK, \\\n\tISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))\n#define KBx(i)\tcheck_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i))\n\n\n#define dojump(L,pc,i)\t{(pc) += (i); luai_threadyield(L);}\n\n\n#define Protect(x)\t{ L->savedpc = pc; {x;}; base = L->base; }\n\n\n#define arith_op(op,tm) { \\\n        TValue *rb = RKB(i); \\\n        TValue *rc = RKC(i); \\\n        if (ttisnumber(rb) && ttisnumber(rc)) { \\\n          lua_Number nb = nvalue(rb), nc = nvalue(rc); \\\n          setnvalue(ra, op(nb, nc)); \\\n        } \\\n        else \\\n          Protect(Arith(L, ra, rb, rc, tm)); \\\n      }\n\n\n\nvoid luaV_execute (lua_State *L, int nexeccalls) {\n  LClosure *cl;\n  StkId base;\n  TValue *k;\n  const Instruction *pc;\n reentry:  /* entry point */\n  lua_assert(isLua(L->ci));\n  pc = L->savedpc;\n  cl = &clvalue(L->ci->func)->l;\n  base = L->base;\n  k = cl->p->k;\n  /* main loop of interpreter */\n  for (;;) {\n    const Instruction i = *pc++;\n    StkId ra;\n    if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&\n        (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {\n      traceexec(L, pc);\n      if (L->status == LUA_YIELD) {  /* did hook yield? */\n        L->savedpc = pc - 1;\n        return;\n      }\n      base = L->base;\n    }\n    /* warning!! several calls may realloc the stack and invalidate `ra' */\n    ra = RA(i);\n    lua_assert(base == L->base && L->base == L->ci->base);\n    lua_assert(base <= L->top && L->top <= L->stack + L->stacksize);\n    lua_assert(L->top == L->ci->top || luaG_checkopenop(i));\n    switch (GET_OPCODE(i)) {\n      case OP_MOVE: {\n        setobjs2s(L, ra, RB(i));\n        continue;\n      }\n      case OP_LOADK: {\n        setobj2s(L, ra, KBx(i));\n        continue;\n      }\n      case OP_LOADBOOL: {\n        setbvalue(ra, GETARG_B(i));\n        if (GETARG_C(i)) pc++;  /* skip next instruction (if C) */\n        continue;\n      }\n      case OP_LOADNIL: {\n        TValue *rb = RB(i);\n        do {\n          setnilvalue(rb--);\n        } while (rb >= ra);\n        continue;\n      }\n      case OP_GETUPVAL: {\n        int b = GETARG_B(i);\n        setobj2s(L, ra, cl->upvals[b]->v);\n        continue;\n      }\n      case OP_GETGLOBAL: {\n        TValue g;\n        TValue *rb = KBx(i);\n        sethvalue(L, &g, cl->env);\n        lua_assert(ttisstring(rb));\n        Protect(luaV_gettable(L, &g, rb, ra));\n        continue;\n      }\n      case OP_GETTABLE: {\n        Protect(luaV_gettable(L, RB(i), RKC(i), ra));\n        continue;\n      }\n      case OP_SETGLOBAL: {\n        TValue g;\n        sethvalue(L, &g, cl->env);\n        lua_assert(ttisstring(KBx(i)));\n        Protect(luaV_settable(L, &g, KBx(i), ra));\n        continue;\n      }\n      case OP_SETUPVAL: {\n        UpVal *uv = cl->upvals[GETARG_B(i)];\n        setobj(L, uv->v, ra);\n        luaC_barrier(L, uv, ra);\n        continue;\n      }\n      case OP_SETTABLE: {\n        Protect(luaV_settable(L, ra, RKB(i), RKC(i)));\n        continue;\n      }\n      case OP_NEWTABLE: {\n        int b = GETARG_B(i);\n        int c = GETARG_C(i);\n        sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c)));\n        Protect(luaC_checkGC(L));\n        continue;\n      }\n      case OP_SELF: {\n        StkId rb = RB(i);\n        setobjs2s(L, ra+1, rb);\n        Protect(luaV_gettable(L, rb, RKC(i), ra));\n        continue;\n      }\n      case OP_ADD: {\n        arith_op(luai_numadd, TM_ADD);\n        continue;\n      }\n      case OP_SUB: {\n        arith_op(luai_numsub, TM_SUB);\n        continue;\n      }\n      case OP_MUL: {\n        arith_op(luai_nummul, TM_MUL);\n        continue;\n      }\n      case OP_DIV: {\n        arith_op(luai_numdiv, TM_DIV);\n        continue;\n      }\n      case OP_MOD: {\n        arith_op(luai_nummod, TM_MOD);\n        continue;\n      }\n      case OP_POW: {\n        arith_op(luai_numpow, TM_POW);\n        continue;\n      }\n      case OP_UNM: {\n        TValue *rb = RB(i);\n        if (ttisnumber(rb)) {\n          lua_Number nb = nvalue(rb);\n          setnvalue(ra, luai_numunm(nb));\n        }\n        else {\n          Protect(Arith(L, ra, rb, rb, TM_UNM));\n        }\n        continue;\n      }\n      case OP_NOT: {\n        int res = l_isfalse(RB(i));  /* next assignment may change this value */\n        setbvalue(ra, res);\n        continue;\n      }\n      case OP_LEN: {\n        const TValue *rb = RB(i);\n        switch (ttype(rb)) {\n          case LUA_TTABLE: {\n            setnvalue(ra, cast_num(luaH_getn(hvalue(rb))));\n            break;\n          }\n          case LUA_TSTRING: {\n            setnvalue(ra, cast_num(tsvalue(rb)->len));\n            break;\n          }\n          default: {  /* try metamethod */\n            Protect(\n              if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN))\n                luaG_typeerror(L, rb, \"get length of\");\n            )\n          }\n        }\n        continue;\n      }\n      case OP_CONCAT: {\n        int b = GETARG_B(i);\n        int c = GETARG_C(i);\n        Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L));\n        setobjs2s(L, RA(i), base+b);\n        continue;\n      }\n      case OP_JMP: {\n        dojump(L, pc, GETARG_sBx(i));\n        continue;\n      }\n      case OP_EQ: {\n        TValue *rb = RKB(i);\n        TValue *rc = RKC(i);\n        Protect(\n          if (equalobj(L, rb, rc) == GETARG_A(i))\n            dojump(L, pc, GETARG_sBx(*pc));\n        )\n        pc++;\n        continue;\n      }\n      case OP_LT: {\n        Protect(\n          if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i))\n            dojump(L, pc, GETARG_sBx(*pc));\n        )\n        pc++;\n        continue;\n      }\n      case OP_LE: {\n        Protect(\n          if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i))\n            dojump(L, pc, GETARG_sBx(*pc));\n        )\n        pc++;\n        continue;\n      }\n      case OP_TEST: {\n        if (l_isfalse(ra) != GETARG_C(i))\n          dojump(L, pc, GETARG_sBx(*pc));\n        pc++;\n        continue;\n      }\n      case OP_TESTSET: {\n        TValue *rb = RB(i);\n        if (l_isfalse(rb) != GETARG_C(i)) {\n          setobjs2s(L, ra, rb);\n          dojump(L, pc, GETARG_sBx(*pc));\n        }\n        pc++;\n        continue;\n      }\n      case OP_CALL: {\n        int b = GETARG_B(i);\n        int nresults = GETARG_C(i) - 1;\n        if (b != 0) L->top = ra+b;  /* else previous instruction set top */\n        L->savedpc = pc;\n        switch (luaD_precall(L, ra, nresults)) {\n          case PCRLUA: {\n            nexeccalls++;\n            goto reentry;  /* restart luaV_execute over new Lua function */\n          }\n          case PCRC: {\n            /* it was a C function (`precall' called it); adjust results */\n            if (nresults >= 0) L->top = L->ci->top;\n            base = L->base;\n            continue;\n          }\n          default: {\n            return;  /* yield */\n          }\n        }\n      }\n      case OP_TAILCALL: {\n        int b = GETARG_B(i);\n        if (b != 0) L->top = ra+b;  /* else previous instruction set top */\n        L->savedpc = pc;\n        lua_assert(GETARG_C(i) - 1 == LUA_MULTRET);\n        switch (luaD_precall(L, ra, LUA_MULTRET)) {\n          case PCRLUA: {\n            /* tail call: put new frame in place of previous one */\n            CallInfo *ci = L->ci - 1;  /* previous frame */\n            int aux;\n            StkId func = ci->func;\n            StkId pfunc = (ci+1)->func;  /* previous function index */\n            if (L->openupval) luaF_close(L, ci->base);\n            L->base = ci->base = ci->func + ((ci+1)->base - pfunc);\n            for (aux = 0; pfunc+aux < L->top; aux++)  /* move frame down */\n              setobjs2s(L, func+aux, pfunc+aux);\n            ci->top = L->top = func+aux;  /* correct top */\n            lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize);\n            ci->savedpc = L->savedpc;\n            ci->tailcalls++;  /* one more call lost */\n            L->ci--;  /* remove new frame */\n            goto reentry;\n          }\n          case PCRC: {  /* it was a C function (`precall' called it) */\n            base = L->base;\n            continue;\n          }\n          default: {\n            return;  /* yield */\n          }\n        }\n      }\n      case OP_RETURN: {\n        int b = GETARG_B(i);\n        if (b != 0) L->top = ra+b-1;\n        if (L->openupval) luaF_close(L, base);\n        L->savedpc = pc;\n        b = luaD_poscall(L, ra);\n        if (--nexeccalls == 0)  /* was previous function running `here'? */\n          return;  /* no: return */\n        else {  /* yes: continue its execution */\n          if (b) L->top = L->ci->top;\n          lua_assert(isLua(L->ci));\n          lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL);\n          goto reentry;\n        }\n      }\n      case OP_FORLOOP: {\n        lua_Number step = nvalue(ra+2);\n        lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */\n        lua_Number limit = nvalue(ra+1);\n        if (luai_numlt(0, step) ? luai_numle(idx, limit)\n                                : luai_numle(limit, idx)) {\n          dojump(L, pc, GETARG_sBx(i));  /* jump back */\n          setnvalue(ra, idx);  /* update internal index... */\n          setnvalue(ra+3, idx);  /* ...and external index */\n        }\n        continue;\n      }\n      case OP_FORPREP: {\n        const TValue *init = ra;\n        const TValue *plimit = ra+1;\n        const TValue *pstep = ra+2;\n        L->savedpc = pc;  /* next steps may throw errors */\n        if (!tonumber(init, ra))\n          luaG_runerror(L, LUA_QL(\"for\") \" initial value must be a number\");\n        else if (!tonumber(plimit, ra+1))\n          luaG_runerror(L, LUA_QL(\"for\") \" limit must be a number\");\n        else if (!tonumber(pstep, ra+2))\n          luaG_runerror(L, LUA_QL(\"for\") \" step must be a number\");\n        setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep)));\n        dojump(L, pc, GETARG_sBx(i));\n        continue;\n      }\n      case OP_TFORLOOP: {\n        StkId cb = ra + 3;  /* call base */\n        setobjs2s(L, cb+2, ra+2);\n        setobjs2s(L, cb+1, ra+1);\n        setobjs2s(L, cb, ra);\n        L->top = cb+3;  /* func. + 2 args (state and index) */\n        Protect(luaD_call(L, cb, GETARG_C(i)));\n        L->top = L->ci->top;\n        cb = RA(i) + 3;  /* previous call may change the stack */\n        if (!ttisnil(cb)) {  /* continue loop? */\n          setobjs2s(L, cb-1, cb);  /* save control variable */\n          dojump(L, pc, GETARG_sBx(*pc));  /* jump back */\n        }\n        pc++;\n        continue;\n      }\n      case OP_SETLIST: {\n        int n = GETARG_B(i);\n        int c = GETARG_C(i);\n        int last;\n        Table *h;\n        if (n == 0) {\n          n = cast_int(L->top - ra) - 1;\n          L->top = L->ci->top;\n        }\n        if (c == 0) c = cast_int(*pc++);\n        runtime_check(L, ttistable(ra));\n        h = hvalue(ra);\n        last = ((c-1)*LFIELDS_PER_FLUSH) + n;\n        if (last > h->sizearray)  /* needs more space? */\n          luaH_resizearray(L, h, last);  /* pre-alloc it at once */\n        for (; n > 0; n--) {\n          TValue *val = ra+n;\n          setobj2t(L, luaH_setnum(L, h, last--), val);\n          luaC_barriert(L, h, val);\n        }\n        continue;\n      }\n      case OP_CLOSE: {\n        luaF_close(L, ra);\n        continue;\n      }\n      case OP_CLOSURE: {\n        Proto *p;\n        Closure *ncl;\n        int nup, j;\n        p = cl->p->p[GETARG_Bx(i)];\n        nup = p->nups;\n        ncl = luaF_newLclosure(L, nup, cl->env);\n        ncl->l.p = p;\n        for (j=0; j<nup; j++, pc++) {\n          if (GET_OPCODE(*pc) == OP_GETUPVAL)\n            ncl->l.upvals[j] = cl->upvals[GETARG_B(*pc)];\n          else {\n            lua_assert(GET_OPCODE(*pc) == OP_MOVE);\n            ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc));\n          }\n        }\n        setclvalue(L, ra, ncl);\n        Protect(luaC_checkGC(L));\n        continue;\n      }\n      case OP_VARARG: {\n        int b = GETARG_B(i) - 1;\n        int j;\n        CallInfo *ci = L->ci;\n        int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1;\n        if (b == LUA_MULTRET) {\n          Protect(luaD_checkstack(L, n));\n          ra = RA(i);  /* previous call may change the stack */\n          b = n;\n          L->top = ra + n;\n        }\n        for (j = 0; j < b; j++) {\n          if (j < n) {\n            setobjs2s(L, ra + j, ci->base - n + j);\n          }\n          else {\n            setnilvalue(ra + j);\n          }\n        }\n        continue;\n      }\n    }\n  }\n}\n\n"
  },
  {
    "path": "src/lua/lvm.h",
    "content": "/*\n** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $\n** Lua virtual machine\n** See Copyright Notice in lua.h\n*/\n\n#ifndef lvm_h\n#define lvm_h\n\n\n#include \"ldo.h\"\n#include \"lobject.h\"\n#include \"ltm.h\"\n\n\n#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o)))\n\n#define tonumber(o,n)\t(ttype(o) == LUA_TNUMBER || \\\n                         (((o) = luaV_tonumber(o,n)) != NULL))\n\n#define equalobj(L,o1,o2) \\\n\t(ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2))\n\n\nLUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);\nLUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2);\nLUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n);\nLUAI_FUNC int luaV_tostring (lua_State *L, StkId obj);\nLUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key,\n                                            StkId val);\nLUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,\n                                            StkId val);\nLUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls);\nLUAI_FUNC void luaV_concat (lua_State *L, int total, int last);\n\n#endif\n"
  },
  {
    "path": "src/lua/lzio.c",
    "content": "/*\n** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $\n** a generic input stream interface\n** See Copyright Notice in lua.h\n*/\n\n\n#include <string.h>\n\n#define lzio_c\n#define LUA_CORE\n\n#include \"lua.h\"\n\n#include \"llimits.h\"\n#include \"lmem.h\"\n#include \"lstate.h\"\n#include \"lzio.h\"\n\n\nint luaZ_fill (ZIO *z) {\n  size_t size;\n  lua_State *L = z->L;\n  const char *buff;\n  lua_unlock(L);\n  buff = z->reader(L, z->data, &size);\n  lua_lock(L);\n  if (buff == NULL || size == 0) return EOZ;\n  z->n = size - 1;\n  z->p = buff;\n  return char2int(*(z->p++));\n}\n\n\nint luaZ_lookahead (ZIO *z) {\n  if (z->n == 0) {\n    if (luaZ_fill(z) == EOZ)\n      return EOZ;\n    else {\n      z->n++;  /* luaZ_fill removed first byte; put back it */\n      z->p--;\n    }\n  }\n  return char2int(*z->p);\n}\n\n\nvoid luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) {\n  z->L = L;\n  z->reader = reader;\n  z->data = data;\n  z->n = 0;\n  z->p = NULL;\n}\n\n\n/* --------------------------------------------------------------- read --- */\nsize_t luaZ_read (ZIO *z, void *b, size_t n) {\n  while (n) {\n    size_t m;\n    if (luaZ_lookahead(z) == EOZ)\n      return n;  /* return number of missing bytes */\n    m = (n <= z->n) ? n : z->n;  /* min. between n and z->n */\n    memcpy(b, z->p, m);\n    z->n -= m;\n    z->p += m;\n    b = (char *)b + m;\n    n -= m;\n  }\n  return 0;\n}\n\n/* ------------------------------------------------------------------------ */\nchar *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) {\n  if (n > buff->buffsize) {\n    if (n < LUA_MINBUFFER) n = LUA_MINBUFFER;\n    luaZ_resizebuffer(L, buff, n);\n  }\n  return buff->buffer;\n}\n\n\n"
  },
  {
    "path": "src/lua/lzio.h",
    "content": "/*\n** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $\n** Buffered streams\n** See Copyright Notice in lua.h\n*/\n\n\n#ifndef lzio_h\n#define lzio_h\n\n#include \"lua.h\"\n\n#include \"lmem.h\"\n\n\n#define EOZ\t(-1)\t\t\t/* end of stream */\n\ntypedef struct Zio ZIO;\n\n#define char2int(c)\tcast(int, cast(unsigned char, (c)))\n\n#define zgetc(z)  (((z)->n--)>0 ?  char2int(*(z)->p++) : luaZ_fill(z))\n\ntypedef struct Mbuffer {\n  char *buffer;\n  size_t n;\n  size_t buffsize;\n} Mbuffer;\n\n#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0)\n\n#define luaZ_buffer(buff)\t((buff)->buffer)\n#define luaZ_sizebuffer(buff)\t((buff)->buffsize)\n#define luaZ_bufflen(buff)\t((buff)->n)\n\n#define luaZ_resetbuffer(buff) ((buff)->n = 0)\n\n\n#define luaZ_resizebuffer(L, buff, size) \\\n\t(luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \\\n\t(buff)->buffsize = size)\n\n#define luaZ_freebuffer(L, buff)\tluaZ_resizebuffer(L, buff, 0)\n\n\nLUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n);\nLUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader,\n                                        void *data);\nLUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n);\t/* read next n bytes */\nLUAI_FUNC int luaZ_lookahead (ZIO *z);\n\n\n\n/* --------- Private Part ------------------ */\n\nstruct Zio {\n  size_t n;\t\t\t/* bytes still unread */\n  const char *p;\t\t/* current position in buffer */\n  lua_Reader reader;\n  void* data;\t\t\t/* additional data */\n  lua_State *L;\t\t\t/* Lua state (for reader) */\n};\n\n\nLUAI_FUNC int luaZ_fill (ZIO *z);\n\n#endif\n"
  },
  {
    "path": "src/luasandbox.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Lua sandboxed implementation @file */\n\n#define LUA_LIB\n#include \"luasandbox.h\"\n\n#include <ctype.h>\n#include <setjmp.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include \"luasandbox/lauxlib.h\"\n#include \"luasandbox/lua.h\"\n#include \"luasandbox/lualib.h\"\n#include \"luasandbox/util/output_buffer.h\"\n#include \"luasandbox_defines.h\"\n#include \"luasandbox_impl.h\"\n#include \"luasandbox_serialize.h\"\n\nlsb_err_id LSB_ERR_INIT       = \"already initialized\";\nlsb_err_id LSB_ERR_LUA        = \"lua error\"; // use lsb_get_error for details\nlsb_err_id LSB_ERR_TERMINATED = \"sandbox already terminated\";\n\nstatic jmp_buf g_jbuf;\n\nstatic const luaL_Reg preload_module_list[] = {\n  { LUA_BASELIBNAME, luaopen_base },\n  { LUA_COLIBNAME, luaopen_coroutine },\n  { LUA_TABLIBNAME, luaopen_table },\n  { LUA_IOLIBNAME, luaopen_io },\n  { LUA_OSLIBNAME, luaopen_os },\n  { LUA_STRLIBNAME, luaopen_string },\n  { LUA_MATHLIBNAME, luaopen_math },\n  { NULL, NULL }\n};\n\nstatic int libsize(const luaL_Reg *l)\n{\n  int size = 0;\n  for (; l->name; l++) size++;\n  return size;\n}\n\nstatic void preload_modules(lua_State *lua)\n{\n  const luaL_Reg *lib = preload_module_list;\n  luaL_findtable(lua, LUA_REGISTRYINDEX, \"_PRELOADED\",\n                 libsize(preload_module_list));\n  for (; lib->func; lib++) {\n    lua_pushstring(lua, lib->name);\n    lua_pushcfunction(lua, lib->func);\n    lua_rawset(lua, -3);\n  }\n  lua_pop(lua, 1); // remove the preloaded table\n}\n\n\n/**\n* Implementation of the memory allocator for the Lua state.\n*\n* See: http://www.lua.org/manual/5.1/manual.html#lua_Alloc\n*\n* @param ud Pointer to the lsb_lua_sandbox\n* @param ptr Pointer to the memory block being allocated/reallocated/freed.\n* @param osize The original size of the memory block.\n* @param nsize The new size of the memory block.\n*\n* @return void* A pointer to the memory block.\n*/\nstatic void* memory_manager(void *ud, void *ptr, size_t osize, size_t nsize)\n{\n  lsb_lua_sandbox *lsb = (lsb_lua_sandbox *)ud;\n\n  void *nptr = NULL;\n  if (nsize == 0) {\n    free(ptr);\n    lsb->usage[LSB_UT_MEMORY][LSB_US_CURRENT] -= osize;\n  } else {\n    size_t new_state_memory =\n        lsb->usage[LSB_UT_MEMORY][LSB_US_CURRENT] + nsize - osize;\n    if (0 == lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT]\n        || new_state_memory\n        <= lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT]) {\n      nptr = realloc(ptr, nsize);\n      if (nptr != NULL) {\n        lsb->usage[LSB_UT_MEMORY][LSB_US_CURRENT] =\n            new_state_memory;\n        if (lsb->usage[LSB_UT_MEMORY][LSB_US_CURRENT]\n            > lsb->usage[LSB_UT_MEMORY][LSB_US_MAXIMUM]) {\n          lsb->usage[LSB_UT_MEMORY][LSB_US_MAXIMUM] =\n              lsb->usage[LSB_UT_MEMORY][LSB_US_CURRENT];\n        }\n      }\n    }\n  }\n  return nptr;\n}\n\n\nstatic size_t instruction_usage(lsb_lua_sandbox *lsb)\n{\n  return lua_gethookcount(lsb->lua) - lua_gethookcountremaining(lsb->lua);\n}\n\n\nstatic void instruction_manager(lua_State *lua, lua_Debug *ar)\n{\n  if (LUA_HOOKCOUNT == ar->event) {\n    luaL_error(lua, \"instruction_limit exceeded\");\n  }\n}\n\n\nstatic int output(lua_State *lua)\n{\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_THIS_PTR);\n  lsb_lua_sandbox *lsb = lua_touserdata(lua, -1);\n  lua_pop(lua, 1); // remove this ptr\n  if (!lsb) return luaL_error(lua, \"%s() invalid \" LSB_THIS_PTR, __func__);\n\n  int n = lua_gettop(lua);\n  if (n == 0) {\n    return luaL_argerror(lsb->lua, 0, \"must have at least one argument\");\n  }\n  lsb_output_coroutine(lsb, lua, 1, n, 1);\n  return 0;\n}\n\n\nstatic int output_print(lua_State *lua)\n{\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_THIS_PTR);\n  lsb_lua_sandbox *lsb = lua_touserdata(lua, -1);\n  lua_pop(lua, 1); // remove this ptr\n  if (!lsb) return luaL_error(lua, \"print() invalid \" LSB_THIS_PTR);\n\n  lsb->output.buf[0] = 0;\n  lsb->output.pos = 0; // clear the buffer\n\n  int n = lua_gettop(lua);\n  if (!lsb->logger.cb || n == 0) {\n    return 0;\n  }\n\n  lua_getglobal(lua, \"tostring\");\n  for (int i = 1; i <= n; ++i) {\n    lua_pushvalue(lua, -1);  // tostring\n    lua_pushvalue(lua, i);   // value\n    lua_call(lua, 1, 1);\n    const char *s = lua_tostring(lua, -1);\n    if (s == NULL) {\n      return luaL_error(lua, LUA_QL(\"tostring\") \" must return a string to \"\n                        LUA_QL(\"print\"));\n    }\n    if (i > 1) {\n      lsb_outputc(&lsb->output, '\\t');\n    }\n\n    while (*s) {\n      if (isprint(*s)) {\n        lsb_outputc(&lsb->output, *s);\n      } else {\n        lsb_outputc(&lsb->output, ' ');\n      }\n      ++s;\n    }\n    lua_pop(lua, 1);\n  }\n\n  const char *component = NULL;\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_CONFIG_TABLE);\n  if (lua_type(lua, -1) == LUA_TTABLE) {\n    // this makes an assumptions by looking for a Heka sandbox specific cfg\n    // variable but will fall back to the lua filename in the generic case\n    lua_getfield(lua, -1, \"Logger\");\n    component = lua_tostring(lua, -1);\n    if (!component) {\n      component = lsb->lua_file;\n    }\n  }\n\n  lsb->logger.cb(lsb->logger.context, component, 7, \"%s\", lsb->output.buf);\n  lsb->output.pos = 0;\n  return 0;\n}\n\n\nstatic int read_config(lua_State *lua)\n{\n  luaL_checkstring(lua, 1);\n  luaL_argcheck(lua, lua_gettop(lua) == 1, 0, \"too many arguments\");\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_CONFIG_TABLE);\n  if (lua_type(lua, -1) == LUA_TTABLE) {\n    lua_getfield(lua, -1, lua_tostring(lua, 1));\n  } else {\n    lua_pushnil(lua);\n  }\n  return 1;\n}\n\n\nstatic int unprotected_panic(lua_State *lua)\n{\n  (void)lua;\n  longjmp(g_jbuf, 1);\n  return 0;\n}\n\n\nstatic size_t get_size(lua_State *lua, int idx, const char *item)\n{\n  lua_getfield(lua, idx, item);\n  size_t size = (size_t)lua_tonumber(lua, -1);\n  lua_pop(lua, 1);\n  return size;\n}\n\n\nstatic int check_string(lua_State *L, int idx, const char *name,\n                        const char *dflt)\n{\n  lua_getfield(L, idx, name);\n  int t = lua_type(L, -1);\n  switch (t) {\n  case LUA_TSTRING:\n    break;\n  case LUA_TNIL:\n    if (dflt) {\n      lua_pushstring(L, dflt); // add the default to the config\n      lua_setglobal(L, name);\n    }\n    break;\n  default:\n    lua_pushfstring(L, \"%s must be set to a string\", name);\n    return 1;\n  }\n  return 0;\n}\n\n\nstatic int check_unsigned(lua_State *L, int idx, const char *name, unsigned val)\n{\n  lua_getfield(L, idx, name);\n  double d;\n  switch (lua_type(L, -1)) {\n  case LUA_TNUMBER:\n    d = lua_tonumber(L, -1);\n    if (d < 0 || d > UINT_MAX) {\n      lua_pushfstring(L, \"%s must be an unsigned int\", name);\n      return 1;\n    }\n    break;\n  case LUA_TNIL: // add the default to the config\n    lua_pushnumber(L, (lua_Number)val);\n    lua_setglobal(L, name);\n    break; // use the default\n  default:\n    lua_pushfstring(L, \"%s must be set to a number\", name);\n    return 1;\n  }\n  lua_pop(L, 1);\n  return 0;\n}\n\n\nstatic int check_size(lua_State *L, int idx, const char *name, size_t val)\n{\n  lua_getfield(L, idx, name);\n  double d;\n  switch (lua_type(L, -1)) {\n  case LUA_TNUMBER:\n    d = lua_tonumber(L, -1);\n    if (d < 0 || d > SIZE_MAX) {\n      lua_pushfstring(L, \"%s must be a size_t\", name);\n      return 1;\n    }\n    break;\n  case LUA_TNIL: // add the default to the config\n    lua_pushnumber(L, (lua_Number)val);\n    lua_setglobal(L, name);\n    break; // use the default\n  default:\n    lua_pushfstring(L, \"%s must be set to a number\", name);\n    return 1;\n  }\n  lua_pop(L, 1);\n  return 0;\n}\n\n\nstatic lua_State* load_sandbox_config(const char *cfg, lsb_logger *logger)\n{\n  lua_State *L = luaL_newstate();\n  if (!L) {\n    if (logger->cb) logger->cb(logger->context, __func__, 3,\n                               \"lua_State creation failed\");\n    return NULL;\n  }\n\n  if (!cfg) cfg = \"\"; // use the default settings\n\n  int ret = luaL_dostring(L, cfg);\n  if (ret) goto cleanup;\n\n  ret = check_size(L, LUA_GLOBALSINDEX, LSB_INPUT_LIMIT, 64 * 1024);\n  if (ret) goto cleanup;\n\n  ret = check_size(L, LUA_GLOBALSINDEX, LSB_OUTPUT_LIMIT, 64 * 1024);\n  if (ret) goto cleanup;\n\n  ret = check_size(L, LUA_GLOBALSINDEX, LSB_MEMORY_LIMIT, 8 * 1024 * 1024);\n  if (ret) goto cleanup;\n\n  ret = check_size(L, LUA_GLOBALSINDEX, LSB_INSTRUCTION_LIMIT, 1000000);\n  if (ret) goto cleanup;\n\n  ret = check_unsigned(L, LUA_GLOBALSINDEX, LSB_LOG_LEVEL, 3);\n  if (ret) goto cleanup;\n\n  ret = check_string(L, LUA_GLOBALSINDEX, LSB_LUA_PATH, NULL);\n  if (ret) goto cleanup;\n\n  ret = check_string(L, LUA_GLOBALSINDEX, LSB_LUA_CPATH, NULL);\n  if (ret) goto cleanup;\n\ncleanup:\n  if (ret) {\n    if (logger->cb) {\n      logger->cb(logger->context, __func__, 3, \"config error: %s\",\n                 lua_tostring(L, -1));\n    }\n    lua_close(L);\n    return NULL;\n  }\n  return L;\n}\n\n\nstatic void copy_table(lua_State *sb, lua_State *cfg, lsb_logger *logger)\n{\n  lua_newtable(sb);\n  lua_pushnil(cfg);\n  while (lua_next(cfg, -2) != 0) {\n    int kt = lua_type(cfg, -2);\n    int vt = lua_type(cfg, -1);\n    switch (kt) {\n    case LUA_TNUMBER:\n    case LUA_TSTRING:\n      switch (vt) {\n      case LUA_TSTRING:\n        {\n          size_t len;\n          const char *tmp = lua_tolstring(cfg, -1, &len);\n          if (tmp) {\n            lua_pushlstring(sb, tmp, len);\n            if (kt == LUA_TSTRING) {\n              lua_setfield(sb, -2, lua_tostring(cfg, -2));\n            } else {\n              lua_rawseti(sb, -2, (int)lua_tointeger(cfg, -2));\n            }\n          }\n        }\n        break;\n      case LUA_TNUMBER:\n        lua_pushnumber(sb, lua_tonumber(cfg, -1));\n        if (kt == LUA_TSTRING) {\n          lua_setfield(sb, -2, lua_tostring(cfg, -2));\n        } else {\n          lua_rawseti(sb, -2, (int)lua_tointeger(cfg, -2));\n        }\n        break;\n      case LUA_TBOOLEAN:\n        lua_pushboolean(sb, lua_toboolean(cfg, -1));\n        if (kt == LUA_TSTRING) {\n          lua_setfield(sb, -2, lua_tostring(cfg, -2));\n        } else {\n          lua_rawseti(sb, -2, (int)lua_tointeger(cfg, -2));\n        }\n        break;\n      case LUA_TTABLE:\n        copy_table(sb, cfg, logger);\n        break;\n      default:\n        if (logger->cb) {\n          logger->cb(logger->context, __func__, 4,\n                     \"skipping config value type: %s\", lua_typename(cfg, vt));\n        }\n        break;\n      }\n      break;\n    default:\n      if (logger->cb) {\n        logger->cb(logger->context, __func__, 4, \"skipping config key type: %s\",\n                   lua_typename(cfg, kt));\n      }\n      break;\n    }\n    lua_pop(cfg, 1);\n  }\n\n  switch (lua_type(cfg, -2)) {\n  case LUA_TSTRING:\n    lua_setfield(sb, -2, lua_tostring(cfg, -2));\n    break;\n  case LUA_TNUMBER:\n    lua_rawseti(sb, -2, (int)lua_tointeger(cfg, -2));\n    break;\n  }\n}\n\n\nstatic void set_random_seed()\n{\n  bool seeded = false;\n#ifdef _WIN32\n  // todo use CryptGenRandom to seed srand\n#else\n  FILE *fh = fopen(\"/dev/urandom\", \"r\" CLOSE_ON_EXEC);\n  if (fh) {\n    unsigned seed;\n    unsigned char advance;\n    if (fread(&seed, sizeof(unsigned), 1, fh) == 1 &&\n        fread(&advance, sizeof(char), 1, fh) == 1) {\n      srand(seed);\n      // advance the sequence a random amount\n      for (unsigned i = 0; i < advance; ++i) {\n        rand();\n      }\n      seeded = true;\n    }\n    fclose(fh);\n  }\n#endif\n  if (!seeded) {\n    srand((unsigned)time(NULL));\n  }\n}\n\n\nlsb_lua_sandbox* lsb_create(void *parent,\n                            const char *lua_file,\n                            const char *cfg,\n                            lsb_logger *logger)\n{\n  if (!lua_file) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 3, \"lua_file must be specified\");\n    }\n    return NULL;\n  }\n\n  if (!lsb_set_tz(NULL)) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 3, \"fail to set the TZ to UTC\");\n    }\n    return NULL;\n  }\n\n  set_random_seed();\n\n  lsb_lua_sandbox *lsb = calloc(1, sizeof(*lsb));\n  if (!lsb) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 3, \"memory allocation failed\");\n    }\n    return NULL;\n  }\n\n  lsb->lua = lua_newstate(memory_manager, lsb);\n  if (logger) {\n    lsb->logger = *logger;\n  }\n\n  if (!lsb->lua) {\n    if (lsb->logger.cb) {\n      lsb->logger.cb(lsb->logger.context, __func__, 3, \"lua state creation \"\n                     \"failed\");\n    }\n    free(lsb);\n    return NULL;\n  }\n\n\n  // add the config to the lsb_config registry table\n  lua_State *lua_cfg = load_sandbox_config(cfg, &lsb->logger);\n  if (!lua_cfg) {\n    lua_close(lsb->lua);\n    free(lsb);\n    return NULL;\n  }\n  lua_pushnil(lua_cfg);\n  lua_pushvalue(lua_cfg, LUA_GLOBALSINDEX);\n  copy_table(lsb->lua, lua_cfg, &lsb->logger);\n  lua_pop(lua_cfg, 2);\n  lua_close(lua_cfg);\n  size_t ml = get_size(lsb->lua, -1, LSB_MEMORY_LIMIT);\n  size_t il = get_size(lsb->lua, -1, LSB_INSTRUCTION_LIMIT);\n  size_t ol = get_size(lsb->lua, -1, LSB_OUTPUT_LIMIT);\n  size_t log_level = get_size(lsb->lua, -1, LSB_LOG_LEVEL);\n  lua_setfield(lsb->lua, LUA_REGISTRYINDEX, LSB_CONFIG_TABLE);\n  lua_pushlightuserdata(lsb->lua, lsb);\n  lua_setfield(lsb->lua, LUA_REGISTRYINDEX, LSB_THIS_PTR);\n  lua_pushcfunction(lsb->lua, &read_config);\n  lua_setglobal(lsb->lua, \"read_config\");\n\n  lua_pushcfunction(lsb->lua, &output);\n  lua_setglobal(lsb->lua, \"output\");\n  preload_modules(lsb->lua);\n\n  lsb->parent = parent;\n  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = ml;\n  lsb->usage[LSB_UT_INSTRUCTION][LSB_US_LIMIT] = il;\n  lsb->usage[LSB_UT_OUTPUT][LSB_US_LIMIT] = ol;\n  lsb->state = LSB_UNKNOWN;\n  lsb->error_message[0] = 0;\n  lsb->lua_file = malloc(strlen(lua_file) + 1);\n  lsb->state_file = NULL;\n  if (log_level != 7) {\n    lsb->logger.cb = NULL; // only give the sandbox access to the logger (print)\n                           // when debugging\n  }\n\n  if (!lsb->lua_file || lsb_init_output_buffer(&lsb->output, ol)) {\n    if (lsb->logger.cb) {\n      lsb->logger.cb(lsb->logger.context, __func__, 3, \"memory allocation \"\n                     \"failed\");\n    }\n    lsb_free_output_buffer(&lsb->output);\n    free(lsb->lua_file);\n    lua_close(lsb->lua);\n    lsb->lua = NULL;\n    free(lsb);\n    return NULL;\n  }\n  strcpy(lsb->lua_file, lua_file);\n  return lsb;\n}\n\n\nlsb_err_value lsb_init(lsb_lua_sandbox *lsb, const char *state_file)\n{\n  if (!lsb) {\n    return LSB_ERR_UTIL_NULL;\n  }\n\n  if (lsb->state != LSB_UNKNOWN) {\n    lsb_terminate(lsb, LSB_ERR_INIT);\n    return LSB_ERR_INIT;\n  }\n\n  if (state_file && strlen(state_file) > 0) {\n    lsb->state_file = malloc(strlen(state_file) + 1);\n    if (!lsb->state_file) {\n      lsb_terminate(lsb, LSB_ERR_UTIL_OOM);\n      return LSB_ERR_UTIL_OOM;\n    }\n    strcpy(lsb->state_file, state_file);\n  }\n\n  size_t mem_limit = lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT];\n  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = 0;\n\n  // load package module\n  lua_pushcfunction(lsb->lua, luaopen_package);\n  lua_pushstring(lsb->lua, LUA_LOADLIBNAME);\n  lua_call(lsb->lua, 1, 1);\n  lua_newtable(lsb->lua);\n  lua_setmetatable(lsb->lua, -2);\n  lua_pop(lsb->lua, 1);\n\n  // load base module\n  lua_getglobal(lsb->lua, \"require\");\n  if (!lua_iscfunction(lsb->lua, -1)) {\n    snprintf(lsb->error_message, LSB_ERROR_SIZE,\n             \"lsb_init() 'require' not found\");\n    lsb_terminate(lsb, NULL);\n    return LSB_ERR_LUA;\n  }\n  lua_pushstring(lsb->lua, LUA_BASELIBNAME);\n  if (lua_pcall(lsb->lua, 1, 0, 0)) {\n    const char *em = lua_tostring(lsb->lua, -1);\n    snprintf(lsb->error_message, LSB_ERROR_SIZE,\n             \"lsb_init %s\", em ? em : LSB_NIL_ERROR);\n    lsb_terminate(lsb, NULL);\n    return LSB_ERR_LUA;\n  }\n  lsb_add_function(lsb, output_print, \"print\");\n\n  if (lsb->usage[LSB_UT_INSTRUCTION][LSB_US_LIMIT] != 0) {\n    lua_sethook(lsb->lua, instruction_manager, LUA_MASKCOUNT,\n                (int)lsb->usage[LSB_UT_INSTRUCTION][LSB_US_LIMIT]);\n  } else {\n    lua_sethook(lsb->lua, NULL, 0, 0);\n  }\n  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = mem_limit;\n  lua_CFunction pf = lua_atpanic(lsb->lua, unprotected_panic);\n  int jump = setjmp(g_jbuf);\n  if (jump || luaL_dofile(lsb->lua, lsb->lua_file) != 0) {\n    int len = snprintf(lsb->error_message, LSB_ERROR_SIZE, \"%s\",\n                       lua_tostring(lsb->lua, -1));\n    if (len >= LSB_ERROR_SIZE || len < 0) {\n      lsb->error_message[LSB_ERROR_SIZE - 1] = 0;\n    }\n    lsb_terminate(lsb, NULL);\n    return LSB_ERR_LUA;\n  } else {\n    lua_gc(lsb->lua, LUA_GCCOLLECT, 0);\n    lsb->usage[LSB_UT_INSTRUCTION][LSB_US_CURRENT] = instruction_usage(lsb);\n    if (lsb->usage[LSB_UT_INSTRUCTION][LSB_US_CURRENT]\n        > lsb->usage[LSB_UT_INSTRUCTION][LSB_US_MAXIMUM]) {\n      lsb->usage[LSB_UT_INSTRUCTION][LSB_US_MAXIMUM] =\n          lsb->usage[LSB_UT_INSTRUCTION][LSB_US_CURRENT];\n    }\n    lsb->state = LSB_RUNNING;\n    if (lsb->state_file) {\n      lsb_err_value ret = restore_global_data(lsb);\n      if (ret) return ret;\n    }\n  }\n  lua_atpanic(lsb->lua, pf);\n  return NULL;\n}\n\n\nstatic void stop_hook(lua_State *lua, lua_Debug *ar)\n{\n  (void)ar;  /* unused arg. */\n  lua_sethook(lua, NULL, 0, 0);\n  luaL_error(lua, LSB_SHUTTING_DOWN);\n}\n\n\nvoid lsb_stop_sandbox_clean(lsb_lua_sandbox *lsb)\n{\n  if (!lsb) {\n    return;\n  }\n  lsb->state = LSB_STOP;\n}\n\n\nvoid lsb_stop_sandbox(lsb_lua_sandbox *lsb)\n{\n  if (!lsb) {\n    return;\n  }\n\n  lua_State *lua = lsb_get_lua(lsb);\n  if (lua) {\n    lua_sethook(lua, stop_hook, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1);\n  }\n}\n\n\nchar* lsb_destroy(lsb_lua_sandbox *lsb)\n{\n  char *err = NULL;\n  if (!lsb) {\n    return err;\n  }\n\n  if (preserve_global_data(lsb)) {\n    size_t len = strlen(lsb->error_message);\n    err = malloc(len + 1);\n    if (err != NULL) {\n      strcpy(err, lsb->error_message);\n    }\n  }\n\n  if (lsb->lua) {\n    lua_close(lsb->lua);\n    lsb->lua = NULL;\n  }\n\n  lsb_free_output_buffer(&lsb->output);\n  free(lsb->state_file);\n  free(lsb->lua_file);\n  free(lsb);\n  return err;\n}\n\n\nsize_t lsb_usage(lsb_lua_sandbox *lsb, lsb_usage_type utype,\n                 lsb_usage_stat ustat)\n{\n  if (!lsb || utype >= LSB_UT_MAX || ustat >= LSB_US_MAX) {\n    return 0;\n  }\n  return lsb->usage[utype][ustat];\n}\n\n\nconst char* lsb_get_error(lsb_lua_sandbox *lsb)\n{\n  return lsb ? lsb->error_message : \"\";\n}\n\n\nvoid lsb_set_error(lsb_lua_sandbox *lsb, const char *err)\n{\n  if (lsb) {\n    if (err) {\n      strncpy(lsb->error_message, err, LSB_ERROR_SIZE);\n      lsb->error_message[LSB_ERROR_SIZE - 1] = 0;\n    } else {\n      lsb->error_message[0] = 0;\n    }\n  }\n}\n\n\nlua_State* lsb_get_lua(lsb_lua_sandbox *lsb)\n{\n  return lsb ? lsb->lua : NULL;\n}\n\n\nconst char* lsb_get_lua_file(lsb_lua_sandbox *lsb)\n{\n  return lsb ? lsb->lua_file : NULL;\n}\n\n\nvoid* lsb_get_parent(lsb_lua_sandbox *lsb)\n{\n  return lsb ? lsb->parent : NULL;\n}\n\n\nconst lsb_logger* lsb_get_logger(lsb_lua_sandbox *lsb)\n{\n  return lsb ? &lsb->logger : NULL;\n}\n\n\nlsb_state lsb_get_state(lsb_lua_sandbox *lsb)\n{\n  return lsb ? lsb->state : LSB_UNKNOWN;\n}\n\n\nvoid lsb_add_function(lsb_lua_sandbox *lsb, lua_CFunction func,\n                      const char *func_name)\n{\n  if (!lsb || !func || !func_name) return;\n  if (lsb->state == LSB_TERMINATED) return;\n\n  lua_pushcfunction(lsb->lua, func);\n  lua_setglobal(lsb->lua, func_name);\n}\n\n\nlsb_err_value lsb_pcall_setup(lsb_lua_sandbox *lsb, const char *func_name)\n{\n  if (!lsb || !func_name) return LSB_ERR_UTIL_NULL;\n  if (lsb->state == LSB_TERMINATED) return LSB_ERR_TERMINATED;\n\n  if (lsb->usage[LSB_UT_INSTRUCTION][LSB_US_LIMIT] != 0) {\n    lua_sethook(lsb->lua, instruction_manager, LUA_MASKCOUNT,\n                (int)lsb->usage[LSB_UT_INSTRUCTION][LSB_US_LIMIT]);\n  } else {\n    lua_sethook(lsb->lua, NULL, 0, 0);\n  }\n  lua_getglobal(lsb->lua, func_name);\n  if (!lua_isfunction(lsb->lua, -1)) {\n    int len = snprintf(lsb->error_message, LSB_ERROR_SIZE, \"%s() not found\",\n                       func_name);\n    if (len >= LSB_ERROR_SIZE || len < 0) {\n      lsb->error_message[LSB_ERROR_SIZE - 1] = 0;\n    }\n    return LSB_ERR_LUA;\n  }\n  return NULL;\n}\n\n\nvoid lsb_pcall_teardown(lsb_lua_sandbox *lsb)\n{\n  if (!lsb) return;\n\n  lsb->usage[LSB_UT_INSTRUCTION][LSB_US_CURRENT] =\n      (unsigned)instruction_usage(lsb);\n  if (lsb->usage[LSB_UT_INSTRUCTION][LSB_US_CURRENT]\n      > lsb->usage[LSB_UT_INSTRUCTION][LSB_US_MAXIMUM]) {\n    lsb->usage[LSB_UT_INSTRUCTION][LSB_US_MAXIMUM] =\n        lsb->usage[LSB_UT_INSTRUCTION][LSB_US_CURRENT];\n  }\n}\n\n\nvoid lsb_terminate(lsb_lua_sandbox *lsb, const char *err)\n{\n  if (!lsb) return;\n\n  if (err) {\n    strncpy(lsb->error_message, err, LSB_ERROR_SIZE);\n    lsb->error_message[LSB_ERROR_SIZE - 1] = 0;\n  }\n  lsb->state = LSB_TERMINATED;\n}\n"
  },
  {
    "path": "src/luasandbox_defines.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Shared compiler defines @file */\n\n#ifndef luasandbox_defines_h_\n#define luasandbox_defines_h_\n\n#ifdef _WIN32\n#if _MSC_VER < 1900\n#define snprintf _snprintf\n#endif\n#endif\n\n#if __linux\n#define CLOSE_ON_EXEC \"e\"\n#else\n#define CLOSE_ON_EXEC \"\"\n#endif\n\n#ifdef _MSC_VER\n#ifndef __func__\n#define __func__ __FUNCTION__\n#endif\n#endif\n\n#endif\n"
  },
  {
    "path": "src/luasandbox_impl.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Lua sandbox private functions @file */\n\n#ifndef luasandbox_impl_h_\n#define luasandbox_impl_h_\n\n#include \"luasandbox.h\"\n#include \"luasandbox/lua.h\"\n#include \"luasandbox/util/output_buffer.h\"\n\nstruct lsb_lua_sandbox {\n  lua_State         *lua;\n  void              *parent;\n  char              *lua_file;\n  char              *state_file;\n  lsb_logger        logger;\n  lsb_state         state;\n  lsb_output_buffer output;\n  size_t            usage[LSB_UT_MAX][LSB_US_MAX];\n  char              error_message[LSB_ERROR_SIZE];\n};\n\n/**\n * Serialize all user global data to disk.\n *\n * @param lsb Pointer to the sandbox.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nlsb_err_value preserve_global_data(lsb_lua_sandbox *lsb);\n\n/**\n * Restores previously serialized data from disk.\n *\n * @param lsb Pointer to the sandbox.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nlsb_err_value restore_global_data(lsb_lua_sandbox *lsb);\n\n#endif\n"
  },
  {
    "path": "src/luasandbox_output.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Lua sandbox output buffer implementation @file */\n\n#define LUA_LIB\n#include \"luasandbox_output.h\"\n\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"luasandbox/lauxlib.h\"\n#include \"luasandbox_impl.h\"\n#include \"luasandbox_serialize.h\"\n\nstatic const char *output_function = \"lsb_output\";\nstatic const char *zero_copy_function = \"lsb_zero_copy\";\n\nvoid lsb_add_output_function(lua_State *lua, lua_CFunction fp)\n{\n  lua_pushstring(lua, output_function);\n  lua_pushcfunction(lua, fp);\n  lua_rawset(lua, -3);\n}\n\n\nlua_CFunction lsb_get_output_function(lua_State *lua, int index)\n{\n  lua_CFunction fp = NULL;\n  lua_getfenv(lua, index);\n  lua_pushstring(lua, output_function);\n  lua_rawget(lua, -2);\n  fp = lua_tocfunction(lua, -1);\n  lua_pop(lua, 2); // environment and field\n  return fp;\n}\n\n\nvoid lsb_add_zero_copy_function(lua_State *lua, lua_CFunction fp)\n{\n  lua_pushstring(lua, zero_copy_function);\n  lua_pushcfunction(lua, fp);\n  lua_rawset(lua, -3);\n}\n\n\nlua_CFunction lsb_get_zero_copy_function(lua_State *lua, int index)\n{\n  lua_CFunction fp = NULL;\n  lua_getfenv(lua, index);\n  lua_pushstring(lua, zero_copy_function);\n  lua_rawget(lua, -2);\n  fp = lua_tocfunction(lua, -1);\n  lua_pop(lua, 2); // environment and field\n  return fp;\n}\n\n\nvoid lsb_output(lsb_lua_sandbox *lsb, int start, int end, int append)\n{\n  lsb_output_coroutine(lsb, lsb->lua, start, end, append);\n}\n\n\nvoid lsb_output_coroutine(lsb_lua_sandbox *lsb, lua_State *lua, int start,\n                          int end, int append)\n{\n  if (!append) {\n    lsb->output.pos = 0;\n  }\n\n  int result = 0;\n  for (int i = start; result == 0 && i <= end; ++i) {\n    switch (lua_type(lua, i)) {\n    case LUA_TNUMBER:\n      if (lsb_outputd(&lsb->output, lua_tonumber(lua, i))) {\n        result = 1;\n      }\n      break;\n    case LUA_TSTRING:\n      {\n        size_t len;\n        const char *s = lua_tolstring(lua, i, &len);\n        if (lsb_outputs(&lsb->output, s, len)) {\n          result = 1;\n        }\n      }\n      break;\n    case LUA_TNIL:\n      if (lsb_outputs(&lsb->output, \"nil\", 3)) {\n        result = 1;\n      }\n      break;\n    case LUA_TBOOLEAN:\n      if (lsb_outputf(&lsb->output, \"%s\", lua_toboolean(lua, i)\n                      ? \"true\" : \"false\")) {\n        result = 1;\n      }\n      break;\n    case LUA_TUSERDATA:\n      {\n        lua_CFunction fp = lsb_get_output_function(lua, i);\n        if (!fp) {\n          luaL_argerror(lua, i, \"unknown userdata type\");\n          return; // never reaches here but the compiler doesn't know it\n        }\n        lua_pushvalue(lua, i);\n        lua_pushlightuserdata(lua, &lsb->output);\n        result = fp(lua);\n        lua_pop(lua, 2); // remove the copy of the value and the output\n      }\n      break;\n    default:\n      luaL_argerror(lua, i, \"unsupported type\");\n      break;\n    }\n  }\n  lsb->usage[LSB_UT_OUTPUT][LSB_US_CURRENT] = lsb->output.pos;\n  if (lsb->usage[LSB_UT_OUTPUT][LSB_US_CURRENT]\n      > lsb->usage[LSB_UT_OUTPUT][LSB_US_MAXIMUM]) {\n    lsb->usage[LSB_UT_OUTPUT][LSB_US_MAXIMUM] =\n        lsb->usage[LSB_UT_OUTPUT][LSB_US_CURRENT];\n  }\n\n  if (result != 0) {\n    if (lsb->error_message[0] == 0) {\n      luaL_error(lua, \"output_limit exceeded\");\n    }\n    luaL_error(lua, lsb->error_message);\n  }\n}\n\n\nconst char* lsb_get_output(lsb_lua_sandbox *lsb, size_t *len)\n{\n  if (len) *len = lsb->output.pos;\n  if (lsb->output.pos == 0) return \"\";\n  lsb->output.pos = 0; // internally reset the buffer for the next write\n  return lsb->output.buf;\n}\n"
  },
  {
    "path": "src/luasandbox_serialize.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Sandbox serialization implementation @file */\n\n#define LUA_LIB\n#include \"luasandbox_serialize.h\"\n\n#include <math.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"luasandbox/lauxlib.h\"\n#include \"luasandbox/lualib.h\"\n#include \"luasandbox_defines.h\"\n#include \"luasandbox_impl.h\"\n\n#ifdef _MSC_VER\n#pragma warning( disable : 4056 )\n#endif\n\ntypedef struct\n{\n  const void *ptr;\n  size_t name_pos;\n} table_ref;\n\ntypedef struct\n{\n  size_t size;\n  size_t pos;\n  table_ref *array;\n} table_ref_array;\n\ntypedef struct\n{\n  FILE *fh;\n  lsb_output_buffer keys;\n  table_ref_array tables;\n  const void *globals;\n} serialization_data;\n\nstatic const char *preservation_version = \"_PRESERVATION_VERSION\";\nstatic const char *serialize_function = \"lsb_serialize\";\n\n/**\n * Serializes a Lua table structure.\n *\n * @param lsb Pointer to the sandbox.\n * @param data Pointer to the serialization state data.\n * @param parent Index pointing to the parent's name in the table array.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nstatic lsb_err_value\nserialize_table(lsb_lua_sandbox *lsb, serialization_data *data, size_t parent);\n\n/**\n * Serializes a Lua data value.\n *\n * @param lsb Pointer to the sandbox.\n * @param index Lua stack index where the data resides.\n * @param ob Pointer the output buffer.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nstatic lsb_err_value serialize_data(lsb_lua_sandbox *lsb,\n                                    int index,\n                                    lsb_output_buffer *ob);\n\n/**\n * Serializes a table key value pair.\n *\n * @param lsb Pointer to the sandbox.\n * @param data Pointer to the serialization state data.\n * @param parent Index pointing to the parent's name in the table array.\n *\n * @return lsb_err_value NULL on success error message on failure\n */\nstatic lsb_err_value\nserialize_kvp(lsb_lua_sandbox *lsb, serialization_data *data, size_t parent);\n\n/**\n * Returns the serialization function if the userdata implemented one.\n *\n * @param lua Lua State.\n * @param index Position on the stack where the userdata pointer resides.\n *\n * @return lua_CFunction NULL if not found\n */\nstatic lua_CFunction get_serialize_function(lua_State *lua, int index)\n{\n  lua_CFunction fp = NULL;\n  lua_getfenv(lua, index);\n  lua_pushstring(lua, serialize_function);\n  lua_rawget(lua, -2);\n  fp = lua_tocfunction(lua, -1);\n  lua_pop(lua, 2); // environment and field\n  return fp;\n}\n\n/**\n * Helper function to determine what data should not be serialized.\n *\n * @param lsb Pointer to the sandbox.\n * @param data Pointer to the serialization state data.\n * @param index Lua stack index where the data resides.\n * @param fp Function pointer to be set for userdata serialization\n *\n * @return int\n */\nstatic int\nignore_value_type(lsb_lua_sandbox *lsb, serialization_data *data, int index,\n                  lua_CFunction *fp)\n{\n  switch (lua_type(lsb->lua, index)) {\n  case LUA_TSTRING:\n  case LUA_TNUMBER:\n  case LUA_TBOOLEAN:\n    return 0;\n  case LUA_TTABLE:\n    if (lua_getmetatable(lsb->lua, index) != 0) {\n      lua_pop(lsb->lua, 1); // Remove the metatable.\n      return 1;\n    }\n    if (lua_topointer(lsb->lua, index) == data->globals) {\n      return 1;\n    }\n    return 0;\n  case LUA_TUSERDATA:\n    *fp = get_serialize_function(lsb->lua, index);\n    return !*fp ? 1 : 0;\n  default:\n    break;\n  }\n  return 1;\n}\n\n\n/**\n * Looks for a table to see if it has already been processed.\n *\n * @param tra Pointer to the table references.\n * @param ptr Pointer value of the table.\n *\n * @return table_ref* NULL if not found.\n */\nstatic table_ref* find_table_ref(table_ref_array *tra, const void *ptr)\n{\n  for (size_t i = 0; i < tra->pos; ++i) {\n    if (ptr == tra->array[i].ptr) {\n      return &tra->array[i];\n    }\n  }\n  return NULL;\n}\n\n\n/**\n * Adds a table to the processed array.\n *\n * @param tra Pointer to the table references.\n * @param ptr Pointer value of the table.\n * @param name_pos Index pointing to name in the table array.\n *\n * @return table_ref* Pointer to the table reference or NULL if out of memory.\n */\nstatic table_ref*\nadd_table_ref(table_ref_array *tra, const void *ptr, size_t name_pos)\n{\n  if (tra->pos == tra->size) {\n    size_t newsize = tra->size * 2;\n    void *p = realloc(tra->array, newsize * sizeof(table_ref));\n    if (p != NULL) {\n      tra->array = p;\n      tra->size = newsize;\n    } else {\n      return NULL;\n    }\n  }\n  tra->array[tra->pos].ptr = ptr;\n  tra->array[tra->pos].name_pos = name_pos;\n  return &tra->array[tra->pos++];\n}\n\n\n/**\n * Extracts the current preservation from the sandbox.\n *\n * @param lua Lua state\n *\n * @return int Version numebr\n */\nstatic int get_preservation_version(lua_State *lua)\n{\n  int ver = 0;\n  lua_getglobal(lua, preservation_version);\n  int t = lua_type(lua, -1);\n  if (t == LUA_TNUMBER) {\n    ver = (int)lua_tointeger(lua, -1);\n  }\n  lua_pop(lua, 1); // remove the version from the stack\n\n  if (t != LUA_TNIL) { // remove the version from the data preservation\n    lua_pushnil(lua);\n    lua_setglobal(lua, preservation_version);\n  }\n  return ver;\n}\n\n\nstatic lsb_err_value\nserialize_table(lsb_lua_sandbox *lsb, serialization_data *data, size_t parent)\n{\n  lsb_err_value ret = NULL;\n  lua_checkstack(lsb->lua, 2);\n  lua_pushnil(lsb->lua);\n  while (!ret && lua_next(lsb->lua, -2) != 0) {\n    ret = serialize_kvp(lsb, data, parent);\n    lua_pop(lsb->lua, 1); // Remove the value leaving the key on top for\n                          // the next interation.\n  }\n  return ret;\n}\n\n\nstatic lsb_err_value\nserialize_data(lsb_lua_sandbox *lsb, int index, lsb_output_buffer *ob)\n{\n  lsb_err_value ret = NULL;\n  ob->pos = 0; // clear the buffer\n  switch (lua_type(lsb->lua, index)) {\n  case LUA_TNUMBER:\n    ret = lsb_serialize_double(ob, lua_tonumber(lsb->lua, index));\n    break;\n  case LUA_TSTRING:\n    // The stack is cleaned up on failure by preserve_global_data\n    // but for clarity it is incrementally cleaned up anyway.\n    lua_checkstack(lsb->lua, 4);\n    lua_getglobal(lsb->lua, LUA_STRLIBNAME);\n    lua_getfield(lsb->lua, -1, \"format\");\n    if (!lua_isfunction(lsb->lua, -1)) {\n      snprintf(lsb->error_message, LSB_ERROR_SIZE,\n               \"serialize_data cannot access the string format function\");\n      lua_pop(lsb->lua, 2); // Remove the bogus format function and\n                            // string table.\n      return LSB_ERR_LUA;\n    }\n    lua_pushstring(lsb->lua, \"%q\");\n    lua_pushvalue(lsb->lua, index - 3);\n    if (lua_pcall(lsb->lua, 2, 1, 0) == 0) {\n      const char* em = lua_tostring(lsb->lua, -1);\n      ret = lsb_outputf(ob, \"%s\", em ? em : LSB_NIL_ERROR);\n      if (ret) {\n        lua_pop(lsb->lua, 1); // Remove the string table.\n        return ret;\n      }\n    } else {\n      int len = snprintf(lsb->error_message, LSB_ERROR_SIZE,\n                         \"serialize_data '%s'\",\n                         lua_tostring(lsb->lua, -1));\n      if (len >= LSB_ERROR_SIZE || len < 0) {\n        lsb->error_message[LSB_ERROR_SIZE - 1] = 0;\n      }\n      lua_pop(lsb->lua, 2); // Remove the error message and the string\n                            // table.\n      return LSB_ERR_LUA;\n    }\n    lua_pop(lsb->lua, 2); // Remove the pcall result and the string table.\n    break;\n  case LUA_TBOOLEAN:\n    ret = lsb_outputf(ob, \"%s\", lua_toboolean(lsb->lua, index) ? \"true\" :\n                                                                 \"false\");\n    break;\n  default:\n    snprintf(lsb->error_message, LSB_ERROR_SIZE,\n             \"serialize_data cannot preserve type '%s'\",\n             lua_typename(lsb->lua, lua_type(lsb->lua, index)));\n    ret = LSB_ERR_LUA;\n  }\n  return ret;\n}\n\n\nstatic lsb_err_value\nserialize_kvp(lsb_lua_sandbox *lsb, serialization_data *data, size_t parent)\n{\n  lsb_err_value ret = NULL;\n  lua_CFunction fp = NULL;\n  int kindex = -2, vindex = -1;\n  if (ignore_value_type(lsb, data, vindex, &fp)) {\n    return ret;\n  }\n  ret = serialize_data(lsb, kindex, &lsb->output);\n  if (ret) {\n    return ret;\n  }\n\n  size_t pos = data->keys.pos;\n  ret = lsb_outputf(&data->keys, \"%s[%s]\", data->keys.buf + parent,\n                    lsb->output.buf);\n  if (ret) return ret;\n\n  if (lua_type(lsb->lua, vindex) == LUA_TTABLE) {\n    const void *ptr = lua_topointer(lsb->lua, vindex);\n    table_ref *seen = find_table_ref(&data->tables, ptr);\n    if (seen == NULL) {\n      seen = add_table_ref(&data->tables, ptr, pos);\n      if (seen != NULL) {\n        data->keys.pos += 1;\n        if (lua_tabletype(lsb->lua, vindex) == LUA_TTARRAY\n            && lua_objlen(lsb->lua, vindex) == 0) {\n            fprintf(data->fh, \"%s = {nil}\\n\", data->keys.buf + pos);\n        } else {\n          fprintf(data->fh, \"%s = {}\\n\", data->keys.buf + pos);\n          ret = serialize_table(lsb, data, pos);\n        }\n      } else {\n        snprintf(lsb->error_message, LSB_ERROR_SIZE,\n                 \"lsb_serialize preserve table out of memory\");\n        return LSB_ERR_UTIL_OOM;\n      }\n    } else {\n      fprintf(data->fh, \"%s = \", data->keys.buf + pos);\n      data->keys.pos = pos;\n      fprintf(data->fh, \"%s\\n\", data->keys.buf + seen->name_pos);\n    }\n  } else if (lua_type(lsb->lua, vindex) == LUA_TUSERDATA) {\n    void *ud = lua_touserdata(lsb->lua, vindex);\n    table_ref *seen = find_table_ref(&data->tables, ud);\n    if (seen == NULL) {\n      seen = add_table_ref(&data->tables, ud, pos);\n      if (seen != NULL) {\n        data->keys.pos += 1;\n        lua_pushlightuserdata(lsb->lua, data->keys.buf + pos);\n        lua_pushlightuserdata(lsb->lua, &lsb->output);\n        lsb->output.pos = 0;\n        int result = fp(lsb->lua);\n        lua_pop(lsb->lua, 2); // remove the key and the output\n        if (!result) {\n          size_t n = fwrite(lsb->output.buf, 1, lsb->output.pos, data->fh);\n          if (n != lsb->output.pos) {\n            snprintf(lsb->error_message, LSB_ERROR_SIZE,\n                     \"lsb_serialize failed %s\", data->keys.buf + pos);\n            return LSB_ERR_LUA;\n          }\n        }\n      } else {\n        snprintf(lsb->error_message, LSB_ERROR_SIZE,\n                 \"lsb_serialize out of memory %s\", data->keys.buf + pos);\n        return LSB_ERR_UTIL_OOM;\n      }\n    } else {\n      fprintf(data->fh, \"%s = \", data->keys.buf + pos);\n      data->keys.pos = pos;\n      fprintf(data->fh, \"%s\\n\", data->keys.buf +\n              seen->name_pos);\n    }\n  } else {\n    fprintf(data->fh, \"%s = \", data->keys.buf + pos);\n    data->keys.pos = pos;\n    ret = serialize_data(lsb, vindex, &lsb->output);\n    if (!ret) {\n      fprintf(data->fh, \"%s\\n\", lsb->output.buf);\n    }\n  }\n  return ret;\n}\n\n\nlsb_err_value preserve_global_data(lsb_lua_sandbox *lsb)\n{\n\n  if (!lsb->lua || !lsb->state_file || lsb->state == LSB_TERMINATED) {\n    return NULL;\n  }\n  lua_sethook(lsb->lua, NULL, 0, 0);\n\n  // make sure the string library is loaded before we start\n  lua_getglobal(lsb->lua, LUA_STRLIBNAME);\n  if (!lua_istable(lsb->lua, -1)) {\n    lua_getglobal(lsb->lua, \"require\");\n    if (!lua_iscfunction(lsb->lua, -1)) {\n      snprintf(lsb->error_message, LSB_ERROR_SIZE,\n               \"preserve_global_data 'require' function not found\");\n      return LSB_ERR_LUA;\n    }\n    lua_pushstring(lsb->lua, LUA_STRLIBNAME);\n    if (lua_pcall(lsb->lua, 1, 1, 0)) {\n      int len = snprintf(lsb->error_message, LSB_ERROR_SIZE,\n                         \"preserve_global_data failed loading 'string'\");\n      if (len >= LSB_ERROR_SIZE || len < 0) {\n        lsb->error_message[LSB_ERROR_SIZE - 1] = 0;\n      }\n      return LSB_ERR_LUA;\n    }\n  }\n  lua_pop(lsb->lua, 1);\n\n  lua_pushvalue(lsb->lua, LUA_GLOBALSINDEX);\n\n  FILE *fh = fopen(lsb->state_file, \"wb\" CLOSE_ON_EXEC);\n  if (fh == NULL) {\n    int len = snprintf(lsb->error_message, LSB_ERROR_SIZE,\n                       \"preserve_global_data could not open: %s\",\n                       lsb->state_file);\n    if (len >= LSB_ERROR_SIZE || len < 0) {\n      lsb->error_message[LSB_ERROR_SIZE - 1] = 0;\n    }\n    return LSB_ERR_LUA;;\n  }\n\n  lsb_err_value ret = NULL;\n  serialization_data data;\n  data.fh = fh;\n\n// Clear the sandbox limits during preservation.\n//  size_t limit = lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT];\n  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = 0;\n//  size_t cur_output_size = lsb->output.size;\n//  size_t max_output_size = lsb->output.maxsize;\n  lsb->output.maxsize = 0;\n// end clear\n\n  data.tables.size = 64;\n  data.tables.pos = 0;\n  data.tables.array = malloc(data.tables.size * sizeof(table_ref));\n  if (data.tables.array == NULL || lsb_init_output_buffer(&data.keys, 0)) {\n    snprintf(lsb->error_message, LSB_ERROR_SIZE,\n             \"preserve_global_data out of memory\");\n    ret = LSB_ERR_UTIL_OOM;\n  } else {\n    fprintf(data.fh, \"if %s and %s ~= %d then return end\\n\",\n            preservation_version,\n            preservation_version,\n            get_preservation_version(lsb->lua));\n    ret = lsb_outputs(&data.keys, \"_G\", 2);\n    if (!ret) {\n      data.keys.pos += 1; // preserve the NUL in this use case\n      data.globals = lua_topointer(lsb->lua, -1);\n      lua_checkstack(lsb->lua, 2);\n      lua_pushnil(lsb->lua);\n      while (!ret && lua_next(lsb->lua, -2) != 0) {\n        ret = serialize_kvp(lsb, &data, 0);\n        lua_pop(lsb->lua, 1);\n      }\n    }\n    lua_pop(lsb->lua, lua_gettop(lsb->lua));\n    // Wipe the entire Lua stack.  Since incremental cleanup on failure\n    // was added the stack should only contain table _G.\n  }\n  free(data.tables.array);\n  lsb_free_output_buffer(&data.keys);\n  fclose(fh);\n  if (ret) remove(lsb->state_file);\n\n// Uncomment if we start preserving state when not destroying the sandbox\n// Note: serialization uses the output buffer, inprogress output can be\n// destroyed if the user was collecting output between calls.\n/*\n// Restore the sandbox limits after preservation\n  lua_gc(lsb->lua, LUA_GCCOLLECT, 0);\n  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = limit;\n  lsb->usage[LSB_UT_MEMORY][LSB_US_MAXIMUM] =\n    lsb->usage[LSB_UT_MEMORY][LSB_US_CURRENT];\n  lsb->output.maxsize = max_output_size;\n  lsb_clear_output_buffer(lsb->output);\n  if (lsb->output.size > cur_output_size) {\n    void* ptr = realloc(lsb->output.data, cur_output_size);\n    if (!ptr) return 1;\n    lsb->output.data = ptr;\n    lsb->output.size = cur_output_size;\n  }\n// end restore\n*/\n  return ret;\n}\n\n\nstatic int file_exists(const char *fn)\n{\n  FILE *fh = fopen(fn, \"r\" CLOSE_ON_EXEC);\n  if (fh) {\n    fclose(fh);\n    return 1;\n  }\n  return 0;\n}\n\n\nlsb_err_value restore_global_data(lsb_lua_sandbox *lsb)\n{\n  if (!lsb) {\n    return LSB_ERR_UTIL_NULL;\n  }\n  if (!lsb->state_file || !file_exists(lsb->state_file)) {\n    return NULL;\n  }\n\n  // Clear the sandbox limits during restoration.\n  size_t limit = lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT];\n  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = 0;\n  lua_sethook(lsb->lua, NULL, 0, 0);\n\n  int err = luaL_dofile(lsb->lua, lsb->state_file);\n  if (err) {\n    if (LUA_ERRFILE != err) {\n      int len = snprintf(lsb->error_message, LSB_ERROR_SIZE,\n                         \"restore_global_data %s\",\n                         lua_tostring(lsb->lua, -1));\n      if (len >= LSB_ERROR_SIZE || len < 0) {\n        lsb->error_message[LSB_ERROR_SIZE - 1] = 0;\n      }\n      lsb_terminate(lsb, NULL);\n      return LSB_ERR_LUA;\n    }\n  }\n  lua_gc(lsb->lua, LUA_GCCOLLECT, 0);\n  lsb->usage[LSB_UT_MEMORY][LSB_US_LIMIT] = limit;\n  lsb->usage[LSB_UT_MEMORY][LSB_US_MAXIMUM] =\n      lsb->usage[LSB_UT_MEMORY][LSB_US_CURRENT];\n  return NULL;\n}\n\n\nvoid lsb_add_serialize_function(lua_State *lua, lua_CFunction fp)\n{\n  lua_pushstring(lua, serialize_function);\n  lua_pushcfunction(lua, fp);\n  lua_rawset(lua, -3);\n}\n\n\nlsb_err_value lsb_serialize_binary(lsb_output_buffer *ob, const void *src, size_t len)\n{\n  lsb_err_value ret = NULL;\n  const char *uc = (const char *)src;\n  for (unsigned i = 0; !ret && i < len; ++i) {\n    switch (uc[i]) {\n    case '\\n':\n      ret = lsb_outputs(ob, \"\\\\n\", 2);\n      break;\n    case '\\r':\n      ret = lsb_outputs(ob, \"\\\\r\", 2);\n      break;\n    case '\"':\n      ret = lsb_outputs(ob, \"\\\\\\\"\", 2);\n      break;\n    case '\\\\':\n      ret = lsb_outputs(ob, \"\\\\\\\\\", 2);\n      break;\n    default:\n      ret = lsb_outputc(ob, uc[i]);\n      break;\n    }\n  }\n  return ret;\n}\n\n\nlsb_err_value lsb_serialize_double(lsb_output_buffer *ob, double d)\n{\n  if (isnan(d)) {\n    return lsb_outputs(ob, \"0/0\", 3);\n  }\n  if (d == INFINITY) {\n    return lsb_outputs(ob, \"1/0\", 3);\n  }\n  if (d == -INFINITY) {\n    return lsb_outputs(ob, \"-1/0\", 4);\n  }\n  return lsb_outputfd(ob, d);\n}\n"
  },
  {
    "path": "src/test/CMakeLists.txt",
    "content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nadd_library(luasandboxtest SHARED sandbox.c)\nset_target_properties(luasandboxtest PROPERTIES VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} SOVERSION 0)\ntarget_compile_definitions(luasandboxtest PRIVATE -Dluasandboxtest_EXPORTS)\ntarget_link_libraries(luasandboxtest luasandbox)\ninstall(TARGETS luasandboxtest DESTINATION ${CMAKE_INSTALL_LIBDIR})\n\nadd_executable(test_generic_sandbox test_generic_sandbox.c)\ntarget_link_libraries(test_generic_sandbox luasandboxtest)\nset(LIBRARY_PATHS \"${CMAKE_BINARY_DIR}/src;${CMAKE_BINARY_DIR}/src/util;${CMAKE_BINARY_DIR}/src/test\")\n\nadd_test(NAME test_move_luasandbox_tests COMMAND cmake -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})\nadd_test(NAME test_generic_sandbox COMMAND test_generic_sandbox)\n\nif(WIN32)\n   STRING(REPLACE \";\" \"\\\\\\\\;\" LIBRARY_PATHS \"${LIBRARY_PATHS}\")\n   set_tests_properties(test_generic_sandbox PROPERTIES ENVIRONMENT PATH=${LIBRARY_PATHS})\nendif()\n\n"
  },
  {
    "path": "src/test/lua/bad_module.lua",
    "content": "return 1 + nilvalue\n"
  },
  {
    "path": "src/test/lua/counter.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\ncount = 0\n\nfunction process(tc)\n    count = count + 1\n    return 0\nend\n"
  },
  {
    "path": "src/test/lua/errors.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\ndata = \"\"\n\nfunction process(tc)\n    if tc == 0 then\n        require(\"unknown\")\n    elseif tc == 1 then\n        output()\n    elseif tc == 2 then\n        for i=1,500 do\n            data = data .. \"012345678901234567890123456789010123456789012345678901234567890123456789012345678901234567890123456789\"\n        end\n    elseif tc == 3 then\n        while true do\n        end\n    elseif tc == 4 then\n        x = x + 1\n    elseif tc == 5 then\n        return nil\n    elseif tc == 6 then\n        return\n    elseif tc == 7 then\n        for i=1,15 do\n            output(\"012345678901234567890123456789010123456789012345678901234567890123456789012345678901234567890123456789\")\n        end\n    elseif tc == 8 then\n        local v = require \"bad_module\"\n    elseif tc == 9 then\n        local v = require \"../invalid\"\n    elseif tc == 10 then\n        local v = require \"pathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflow\"\n    elseif tc == 11 then\n        local v = require \"foo.bar\"\n    end\n    return 0\nend\n"
  },
  {
    "path": "src/test/lua/no_external_modules.lua",
    "content": "require \"foo\"\n\nfunction process(tc)\n    return 0\nend\n\nfunction report()\nend\n"
  },
  {
    "path": "src/test/lua/output.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\n\nfunction process(tc)\n    if tc == 0 then -- lua types\n        write_output(1.2, \" string \", nil, \" \", true, \" \", false)\n    elseif tc == 1 then -- user data\n        require \"ud\"\n        local udv = ud.new(\"foo\")\n        write_output(udv)\n    end\n    return 0\nend\n"
  },
  {
    "path": "src/test/lua/output_errors.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nrequire \"io\"\n\n\nfunction process(tc)\n    if tc == 0 then -- error internal reference\n        output({})\n    elseif tc == 1 then -- error escape overflow\n        local escape = \"\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\"\n        for i=1, 10 do\n            escape = escape .. escape\n        end\n        output(escape)\n    elseif tc == 2 then -- unsupported userdata\n        write_output(io.stdin)\n    end\n    return 0\nend\n"
  },
  {
    "path": "src/test/lua/print.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nfunction process(tc)\n    if tc == 0 then\n        print()\n    elseif tc == 1 then\n        print(\"foo\\n\", 10, true)\n    elseif tc == 2 then\n        print(\"f\\r\\0\", 10, true)\n    elseif tc == 3 then\n        tostring = nil\n        local ok, err = pcall(print, \"foo\")\n        assert(not ok)\n        assert(err == \"attempt to call a nil value\", err)\n    end\n    return 0\nend\n"
  },
  {
    "path": "src/test/lua/read_config.lua",
    "content": "assert(type(read_config) == \"function\")\nassert(read_config(\"memory_limit\") == 65765)\nassert(read_config(\"instruction_limit\") == 1000)\nassert(read_config(\"output_limit\") == 1024)\nassert(read_config(\"input_limit\") == 1024 * 64)\n\nlocal array = read_config(\"array\")\nassert(type(array) ==  \"table\")\nassert(array[1] == \"foo\")\nassert(array[2] == 99)\n\nlocal hash = read_config(\"hash\")\nassert(type(hash) == \"table\")\nassert(hash.foo == \"bar\")\nassert(hash.hash1.subfoo == \"subbar\")\n\nassert(type(read_config(\"path\")) == \"string\")\nassert(type(read_config(\"cpath\")) == \"string\")\n"
  },
  {
    "path": "src/test/lua/restore.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n_PRESERVATION_VERSION = 1\n\ncount = 100\n\nfunction process()\n    count = count + 1\n    write_output(count)\n    return 0\nend\n\n\nfunction report(ns)\n    _PRESERVATION_VERSION = ns\nend\n\n\n"
  },
  {
    "path": "src/test/lua/sandbox_config.lua",
    "content": "local ok, err = pcall(require, \"io\")\nassert(not ok, \"the io module is disabled\")\nassert(err == \"module 'io' disabled\", err)\n\nrequire \"math\"\nrequire \"os\"\nrequire \"string\"\nrequire \"table\"\n\nlocal function all_there(test)\n    for k, v in pairs(test.values) do\n        assert(test.t[k], string.format(\"missing: %s.%s\", test.name, k))\n    end\nend\n\nlocal function nothing_extra(test)\n    for k, v in pairs(test.t) do\n        assert(test.values[k], string.format(\"extra: %s.%s\", test.name, k))\n    end\nend\n\nlocal tests = {\n    {name = \"base\", t = _G, values = {\n        _G=1,\n        _VERSION=1,\n        assert=1,\n        error=1,\n        gcinfo=1,\n        getfenv=1,\n        getmetatable=1,\n        ipairs=1,\n        read_config=1,\n        math=1,\n        module=1,\n        next=1,\n        os=1,\n        output=1,\n        package=1,\n        pairs=1,\n        pcall=1,\n        print=1,\n        rawequal=1,\n        rawget=1,\n        rawset=1,\n        require=1,\n        select=1,\n        setfenv=1,\n        setmetatable=1,\n        string=1,\n        table=1,\n        tonumber=1,\n        tostring=1,\n        type=1,\n        unpack=1,\n        xpcall=1,\n        }\n    },\n\n    {name = \"math\", t = math, values = {\n        abs=1,\n        acos=1,\n        asin=1,\n        atan2=1,\n        atan=1,\n        ceil=1,\n        cos=1,\n        cosh=1,\n        deg=1,\n        erf=1,\n        erfc=1,\n        exp=1,\n        floor=1,\n        fmod=1,\n        frexp=1,\n        huge=1,\n        ldexp=1,\n        log10=1,\n        log=1,\n        max=1,\n        min=1,\n        mod=1, -- compat\n        modf=1,\n        pi=1,\n        pow=1,\n        rad=1,\n        random=1,\n        randomseed=1,\n        sin=1,\n        sinh=1,\n        sqrt=1,\n        tan=1,\n        tanh=1,\n        }\n    },\n\n    {name = \"os\", t = os, values = {\n        clock=1,\n        date=1,\n        difftime=1,\n        time=1,\n        }\n    },\n\n    {name = \"package\", t = package, values = {\n        seeall=1,\n        }\n    },\n\n    {name = \"string\", t = string, values = {\n        byte=1,\n        char=1,\n        dump=1,\n        find=1,\n        format=1,\n        gfind=1, -- compat\n        gmatch=1,\n        gsub=1,\n        len=1,\n        lower=1,\n        match=1,\n        rep=1,\n        reverse=1,\n        sub=1,\n        upper=1,\n        }\n    },\n\n    {name = \"table\", t = table, values = {\n        concat=1,\n        foreach=1,\n        foreachi=1,\n        getn=1,\n        insert=1,\n        maxn=1,\n        remove=1,\n        setn=1,\n        sort=1,\n        }\n    },\n}\n\nfor i, v in ipairs(tests) do\n    all_there(v)\n    nothing_extra(v)\nend\n"
  },
  {
    "path": "src/test/lua/serialize.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nrequire \"ud\"\n\ncount = 0\nrate = 0.12345678\nrates = {99.1,98,97,92.002,91.10001,key=\"val\"}\nkvp = {a=\"foo\", b=\"bar\", r=rates}\nnested = {arg1=1, arg2=2, nested={n1=\"one\",n2=\"two\"}, empty = nil, ud = ud.new(\"ud1\")}\n_G[\"key with spaces\"] = \"kws\"\nboolean = true\nempty = nil\nfunc = function (s) return s end\nuuids = {\n    {uuid=\"BD48B609-8922-4E59-A358-C242075CE088\", type=\"test\"},\n    {uuid=\"BD48B609-8922-4E59-A358-C242075CE089\", type=\"test1\"}\n}\nnan = 0/0\ninf = 1/0\nninf = -1/0\n\nlarge_key = {\n    aaaaaaaaaaaaaaaaaaa = {[\"BD48B609-8922-4E59-A358-C242075CE081\"] = 1,\n    bbbbbbbbbbbbbbbbbbb = {[\"BD48B609-8922-4E59-A358-C242075CE082\"] = 2,\n    ccccccccccccccccccc = {[\"BD48B609-8922-4E59-A358-C242075CE083\"] = 3,\n    ddddddddddddddddddd = {[\"BD48B609-8922-4E59-A358-C242075CE084\"] = 4,\n    eeeeeeeeeeeeeeeeeee = {[\"BD48B609-8922-4E59-A358-C242075CE085\"] = 5,\n    fffffffffffffffffff = {[\"BD48B609-8922-4E59-A358-C242075CE086\"] = 6,\n    ggggggggggggggggggg = {[\"BD48B609-8922-4E59-A358-C242075CE087\"] = 7,\n    hhhhhhhhhhhhhhhhhhh = {[\"BD48B609-8922-4E59-A358-C242075CE088\"] = 8,\n    iiiiiiiiiiiiiiiiiii = {[\"BD48B609-8922-4E59-A358-C242075CE089\"] = 9,}}}}}}}}}\n}\n\ncyclea = {type=\"cycle a\"}\ncycleb = {type=\"cycle b\"}\ncyclea[\"b\"] = cycleb\ncycleb[\"a\"] = cyclea\n\ndata = ud.new(\"ud2\")\n\ndataRef = data\n\nempty_array = {nil}\nempty_array1 = {}\nempty_array1[1] = nil\nempty_object = {}\nempty_object1 = {[1] = nil}\narray = {1, \"two\", 3, \"four\", 5}\n\nfunction process_message ()\n    return 0\nend\n\n\nfunction timer_event(ns)\nend\n\n"
  },
  {
    "path": "src/test/lua/serialize_failure.lua",
    "content": "-- This Source Code Form is subject to the terms of the Mozilla Public\n-- License, v. 2.0. If a copy of the MPL was not distributed with this\n-- file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nt = { [function(x) print(x) end] = \"foo\" }\n"
  },
  {
    "path": "src/test/lua/simple.lua",
    "content": "gint = 1\n\nfunction process(tc)\n    if tc == 1 then\n        return 0, \"ok\"\n    elseif tc == 2  then\n        return 0, true\n    end\n    return 0\nend\n\nfunction report()\nend\n"
  },
  {
    "path": "src/test/output/serialize.lua51.data",
    "content": "if _PRESERVATION_VERSION and _PRESERVATION_VERSION ~= 0 then return end\n_G[\"ninf\"] = -1/0\n_G[\"empty_object1\"] = {}\nif _G[\"dataRef\"] == nil then _G[\"dataRef\"] = ud.new('ud2') end\n_G[\"array\"] = {}\n_G[\"array\"][1] = 1\n_G[\"array\"][2] = \"two\"\n_G[\"array\"][3] = 3\n_G[\"array\"][4] = \"four\"\n_G[\"array\"][5] = 5\n_G[\"empty_object\"] = {}\n_G[\"rate\"] = 0.12345678\n_G[\"kvp\"] = {}\n_G[\"kvp\"][\"a\"] = \"foo\"\n_G[\"kvp\"][\"r\"] = {}\n_G[\"kvp\"][\"r\"][1] = 99.1\n_G[\"kvp\"][\"r\"][2] = 98\n_G[\"kvp\"][\"r\"][3] = 97\n_G[\"kvp\"][\"r\"][4] = 92.002\n_G[\"kvp\"][\"r\"][5] = 91.10001\n_G[\"kvp\"][\"r\"][\"key\"] = \"val\"\n_G[\"kvp\"][\"b\"] = \"bar\"\n_G[\"key with spaces\"] = \"kws\"\n_G[\"uuids\"] = {}\n_G[\"uuids\"][1] = {}\n_G[\"uuids\"][1][\"type\"] = \"test\"\n_G[\"uuids\"][1][\"uuid\"] = \"BD48B609-8922-4E59-A358-C242075CE088\"\n_G[\"uuids\"][2] = {}\n_G[\"uuids\"][2][\"type\"] = \"test1\"\n_G[\"uuids\"][2][\"uuid\"] = \"BD48B609-8922-4E59-A358-C242075CE089\"\n_G[\"inf\"] = 1/0\n_G[\"empty_array\"] = {nil}\n_G[\"data\"] = _G[\"dataRef\"]\n_G[\"cycleb\"] = {}\n_G[\"cycleb\"][\"a\"] = {}\n_G[\"cycleb\"][\"a\"][\"b\"] = _G[\"cycleb\"]\n_G[\"cycleb\"][\"a\"][\"type\"] = \"cycle a\"\n_G[\"cycleb\"][\"type\"] = \"cycle b\"\n_G[\"cyclea\"] = _G[\"cycleb\"][\"a\"]\n_G[\"large_key\"] = {}\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"] = {}\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"] = {}\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"] = {}\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"BD48B609-8922-4E59-A358-C242075CE083\"] = 3\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"ddddddddddddddddddd\"] = {}\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"ddddddddddddddddddd\"][\"BD48B609-8922-4E59-A358-C242075CE084\"] = 4\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"ddddddddddddddddddd\"][\"eeeeeeeeeeeeeeeeeee\"] = {}\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"ddddddddddddddddddd\"][\"eeeeeeeeeeeeeeeeeee\"][\"BD48B609-8922-4E59-A358-C242075CE085\"] = 5\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"ddddddddddddddddddd\"][\"eeeeeeeeeeeeeeeeeee\"][\"fffffffffffffffffff\"] = {}\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"ddddddddddddddddddd\"][\"eeeeeeeeeeeeeeeeeee\"][\"fffffffffffffffffff\"][\"ggggggggggggggggggg\"] = {}\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"ddddddddddddddddddd\"][\"eeeeeeeeeeeeeeeeeee\"][\"fffffffffffffffffff\"][\"ggggggggggggggggggg\"][\"BD48B609-8922-4E59-A358-C242075CE087\"] = 7\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"ddddddddddddddddddd\"][\"eeeeeeeeeeeeeeeeeee\"][\"fffffffffffffffffff\"][\"ggggggggggggggggggg\"][\"hhhhhhhhhhhhhhhhhhh\"] = {}\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"ddddddddddddddddddd\"][\"eeeeeeeeeeeeeeeeeee\"][\"fffffffffffffffffff\"][\"ggggggggggggggggggg\"][\"hhhhhhhhhhhhhhhhhhh\"][\"BD48B609-8922-4E59-A358-C242075CE088\"] = 8\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"ddddddddddddddddddd\"][\"eeeeeeeeeeeeeeeeeee\"][\"fffffffffffffffffff\"][\"ggggggggggggggggggg\"][\"hhhhhhhhhhhhhhhhhhh\"][\"iiiiiiiiiiiiiiiiiii\"] = {}\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"ddddddddddddddddddd\"][\"eeeeeeeeeeeeeeeeeee\"][\"fffffffffffffffffff\"][\"ggggggggggggggggggg\"][\"hhhhhhhhhhhhhhhhhhh\"][\"iiiiiiiiiiiiiiiiiii\"][\"BD48B609-8922-4E59-A358-C242075CE089\"] = 9\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"ccccccccccccccccccc\"][\"ddddddddddddddddddd\"][\"eeeeeeeeeeeeeeeeeee\"][\"fffffffffffffffffff\"][\"BD48B609-8922-4E59-A358-C242075CE086\"] = 6\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"bbbbbbbbbbbbbbbbbbb\"][\"BD48B609-8922-4E59-A358-C242075CE082\"] = 2\n_G[\"large_key\"][\"aaaaaaaaaaaaaaaaaaa\"][\"BD48B609-8922-4E59-A358-C242075CE081\"] = 1\n_G[\"count\"] = 0\n_G[\"boolean\"] = true\n_G[\"empty_array1\"] = {nil}\n_G[\"nested\"] = {}\n_G[\"nested\"][\"arg2\"] = 2\n_G[\"nested\"][\"nested\"] = {}\n_G[\"nested\"][\"nested\"][\"n2\"] = \"two\"\n_G[\"nested\"][\"nested\"][\"n1\"] = \"one\"\n_G[\"nested\"][\"arg1\"] = 1\nif _G[\"nested\"][\"ud\"] == nil then _G[\"nested\"][\"ud\"] = ud.new('ud1') end\n_G[\"rates\"] = _G[\"kvp\"][\"r\"]\n_G[\"_VERSION\"] = \"Lua 5.1\"\n_G[\"nan\"] = 0/0\n"
  },
  {
    "path": "src/test/sandbox.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Implementation of the test interface for the generic lua sandbox @file */\n\n#include \"luasandbox/test/sandbox.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n#include \"luasandbox.h\"\n#include \"luasandbox/lauxlib.h\"\n#include \"luasandbox/lua.h\"\n#include \"luasandbox_output.h\"\n#include \"../luasandbox_defines.h\"\n\nconst char *lsb_test_output = NULL;\nsize_t lsb_test_output_len = 0;\n\nstatic void logger(void *context,\n                   const char *component,\n                   int level,\n                   const char *fmt,\n                   ...)\n{\n  (void)context;\n  va_list args;\n  fprintf(stderr, \"%lld [%d] %s \", (long long)time(NULL), level,\n          component ? component : \"unnamed\");\n  va_start(args, fmt);\n  vfprintf(stderr, fmt, args);\n  va_end(args);\n  fwrite(\"\\n\", 1, 1, stderr);\n}\nlsb_logger lsb_test_logger = { .context = NULL, .cb = logger };\n\n\nint lsb_test_write_output(lua_State *lua)\n{\n  lua_getfield(lua, LUA_REGISTRYINDEX, LSB_THIS_PTR);\n  lsb_lua_sandbox *lsb = lua_touserdata(lua, -1);\n  lua_pop(lua, 1); // remove this ptr\n  if (!lsb) return luaL_error(lua, \"%s() invalid \" LSB_THIS_PTR, __func__);\n\n  int n = lua_gettop(lua);\n  lsb_output(lsb, 1, n, 1);\n  lsb_test_output = lsb_get_output(lsb, &lsb_test_output_len);\n  return 0;\n}\n\n\nint lsb_test_process(lsb_lua_sandbox *lsb, double tc)\n{\n  static const char *func_name = \"process\";\n  lua_State *lua = lsb_get_lua(lsb);\n  if (!lua) return 1;\n\n  if (lsb_pcall_setup(lsb, func_name)) return 1;\n\n  lua_pushnumber(lua, tc);\n  if (lua_pcall(lua, 1, 2, 0) != 0) {\n    char err[LSB_ERROR_SIZE];\n    const char *em = lua_tostring(lua, -1);\n    int len = snprintf(err, LSB_ERROR_SIZE, \"%s() %s\", func_name,\n                       em ? em : LSB_NIL_ERROR);\n    if (len >= LSB_ERROR_SIZE || len < 0) {\n      err[LSB_ERROR_SIZE - 1] = 0;\n    }\n    lsb_terminate(lsb, err);\n    return 1;\n  }\n\n  if (!lua_isnumber(lua, 1)) {\n    char err[LSB_ERROR_SIZE];\n    int len = snprintf(err, LSB_ERROR_SIZE,\n                       \"%s() must return a numeric error code\", func_name);\n    if (len >= LSB_ERROR_SIZE || len < 0) {\n      err[LSB_ERROR_SIZE - 1] = 0;\n    }\n    lsb_terminate(lsb, err);\n    return 1;\n  }\n\n  int status = (int)lua_tointeger(lua, 1);\n  switch (lua_type(lua, 2)) {\n  case LUA_TNIL:\n    lsb_set_error(lsb, NULL);\n    break;\n  case LUA_TSTRING:\n    lsb_set_error(lsb, lua_tostring(lua, 2));\n    break;\n  default:\n    {\n      char err[LSB_ERROR_SIZE];\n      int len = snprintf(err, LSB_ERROR_SIZE,\n                         \"%s() must return a nil or string error message\",\n                         func_name);\n      if (len >= LSB_ERROR_SIZE || len < 0) {\n        err[LSB_ERROR_SIZE - 1] = 0;\n      }\n      lsb_terminate(lsb, err);\n      return 1;\n    }\n    break;\n  }\n  lua_pop(lua, 2);\n\n  lsb_pcall_teardown(lsb);\n\n  return status;\n}\n\n\nint lsb_test_report(lsb_lua_sandbox *lsb, double tc)\n{\n  static const char *func_name = \"report\";\n  lua_State *lua = lsb_get_lua(lsb);\n  if (!lua) return 1;\n\n  if (lsb_pcall_setup(lsb, func_name)) return 1;\n\n  lua_pushnumber(lua, tc);\n  if (lua_pcall(lua, 1, 0, 0) != 0) {\n    char err[LSB_ERROR_SIZE];\n    const char *em = lua_tostring(lua, -1);\n    int len = snprintf(err, LSB_ERROR_SIZE, \"%s() %s\", func_name,\n                       em ? em : LSB_NIL_ERROR);\n    if (len >= LSB_ERROR_SIZE || len < 0) {\n      err[LSB_ERROR_SIZE - 1] = 0;\n    }\n    lsb_terminate(lsb, err);\n    return 1;\n  }\n\n  lsb_pcall_teardown(lsb);\n  lua_gc(lua, LUA_GCCOLLECT, 0);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/test_generic_sandbox.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Lua sandbox unit tests @file */\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include \"../luasandbox_impl.h\"\n#include \"luasandbox/lauxlib.h\"\n#include \"luasandbox/lua.h\"\n#include \"luasandbox/test/mu_test.h\"\n#include \"luasandbox/test/sandbox.h\"\n#include \"luasandbox/util/util.h\"\n#include \"luasandbox_output.h\"\n#include \"luasandbox_serialize.h\"\n\nchar *e = NULL;\nstatic char print_out[2048] = { 0 };\n\n\n#ifdef _WIN32\n#define MODULE_PATH \"path = 'modules\\\\\\\\?.lua';cpath = 'modules\\\\\\\\?.dll'\\n\"\n#else\n#define MODULE_PATH \"path = 'modules/?.lua';cpath = 'modules/?.so'\\n\"\n#endif\n\nstatic const char *mozsvc_test_ud = \"mozsvc.test_ud\";\n\ntypedef struct test_ud {\n  char name[10];\n} test_ud;\n\n\nstatic int ud_new(lua_State *lua)\n{\n  size_t len;\n  const char *name = luaL_checklstring(lua, 1, &len);\n  test_ud *ud = lua_newuserdata(lua, sizeof(test_ud));\n  if (len < 10) {\n    strcpy(ud->name, name);\n  } else {\n    memcpy(ud->name, name, 9);\n    ud->name[9] = 0;\n  }\n  luaL_getmetatable(lua, mozsvc_test_ud);\n  lua_setmetatable(lua, -2);\n  return 1;\n}\n\n\nstatic int ud_serialize(lua_State *lua)\n{\n  lsb_output_buffer *ob = lua_touserdata(lua, -1);\n  const char *key = lua_touserdata(lua, -2);\n  test_ud *ud = lua_touserdata(lua, -3);\n  if (!(ob && key && ud)) {return 1;}\n  return lsb_outputf(ob, \"if %s == nil then %s = ud.new('%s') end\\n\", key, key,\n                     ud->name) == NULL ? 0 : 1;\n}\n\n\nstatic int ud_output(lua_State *lua)\n{\n  lsb_output_buffer *ob = lua_touserdata(lua, -1);\n  test_ud *ud = lua_touserdata(lua, -2);\n  if (!(ob && ud)) {return 1; }\n  return lsb_outputf(ob, \"%s\", ud->name) == NULL ? 0 : 1;\n}\n\n\nstatic const struct luaL_reg testudlib_f[] =\n{\n  { \"new\", ud_new }, { NULL, NULL }\n};\n\n\nstatic int luaopen_ud(lua_State *lua)\n{\n  lua_newtable(lua);\n  lsb_add_serialize_function(lua, ud_serialize);\n  lsb_add_output_function(lua, ud_output);\n  lua_replace(lua, LUA_ENVIRONINDEX);\n  luaL_newmetatable(lua, mozsvc_test_ud);\n  luaL_register(lua, \"ud\", testudlib_f);\n  return 1;\n}\n\n\nstatic void add_ud_module(lsb_lua_sandbox *sb)\n{\n  lua_State *lua = lsb_get_lua(sb);\n  luaL_findtable(lua, LUA_REGISTRYINDEX, \"_PRELOADED\", 1);\n  lua_pushstring(lua, \"ud\");\n  lua_pushcfunction(lua, luaopen_ud);\n  lua_rawset(lua, -3);\n  lua_pop(lua, 1); // remove the preloaded table\n}\n\n\nstatic const char *test_cfg =\n    \"userflag = true\\n\"\n    \"memory_limit = 0\\n\"\n    \"instruction_limit = 0\\n\"\n    \"output_limit = 0\\n\"\n    \"remove_entries = {\\n\"\n    \"[''] = {'collectgarbage','dofile','load','loadfile','loadstring',\"\n    \"'newproxy','print'},\\n\"\n    \"os = {'getenv','execute','exit','remove','rename','setlocale','tmpname'}\\n\"\n    \"}\\n\"\n    \"disable_modules = {io = 1, coroutine = 1}\\n\"\n    \"log_level = 7\\n\"\n    MODULE_PATH\n;\n\n\nint file_exists(const char *fn)\n{\n  FILE *fh;\n  fh = fopen(fn, \"r\");\n  if (fh) {\n    fclose(fh);\n    return 1;\n  }\n  return 0;\n}\n\n\nvoid print(void *context, const char *component, int level, const char *fmt, ...)\n{\n  (void)context;\n  va_list args;\n  int n = snprintf(print_out, sizeof print_out, \"%d %s \", level,\n                   component ? component : \"unnamed\");\n  va_start(args, fmt);\n  n = vsnprintf(print_out + n, sizeof print_out - n, fmt, args);\n  va_end(args);\n}\nstatic lsb_logger printer = { .context = NULL, .cb = print };\n\n\nstatic char* test_api_assertion()\n{\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/counter.lua\", \"\", NULL);\n  lsb_err_value ret = lsb_init(sb, NULL);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n\n  lsb_stop_sandbox(NULL);\n  mu_assert(lsb_destroy(NULL) == NULL, \"not null\");\n  mu_assert(lsb_usage(NULL, 0, 0) == 0, \"not 0\");\n  mu_assert(lsb_usage(sb, LSB_UT_MAX, 0) == 0, \"not 0\");\n  mu_assert(lsb_usage(sb, 0, LSB_US_MAX) == 0, \"not 0\");\n  mu_assert(strcmp(lsb_get_error(NULL), \"\") == 0, \"not empty\");\n  lsb_set_error(NULL, \"foo\");\n  mu_assert(lsb_get_lua(NULL) == NULL, \"not null\");\n  mu_assert(lsb_get_lua_file(NULL) == NULL, \"not null\");\n  mu_assert(lsb_get_parent(NULL) == NULL, \"not null\");\n  mu_assert(lsb_get_logger(NULL) == NULL, \"not null\");\n  mu_assert(lsb_get_state(NULL) == LSB_UNKNOWN, \"not unknown\");\n  lsb_add_function(NULL, lsb_test_write_output, \"foo\");\n  lsb_add_function(sb, NULL, \"foo\");\n  lsb_add_function(sb, lsb_test_write_output, NULL);\n  mu_assert(lsb_pcall_setup(NULL, \"foo\") == LSB_ERR_UTIL_NULL, \"not null\");\n  mu_assert(lsb_pcall_setup(sb, NULL) == LSB_ERR_UTIL_NULL, \"not null\");\n  lsb_add_function(NULL, NULL, NULL);\n  lsb_pcall_teardown(NULL);\n  lsb_terminate(NULL, NULL);\n  lsb_terminate(sb, NULL);\n  lsb_add_function(sb, lsb_test_write_output, \"write_output\");\n\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n  return NULL;\n}\n\n\nstatic char* test_create()\n{\n  static char *cfg = \"function foo() return 0 end\\nt = {[true] = 1}\\n\";\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/counter.lua\", cfg, &lsb_test_logger);\n  mu_assert(sb, \"lsb_create() failed\");\n  lsb_destroy(sb);\n  sb = lsb_create(NULL, \"lua/counter.lua\", cfg, NULL);\n  mu_assert(sb, \"lsb_create() failed\");\n  lsb_destroy(sb);\n  sb = lsb_create(NULL, \"lua/counter.lua\", \"memory_limit = 3e9\", NULL);\n  mu_assert(sb, \"lsb_create() failed\");\n  lsb_destroy(sb);\n  return NULL;\n}\n\n\nstatic char* test_create_error()\n{\n  lsb_lua_sandbox *sb = lsb_create(NULL, NULL, NULL, NULL);\n  mu_assert(!sb, \"lsb_create() null lua_file\");\n\n  sb = lsb_create(NULL, \"lua/counter.lua\", \"input_limit = 'aaa'\", NULL);\n  mu_assert(!sb, \"lsb_create() invalid config\");\n\n  sb = lsb_create(NULL, \"lua/counter.lua\", \"output_limit = 'aaa'\", NULL);\n  mu_assert(!sb, \"lsb_create() invalid config\");\n\n  sb = lsb_create(NULL, \"lua/counter.lua\", \"memory_limit = 'aaa'\", NULL);\n  mu_assert(!sb, \"lsb_create() invalid config\");\n\n  sb = lsb_create(NULL, \"lua/counter.lua\", \"memory_limit = -1\", NULL);\n  mu_assert(!sb, \"lsb_create() invalid config\");\n\n  sb = lsb_create(NULL, \"lua/counter.lua\", \"memory_limit = 1.85e19\", NULL);\n  mu_assert(!sb, \"lsb_create() invalid config\");\n\n  sb = lsb_create(NULL, \"lua/counter.lua\", \"instruction_limit = 'aaa'\", NULL);\n  mu_assert(!sb, \"lsb_create() invalid config\");\n\n  sb = lsb_create(NULL, \"lua/counter.lua\", \"path = 1\", NULL);\n  mu_assert(!sb, \"lsb_create() invalid config\");\n\n  sb = lsb_create(NULL, \"lua/counter.lua\", \"cpath = 1\", NULL);\n  mu_assert(!sb, \"lsb_create() invalid config\");\n\n  sb = lsb_create(NULL, \"lua/counter.lua\", \"test = {\", &lsb_test_logger);\n  mu_assert(!sb, \"lsb_create() invalid config\");\n\n  return NULL;\n}\n\n\nstatic char* test_read_config()\n{\n  const char *cfg = \"memory_limit = 65765\\n\"\n      \"instruction_limit = 1000\\n\"\n      \"output_limit = 1024\\n\"\n      \"array = {'foo', 99}\\n\"\n      \"hash  = {foo = 'bar', hash1 = {subfoo = 'subbar'}}\\n\"\n      MODULE_PATH;\n\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/read_config.lua\", cfg, NULL);\n  lsb_err_value ret = lsb_init(sb, NULL);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  return NULL;\n}\n\n\nstatic char* test_init_error()\n{\n  // null sandbox\n  lsb_err_value ret = lsb_init(NULL, NULL);\n  mu_assert(ret == LSB_ERR_UTIL_NULL, \"lsb_init() null sandbox ptr\");\n\n  // load error\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/simple1.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  ret = lsb_init(sb, NULL);\n  mu_assert(ret == LSB_ERR_LUA, \"lsb_init() received: %s\", lsb_err_string(ret));\n  lsb_state s = lsb_get_state(sb);\n  mu_assert(s == LSB_TERMINATED, \"lsb_get_state() received: %d\", s);\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  // out of memory\n  sb = lsb_create(NULL, \"lua/simple.lua\", \"memory_limit = 6000\", NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  ret = lsb_init(sb, NULL);\n  mu_assert(ret == LSB_ERR_LUA, \"lsb_init() received: %s\", lsb_err_string(ret));\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\\n\", e);\n\n  sb = lsb_create(NULL, \"lua/no_external_modules.lua\", NULL, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n\n  // disabled external modules\n  ret = lsb_init(sb, NULL);\n  mu_assert(ret == LSB_ERR_LUA, \"lsb_init() received: %s\", lsb_err_string(ret));\n  const char *expected = \"no 'path' configuration was specified for the \"\n      \"sandbox; external modules have been disabled\";\n  mu_assert(strcmp(lsb_get_error(sb), expected) == 0,\n            \"lsb_get_error() received: %s\", lsb_get_error(sb));\n\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  return NULL;\n}\n\n\nstatic char* test_destroy_error()\n{\n  const char *expected = \"preserve_global_data could not open: \"\n      \"invaliddir/simple.preserve\";\n  e = lsb_destroy(NULL);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/simple.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  lsb_err_value ret = lsb_init(sb, \"invaliddir/simple.preserve\");\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n  e = lsb_destroy(sb);\n  mu_assert(e, \"lsb_destroy() received NULL\");\n  mu_assert(strcmp(e, expected) == 0,\n            \"lsb_destroy() received: %s\", e);\n  free(e);\n  e = NULL;\n\n  return NULL;\n}\n\n\nstatic char* test_usage_error()\n{\n  size_t u = lsb_usage(NULL, LSB_UT_MEMORY, LSB_US_CURRENT);\n  mu_assert(u == 0, \"NULL sandbox memory usage received: %\" PRIuSIZE, u);\n\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/simple.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n\n  u = lsb_usage(NULL, LSB_UT_MAX + 1, LSB_US_CURRENT);\n  mu_assert(u == 0, \"Invalid usage type received: %\" PRIuSIZE, u);\n\n  u = lsb_usage(NULL, LSB_UT_MEMORY, LSB_US_MAX + 1);\n  mu_assert(u == 0, \"Invalid usage stat received: %\" PRIuSIZE, u);\n\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  lsb_terminate(sb, \"forced termination\");\n  lsb_state s = lsb_get_state(sb);\n  mu_assert(s == LSB_TERMINATED, \"lsb_get_state() received: %d\", s);\n  u = lsb_usage(sb, LSB_UT_MEMORY, LSB_US_CURRENT);\n  mu_assert(u > 0, \"Terminated memory usage received: 0\");\n\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  return NULL;\n}\n\n\nstatic char* test_stop()\n{\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/counter.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  lsb_err_value ret = lsb_init(sb, NULL);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n  lsb_stop_sandbox(sb);\n  lua_getglobal(lsb_get_lua(sb), \"process\");\n  lua_pushnumber(lsb_get_lua(sb), 0);\n  mu_assert_rv(2, lua_pcall(lsb_get_lua(sb), 1, 2, 0));\n  const char *msg = lua_tostring(lsb_get_lua(sb), -1);\n  mu_assert(strcmp(LSB_SHUTTING_DOWN, msg) == 0, \"received: %s\", msg);\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n  return NULL;\n}\n\n\nstatic char* test_simple()\n{\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/simple.lua\",\n                                   \"memory_limit = 65765;\"\n                                   \"instruction_limit = 1000;\"\n                                   \"output_limit = 1024;\", NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n\n  lsb_err_value ret = lsb_init(sb, \"simple.preserve\");\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n\n  size_t u = lsb_usage(sb, LSB_UT_MEMORY, LSB_US_CURRENT);\n  mu_assert(u > 0, \"Current memory usage received: %\" PRIuSIZE, u);\n  printf(\"cur_mem %\" PRIuSIZE \"\\n\", u);\n\n  u = lsb_usage(sb, LSB_UT_MEMORY, LSB_US_MAXIMUM);\n  mu_assert(u > 0, \"Maximum memory usage received: %\" PRIuSIZE, u);\n  printf(\"max_mem %\" PRIuSIZE \"\\n\", u);\n\n  u = lsb_usage(sb, LSB_UT_MEMORY, LSB_US_LIMIT);\n  mu_assert(u == 65765, \"Memory limit received: %\" PRIuSIZE, u);\n\n  u = lsb_usage(sb, LSB_UT_INSTRUCTION, LSB_US_CURRENT);\n  mu_assert(u == 7, \"Current instructions received: %\" PRIuSIZE, u);\n\n  u = lsb_usage(sb, LSB_UT_INSTRUCTION, LSB_US_MAXIMUM);\n  mu_assert(u == 7, \"Maximum instructions received: %\" PRIuSIZE, u);\n  printf(\"max_ins %\" PRIuSIZE \"\\n\", u);\n\n  u = lsb_usage(sb, LSB_UT_INSTRUCTION, LSB_US_LIMIT);\n  mu_assert(u == 1000, \"Instruction limit received: %\" PRIuSIZE, u);\n\n  u = lsb_usage(sb, LSB_UT_OUTPUT, LSB_US_CURRENT);\n  mu_assert(u == 0, \"Current output received: %\" PRIuSIZE, u);\n\n  u = lsb_usage(sb, LSB_UT_OUTPUT, LSB_US_MAXIMUM);\n  mu_assert(u == 0, \"Maximum output received: %\" PRIuSIZE, u);\n  printf(\"max_out %\" PRIuSIZE \"\\n\", u);\n\n  u = lsb_usage(sb, LSB_UT_OUTPUT, LSB_US_LIMIT);\n  mu_assert(u == 1024, \"Output limit received: %\" PRIuSIZE, u);\n\n  u = lsb_usage(sb, LSB_UT_OUTPUT, LSB_US_LIMIT);\n  mu_assert(u == 1024, \"Output limit received: %\" PRIuSIZE, u);\n\n  lsb_state s = lsb_get_state(sb);\n  mu_assert(s == LSB_RUNNING, \"lsb_get_state() received: %d\", s);\n\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  return NULL;\n}\n\n\n\nstatic char* test_simple_error()\n{\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/simple.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n\n  lsb_err_value ret = lsb_init(sb, NULL);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n\n  int result = lsb_test_process(sb, 1);\n  mu_assert(result == 0, \"process() received: %d %s\", result,\n            lsb_get_error(sb));\n\n  mu_assert(strcmp(\"ok\", lsb_get_error(sb)) == 0, \"process() received: %d %s\", result,\n            lsb_get_error(sb));\n\n  result = lsb_test_process(sb, 0);\n  mu_assert(result == 0, \"process() received: %d %s\", result,\n            lsb_get_error(sb));\n\n  mu_assert(strcmp(\"\", lsb_get_error(sb)) == 0, \"process() received: %d %s\", result,\n            lsb_get_error(sb));\n\n  result = lsb_test_process(sb, 2);\n  mu_assert(result == 1, \"process() received: %d %s\", result,\n            lsb_get_error(sb));\n\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  return NULL;\n}\n\n\nstatic char* test_output()\n{\n  const char *outputs[] = {\n    \"1.2 string nil true false\",\n    \"foo\",\n    NULL\n  };\n\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/output.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  add_ud_module(sb);\n\n  lsb_err_value ret = lsb_init(sb, NULL);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n  lsb_add_function(sb, &lsb_test_write_output, \"write_output\");\n\n  for (int x = 0; outputs[x]; ++x) {\n    int result = lsb_test_process(sb, x);\n    mu_assert(!result, \"process() test: %d failed: %d %s\", x, result,\n              lsb_get_error(sb));\n    if (outputs[x][0]) {\n      mu_assert(strcmp(outputs[x], lsb_test_output) == 0,\n                \"test: %d received: %s\", x, lsb_test_output);\n    }\n  }\n\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  return NULL;\n}\n\n\nstatic char* test_output_errors()\n{\n  const char *tests[] =\n  {\n    \"process() lua/output_errors.lua:10: bad argument #1 to 'output' (unsupported type)\"\n    , \"process() lua/output_errors.lua:16: output_limit exceeded\"\n    , \"process() lua/output_errors.lua:18: bad argument #1 to 'write_output' (unknown userdata type)\"\n    , NULL\n  };\n\n  for (int i = 0; tests[i]; ++i) {\n    lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/output_errors.lua\",\n                                     MODULE_PATH \"output_limit = 128\", NULL);\n    mu_assert(sb, \"lsb_create() received: NULL\");\n\n    lsb_err_value ret = lsb_init(sb, NULL);\n    mu_assert(!ret, \"lsb_init() received: %s\", ret);\n    lsb_add_function(sb, &lsb_test_write_output, \"write_output\");\n\n    int result = lsb_test_process(sb, i);\n    mu_assert(result == 1, \"test: %d received: %d\", i, result);\n\n    const char *le = lsb_get_error(sb);\n    mu_assert(le, \"test: %d received NULL\", i);\n    mu_assert(strcmp(tests[i], le) == 0, \"test: %d received: %s\", i, le);\n\n    e = lsb_destroy(sb);\n    mu_assert(!e, \"lsb_destroy() received: %s\", e);\n  }\n\n  return NULL;\n}\n\n\nstatic char* test_errors()\n{\n  const char *tests[] = {\n#ifdef _WIN32\n    \"process() lua/errors.lua:9: module 'unknown' not found:\\n\\tno file 'lua\\\\unknown.lua'\\n\\tno file 'lua\\\\unknown.dll'\"\n#else\n    \"process() lua/errors.lua:9: module 'unknown' not found:\\n\\tno file 'lua/unknown.lua'\\n\\tno file 'lua/unknown.so'\"\n#endif\n    , \"process() lua/errors.lua:11: bad argument #0 to 'output' (must have at least one argument)\"\n    , \"process() not enough memory\"\n    , \"process() instruction_limit exceeded\"\n    , \"process() lua/errors.lua:20: attempt to perform arithmetic on global 'x' (a nil value)\"\n    , \"process() must return a numeric error code\"\n    , \"process() must return a numeric error code\"\n    , \"process() lua/errors.lua:27: output_limit exceeded\"\n#ifdef _WIN32\n    , \"process() lua\\\\bad_module.lua:1: attempt to perform arithmetic on global 'nilvalue' (a nil value)\"\n#else\n    , \"process() lua/bad_module.lua:1: attempt to perform arithmetic on global 'nilvalue' (a nil value)\"\n#endif\n    , \"process() invalid module name '../invalid'\"\n    , \"process() lua/errors.lua:34: module 'pathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpathoverflowpa\"\n#ifdef _WIN32\n    , \"process() lua/errors.lua:36: module 'foo.bar' not found:\\n\\tno file 'lua\\\\foo\\\\bar.lua'\\n\\tno file 'lua\\\\foo\\\\bar.dll'\\n\\tno file 'lua\\\\foo.dll'\"\n#else\n    , \"process() lua/errors.lua:36: module 'foo.bar' not found:\\n\\tno file 'lua/foo/bar.lua'\\n\\tno file 'lua/foo/bar.so'\\n\\tno file 'lua/foo.so'\"\n#endif\n    , NULL\n  };\n\n  for (int i = 0; tests[i]; ++i) {\n    lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/errors.lua\",\n                                     \"memory_limit = 32767;\"\n                                     \"instruction_limit = 1000;\"\n                                     \"output_limit = 128;\"\n#ifdef _WIN32\n                                     \"path = 'lua\\\\\\\\?.lua'\"\n                                     \"cpath = 'lua\\\\\\\\?.dll'\",\n#else\n                                     \"path = 'lua/?.lua'\"\n                                     \"cpath = 'lua/?.so'\",\n#endif\n                                     NULL);\n    mu_assert(sb, \"lsb_create() received: NULL\");\n\n    lsb_err_value ret = lsb_init(sb, NULL);\n    mu_assert(!ret, \"lsb_init() received: %s\", ret);\n\n    int result = lsb_test_process(sb, i);\n    mu_assert(result == 1, \"test: %d received: %d\", i, result);\n\n    const char *le = lsb_get_error(sb);\n    mu_assert(le, \"test: %d received NULL\", i);\n    mu_assert(strcmp(tests[i], le) == 0, \"test: %d received: %s\", i, le);\n\n    e = lsb_destroy(sb);\n    mu_assert(!e, \"lsb_destroy() received: %s\", e);\n  }\n\n  return NULL;\n}\n\n\nstatic char* test_serialize()\n{\n  const char *output_file = \"serialize.preserve\";\n\n  remove(output_file);\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/serialize.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  add_ud_module(sb);\n\n  lsb_err_value ret = lsb_init(sb, output_file);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  char *expected = lsb_read_file(\"output/serialize.lua51.data\");\n  char *actual = lsb_read_file(output_file);\n  mu_assert(strcmp(expected, actual) == 0, \"serialization mismatch\");\n  free(expected);\n  free(actual);\n\n  return NULL;\n}\n\n\nstatic char* test_restore()\n{\n  const char *output_file = \"restore.preserve\";\n\n  remove(output_file);\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/restore.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  lsb_err_value ret = lsb_init(sb, output_file);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n  lsb_add_function(sb, &lsb_test_write_output, \"write_output\");\n  int result = lsb_test_process(sb, 0);\n  mu_assert(result == 0, \"process() received: %d %s\", result,\n            lsb_get_error(sb));\n  mu_assert(strcmp(\"101\", lsb_test_output) == 0, \"test: initial load received: %s\",\n            lsb_test_output);\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  // re-load to test the preserved data\n  sb = lsb_create(NULL, \"lua/restore.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  ret = lsb_init(sb, output_file);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n  lsb_add_function(sb, &lsb_test_write_output, \"write_output\");\n  result = lsb_test_process(sb, 0);\n  mu_assert(result == 0, \"process() received: %d %s\", result,\n            lsb_get_error(sb));\n  mu_assert(strcmp(\"102\", lsb_test_output) == 0, \"test: reload received: %s\",\n            lsb_test_output);\n  result = lsb_test_report(sb, 2); // change the preservation version\n  mu_assert(result == 0, \"report() received: %d\", result);\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  // re-load to test the preserved data with a version change\n  sb = lsb_create(NULL, \"lua/restore.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  ret = lsb_init(sb, output_file);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n  lsb_add_function(sb, &lsb_test_write_output, \"write_output\");\n  result = lsb_test_process(sb, 0);\n  mu_assert(result == 0, \"process() received: %d %s\", result,\n            lsb_get_error(sb));\n  mu_assert(strcmp(\"101\", lsb_test_output) == 0,\n            \"test: reload with version change received: %s\", lsb_test_output);\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  return NULL;\n}\n\n\nstatic char* test_serialize_failure()\n{\n  const char *output_file = \"serialize_failure.preserve\";\n  const char *expected = \"serialize_data cannot preserve type 'function'\";\n\n  remove(output_file);\n  lsb_lua_sandbox *sb = lsb_create(NULL,\n                                   \"lua/serialize_failure.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n\n  lsb_err_value ret = lsb_init(sb, output_file);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n  e = lsb_destroy(sb);\n  mu_assert(e, \"lsb_destroy() received: no error\");\n  mu_assert(strcmp(e, expected) == 0, \"lsb_destroy() received: %s\", e);\n  free(e);\n  e = NULL;\n  mu_assert(file_exists(output_file) == 0, \"output file was not cleaned up\");\n\n  return NULL;\n}\n\n\nstatic char* test_sandbox_config()\n{\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/sandbox_config.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n\n  lsb_err_value ret = lsb_init(sb, NULL);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n\n  return NULL;\n}\n\n\nstatic char* test_print()\n{\n  const char *tests[] =\n  {\n    \"\"\n    , \"7 lua/print.lua foo \\t10\\ttrue\"\n    , \"7 lua/print.lua f \\t10\\ttrue\"\n    , \"\"\n    , NULL\n  };\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/print.lua\", \"log_level = 7;\", &printer);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  mu_assert(lsb_get_logger(sb) != NULL, \"no logger\");\n  mu_assert(lsb_get_logger(sb)->cb == printer.cb, \"incorrect logger callback\");\n\n  lsb_err_value ret = lsb_init(sb, NULL);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n\n  for (int i = 0; tests[i]; ++i) {\n    print_out[0] = 0;\n    int result = lsb_test_process(sb, i);\n    mu_assert(result == 0, \"test: %d received: %d error: %s\", i, result, lsb_get_error(sb));\n    mu_assert(strcmp(tests[i], print_out) == 0, \"test: %d expected: %s received: %s\", i, tests[i], print_out);\n  }\n\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n  return NULL;\n}\n\n\nstatic char* test_print_disabled()\n{\n  const char *tests[] =\n  {\n    \"\"\n    , \"\"\n    , NULL\n  };\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/print.lua\", \"log_level = 6;\", &printer);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n\n  lsb_err_value ret = lsb_init(sb, NULL);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n\n  for (int i = 0; tests[i]; ++i) {\n    print_out[0] = 0;\n    int result = lsb_test_process(sb, i);\n    mu_assert(result == 0, \"test: %d received: %d error: %s\", i, result, lsb_get_error(sb));\n    mu_assert(strcmp(tests[i], print_out) == 0, \"test: %d expected: %s received: %s\", i, tests[i], print_out);\n  }\n\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n  return NULL;\n}\n\n\nstatic char* test_print_lsb_test_logger()\n{\n  const char *tests[] =\n  {\n    \"\"\n    , \"7 test.print foo \\t10\\ttrue\"\n    , NULL\n  };\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/print.lua\", \"log_level = 7;Logger = 'test.print';\", &printer);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n\n  lsb_err_value ret = lsb_init(sb, NULL);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n\n  for (int i = 0; tests[i]; ++i) {\n    print_out[0] = 0;\n    int result = lsb_test_process(sb, i);\n    mu_assert(result == 0, \"test: %d received: %d error: %s\", i, result, lsb_get_error(sb));\n    mu_assert(strcmp(tests[i], print_out) == 0, \"test: %d expected: %s received: %s\", i, tests[i], print_out);\n  }\n\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n  return NULL;\n}\n\n\nstatic char* test_serialize_binary()\n{\n  size_t size = 512;\n  lsb_output_buffer b;\n  lsb_err_value ret = lsb_init_output_buffer(&b, size);\n  mu_assert(ret == NULL, \"received: %s\", lsb_err_string(ret));\n  lsb_serialize_binary(&b, \"a\\r\\n\\\\\\\"\", 5);\n  mu_assert(b.pos == 9, \"received %d\", (int)b.pos);\n  mu_assert(memcmp(b.buf, \"a\\\\r\\\\n\\\\\\\\\\\\\\\"\", 5) == 0, \"received %.*s\", 9,\n            b.buf);\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* benchmark_counter()\n{\n  int iter = 10000000;\n\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/counter.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  lsb_err_value ret = lsb_init(sb, NULL);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n  clock_t t = clock();\n  for (int x = 0; x < iter; ++x) {\n    lsb_test_process(sb, 0);\n  }\n  t = clock() - t;\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n  printf(\"benchmark_counter() %g seconds\\n\", ((double)t) / CLOCKS_PER_SEC\n         / iter);\n\n  return NULL;\n}\n\n\nstatic char* benchmark_serialize()\n{\n  int iter = 1000;\n  const char *output_file = \"serialize.preserve\";\n\n  clock_t t = clock();\n  for (int x = 0; x < iter; ++x) {\n    remove(output_file);\n    lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/serialize.lua\", test_cfg, NULL);\n    mu_assert(sb, \"lsb_create() received: NULL\");\n    add_ud_module(sb);\n\n    lsb_err_value ret = lsb_init(sb, output_file);\n    mu_assert(!ret, \"lsb_init() received: %s %s\", ret, lsb_get_error(sb));\n    e = lsb_destroy(sb);\n    mu_assert(!e, \"lsb_destroy() received: %s\", e);\n  }\n  t = clock() - t;\n  printf(\"benchmark_serialize() %g seconds\\n\", ((double)t) / CLOCKS_PER_SEC\n         / iter);\n\n  return NULL;\n}\n\n\nstatic char* benchmark_deserialize()\n{\n  int iter = 1000;\n\n  clock_t t = clock();\n  for (int x = 0; x < iter; ++x) {\n    lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/serialize.lua\", test_cfg, NULL);\n    mu_assert(sb, \"lsb_create() received: NULL\");\n    add_ud_module(sb);\n\n    lsb_err_value ret = lsb_init(sb, \"output/serialize.data\");\n    mu_assert(!ret, \"lsb_init() received: %s\", ret);\n    free(sb->state_file);\n    sb->state_file = NULL; // poke the internals to prevent serialization\n    e = lsb_destroy(sb);\n    mu_assert(!e, \"lsb_destroy() received: %s\", e);\n  }\n  t = clock() - t;\n  printf(\"benchmark_deserialize() %g seconds\\n\", ((double)t) / CLOCKS_PER_SEC\n         / iter);\n\n  return NULL;\n}\n\n\nstatic char* benchmark_lua_types_output()\n{\n  int iter = 1000000;\n\n  lsb_lua_sandbox *sb = lsb_create(NULL, \"lua/output.lua\", test_cfg, NULL);\n  mu_assert(sb, \"lsb_create() received: NULL\");\n  lsb_err_value ret = lsb_init(sb, NULL);\n  mu_assert(!ret, \"lsb_init() received: %s\", ret);\n  lsb_add_function(sb, &lsb_test_write_output, \"write_output\");\n\n  clock_t t = clock();\n  for (int x = 0; x < iter; ++x) {\n    mu_assert(0 == lsb_test_process(sb, 0), \"%s\", lsb_get_error(sb));\n  }\n  t = clock() - t;\n  e = lsb_destroy(sb);\n  mu_assert(!e, \"lsb_destroy() received: %s\", e);\n  printf(\"benchmark_lua_types_output() %g seconds\\n\", ((double)t)\n         / CLOCKS_PER_SEC / iter);\n\n  return NULL;\n}\n\n\nstatic char* all_tests()\n{\n  mu_run_test(test_api_assertion);\n  mu_run_test(test_create);\n  mu_run_test(test_create_error);\n  mu_run_test(test_read_config);\n  mu_run_test(test_init_error);\n  mu_run_test(test_destroy_error);\n  mu_run_test(test_usage_error);\n  mu_run_test(test_stop);\n  mu_run_test(test_simple);\n  mu_run_test(test_simple_error);\n  mu_run_test(test_output);\n  mu_run_test(test_output_errors);\n  mu_run_test(test_errors);\n  mu_run_test(test_serialize);\n  mu_run_test(test_restore);\n  mu_run_test(test_serialize_failure);\n  mu_run_test(test_sandbox_config);\n  mu_run_test(test_print);\n  mu_run_test(test_print_disabled);\n  mu_run_test(test_print_lsb_test_logger);\n  mu_run_test(test_serialize_binary);\n\n  mu_run_test(benchmark_counter);\n  mu_run_test(benchmark_serialize);\n  mu_run_test(benchmark_deserialize);\n  mu_run_test(benchmark_lua_types_output);\n\n  return NULL;\n}\n\n\nint main()\n{\n  char *result = all_tests();\n  if (result) {\n    printf(\"%s\\n\", result);\n  } else {\n    printf(\"ALL TESTS PASSED\\n\");\n  }\n  printf(\"Tests run: %d\\n\", mu_tests_run);\n  free(e);\n\n  return result != NULL;\n}\n"
  },
  {
    "path": "src/util/CMakeLists.txt",
    "content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nset(UTIL_SRC\nheka_message.c\nheka_message_matcher.c\nheka_message_matcher_parser.c\ninput_buffer.c\noutput_buffer.c\nprotobuf.c\nrunning_stats.c\nstring.c\nstring_matcher.c\nutil.c\n)\n\nadd_library(luasandboxutil SHARED ${UTIL_SRC})\nset_target_properties(luasandboxutil PROPERTIES VERSION ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH} SOVERSION 0)\ntarget_compile_definitions(luasandboxutil PRIVATE -Dluasandboxutil_EXPORTS)\n\nif(LIBM_LIBRARY)\n  target_link_libraries(luasandboxutil ${LIBM_LIBRARY})\nendif()\n\ninstall(TARGETS luasandboxutil DESTINATION ${CMAKE_INSTALL_LIBDIR})\nadd_subdirectory(test)\n"
  },
  {
    "path": "src/util/heka_message.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Hindsight Heka message implementation @file */\n\n#include \"luasandbox/util/heka_message.h\"\n\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"../luasandbox_defines.h\"\n#include \"luasandbox/util/output_buffer.h\"\n#include \"luasandbox/util/protobuf.h\"\n\nstatic size_t decode_header(char *buf,\n                            size_t len,\n                            size_t max_message_size,\n                            lsb_logger *logger)\n{\n  if (*buf != 0x08) {\n    return 0;\n  }\n\n  char *p = buf;\n  if (p && p < buf + len - 1) {\n    long long vi;\n    if (lsb_pb_read_varint(p + 1, buf + len, &vi)) {\n      if (vi > 0 && vi <= (long long)max_message_size) {\n        return (size_t)vi;\n      } else {\n        if (logger && logger->cb) {\n          logger->cb(logger->context, __func__, 4,\n                     \"maximum (%lld) messages size exceeded: %lld\",\n                     (long long)max_message_size, vi);\n        }\n      }\n    }\n  }\n  return 0;\n}\n\n\nstatic const char*\nread_string(int wiretype, const char *p, const char *e, lsb_const_string *s)\n{\n  if (wiretype != LSB_PB_WT_LENGTH) {\n    return NULL;\n  }\n\n  long long vi;\n  p = lsb_pb_read_varint(p, e, &vi);\n  if (!p || vi < 0 || vi > e - p) {\n    return NULL;\n  }\n  s->s = p;\n  s->len = (size_t)vi;\n  return p + vi;\n}\n\n\nstatic bool\nread_string_value(const char *p, const char *e, int ai, lsb_read_value *val)\n{\n  int acnt = 0;\n  int tag = 0;\n  int wiretype = 0;\n  while (p && p < e) {\n    val->type = LSB_READ_NIL;\n    p = lsb_pb_read_key(p, &tag, &wiretype);\n    p = read_string(wiretype, p, e, &val->u.s);\n    if (p) {\n      if (ai == acnt++) {\n        val->type = LSB_READ_STRING;\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nstatic bool\nread_integer_value(const char *p, const char *e, int ai, lsb_read_value *val)\n{\n  int acnt = 0;\n  long long ll = 0;\n  while (p && p < e) {\n    p = lsb_pb_read_varint(p, e, &ll);\n    if (p) {\n      if (ai == acnt++) {\n        val->type = LSB_READ_NUMERIC;\n        val->u.d = (double)ll;\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n\nstatic bool\nread_double_value(const char *p, const char *e, int ai, lsb_read_value *val)\n{\n  if (p + (sizeof(double) * (ai + 1)) > e) {\n    return false;\n  }\n  val->type = LSB_READ_NUMERIC;\n  p += sizeof(double) * ai;\n  memcpy(&val->u.d, p, sizeof(double));\n  return true;\n}\n\n\nstatic const char*\nprocess_varint(int wiretype, const char *p, const char *e, long long *val)\n{\n  if (wiretype != 0) {\n    return NULL;\n  }\n  p = lsb_pb_read_varint(p, e, val);\n  return p ? p : NULL;\n}\n\n\nstatic const char*\nprocess_fields(lsb_heka_field *f, const char *p, const char *e)\n{\n  int tag       = 0;\n  int wiretype  = 0;\n  long long vi  = 0;\n\n  memset(f, 0, sizeof(lsb_heka_field));\n  p = lsb_pb_read_varint(p, e, &vi);\n  if (!p || vi < 0 || vi > e - p) {\n    return NULL;\n  }\n  e = p + vi; // only process to the end of the current field record\n\n  do {\n    p = lsb_pb_read_key(p, &tag, &wiretype);\n\n    switch (tag) {\n    case LSB_PB_NAME:\n      p = read_string(wiretype, p, e, &f->name);\n      break;\n\n    case LSB_PB_VALUE_TYPE:\n      p = process_varint(wiretype, p, e, &vi);\n      if (p) {\n        f->value_type = (int)vi;\n      }\n      break;\n\n    case LSB_PB_REPRESENTATION:\n      p = read_string(wiretype, p, e, &f->representation);\n      break;\n\n      // don't bother with the value(s) until we actually need them\n      // since this stream is created by Hindsight\n      // - tags are guaranteed to be properly ordered (values at the end)\n      // - there won't be repeated tags for packed values\n    case LSB_PB_VALUE_STRING:\n    case LSB_PB_VALUE_BYTES:\n      if (wiretype != 2) {\n        p = NULL;\n        break;\n      }\n      f->value.s = p - 1;\n      f->value.len = e - f->value.s;\n      p = e;\n      break;\n\n    case LSB_PB_VALUE_INTEGER:\n    case LSB_PB_VALUE_BOOL:\n      if (wiretype != 0 && wiretype != 2) {\n        p = NULL;\n        break;\n      }\n      // fall thru\n    case LSB_PB_VALUE_DOUBLE:\n      if (tag == 7 && wiretype != 1 && wiretype != 2) {\n        p = NULL;\n        break;\n      }\n      if (wiretype == 2) {\n        p = lsb_pb_read_varint(p, e, &vi);\n        if (!p || vi < 0 || vi > e - p) {\n          p = NULL;\n          break;\n        }\n      }\n      f->value.s = p;\n      f->value.len = e - f->value.s;\n      p = e;\n      break;\n\n    default:\n      p = NULL; // don't allow unknown tags\n      break;\n    }\n  } while (p && p < e);\n\n  return p && f->name.s ? p : NULL;\n}\n\n\nbool lsb_decode_heka_message(lsb_heka_message *m,\n                             const char *buf,\n                             size_t len,\n                             lsb_logger *logger)\n{\n  if (!m || !buf || len == 0) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 4, \"%s\", LSB_ERR_UTIL_NULL);\n    }\n    return false;\n  }\n\n  const char *cp  = buf;       // current position\n  const char *lp  = buf;       // last position\n  const char *ep  = buf + len; // end position\n  int wiretype    = 0;\n  int tag         = 0;\n  long long val   = 0;\n  bool timestamp  = false;\n\n  lsb_clear_heka_message(m);\n\n  do {\n    cp = lsb_pb_read_key(cp, &tag, &wiretype);\n\n    switch (tag) {\n    case LSB_PB_UUID:\n      cp = read_string(wiretype, cp, ep, &m->uuid);\n      if (m->uuid.len != LSB_UUID_SIZE) cp = NULL;\n      break;\n\n    case LSB_PB_TIMESTAMP:\n      cp = process_varint(wiretype, cp, ep, &m->timestamp);\n      if (cp) timestamp = true;\n      break;\n\n    case LSB_PB_TYPE:\n      cp = read_string(wiretype, cp, ep, &m->type);\n      break;\n\n    case LSB_PB_LOGGER:\n      cp = read_string(wiretype, cp, ep, &m->logger);\n      break;\n\n    case LSB_PB_SEVERITY:\n      cp = process_varint(wiretype, cp, ep, &val);\n      if (cp) m->severity = (int)val;\n      break;\n\n    case LSB_PB_PAYLOAD:\n      cp = read_string(wiretype, cp, ep, &m->payload);\n      break;\n\n    case LSB_PB_ENV_VERSION:\n      cp = read_string(wiretype, cp, ep, &m->env_version);\n      break;\n\n    case LSB_PB_PID:\n      cp = process_varint(wiretype, cp, ep, &val);\n      if (cp) m->pid = (int)val;\n      break;\n\n    case LSB_PB_HOSTNAME:\n      cp = read_string(wiretype, cp, ep, &m->hostname);\n      break;\n\n    case LSB_PB_FIELDS:\n      if (wiretype != 2) {\n        cp = NULL;\n        break;\n      }\n      if (m->fields_len == m->fields_size) {\n        int step = 8;\n        m->fields_size += step;\n        lsb_heka_field *tmp = realloc(m->fields,\n                                      m->fields_size * sizeof(lsb_heka_field));\n        if (!tmp) {\n          if (logger && logger->cb) {\n            logger->cb(logger->context, __func__, 0,\n                       \"fields reallocation failed\");\n          }\n          return false;\n        }\n        // the new memory will be initialized as needed Issue #231\n        m->fields = tmp;\n      }\n      cp = process_fields(&m->fields[m->fields_len], cp, ep);\n      ++m->fields_len;\n      break;\n\n    default:\n      cp = NULL;\n      break;\n    }\n    if (cp) lp = cp;\n  } while (cp && cp < ep);\n\n  if (!cp) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 4, \"tag:%d wiretype:%d position:%d\",\n                 tag, wiretype, lp - buf);\n    }\n    return false;\n  }\n\n  if (!m->uuid.s) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 4, \"%s\", \"missing \" LSB_UUID);\n    }\n    return false;\n  }\n\n  if (!timestamp) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 4, \"%s\", \"missing \" LSB_TIMESTAMP);\n    }\n    return false;\n  }\n\n  m->raw.s = buf;\n  m->raw.len = len;\n  return true;\n}\n\n\nbool lsb_find_heka_message(lsb_heka_message *m,\n                           lsb_input_buffer *ib,\n                           bool decode,\n                           size_t *discarded_bytes,\n                           lsb_logger *logger)\n{\n  if (!m || !ib || !discarded_bytes) {\n    if (logger && logger->cb) {\n      logger->cb(logger->context, __func__, 4, \"%s\", LSB_ERR_UTIL_NULL);\n    }\n    return false;\n  }\n\n  *discarded_bytes = 0;\n  if (ib->readpos == ib->scanpos) {\n    return false; // empty buffer\n  }\n\n  char *p = memchr(&ib->buf[ib->scanpos], 0x1e, ib->readpos - ib->scanpos);\n  if (p) {\n    if (p != ib->buf + ib->scanpos) {\n      // partial buffer skipped before locating a possible header\n      *discarded_bytes += p - ib->buf - ib->scanpos;\n    }\n    ib->scanpos = p - ib->buf;\n\n    if (ib->readpos - ib->scanpos < 2) {\n      return false; // header length is not buf\n    }\n\n    size_t hlen = (unsigned char)ib->buf[ib->scanpos + 1];\n    size_t hend = ib->scanpos + hlen + 3;\n    if (hend > ib->readpos) {\n      return false; // header is not in buf\n    }\n    if (ib->buf[hend - 1] != 0x1f) {\n      // invalid header length\n      ++ib->scanpos;\n      ++*discarded_bytes;\n      size_t db;\n      bool b =  lsb_find_heka_message(m, ib, decode, &db, logger);\n      *discarded_bytes += db;\n      return b;\n    }\n\n    if (!ib->msglen) {\n      ib->msglen = decode_header(&ib->buf[ib->scanpos + 2], hlen,\n                                 ib->maxsize - LSB_MAX_HDR_SIZE, logger);\n    }\n\n    if (ib->msglen) {\n      size_t mend = hend + ib->msglen;\n      if (mend > ib->readpos) {\n        return false; // message is not in buf\n      }\n\n      if (decode) {\n        if (lsb_decode_heka_message(m, &ib->buf[hend], ib->msglen, logger)) {\n          ib->scanpos = mend;\n          ib->msglen = 0;\n          return true;\n        } else {\n          // message decode failure\n          ++ib->scanpos;\n          ++*discarded_bytes;\n          ib->msglen = 0;\n          size_t db;\n          bool b =  lsb_find_heka_message(m, ib, decode, &db, logger);\n          *discarded_bytes += db;\n          return b;\n        }\n      } else {\n        // allow a framed message is non Heka protobuf format\n        lsb_clear_heka_message(m);\n        m->raw.s = &ib->buf[hend];\n        m->raw.len = ib->msglen;\n        ib->scanpos = mend;\n        ib->msglen = 0;\n        return true;\n      }\n    } else {\n      // header decode failure\n      ++ib->scanpos;\n      ++*discarded_bytes;\n      size_t db;\n      bool b =  lsb_find_heka_message(m, ib, decode, &db, logger);\n      *discarded_bytes += db;\n      return b;\n    }\n  } else {\n    // full buffer skipped since no header was located\n    *discarded_bytes += ib->readpos - ib->scanpos;\n    ib->scanpos = ib->readpos = 0;\n  }\n  return false;\n}\n\n\nlsb_err_value lsb_init_heka_message(lsb_heka_message *m, int num_fields)\n{\n  if (!m) return LSB_ERR_UTIL_NULL;\n  if (num_fields < 1) return LSB_ERR_UTIL_PRANGE;\n\n  m->fields = malloc(num_fields * sizeof(lsb_heka_field));\n  if (!m->fields) return LSB_ERR_UTIL_OOM;\n\n  m->fields_size = num_fields;\n  lsb_clear_heka_message(m);\n  return NULL;\n}\n\n\nvoid lsb_clear_heka_message(lsb_heka_message *m)\n{\n  if (!m) return;\n\n  lsb_init_const_string(&m->raw);\n  lsb_init_const_string(&m->uuid);\n  lsb_init_const_string(&m->type);\n  lsb_init_const_string(&m->logger);\n  lsb_init_const_string(&m->payload);\n  lsb_init_const_string(&m->env_version);\n  lsb_init_const_string(&m->hostname);\n\n  // The fields will be cleared as they are built out anything beyond fields_len\n  // should be considered uninitialized Issue #231.\n  m->timestamp = 0;\n  m->severity = 7;\n  m->pid = INT_MIN;\n  m->fields_len = 0;\n}\n\n\nvoid lsb_free_heka_message(lsb_heka_message *m)\n{\n  if (!m) return;\n\n  lsb_clear_heka_message(m);\n  free(m->fields);\n  m->fields = NULL;\n  m->fields_size = 0;\n}\n\n\nbool lsb_read_heka_field(const lsb_heka_message *m,\n                         lsb_const_string *name,\n                         int fi,\n                         int ai,\n                         lsb_read_value *val)\n{\n  if (!m || !name || !val) {\n    return false;\n  }\n\n  int fcnt = 0;\n  const char *p, *e;\n  val->type = LSB_READ_NIL;\n\n  for (int i = 0; i < m->fields_len; ++i) {\n    if (name->len == m->fields[i].name.len\n        && strncmp(name->s, m->fields[i].name.s, m->fields[i].name.len) == 0) {\n      if (fi == fcnt++) {\n        p = m->fields[i].value.s;\n        e = p + m->fields[i].value.len;\n        switch (m->fields[i].value_type) {\n        case LSB_PB_STRING:\n        case LSB_PB_BYTES:\n          return read_string_value(p, e, ai, val);\n        case LSB_PB_INTEGER:\n          return read_integer_value(p, e, ai, val);\n        case LSB_PB_BOOL:\n          if (read_integer_value(p, e, ai, val)) {\n            val->type = LSB_READ_BOOL;\n            return true;\n          }\n          return false;\n        case LSB_PB_DOUBLE:\n          return read_double_value(p, e, ai, val);\n        default:\n          return false;\n        }\n      }\n    }\n  }\n  return false;\n}\n\n\nlsb_err_value\nlsb_write_heka_uuid(lsb_output_buffer *ob, const char *uuid, size_t len)\n{\n  if (!ob) {\n    return LSB_ERR_UTIL_NULL;\n  }\n\n  static const size_t needed = 18;\n  ob->pos = 0; // writing a uuid will always clear the buffer as it is the\n               // start of a new message\n  lsb_err_value ret = lsb_expand_output_buffer(ob, needed);\n  if (ret) return ret;\n\n  ob->buf[ob->pos++] = 2 | (LSB_PB_UUID << 3); // write key\n  ob->buf[ob->pos++] = LSB_UUID_SIZE; // write length\n  if (uuid && len == LSB_UUID_SIZE) {\n    memcpy(ob->buf + ob->pos, uuid, LSB_UUID_SIZE);\n    ob->pos += LSB_UUID_SIZE;\n  } else if (uuid && len == LSB_UUID_STR_SIZE) {\n    int cnt = sscanf(uuid, \"%02hhx%02hhx%02hhx%02hhx\"\n                     \"-%02hhx%02hhx\"\n                     \"-%02hhx%02hhx\"\n                     \"-%02hhx%02hhx\"\n                     \"-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx\",\n                     (unsigned char *)ob->buf + ob->pos,\n                     (unsigned char *)ob->buf + ob->pos + 1,\n                     (unsigned char *)ob->buf + ob->pos + 2,\n                     (unsigned char *)ob->buf + ob->pos + 3,\n                     (unsigned char *)ob->buf + ob->pos + 4,\n                     (unsigned char *)ob->buf + ob->pos + 5,\n                     (unsigned char *)ob->buf + ob->pos + 6,\n                     (unsigned char *)ob->buf + ob->pos + 7,\n                     (unsigned char *)ob->buf + ob->pos + 8,\n                     (unsigned char *)ob->buf + ob->pos + 9,\n                     (unsigned char *)ob->buf + ob->pos + 10,\n                     (unsigned char *)ob->buf + ob->pos + 11,\n                     (unsigned char *)ob->buf + ob->pos + 12,\n                     (unsigned char *)ob->buf + ob->pos + 13,\n                     (unsigned char *)ob->buf + ob->pos + 14,\n                     (unsigned char *)ob->buf + ob->pos + 15);\n    if (cnt == LSB_UUID_SIZE) {\n      ob->pos += cnt;\n    }\n  }\n\n  if (ob->pos == 2) { // only the header has been written\n    for (int x = 0; x < LSB_UUID_SIZE; ++x) {\n      ob->buf[ob->pos++] = rand() % 256;\n    }\n    ob->buf[8] = (ob->buf[8] & 0x0F) | 0x40;\n    ob->buf[10] = (ob->buf[10] & 0x0F) | 0xA0;\n  }\n  return NULL;\n}\n\n\nsize_t lsb_write_heka_header(char *buf, size_t len)\n{\n  int hlen = lsb_pb_output_varint(buf + 3, len) + 1;\n  buf[hlen + 2] = '\\x1f';\n  buf[0] = '\\x1e';\n  buf[1] = (char)hlen;\n  buf[2] = '\\x08';\n  return LSB_HDR_FRAME_SIZE + hlen;\n}\n"
  },
  {
    "path": "src/util/heka_message_matcher.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Hindsight/Heka message matcher implementation @file */\n\n#include \"heka_message_matcher_impl.h\"\n\n#include <limits.h>\n#include <stdbool.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"luasandbox/util/heka_message.h\"\n#include \"luasandbox/util/heka_message_matcher.h\"\n#include \"luasandbox/util/string.h\"\n#include \"luasandbox/util/string_matcher.h\"\n\n\nstatic bool string_test(match_node *mn, lsb_const_string *val)\n{\n  const char *mn_val = mn->data + mn->var_len;\n  switch (mn->op) {\n  case OP_EQ:\n    if (val->len != mn->val_len || !val->s) return false;\n    return strncmp(val->s, mn_val, val->len) == 0;\n  case OP_NE:\n    if (val->len != mn->val_len || !val->s) return true;\n    return strncmp(val->s, mn_val, val->len) != 0;\n  case OP_LT:\n    {\n      if (!val->s) return true;\n      int cmp = strncmp(val->s, mn_val, val->len);\n      return cmp == 0 ? val->len < mn->val_len : cmp < 0;\n    }\n  case OP_LTE:\n    return val->s ? strncmp(val->s, mn_val, val->len) <= 0 : true;\n  case OP_GT:\n    {\n      if (!val->s) return false;\n      int cmp = strncmp(val->s, mn_val, val->len);\n      return cmp == 0 ? val->len > mn->val_len : cmp > 0;\n    }\n  case OP_GTE:\n    {\n      if (!val->s) return false;\n      int cmp = strncmp(val->s, mn_val, val->len);\n      return cmp == 0 ? val->len >= mn->val_len : cmp > 0;\n    }\n  case OP_RE:\n    if (mn->val_mod == PATTERN_MOD_ESC) {\n      return lsb_string_find(val->s, val->len, mn_val, mn->val_len);\n    } else {\n      return lsb_string_match(val->s, val->len, mn_val);\n    }\n  case OP_NRE:\n    if (mn->val_mod == PATTERN_MOD_ESC) {\n      return !lsb_string_find(val->s, val->len, mn_val, mn->val_len);\n    } else {\n      return !lsb_string_match(val->s, val->len, mn_val);\n    }\n  default:\n    break;\n  }\n  return false;\n}\n\n\nstatic bool numeric_test(match_node *mn, double val)\n{\n  double d = 0;\n  memcpy(&d, mn->data + mn->var_len, sizeof(double));\n  switch (mn->op) {\n  case OP_EQ:\n    return val == d;\n  case OP_NE:\n    return val != d;\n  case OP_LT:\n    return val < d;\n  case OP_LTE:\n    return val <= d;\n  case OP_GT:\n    return val > d;\n  case OP_GTE:\n    return val >= d;\n  default:\n    break;\n  }\n  return false;\n}\n\n\nstatic bool eval_node(match_node *mn, lsb_heka_message *m)\n{\n  switch (mn->op) {\n  case OP_TRUE:\n    return true;\n  case OP_FALSE:\n    return false;\n  default:\n    switch (mn->field_id) {\n    case LSB_PB_TIMESTAMP:\n      return numeric_test(mn, (double)m->timestamp);\n    case LSB_PB_TYPE:\n      if (mn->val_type == TYPE_NIL) {\n        bool is_nil = m->type.s == NULL;\n        return mn->op == OP_EQ  ? is_nil : !is_nil;\n      }\n      return string_test(mn, &m->type);\n    case LSB_PB_LOGGER:\n      if (mn->val_type == TYPE_NIL) {\n        bool is_nil = m->logger.s == NULL;\n        return mn->op == OP_EQ  ? is_nil : !is_nil;\n      }\n      return string_test(mn, &m->logger);\n    case LSB_PB_SEVERITY:\n      return numeric_test(mn, m->severity);\n    case LSB_PB_PAYLOAD:\n      if (mn->val_type == TYPE_NIL) {\n        bool is_nil = m->payload.s == NULL;\n        return mn->op == OP_EQ  ? is_nil : !is_nil;\n      }\n      return string_test(mn, &m->payload);\n    case LSB_PB_ENV_VERSION:\n      if (mn->val_type == TYPE_NIL) {\n        bool is_nil = m->env_version.s == NULL;\n        return mn->op == OP_EQ  ? is_nil : !is_nil;\n      }\n      return string_test(mn, &m->env_version);\n    case LSB_PB_PID:\n      if (mn->val_type == TYPE_NIL) {\n        bool is_nil = m->pid == INT_MIN;\n        return mn->op == OP_EQ  ? is_nil : !is_nil;\n      }\n      return numeric_test(mn, m->pid);\n    case LSB_PB_HOSTNAME:\n      if (mn->val_type == TYPE_NIL) {\n        bool is_nil = m->hostname.s == NULL;\n        return mn->op == OP_EQ  ? is_nil : !is_nil;\n      }\n      return string_test(mn, &m->hostname);\n    case LSB_PB_UUID:\n      return string_test(mn, &m->uuid);\n    default:\n      {\n        lsb_read_value val;\n        lsb_const_string variable = { .s = mn->data, .len = mn->var_len };\n\n        if (!lsb_read_heka_field(m, &variable, mn->u.idx.f, mn->u.idx.a,\n                                 &val)) {\n          if (mn->val_type == TYPE_NIL) {\n            return mn->op == OP_EQ;\n          }\n          return false;\n        }\n\n        switch (mn->val_type) {\n        case TYPE_STRING:\n          if (val.type == LSB_READ_STRING) {\n            return string_test(mn, &val.u.s);\n          }\n          break;\n        case TYPE_NUMERIC:\n          if (val.type == LSB_READ_NUMERIC) {\n            return numeric_test(mn, val.u.d);\n          }\n          break;\n        case TYPE_TRUE:\n          if (val.type == LSB_READ_BOOL || val.type == LSB_READ_NUMERIC) {\n            return mn->op == OP_EQ ? val.u.d == true : val.u.d != true;\n          }\n          break;\n        case TYPE_FALSE:\n          if (val.type == LSB_READ_BOOL || val.type == LSB_READ_NUMERIC) {\n            return mn->op == OP_EQ ? val.u.d == false: val.u.d != false;\n          }\n          break;\n        case TYPE_NIL:\n          return mn->op == OP_NE;\n        }\n      }\n      break;\n    }\n    break;\n  }\n  return false;\n}\n\n\nvoid lsb_destroy_message_matcher(lsb_message_matcher *mm)\n{\n  if (!mm) return;\n  free(mm->nodes);\n  free(mm);\n}\n\n\nbool lsb_eval_message_matcher(lsb_message_matcher *mm, lsb_heka_message *m)\n{\n  bool match = false;\n  if (!mm) return match;\n\n  match_node *s = mm->nodes;\n  match_node *e = mm->nodes + (mm->bytes / sizeof(match_node));\n  for (match_node *p = mm->nodes; p < e;) {\n    switch (p->op) {\n    case OP_OR:\n      if (match) {\n        p = s + p->u.off; // short circuit\n        continue;\n      }\n      break;\n    case OP_AND:\n      if (!match) {\n        p = s + p->u.off; // short circuit\n        continue;\n      }\n      break;\n    default:\n      match = eval_node(p, m);\n      break;\n    }\n    p += p->units;\n  }\n  return match;\n}\n"
  },
  {
    "path": "src/util/heka_message_matcher_impl.h",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Hindsight/Heka message matcher implementation header @file */\n\n#ifndef luasandbox_util_heka_message_matcher_impl_h_\n#define luasandbox_util_heka_message_matcher_impl_h_\n\n#include <stddef.h>\n#include <stdint.h>\n\ntypedef enum {\n  OP_EQ,\n  OP_NE,\n  OP_GTE,\n  OP_GT,\n  OP_LTE,\n  OP_LT,\n  OP_RE,\n  OP_NRE,\n  OP_TRUE,\n  OP_FALSE,\n  OP_OPEN,\n  OP_OR,\n  OP_AND\n} match_operation;\n\n\ntypedef enum {\n  TYPE_NIL,\n  TYPE_STRING,\n  TYPE_NUMERIC,\n  TYPE_FALSE,\n  TYPE_TRUE,\n} match_type;\n\n\ntypedef enum {\n  PATTERN_MOD_NONE,\n  PATTERN_MOD_ESC,\n} match_pattern_mod;\n\n\nstruct indices {\n  uint8_t f;\n  uint8_t a;\n};\n\n\ntypedef struct match_node {\n  uint8_t op;\n  uint8_t units;\n  uint8_t var_len;\n  uint8_t val_len;\n  uint8_t field_id;\n  uint8_t val_type : 4;\n  uint8_t val_mod  : 4;\n  union {\n    struct indices idx;\n    uint16_t       off;\n  } u;\n  char data[]; // inlined field variable and value data (when necessary)\n} match_node;\n\n\nstruct lsb_message_matcher {\n  size_t bytes;\n  match_node *nodes;\n};\n\n#endif\n"
  },
  {
    "path": "src/util/heka_message_matcher_parser.c",
    "content": "/* A recursive-descent parser generated by peg 0.1.18 */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#define YYRULECOUNT 56\n#line 1 \"../src/util/heka_message_matcher_parser.leg\"\n\n/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Hindsight message matcher parser @file */\n\n#include <limits.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n#include \"heka_message_matcher_impl.h\"\n#include \"luasandbox/util/heka_message.h\"\n#include \"luasandbox/util/heka_message_matcher.h\"\n\n#ifndef _MSC_VER\n#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n#pragma GCC diagnostic ignored \"-Wunused-function\"\n#else\n#pragma warning( disable : 4267 4244 )\n#endif\n\ntypedef struct match_node_tmp {\n  uint8_t id;\n  uint8_t op;\n  uint8_t val_mod;\n  uint8_t val_type;\n  uint8_t val_len;\n  uint8_t var_len;\n  uint8_t fi; // left node index for logical op\n  uint8_t ai; // right node index for logical op\n  char          *var;\n\n  union {\n    char    *s;\n    double  d;\n  } val;\n} match_node_tmp;\n\n\ntypedef struct match_node_array {\n  match_node_tmp *a;\n  int            pos;\n  int            size;\n} match_node_array;\n\n\ntypedef struct input_string {\n  const char *s;\n  size_t     pos;\n  size_t     size;\n} input_string;\n\n\ntypedef struct context {\n  match_node_array  out;\n  match_node_array  ops;\n  match_node_tmp    mn;\n  struct tm         tms;\n  int               cond_cnt;\n  input_string      is;\n} context;\n\n\n#define YY_PARSE(T) static T\n#define YY_CTX_LOCAL 1\n#define YY_CTX_MEMBERS \\\n   context ctx;\n\n#define YY_INPUT(yy, buf, result, max_size)                                    \\\n{                                                                              \\\n  input_string *is = &yy->ctx.is;                                              \\\n  result = is->size - is->pos;                                                 \\\n  if (result > 0) {                                                            \\\n    if (max_size >= result) {                                                  \\\n      memcpy(buf, &is->s[is->pos], result);                                    \\\n      is->pos += result;                                                       \\\n    } else {                                                                   \\\n      memcpy(buf, &is->s[is->pos], max_size);                                  \\\n      is->pos += max_size;                                                     \\\n      result = max_size;                                                       \\\n    }                                                                          \\\n  }                                                                            \\\n}\n\n\nstatic void init_match_node(match_node_tmp *mn)\n{\n  memset(mn, 0, sizeof(match_node_tmp));\n}\n\n\nstatic void move_match_node(match_node_tmp *dest, match_node_tmp *src)\n{\n  memcpy(dest, src, sizeof(match_node_tmp));\n  init_match_node(src); // dest now owns the memory, wipe the pointers\n}\n\n\nstatic void realloc_mna(match_node_array *mna)\n{\n  size_t bytes = sizeof(match_node_tmp) * ++mna->size;\n  match_node_tmp *tmp = realloc(mna->a, bytes);\n  if (tmp) {\n    mna->a = tmp;\n    init_match_node(&mna->a[mna->size - 1]);\n  } else {\n    fprintf(stderr, \"realloc failed\\n\");\n    exit(1);\n  }\n}\n\n\nstatic void push_output(context *ctx, match_node_tmp *mn)\n{\n  if (!ctx->out.a || ctx->out.pos == ctx->out.size) {\n    realloc_mna(&ctx->out);\n  }\n  move_match_node(&ctx->out.a[ctx->out.pos++], mn);\n}\n\n\nstatic void push_op(context *ctx, match_operation op)\n{\n  if (!ctx->ops.a) {\n    realloc_mna(&ctx->ops);\n    ctx->ops.a[ctx->ops.pos++].op = op;\n    return;\n  }\n\n  if (op == OP_OPEN || op > ctx->ops.a[ctx->ops.pos - 1].op) {\n    if (ctx->ops.pos == ctx->ops.size) {\n      realloc_mna(&ctx->ops);\n    }\n    ctx->ops.a[ctx->ops.pos++].op = op;\n  } else {\n    push_output(ctx, &ctx->ops.a[ctx->ops.pos - 1]);\n    ctx->ops.a[ctx->ops.pos - 1].op = op;\n  }\n}\n\n\nstatic void pop_to_paren(context *ctx)\n{\n  for (; ctx->ops.pos > 0; --ctx->ops.pos) {\n    match_node_tmp *op = &ctx->ops.a[ctx->ops.pos - 1];\n    if (op->op == OP_OPEN) break;\n    push_output(ctx, op);\n  }\n}\n\n\nstatic void pop_all_ops(context *ctx)\n{\n  for (; ctx->ops.pos > 0; --ctx->ops.pos) {\n    match_node_tmp *op = &ctx->ops.a[ctx->ops.pos - 1];\n    if (op->op == OP_OPEN) continue;\n    push_output(ctx, op);\n  }\n}\n\n\nstatic void update_date(context *ctx, int year, int mon, int day)\n{\n  ctx->tms.tm_isdst = -1;\n  ctx->tms.tm_year  = year - 1900;\n  ctx->tms.tm_mon   = mon - 1;\n  ctx->tms.tm_mday  = day;\n}\n\n\nstatic void update_time(context *ctx, int hour, int minute, int sec)\n{\n  ctx->tms.tm_hour  = hour;\n  ctx->tms.tm_min   = minute;\n  ctx->tms.tm_sec   = sec;\n}\n\n\nstatic void update_offset(context *ctx, char sign, int hour, int minute)\n{\n  ctx->mn.val.d += (hour * 3600 + minute * 60) * (sign == '-' ? -1 : 1);\n}\n\n\nstatic void set_field(context *ctx, char *name)\n{\n  ctx->mn.id = LSB_PB_FIELDS;\n  ctx->mn.var_len = strlen(name);\n  ctx->mn.var = malloc(ctx->mn.var_len + 1);\n  if (!ctx->mn.var) {\n    fprintf(stderr, \"malloc failed\\n\");\n    exit(1);\n  }\n  memcpy(ctx->mn.var, name, ctx->mn.var_len + 1);\n}\n\n\nstatic void set_timestamp(context *ctx)\n{\n  ctx->mn.id = LSB_PB_TIMESTAMP;\n  ctx->mn.val_type = TYPE_NUMERIC;\n  if (ctx->tms.tm_isdst == -1) {\n    ctx->mn.val.d += mktime(&ctx->tms);\n    ctx->mn.val.d *= 1e9;\n  }\n  memset(&ctx->tms, 0, sizeof(struct tm));\n}\n\n\nstatic void set_numeric_value(context *ctx, char *s)\n{\n  ctx->mn.val_type = TYPE_NUMERIC;\n  ctx->mn.val.d = strtod(s, NULL);\n}\n\n\nstatic void set_string_value(context *ctx, char *s)\n{\n  ctx->mn.val_type = TYPE_STRING;\n  int i, j;\n  for (i = 0, j = 0; s[i]; ++i, ++j) {\n    if (s[i] == '\\\\'\n    && (s[i + 1] == '\"' || s[i + 1] == '\\'' || s[i + 1] == '\\\\')) {\n      ++i;\n    }\n    s[j] = s[i];\n  }\n  s[j] = 0;\n\n  ctx->mn.val_len = j;\n  ctx->mn.val.s = malloc(j + 1);\n  if (!ctx->mn.val.s) {\n    fprintf(stderr, \"malloc failed\\n\");\n    exit(1);\n  }\n  memcpy(ctx->mn.val.s, s, j + 1);\n}\n\n\nstatic void set_match_mod(context *ctx)\n{\n  if (ctx->mn.val_mod == PATTERN_MOD_NONE\n     && strpbrk(ctx->mn.val.s, \"^$*+?.[%-\") == NULL) { // literal\n    ctx->mn.val_mod = PATTERN_MOD_ESC;\n  }\n}\n\n\nstatic bool check_string_len(char *s)\n{\n  int i, j;\n  for (i = 0, j = 0; s[i]; ++i, ++j) {\n    if (s[i] == '\\\\'\n    && (s[i + 1] == '\"' || s[i + 1] == '\\'' || s[i + 1] == '\\\\')) {\n      ++i;\n    }\n  }\n  return (j > UCHAR_MAX) ? false : true;\n}\n\n\nstatic int cond_cnt(context *ctx)\n{\n  return (++ctx->cond_cnt * 2 + 1 > UCHAR_MAX) ? 0 : 1;\n}\n\n\n#ifndef YY_MALLOC\n#define YY_MALLOC(C, N)\t\tmalloc(N)\n#endif\n#ifndef YY_REALLOC\n#define YY_REALLOC(C, P, N)\trealloc(P, N)\n#endif\n#ifndef YY_FREE\n#define YY_FREE(C, P)\t\tfree(P)\n#endif\n#ifndef YY_LOCAL\n#define YY_LOCAL(T)\tstatic T\n#endif\n#ifndef YY_ACTION\n#define YY_ACTION(T)\tstatic T\n#endif\n#ifndef YY_RULE\n#define YY_RULE(T)\tstatic T\n#endif\n#ifndef YY_PARSE\n#define YY_PARSE(T)\tT\n#endif\n#ifndef YYPARSE\n#define YYPARSE\t\tyyparse\n#endif\n#ifndef YYPARSEFROM\n#define YYPARSEFROM\tyyparsefrom\n#endif\n#ifndef YYRELEASE\n#define YYRELEASE\tyyrelease\n#endif\n#ifndef YY_BEGIN\n#define YY_BEGIN\t( yy->__begin= yy->__pos, 1)\n#endif\n#ifndef YY_END\n#define YY_END\t\t( yy->__end= yy->__pos, 1)\n#endif\n#ifdef YY_DEBUG\n# define yyprintf(args)\tfprintf args\n#else\n# define yyprintf(args)\n#endif\n#ifndef YYSTYPE\n#define YYSTYPE\tint\n#endif\n#ifndef YY_STACK_SIZE\n#define YY_STACK_SIZE 128\n#endif\n\n#ifndef YY_BUFFER_SIZE\n#define YY_BUFFER_SIZE 1024\n#endif\n\n#ifndef YY_PART\n\ntypedef struct _yycontext yycontext;\ntypedef void (*yyaction)(yycontext *yy, char *yytext, int yyleng);\ntypedef struct _yythunk { int begin, end;  yyaction  action;  struct _yythunk *next; } yythunk;\n\nstruct _yycontext {\n  char     *__buf;\n  int       __buflen;\n  int       __pos;\n  int       __limit;\n  char     *__text;\n  int       __textlen;\n  int       __begin;\n  int       __end;\n  int       __textmax;\n  yythunk  *__thunks;\n  int       __thunkslen;\n  int       __thunkpos;\n  YYSTYPE   __;\n  YYSTYPE  *__val;\n  YYSTYPE  *__vals;\n  int       __valslen;\n#ifdef YY_CTX_MEMBERS\n  YY_CTX_MEMBERS\n#endif\n};\n\n#ifdef YY_CTX_LOCAL\n#define YY_CTX_PARAM_\tyycontext *yyctx,\n#define YY_CTX_PARAM\tyycontext *yyctx\n#define YY_CTX_ARG_\tyyctx,\n#define YY_CTX_ARG\tyyctx\n#ifndef YY_INPUT\n#define YY_INPUT(yy, buf, result, max_size)\t\t\\\n  {\t\t\t\t\t\t\t\\\n    int yyc= getchar();\t\t\t\t\t\\\n    result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1);\t\\\n    yyprintf((stderr, \"<%c>\", yyc));\t\t\t\\\n  }\n#endif\n#else\n#define YY_CTX_PARAM_\n#define YY_CTX_PARAM\n#define YY_CTX_ARG_\n#define YY_CTX_ARG\nyycontext _yyctx= { 0, 0 };\nyycontext *yyctx= &_yyctx;\n#ifndef YY_INPUT\n#define YY_INPUT(buf, result, max_size)\t\t\t\\\n  {\t\t\t\t\t\t\t\\\n    int yyc= getchar();\t\t\t\t\t\\\n    result= (EOF == yyc) ? 0 : (*(buf)= yyc, 1);\t\\\n    yyprintf((stderr, \"<%c>\", yyc));\t\t\t\\\n  }\n#endif\n#endif\n\nYY_LOCAL(int) yyrefill(yycontext *yy)\n{\n  int yyn;\n  while (yy->__buflen - yy->__pos < 512)\n    {\n      yy->__buflen *= 2;\n      yy->__buf= (char *)YY_REALLOC(yy, yy->__buf, yy->__buflen);\n    }\n#ifdef YY_CTX_LOCAL\n  YY_INPUT(yy, (yy->__buf + yy->__pos), yyn, (yy->__buflen - yy->__pos));\n#else\n  YY_INPUT((yy->__buf + yy->__pos), yyn, (yy->__buflen - yy->__pos));\n#endif\n  if (!yyn) return 0;\n  yy->__limit += yyn;\n  return 1;\n}\n\nYY_LOCAL(int) yymatchDot(yycontext *yy)\n{\n  if (yy->__pos >= yy->__limit && !yyrefill(yy)) return 0;\n  ++yy->__pos;\n  return 1;\n}\n\nYY_LOCAL(int) yymatchChar(yycontext *yy, int c)\n{\n  if (yy->__pos >= yy->__limit && !yyrefill(yy)) return 0;\n  if ((unsigned char)yy->__buf[yy->__pos] == c)\n    {\n      ++yy->__pos;\n      yyprintf((stderr, \"  ok   yymatchChar(yy, %c) @ %s\\n\", c, yy->__buf+yy->__pos));\n      return 1;\n    }\n  yyprintf((stderr, \"  fail yymatchChar(yy, %c) @ %s\\n\", c, yy->__buf+yy->__pos));\n  return 0;\n}\n\nYY_LOCAL(int) yymatchString(yycontext *yy, const char *s)\n{\n  int yysav= yy->__pos;\n  while (*s)\n    {\n      if (yy->__pos >= yy->__limit && !yyrefill(yy)) return 0;\n      if (yy->__buf[yy->__pos] != *s)\n        {\n          yy->__pos= yysav;\n          return 0;\n        }\n      ++s;\n      ++yy->__pos;\n    }\n  return 1;\n}\n\nYY_LOCAL(int) yymatchClass(yycontext *yy, unsigned char *bits)\n{\n  int c;\n  if (yy->__pos >= yy->__limit && !yyrefill(yy)) return 0;\n  c= (unsigned char)yy->__buf[yy->__pos];\n  if (bits[c >> 3] & (1 << (c & 7)))\n    {\n      ++yy->__pos;\n      yyprintf((stderr, \"  ok   yymatchClass @ %s\\n\", yy->__buf+yy->__pos));\n      return 1;\n    }\n  yyprintf((stderr, \"  fail yymatchClass @ %s\\n\", yy->__buf+yy->__pos));\n  return 0;\n}\n\nYY_LOCAL(void) yyDo(yycontext *yy, yyaction action, int begin, int end)\n{\n  while (yy->__thunkpos >= yy->__thunkslen)\n    {\n      yy->__thunkslen *= 2;\n      yy->__thunks= (yythunk *)YY_REALLOC(yy, yy->__thunks, sizeof(yythunk) * yy->__thunkslen);\n    }\n  yy->__thunks[yy->__thunkpos].begin=  begin;\n  yy->__thunks[yy->__thunkpos].end=    end;\n  yy->__thunks[yy->__thunkpos].action= action;\n  ++yy->__thunkpos;\n}\n\nYY_LOCAL(int) yyText(yycontext *yy, int begin, int end)\n{\n  int yyleng= end - begin;\n  if (yyleng <= 0)\n    yyleng= 0;\n  else\n    {\n      while (yy->__textlen < (yyleng + 1))\n\t{\n\t  yy->__textlen *= 2;\n\t  yy->__text= (char *)YY_REALLOC(yy, yy->__text, yy->__textlen);\n\t}\n      memcpy(yy->__text, yy->__buf + begin, yyleng);\n    }\n  yy->__text[yyleng]= '\\0';\n  return yyleng;\n}\n\nYY_LOCAL(void) yyDone(yycontext *yy)\n{\n  int pos;\n  for (pos= 0;  pos < yy->__thunkpos;  ++pos)\n    {\n      yythunk *thunk= &yy->__thunks[pos];\n      int yyleng= thunk->end ? yyText(yy, thunk->begin, thunk->end) : thunk->begin;\n      yyprintf((stderr, \"DO [%d] %p %s\\n\", pos, thunk->action, yy->__text));\n      thunk->action(yy, yy->__text, yyleng);\n    }\n  yy->__thunkpos= 0;\n}\n\nYY_LOCAL(void) yyCommit(yycontext *yy)\n{\n  if ((yy->__limit -= yy->__pos))\n    {\n      memmove(yy->__buf, yy->__buf + yy->__pos, yy->__limit);\n    }\n  yy->__begin -= yy->__pos;\n  yy->__end -= yy->__pos;\n  yy->__pos= yy->__thunkpos= 0;\n}\n\nYY_LOCAL(int) yyAccept(yycontext *yy, int tp0)\n{\n  if (tp0)\n    {\n      fprintf(stderr, \"accept denied at %d\\n\", tp0);\n      return 0;\n    }\n  else\n    {\n      yyDone(yy);\n      yyCommit(yy);\n    }\n  return 1;\n}\n\nYY_LOCAL(void) yyPush(yycontext *yy, char *text, int count)\n{\n  yy->__val += count;\n  while (yy->__valslen <= yy->__val - yy->__vals)\n    {\n      long offset= yy->__val - yy->__vals;\n      int olen = yy->__valslen;\n      yy->__valslen *= 2;\n      yy->__vals= (YYSTYPE *)YY_REALLOC(yy, yy->__vals, sizeof(YYSTYPE) * yy->__valslen);\n      yy->__val= yy->__vals + offset;\n      memset(yy->__vals + olen, 0, sizeof(YYSTYPE) * olen);\n    }\n}\nYY_LOCAL(void) yyPop(yycontext *yy, char *text, int count)   { yy->__val -= count; }\nYY_LOCAL(void) yySet(yycontext *yy, char *text, int count)   { yy->__val[count]= yy->__; }\n\n#endif /* YY_PART */\n\n#define\tYYACCEPT\tyyAccept(yy, yythunkpos0)\n\nYY_RULE(int) yy_second_frac(yycontext *yy); /* 56 */\nYY_RULE(int) yy_second(yycontext *yy); /* 55 */\nYY_RULE(int) yy_minute(yycontext *yy); /* 54 */\nYY_RULE(int) yy_hour(yycontext *yy); /* 53 */\nYY_RULE(int) yy_timeoffset(yycontext *yy); /* 52 */\nYY_RULE(int) yy_partialtime(yycontext *yy); /* 51 */\nYY_RULE(int) yy_fulltime(yycontext *yy); /* 50 */\nYY_RULE(int) yy_day(yycontext *yy); /* 49 */\nYY_RULE(int) yy_month(yycontext *yy); /* 48 */\nYY_RULE(int) yy_year(yycontext *yy); /* 47 */\nYY_RULE(int) yy_fulldate(yycontext *yy); /* 46 */\nYY_RULE(int) yy_rfc3339(yycontext *yy); /* 45 */\nYY_RULE(int) yy_ts_quoted(yycontext *yy); /* 44 */\nYY_RULE(int) yy_zero_to_255(yycontext *yy); /* 43 */\nYY_RULE(int) yy_index(yycontext *yy); /* 42 */\nYY_RULE(int) yy_fields(yycontext *yy); /* 41 */\nYY_RULE(int) yy_exponent(yycontext *yy); /* 40 */\nYY_RULE(int) yy_decimal(yycontext *yy); /* 39 */\nYY_RULE(int) yy_number(yycontext *yy); /* 38 */\nYY_RULE(int) yy_sign(yycontext *yy); /* 37 */\nYY_RULE(int) yy_numeric_value(yycontext *yy); /* 36 */\nYY_RULE(int) yy_string_match_mod(yycontext *yy); /* 35 */\nYY_RULE(int) yy_nil(yycontext *yy); /* 34 */\nYY_RULE(int) yy_string_match(yycontext *yy); /* 33 */\nYY_RULE(int) yy_string_value(yycontext *yy); /* 32 */\nYY_RULE(int) yy_string_headers(yycontext *yy); /* 31 */\nYY_RULE(int) yy_boolean(yycontext *yy); /* 30 */\nYY_RULE(int) yy_false(yycontext *yy); /* 29 */\nYY_RULE(int) yy_true(yycontext *yy); /* 28 */\nYY_RULE(int) yy_relational(yycontext *yy); /* 27 */\nYY_RULE(int) yy_op_lt(yycontext *yy); /* 26 */\nYY_RULE(int) yy_op_lte(yycontext *yy); /* 25 */\nYY_RULE(int) yy_op_gt(yycontext *yy); /* 24 */\nYY_RULE(int) yy_op_gte(yycontext *yy); /* 23 */\nYY_RULE(int) yy_op_sne(yycontext *yy); /* 22 */\nYY_RULE(int) yy_op_seq(yycontext *yy); /* 21 */\nYY_RULE(int) yy_op_ne(yycontext *yy); /* 20 */\nYY_RULE(int) yy_op_eq(yycontext *yy); /* 19 */\nYY_RULE(int) yy_boolean_test(yycontext *yy); /* 18 */\nYY_RULE(int) yy_field_test(yycontext *yy); /* 17 */\nYY_RULE(int) yy_pid(yycontext *yy); /* 16 */\nYY_RULE(int) yy_severity(yycontext *yy); /* 15 */\nYY_RULE(int) yy_optional_string_headers(yycontext *yy); /* 14 */\nYY_RULE(int) yy_timestamp(yycontext *yy); /* 13 */\nYY_RULE(int) yy_uuid(yycontext *yy); /* 12 */\nYY_RULE(int) yy_close(yycontext *yy); /* 11 */\nYY_RULE(int) yy_open(yycontext *yy); /* 10 */\nYY_RULE(int) yy_test(yycontext *yy); /* 9 */\nYY_RULE(int) yy_and(yycontext *yy); /* 8 */\nYY_RULE(int) yy_expr(yycontext *yy); /* 7 */\nYY_RULE(int) yy_or(yycontext *yy); /* 6 */\nYY_RULE(int) yy_anded(yycontext *yy); /* 5 */\nYY_RULE(int) yy_eol(yycontext *yy); /* 4 */\nYY_RULE(int) yy_ored(yycontext *yy); /* 3 */\nYY_RULE(int) yy_sp(yycontext *yy); /* 2 */\nYY_RULE(int) yy_match(yycontext *yy); /* 1 */\n\nYY_ACTION(void) yy_1_nil(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_nil\\n\"));\n  {\n#line 379\n  yy->ctx.mn.val_type = TYPE_NIL;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_second_frac(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_second_frac\\n\"));\n  {\n#line 377\n  yy->ctx.mn.val.d += strtod(yytext, NULL);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_second(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_second\\n\"));\n  {\n#line 376\n  __ = atoi(yytext);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_minute(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_minute\\n\"));\n  {\n#line 372\n  __ = atoi(yytext);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_hour(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_hour\\n\"));\n  {\n#line 371\n  __ = atoi(yytext);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_2_timeoffset(yycontext *yy, char *yytext, int yyleng)\n{\n#define m yy->__val[-1]\n#define h yy->__val[-2]\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_2_timeoffset\\n\"));\n  {\n#line 367\n  update_offset(&yy->ctx, yytext[0], h, m);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n#undef m\n#undef h\n}\nYY_ACTION(void) yy_1_timeoffset(yycontext *yy, char *yytext, int yyleng)\n{\n#define m yy->__val[-1]\n#define h yy->__val[-2]\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_timeoffset\\n\"));\n  {\n#line 366\n  update_offset(&yy->ctx, '+', 0, 0);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n#undef m\n#undef h\n}\nYY_ACTION(void) yy_1_partialtime(yycontext *yy, char *yytext, int yyleng)\n{\n#define s yy->__val[-1]\n#define m yy->__val[-2]\n#define h yy->__val[-3]\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_partialtime\\n\"));\n  {\n#line 365\n  update_time(&yy->ctx, h, m, s);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n#undef s\n#undef m\n#undef h\n}\nYY_ACTION(void) yy_1_day(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_day\\n\"));\n  {\n#line 361\n  __ = atoi(yytext);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_month(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_month\\n\"));\n  {\n#line 356\n  __ = atoi(yytext);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_year(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_year\\n\"));\n  {\n#line 353\n  __ = atoi(yytext);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_fulldate(yycontext *yy, char *yytext, int yyleng)\n{\n#define d yy->__val[-1]\n#define m yy->__val[-2]\n#define y yy->__val[-3]\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_fulldate\\n\"));\n  {\n#line 352\n  update_date(&yy->ctx, y, m, d);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n#undef d\n#undef m\n#undef y\n}\nYY_ACTION(void) yy_1_timestamp(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_timestamp\\n\"));\n  {\n#line 350\n  set_timestamp(&yy->ctx);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_index(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_index\\n\"));\n  {\n#line 344\n  __ = atoi(yytext);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_3_fields(yycontext *yy, char *yytext, int yyleng)\n{\n#define a yy->__val[-1]\n#define f yy->__val[-2]\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_3_fields\\n\"));\n  {\n#line 343\n  yy->ctx.mn.ai = a;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n#undef a\n#undef f\n}\nYY_ACTION(void) yy_2_fields(yycontext *yy, char *yytext, int yyleng)\n{\n#define a yy->__val[-1]\n#define f yy->__val[-2]\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_2_fields\\n\"));\n  {\n#line 343\n  yy->ctx.mn.fi = f;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n#undef a\n#undef f\n}\nYY_ACTION(void) yy_1_fields(yycontext *yy, char *yytext, int yyleng)\n{\n#define a yy->__val[-1]\n#define f yy->__val[-2]\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_fields\\n\"));\n  {\n#line 343\n  set_field(&yy->ctx, yytext);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n#undef a\n#undef f\n}\nYY_ACTION(void) yy_1_numeric_value(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_numeric_value\\n\"));\n  {\n#line 333\n  set_numeric_value(&yy->ctx, yytext);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_pid(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_pid\\n\"));\n  {\n#line 331\n  yy->ctx.mn.id = LSB_PB_PID;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_severity(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_severity\\n\"));\n  {\n#line 330\n  yy->ctx.mn.id = LSB_PB_SEVERITY;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_string_match_mod(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_string_match_mod\\n\"));\n  {\n#line 328\n  yy->ctx.mn.val_mod = PATTERN_MOD_ESC;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_string_match(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_string_match\\n\"));\n  {\n#line 326\n  set_match_mod(&yy->ctx);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_string_value(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_string_value\\n\"));\n  {\n#line 324\n  set_string_value(&yy->ctx, yytext);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_5_string_headers(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_5_string_headers\\n\"));\n  {\n#line 320\n  yy->ctx.mn.id = LSB_PB_PAYLOAD;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_4_string_headers(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_4_string_headers\\n\"));\n  {\n#line 319\n  yy->ctx.mn.id = LSB_PB_ENV_VERSION;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_3_string_headers(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_3_string_headers\\n\"));\n  {\n#line 318\n  yy->ctx.mn.id = LSB_PB_HOSTNAME;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_2_string_headers(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_2_string_headers\\n\"));\n  {\n#line 317\n  yy->ctx.mn.id = LSB_PB_LOGGER;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_string_headers(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_string_headers\\n\"));\n  {\n#line 316\n  yy->ctx.mn.id = LSB_PB_TYPE;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_uuid(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_uuid\\n\"));\n  {\n#line 315\n  yy->ctx.mn.id = LSB_PB_UUID;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_close(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_close\\n\"));\n  {\n#line 311\n  pop_to_paren(&yy->ctx);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_open(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_open\\n\"));\n  {\n#line 310\n  push_op(&yy->ctx, OP_OPEN);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_or(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_or\\n\"));\n  {\n#line 309\n  push_op(&yy->ctx, OP_OR);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_and(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_and\\n\"));\n  {\n#line 308\n  push_op(&yy->ctx, OP_AND);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_2_boolean(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_2_boolean\\n\"));\n  {\n#line 306\n  yy->ctx.mn.val_type = TYPE_FALSE;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_boolean(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_boolean\\n\"));\n  {\n#line 305\n  yy->ctx.mn.val_type = TYPE_TRUE;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_2_boolean_test(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_2_boolean_test\\n\"));\n  {\n#line 304\n  yy->ctx.mn.op = OP_FALSE;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_boolean_test(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_boolean_test\\n\"));\n  {\n#line 303\n  yy->ctx.mn.op = OP_TRUE;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_op_lt(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_op_lt\\n\"));\n  {\n#line 294\n  yy->ctx.mn.op = OP_LT;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_op_lte(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_op_lte\\n\"));\n  {\n#line 293\n  yy->ctx.mn.op = OP_LTE;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_op_gt(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_op_gt\\n\"));\n  {\n#line 292\n  yy->ctx.mn.op = OP_GT;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_op_gte(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_op_gte\\n\"));\n  {\n#line 291\n  yy->ctx.mn.op = OP_GTE;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_op_sne(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_op_sne\\n\"));\n  {\n#line 290\n  yy->ctx.mn.op = OP_NRE;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_op_seq(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_op_seq\\n\"));\n  {\n#line 289\n  yy->ctx.mn.op = OP_RE;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_op_ne(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_op_ne\\n\"));\n  {\n#line 288\n  yy->ctx.mn.op = OP_NE;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_op_eq(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_op_eq\\n\"));\n  {\n#line 287\n  yy->ctx.mn.op = OP_EQ;\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_test(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_test\\n\"));\n  {\n#line 285\n  push_output(&yy->ctx, &yy->ctx.mn);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\nYY_ACTION(void) yy_1_match(yycontext *yy, char *yytext, int yyleng)\n{\n#define __ yy->__\n#define yypos yy->__pos\n#define yythunkpos yy->__thunkpos\n  yyprintf((stderr, \"do yy_1_match\\n\"));\n  {\n#line 274\n  pop_all_ops(&yy->ctx);\n  }\n#undef yythunkpos\n#undef yypos\n#undef yy\n}\n\nYY_RULE(int) yy_second_frac(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"second_frac\"));  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l1;\n#undef yytext\n#undef yyleng\n  }  if (!yy_decimal(yy)) goto l1;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l1;\n#undef yytext\n#undef yyleng\n  }  yyDo(yy, yy_1_second_frac, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"second_frac\", yy->__buf+yy->__pos));\n  return 1;\n  l1:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"second_frac\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_second(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"second\"));\n  {  int yypos3= yy->__pos, yythunkpos3= yy->__thunkpos;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l4;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\077\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l4;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l4;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l4;\n#undef yytext\n#undef yyleng\n  }  goto l3;\n  l4:;\t  yy->__pos= yypos3; yy->__thunkpos= yythunkpos3;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l2;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchString(yy, \"60\")) goto l2;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l2;\n#undef yytext\n#undef yyleng\n  }\n  }\n  l3:;\t  yyDo(yy, yy_1_second, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"second\", yy->__buf+yy->__pos));\n  return 1;\n  l2:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"second\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_minute(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"minute\"));  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l5;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\077\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l5;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l5;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l5;\n#undef yytext\n#undef yyleng\n  }  yyDo(yy, yy_1_minute, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"minute\", yy->__buf+yy->__pos));\n  return 1;\n  l5:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"minute\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_hour(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"hour\"));\n  {  int yypos7= yy->__pos, yythunkpos7= yy->__thunkpos;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l8;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l8;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l8;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l8;\n#undef yytext\n#undef yyleng\n  }  goto l7;\n  l8:;\t  yy->__pos= yypos7; yy->__thunkpos= yythunkpos7;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l6;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchChar(yy, '2')) goto l6;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\017\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l6;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l6;\n#undef yytext\n#undef yyleng\n  }\n  }\n  l7:;\t  yyDo(yy, yy_1_hour, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"hour\", yy->__buf+yy->__pos));\n  return 1;\n  l6:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"hour\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_timeoffset(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;  yyDo(yy, yyPush, 2, 0);\n  yyprintf((stderr, \"%s\\n\", \"timeoffset\"));\n  {  int yypos10= yy->__pos, yythunkpos10= yy->__thunkpos;  if (!yymatchChar(yy, 'Z')) goto l11;  yyDo(yy, yy_1_timeoffset, yy->__begin, yy->__end);  goto l10;\n  l11:;\t  yy->__pos= yypos10; yy->__thunkpos= yythunkpos10;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l9;\n#undef yytext\n#undef yyleng\n  }  if (!yy_sign(yy)) goto l9;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l9;\n#undef yytext\n#undef yyleng\n  }  if (!yy_hour(yy)) goto l9;  yyDo(yy, yySet, -2, 0);  if (!yy_minute(yy)) goto l9;  yyDo(yy, yySet, -1, 0);  yyDo(yy, yy_2_timeoffset, yy->__begin, yy->__end);\n  }\n  l10:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"timeoffset\", yy->__buf+yy->__pos));  yyDo(yy, yyPop, 2, 0);\n  return 1;\n  l9:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"timeoffset\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_partialtime(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;  yyDo(yy, yyPush, 3, 0);\n  yyprintf((stderr, \"%s\\n\", \"partialtime\"));  if (!yy_hour(yy)) goto l12;  yyDo(yy, yySet, -3, 0);  if (!yymatchChar(yy, ':')) goto l12;  if (!yy_minute(yy)) goto l12;  yyDo(yy, yySet, -2, 0);  if (!yymatchChar(yy, ':')) goto l12;  if (!yy_second(yy)) goto l12;  yyDo(yy, yySet, -1, 0);\n  {  int yypos13= yy->__pos, yythunkpos13= yy->__thunkpos;  if (!yy_second_frac(yy)) goto l13;  goto l14;\n  l13:;\t  yy->__pos= yypos13; yy->__thunkpos= yythunkpos13;\n  }\n  l14:;\t  yyDo(yy, yy_1_partialtime, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"partialtime\", yy->__buf+yy->__pos));  yyDo(yy, yyPop, 3, 0);\n  return 1;\n  l12:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"partialtime\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_fulltime(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"fulltime\"));  if (!yy_partialtime(yy)) goto l15;  if (!yy_timeoffset(yy)) goto l15;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"fulltime\", yy->__buf+yy->__pos));\n  return 1;\n  l15:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"fulltime\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_day(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"day\"));\n  {  int yypos17= yy->__pos, yythunkpos17= yy->__thunkpos;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l18;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\006\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l18;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l18;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l18;\n#undef yytext\n#undef yyleng\n  }  goto l17;\n  l18:;\t  yy->__pos= yypos17; yy->__thunkpos= yythunkpos17;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l19;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchChar(yy, '0')) goto l19;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\376\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l19;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l19;\n#undef yytext\n#undef yyleng\n  }  goto l17;\n  l19:;\t  yy->__pos= yypos17; yy->__thunkpos= yythunkpos17;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l16;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchChar(yy, '3')) goto l16;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l16;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l16;\n#undef yytext\n#undef yyleng\n  }\n  }\n  l17:;\t  yyDo(yy, yy_1_day, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"day\", yy->__buf+yy->__pos));\n  return 1;\n  l16:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"day\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_month(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"month\"));\n  {  int yypos21= yy->__pos, yythunkpos21= yy->__thunkpos;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l22;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchChar(yy, '0')) goto l22;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\376\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l22;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l22;\n#undef yytext\n#undef yyleng\n  }  goto l21;\n  l22:;\t  yy->__pos= yypos21; yy->__thunkpos= yythunkpos21;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l20;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchChar(yy, '1')) goto l20;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\007\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l20;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l20;\n#undef yytext\n#undef yyleng\n  }\n  }\n  l21:;\t  yyDo(yy, yy_1_month, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"month\", yy->__buf+yy->__pos));\n  return 1;\n  l20:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"month\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_year(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"year\"));  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l23;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l23;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l23;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l23;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l23;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l23;\n#undef yytext\n#undef yyleng\n  }  yyDo(yy, yy_1_year, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"year\", yy->__buf+yy->__pos));\n  return 1;\n  l23:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"year\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_fulldate(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;  yyDo(yy, yyPush, 3, 0);\n  yyprintf((stderr, \"%s\\n\", \"fulldate\"));  if (!yy_year(yy)) goto l24;  yyDo(yy, yySet, -3, 0);  if (!yymatchChar(yy, '-')) goto l24;  if (!yy_month(yy)) goto l24;  yyDo(yy, yySet, -2, 0);  if (!yymatchChar(yy, '-')) goto l24;  if (!yy_day(yy)) goto l24;  yyDo(yy, yySet, -1, 0);  yyDo(yy, yy_1_fulldate, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"fulldate\", yy->__buf+yy->__pos));  yyDo(yy, yyPop, 3, 0);\n  return 1;\n  l24:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"fulldate\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_rfc3339(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"rfc3339\"));  if (!yy_fulldate(yy)) goto l25;  if (!yymatchChar(yy, 'T')) goto l25;  if (!yy_fulltime(yy)) goto l25;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"rfc3339\", yy->__buf+yy->__pos));\n  return 1;\n  l25:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"rfc3339\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_ts_quoted(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"ts_quoted\"));\n  {  int yypos27= yy->__pos, yythunkpos27= yy->__thunkpos;  if (!yymatchChar(yy, '\"')) goto l28;  if (!yy_rfc3339(yy)) goto l28;  if (!yymatchChar(yy, '\"')) goto l28;  goto l27;\n  l28:;\t  yy->__pos= yypos27; yy->__thunkpos= yythunkpos27;  if (!yymatchChar(yy, '\\'')) goto l26;  if (!yy_rfc3339(yy)) goto l26;  if (!yymatchChar(yy, '\\'')) goto l26;\n  }\n  l27:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"ts_quoted\", yy->__buf+yy->__pos));\n  return 1;\n  l26:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"ts_quoted\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_zero_to_255(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"zero_to_255\"));\n  {  int yypos30= yy->__pos, yythunkpos30= yy->__thunkpos;  if (!yymatchChar(yy, '2')) goto l31;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\077\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l31;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\077\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l31;  goto l30;\n  l31:;\t  yy->__pos= yypos30; yy->__thunkpos= yythunkpos30;  if (!yymatchChar(yy, '1')) goto l32;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l32;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l32;  goto l30;\n  l32:;\t  yy->__pos= yypos30; yy->__thunkpos= yythunkpos30;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\376\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l33;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l33;  goto l30;\n  l33:;\t  yy->__pos= yypos30; yy->__thunkpos= yythunkpos30;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l29;\n  }\n  l30:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"zero_to_255\", yy->__buf+yy->__pos));\n  return 1;\n  l29:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"zero_to_255\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_index(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"index\"));  if (!yymatchChar(yy, '[')) goto l34;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l34;\n#undef yytext\n#undef yyleng\n  }  if (!yy_zero_to_255(yy)) goto l34;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l34;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchChar(yy, ']')) goto l34;  yyDo(yy, yy_1_index, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"index\", yy->__buf+yy->__pos));\n  return 1;\n  l34:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"index\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_fields(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;  yyDo(yy, yyPush, 2, 0);\n  yyprintf((stderr, \"%s\\n\", \"fields\"));  if (!yymatchString(yy, \"Fields[\")) goto l35;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l35;\n#undef yytext\n#undef yyleng\n  }\n  l36:;\t\n  {  int yypos37= yy->__pos, yythunkpos37= yy->__thunkpos;  if (!yymatchClass(yy, (unsigned char *)\"\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\337\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\\377\")) goto l37;  goto l36;\n  l37:;\t  yy->__pos= yypos37; yy->__thunkpos= yythunkpos37;\n  }  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l35;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchChar(yy, ']')) goto l35;  yyDo(yy, yy_1_fields, yy->__begin, yy->__end);\n  {  int yypos38= yy->__pos, yythunkpos38= yy->__thunkpos;  if (!yy_index(yy)) goto l38;  yyDo(yy, yySet, -2, 0);  goto l39;\n  l38:;\t  yy->__pos= yypos38; yy->__thunkpos= yythunkpos38;\n  }\n  l39:;\t  yyDo(yy, yy_2_fields, yy->__begin, yy->__end);\n  {  int yypos40= yy->__pos, yythunkpos40= yy->__thunkpos;  if (!yy_index(yy)) goto l40;  yyDo(yy, yySet, -1, 0);  goto l41;\n  l40:;\t  yy->__pos= yypos40; yy->__thunkpos= yythunkpos40;\n  }\n  l41:;\t  yyDo(yy, yy_3_fields, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"fields\", yy->__buf+yy->__pos));  yyDo(yy, yyPop, 2, 0);\n  return 1;\n  l35:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"fields\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_exponent(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"exponent\"));  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\000\\000\\040\\000\\000\\000\\040\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l42;\n  {  int yypos43= yy->__pos, yythunkpos43= yy->__thunkpos;  if (!yy_sign(yy)) goto l43;  goto l44;\n  l43:;\t  yy->__pos= yypos43; yy->__thunkpos= yythunkpos43;\n  }\n  l44:;\t  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l42;\n  l45:;\t\n  {  int yypos46= yy->__pos, yythunkpos46= yy->__thunkpos;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l46;  goto l45;\n  l46:;\t  yy->__pos= yypos46; yy->__thunkpos= yythunkpos46;\n  }\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"exponent\", yy->__buf+yy->__pos));\n  return 1;\n  l42:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"exponent\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_decimal(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"decimal\"));  if (!yymatchChar(yy, '.')) goto l47;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l47;\n  l48:;\t\n  {  int yypos49= yy->__pos, yythunkpos49= yy->__thunkpos;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l49;  goto l48;\n  l49:;\t  yy->__pos= yypos49; yy->__thunkpos= yythunkpos49;\n  }\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"decimal\", yy->__buf+yy->__pos));\n  return 1;\n  l47:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"decimal\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_number(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"number\"));\n  {  int yypos51= yy->__pos, yythunkpos51= yy->__thunkpos;  if (!yymatchChar(yy, '0')) goto l52;  goto l51;\n  l52:;\t  yy->__pos= yypos51; yy->__thunkpos= yythunkpos51;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\376\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l50;\n  l53:;\t\n  {  int yypos54= yy->__pos, yythunkpos54= yy->__thunkpos;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\000\\377\\003\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l54;  goto l53;\n  l54:;\t  yy->__pos= yypos54; yy->__thunkpos= yythunkpos54;\n  }\n  }\n  l51:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"number\", yy->__buf+yy->__pos));\n  return 1;\n  l50:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"number\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_sign(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"sign\"));  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\000\\050\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l55;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"sign\", yy->__buf+yy->__pos));\n  return 1;\n  l55:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"sign\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_numeric_value(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"numeric_value\"));  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l56;\n#undef yytext\n#undef yyleng\n  }\n  {  int yypos57= yy->__pos, yythunkpos57= yy->__thunkpos;  if (!yy_sign(yy)) goto l57;  goto l58;\n  l57:;\t  yy->__pos= yypos57; yy->__thunkpos= yythunkpos57;\n  }\n  l58:;\t  if (!yy_number(yy)) goto l56;\n  {  int yypos59= yy->__pos, yythunkpos59= yy->__thunkpos;  if (!yy_decimal(yy)) goto l59;  goto l60;\n  l59:;\t  yy->__pos= yypos59; yy->__thunkpos= yythunkpos59;\n  }\n  l60:;\t\n  {  int yypos61= yy->__pos, yythunkpos61= yy->__thunkpos;  if (!yy_exponent(yy)) goto l61;  goto l62;\n  l61:;\t  yy->__pos= yypos61; yy->__thunkpos= yythunkpos61;\n  }\n  l62:;\t  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l56;\n#undef yytext\n#undef yyleng\n  }  yyDo(yy, yy_1_numeric_value, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"numeric_value\", yy->__buf+yy->__pos));\n  return 1;\n  l56:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"numeric_value\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_string_match_mod(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"string_match_mod\"));  if (!yymatchChar(yy, '%')) goto l63;  yyDo(yy, yy_1_string_match_mod, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"string_match_mod\", yy->__buf+yy->__pos));\n  return 1;\n  l63:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"string_match_mod\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_nil(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"nil\"));  if (!yymatchString(yy, \"NIL\")) goto l64;  yyDo(yy, yy_1_nil, yy->__begin, yy->__end);  if (!yy_sp(yy)) goto l64;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"nil\", yy->__buf+yy->__pos));\n  return 1;\n  l64:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"nil\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_string_match(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"string_match\"));\n  {  int yypos66= yy->__pos, yythunkpos66= yy->__thunkpos;  if (!yy_op_seq(yy)) goto l67;  goto l66;\n  l67:;\t  yy->__pos= yypos66; yy->__thunkpos= yythunkpos66;  if (!yy_op_sne(yy)) goto l65;\n  }\n  l66:;\t  if (!yy_sp(yy)) goto l65;  if (!yy_string_value(yy)) goto l65;\n  {  int yypos68= yy->__pos, yythunkpos68= yy->__thunkpos;  if (!yy_string_match_mod(yy)) goto l68;  goto l69;\n  l68:;\t  yy->__pos= yypos68; yy->__thunkpos= yythunkpos68;\n  }\n  l69:;\t  yyDo(yy, yy_1_string_match, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"string_match\", yy->__buf+yy->__pos));\n  return 1;\n  l65:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"string_match\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_string_value(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"string_value\"));\n  {  int yypos71= yy->__pos, yythunkpos71= yy->__thunkpos;  if (!yymatchChar(yy, '\"')) goto l72;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l72;\n#undef yytext\n#undef yyleng\n  }\n  l73:;\t\n  {  int yypos74= yy->__pos, yythunkpos74= yy->__thunkpos;\n  {  int yypos75= yy->__pos, yythunkpos75= yy->__thunkpos;  if (!yymatchChar(yy, '\\\\')) goto l76;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\004\\000\\000\\000\\000\\000\\000\\020\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l76;  goto l75;\n  l76:;\t  yy->__pos= yypos75; yy->__thunkpos= yythunkpos75;\n  {  int yypos77= yy->__pos, yythunkpos77= yy->__thunkpos;  if (!yymatchChar(yy, '\"')) goto l77;  goto l74;\n  l77:;\t  yy->__pos= yypos77; yy->__thunkpos= yythunkpos77;\n  }  if (!yymatchDot(yy)) goto l74;\n  }\n  l75:;\t  goto l73;\n  l74:;\t  yy->__pos= yypos74; yy->__thunkpos= yythunkpos74;\n  }  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l72;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchChar(yy, '\"')) goto l72;  goto l71;\n  l72:;\t  yy->__pos= yypos71; yy->__thunkpos= yythunkpos71;  if (!yymatchChar(yy, '\\'')) goto l70;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_BEGIN)) goto l70;\n#undef yytext\n#undef yyleng\n  }\n  l78:;\t\n  {  int yypos79= yy->__pos, yythunkpos79= yy->__thunkpos;\n  {  int yypos80= yy->__pos, yythunkpos80= yy->__thunkpos;  if (!yymatchChar(yy, '\\\\')) goto l81;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\000\\000\\000\\200\\000\\000\\000\\000\\000\\000\\020\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l81;  goto l80;\n  l81:;\t  yy->__pos= yypos80; yy->__thunkpos= yythunkpos80;\n  {  int yypos82= yy->__pos, yythunkpos82= yy->__thunkpos;  if (!yymatchChar(yy, '\\'')) goto l82;  goto l79;\n  l82:;\t  yy->__pos= yypos82; yy->__thunkpos= yythunkpos82;\n  }  if (!yymatchDot(yy)) goto l79;\n  }\n  l80:;\t  goto l78;\n  l79:;\t  yy->__pos= yypos79; yy->__thunkpos= yythunkpos79;\n  }  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(YY_END)) goto l70;\n#undef yytext\n#undef yyleng\n  }  if (!yymatchChar(yy, '\\'')) goto l70;\n  }\n  l71:;\t  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(check_string_len(yytext))) goto l70;\n#undef yytext\n#undef yyleng\n  }  yyDo(yy, yy_1_string_value, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"string_value\", yy->__buf+yy->__pos));\n  return 1;\n  l70:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"string_value\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_string_headers(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"string_headers\"));\n  {  int yypos84= yy->__pos, yythunkpos84= yy->__thunkpos;  if (!yymatchString(yy, \"Type\")) goto l85;  yyDo(yy, yy_1_string_headers, yy->__begin, yy->__end);  goto l84;\n  l85:;\t  yy->__pos= yypos84; yy->__thunkpos= yythunkpos84;  if (!yymatchString(yy, \"Logger\")) goto l86;  yyDo(yy, yy_2_string_headers, yy->__begin, yy->__end);  goto l84;\n  l86:;\t  yy->__pos= yypos84; yy->__thunkpos= yythunkpos84;  if (!yymatchString(yy, \"Hostname\")) goto l87;  yyDo(yy, yy_3_string_headers, yy->__begin, yy->__end);  goto l84;\n  l87:;\t  yy->__pos= yypos84; yy->__thunkpos= yythunkpos84;  if (!yymatchString(yy, \"EnvVersion\")) goto l88;  yyDo(yy, yy_4_string_headers, yy->__begin, yy->__end);  goto l84;\n  l88:;\t  yy->__pos= yypos84; yy->__thunkpos= yythunkpos84;  if (!yymatchString(yy, \"Payload\")) goto l83;  yyDo(yy, yy_5_string_headers, yy->__begin, yy->__end);\n  }\n  l84:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"string_headers\", yy->__buf+yy->__pos));\n  return 1;\n  l83:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"string_headers\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_boolean(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"boolean\"));\n  {  int yypos90= yy->__pos, yythunkpos90= yy->__thunkpos;  if (!yy_true(yy)) goto l91;  yyDo(yy, yy_1_boolean, yy->__begin, yy->__end);  goto l90;\n  l91:;\t  yy->__pos= yypos90; yy->__thunkpos= yythunkpos90;  if (!yy_false(yy)) goto l89;  yyDo(yy, yy_2_boolean, yy->__begin, yy->__end);\n  }\n  l90:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"boolean\", yy->__buf+yy->__pos));\n  return 1;\n  l89:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"boolean\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_false(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"false\"));  if (!yymatchString(yy, \"FALSE\")) goto l92;  if (!yy_sp(yy)) goto l92;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"false\", yy->__buf+yy->__pos));\n  return 1;\n  l92:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"false\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_true(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"true\"));  if (!yymatchString(yy, \"TRUE\")) goto l93;  if (!yy_sp(yy)) goto l93;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"true\", yy->__buf+yy->__pos));\n  return 1;\n  l93:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"true\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_relational(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"relational\"));\n  {  int yypos95= yy->__pos, yythunkpos95= yy->__thunkpos;  if (!yy_op_eq(yy)) goto l96;  goto l95;\n  l96:;\t  yy->__pos= yypos95; yy->__thunkpos= yythunkpos95;  if (!yy_op_ne(yy)) goto l97;  goto l95;\n  l97:;\t  yy->__pos= yypos95; yy->__thunkpos= yythunkpos95;  if (!yy_op_gte(yy)) goto l98;  goto l95;\n  l98:;\t  yy->__pos= yypos95; yy->__thunkpos= yythunkpos95;  if (!yy_op_gt(yy)) goto l99;  goto l95;\n  l99:;\t  yy->__pos= yypos95; yy->__thunkpos= yythunkpos95;  if (!yy_op_lte(yy)) goto l100;  goto l95;\n  l100:;\t  yy->__pos= yypos95; yy->__thunkpos= yythunkpos95;  if (!yy_op_lt(yy)) goto l94;\n  }\n  l95:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"relational\", yy->__buf+yy->__pos));\n  return 1;\n  l94:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"relational\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_op_lt(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"op_lt\"));  if (!yymatchChar(yy, '<')) goto l101;  if (!yy_sp(yy)) goto l101;  yyDo(yy, yy_1_op_lt, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"op_lt\", yy->__buf+yy->__pos));\n  return 1;\n  l101:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"op_lt\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_op_lte(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"op_lte\"));  if (!yymatchString(yy, \"<=\")) goto l102;  if (!yy_sp(yy)) goto l102;  yyDo(yy, yy_1_op_lte, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"op_lte\", yy->__buf+yy->__pos));\n  return 1;\n  l102:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"op_lte\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_op_gt(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"op_gt\"));  if (!yymatchChar(yy, '>')) goto l103;  if (!yy_sp(yy)) goto l103;  yyDo(yy, yy_1_op_gt, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"op_gt\", yy->__buf+yy->__pos));\n  return 1;\n  l103:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"op_gt\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_op_gte(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"op_gte\"));  if (!yymatchString(yy, \">=\")) goto l104;  if (!yy_sp(yy)) goto l104;  yyDo(yy, yy_1_op_gte, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"op_gte\", yy->__buf+yy->__pos));\n  return 1;\n  l104:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"op_gte\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_op_sne(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"op_sne\"));  if (!yymatchString(yy, \"!~\")) goto l105;  if (!yy_sp(yy)) goto l105;  yyDo(yy, yy_1_op_sne, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"op_sne\", yy->__buf+yy->__pos));\n  return 1;\n  l105:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"op_sne\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_op_seq(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"op_seq\"));  if (!yymatchString(yy, \"=~\")) goto l106;  if (!yy_sp(yy)) goto l106;  yyDo(yy, yy_1_op_seq, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"op_seq\", yy->__buf+yy->__pos));\n  return 1;\n  l106:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"op_seq\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_op_ne(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"op_ne\"));  if (!yymatchString(yy, \"!=\")) goto l107;  if (!yy_sp(yy)) goto l107;  yyDo(yy, yy_1_op_ne, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"op_ne\", yy->__buf+yy->__pos));\n  return 1;\n  l107:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"op_ne\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_op_eq(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"op_eq\"));  if (!yymatchString(yy, \"==\")) goto l108;  if (!yy_sp(yy)) goto l108;  yyDo(yy, yy_1_op_eq, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"op_eq\", yy->__buf+yy->__pos));\n  return 1;\n  l108:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"op_eq\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_boolean_test(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"boolean_test\"));\n  {  int yypos110= yy->__pos, yythunkpos110= yy->__thunkpos;  if (!yy_true(yy)) goto l111;  yyDo(yy, yy_1_boolean_test, yy->__begin, yy->__end);  goto l110;\n  l111:;\t  yy->__pos= yypos110; yy->__thunkpos= yythunkpos110;  if (!yy_false(yy)) goto l109;  yyDo(yy, yy_2_boolean_test, yy->__begin, yy->__end);\n  }\n  l110:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"boolean_test\", yy->__buf+yy->__pos));\n  return 1;\n  l109:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"boolean_test\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_field_test(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"field_test\"));  if (!yy_fields(yy)) goto l112;  if (!yy_sp(yy)) goto l112;\n  {  int yypos113= yy->__pos, yythunkpos113= yy->__thunkpos;  if (!yy_relational(yy)) goto l114;  if (!yy_sp(yy)) goto l114;\n  {  int yypos115= yy->__pos, yythunkpos115= yy->__thunkpos;  if (!yy_string_value(yy)) goto l116;  goto l115;\n  l116:;\t  yy->__pos= yypos115; yy->__thunkpos= yythunkpos115;  if (!yy_numeric_value(yy)) goto l114;\n  }\n  l115:;\t  goto l113;\n  l114:;\t  yy->__pos= yypos113; yy->__thunkpos= yythunkpos113;  if (!yy_string_match(yy)) goto l117;  goto l113;\n  l117:;\t  yy->__pos= yypos113; yy->__thunkpos= yythunkpos113;\n  {  int yypos118= yy->__pos, yythunkpos118= yy->__thunkpos;  if (!yy_op_eq(yy)) goto l119;  goto l118;\n  l119:;\t  yy->__pos= yypos118; yy->__thunkpos= yythunkpos118;  if (!yy_op_ne(yy)) goto l112;\n  }\n  l118:;\t  if (!yy_sp(yy)) goto l112;\n  {  int yypos120= yy->__pos, yythunkpos120= yy->__thunkpos;  if (!yy_boolean(yy)) goto l121;  goto l120;\n  l121:;\t  yy->__pos= yypos120; yy->__thunkpos= yythunkpos120;  if (!yy_nil(yy)) goto l112;\n  }\n  l120:;\t\n  }\n  l113:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"field_test\", yy->__buf+yy->__pos));\n  return 1;\n  l112:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"field_test\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_pid(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"pid\"));  if (!yymatchString(yy, \"Pid\")) goto l122;  yyDo(yy, yy_1_pid, yy->__begin, yy->__end);  if (!yy_sp(yy)) goto l122;\n  {  int yypos123= yy->__pos, yythunkpos123= yy->__thunkpos;  if (!yy_relational(yy)) goto l124;  if (!yy_sp(yy)) goto l124;  if (!yy_numeric_value(yy)) goto l124;  goto l123;\n  l124:;\t  yy->__pos= yypos123; yy->__thunkpos= yythunkpos123;\n  {  int yypos125= yy->__pos, yythunkpos125= yy->__thunkpos;  if (!yy_op_eq(yy)) goto l126;  goto l125;\n  l126:;\t  yy->__pos= yypos125; yy->__thunkpos= yythunkpos125;  if (!yy_op_ne(yy)) goto l122;\n  }\n  l125:;\t  if (!yy_sp(yy)) goto l122;  if (!yy_nil(yy)) goto l122;\n  }\n  l123:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"pid\", yy->__buf+yy->__pos));\n  return 1;\n  l122:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"pid\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_severity(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"severity\"));  if (!yymatchString(yy, \"Severity\")) goto l127;  yyDo(yy, yy_1_severity, yy->__begin, yy->__end);  if (!yy_sp(yy)) goto l127;  if (!yy_relational(yy)) goto l127;  if (!yy_sp(yy)) goto l127;  if (!yy_numeric_value(yy)) goto l127;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"severity\", yy->__buf+yy->__pos));\n  return 1;\n  l127:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"severity\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_optional_string_headers(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"optional_string_headers\"));  if (!yy_string_headers(yy)) goto l128;  if (!yy_sp(yy)) goto l128;\n  {  int yypos129= yy->__pos, yythunkpos129= yy->__thunkpos;  if (!yy_relational(yy)) goto l130;  if (!yy_sp(yy)) goto l130;  if (!yy_string_value(yy)) goto l130;  goto l129;\n  l130:;\t  yy->__pos= yypos129; yy->__thunkpos= yythunkpos129;  if (!yy_string_match(yy)) goto l131;  goto l129;\n  l131:;\t  yy->__pos= yypos129; yy->__thunkpos= yythunkpos129;\n  {  int yypos132= yy->__pos, yythunkpos132= yy->__thunkpos;  if (!yy_op_eq(yy)) goto l133;  goto l132;\n  l133:;\t  yy->__pos= yypos132; yy->__thunkpos= yythunkpos132;  if (!yy_op_ne(yy)) goto l128;\n  }\n  l132:;\t  if (!yy_sp(yy)) goto l128;  if (!yy_nil(yy)) goto l128;\n  }\n  l129:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"optional_string_headers\", yy->__buf+yy->__pos));\n  return 1;\n  l128:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"optional_string_headers\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_timestamp(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"timestamp\"));  if (!yymatchString(yy, \"Timestamp\")) goto l134;  if (!yy_sp(yy)) goto l134;  if (!yy_relational(yy)) goto l134;  if (!yy_sp(yy)) goto l134;\n  {  int yypos135= yy->__pos, yythunkpos135= yy->__thunkpos;  if (!yy_numeric_value(yy)) goto l136;  goto l135;\n  l136:;\t  yy->__pos= yypos135; yy->__thunkpos= yythunkpos135;  if (!yy_ts_quoted(yy)) goto l134;\n  }\n  l135:;\t  yyDo(yy, yy_1_timestamp, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"timestamp\", yy->__buf+yy->__pos));\n  return 1;\n  l134:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"timestamp\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_uuid(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"uuid\"));  if (!yymatchString(yy, \"Uuid\")) goto l137;  yyDo(yy, yy_1_uuid, yy->__begin, yy->__end);  if (!yy_sp(yy)) goto l137;\n  {  int yypos138= yy->__pos, yythunkpos138= yy->__thunkpos;  if (!yy_relational(yy)) goto l139;  if (!yy_sp(yy)) goto l139;  if (!yy_string_value(yy)) goto l139;  goto l138;\n  l139:;\t  yy->__pos= yypos138; yy->__thunkpos= yythunkpos138;  if (!yy_string_match(yy)) goto l137;\n  }\n  l138:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"uuid\", yy->__buf+yy->__pos));\n  return 1;\n  l137:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"uuid\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_close(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"close\"));  if (!yymatchChar(yy, ')')) goto l140;  yyDo(yy, yy_1_close, yy->__begin, yy->__end);  if (!yy_sp(yy)) goto l140;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"close\", yy->__buf+yy->__pos));\n  return 1;\n  l140:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"close\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_open(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"open\"));  if (!yymatchChar(yy, '(')) goto l141;  yyDo(yy, yy_1_open, yy->__begin, yy->__end);  if (!yy_sp(yy)) goto l141;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"open\", yy->__buf+yy->__pos));\n  return 1;\n  l141:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"open\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_test(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"test\"));\n  {  int yypos143= yy->__pos, yythunkpos143= yy->__thunkpos;  if (!yy_uuid(yy)) goto l144;  goto l143;\n  l144:;\t  yy->__pos= yypos143; yy->__thunkpos= yythunkpos143;  if (!yy_timestamp(yy)) goto l145;  goto l143;\n  l145:;\t  yy->__pos= yypos143; yy->__thunkpos= yythunkpos143;  if (!yy_optional_string_headers(yy)) goto l146;  goto l143;\n  l146:;\t  yy->__pos= yypos143; yy->__thunkpos= yythunkpos143;  if (!yy_severity(yy)) goto l147;  goto l143;\n  l147:;\t  yy->__pos= yypos143; yy->__thunkpos= yythunkpos143;  if (!yy_pid(yy)) goto l148;  goto l143;\n  l148:;\t  yy->__pos= yypos143; yy->__thunkpos= yythunkpos143;  if (!yy_field_test(yy)) goto l149;  goto l143;\n  l149:;\t  yy->__pos= yypos143; yy->__thunkpos= yythunkpos143;  if (!yy_boolean_test(yy)) goto l142;\n  }\n  l143:;\t  yyDo(yy, yy_1_test, yy->__begin, yy->__end);  if (!yy_sp(yy)) goto l142;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"test\", yy->__buf+yy->__pos));\n  return 1;\n  l142:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"test\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_and(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"and\"));  if (!yymatchString(yy, \"&&\")) goto l150;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(cond_cnt(&yy->ctx))) goto l150;\n#undef yytext\n#undef yyleng\n  }  yyDo(yy, yy_1_and, yy->__begin, yy->__end);  if (!yy_sp(yy)) goto l150;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"and\", yy->__buf+yy->__pos));\n  return 1;\n  l150:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"and\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_expr(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"expr\"));\n  {  int yypos152= yy->__pos, yythunkpos152= yy->__thunkpos;  if (!yy_test(yy)) goto l153;  goto l152;\n  l153:;\t  yy->__pos= yypos152; yy->__thunkpos= yythunkpos152;  if (!yy_open(yy)) goto l151;  if (!yy_ored(yy)) goto l151;  if (!yy_close(yy)) goto l151;\n  }\n  l152:;\t\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"expr\", yy->__buf+yy->__pos));\n  return 1;\n  l151:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"expr\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_or(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"or\"));  if (!yymatchString(yy, \"||\")) goto l154;  yyText(yy, yy->__begin, yy->__end);  {\n#define yytext yy->__text\n#define yyleng yy->__textlen\nif (!(cond_cnt(&yy->ctx))) goto l154;\n#undef yytext\n#undef yyleng\n  }  yyDo(yy, yy_1_or, yy->__begin, yy->__end);  if (!yy_sp(yy)) goto l154;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"or\", yy->__buf+yy->__pos));\n  return 1;\n  l154:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"or\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_anded(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"anded\"));  if (!yy_expr(yy)) goto l155;\n  l156:;\t\n  {  int yypos157= yy->__pos, yythunkpos157= yy->__thunkpos;  if (!yy_and(yy)) goto l157;  if (!yy_expr(yy)) goto l157;  goto l156;\n  l157:;\t  yy->__pos= yypos157; yy->__thunkpos= yythunkpos157;\n  }  if (!yy_sp(yy)) goto l155;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"anded\", yy->__buf+yy->__pos));\n  return 1;\n  l155:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"anded\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_eol(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"eol\"));\n  {  int yypos159= yy->__pos, yythunkpos159= yy->__thunkpos;  if (!yymatchDot(yy)) goto l159;  goto l158;\n  l159:;\t  yy->__pos= yypos159; yy->__thunkpos= yythunkpos159;\n  }\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"eol\", yy->__buf+yy->__pos));\n  return 1;\n  l158:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"eol\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_ored(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"ored\"));  if (!yy_anded(yy)) goto l160;\n  l161:;\t\n  {  int yypos162= yy->__pos, yythunkpos162= yy->__thunkpos;  if (!yy_or(yy)) goto l162;  if (!yy_anded(yy)) goto l162;  goto l161;\n  l162:;\t  yy->__pos= yypos162; yy->__thunkpos= yythunkpos162;\n  }  if (!yy_sp(yy)) goto l160;\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"ored\", yy->__buf+yy->__pos));\n  return 1;\n  l160:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"ored\", yy->__buf+yy->__pos));\n  return 0;\n}\nYY_RULE(int) yy_sp(yycontext *yy)\n{\n  yyprintf((stderr, \"%s\\n\", \"sp\"));\n  l164:;\t\n  {  int yypos165= yy->__pos, yythunkpos165= yy->__thunkpos;  if (!yymatchClass(yy, (unsigned char *)\"\\000\\046\\000\\000\\001\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\\000\")) goto l165;  goto l164;\n  l165:;\t  yy->__pos= yypos165; yy->__thunkpos= yythunkpos165;\n  }\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"sp\", yy->__buf+yy->__pos));\n  return 1;\n}\nYY_RULE(int) yy_match(yycontext *yy)\n{  int yypos0= yy->__pos, yythunkpos0= yy->__thunkpos;\n  yyprintf((stderr, \"%s\\n\", \"match\"));  if (!yy_sp(yy)) goto l166;  if (!yy_ored(yy)) goto l166;  if (!yy_eol(yy)) goto l166;  yyDo(yy, yy_1_match, yy->__begin, yy->__end);\n  yyprintf((stderr, \"  ok   %s @ %s\\n\", \"match\", yy->__buf+yy->__pos));\n  return 1;\n  l166:;\t  yy->__pos= yypos0; yy->__thunkpos= yythunkpos0;\n  yyprintf((stderr, \"  fail %s @ %s\\n\", \"match\", yy->__buf+yy->__pos));\n  return 0;\n}\n\n#ifndef YY_PART\n\ntypedef int (*yyrule)(yycontext *yy);\n\nYY_PARSE(int) YYPARSEFROM(YY_CTX_PARAM_ yyrule yystart)\n{\n  int yyok;\n  if (!yyctx->__buflen)\n    {\n      yyctx->__buflen= YY_BUFFER_SIZE;\n      yyctx->__buf= (char *)YY_MALLOC(yyctx, yyctx->__buflen);\n      yyctx->__textlen= YY_BUFFER_SIZE;\n      yyctx->__text= (char *)YY_MALLOC(yyctx, yyctx->__textlen);\n      yyctx->__thunkslen= YY_STACK_SIZE;\n      yyctx->__thunks= (yythunk *)YY_MALLOC(yyctx, sizeof(yythunk) * yyctx->__thunkslen);\n      yyctx->__valslen= YY_STACK_SIZE;\n      yyctx->__vals= (YYSTYPE *)YY_MALLOC(yyctx, sizeof(YYSTYPE) * yyctx->__valslen);\n      memset(yyctx->__vals, 0, sizeof(YYSTYPE) * yyctx->__valslen);\n      yyctx->__begin= yyctx->__end= yyctx->__pos= yyctx->__limit= yyctx->__thunkpos= 0;\n    }\n  yyctx->__begin= yyctx->__end= yyctx->__pos;\n  yyctx->__thunkpos= 0;\n  yyctx->__val= yyctx->__vals;\n  yyok= yystart(yyctx);\n  if (yyok) yyDone(yyctx);\n  yyCommit(yyctx);\n  return yyok;\n}\n\nYY_PARSE(int) YYPARSE(YY_CTX_PARAM)\n{\n  return YYPARSEFROM(YY_CTX_ARG_ yy_match);\n}\n\nYY_PARSE(yycontext *) YYRELEASE(yycontext *yyctx)\n{\n  if (yyctx->__buflen)\n    {\n      yyctx->__buflen= 0;\n      YY_FREE(yyctx, yyctx->__buf);\n      YY_FREE(yyctx, yyctx->__text);\n      YY_FREE(yyctx, yyctx->__thunks);\n      YY_FREE(yyctx, yyctx->__vals);\n    }\n  return yyctx;\n}\n\n#endif\n#line 385 \"../src/util/heka_message_matcher_parser.leg\"\n\n\nstatic match_node* copy_node(unsigned char parent, match_node *mn,\n                             match_node_tmp *mnt)\n{\n  mn->op        = mnt->op;\n  mn->val_len   = 0;\n  mn->var_len   = 0;\n  mn->field_id  = mnt->id;\n  mn->val_mod   = mnt->val_mod;\n  mn->val_type  = mnt->val_type;\n\n  if (mn->op == OP_AND || mn->op == OP_OR) {\n    mn->u.off = parent;\n  } else {\n    mn->u.idx.f = mnt->fi;\n    mn->u.idx.a = mnt->ai;\n  }\n\n  if (mnt->id == LSB_PB_FIELDS) {\n    mn->var_len = mnt->var_len;\n  }\n  if (mn->var_len) {\n    memcpy(mn->data, mnt->var, mn->var_len); // no NUL terminator\n    free(mnt->var);\n    mnt->var = NULL;\n    mnt->var_len = 0;\n  }\n\n  size_t val_len = 0;\n  switch (mnt->val_type) {\n  case TYPE_STRING:\n    val_len = mnt->val_len + 1;\n    memcpy(mn->data + mn->var_len, mnt->val.s, val_len);\n    free(mnt->val.s);\n    mnt->val.s = NULL;\n    mnt->val_len = 0;\n    break;\n  case TYPE_NUMERIC:\n    val_len = sizeof(double);\n    memcpy(mn->data + mn->var_len, &mnt->val.d, val_len);\n    break;\n  default:\n    break;\n  }\n\n  mn->units = 1 + ((sizeof(match_node) - 1 + mn->var_len + val_len)\n                   / sizeof(match_node));\n  if (val_len && mnt->val_type == TYPE_STRING) {\n    mn->val_len = val_len - 1;\n  } else {\n    mn->val_len = val_len;\n  }\n  return mn + mn->units;\n}\n\n\nstatic match_node* inorder_traverse(unsigned char parent, match_node **offsets,\n                                    match_node *mn, match_node_tmp *root,\n                                    match_node_tmp *mnt)\n{\n  if (mnt->id == 0 && (mnt->op == OP_AND || mnt->op == OP_OR)) {\n    unsigned char idx = mnt->val_len;\n    mnt->val_len = 0;\n    mn = inorder_traverse(idx, offsets, mn, root, root + mnt->fi);\n    offsets[idx] = mn;\n    mn = copy_node(parent, mn, mnt);\n  } else {\n    mn = copy_node(parent, mn, mnt);\n  }\n  if (mnt->id == 0 && (mnt->op == OP_AND || mnt->op == OP_OR)) {\n    mn = inorder_traverse(parent, offsets, mn, root, root + mnt->ai);\n  }\n  return mn;\n}\n\n\nstatic size_t get_matcher_bytes(match_node_tmp nodes[], size_t size)\n{\n  size_t len = 0;\n  for (unsigned i = 0; i < size; ++i) {\n    size_t val_len = 0;\n    switch (nodes[i].val_type) {\n    case TYPE_STRING:\n      val_len = nodes[i].val_len + 1;\n      break;\n    case TYPE_NUMERIC:\n      val_len = sizeof(double);\n      break;\n    default:\n      break;\n    }\n\n    size_t var_len = 0;\n    if (nodes[i].id == LSB_PB_FIELDS) {\n      var_len = nodes[i].var_len;\n    }\n\n    len += (sizeof(match_node) * 2 + val_len + var_len - 1)\n      / sizeof(match_node) * sizeof(match_node);\n\n    if (nodes[i].op == OP_OR || nodes[i].op == OP_AND) {\n      // squirrel away the position for the short-circuit calculation\n      nodes[i].val_len = i;\n    }\n  }\n  return len;\n}\n\n\nstatic void make_tree(match_node_tmp nodes[], size_t size)\n{\n  // turn the postfix stack into a traversable tree\n  match_node_tmp *stack[size];\n  memset(stack, 0, sizeof(stack));\n  int top = 0;\n  for (unsigned i = 0; i < size; ++i) {\n    if (nodes[i].op != OP_AND && nodes[i].op != OP_OR) {\n      stack[top++] = &nodes[i];\n    } else {\n      nodes[i].ai = stack[--top] - nodes;\n      nodes[i].fi = stack[--top] - nodes;\n      stack[top++] = &nodes[i];\n    }\n  }\n}\n\n\nstatic lsb_message_matcher* make_matcher(match_node_tmp nodes[], size_t size)\n{\n  lsb_message_matcher *mm = malloc(sizeof(lsb_message_matcher));\n  if (!mm) { return NULL; }\n\n  mm->bytes = get_matcher_bytes(nodes, size);\n  mm->nodes = calloc(mm->bytes, 1);\n  if (!mm->nodes) {\n    free(mm);\n    return NULL;\n  }\n\n  match_node *offsets[size];\n  memset(offsets, 0, sizeof(offsets));\n\n  inorder_traverse(size, offsets, mm->nodes, nodes, nodes + (size - 1));\n\n  // populate the short-circuit offsets\n  match_node *e = mm->nodes + (mm->bytes / sizeof(match_node));\n  for (match_node *p = mm->nodes; p < e;){\n    if (p->op == OP_AND || p->op == OP_OR) {\n      if (p->u.off < size) {\n        p->u.off = offsets[p->u.off] - mm->nodes;\n      } else {\n        p->u.off =  mm->bytes / sizeof(match_node);\n      }\n    }\n    p += p->units;\n  }\n  return mm;\n}\n\n\nlsb_message_matcher* lsb_create_message_matcher(const char *exp)\n{\n  if (!exp) { return NULL; }\n\n  lsb_message_matcher *mm = NULL;\n  yycontext yy;\n  memset(&yy, 0, sizeof(yy));\n  yy.ctx.is.s = exp;\n  yy.ctx.is.size = strlen(exp);\n  int ret = yyparse(&yy);\n  if (ret) {\n    make_tree(yy.ctx.out.a, yy.ctx.out.pos);\n    mm = make_matcher(yy.ctx.out.a, yy.ctx.out.pos);\n  }\n  free(yy.ctx.out.a);\n  free(yy.ctx.ops.a);\n  yyrelease(&yy);\n  return mm;\n}\n\n"
  },
  {
    "path": "src/util/heka_message_matcher_parser.leg",
    "content": "%{\n/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Hindsight message matcher parser @file */\n\n#include <limits.h>\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n#include \"heka_message_matcher_impl.h\"\n#include \"luasandbox/util/heka_message.h\"\n#include \"luasandbox/util/heka_message_matcher.h\"\n\n#ifndef _MSC_VER\n#pragma GCC diagnostic ignored \"-Wunused-parameter\"\n#pragma GCC diagnostic ignored \"-Wunused-function\"\n#else\n#pragma warning( disable : 4267 4244 )\n#endif\n\ntypedef struct match_node_tmp {\n  uint8_t id;\n  uint8_t op;\n  uint8_t val_mod;\n  uint8_t val_type;\n  uint8_t val_len;\n  uint8_t var_len;\n  uint8_t fi; // left node index for logical op\n  uint8_t ai; // right node index for logical op\n  char          *var;\n\n  union {\n    char    *s;\n    double  d;\n  } val;\n} match_node_tmp;\n\n\ntypedef struct match_node_array {\n  match_node_tmp *a;\n  int            pos;\n  int            size;\n} match_node_array;\n\n\ntypedef struct input_string {\n  const char *s;\n  size_t     pos;\n  size_t     size;\n} input_string;\n\n\ntypedef struct context {\n  match_node_array  out;\n  match_node_array  ops;\n  match_node_tmp    mn;\n  struct tm         tms;\n  int               cond_cnt;\n  input_string      is;\n} context;\n\n\n#define YY_PARSE(T) static T\n#define YY_CTX_LOCAL 1\n#define YY_CTX_MEMBERS \\\n   context ctx;\n\n#define YY_INPUT(yy, buf, result, max_size)                                    \\\n{                                                                              \\\n  input_string *is = &yy->ctx.is;                                              \\\n  result = is->size - is->pos;                                                 \\\n  if (result > 0) {                                                            \\\n    if (max_size >= result) {                                                  \\\n      memcpy(buf, &is->s[is->pos], result);                                    \\\n      is->pos += result;                                                       \\\n    } else {                                                                   \\\n      memcpy(buf, &is->s[is->pos], max_size);                                  \\\n      is->pos += max_size;                                                     \\\n      result = max_size;                                                       \\\n    }                                                                          \\\n  }                                                                            \\\n}\n\n\nstatic void init_match_node(match_node_tmp *mn)\n{\n  memset(mn, 0, sizeof(match_node_tmp));\n}\n\n\nstatic void move_match_node(match_node_tmp *dest, match_node_tmp *src)\n{\n  memcpy(dest, src, sizeof(match_node_tmp));\n  init_match_node(src); // dest now owns the memory, wipe the pointers\n}\n\n\nstatic void realloc_mna(match_node_array *mna)\n{\n  size_t bytes = sizeof(match_node_tmp) * ++mna->size;\n  match_node_tmp *tmp = realloc(mna->a, bytes);\n  if (tmp) {\n    mna->a = tmp;\n    init_match_node(&mna->a[mna->size - 1]);\n  } else {\n    fprintf(stderr, \"realloc failed\\n\");\n    exit(1);\n  }\n}\n\n\nstatic void push_output(context *ctx, match_node_tmp *mn)\n{\n  if (!ctx->out.a || ctx->out.pos == ctx->out.size) {\n    realloc_mna(&ctx->out);\n  }\n  move_match_node(&ctx->out.a[ctx->out.pos++], mn);\n}\n\n\nstatic void push_op(context *ctx, match_operation op)\n{\n  if (!ctx->ops.a) {\n    realloc_mna(&ctx->ops);\n    ctx->ops.a[ctx->ops.pos++].op = op;\n    return;\n  }\n\n  if (op == OP_OPEN || op > ctx->ops.a[ctx->ops.pos - 1].op) {\n    if (ctx->ops.pos == ctx->ops.size) {\n      realloc_mna(&ctx->ops);\n    }\n    ctx->ops.a[ctx->ops.pos++].op = op;\n  } else {\n    push_output(ctx, &ctx->ops.a[ctx->ops.pos - 1]);\n    ctx->ops.a[ctx->ops.pos - 1].op = op;\n  }\n}\n\n\nstatic void pop_to_paren(context *ctx)\n{\n  for (; ctx->ops.pos > 0; --ctx->ops.pos) {\n    match_node_tmp *op = &ctx->ops.a[ctx->ops.pos - 1];\n    if (op->op == OP_OPEN) break;\n    push_output(ctx, op);\n  }\n}\n\n\nstatic void pop_all_ops(context *ctx)\n{\n  for (; ctx->ops.pos > 0; --ctx->ops.pos) {\n    match_node_tmp *op = &ctx->ops.a[ctx->ops.pos - 1];\n    if (op->op == OP_OPEN) continue;\n    push_output(ctx, op);\n  }\n}\n\n\nstatic void update_date(context *ctx, int year, int mon, int day)\n{\n  ctx->tms.tm_isdst = -1;\n  ctx->tms.tm_year  = year - 1900;\n  ctx->tms.tm_mon   = mon - 1;\n  ctx->tms.tm_mday  = day;\n}\n\n\nstatic void update_time(context *ctx, int hour, int minute, int sec)\n{\n  ctx->tms.tm_hour  = hour;\n  ctx->tms.tm_min   = minute;\n  ctx->tms.tm_sec   = sec;\n}\n\n\nstatic void update_offset(context *ctx, char sign, int hour, int minute)\n{\n  ctx->mn.val.d += (hour * 3600 + minute * 60) * (sign == '-' ? -1 : 1);\n}\n\n\nstatic void set_field(context *ctx, char *name)\n{\n  ctx->mn.id = LSB_PB_FIELDS;\n  ctx->mn.var_len = strlen(name);\n  ctx->mn.var = malloc(ctx->mn.var_len + 1);\n  if (!ctx->mn.var) {\n    fprintf(stderr, \"malloc failed\\n\");\n    exit(1);\n  }\n  memcpy(ctx->mn.var, name, ctx->mn.var_len + 1);\n}\n\n\nstatic void set_timestamp(context *ctx)\n{\n  ctx->mn.id = LSB_PB_TIMESTAMP;\n  ctx->mn.val_type = TYPE_NUMERIC;\n  if (ctx->tms.tm_isdst == -1) {\n    ctx->mn.val.d += mktime(&ctx->tms);\n    ctx->mn.val.d *= 1e9;\n  }\n  memset(&ctx->tms, 0, sizeof(struct tm));\n}\n\n\nstatic void set_numeric_value(context *ctx, char *s)\n{\n  ctx->mn.val_type = TYPE_NUMERIC;\n  ctx->mn.val.d = strtod(s, NULL);\n}\n\n\nstatic void set_string_value(context *ctx, char *s)\n{\n  ctx->mn.val_type = TYPE_STRING;\n  int i, j;\n  for (i = 0, j = 0; s[i]; ++i, ++j) {\n    if (s[i] == '\\\\'\n    && (s[i + 1] == '\"' || s[i + 1] == '\\'' || s[i + 1] == '\\\\')) {\n      ++i;\n    }\n    s[j] = s[i];\n  }\n  s[j] = 0;\n\n  ctx->mn.val_len = j;\n  ctx->mn.val.s = malloc(j + 1);\n  if (!ctx->mn.val.s) {\n    fprintf(stderr, \"malloc failed\\n\");\n    exit(1);\n  }\n  memcpy(ctx->mn.val.s, s, j + 1);\n}\n\n\nstatic void set_match_mod(context *ctx)\n{\n  if (ctx->mn.val_mod == PATTERN_MOD_NONE\n     && strpbrk(ctx->mn.val.s, \"^$*+?.[%-\") == NULL) { // literal\n    ctx->mn.val_mod = PATTERN_MOD_ESC;\n  }\n}\n\n\nstatic bool check_string_len(char *s)\n{\n  int i, j;\n  for (i = 0, j = 0; s[i]; ++i, ++j) {\n    if (s[i] == '\\\\'\n    && (s[i + 1] == '\"' || s[i + 1] == '\\'' || s[i + 1] == '\\\\')) {\n      ++i;\n    }\n  }\n  return (j > UCHAR_MAX) ? false : true;\n}\n\n\nstatic int cond_cnt(context *ctx)\n{\n  return (++ctx->cond_cnt * 2 + 1 > UCHAR_MAX) ? 0 : 1;\n}\n\n%}\n\nmatch = sp ored eol {pop_all_ops(&yy->ctx)}\nored  = anded (or anded)* sp\nanded = expr (and expr)* sp\nexpr  = test | open ored close\ntest  = ( uuid\n        | timestamp\n        | optional_string_headers\n        | severity\n        | pid\n        | field_test\n        | boolean_test\n        ) {push_output(&yy->ctx, &yy->ctx.mn)} sp\n\nop_eq  = \"==\" sp {yy->ctx.mn.op = OP_EQ}\nop_ne  = \"!=\" sp {yy->ctx.mn.op = OP_NE}\nop_seq = \"=~\" sp {yy->ctx.mn.op = OP_RE}\nop_sne = \"!~\" sp {yy->ctx.mn.op = OP_NRE}\nop_gte = \">=\" sp {yy->ctx.mn.op = OP_GTE}\nop_gt  = \">\"  sp {yy->ctx.mn.op = OP_GT}\nop_lte = \"<=\" sp {yy->ctx.mn.op = OP_LTE}\nop_lt  = \"<\"  sp {yy->ctx.mn.op = OP_LT}\n\nrelational  = op_eq\n            | op_ne\n            | op_gte\n            | op_gt\n            | op_lte\n            | op_lt\n\nboolean_test  = true  {yy->ctx.mn.op = OP_TRUE}\n              | false {yy->ctx.mn.op = OP_FALSE}\nboolean       = true  {yy->ctx.mn.val_type = TYPE_TRUE}\n              | false {yy->ctx.mn.val_type = TYPE_FALSE}\n\nand         = \"&&\" &{cond_cnt(&yy->ctx)} {push_op(&yy->ctx, OP_AND)}  sp\nor          = \"||\" &{cond_cnt(&yy->ctx)} {push_op(&yy->ctx, OP_OR)}   sp\nopen        = \"(\"  {push_op(&yy->ctx, OP_OPEN)}                       sp\nclose       = \")\"  {pop_to_paren(&yy->ctx)}                           sp\n\noptional_string_headers = string_headers sp (relational sp string_value | string_match | (op_eq | op_ne) sp nil)\n\nuuid            = \"Uuid\"        {yy->ctx.mn.id = LSB_PB_UUID} sp (relational sp string_value | string_match)\nstring_headers  = \"Type\"        {yy->ctx.mn.id = LSB_PB_TYPE}\n                | \"Logger\"      {yy->ctx.mn.id = LSB_PB_LOGGER}\n                | \"Hostname\"    {yy->ctx.mn.id = LSB_PB_HOSTNAME}\n                | \"EnvVersion\"  {yy->ctx.mn.id = LSB_PB_ENV_VERSION}\n                | \"Payload\"     {yy->ctx.mn.id = LSB_PB_PAYLOAD}\n\nstring_value = ( '\"' < ((\"\\\\\" [\"\\\\]) | (!'\"' .))* > '\"'\n               | \"'\" < ((\"\\\\\" ['\\\\]) | (!\"'\" .))* > \"'\"\n               ) &{check_string_len(yytext)} {set_string_value(&yy->ctx, yytext)}\n\nstring_match = (op_seq | op_sne) sp string_value string_match_mod? {set_match_mod(&yy->ctx)}\n\nstring_match_mod = \"%\" {yy->ctx.mn.val_mod = PATTERN_MOD_ESC}\n\nseverity = \"Severity\"  {yy->ctx.mn.id = LSB_PB_SEVERITY} sp relational sp numeric_value\npid      = \"Pid\"       {yy->ctx.mn.id = LSB_PB_PID} sp (relational sp numeric_value | (op_eq | op_ne) sp nil)\n\nnumeric_value = < sign? number decimal? exponent? > {set_numeric_value(&yy->ctx, yytext)}\nsign          = [-+]\nnumber        = \"0\"\n              | [1-9] [0-9]*\ndecimal       = \".\" [0-9]+\nexponent      = [eE] sign? [0-9]+\n\nfield_test  = fields sp ((relational sp (string_value | numeric_value))\n            | string_match\n            | (op_eq | op_ne) sp (boolean | nil))\nfields      = \"Fields[\" < [^\\]]* > \"]\" {set_field(&yy->ctx, yytext)} f:index? {yy->ctx.mn.fi = f} a:index? {yy->ctx.mn.ai = a}\nindex       = \"[\" < zero_to_255 > \"]\" {$$ = atoi(yytext)}\nzero_to_255 = \"2\" [0-5] [0-5]\n            | \"1\" [0-9] [0-9]\n            | [1-9] [0-9]\n            | [0-9]\n\ntimestamp = (\"Timestamp\" sp relational sp (numeric_value | ts_quoted)) {set_timestamp(&yy->ctx)}\nts_quoted = '\"' rfc3339 '\"' | \"'\" rfc3339 \"'\"\nfulldate  = (y:year \"-\" m:month \"-\" d:day) {update_date(&yy->ctx, y, m, d)}\nyear      = < [0-9] [0-9] [0-9] [0-9] > {$$ = atoi(yytext)}\nmonth     = ( < \"0\" [1-9] >\n            | < \"1\" [0-2] >\n            ) {$$ = atoi(yytext)}\nday       = (\n              < [1-2] [0-9] >\n            | < \"0\" [1-9] >\n            | < \"3\" [0-1] >\n            ) {$$ = atoi(yytext)}\n\nrfc3339     = fulldate \"T\" fulltime\nfulltime    = partialtime timeoffset\npartialtime = h:hour \":\" m:minute \":\" s:second second_frac? {update_time(&yy->ctx, h, m, s)}\ntimeoffset  = \"Z\" {update_offset(&yy->ctx, '+', 0, 0)}\n            | < sign > h:hour m:minute {update_offset(&yy->ctx, yytext[0], h, m)}\nhour        = (\n                < [0-1] [0-9] >\n              | < \"2\" [0-3] >\n              ) {$$ = atoi(yytext)}\nminute      = < [0-5] [0-9] > {$$ = atoi(yytext)}\nsecond      = (\n                < [0-5] [0-9] >\n              | < \"60\" >\n              ) {$$ = atoi(yytext)}\nsecond_frac = < decimal > {yy->ctx.mn.val.d += strtod(yytext, NULL)}\n\nnil       = \"NIL\" {yy->ctx.mn.val_type = TYPE_NIL} sp\ntrue      = \"TRUE\" sp\nfalse     = \"FALSE\" sp\nsp        = [ \\r\\n\\t]*\neol       = !.\n\n%%\n\nstatic match_node* copy_node(unsigned char parent, match_node *mn,\n                             match_node_tmp *mnt)\n{\n  mn->op        = mnt->op;\n  mn->val_len   = 0;\n  mn->var_len   = 0;\n  mn->field_id  = mnt->id;\n  mn->val_mod   = mnt->val_mod;\n  mn->val_type  = mnt->val_type;\n\n  if (mn->op == OP_AND || mn->op == OP_OR) {\n    mn->u.off = parent;\n  } else {\n    mn->u.idx.f = mnt->fi;\n    mn->u.idx.a = mnt->ai;\n  }\n\n  if (mnt->id == LSB_PB_FIELDS) {\n    mn->var_len = mnt->var_len;\n  }\n  if (mn->var_len) {\n    memcpy(mn->data, mnt->var, mn->var_len); // no NUL terminator\n    free(mnt->var);\n    mnt->var = NULL;\n    mnt->var_len = 0;\n  }\n\n  size_t val_len = 0;\n  switch (mnt->val_type) {\n  case TYPE_STRING:\n    val_len = mnt->val_len + 1;\n    memcpy(mn->data + mn->var_len, mnt->val.s, val_len);\n    free(mnt->val.s);\n    mnt->val.s = NULL;\n    mnt->val_len = 0;\n    break;\n  case TYPE_NUMERIC:\n    val_len = sizeof(double);\n    memcpy(mn->data + mn->var_len, &mnt->val.d, val_len);\n    break;\n  default:\n    break;\n  }\n\n  mn->units = 1 + ((sizeof(match_node) - 1 + mn->var_len + val_len)\n                   / sizeof(match_node));\n  if (val_len && mnt->val_type == TYPE_STRING) {\n    mn->val_len = val_len - 1;\n  } else {\n    mn->val_len = val_len;\n  }\n  return mn + mn->units;\n}\n\n\nstatic match_node* inorder_traverse(unsigned char parent, match_node **offsets,\n                                    match_node *mn, match_node_tmp *root,\n                                    match_node_tmp *mnt)\n{\n  if (mnt->id == 0 && (mnt->op == OP_AND || mnt->op == OP_OR)) {\n    unsigned char idx = mnt->val_len;\n    mnt->val_len = 0;\n    mn = inorder_traverse(idx, offsets, mn, root, root + mnt->fi);\n    offsets[idx] = mn;\n    mn = copy_node(parent, mn, mnt);\n  } else {\n    mn = copy_node(parent, mn, mnt);\n  }\n  if (mnt->id == 0 && (mnt->op == OP_AND || mnt->op == OP_OR)) {\n    mn = inorder_traverse(parent, offsets, mn, root, root + mnt->ai);\n  }\n  return mn;\n}\n\n\nstatic size_t get_matcher_bytes(match_node_tmp nodes[], size_t size)\n{\n  size_t len = 0;\n  for (unsigned i = 0; i < size; ++i) {\n    size_t val_len = 0;\n    switch (nodes[i].val_type) {\n    case TYPE_STRING:\n      val_len = nodes[i].val_len + 1;\n      break;\n    case TYPE_NUMERIC:\n      val_len = sizeof(double);\n      break;\n    default:\n      break;\n    }\n\n    size_t var_len = 0;\n    if (nodes[i].id == LSB_PB_FIELDS) {\n      var_len = nodes[i].var_len;\n    }\n\n    len += (sizeof(match_node) * 2 + val_len + var_len - 1)\n      / sizeof(match_node) * sizeof(match_node);\n\n    if (nodes[i].op == OP_OR || nodes[i].op == OP_AND) {\n      // squirrel away the position for the short-circuit calculation\n      nodes[i].val_len = i;\n    }\n  }\n  return len;\n}\n\n\nstatic void make_tree(match_node_tmp nodes[], size_t size)\n{\n  // turn the postfix stack into a traversable tree\n  match_node_tmp *stack[size];\n  memset(stack, 0, sizeof(stack));\n  int top = 0;\n  for (unsigned i = 0; i < size; ++i) {\n    if (nodes[i].op != OP_AND && nodes[i].op != OP_OR) {\n      stack[top++] = &nodes[i];\n    } else {\n      nodes[i].ai = stack[--top] - nodes;\n      nodes[i].fi = stack[--top] - nodes;\n      stack[top++] = &nodes[i];\n    }\n  }\n}\n\n\nstatic lsb_message_matcher* make_matcher(match_node_tmp nodes[], size_t size)\n{\n  lsb_message_matcher *mm = malloc(sizeof(lsb_message_matcher));\n  if (!mm) { return NULL; }\n\n  mm->bytes = get_matcher_bytes(nodes, size);\n  mm->nodes = calloc(mm->bytes, 1);\n  if (!mm->nodes) {\n    free(mm);\n    return NULL;\n  }\n\n  match_node *offsets[size];\n  memset(offsets, 0, sizeof(offsets));\n\n  inorder_traverse(size, offsets, mm->nodes, nodes, nodes + (size - 1));\n\n  // populate the short-circuit offsets\n  match_node *e = mm->nodes + (mm->bytes / sizeof(match_node));\n  for (match_node *p = mm->nodes; p < e;){\n    if (p->op == OP_AND || p->op == OP_OR) {\n      if (p->u.off < size) {\n        p->u.off = offsets[p->u.off] - mm->nodes;\n      } else {\n        p->u.off =  mm->bytes / sizeof(match_node);\n      }\n    }\n    p += p->units;\n  }\n  return mm;\n}\n\n\nlsb_message_matcher* lsb_create_message_matcher(const char *exp)\n{\n  if (!exp) { return NULL; }\n\n  lsb_message_matcher *mm = NULL;\n  yycontext yy;\n  memset(&yy, 0, sizeof(yy));\n  yy.ctx.is.s = exp;\n  yy.ctx.is.size = strlen(exp);\n  int ret = yyparse(&yy);\n  if (ret) {\n    make_tree(yy.ctx.out.a, yy.ctx.out.pos);\n    mm = make_matcher(yy.ctx.out.a, yy.ctx.out.pos);\n  }\n  free(yy.ctx.out.a);\n  free(yy.ctx.ops.a);\n  yyrelease(&yy);\n  return mm;\n}\n"
  },
  {
    "path": "src/util/input_buffer.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Data stream input buffer implementation @file */\n\n#include \"luasandbox/util/input_buffer.h\"\n\n#include <stdbool.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"luasandbox/util/util.h\"\n#include \"luasandbox/util/heka_message.h\"\n\nlsb_err_value\nlsb_init_input_buffer(lsb_input_buffer *b, size_t max_message_size)\n{\n  if (!b) return LSB_ERR_UTIL_NULL;\n  b->buf = NULL;\n  if (max_message_size == 0) return LSB_ERR_UTIL_PRANGE;\n  max_message_size += LSB_MAX_HDR_SIZE;\n  b->size = max_message_size < BUFSIZ ? max_message_size : BUFSIZ;\n  b->maxsize = max_message_size;\n  b->readpos = 0;\n  b->scanpos = 0;\n  b->msglen = 0;\n  b->buf = malloc(b->size);\n  return b->buf ? NULL : LSB_ERR_UTIL_OOM;\n}\n\n\nvoid lsb_free_input_buffer(lsb_input_buffer *b)\n{\n  if (!b) return;\n\n  free(b->buf);\n  b->buf = NULL;\n  b->size = 0;\n  b->readpos = 0;\n  b->scanpos = 0;\n  b->msglen = 0;\n}\n\n\nlsb_err_value lsb_expand_input_buffer(lsb_input_buffer *b, size_t len)\n{\n  if (!b) return LSB_ERR_UTIL_NULL;\n\n  if (b->scanpos != 0) { // shift the data to the beginning of the buffer\n    if (b->scanpos == b->readpos) {\n      b->scanpos = b->readpos = 0;\n    } else {\n      memmove(b->buf, b->buf + b->scanpos, b->readpos - b->scanpos);\n      b->readpos = b->readpos - b->scanpos;\n      b->scanpos = 0;\n    }\n  }\n\n  if (b->readpos + len > b->size) {\n    size_t newsize = b->readpos + len;\n    if (newsize > b->maxsize) return LSB_ERR_UTIL_FULL;\n\n    newsize = lsb_lp2(newsize);\n    if (newsize > b->maxsize) newsize = b->maxsize;\n    char *tmp = realloc(b->buf, newsize);\n    if (tmp) {\n      b->buf = tmp;\n      b->size = newsize;\n    } else {\n      return LSB_ERR_UTIL_OOM;\n    }\n  }\n  return NULL;\n}\n"
  },
  {
    "path": "src/util/output_buffer.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Data stream output buffer implementation @file */\n\n#include \"luasandbox/util/output_buffer.h\"\n\n#include <limits.h>\n#include <math.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"luasandbox/util/util.h\"\n\n#ifdef _MSC_VER\n// To silence the +/-INFINITY warning\n#pragma warning( disable : 4756 )\n#pragma warning( disable : 4056 )\n#endif\n\nlsb_err_value\nlsb_init_output_buffer(lsb_output_buffer *b, size_t max_message_size)\n{\n  if (!b) return LSB_ERR_UTIL_NULL;\n  if (max_message_size && max_message_size < LSB_OUTPUT_SIZE) {\n    b->size = max_message_size;\n  } else {\n    b->size = LSB_OUTPUT_SIZE;\n  }\n  b->maxsize = max_message_size;\n  b->pos = 0;\n  b->buf = malloc(b->size);\n  return b->buf ? NULL : LSB_ERR_UTIL_OOM;\n}\n\n\nvoid lsb_free_output_buffer(lsb_output_buffer *b)\n{\n  if (!b) return;\n  free(b->buf);\n  b->buf = NULL;\n  b->size = 0;\n  b->pos = 0;\n}\n\n\nlsb_err_value lsb_expand_output_buffer(lsb_output_buffer *b, size_t needed)\n{\n  if (!b) return LSB_ERR_UTIL_NULL;\n\n  if (needed <= b->size - b->pos) return NULL;\n\n  if (b->maxsize && needed + b->pos > b->maxsize) {\n    return LSB_ERR_UTIL_FULL;\n  }\n\n  size_t newsize = lsb_lp2(b->pos + needed);\n  if (b->maxsize && newsize > b->maxsize) {\n    newsize = b->maxsize;\n  }\n\n  void *ptr = realloc(b->buf, newsize);\n  if (!ptr) {\n    return LSB_ERR_UTIL_OOM;\n  }\n\n  b->buf = ptr;\n  b->size = newsize;\n  return NULL;\n}\n\n\nlsb_err_value lsb_outputc(lsb_output_buffer *b, char ch)\n{\n  if (!b) {\n    return LSB_ERR_UTIL_NULL;\n  }\n  lsb_err_value ret = lsb_expand_output_buffer(b, 2);\n  if (ret) return ret;\n\n  b->buf[b->pos++] = ch;\n  b->buf[b->pos] = 0;\n  return NULL;\n}\n\n\nlsb_err_value lsb_outputf(lsb_output_buffer *b, const char *fmt, ...)\n{\n  if (!b || !fmt) {\n    return LSB_ERR_UTIL_NULL;\n  }\n\n  va_list args;\n  int remaining = 0;\n  char *ptr = NULL, *old_ptr = NULL;\n  do {\n    ptr = b->buf + b->pos;\n    remaining = (int)(b->size - b->pos);\n    va_start(args, fmt);\n    int needed = vsnprintf(ptr, remaining, fmt, args);\n    va_end(args);\n    if (needed == -1) {\n      // Windows and Unix have different return values for this function\n      // -1 on Unix is a format error\n      // -1 on Windows means the buffer is too small and the required len\n      // is not returned\n      needed = remaining;\n    }\n    if (needed >= remaining) {\n      if (b->maxsize && (b->size >= b->maxsize\n                         || b->pos + needed >= b->maxsize)) {\n        return LSB_ERR_UTIL_FULL;\n      }\n      size_t newsize = b->size * 2;\n      while ((size_t)needed >= newsize - b->pos) {\n        newsize *= 2;\n      }\n      if (b->maxsize && newsize > b->maxsize) {\n        newsize = b->maxsize;\n      }\n      void *p = malloc(newsize);\n      if (p != NULL) {\n        memcpy(p, b->buf, b->pos);\n        old_ptr = b->buf;\n        b->buf = p;\n        b->size = newsize;\n      } else {\n        return LSB_ERR_UTIL_OOM;\n      }\n    } else {\n      b->pos += needed;\n      break;\n    }\n  } while (1);\n\n  free(old_ptr);\n  return NULL;\n}\n\n\nlsb_err_value lsb_outputs(lsb_output_buffer *b, const char *str, size_t len)\n{\n  if (!b) {\n    return LSB_ERR_UTIL_NULL;\n  }\n  lsb_err_value ret = lsb_expand_output_buffer(b, len + 1);\n  if (ret) return ret;\n\n  memcpy(b->buf + b->pos, str, len);\n  b->pos += len;\n  b->buf[b->pos] = 0;\n  return ret;\n}\n\n\nlsb_err_value lsb_outputd(lsb_output_buffer *b, double d)\n{\n  if (!b) return LSB_ERR_UTIL_NULL;\n\n  if (isnan(d)) {\n    return lsb_outputs(b, \"nan\", 3);\n  }\n  if (d == INFINITY) {\n    return lsb_outputs(b, \"inf\", 3);\n  }\n  if (d == -INFINITY) {\n    return lsb_outputs(b, \"-inf\", 4);\n  }\n  return lsb_outputfd(b, d);\n}\n\n\nlsb_err_value lsb_outputfd(lsb_output_buffer *b, double d)\n{\n  if (!b) return LSB_ERR_UTIL_NULL;\n\n  if (d < INT_MIN || d > INT_MAX) {\n    return lsb_outputf(b, \"%0.17g\", d);\n  }\n\n  const int precision = 8;\n  const unsigned magnitude = 100000000;\n  char buffer[20];\n  char *p = buffer;\n  int negative = 0;\n\n  if (d < 0) {\n    negative = 1;\n    d = -d;\n  }\n\n  int number = (int)d;\n  double tmp = (d - number) * magnitude;\n  unsigned fraction = (unsigned)tmp;\n  double diff = tmp - fraction;\n\n  if (diff > 0.5) {\n    ++fraction;\n    if (fraction >= magnitude) {\n      fraction = 0;\n      ++number;\n    }\n  } else if (diff == 0.5 && ((fraction == 0) || (fraction & 1))) {\n    // bankers rounding\n    ++fraction;\n  }\n\n  // decimal fraction\n  if (fraction != 0) {\n    int nodigits = 1;\n    char c = 0;\n    for (int x = 0; x < precision; ++x) {\n      c = fraction % 10;\n      if (!(c == 0 && nodigits)) {\n        *p++ = c + '0';\n        nodigits = 0;\n      }\n      fraction /= 10;\n    }\n    *p++ = '.';\n  }\n\n  // number\n  do {\n    *p++ = (number % 10) + '0';\n    number /= 10;\n  } while (number > 0);\n\n  lsb_err_value ret = lsb_expand_output_buffer(b, (p - buffer) + negative + 1);\n  if (!ret) {\n    if (negative) {\n      b->buf[b->pos++] = '-';\n    }\n\n    do {\n      --p;\n      b->buf[b->pos++] = *p;\n    } while (p != buffer);\n\n    b->buf[b->pos] = 0;\n  }\n  return ret;\n}\n"
  },
  {
    "path": "src/util/protobuf.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** Generic protobuf utility functions @file */\n\n#include \"luasandbox/util/protobuf.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\nconst char* lsb_pb_read_key(const char *p, int *tag, int *wiretype)\n{\n  if (!p || !tag || !wiretype) return NULL;\n\n  *wiretype = 7 & (unsigned char)*p;\n  *tag = (unsigned char)*p >> 3;\n  return ++p;\n}\n\n\nlsb_err_value lsb_pb_write_key(lsb_output_buffer *ob, unsigned char tag,\n                               unsigned char wiretype)\n{\n  lsb_err_value ret = lsb_expand_output_buffer(ob, 1);\n  if (!ret) {\n    ob->buf[ob->pos++] = wiretype | (tag << 3);\n  }\n  return ret;\n}\n\n\nconst char* lsb_pb_read_varint(const char *p, const char *e, long long *vi)\n{\n  if (!p || !e || !vi) {\n    return NULL;\n  }\n\n  *vi = 0;\n  int i, shift = 0;\n  for (i = 0; p != e && i < LSB_MAX_VARINT_BYTES; ++i, ++p) {\n    *vi |= ((unsigned long long)*p & 0x7f) << shift;\n    shift += 7;\n    if ((*p & 0x80) == 0) break;\n  }\n  if (i == LSB_MAX_VARINT_BYTES || p == e) {\n    return NULL;\n  }\n  return ++p;\n}\n\n\nint lsb_pb_output_varint(char *buf, unsigned long long i)\n{\n  int pos = 0;\n  if (!buf) return pos;\n\n  if (i == 0) {\n    buf[pos++] = 0;\n    return pos;\n  }\n\n  while (i) {\n    buf[pos++] = (i & 0x7F) | 0x80;\n    i >>= 7;\n  }\n  buf[pos - 1] &= 0x7F; // end the varint\n  return pos;\n}\n\n\nlsb_err_value lsb_pb_write_varint(lsb_output_buffer *ob, unsigned long long i)\n{\n  lsb_err_value ret = lsb_expand_output_buffer(ob, LSB_MAX_VARINT_BYTES);\n  if (!ret) {\n    ob->pos += lsb_pb_output_varint(ob->buf + ob->pos, i);\n  }\n  return ret;\n}\n\n\nlsb_err_value lsb_pb_write_bool(lsb_output_buffer *ob, int i)\n{\n  lsb_err_value ret = lsb_expand_output_buffer(ob, 1);\n  if (!ret) {\n    if (i) {\n      ob->buf[ob->pos++] = 1;\n    } else {\n      ob->buf[ob->pos++] = 0;\n    }\n  }\n  return ret;\n}\n\n\nlsb_err_value lsb_pb_write_double(lsb_output_buffer *ob, double i)\n{\n  static const size_t needed = sizeof(double);\n\n  lsb_err_value ret = lsb_expand_output_buffer(ob, needed);\n  if (!ret) {\n    // todo add big endian support if necessary\n    memcpy(&ob->buf[ob->pos], &i, needed);\n    ob->pos += needed;\n  }\n  return ret;\n}\n\n\nlsb_err_value\nlsb_pb_write_string(lsb_output_buffer *ob, char tag, const char *s, size_t len)\n{\n  lsb_err_value ret = lsb_pb_write_key(ob, tag, LSB_PB_WT_LENGTH);\n  if (!ret) ret = lsb_pb_write_varint(ob, len);\n  if (!ret) ret = lsb_expand_output_buffer(ob, len);\n  if (!ret) {\n    memcpy(&ob->buf[ob->pos], s, len);\n    ob->pos += len;\n  }\n  return ret;\n}\n\n\nlsb_err_value lsb_pb_update_field_length(lsb_output_buffer *ob, size_t len_pos)\n{\n  if (len_pos >= ob->pos) {\n    return LSB_ERR_UTIL_PRANGE;\n  }\n\n  size_t len = ob->pos - len_pos - 1;\n  if (len < 128) {\n    ob->buf[len_pos] = (char)len;\n    return NULL;\n  }\n  size_t l = len, cnt = 0;\n  while (l) {\n    l >>= 7;\n    ++cnt;  // compute the number of bytes needed for the varint length\n  }\n  size_t needed = cnt - 1;\n  lsb_err_value ret = lsb_expand_output_buffer(ob, needed);\n  if (!ret) {\n    ob->pos += needed;\n    memmove(&ob->buf[len_pos + cnt], &ob->buf[len_pos + 1], len);\n    lsb_pb_output_varint(ob->buf + len_pos, len);\n  }\n  return ret;\n}\n"
  },
  {
    "path": "src/util/running_stats.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Running stats implementation @file */\n\n#include \"luasandbox/util/running_stats.h\"\n\n#include <math.h>\n\nvoid lsb_init_running_stats(lsb_running_stats *s)\n{\n  s->count = 0.0;\n  s->mean = 0.0;\n  s->sum = 0.0;\n}\n\n\nvoid lsb_update_running_stats(lsb_running_stats *s, double d)\n{\n  if (!isfinite(d)) return;\n\n  double old_mean = s->mean;\n  double old_sum = s->sum;\n\n  if (++s->count == 1) {\n    s->mean = d;\n  } else {\n    s->mean = old_mean + (d - old_mean) / s->count;\n    s->sum = old_sum + (d - old_mean) * (d - s->mean);\n  }\n}\n\n\ndouble lsb_sd_running_stats(lsb_running_stats *s)\n{\n  if (s->count < 2) return 0.0;\n  return sqrt(s->sum / (s->count - 1));\n}\n\n"
  },
  {
    "path": "src/util/string.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** String functions @file */\n\n#include <ctype.h>\n#include <limits.h>\n#include <string.h>\n\n#include \"luasandbox/util/string.h\"\n\nvoid lsb_init_const_string(lsb_const_string *s)\n{\n  s->s = NULL;\n  s->len = 0;\n}\n\n\nchar* lsb_lua_string_unescape(char *d, const char *s, size_t *dlen)\n{\n  if (!s || !d || !dlen || *dlen <= strlen(s)) {\n    return NULL;\n  }\n\n  int x = 0;\n  int y = 0;\n  while (s[x]) {\n    switch (s[x]) {\n    case '\\\\':\n      ++x;\n      switch (s[x]) {\n      case 'a':\n        d[y++] = '\\a'; break;\n      case 'b':\n        d[y++] = '\\b'; break;\n      case 'f':\n        d[y++] = '\\f'; break;\n      case 'n':\n        d[y++] = '\\n'; break;\n      case 'r':\n        d[y++] = '\\r'; break;\n      case 't':\n        d[y++] = '\\t'; break;\n      case 'v':\n        d[y++] = '\\v'; break;\n      default:\n        if (!isdigit(s[x])) {\n          switch (s[x]) {\n          case '\"':\n          case '\\'':\n          case '?':\n          case '\\\\':\n            break;\n          default:\n            return NULL;\n          }\n          d[y++] = s[x];\n        } else {  /* \\xxx */\n          int n = 0;\n          int c = 0;\n          do {\n            c = 10 * c + (s[x++] - '0');\n          } while (++n < 3 && isdigit(s[x]));\n          if (c > UCHAR_MAX) return NULL;\n          d[y++] = (char)c;\n          --x;\n        }\n      }\n      ++x;\n      break;\n\n    default:\n      d[y++] = s[x++];\n      break;\n    }\n  }\n  d[y] = 0;\n  *dlen = y;\n  return d;\n}\n"
  },
  {
    "path": "src/util/string_matcher.c",
    "content": "/*\n** Modified Lua lstrlib.c for the Lua sandbox message matcher pattern-matching\n*\n* Copyright (C) 1994-2012 Lua.org, PUC-Rio.  All rights reserved.\n*\n* Permission is hereby granted, free of charge, to any person obtaining\n* a copy of this software and associated documentation files (the\n* \"Software\"), to deal in the Software without restriction, including\n* without limitation the rights to use, copy, modify, merge, publish,\n* distribute, sublicense, and/or sell copies of the Software, and to\n* permit persons to whom the Software is furnished to do so, subject to\n* the following conditions:\n*\n* The above copyright notice and this permission notice shall be\n* included in all copies or substantial portions of the Software.\n*\n* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n******************************************************************************/\n\n#include \"luasandbox/util/string_matcher.h\"\n\n#include <ctype.h>\n#include <string.h>\n\n/* macro to `unsign' a character */\n#define uchar(c)        ((unsigned char)(c))\n#define L_ESC   '%'\n\ntypedef struct MatchState {\n  const char *src_init;  /* init of source string */\n  const char *src_end;  /* end (`\\0') of source string */\n} MatchState;\n\n\nstatic const char* classend(const char *p)\n{\n  switch (*p++) {\n  case L_ESC:\n    {\n      if (*p == '\\0') return NULL; // error pattern ends with a %\n      return p + 1;\n    }\n  case '[':\n    {\n      if (*p == '^') p++;\n      do {  /* look for a `]' */\n        if (*p == '\\0') return NULL; // error missing closing ]\n        if (*(p++) == L_ESC && *p != '\\0') p++;  /* skip escapes (e.g. `%]') */\n      }while (*p != ']');\n      return p + 1;\n    }\n  default:\n    {\n      return p;\n    }\n  }\n}\n\n\nstatic int match_class(int c, int cl)\n{\n  int res;\n  switch (tolower(cl)) {\n  case 'a' :\n    res = isalpha(c); break;\n  case 'c' :\n    res = iscntrl(c); break;\n  case 'd' :\n    res = isdigit(c); break;\n  case 'l' :\n    res = islower(c); break;\n  case 'p' :\n    res = ispunct(c); break;\n  case 's' :\n    res = isspace(c); break;\n  case 'u' :\n    res = isupper(c); break;\n  case 'w' :\n    res = isalnum(c); break;\n  case 'x' :\n    res = isxdigit(c); break;\n  case 'z' :\n    res = (c == 0); break;\n  default:\n    return (cl == c);\n  }\n  return (islower(cl) ? res : !res);\n}\n\n\nstatic int matchbracketclass(int c, const char *p, const char *ec)\n{\n  int sig = 1;\n  if (*(p + 1) == '^') {\n    sig = 0;\n    p++;  /* skip the `^' */\n  }\n  while (++p < ec) {\n    if (*p == L_ESC) {\n      p++;\n      if (match_class(c, uchar(*p))) return sig;\n    } else if ((*(p + 1) == '-') && (p + 2 < ec)) {\n      p += 2;\n      if (uchar(*(p - 2)) <= c && c <= uchar(*p)) return sig;\n    } else if (uchar(*p) == c) return sig;\n  }\n  return !sig;\n}\n\n\nstatic int singlematch(int c, const char *p, const char *ep)\n{\n  switch (*p) {\n  case '.':\n    return 1;  /* matches any char */\n  case L_ESC:\n    return match_class(c, uchar(*(p + 1)));\n  case '[':\n    return matchbracketclass(c, p, ep - 1);\n  default:\n    return (uchar(*p) == c);\n  }\n}\n\n\nstatic const char* match(MatchState *ms, const char *s, const char *p);\n\n\nstatic const char* matchbalance(MatchState *ms, const char *s,\n                                const char *p)\n{\n  if (*p == 0 || *(p + 1) == 0) return NULL; // ubalanced pattern;\n  if (*s != *p) return NULL;\n  else {\n    int b = *p;\n    int e = *(p + 1);\n    int cont = 1;\n    while (++s < ms->src_end) {\n      if (*s == e) {\n        if (--cont == 0) return s + 1;\n      } else if (*s == b) cont++;\n    }\n  }\n  return NULL;  /* string ends out of balance */\n}\n\n\nstatic const char* max_expand(MatchState *ms, const char *s,\n                              const char *p, const char *ep)\n{\n  ptrdiff_t i = 0;  /* counts maximum expand for item */\n  while ((s + i) < ms->src_end && singlematch(uchar(*(s + i)), p, ep)) i++;\n  /* keeps trying to match with the maximum repetitions */\n  while (i >= 0) {\n    const char *res = match(ms, (s + i), ep + 1);\n    if (res) return res;\n    i--;  /* else didn't match; reduce 1 repetition to try again */\n  }\n  return NULL;\n}\n\n\nstatic const char* min_expand(MatchState *ms, const char *s,\n                              const char *p, const char *ep)\n{\n  for (;;) {\n    const char *res = match(ms, s, ep + 1);\n    if (res != NULL) return res;\n    else if (s < ms->src_end && singlematch(uchar(*s), p, ep)) s++;  /* try with one more repetition */\n    else return NULL;\n  }\n}\n\n\nstatic const char* match(MatchState *ms, const char *s, const char *p)\n{\ninit: /* using goto's to optimize tail recursion */\n  switch (*p) {\n  case L_ESC:\n    {\n      switch (*(p + 1)) {\n      case 'b':\n        {  /* balanced string? */\n          s = matchbalance(ms, s, p + 2);\n          if (s == NULL) return NULL;\n          p += 4; goto init;  /* else return match(ms, s, p+4); */\n        }\n      case 'f':\n        {  /* frontier? */\n          const char *ep; char previous;\n          p += 2;\n          if (*p != '[') return NULL; // missing [ after %f\n          ep = classend(p);  /* points to what is next */\n          if (ep == NULL) return NULL;\n          previous = (s == ms->src_init) ? '\\0' : *(s - 1);\n          if (matchbracketclass(uchar(previous), p, ep - 1) ||\n              !matchbracketclass(uchar(*s), p, ep - 1)) return NULL;\n          p = ep; goto init;  /* else return match(ms, s, ep); */\n        }\n      default:\n        {\n          goto dflt;  /* case default */\n        }\n      }\n    }\n  case '\\0':\n    {  /* end of pattern */\n      return s;  /* match succeeded */\n    }\n  case '$':\n    {\n      if (*(p + 1) == '\\0')  /* is the `$' the last char in pattern? */\n        return (s == ms->src_end) ? s : NULL;  /* check end of string */\n      else goto dflt;\n    }\n  default:\n  dflt:\n    {  /* it is a pattern item */\n      const char *ep = classend(p);  /* points to what is next */\n      if (ep == NULL) return NULL;\n\n      int m = s < ms->src_end && singlematch(uchar(*s), p, ep);\n      switch (*ep) {\n      case '?':\n        {  /* optional */\n          const char *res;\n          if (m && ((res = match(ms, s + 1, ep + 1)) != NULL)) return res;\n          p = ep + 1; goto init;  /* else return match(ms, s, ep+1); */\n        }\n      case '*':\n        {  /* 0 or more repetitions */\n          return max_expand(ms, s, p, ep);\n        }\n      case '+':\n        {  /* 1 or more repetitions */\n          return (m ? max_expand(ms, s + 1, p, ep) : NULL);\n        }\n      case '-':\n        {  /* 0 or more repetitions (minimum) */\n          return min_expand(ms, s, p, ep);\n        }\n      default:\n        {\n          if (!m) return NULL;\n          s++; p = ep; goto init;  /* else return match(ms, s+1, ep); */\n        }\n      }\n    }\n  }\n}\n\n\nstatic const char* lmemfind(const char *s1, size_t l1,\n                            const char *s2, size_t l2)\n{\n  if (l2 == 0) return s1;  /* empty strings are everywhere */\n  else if (l2 > l1) return NULL;  /* avoids a negative `l1' */\n  else {\n    const char *init;  /* to search for a `*s2' inside `s1' */\n    l2--;  /* 1st char will be checked by `memchr' */\n    l1 = l1 - l2;  /* `s2' cannot be found after that */\n    while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) {\n      init++;   /* 1st char is already checked */\n      if (memcmp(init, s2 + 1, l2) == 0) return init - 1;\n      else {  /* correct `l1' and `s1' to try again */\n        l1 -= init - s1;\n        s1 = init;\n      }\n    }\n    return NULL;  /* not found */\n  }\n}\n\n\n\nbool lsb_string_match(const char *s, size_t len, const char *p)\n{\n  if (!s || !p) { return false; }\n  MatchState ms;\n  int anchor = (*p == '^') ? (p++, 1) : 0;\n  const char *s1 = s;\n  ms.src_init = s;\n  ms.src_end = s + len;\n  do {\n    const char *res;\n    if ((res = match(&ms, s1, p)) != NULL) {\n      return true;\n    }\n  } while (s1++ < ms.src_end && !anchor);\n  return false;\n}\n\n\nbool lsb_string_find(const char *s, size_t ls, const char *p, size_t lp)\n{\n  if (!s || !p) { return false; }\n  if (lmemfind(s, ls, p, lp)) {\n    return true;\n  }\n  return false;\n}\n"
  },
  {
    "path": "src/util/test/CMakeLists.txt",
    "content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n\nadd_executable(test_input_buffer test_input_buffer.c)\ntarget_link_libraries(test_input_buffer luasandboxutil)\nadd_test(NAME test_input_buffer COMMAND test_input_buffer)\n\nadd_executable(test_output_buffer test_output_buffer.c)\ntarget_link_libraries(test_output_buffer luasandboxutil)\nadd_test(NAME test_output_buffer COMMAND test_output_buffer)\n\nadd_executable(test_protobuf test_protobuf.c)\ntarget_link_libraries(test_protobuf luasandboxutil)\nadd_test(NAME test_protobuf COMMAND test_protobuf)\n\nadd_executable(test_string_matcher test_string_matcher.c)\ntarget_link_libraries(test_string_matcher luasandboxutil)\nadd_test(NAME test_string_matcher COMMAND test_string_matcher)\n\nadd_executable(test_running_stats test_running_stats.c)\ntarget_link_libraries(test_running_stats luasandboxutil)\nadd_test(NAME test_running_stats COMMAND test_running_stats)\n\nadd_executable(test_util test_util.c)\ntarget_link_libraries(test_util luasandboxutil)\nadd_test(NAME test_util COMMAND test_util)\n\nadd_executable(test_heka_message test_heka_message.c)\ntarget_link_libraries(test_heka_message luasandboxutil)\nadd_test(NAME test_heka_message COMMAND test_heka_message)\n\nadd_executable(test_heka_message_matcher test_heka_message_matcher.c)\ntarget_link_libraries(test_heka_message_matcher luasandboxutil)\nadd_test(NAME test_heka_message_matcher COMMAND test_heka_message_matcher)\n\nadd_executable(test_string test_string.c)\ntarget_link_libraries(test_string luasandboxutil)\nadd_test(NAME test_string COMMAND test_string)\n\nif(WIN32)\n   set(LIBRARY_PATHS \"${CMAKE_BINARY_DIR}/src/util\")\n   set_tests_properties(test_input_buffer PROPERTIES ENVIRONMENT PATH=${LIBRARY_PATHS})\n   set_tests_properties(test_output_buffer PROPERTIES ENVIRONMENT PATH=${LIBRARY_PATHS})\n   set_tests_properties(test_protobuf PROPERTIES ENVIRONMENT PATH=${LIBRARY_PATHS})\n   set_tests_properties(test_string_matcher PROPERTIES ENVIRONMENT PATH=${LIBRARY_PATHS})\n   set_tests_properties(test_running_stats PROPERTIES ENVIRONMENT PATH=${LIBRARY_PATHS})\n   set_tests_properties(test_util PROPERTIES ENVIRONMENT PATH=${LIBRARY_PATHS})\n   set_tests_properties(test_heka_message PROPERTIES ENVIRONMENT PATH=${LIBRARY_PATHS})\n   set_tests_properties(test_heka_message_matcher PROPERTIES ENVIRONMENT PATH=${LIBRARY_PATHS})\n   set_tests_properties(test_string PROPERTIES ENVIRONMENT PATH=${LIBRARY_PATHS})\nendif()\n"
  },
  {
    "path": "src/util/test/test_heka_message.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief heka_message unit tests @file */\n\n#include <stddef.h>\n#include <stdarg.h>\n#include <string.h>\n\n#include <stdio.h>\n\n#include \"luasandbox/error.h\"\n#include \"luasandbox/test/mu_test.h\"\n#include \"luasandbox/util/heka_message.h\"\n\n#define TEST_UUID \"\\x0a\\x10\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\"\n#define TEST_NS   \"\\x10\\x01\"\n\n// {Uuid=\"\" Timestamp = 1e9, Type=\"type\", Logger=\"logger\", Payload=\"payload\", EnvVersion=\"env_version\", Hostname=\"hostname\", Severity=9, Fields = {number=1,numbers={value={1,2,3}, representation=\"count\"},string=\"string\",strings={\"s1\",\"s2\",\"s3\"}, bool=true, bools={true,false,false}}}\nstatic char pb[] = \"\\x0a\\x10\\x73\\x1e\\x36\\x84\\xec\\x25\\x42\\x76\\xa4\\x01\\x79\\x6f\\x17\\xdd\\x20\\x63\\x10\\x80\\x94\\xeb\\xdc\\x03\\x1a\\x04\\x74\\x79\\x70\\x65\\x22\\x06\\x6c\\x6f\\x67\\x67\\x65\\x72\\x28\\x09\\x32\\x07\\x70\\x61\\x79\\x6c\\x6f\\x61\\x64\\x3a\\x0b\\x65\\x6e\\x76\\x5f\\x76\\x65\\x72\\x73\\x69\\x6f\\x6e\\x4a\\x08\\x68\\x6f\\x73\\x74\\x6e\\x61\\x6d\\x65\\x52\\x13\\x0a\\x06\\x6e\\x75\\x6d\\x62\\x65\\x72\\x10\\x03\\x39\\x00\\x00\\x00\\x00\\x00\\x00\\xf0\\x3f\\x52\\x2c\\x0a\\x07\\x6e\\x75\\x6d\\x62\\x65\\x72\\x73\\x10\\x03\\x1a\\x05\\x63\\x6f\\x75\\x6e\\x74\\x3a\\x18\\x00\\x00\\x00\\x00\\x00\\x00\\xf0\\x3f\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x40\\x00\\x00\\x00\\x00\\x00\\x00\\x08\\x40\\x52\\x0e\\x0a\\x05\\x62\\x6f\\x6f\\x6c\\x73\\x10\\x04\\x42\\x03\\x01\\x00\\x00\\x52\\x0a\\x0a\\x04\\x62\\x6f\\x6f\\x6c\\x10\\x04\\x40\\x01\\x52\\x10\\x0a\\x06\\x73\\x74\\x72\\x69\\x6e\\x67\\x22\\x06\\x73\\x74\\x72\\x69\\x6e\\x67\\x52\\x15\\x0a\\x07\\x73\\x74\\x72\\x69\\x6e\\x67\\x73\\x22\\x02\\x73\\x31\\x22\\x02\\x73\\x32\\x22\\x02\\x73\\x33\";\n\n\nstruct log_message {\n  const char  *component;\n  int         severity;\n  char        msg[1024];\n};\n\nstatic struct log_message lm = { .component = NULL, .severity = 0, .msg = { 0 } };\n\nvoid log_cb(void *context, const char *component, int severity, const char *fmt,\n            ...)\n{\n  (void)context;\n  lm.component = component;\n  lm.severity = severity;\n  va_list args;\n  va_start(args, fmt);\n  vsnprintf(lm.msg, sizeof lm.msg, fmt, args);\n  va_end(args);\n}\nstatic lsb_logger logger = { .context = NULL, .cb = log_cb };\n\nstatic char* test_stub()\n{\n  return NULL;\n}\n\n\nstatic char* test_init()\n{\n  lsb_heka_message m;\n  mu_assert(!lsb_init_heka_message(&m, 10), \"failed\");\n  lsb_free_heka_message(&m);\n  lsb_free_heka_message(NULL);\n  return NULL;\n}\n\n\nstatic char* test_init_failure()\n{\n  lsb_heka_message m;\n  mu_assert(lsb_init_heka_message(&m, 0), \"suceeded\");\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_decode()\n{\n\n#define add_string(str) {.s = str, .len = sizeof str - 1},\n  lsb_const_string tests[] = {\n    add_string(TEST_UUID TEST_NS) // required fields\n    add_string(TEST_UUID TEST_NS \"\\x1a\\x04\" \"Type\")\n    add_string(TEST_UUID TEST_NS \"\\x22\\x06\" \"Logger\")\n    add_string(TEST_UUID TEST_NS \"\\x28\\x07\") // Severity\n    add_string(TEST_UUID TEST_NS \"\\x32\\x07\" \"Payload\")\n    add_string(TEST_UUID TEST_NS \"\\x3a\\x0a\" \"EnvVersion\")\n    add_string(TEST_UUID TEST_NS \"\\x40\\x11\") // Pid\n    add_string(TEST_UUID TEST_NS \"\\x4a\\x08\" \"Hostname\")\n    add_string(TEST_UUID TEST_NS \"\\x52\\x11\\x0a\\x03\" \"foo\\x10\\x00\\x1a\\x03\" \"rep\\x22\\x03\" \"bar\") // string\n    add_string(TEST_UUID TEST_NS \"\\x52\\x11\\x0a\\x03\" \"foo\\x10\\x01\\x1a\\x03\" \"rep\\x2a\\x03\" \"bar\") // bytes\n    add_string(TEST_UUID TEST_NS \"\\x52\\x0e\\x0a\\x03\" \"foo\\x10\\x02\\x1a\\x03\" \"rep\\x30\\x11\")    // integer\n    add_string(TEST_UUID TEST_NS \"\\x52\\x15\\x0a\\x03\" \"foo\\x10\\x03\\x1a\\x03\" \"rep\\x39\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\") // double\n    add_string(TEST_UUID TEST_NS \"\\x52\\x0e\\x0a\\x03\" \"foo\\x10\\x04\\x1a\\x03\" \"rep\\x40\\x01\") // bool\n  };\n\n  lsb_heka_message m;\n  mu_assert(!lsb_init_heka_message(&m, 1), \"failed\");\n  for (unsigned i = 0; i < sizeof tests / sizeof(lsb_const_string); ++i){\n    bool ok = lsb_decode_heka_message(&m, tests[i].s, tests[i].len, &logger);\n    mu_assert(ok, \"test: %d failed err: %s\", i, lm.msg);\n  }\n  mu_assert(!lsb_decode_heka_message(NULL, NULL, 0, NULL), \"succeeded\");\n  mu_assert(!lsb_decode_heka_message(&m, NULL, 0, NULL), \"succeeded\");\n  mu_assert(!lsb_decode_heka_message(&m, tests[0].s, 0, NULL), \"succeeded\");\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_decode_failure()\n{\n  struct decode_failure {\n    const char *s;\n    const char *e;\n  };\n\n  struct decode_failure tests[] = {\n    {   TEST_NS, \"missing Uuid\" } // required test\n    , { TEST_UUID, \"missing Timestamp\" } // require test\n    , { \"\\x0a\\x01\\xff\", \"tag:1 wiretype:2 position:0\" } // invalid UUID length\n    , { \"\\xf0\", \"tag:30 wiretype:0 position:0\" } // unknown message tag\n    , { \"\\x0b\", \"tag:1 wiretype:3 position:0\" } // uuid invalid wiretype\n    , { \"\\x11\", \"tag:2 wiretype:1 position:0\" } // timestamp invalid wiretype\n    , { \"\\x1b\", \"tag:3 wiretype:3 position:0\" } // type invalid wiretype\n    , { \"\\x23\", \"tag:4 wiretype:3 position:0\" } // logger invalid wiretype\n    , { \"\\x2b\", \"tag:5 wiretype:3 position:0\" } // severity invalid wiretype\n    , { \"\\x33\", \"tag:6 wiretype:3 position:0\" } // payload invalid wiretype\n    , { \"\\x3b\", \"tag:7 wiretype:3 position:0\" } // env_version invalid wiretype\n    , { \"\\x43\", \"tag:8 wiretype:3 position:0\" } // pid invalid wiretype\n    , { \"\\x4b\", \"tag:9 wiretype:3 position:0\" } // hostname invalid wiretype\n    , { \"\\x53\", \"tag:10 wiretype:3 position:0\" } // fields invalid wiretype\n    , { \"\\x52\\x10\", \"tag:10 wiretype:2 position:0\" } // invalid field length\n    , { \"\\x52\\x01\\x0b\", \"tag:10 wiretype:2 position:0\" } // invalid name wiretype\n    , { \"\\x52\\x01\\x13\", \"tag:10 wiretype:2 position:0\" } // invalid value_type wiretype\n    , { \"\\x52\\x01\\x1b\", \"tag:10 wiretype:2 position:0\" } // invalid representation wiretype\n    , { \"\\x52\\x01\\x23\", \"tag:10 wiretype:2 position:0\" } // invalid string wiretype\n    , { \"\\x52\\x01\\x2b\", \"tag:10 wiretype:2 position:0\" } // invalid bytes wiretype\n    , { \"\\x52\\x01\\x33\", \"tag:10 wiretype:2 position:0\" } // invalid integer wiretype\n    , { \"\\x52\\x01\\x3b\", \"tag:10 wiretype:2 position:0\" } // invalid bool wiretype\n    , { \"\\x52\\x01\\x43\", \"tag:10 wiretype:2 position:0\" } // invalid double wiretype\n    , { \"\\x52\\x01\\x4b\", \"tag:10 wiretype:2 position:0\" } // unknown field tag\n    , { \"\\x52\\xc\\x10\\x00\\x1a\\x03\" \"rep\\x22\\x03\" \"bar\", \"tag:10 wiretype:2 position:0\" } // no name\n    , { \"\\x10\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\", \"tag:2 wiretype:0 position:0\" } // invalid varint\n    , { \"\\x0a\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\", \"tag:1 wiretype:2 position:0\" } // invalid varint length\n  };\n\n  lsb_heka_message m;\n  mu_assert(!lsb_init_heka_message(&m, 10), \"failed\");\n  for (unsigned i = 0; i < sizeof(tests) / sizeof(struct decode_failure); ++i) {\n    bool ok = lsb_decode_heka_message(&m, tests[i].s, strlen(tests[i].s), &logger);\n    mu_assert(!ok, \"test: %u no error generated\", i);\n    mu_assert(!strcmp(lm.msg, tests[i].e), \"test: %u expected: %s received: %s\",\n              i, tests[i].e, lm.msg);\n  }\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_find_message()\n{\n  struct find_message {\n    lsb_const_string s;\n    bool             b;\n    size_t           d;\n  };\n\n#define ONE_TWENTY_SIX \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"\n#define add_input(str, result, discard) {.s = {.s = str, .len = sizeof str - 1}, .b = result, .d = discard},\n  struct find_message tests[] = {\n    add_input(\"\\x1e\\x02\\x08\\x14\\x1f\" TEST_UUID TEST_NS, true, 0) // full message\n    add_input(\"\\x1e\\x80\\x08\\x14\" ONE_TWENTY_SIX \"\\x1f\" TEST_UUID TEST_NS, true, 0) // large header\n    add_input(\"\\x1e\", false, 0)\n    add_input(\"\\x02\", false, 0)\n    add_input(\"\\x08\", false, 0)\n    add_input(\"\\x14\", false, 0)\n    add_input(\"\\x1f\", false, 0)\n    add_input(TEST_UUID, false, 0)\n    add_input(TEST_NS \"\\x1e\\x02\\x08\\x14\\x1f\", true, 0) // completion of an incremental message and the start of another\n    add_input(TEST_UUID TEST_NS, true, 0)\n    add_input(TEST_UUID TEST_NS, false, 20) // no framing\n    add_input(\"\\x1e\\x02\\x08\\x15\\x1f\" TEST_UUID TEST_NS \"\\x00\", false, 26) // message decode failure\n    add_input(\"\\x1e\\x02\\x08\\x00\\x1f\", false, 5) // header decoder failure\n    add_input(\"\\x1e\\x02\\x08\\x14\\x01\\x1f\", false, 6) // invalid header length\n    add_input(\"\\x1e\\x02\\x09\\x14\\x1f\", false, 5) // invalid protobuf header incorrect tag\n    add_input(\"\\x1e\\x02\\x08\\x65\\x1f\", false, 5) // invalid header message too long\n  };\n\n  lsb_heka_message m;\n  lsb_input_buffer ib;\n  size_t db;\n  mu_assert(!lsb_init_heka_message(&m, 1), \"failed\");\n  mu_assert(!lsb_init_input_buffer(&ib, 100), \"failed\");\n  for (unsigned i = 0; i < sizeof(tests) / sizeof(struct find_message); ++i) {\n    mu_assert(!lsb_expand_input_buffer(&ib, tests[i].s.len), \"buffer exhausted\");\n    memcpy(ib.buf + ib.readpos, tests[i].s.s, tests[i].s.len);\n    ib.readpos += tests[i].s.len;\n    bool b = lsb_find_heka_message(&m, &ib, true, &db, NULL);\n    mu_assert(tests[i].b == b, \"test: %u failed\", i);\n    mu_assert(tests[i].d == db, \"test: %u failed expected: %\" PRIuSIZE \" received: %\" PRIuSIZE, i, tests[i].d, db);\n  }\n  mu_assert(!lsb_find_heka_message(NULL, NULL, true, NULL, NULL), \"succeeded\");\n  mu_assert(!lsb_find_heka_message(&m, NULL, true, NULL, NULL), \"succeeded\");\n  mu_assert(!lsb_find_heka_message(&m, &ib, true, NULL, NULL), \"succeeded\");\n  lsb_free_input_buffer(&ib);\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_read_heka_field()\n{\n  lsb_heka_message m;\n  lsb_init_heka_message(&m, 8);\n  mu_assert(lsb_decode_heka_message(&m, pb, sizeof pb - 1, NULL), \"decode failed\");\n\n  lsb_read_value v;\n  lsb_const_string cs;\n  cs.s = \"string\";\n  cs.len = 6;\n  mu_assert(lsb_read_heka_field(&m, &cs, 0, 0, &v), \"standalone\");\n  mu_assert(v.type == LSB_READ_STRING, \"%d\", v.type);\n  mu_assert(strncmp(v.u.s.s, \"string\", v.u.s.len) == 0, \"invalid value: %.*s\",\n            (int)v.u.s.len, v.u.s.s);\n\n  cs.s = \"strings\";\n  cs.len = 7;\n  mu_assert(lsb_read_heka_field(&m, &cs, 0, 0, &v), \"item 0\");\n  mu_assert(v.type == LSB_READ_STRING, \"%d\", v.type);\n  mu_assert(strncmp(v.u.s.s, \"s1\", v.u.s.len) == 0, \"invalid value: %.*s\",\n            (int)v.u.s.len, v.u.s.s);\n\n  mu_assert(lsb_read_heka_field(&m, &cs, 0, 1, &v), \"item 1\");\n  mu_assert(v.type == LSB_READ_STRING, \"%d\", v.type);\n  mu_assert(strncmp(v.u.s.s, \"s2\", v.u.s.len) == 0, \"invalid value: %.*s\",\n            (int)v.u.s.len, v.u.s.s);\n\n  mu_assert(lsb_read_heka_field(&m, &cs, 0, 2, &v), \"item 2\");\n  mu_assert(v.type == LSB_READ_STRING, \"%d\", v.type);\n  mu_assert(strncmp(v.u.s.s, \"s3\", v.u.s.len) == 0, \"invalid value: %.*s\",\n            (int)v.u.s.len, v.u.s.s);\n\n  mu_assert(lsb_read_heka_field(&m, &cs, 0, 3, &v) == false,\n            \"no item 3\");\n  mu_assert(v.type == LSB_READ_NIL, \"%d\", v.type);\n\n  cs.s = \"number\";\n  cs.len = 6;\n  mu_assert(lsb_read_heka_field(&m, &cs, 0, 0, &v), \"standalone\");\n  mu_assert(v.type == LSB_READ_NUMERIC, \"%d\", v.type);\n  mu_assert(v.u.d == 1, \"invalid value: %g\", v.u.d);\n\n  cs.s = \"numbers\";\n  cs.len = 7;\n  mu_assert(lsb_read_heka_field(&m, &cs, 0, 0, &v), \"item 0\");\n  mu_assert(v.type == LSB_READ_NUMERIC, \"%d\", v.type);\n  mu_assert(v.u.d == 1, \"invalid value: %g\", v.u.d);\n\n  mu_assert(lsb_read_heka_field(&m, &cs, 0, 1, &v), \"item 1\");\n  mu_assert(v.type == LSB_READ_NUMERIC, \"%d\", v.type);\n  mu_assert(v.u.d == 2, \"invalid value: %g\", v.u.d);\n\n  mu_assert(lsb_read_heka_field(&m, &cs, 0, 2, &v), \"item 2\");\n  mu_assert(v.type == LSB_READ_NUMERIC, \"%d\", v.type);\n  mu_assert(v.u.d == 3, \"invalid value: %g\", v.u.d);\n\n  mu_assert(lsb_read_heka_field(&m, &cs, 0, 3, &v) == false,\n            \"no item 3\");\n  mu_assert(v.type == LSB_READ_NIL, \"%d\", v.type);\n\n  cs.s = \"bool\";\n  cs.len = 4;\n  mu_assert(lsb_read_heka_field(&m, &cs, 0, 0, &v), \"standalone\");\n  mu_assert(v.type == LSB_READ_BOOL, \"%d\", v.type);\n  mu_assert(v.u.d == 1, \"invalid value: %g\", v.u.d);\n\n  mu_assert(!lsb_read_heka_field(NULL, NULL, 0, 0, NULL), \"succeeded\");\n  mu_assert(!lsb_read_heka_field(&m, NULL, 0, 0, NULL), \"succeeded\");\n  mu_assert(!lsb_read_heka_field(&m, &cs, 0, 0, NULL), \"succeeded\");\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_write_heka_uuid()\n{\n  lsb_err_value ret;\n  lsb_output_buffer ob;\n  lsb_init_output_buffer(&ob, LSB_UUID_SIZE + 2);\n\n  const char header[2] = \"\\x0a\\x10\";\n  const char bin_uuid[LSB_UUID_SIZE] = { 0 };\n  ret = lsb_write_heka_uuid(&ob, bin_uuid, LSB_UUID_SIZE);\n  mu_assert(!ret, \"received %s\", ret);\n  mu_assert(ob.pos == LSB_UUID_SIZE + 2, \"received: %\" PRIuSIZE, ob.pos);\n  mu_assert(memcmp(ob.buf, header, sizeof header) == 0, \"invalid header\");\n  mu_assert(memcmp(ob.buf + 2, bin_uuid, LSB_UUID_SIZE) == 0, \"invalid\");\n\n  const char str_uuid[] = \"00000000-0000-0000-0000-\"\n      \"000000000000\";\n  ret = lsb_write_heka_uuid(&ob, str_uuid, LSB_UUID_STR_SIZE);\n  mu_assert(!ret, \"received %s\", ret);\n  mu_assert(ob.pos == LSB_UUID_SIZE + 2, \"received: %\" PRIuSIZE, ob.pos);\n  mu_assert(memcmp(ob.buf, header, sizeof header) == 0, \"invalid header\");\n  mu_assert(memcmp(ob.buf + 2, bin_uuid, LSB_UUID_SIZE) == 0, \"invalid\");\n\n  const char err_uuid[] = \"00000000+0000-0000-0000-\"\n      \"000000000000\";\n  ret = lsb_write_heka_uuid(&ob, err_uuid, LSB_UUID_STR_SIZE);\n  mu_assert(!ret, \"received %s\", ret);\n  mu_assert(ob.pos == LSB_UUID_SIZE + 2, \"received: %\" PRIuSIZE, ob.pos);\n  mu_assert(memcmp(ob.buf, header, sizeof header) == 0, \"invalid header\");\n  mu_assert(ob.buf[8] & 0x40, \"invalid format should create a type 4 uuid\");\n\n  ret = lsb_write_heka_uuid(&ob, NULL, 0);\n  mu_assert(!ret, \"received %s\", ret);\n  mu_assert(ob.pos == LSB_UUID_SIZE + 2, \"received: %\" PRIuSIZE, ob.pos);\n  mu_assert(ob.buf[8] & 0x40, \"null string should create a type 4 uuid\");\n  lsb_free_output_buffer(&ob);\n\n  ret = lsb_write_heka_uuid(&ob, bin_uuid, 10);\n  mu_assert(!ret, \"received %s\", ret);\n  mu_assert(ob.pos == LSB_UUID_SIZE + 2, \"received: %\" PRIuSIZE, ob.pos);\n  mu_assert(ob.buf[8] & 0x40, \"unexpected length should create a type 4 uuid\");\n  lsb_free_output_buffer(&ob);\n\n  lsb_output_buffer sob;\n  lsb_init_output_buffer(&sob, LSB_UUID_SIZE);\n  ret = lsb_write_heka_uuid(&sob, NULL, 0);\n  mu_assert(ret, \"received <no error>\");\n  mu_assert(sob.pos == 0, \"received: %\" PRIuSIZE, sob.pos);\n  lsb_free_output_buffer(&sob);\n\n  ret = lsb_write_heka_uuid(NULL, bin_uuid, LSB_UUID_SIZE);\n  mu_assert(ret == LSB_ERR_UTIL_NULL, \"received %s\", lsb_err_string(ret));\n\n  return NULL;\n}\n\n#if SIZE_MAX < 65536\nstatic char* test_write_heka_header()\n{\n  char header[LSB_MIN_HDR_SIZE];\n  size_t hlen;\n\n  for (unsigned i = 0; i < sizeof(size_t); ++i) {\n    hlen = lsb_write_heka_header(header, (size_t)1 << (i * 8));\n    mu_assert(hlen == 5 + i, \"i: %u received %\" PRIuSIZE, i, hlen);\n  }\n  hlen = lsb_write_heka_header(header, (size_t)1 << 15);\n  mu_assert(hlen == 7, \"received %\" PRIuSIZE, hlen);\n  return NULL;\n}\n#elif SIZE_MAX < 4294967296\nstatic char* test_write_heka_header()\n{\n  char header[LSB_MIN_HDR_SIZE];\n  size_t hlen;\n\n  for (unsigned i = 0; i < sizeof(size_t); ++i) {\n    hlen = lsb_write_heka_header(header, (size_t)1 << (i * 8));\n    mu_assert(hlen == 5 + i, \"i: %u received %\" PRIuSIZE, i, hlen);\n  }\n  hlen = lsb_write_heka_header(header, (size_t)1 << 31);\n  mu_assert(hlen == 9, \"received %\" PRIuSIZE, hlen);\n  return NULL;\n}\n#else\nstatic char* test_write_heka_header() // limit to 8 byte test\n{\n  char header[LSB_MIN_HDR_SIZE];\n  size_t hlen;\n\n  for (unsigned i = 0; i < 7; ++i) {\n    hlen = lsb_write_heka_header(header, (size_t)1 << (i * 8));\n    mu_assert(hlen == 5 + i, \"i: %u received %\" PRIuSIZE, i, hlen);\n  }\n  hlen = lsb_write_heka_header(header, (size_t)1 << 56);\n  mu_assert(hlen == 13, \"received %\" PRIuSIZE, hlen);\n  hlen = lsb_write_heka_header(header, (size_t)1 << 63);\n  mu_assert(hlen == 14, \"received %\" PRIuSIZE, hlen);\n  return NULL;\n}\n#endif\n\n\nstatic char* all_tests()\n{\n  mu_run_test(test_stub);\n  mu_run_test(test_init);\n  mu_run_test(test_init_failure);\n  mu_run_test(test_decode);\n  mu_run_test(test_decode_failure);\n  mu_run_test(test_find_message);\n  mu_run_test(test_read_heka_field);\n  mu_run_test(test_write_heka_uuid);\n  mu_run_test(test_write_heka_header);\n  return NULL;\n}\n\n\nint main()\n{\n  char *result = all_tests();\n  if (result) {\n    printf(\"%s\\n\", result);\n  } else {\n    printf(\"ALL TESTS PASSED\\n\");\n  }\n  printf(\"Tests run: %d\\n\", mu_tests_run);\n  return result != NULL;\n}\n"
  },
  {
    "path": "src/util/test/test_heka_message_matcher.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief Hindsight/Heka message matcher unit tests @file */\n\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#include \"luasandbox/test/mu_test.h\"\n#include \"luasandbox/util/heka_message.h\"\n#include \"luasandbox/util/heka_message_matcher.h\"\n\n// {\"Logger\":\"GoSpec\",\"Uuid\":\"xxx\",\"Pid\":32157,\"Severity\":6,\"EnvVersion\":\"0.8\",\"Fields\":[{\"\"value\":[\"bar\"],\"name\":\"foo\",\"value_type\":0},{\"value\":[64],\"name\":\"number\",\"value_type\":2},{\"value\":[\"data\"],\"name\":\"bytes\",\"value_type\":1},{\"value\":[999,1024],\"name\":\"int\",\"value_type\":2},{\"value\":[99.9],\"name\":\"double\",\"value_type\":3},{\"value\":[true],\"name\":\"bool\",\"value_type\":4},{\"value\":[\"alternate\"],\"name\":\"foo\",\"value_type\":0},{\"value\":[\"name=test;type=web;\"],\"name\":\"Payload\",\"value_type\":0},{\"representation\":\"date-time\",\"value\":[\"Mon Jan 02 15:04:05 -0700 2006\"],\"name\":\"Timestamp\",\"value_type\":0},{\"value\":[0],\"name\":\"zero\",\"value_type\":2},{\"value\":[\"43\"],\"name\":\"string\",\"value_type\":0}],\"Payload\":\"Test Payload with a longer string to attempt to create a difference in pattern match time versus the string literal match time for a unique-item\",\"Timestamp\":1.428773426113e+18,\"Hostname\":\"trink-x230\",\"Type\":\"TEST\"}\n\nchar pb[] = \"\\x0a\\x10\\x23\\x00\\x81\\xdc\\x32\\x6f\\x4e\\x3f\\x9a\\x5a\\x93\\x86\\xa3\\x7e\\x24\\x6f\\x10\\xe4\\x9e\\xf1\\xff\\xc6\\xbb\\x81\\xea\\x13\\x1a\\x04\\x54\\x45\\x53\\x54\\x22\\x06\\x47\\x6f\\x53\\x70\\x65\\x63\\x28\\x06\\x32\\x90\\x01Test Payload with a longer string to attempt to create a difference in pattern match time versus the string literal match time for a unique-item\\x3a\\x03\\x30\\x2e\\x38\\x40\\x9d\\xfb\\x01\\x4a\\x0a\\x74\\x72\\x69\\x6e\\x6b\\x2d\\x78\\x32\\x33\\x30\\x52\\x0c\\x0a\\x03\\x66\\x6f\\x6f\\x10\\x00\\x22\\x03\\x62\\x61\\x72\\x52\\x0d\\x0a\\x06\\x6e\\x75\\x6d\\x62\\x65\\x72\\x10\\x02\\x32\\x01\\x40\\x52\\x0f\\x0a\\x05\\x62\\x79\\x74\\x65\\x73\\x10\\x01\\x2a\\x04\\x64\\x61\\x74\\x61\\x52\\x0d\\x0a\\x03\\x69\\x6e\\x74\\x10\\x02\\x32\\x04\\xe7\\x07\\x80\\x08\\x52\\x14\\x0a\\x06\\x64\\x6f\\x75\\x62\\x6c\\x65\\x10\\x03\\x3a\\x08\\x9a\\x99\\x99\\x99\\x99\\xf9\\x58\\x40\\x52\\x0b\\x0a\\x04\\x62\\x6f\\x6f\\x6c\\x10\\x04\\x42\\x01\\x01\\x52\\x12\\x0a\\x03\\x66\\x6f\\x6f\\x10\\x00\\x22\\x09\\x61\\x6c\\x74\\x65\\x72\\x6e\\x61\\x74\\x65\\x52\\x20\\x0a\\x07\\x50\\x61\\x79\\x6c\\x6f\\x61\\x64\\x10\\x00\\x22\\x13\\x6e\\x61\\x6d\\x65\\x3d\\x74\\x65\\x73\\x74\\x3b\\x74\\x79\\x70\\x65\\x3d\\x77\\x65\\x62\\x3b\\x52\\x38\\x0a\\x09\\x54\\x69\\x6d\\x65\\x73\\x74\\x61\\x6d\\x70\\x10\\x00\\x1a\\x09\\x64\\x61\\x74\\x65\\x2d\\x74\\x69\\x6d\\x65\\x22\\x1e\\x4d\\x6f\\x6e\\x20\\x4a\\x61\\x6e\\x20\\x30\\x32\\x20\\x31\\x35\\x3a\\x30\\x34\\x3a\\x30\\x35\\x20\\x2d\\x30\\x37\\x30\\x30\\x20\\x32\\x30\\x30\\x36\\x52\\x0b\\x0a\\x04\\x7a\\x65\\x72\\x6f\\x10\\x02\\x32\\x01\\x00\\x52\\x0e\\x0a\\x06\\x73\\x74\\x72\\x69\\x6e\\x67\\x10\\x00\\x22\\x02\\x34\\x33\";\nsize_t pblen = sizeof(pb);\n\nchar pbmin[] = \"\\x0a\\x10\\x23\\x00\\x81\\xdc\\x32\\x6f\\x4e\\x3f\\x9a\\x5a\\x93\\x86\\xa3\\x7e\\x24\\x6f\\x10\\x00\";\nsize_t pbminlen = sizeof(pbmin);\n\n\nstatic char* test_stub()\n{\n  return NULL;\n}\n\n\nstatic char* test_api_assertion()\n{\n  mu_assert(NULL == lsb_create_message_matcher(NULL), \"not null\");\n  lsb_destroy_message_matcher(NULL);\n  return NULL;\n}\n\n#define T128 \"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' &&\" \\\n\"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' &&\" \\\n\"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' &&\" \\\n\"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' &&\" \\\n\"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' &&\" \\\n\"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' &&\" \\\n\"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' &&\" \\\n\"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' &&\" \\\n\"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' &&\" \\\n\"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' &&\" \\\n\"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' &&\" \\\n\"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' &&\" \\\n\"Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.' && Type =~ '.'\"\n\n#define S255 \"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\" \\\n\"0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\" \\\n\"0123456789012345678901234567890123456789012345678901234\"\n\nstatic char* test_true_matcher()\n{\n  char *tests[] = {\n    \"TRUE\"\n    , \"Timestamp > 1.428773420000e+18\"\n    , \"Timestamp < 1.428773426999e18\"\n    , \"Timestamp == 1428773426113040228\"\n    , \"Timestamp > '2015-04-11T17:30:26Z'\" // 1428773426000000000\n    , \"Timestamp > '2015-04-11T17:30:26.112Z'\"\n    , \"Timestamp < '2015-04-11T17:30:26.114Z'\"\n    , \"(Severity == 7 || Logger == 'GoSpec') && Type == 'TEST'\"\n    , \"EnvVersion == \\\"0.8\\\"\"\n    , \"EnvVersion == '0.8'\"\n    , \"EnvVersion != '0.9'\"\n    , \"EnvVersion > '0.7'\"\n    , \"EnvVersion >= '0.8'\"\n    , \"EnvVersion < '0.9'\"\n    , \"EnvVersion <= '0.8'\"\n    , \"Hostname != ''\"\n    , \"Logger == 'GoSpec'\"\n    , \"Pid != 0\"\n    , \"Pid != NIL\"\n    , \"Severity != 5\"\n    , \"Severity < 7\"\n    , \"Severity <= 7\"\n    , \"Severity <= 6\"\n    , \"Severity == 6\"\n    , \"Severity > 5\"\n    , \"Severity >= 5\"\n    , \"Severity >= 6\"\n    , \"Timestamp > 0\"\n    , \"Type != 'test'\"\n    , \"Type == 'TEST' && Severity == 6\"\n    , \"Type == 'test' && Severity == 7 || Logger == 'GoSpec'\"\n    , \"Type == 'TEST'\"\n    , \"Type == 'foo' || Type == 'bar' || Type == 'TEST'\"\n    , \"Fields[foo] == 'bar'\"\n    , \"Fields[foo][0] == 'bar'\"\n    , \"Fields[foo][0][0] == 'bar'\"\n    , \"Fields[foo][1] == 'alternate'\"\n    , \"Fields[foo][1][0] == 'alternate'\"\n    , \"Fields[foo] <= 'barx'\"\n    , \"Fields[foo] < 'barx'\"\n    , \"Fields[foo] >= 'bar'\"\n    , \"Uuid > '#'\"\n    , \"Uuid >= '#'\"\n    , \"Fields[foo] > 'baq'\"\n    , \"Fields[foo] != 'bara'\"\n    , \"Fields[bytes] == 'data'\"\n    , \"Fields[int] == 999\"\n    , \"Fields[int][0][1] == 1024\"\n    , \"Fields[double] == 99.9\"\n    , \"Fields[bool] == TRUE\"\n    , \"Fields[bool] != FALSE\"\n    , \"Fields[int] != NIL\"\n    , \"Fields[int][0][1] != NIL\"\n    , \"Fields[int][0][2] == NIL\"\n    , \"Fields[missing] == NIL\"\n    , \"Type =~ 'TEST'\"\n    , \"Type !~ 'bogus'\"\n    , \"Type =~ 'TEST' && Payload =~ 'Payload'\"\n    , \"Fields[foo][1] =~ 'alt'\"\n    , \"Fields[Payload] =~ 'name=%w+'\"\n    , \"Type =~ 'ST'\"\n    , \"Type =~ '^TE'\"\n    , \"Type =~ 'ST$'\"\n    , \"Type !~ '^te'\"\n    , \"Type !~ 'st$'\"\n    , \"Fields[foo][255] == NIL\"\n    , \"Fields[foo][0][255] == NIL\"\n    , T128\n    , \"Payload =~ 'unique-item'%\"\n    , \"Fields[Timestamp] =~ ' -0700'%\"\n    , \"Type != NIL\"\n    , \"Hostname != NIL\"\n    , \"EnvVersion != NIL\"\n    , \"Pid != NIL\"\n    , \"Logger != NIL\"\n    , \"Payload != NIL\"\n    , \"Pid == 32157\"\n    , \"Uuid < '\\\\\\\\'\"\n    , \"Uuid < \\\"\\\\\\\\\\\"\"\n    , \"(Severity == 7 || Logger == 'GoSpec') \\r\\n\\t&& Type == 'TEST'\"\n    , NULL };\n\n  lsb_heka_message m;\n  lsb_init_heka_message(&m, 16);\n  mu_assert(lsb_decode_heka_message(&m, pb, pblen - 1, NULL), \"decode failed\");\n  for (int i = 0; tests[i]; ++i) {\n    lsb_message_matcher *mm = lsb_create_message_matcher(tests[i]);\n    mu_assert(mm, \"failed to create the matcher %s\", tests[i]);\n    mu_assert(lsb_eval_message_matcher(mm, &m), \"%s\", tests[i]);\n    lsb_destroy_message_matcher(mm);\n  }\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_nil_header_true_matcher()\n{\n  char *tests[] = {\n    \"Type == NIL\"\n    , \"Type != ''\"\n    , \"Type < ''\"\n    , \"Type <= ''\"\n    , \"Type !~ '.'\"\n    , \"Type !~ 'foo'\"\n    , \"Hostname == NIL\"\n    , \"EnvVersion == NIL\"\n    , \"Pid == NIL\"\n    , \"Logger == NIL\"\n    , \"Payload == NIL\"\n    , NULL };\n\n  lsb_heka_message m;\n  lsb_init_heka_message(&m, 1);\n  mu_assert(lsb_decode_heka_message(&m, pbmin, pbminlen - 1, NULL), \"decode failed\");\n  for (int i = 0; tests[i]; ++i) {\n    lsb_message_matcher *mm = lsb_create_message_matcher(tests[i]);\n    mu_assert(mm, \"failed to create the matcher %s\", tests[i]);\n    mu_assert(lsb_eval_message_matcher(mm, &m), \"%s\", tests[i]);\n    lsb_destroy_message_matcher(mm);\n  }\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_nil_header_false_matcher()\n{\n  char *tests[] = {\n    \"Type != NIL\"\n    , \"Type == '%b()'\"\n    , \"Type == ''\"\n    , \"Type > ''\"\n    , \"Type >= ''\"\n    , \"Type =~ '.'\"\n    , \"Type =~ 'foo'\"\n    , \"Hostname != NIL\"\n    , \"Hostname == ''\"\n    , \"EnvVersion != NIL\"\n    , \"EnvVersion == ''\"\n    , \"Pid != NIL\"\n    , \"Logger != NIL\"\n    , \"Logger == ''\"\n    , \"Payload != NIL\"\n    , \"Payload == ''\"\n    , NULL };\n\n  lsb_heka_message m;\n  lsb_init_heka_message(&m, 1);\n  mu_assert(lsb_decode_heka_message(&m, pbmin, pbminlen - 1, NULL), \"decode failed\");\n  for (int i = 0; tests[i]; ++i) {\n    lsb_message_matcher *mm = lsb_create_message_matcher(tests[i]);\n    mu_assert(mm, \"failed to create the matcher %s\", tests[i]);\n    mu_assert(lsb_eval_message_matcher(mm, &m) == false, \"%s\", tests[i]);\n    lsb_destroy_message_matcher(mm);\n  }\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_false_matcher()\n{\n  char *tests[] = {\n    \"FALSE\"\n    , \"Timestamp == 1e9\"\n    , \"Timestamp > '2015-04-11T17:30:27Z'\"\n    , \"Type == 'test'&&(Severity==7||Payload=='Test Payload')\"\n    , \"EnvVersion == '0.9'\"\n    , \"EnvVersion != '0.8'\"\n    , \"EnvVersion > '0.9'\"\n    , \"EnvVersion >= '0.9'\"\n    , \"EnvVersion < '0.8'\"\n    , \"EnvVersion <= '0.7'\"\n    , \"Severity == 5\"\n    , \"Severity != 6\"\n    , \"Severity < 6\"\n    , \"Severity <= 5\"\n    , \"Severity > 6\"\n    , \"Severity >= 7\"\n    , \"Fields[foo] == 'ba'\"\n    , \"Fields[foo][1] == 'bar'\"\n    , \"Fields[foo][0][1] == 'bar'\"\n    , \"Fields[bool] == FALSE\"\n    , \"Fields[bool] != TRUE\"\n    , \"Fields[foo] > 'bara'\"\n    , \"Fields[foo] >= 'bara'\"\n    , \"Fields[foo] == 'bara'\"\n    , \"Type =~ 'Test'\"\n    , \"Type !~ 'TEST'\"\n    , \"Payload =~ '^Payload'\"\n    , \"Type == \\\"te'st\\\"\"\n    , \"Type == 'te\\\"st'\"\n    , \"Fields[int] =~ '999'\"\n    , \"Fields[zero] == \\\"0\\\"\"\n    , \"Fields[string] == 43\"\n    , \"Fields[int] == NIL\"\n    , \"Fields[int][0][1] == NIL\"\n    , \"Fields[missing] != NIL\"\n    , \"Type =~ '^te'\"\n    , \"Type =~ 'st$'\"\n    , \"Type !~ '^TE'\"\n    , \"Type !~ 'ST$'\"\n    , \"Logger =~ '.' && Type =~ '^anything'\"\n    , \"Type == '\" S255 \"'\"\n    , \"Payload =~ 'not.found'%\"\n    , \"Fields[foo][1] =~ 'not.found'%\"\n    , \"Type == NIL\"\n    , \"Hostname == NIL\"\n    , \"EnvVersion == NIL\"\n    , \"Pid == NIL\"\n    , \"Logger == NIL\"\n    , \"Payload == NIL\"\n    , \"Uuid > '\\\\\\\\'\"\n    , NULL };\n\n  lsb_heka_message m;\n  lsb_init_heka_message(&m, 8);\n  mu_assert(lsb_decode_heka_message(&m, pb, pblen - 1, NULL), \"decode failed\");\n  for (int i = 0; tests[i]; ++i) {\n    lsb_message_matcher *mm = lsb_create_message_matcher(tests[i]);\n    mu_assert(mm, \"failed to create the matcher %s\", tests[i]);\n    mu_assert(lsb_eval_message_matcher(mm, &m) == false, \"%s\", tests[i]);\n    lsb_destroy_message_matcher(mm);\n  }\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* test_malformed_matcher()\n{\n  char *tests[] = {\n    \"\"\n    , \"bogus\"\n    , \"Type = 'test'\"                                               // invalid operator\n    , \"Pid == 'test='\"                                              // Pid is not a string\n    , \"Type == 'test' && (Severity==7 || Payload == 'Test Payload'\" // missing paren\n    , \"Invalid == 'bogus'\"                                          // unknown variable name\n    , \"Fields[]\"                                                    // empty name key\n    , \"Fields[test][]\"                                              // empty field index\n    , \"Fields[test][a]\"                                             // non numeric field index\n    , \"Fields[test][0][]\"                                           // empty array index\n    , \"Fields[test][0][a]\"                                          // non numeric array index\n    , \"Fields[test][0][0][]\"                                        // extra index dimension\n    , \"Fields[test][xxxx\"                                           // unmatched bracket\n    , \"Pid =~ '6'\"                                                  // string match not allowed on numeric\n    , \"Pid !~ '6'\"                                                  // string match not allowed on numeric\n    , \"Type =~ 'test\"                                               // unmatched quote\n    , \"Type != 'test\\\"\"                                             // mis matched quote types\n    , \"Pid =~ 6\"                                                    // incorrect type for the operator\n    , \"NIL\"                                                         // invalid use of constant\n    , \"Type         > NIL\"                                          // existence check only works with equals and not equals\n    , \"Pid > NIL\"\n    , \"Fields[test] > NIL\"\n    , \"Uuid == NIL\"                                                 // required header, cannot be nil\n    , \"Severity == NIL\"                                             // defaulted header, cannot be nil\n    , \"TRUE FALSE\"                                                  // missing operator\n    , \"Timestamp == '20150411T173026'\"                              // non rfc3339 timestamp\n    , T128 \" && Type =~ '.'\"                                        // too many tests\n    , \"Type == '\" S255 \"5'\"                                         // string too long\n    , \"Fields[test][256] == 1\"                                      // field index out of bounds\n    , \"Fields[test][0][256] == 1\"                                   // array index out of bounds\n    , \"Payload =~ 'foo'i\"                                           // invalid string match pattern modifier\n    , \"Uuid < '\\\\'\"                                                 // unescaped backslash leaving an open string '\\'\n    , NULL };\n\n  lsb_heka_message m;\n  lsb_init_heka_message(&m, 8);\n  mu_assert(lsb_decode_heka_message(&m, pb, pblen - 1, NULL), \"decode failed\");\n  for (int i = 0; tests[i]; ++i) {\n    lsb_message_matcher *mm = lsb_create_message_matcher(tests[i]);\n    mu_assert(mm == NULL, \"created malformed matcher\");\n  }\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* benchmark_matcher_create()\n{\n  int iter = 100000;\n  const char *exp = \"Type == 'TEST' && Severity == 6\";\n\n  clock_t t = clock();\n  for (int x = 0; x < iter; ++x) {\n    lsb_message_matcher *mm = lsb_create_message_matcher(exp);\n    mu_assert(mm, \"lsb_create_message_matcher failed\");\n    lsb_destroy_message_matcher(mm);\n  }\n  t = clock() - t;\n  printf(\"benchmark_matcher_create: %g\\n\", ((double)t) / CLOCKS_PER_SEC\n         / iter);\n  return NULL;\n}\n\n\nstatic char* benchmark_match_hs()\n{\n  // see what a single sample looks like for a better comparison with Hindsight\n  char *tests[] = {\n    \"TRUE\"\n    , \"Type == 'TEST' && Severity == 6\"\n    , \"Fields[foo] == 'bar' && Severity == 6\"\n    , \"Fields[number] == 64 && Severity == 6\"\n    , \"Fields[missing] == NIL\"\n    , \"Fields[int] != NIL\"\n    , \"Type =~ '^[Tt]EST' && Severity == 6\"\n    , \"Payload =~ '^Test'\"\n    , \"Payload =~ 'item$'\"\n    , \"Payload =~ 'unique%-item'\"\n    , \"Payload =~ 'unique-item'%\"\n    , \"Payload =~ 'unique'\"\n    , \"Payload =~ 'unique'%\"\n    , NULL };\n\n  lsb_heka_message m;\n  lsb_init_heka_message(&m, 8);\n  mu_assert(lsb_decode_heka_message(&m, pb, pblen - 1, NULL), \"decode failed\");\n\n  unsigned long long start, end;\n  for (int i = 0; tests[i]; i++) {\n    lsb_message_matcher *mm = lsb_create_message_matcher(tests[i]);\n    mu_assert(mm, \"lsb_create_message_matcher failed: %s\", tests[i]);\n    start = lsb_get_time();\n    mu_assert(lsb_eval_message_matcher(mm, &m),\n              \"lsb_eval_message_matcher failed\");\n    end = lsb_get_time();\n    lsb_destroy_message_matcher(mm);\n    printf(\"matcher (lsb_get_time): '%s': %g\\n\", tests[i],\n           (double)(end - start) / 1e9);\n  }\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* benchmark_match()\n{\n  int iter = 1000000;\n  char *tests[] = {\n    \"TRUE\"\n    , \"Type == 'TEST' && Severity == 6\"\n    , \"Fields[foo] == 'bar' && Severity == 6\"\n    , \"Fields[number] == 64 && Severity == 6\"\n    , \"Fields[missing] == NIL\"\n    , \"Fields[int] != NIL\"\n    , \"Type =~ '^[Tt]EST' && Severity == 6\"\n    , \"Payload =~ '^Test'\"\n    , \"Payload =~ 'item$'\"\n    , \"Payload =~ 'unique%-item'\"\n    , \"Payload =~ 'unique-item'%\"\n    , \"Payload =~ 'unique'\"\n    , \"Payload =~ 'unique'%\"\n    , NULL };\n\n  lsb_heka_message m;\n  lsb_init_heka_message(&m, 8);\n  mu_assert(lsb_decode_heka_message(&m, pb, pblen - 1, NULL), \"decode failed\");\n\n  for (int i = 0; tests[i]; i++) {\n    lsb_message_matcher *mm = lsb_create_message_matcher(tests[i]);\n    mu_assert(mm, \"lsb_create_message_matcher failed: %s\", tests[i]);\n    clock_t t = clock();\n    for (int x = 0; x < iter; ++x) {\n      mu_assert(lsb_eval_message_matcher(mm, &m),\n                \"lsb_eval_message_matcher failed\");\n    }\n    t = clock() - t;\n    lsb_destroy_message_matcher(mm);\n    printf(\"matcher: '%s': %g\\n\", tests[i], ((double)t) / CLOCKS_PER_SEC\n           / iter);\n  }\n  lsb_free_heka_message(&m);\n  return NULL;\n}\n\n\nstatic char* all_tests()\n{\n  mu_run_test(test_stub);\n  mu_run_test(test_api_assertion);\n  mu_run_test(test_true_matcher);\n  mu_run_test(test_nil_header_true_matcher);\n  mu_run_test(test_false_matcher);\n  mu_run_test(test_nil_header_false_matcher);\n  mu_run_test(test_malformed_matcher);\n\n  mu_run_test(benchmark_match_hs);\n  mu_run_test(benchmark_matcher_create);\n  mu_run_test(benchmark_match);\n  return NULL;\n}\n\n\nint main()\n{\n  lsb_set_tz(NULL);\n  char *result = all_tests();\n  if (result) {\n    printf(\"%s\\n\", result);\n  } else {\n    printf(\"ALL TESTS PASSED\\n\");\n  }\n  printf(\"Tests run: %d\\n\", mu_tests_run);\n  return result != NULL;\n}\n"
  },
  {
    "path": "src/util/test/test_input_buffer.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief lsb_input_buffer unit tests @file */\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"luasandbox/error.h\"\n#include \"luasandbox/test/mu_test.h\"\n#include \"luasandbox/util/heka_message.h\"\n#include \"luasandbox/util/input_buffer.h\"\n\nstatic char* test_stub()\n{\n  return NULL;\n}\n\nstatic char* test_init_small_buf()\n{\n  size_t size = 100;\n  lsb_input_buffer b;\n\n  lsb_err_value ret = lsb_init_input_buffer(NULL, size);\n  mu_assert(ret == LSB_ERR_UTIL_NULL, \"received: %s\", lsb_err_string(ret));\n\n  mu_assert(!lsb_init_input_buffer(&b, size), \"init failed\");\n  mu_assert(b.size == size + LSB_MAX_HDR_SIZE, \"received: %\" PRIuSIZE,\n            b.size);\n  mu_assert(b.maxsize == size + LSB_MAX_HDR_SIZE, \"received: %\" PRIuSIZE,\n            b.size);\n  lsb_free_input_buffer(&b);\n  lsb_free_input_buffer(NULL);\n  return NULL;\n}\n\n\nstatic char* test_init_large_buf()\n{\n  size_t size = 1024 * 1024;\n  lsb_input_buffer b;\n  mu_assert(!lsb_init_input_buffer(&b, size), \"init failed\");\n  mu_assert(b.size == BUFSIZ, \"received: %\" PRIuSIZE, b.size);\n  mu_assert(b.maxsize == size + LSB_MAX_HDR_SIZE, \"received: %\" PRIuSIZE,\n            b.size);\n  lsb_free_input_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_init_zero_buf()\n{\n  lsb_input_buffer b;\n  lsb_err_value ret = lsb_init_input_buffer(&b, 0);\n  mu_assert(ret == LSB_ERR_UTIL_PRANGE, \"received: %s\", lsb_err_string(ret));\n  lsb_free_input_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_expand_buf()\n{\n  size_t size = 1024 * 1024;\n  size_t rsize = 1024 * 16;\n  lsb_input_buffer b;\n  mu_assert(!lsb_init_input_buffer(&b, size), \"init failed\");\n  mu_assert(b.size == BUFSIZ, \"received: %\" PRIuSIZE, b.size);\n\n  lsb_err_value ret = lsb_expand_input_buffer(NULL, 0);\n  mu_assert(LSB_ERR_UTIL_NULL == ret, \"received: %s\", lsb_err_string(ret));\n\n  mu_assert(!lsb_expand_input_buffer(&b, 1024 * 9), \"expand failed\");\n  mu_assert(b.size == rsize, \"received: %\" PRIuSIZE, b.size);\n  mu_assert(b.maxsize == size + LSB_MAX_HDR_SIZE, \"received: %\" PRIuSIZE,\n            b.size);\n\n  mu_assert(!lsb_expand_input_buffer(&b, 1024), \"expand failed\");\n  mu_assert(b.size == rsize, \"received: %\" PRIuSIZE, b.size);\n  mu_assert(b.maxsize == size + LSB_MAX_HDR_SIZE, \"received: %\" PRIuSIZE,\n            b.size);\n\n  lsb_free_input_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_expand_failure()\n{\n  size_t size = 1024;\n  lsb_input_buffer b;\n  mu_assert(!lsb_init_input_buffer(&b, size), \"init failed\");\n  lsb_err_value ret = lsb_expand_input_buffer(&b, size  + LSB_MAX_HDR_SIZE + 1);\n  mu_assert(LSB_ERR_UTIL_FULL == ret, \"received: %s\", lsb_err_string(ret));\n  lsb_free_input_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_shift_empty()\n{\n  size_t size = 16;\n  lsb_input_buffer b;\n  mu_assert(!lsb_init_input_buffer(&b, size), \"init failed\");\n  b.readpos = 10;\n  b.scanpos = 10;\n  mu_assert(!lsb_expand_input_buffer(&b, 1), \"expand failed\");\n  mu_assert(b.scanpos == 0, \"received: %\" PRIuSIZE, b.scanpos);\n  mu_assert(b.readpos == 0, \"received: %\" PRIuSIZE, b.readpos);\n  lsb_free_input_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_shift_partial()\n{\n  size_t size = 16;\n  lsb_input_buffer b;\n  mu_assert(!lsb_init_input_buffer(&b, size), \"init failed\");\n  memset(b.buf, '#', size);\n  b.readpos = 10;\n  b.scanpos = 9;\n  b.buf[b.scanpos] = 'A';\n  mu_assert(!lsb_expand_input_buffer(&b, 1), \"expand failed\");\n  mu_assert(b.scanpos == 0, \"received: %\" PRIuSIZE, b.scanpos);\n  mu_assert(b.readpos == 1, \"received: %\" PRIuSIZE, b.readpos);\n  mu_assert(b.buf[0] == 'A', \"received: %c\", b.buf[0]);\n  lsb_free_input_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* all_tests()\n{\n  mu_run_test(test_stub);\n  mu_run_test(test_init_small_buf);\n  mu_run_test(test_init_large_buf);\n  mu_run_test(test_init_zero_buf);\n  mu_run_test(test_expand_buf);\n  mu_run_test(test_expand_failure);\n  mu_run_test(test_shift_empty);\n  mu_run_test(test_shift_partial);\n  return NULL;\n}\n\n\nint main()\n{\n  char *result = all_tests();\n  if (result) {\n    printf(\"%s\\n\", result);\n  } else {\n    printf(\"ALL TESTS PASSED\\n\");\n  }\n  printf(\"Tests run: %d\\n\", mu_tests_run);\n  return result != NULL;\n}\n"
  },
  {
    "path": "src/util/test/test_output_buffer.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief lsb_output_buffer unit tests @file */\n\n#include <limits.h>\n#include <math.h>\n#include <stdio.h>\n#include <string.h>\n\n#include \"luasandbox/test/mu_test.h\"\n#include \"luasandbox/util/output_buffer.h\"\n#include \"luasandbox/util/heka_message.h\"\n\n#ifdef _MSC_VER\n// To silence the +/-INFINITY warning\n#pragma warning( disable : 4756 )\n#pragma warning( disable : 4056 )\n#endif\n\nstatic char* test_stub()\n{\n  return NULL;\n}\n\n\nstatic char* test_init_small_buf()\n{\n  size_t size = 512;\n  lsb_output_buffer b;\n\n  lsb_err_value ret = lsb_init_output_buffer(NULL, size);\n  mu_assert(ret == LSB_ERR_UTIL_NULL, \"received: %s\", lsb_err_string(ret));\n\n  mu_assert(!lsb_init_output_buffer(&b, size), \"init failed\");\n  mu_assert(b.size == size, \"received: %\" PRIuSIZE, b.size);\n  mu_assert(b.maxsize == size, \"received: %\" PRIuSIZE, b.size);\n  lsb_free_output_buffer(&b);\n  lsb_free_output_buffer(NULL);\n  return NULL;\n}\n\n\nstatic char* test_init_large_buf()\n{\n  size_t size = 1024 * 1024;\n  lsb_output_buffer b;\n  mu_assert(!lsb_init_output_buffer(&b, size), \"init failed\");\n  mu_assert(b.size == LSB_OUTPUT_SIZE, \"received: %\" PRIuSIZE, b.size);\n  mu_assert(b.maxsize == size , \"received: %\" PRIuSIZE, b.size);\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_init_zero_buf()\n{\n  lsb_output_buffer b;\n  mu_assert(!lsb_init_output_buffer(&b, 0), \"init failed\");\n  mu_assert(b.size == LSB_OUTPUT_SIZE, \"received: %\" PRIuSIZE, b.size);\n  mu_assert(b.maxsize == 0 , \"received: %\" PRIuSIZE, b.size);\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_expand_buf()\n{\n  size_t size = 1024 * 1024;\n  size_t rsize = 1024 * 16;\n  lsb_output_buffer b;\n  mu_assert(!lsb_init_output_buffer(&b, size), \"init failed\");\n  mu_assert(b.size == LSB_OUTPUT_SIZE, \"received: %\" PRIuSIZE, b.size);\n\n  lsb_err_value ret = lsb_expand_output_buffer(NULL, 0);\n  mu_assert(LSB_ERR_UTIL_NULL == ret, \"received: %s\", lsb_err_string(ret));\n\n  mu_assert(!lsb_expand_output_buffer(&b, 1024 * 9), \"expand failed\");\n  mu_assert(b.size == rsize, \"received: %\" PRIuSIZE, b.size);\n  mu_assert(b.maxsize == size, \"received: %\" PRIuSIZE, b.size);\n\n  mu_assert(!lsb_expand_output_buffer(&b, 1024), \"expand failed\");\n  mu_assert(b.size == rsize, \"received: %\" PRIuSIZE, b.size);\n  mu_assert(b.maxsize == size, \"received: %\" PRIuSIZE, b.size);\n\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_expand_failure()\n{\n  size_t size = 1024;\n  lsb_output_buffer b;\n  mu_assert(!lsb_init_output_buffer(&b, size), \"init failed\");\n  mu_assert(lsb_expand_output_buffer(&b, size + 1), \"expand succeeded\");\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_outputc()\n{\n  lsb_output_buffer b;\n  mu_assert(!lsb_init_output_buffer(&b, 0), \"init failed\");\n  lsb_outputc(&b, 'a');\n  mu_assert(strcmp(\"a\", b.buf) == 0, \"received: %s\", b.buf);\n  lsb_outputc(&b, 'b');\n  mu_assert(strcmp(\"ab\", b.buf) == 0, \"received: %s\", b.buf);\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_outputf()\n{\n  lsb_err_value ret;\n  lsb_output_buffer b;\n  mu_assert(!lsb_init_output_buffer(&b, 10), \"init failed\");\n  lsb_outputf(&b, \"%s\", \"foo\");\n  mu_assert(strcmp(\"foo\", b.buf) == 0, \"received: %s\", b.buf);\n  lsb_outputf(&b, \" %s\", \"bar\");\n  mu_assert(strcmp(\"foo bar\", b.buf) == 0, \"received: %s\", b.buf);\n  ret = lsb_outputf(&b, \" %s\", \"exceed the buffer\");\n  mu_assert(ret == LSB_ERR_UTIL_FULL, \"received: %s\", lsb_err_string(ret));\n  ret = lsb_outputf(NULL, \"%s\", \"bar\");\n  mu_assert(ret == LSB_ERR_UTIL_NULL, \"received: %s\", lsb_err_string(ret));\n  ret = lsb_outputf(&b, NULL, \"bar\");\n  mu_assert(ret == LSB_ERR_UTIL_NULL, \"received: %s\", lsb_err_string(ret));\n  lsb_free_output_buffer(&b);\n\n  size_t len = 2000;\n  mu_assert(!lsb_init_output_buffer(&b, len), \"init failed\");\n  for (size_t i = 0; i < len - 1; ++i) {\n    ret = lsb_outputf(&b, \"%c\", 'a');\n    mu_assert(!ret, \"received: %s\", ret);\n  }\n  ret = lsb_outputf(&b, \"%c\", 'a');\n  mu_assert(ret == LSB_ERR_UTIL_FULL, \"received: %s\", lsb_err_string(ret));\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_outputs()\n{\n  lsb_output_buffer b;\n  mu_assert(!lsb_init_output_buffer(&b, 0), \"init failed\");\n  lsb_outputs(&b, \"foo\", 3);\n  mu_assert(strcmp(\"foo\", b.buf) == 0, \"received: %s\", b.buf);\n  lsb_outputf(&b, \" bar\", 4);\n  mu_assert(strcmp(\"foo bar\", b.buf) == 0, \"received: %s\", b.buf);\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_outputd()\n{\n  lsb_output_buffer b;\n  mu_assert(!lsb_init_output_buffer(&b, 0), \"init failed\");\n  lsb_outputd(&b, 10.1);\n  mu_assert(strcmp(\"10.1\", b.buf) == 0, \"received: %s\", b.buf);\n  double d = INT_MAX;\n  lsb_outputd(&b, d + 1);\n  mu_assert(strcmp(\"10.12147483648\", b.buf) == 0, \"received: %s\", b.buf);\n  d = INT_MIN;\n  lsb_outputd(&b, d - 1);\n  mu_assert(strcmp(\"10.12147483648-2147483649\", b.buf) == 0,\n            \"received: %s\", b.buf);\n  lsb_outputd(&b, NAN);\n  mu_assert(strcmp(\"10.12147483648-2147483649nan\", b.buf) == 0,\n            \"received: %s\", b.buf);\n  lsb_outputd(&b, INFINITY);\n  mu_assert(strcmp(\"10.12147483648-2147483649naninf\", b.buf) == 0,\n            \"received: %s\", b.buf);\n  lsb_outputd(&b, -INFINITY);\n  mu_assert(strcmp(\"10.12147483648-2147483649naninf-inf\", b.buf) == 0,\n            \"received: %s\", b.buf);\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_outputc_full()\n{\n  lsb_output_buffer b;\n  mu_assert(!lsb_init_output_buffer(&b, 0), \"init failed\");\n  for (int i = 0; i < LSB_OUTPUT_SIZE; ++i) {\n    lsb_outputc(&b, 'a');\n  }\n  mu_assert(b.size == LSB_OUTPUT_SIZE * 2, \"received: %\" PRIuSIZE, b.size);\n  mu_assert(b.pos == LSB_OUTPUT_SIZE, \"received: %\" PRIuSIZE, b.pos);\n  mu_assert(b.buf[b.pos] == '\\0', \"missing NUL\");\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_outputf_full()\n{\n  lsb_output_buffer b;\n  mu_assert(!lsb_init_output_buffer(&b, 0), \"init failed\");\n  for (int i = 0; i < LSB_OUTPUT_SIZE; ++i) {\n    lsb_outputf(&b, \"%s\", \"f\");\n  }\n  mu_assert(b.size == LSB_OUTPUT_SIZE * 2, \"received: %\" PRIuSIZE, b.size);\n  mu_assert(b.pos == LSB_OUTPUT_SIZE, \"received: %\" PRIuSIZE, b.pos);\n  mu_assert(b.buf[b.pos] == '\\0', \"missing NUL\");\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_outputs_full()\n{\n  lsb_output_buffer b;\n  mu_assert(!lsb_init_output_buffer(&b, 0), \"init failed\");\n  for (int i = 0; i < LSB_OUTPUT_SIZE; ++i) {\n    lsb_outputs(&b, \"s\", 1);\n  }\n  mu_assert(b.size == LSB_OUTPUT_SIZE * 2, \"received: %\" PRIuSIZE, b.size);\n  mu_assert(b.pos == LSB_OUTPUT_SIZE, \"received: %\" PRIuSIZE, b.pos);\n  mu_assert(b.buf[b.pos] == '\\0', \"missing NUL\");\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* test_outputd_full()\n{\n  lsb_output_buffer b;\n  mu_assert(!lsb_init_output_buffer(&b, 0), \"init failed\");\n  for (int i = 0; i < LSB_OUTPUT_SIZE; ++i) {\n    lsb_outputd(&b, 1);\n  }\n  mu_assert(b.size == LSB_OUTPUT_SIZE * 2, \"received: %\" PRIuSIZE, b.size);\n  mu_assert(b.pos == LSB_OUTPUT_SIZE, \"received: %\" PRIuSIZE, b.pos);\n  mu_assert(b.buf[b.pos] == '\\0', \"missing NUL\");\n  lsb_free_output_buffer(&b);\n  return NULL;\n}\n\n\nstatic char* all_tests()\n{\n  mu_run_test(test_stub);\n  mu_run_test(test_init_small_buf);\n  mu_run_test(test_init_large_buf);\n  mu_run_test(test_init_zero_buf);\n  mu_run_test(test_expand_buf);\n  mu_run_test(test_expand_failure);\n  mu_run_test(test_outputc);\n  mu_run_test(test_outputf);\n  mu_run_test(test_outputs);\n  mu_run_test(test_outputd);\n\n  // make sure the terminating NUL is included in the size of the buffer\n  mu_run_test(test_outputc_full);\n  mu_run_test(test_outputf_full);\n  mu_run_test(test_outputs_full);\n  mu_run_test(test_outputd_full);\n  return NULL;\n}\n\n\nint main()\n{\n  char *result = all_tests();\n  if (result) {\n    printf(\"%s\\n\", result);\n  } else {\n    printf(\"ALL TESTS PASSED\\n\");\n  }\n  printf(\"Tests run: %d\\n\", mu_tests_run);\n  return result != NULL;\n}\n"
  },
  {
    "path": "src/util/test/test_protobuf.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief util protobuf unit tests @file */\n\n#include <stdio.h>\n#include <string.h>\n\n#include \"luasandbox/error.h\"\n#include \"luasandbox/test/mu_test.h\"\n#include \"luasandbox/util/heka_message.h\"\n#include \"luasandbox/util/protobuf.h\"\n\nstatic char* test_stub()\n{\n  return NULL;\n}\n\n\nstatic char* test_lsb_pb_read_key()\n{\n  int tag, wt;\n  const char input[] = \"\\x0b\";\n  const char *p = lsb_pb_read_key(input, &tag, &wt);\n  mu_assert(p = input + 1, \"received: %p\", (void *)p);\n  mu_assert(tag == 1, \"received: %d\", tag);\n  mu_assert(wt == 3, \"received: %d\", wt);\n  p = lsb_pb_read_key(NULL, &tag, &wt);\n  mu_assert(!p, \"not null\");\n  p = lsb_pb_read_key(input, NULL, &wt);\n  mu_assert(!p, \"not null\");\n  p = lsb_pb_read_key(input, &tag, NULL);\n  mu_assert(!p, \"not null\");\n  return NULL;\n}\n\n\nstatic char* test_lsb_pb_write_key()\n{\n  lsb_output_buffer ob;\n  lsb_init_output_buffer(&ob, LSB_MAX_VARINT_BYTES);\n\n  lsb_err_value ret = lsb_pb_write_key(&ob, 1, 3);\n  mu_assert(!ret, \"received %s\", ret);\n  mu_assert(memcmp(ob.buf, \"\\x0b\", 1) == 0, \"received: %02hhx\", ob.buf[0]);\n\n  ob.pos = ob.maxsize;\n  ret = lsb_pb_write_key(&ob, 1, 3);\n  mu_assert(ret == LSB_ERR_UTIL_FULL, \"received %s\", lsb_err_string(ret));\n  lsb_free_output_buffer(&ob);\n  return NULL;\n}\n\n\nstatic char* test_varint()\n{\n  struct test_data {\n    long long v;\n    const char *s;\n  };\n\n  struct test_data tests[] = {\n    { 0, \"\\x00\" },\n    { 16, \"\\x10\" },\n    { 300, \"\\xac\\x02\" },\n    { -1,  \"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\x01\" },\n    { 5000000000LL, \"\\x80\\xe4\\x97\\xd0\\x12\" }\n  };\n\n  lsb_err_value ret;\n  long long vi;\n  const char *p;\n  for (unsigned i = 0; i < sizeof tests / sizeof tests[0]; ++i){\n    long long v = tests[i].v;\n    const char *s = tests[i].s;\n    size_t len = strlen(s);\n    len = len ? len : 1;\n    p = lsb_pb_read_varint(s, s + len, &vi);\n    mu_assert(p = s + len, \"received: %p\", (void *)p);\n    mu_assert(v == vi, \"expected: %lld received: %lld\", v, vi);\n\n    lsb_output_buffer ob;\n    lsb_init_output_buffer(&ob, LSB_MAX_VARINT_BYTES);\n    ret = lsb_pb_write_varint(&ob, v);\n    mu_assert(!ret, \"received %s\", ret);\n    if (strncmp(s, ob.buf, len) != 0) {\n      char expected[LSB_MAX_VARINT_BYTES + 1] = { 0 };\n      char received[LSB_MAX_VARINT_BYTES + 1] = { 0 };\n      for (unsigned i = 0; i < len; ++i) {\n        sprintf(expected + i * 2, \"%02hhx\", s[i]);\n        sprintf(received + i * 2, \"%02hhx\", ob.buf[i]);\n      }\n      mu_assert(false, \"expected: %s received: %s\", expected, received);\n    }\n    lsb_free_output_buffer(&ob);\n  }\n\n  const char tl[] = \"\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\\xff\";\n  mu_assert(!lsb_pb_read_varint(tl, tl + sizeof(tl) - 1, &vi),\n            \"parsed invalid varint (too long)\");\n\n  const char ts[] = \"\\xff\";\n  mu_assert(!lsb_pb_read_varint(ts, ts + sizeof(ts) - 1, &vi),\n            \"parsed invalid varint (too short)\");\n\n  mu_assert(!lsb_pb_read_varint(NULL, ts + sizeof(ts) - 1, &vi), \"null start\");\n  mu_assert(!lsb_pb_read_varint(ts, NULL, &vi), \"null end\");\n  mu_assert(!lsb_pb_read_varint(ts, ts + sizeof(ts) - 1, NULL), \"null ret\");\n\n  lsb_output_buffer ob;\n  lsb_init_output_buffer(&ob, LSB_MAX_VARINT_BYTES);\n  ob.pos = ob.maxsize;\n  ret = lsb_pb_write_varint(&ob, 1);\n  mu_assert(ret == LSB_ERR_UTIL_FULL, \"received %s\", lsb_err_string(ret));\n  lsb_free_output_buffer(&ob);\n\n  return NULL;\n}\n\n\nstatic char* test_lsb_pb_write_bool()\n{\n  lsb_output_buffer ob;\n  lsb_init_output_buffer(&ob, 1);\n  lsb_err_value ret = lsb_pb_write_bool(&ob, 7);\n  mu_assert(!ret, \"received %s\", ret);\n  mu_assert(ob.buf[0] == 1, \"received: %02hhx\", ob.buf[0]);\n  mu_assert(lsb_pb_write_bool(&ob, 7), \"buffer should be full\");\n\n  ob.pos = 0;\n  ret = lsb_pb_write_bool(&ob, 0);\n  mu_assert(!ret, \"received %s\", ret);\n  mu_assert(ob.buf[0] == 0, \"received: %02hhx\", ob.buf[0]);\n\n  lsb_free_output_buffer(&ob);\n  return NULL;\n}\n\n\nstatic char* test_lsb_pb_write_double()\n{\n  double d = 7.13;\n  lsb_output_buffer ob;\n  lsb_init_output_buffer(&ob, sizeof d);\n  lsb_err_value ret = lsb_pb_write_double(&ob, d);\n  mu_assert(!ret, \"received %s\", ret);\n  mu_assert(memcmp(ob.buf, &d, sizeof d) == 0, \"received: %g\",\n            *((double *)ob.buf));\n  ret = lsb_pb_write_double(&ob, d);\n  mu_assert(ret == LSB_ERR_UTIL_FULL, \"received %s\", lsb_err_string(ret));\n  lsb_free_output_buffer(&ob);\n  return NULL;\n}\n\n\nstatic char* test_lsb_pb_write_string()\n{\n  lsb_output_buffer ob;\n  lsb_init_output_buffer(&ob, 64);\n  const char foo[] = \"foo\";\n  const size_t len = sizeof foo - 1;\n\n  // failure writing the key\n  ob.pos = ob.maxsize;\n  lsb_err_value ret = lsb_pb_write_string(&ob, 1, foo, len);\n  mu_assert(ret == LSB_ERR_UTIL_FULL, \"received %s\", lsb_err_string(ret));\n\n  // failure writing the len\n  ob.pos = ob.maxsize - 1;\n  ret = lsb_pb_write_string(&ob, 1, foo, len);\n  mu_assert(ret == LSB_ERR_UTIL_FULL, \"received %s\", lsb_err_string(ret));\n\n  // failure writing the string\n  ob.pos = ob.maxsize - 3;\n  ret = lsb_pb_write_string(&ob, 1, foo, len);\n  mu_assert(ret == LSB_ERR_UTIL_FULL, \"received %s\", lsb_err_string(ret));\n\n  ob.pos = 0;\n  ret = lsb_pb_write_string(&ob, 1, foo, len);\n  mu_assert(!ret, \"received %s\", ret);\n  mu_assert(ob.pos = len + 2, \"received: %\" PRIuSIZE, ob.pos);\n  mu_assert(memcmp(\"\\x0a\\x03\" \"foo\", ob.buf, 5) == 0, \"received: \"\n            \"%02hhx%02hhx%02hhx%02hhx2%hhx\", ob.buf[0], ob.buf[1], ob.buf[2],\n            ob.buf[3], ob.buf[4]);\n\n  lsb_free_output_buffer(&ob);\n  return NULL;\n}\n\n\nstatic char* test_lsb_pb_update_field_length()\n{\n  lsb_output_buffer ob;\n  lsb_init_output_buffer(&ob, 1024);\n  memset(ob.buf, 0, 1024);\n  ob.buf[0] = 'a';\n  ob.buf[2] = 'b';\n  ob.pos = 3;\n  lsb_err_value ret =  lsb_pb_update_field_length(&ob, 1);\n  mu_assert(!ret, \"received %s\", ret);\n  mu_assert(ob.buf[1] == 1, \"received: %d\", ob.buf[1]);\n  mu_assert(ob.buf[2] == 'b', \"received: %02hhx\", ob.buf[2]);\n  mu_assert(ob.pos == 3, \"received: %\" PRIuSIZE, ob.pos);\n\n  // buffer full\n  ob.pos = 1024;\n  ret = lsb_pb_update_field_length(&ob, 1);\n  mu_assert(ret == LSB_ERR_UTIL_FULL, \"received %s\", lsb_err_string(ret));\n\n  // position is out of bounds\n  ob.pos = 512;\n  ret = lsb_pb_update_field_length(&ob, 512);\n  mu_assert(ret == LSB_ERR_UTIL_PRANGE, \"received %s\", lsb_err_string(ret));\n\n  ob.buf[301] = 'x';\n  ob.pos = 302;\n  ret = lsb_pb_update_field_length(&ob, 1);\n  mu_assert(!ret, \"received %s\", ret);\n  mu_assert((unsigned char)ob.buf[1] == 0xac, \"received: %02hhx\", ob.buf[1]);\n  mu_assert(ob.buf[2] == 0x02, \"received: %02hhx\", ob.buf[2]);\n  mu_assert(ob.buf[3] == 'b', \"received: %02hhx\", ob.buf[3]);\n  mu_assert(ob.buf[302] == 'x', \"received: %02hhx\", ob.buf[302]);\n  mu_assert(ob.pos == 303, \"received: %\" PRIuSIZE, ob.pos);\n\n  lsb_free_output_buffer(&ob);\n  return NULL;\n}\n\nstatic char* all_tests()\n{\n  mu_run_test(test_stub);\n  mu_run_test(test_lsb_pb_read_key);\n  mu_run_test(test_lsb_pb_write_key);\n  mu_run_test(test_varint);\n  mu_run_test(test_lsb_pb_write_bool);\n  mu_run_test(test_lsb_pb_write_double);\n  mu_run_test(test_lsb_pb_write_string);\n  mu_run_test(test_lsb_pb_update_field_length);\n  return NULL;\n}\n\n\nint main()\n{\n  char *result = all_tests();\n  if (result) {\n    printf(\"%s\\n\", result);\n  } else {\n    printf(\"ALL TESTS PASSED\\n\");\n  }\n  printf(\"Tests run: %d\\n\", mu_tests_run);\n  return result != NULL;\n}\n"
  },
  {
    "path": "src/util/test/test_running_stats.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief lsb_input_buffer unit tests @file */\n\n#include <math.h>\n\n#include \"luasandbox/test/mu_test.h\"\n#include \"luasandbox/util/running_stats.h\"\n\n#ifdef _MSC_VER\n// To silence the +/-INFINITY warning\n#pragma warning( disable : 4756 )\n#pragma warning( disable : 4056 )\n#endif\n\nstatic char* test_stub()\n{\n  return NULL;\n}\n\n\nstatic char* test_init()\n{\n  lsb_running_stats stats;\n  lsb_init_running_stats(&stats);\n  mu_assert(stats.count == 0, \"received: %g\", stats.count);\n  mu_assert(stats.mean  == 0, \"received: %g\", stats.mean);\n  mu_assert(stats.sum == 0, \"received: %g\", stats.sum);\n  return NULL;\n}\n\n\nstatic char* test_calculation()\n{\n  lsb_running_stats stats;\n  lsb_init_running_stats(&stats);\n  double sd = lsb_sd_running_stats(&stats);\n  mu_assert(sd == 0, \"received: %g\", sd);\n  lsb_update_running_stats(&stats, 1.0);\n  lsb_update_running_stats(&stats, 2.0);\n  lsb_update_running_stats(&stats, 3.0);\n  mu_assert(stats.count == 3, \"received: %g\", stats.count);\n  mu_assert(stats.mean  == 2, \"received: %g\", stats.mean);\n  sd = lsb_sd_running_stats(&stats);\n  mu_assert(sd == 1.0, \"received: %g\", sd);\n  return NULL;\n}\n\n\nstatic char* test_nan_inf()\n{\n  lsb_running_stats stats;\n  lsb_init_running_stats(&stats);\n  double sd = lsb_sd_running_stats(&stats);\n  mu_assert(sd == 0, \"received: %g\", sd);\n  lsb_update_running_stats(&stats, INFINITY);\n  lsb_update_running_stats(&stats, NAN);\n  lsb_update_running_stats(&stats, -INFINITY);\n  mu_assert(stats.count == 0, \"received: %g\", stats.count);\n  sd = lsb_sd_running_stats(&stats);\n  mu_assert(sd == 0, \"received: %g\", sd);\n  return NULL;\n}\n\n\nstatic char* all_tests()\n{\n  mu_run_test(test_stub);\n  mu_run_test(test_init);\n  mu_run_test(test_calculation);\n  mu_run_test(test_nan_inf);\n  return NULL;\n}\n\n\nint main()\n{\n  char* result = all_tests();\n  if (result) {\n    printf(\"%s\\n\", result);\n  } else {\n    printf(\"ALL TESTS PASSED\\n\");\n  }\n  printf(\"Tests run: %d\\n\", mu_tests_run);\n  return result != NULL;\n}\n"
  },
  {
    "path": "src/util/test/test_string.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief lsb_input_buffer unit tests @file */\n\n#include <stdlib.h>\n#include <string.h>\n\n#include \"luasandbox/test/mu_test.h\"\n#include \"luasandbox/util/string.h\"\n\nstatic char* test_stub()\n{\n  return NULL;\n}\n\ntypedef struct {\n  char *s;\n  char *r;\n  size_t len;\n} testcase;\n\n\nstatic char* test_success()\n{\n  testcase tests[] = {\n    {\"TRUE\"         ,\"TRUE\"   ,4},\n    {\"\\\\a\"          ,\"\\a\"     ,1},\n    {\"\\\\b\"          ,\"\\b\"     ,1},\n    {\"\\\\f\"          ,\"\\f\"     ,1},\n    {\"\\\\n\"          ,\"\\n\"     ,1},\n    {\"\\\\r\"          ,\"\\r\"     ,1},\n    {\"\\\\t\"          ,\"\\t\"     ,1},\n    {\"\\\\v\"          ,\"\\v\"     ,1},\n    {\"\\\\\\\"\"         ,\"\\\"\"     ,1},\n    {\"\\\\'\"          ,\"'\"      ,1},\n    {\"\\\\\\\\\"         ,\"\\\\\"     ,1},\n    {\"\\\\?\"          ,\"?\"      ,1},\n    {\"\\\\1\"          ,\"\\1\"     ,1},\n    {\"\\\\33\"         ,\"!\"      ,1},\n    {\"\\\\109\"        ,\"m\"      ,1},\n    {\"+\\\\99\\\\1009+\" ,\"+cd9+\"  ,5},\n    {\"1\\\\000M\"      ,\"1\\x00M\" ,3},\n  };\n\n  for (unsigned i = 0; i < sizeof tests / sizeof(testcase); ++i){\n    testcase *tc = &tests[i];\n    size_t len = strlen(tc->s) + 1;\n    char *d = malloc(len);\n    char *us = lsb_lua_string_unescape(d, tc->s, &len);\n    mu_assert(us, \"test: %d valid string: %s\", i, tc->s);\n    mu_assert(len == tc->len, \"test: %d string: %s expected len: %\" PRIuSIZE\n              \" received: %\" PRIuSIZE, i, tc->s, tc->len, len);\n    mu_assert(memcmp(us, tc->r, len) == 0, \"test: %d memcmp string: %s\", i,\n              tc->s);\n    free(d);\n  }\n  return NULL;\n}\n\n\nstatic char* test_failure()\n{\n  testcase tests[] = {\n    {\"\\\\p\"    ,NULL ,2}, // invalid escape char\n    {\"\\\\999\"  ,NULL ,4}, // invalid char value\n    {\"foo\"    ,NULL ,2}, // destination too small\n    {NULL     ,NULL ,2}, // NULL source\n  };\n\n  for (unsigned i = 0; i < sizeof tests / sizeof(testcase); ++i){\n    testcase *tc = &tests[i];\n    size_t len = tc->len + 1;\n    char *d = malloc(len);\n    mu_assert(!lsb_lua_string_unescape(d, tc->s, &len),\n              \"test: %d invalid string: %s\", i, tc->s);\n    free(d);\n  }\n  mu_assert(!lsb_lua_string_unescape(NULL, tests[0].s, &tests[0].len),\n            \"NULL destination\");\n\n  char d[3];\n  mu_assert(!lsb_lua_string_unescape(d, tests[0].s, NULL), \"NULL length\");\n  return NULL;\n}\n\n\nstatic char* all_tests()\n{\n  mu_run_test(test_stub);\n  mu_run_test(test_success);\n  mu_run_test(test_failure);\n  return NULL;\n}\n\n\nint main()\n{\n  char *result = all_tests();\n  if (result) {\n    printf(\"%s\\n\", result);\n  } else {\n    printf(\"ALL TESTS PASSED\\n\");\n  }\n  printf(\"Tests run: %d\\n\", mu_tests_run);\n  return result != NULL;\n}\n"
  },
  {
    "path": "src/util/test/test_string_matcher.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief lsb_input_buffer unit tests @file */\n\n#include <string.h>\n\n#include \"luasandbox/test/mu_test.h\"\n#include \"luasandbox/util/string_matcher.h\"\n\nstatic char* test_stub()\n{\n  return NULL;\n}\n\n\nstatic char* test_success()\n{\n  char *tests[] = {\n    \" \"  , \".\"\n    , \"foobar\", \"foo\"\n    , \"foobar\", \"bar$\"\n    , \"a\"     , \"%a\"\n    , \"1\"     , \"%d\"\n    , \"a\"     , \"%l\"\n    , \",\"     , \"%p\"\n    , \"\\t\"    , \"%s\"\n    , \"A\"     , \"%u\"\n    , \"a\"     , \"%w\"\n    , \"f\"     , \"%x\"\n    , \"%\"     , \"%%\"\n    , \"a\"     , \"[a-c]\"\n    , \"d\"     , \"[^a-c]\"\n    , \"abc\"   , \"^%a+$\"\n    , \"(\"     , \"(\"\n    , \"|foo|\" , \"%b||\"\n    , \"?\"     , \"%?\"\n    , \"+\"     , \"%+\"\n    , \"-\"     , \"%-\"\n    , \"*\"     , \"%*\"\n    , \"%\"     , \"%%\"\n    , \".\"     , \"%.\"\n    , \"^\"     , \"%^\"\n    , \"$\"     , \"%$\"\n    , \"[\"     , \"%[\"\n    , \"]\"     , \"%]\"\n    , \"]\"     , \"]\"\n    , \"(\"     , \"%(\"\n    , \")\"     , \"%)\"\n    , \")\"     , \")\"\n    , \"abc\"   , \"^%a-$\"\n    , \"a$c\"   , \"a$c\"\n    , \"a\"     , \"%a?\"\n    , \"abc\"   , \"%a*\"\n    , \"123ab\" , \"%f[%a]\"\n    , NULL\n  };\n\n  for (int i = 0; tests[i]; i += 2) {\n    mu_assert(lsb_string_match(tests[i], strlen(tests[i]), tests[i + 1]),\n              \"no match test: %d string: %s pattern: %s\", i / 2, tests[i],\n              tests[i + 1]);\n  }\n  mu_assert(lsb_string_match(\"\\0\", 1, \"%z\"), \"NULL match\");\n  return NULL;\n}\n\n\nstatic char* test_find_success()\n{\n  char *tests[] = {\n    \"foo.\"  , \".\"\n    , \"foobar\", \"foo\"\n    , \"foo-bar\", \"o-b\"\n    , NULL\n  };\n\n  for (int i = 0; tests[i]; i += 2) {\n    mu_assert(lsb_string_find(tests[i], strlen(tests[i]), tests[i + 1], strlen(tests[i + 1])),\n              \"not found test: %d string: %s pattern: %s\", i / 2, tests[i],\n              tests[i + 1]);\n  }\n  return NULL;\n}\n\n\nstatic char* test_failure()\n{\n  char *tests[] = {\n    \"\"  , \".\"\n    , \"_foobar\", \"^foo\"\n    , \"foobar_\", \"bar$\"\n    , \"1\"     , \"%a\"\n    , \"a\"     , \"%d\"\n    , \"A\"     , \"%l\"\n    , \"a\"     , \"%p\"\n    , \".\"     , \"%s\"\n    , \"a\"     , \"%u\"\n    , \".\"     , \"%w\"\n    , \"p\"     , \"%x\"\n    , \"a\"     , \"%%\"\n    , \"d\"     , \"[a-c]\"\n    , \"a\"     , \"[^a-c]\"\n    , \"a.\"    , \"^%a+$\"\n    , \"foo()\" , \"bar()\"\n    , \"|foo\"  , \"%b||\"\n    , \"aa\"    , \"(%a)%1*\"\n    , NULL\n  };\n\n  for (int i = 0; tests[i]; i += 2) {\n    mu_assert(!lsb_string_match(tests[i], strlen(tests[i]), tests[i + 1]),\n              \"match test: %d string: %s pattern: %s\", i / 2, tests[i],\n              tests[i + 1]);\n  }\n  return NULL;\n}\n\n\nstatic char* test_find_failure()\n{\n  char *tests[] = {\n    \"foo\"        , \".\"\n    , \"foobar\"  , \"longer string\"\n    , NULL\n  };\n\n  for (int i = 0; tests[i]; i += 2) {\n    mu_assert(!lsb_string_find(tests[i], strlen(tests[i]), tests[i + 1], strlen(tests[i + 1])),\n              \"find test: %d string: %s pattern: %s\", i / 2, tests[i],\n              tests[i + 1]);\n  }\n  mu_assert(!lsb_string_find(NULL, 0, tests[0], strlen(tests[1])),\n            \"find test: string: NULL pattern: %s\", tests[1]);\n  mu_assert(!lsb_string_find(tests[0], strlen(tests[0]), NULL, 0),\n            \"find test: string: %s pattern: NULL\", tests[0]);\n  return NULL;\n}\n\n\nstatic char* test_invalid()\n{\n  char *tests[] = {\n    \"\"    , \"[f\"\n    , \"\"  , \"%b|\"\n    , \"\"  , \"?\"\n    , \"\"  , \"+\"\n    , \"\"  , \"-\"\n    , \"\"  , \"*\"\n    , \"\"  , \"%\"\n    , NULL\n  };\n\n  for (int i = 0; tests[i]; i += 2) {\n    mu_assert(!lsb_string_match(tests[i], strlen(tests[i]), tests[i + 1]),\n              \"invalid test: %d string: %s pattern: %s\", i / 2, tests[i],\n              tests[i + 1]);\n  }\n  mu_assert(!lsb_string_match(NULL, 0, tests[1]),\n            \"invalid test: string: NULL pattern: %s\", tests[1]);\n  mu_assert(!lsb_string_match(tests[0], strlen(tests[0]), NULL),\n            \"invalid test: string: %s pattern: NULL\", tests[0]);\n  return NULL;\n}\n\n\nstatic char* all_tests()\n{\n  mu_run_test(test_stub);\n  mu_run_test(test_success);\n  mu_run_test(test_find_success);\n  mu_run_test(test_failure);\n  mu_run_test(test_find_failure);\n  mu_run_test(test_invalid);\n  return NULL;\n}\n\n\nint main()\n{\n  char *result = all_tests();\n  if (result) {\n    printf(\"%s\\n\", result);\n  } else {\n    printf(\"ALL TESTS PASSED\\n\");\n  }\n  printf(\"Tests run: %d\\n\", mu_tests_run);\n  return result != NULL;\n}\n"
  },
  {
    "path": "src/util/test/test_util.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** @brief lsb_util unit tests @file */\n\n#include <inttypes.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n#include \"luasandbox/error.h\"\n#include \"luasandbox/test/mu_test.h\"\n#include \"luasandbox/util/util.h\"\n\nstatic char* test_stub()\n{\n  return NULL;\n}\n\n\nstatic char* test_lsb_lp2()\n{\n  size_t lp2;\n\n  lp2 = lsb_lp2(0);\n  mu_assert(lp2 == 0, \"received: %\" PRIuSIZE, lp2);\n\n  lp2 = lsb_lp2(1);\n  mu_assert(lp2 == 1, \"received: %\" PRIuSIZE, lp2);\n\n  lp2 = lsb_lp2(1000);\n  mu_assert(lp2 == 1024, \"received: %\" PRIuSIZE, lp2);\n  return NULL;\n}\n\n\nstatic char* test_lsb_read_file()\n{\n  char *s = lsb_read_file(\"Makefile\");\n  mu_assert(s, \"read file failed\");\n  free(s);\n\n  s = lsb_read_file(\"_foo_bar_\");\n  free(s); // if it succeeded don't leak\n  mu_assert(!s, \"read file succeeded\");\n  return NULL;\n}\n\n\nstatic char* test_lsb_set_tz()\n{\n  mu_assert(lsb_set_tz(NULL), \"set_tz failed\");\n  mu_assert(lsb_set_tz(\"America/Los_Angeles\"), \"set_tz failed\");\n  static const char too_long[] = \"01234567890123456789012345678901\";\n#ifdef _WIN32\n  mu_assert(!lsb_set_tz(too_long), \"set_tz succeeded\");\n#else\n  mu_assert(lsb_set_tz(too_long), \"set_tz failed\");\n#endif\n  return NULL;\n}\n\n\nstatic char* benchmark_lsb_get_time()\n{\n  int iter = 1000000;\n  unsigned long long start, end;\n  clock_t t = clock();\n  for (int x = 0; x < iter; ++x) {\n    lsb_get_time();\n  }\n  t = clock() - t;\n  printf(\"benchmark_lsb_get_time(%d) - clock %g seconds\\n\", iter,\n         (double)t / CLOCKS_PER_SEC / iter);\n\n  start = lsb_get_time();\n  for (int x = 0; x < iter; ++x) {\n    lsb_get_time();\n  }\n  end = lsb_get_time();\n  printf(\"benchmark_lsb_get_time(%d) - self %g seconds\\n\", iter,\n         (double)(end - start) / iter / 1e9);\n\n  start = lsb_get_time();\n  lsb_get_time();\n  end = lsb_get_time();\n  printf(\"benchmark_lsb_get_time(1) %llu\\n\", end - start);\n  return NULL;\n}\n\n\nstatic char* benchmark_lsb_get_timestamp()\n{\n  int iter = 1000000;\n  clock_t t = clock();\n  for (int x = 0; x < iter; ++x) {\n    lsb_get_timestamp();\n  }\n  t = clock() - t;\n  printf(\"benchmark_lsb_get_timestamp(%d) - clock %g seconds\\n\", iter,\n         (double)t / CLOCKS_PER_SEC / iter);\n  long long delta = lsb_get_timestamp() / 1000000000LL - time(NULL);\n  mu_assert(delta > 0 ? delta <= 1 : delta >= -1, \"delta %lld\", delta);\n  return NULL;\n}\n\n\nstatic char* all_tests()\n{\n  mu_run_test(test_stub);\n  mu_run_test(test_lsb_lp2);\n  mu_run_test(test_lsb_read_file);\n  mu_run_test(test_lsb_set_tz);\n\n  mu_run_test(benchmark_lsb_get_time);\n  mu_run_test(benchmark_lsb_get_timestamp);\n  return NULL;\n}\n\n\nint main()\n{\n  char *result = all_tests();\n  if (result) {\n    printf(\"%s\\n\", result);\n  } else {\n    printf(\"ALL TESTS PASSED\\n\");\n  }\n  printf(\"Tests run: %d\\n\", mu_tests_run);\n  return result != NULL;\n}\n"
  },
  {
    "path": "src/util/util.c",
    "content": "/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */\n/* vim: set ts=2 et sw=2 tw=80: */\n/* This Source Code Form is subject to the terms of the Mozilla Public\n * License, v. 2.0. If a copy of the MPL was not distributed with this\n * file, You can obtain one at http://mozilla.org/MPL/2.0/. */\n\n/** General purpose utility functions @file */\n\n#include \"luasandbox/util/util.h\"\n#include \"../luasandbox_defines.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <time.h>\n\n#ifdef _WIN32\n#include <windows.h>\n#include <limits.h>\n#else\n#include <sys/time.h>\n#endif\n\n#if defined(__MACH__) && defined(__APPLE__)\n#include <mach/clock.h>\n#include <mach/mach.h>\n#include <mach/mach_time.h>\n#endif\n\nlsb_err_id LSB_ERR_UTIL_NULL    = \"pointer is NULL\";\nlsb_err_id LSB_ERR_UTIL_OOM     = \"memory allocation failed\";\nlsb_err_id LSB_ERR_UTIL_FULL    = \"buffer full\";\nlsb_err_id LSB_ERR_UTIL_PRANGE  = \"parameter out of range\";\n\nsize_t lsb_lp2(unsigned long long x)\n{\n  if (x == 0) return 0;\n  x = x - 1;\n  x = x | (x >> 1);\n  x = x | (x >> 2);\n  x = x | (x >> 4);\n  x = x | (x >> 8);\n  x = x | (x >> 16);\n  x = x | (x >> 32);\n  return (size_t)(x + 1);\n}\n\n\nchar* lsb_read_file(const char *fn)\n{\n  char *str = NULL;\n  size_t b;\n  FILE *fh = fopen(fn, \"rb\" CLOSE_ON_EXEC);\n  if (!fh) return str;\n\n  if (fseek(fh, 0, SEEK_END)) goto cleanup;\n  long pos = ftell(fh);\n  if (pos == -1) goto cleanup;\n  rewind(fh);\n\n  str = malloc(pos + 1);\n  if (!str) goto cleanup;\n\n  b = fread(str, 1, pos, fh);\n  if ((long)b == pos) {\n    str[pos] = 0;\n  }\n\ncleanup:\n  fclose(fh);\n  return str;\n}\n\n\nunsigned long long lsb_get_time()\n{\n#ifdef HAVE_CLOCK_GETTIME\n  struct timespec ts;\n  clock_gettime(CLOCK_MONOTONIC, &ts);\n  return ts.tv_sec * 1000000000ULL + ts.tv_nsec;\n#elif defined(__MACH__) && defined(__APPLE__)\n  static unsigned long long convert = 0;\n  if (convert == 0) {\n    mach_timebase_info_data_t tbi;\n    (void)mach_timebase_info(&tbi);\n    convert = tbi.numer / tbi.denom;\n  }\n  return mach_absolute_time() * convert;\n#elif defined(_WIN32)\n  static unsigned long long qpf = ULLONG_MAX;\n  static_assert(sizeof(LARGE_INTEGER) == sizeof qpf, \"size mismatch\");\n\n  unsigned long long t;\n  if (qpf == ULLONG_MAX) QueryPerformanceFrequency((LARGE_INTEGER *)&qpf);\n  if (qpf) {\n    QueryPerformanceCounter((LARGE_INTEGER *)&t);\n    return (t / qpf * 1000000000ULL) + ((t % qpf) * 1000000000ULL / qpf);\n  } else {\n    FILETIME ft;\n    GetSystemTimeAsFileTime(&ft);\n    t = ft.dwHighDateTime;\n    t <<= 32;\n    t |= ft.dwLowDateTime;\n    return t * 100ULL;\n  }\n#else\n  struct timeval tv;\n  gettimeofday(&tv, NULL);\n  return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ULL;\n#endif\n}\n\n\nlong long lsb_get_timestamp()\n{\n#ifdef HAVE_CLOCK_GETTIME\n  struct timespec ts;\n  clock_gettime(CLOCK_REALTIME, &ts);\n  return ts.tv_sec * 1000000000LL + ts.tv_nsec;\n#elif defined(__MACH__) && defined(__APPLE__)\n  clock_serv_t cclock;\n  mach_timespec_t mts;\n  host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);\n  clock_get_time(cclock, &mts);\n  mach_port_deallocate(mach_task_self(), cclock);\n  return mts.tv_sec * 1000000000LL + mts.tv_nsec;\n#elif defined(_WIN32)\n  FILETIME ft;\n  GetSystemTimeAsFileTime(&ft);\n  unsigned long long t = ft.dwHighDateTime;\n  t <<= 32;\n  t |= ft.dwLowDateTime;\n  t -= 116444736000000000ULL; // convert from Jan 1 1601 to Jan 1 1970\n  return t * 100LL;\n#else\n  struct timeval tv;\n  gettimeofday(&tv, NULL);\n  return tv.tv_sec * 1000000000LL + tv.tv_usec * 1000LL;\n#endif\n}\n\n\nbool lsb_set_tz(const char *tz)\n{\n  if (!tz) {\n    tz = \"UTC\";\n  }\n#if _WIN32\n  char s[32];\n  int n = _snprintf(s, sizeof(s), \"TZ=%s\", tz);\n  if (n < 0 || n >= sizeof(s) || _putenv(s) != 0) {\n    return false;\n  }\n#else\n  if (setenv(\"TZ\", tz, 1) != 0) {\n    return false;\n  }\n#endif\n  return true;\n}\n"
  }
]