<commit_before>/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "../scanner.h"
#include "cpp_global.h"
#include "Lexer.h"

using namespace CPlusPlus;

#include <tools/qbspluginmanager.h>
#include <tools/scannerpluginmanager.h>

#ifdef Q_OS_UNIX
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#else
#include <QtCore/qfile.h>
#endif

#include <QtCore/qbytearray.h>
#include <QtCore/qlist.h>
#include <QtCore/qstring.h>

#include <cstring>
#include <memory>

struct ScanResult
{
    char *fileName = nullptr;
    int size = 0;
    int flags = 0;
};

struct Opaq
{
    enum FileType
    {
        FT_UNKNOWN, FT_HPP, FT_CPP, FT_C, FT_OBJC, FT_OBJCPP, FT_RC
    };

    Opaq()
        :
#ifdef Q_OS_UNIX
          fd(0),
          mapl(0),
#endif
          fileContent(nullptr),
          fileType(FT_UNKNOWN),
          hasQObjectMacro(false),
          hasPluginMetaDataMacro(false),
          currentResultIndex(0)
    {}

    ~Opaq()
    {
#ifdef Q_OS_UNIX
        if (fileContent)
            munmap(fileContent, mapl);
        if (fd)
            close(fd);
#endif
    }

#ifdef Q_OS_WIN
    QFile file;
#endif
#ifdef Q_OS_UNIX
    int fd;
    size_t mapl;
#endif

    QString fileName;
    char *fileContent;
    FileType fileType;
    QList<ScanResult> includedFiles;
    bool hasQObjectMacro;
    bool hasPluginMetaDataMacro;
    int currentResultIndex;
};

class TokenComparator
{
    const char * const m_fileContent;
public:
    TokenComparator(const char *fileContent)
        : m_fileContent(fileContent)
    {
    }

    bool equals(const Token &tk, const QLatin1String &literal) const
    {
        return static_cast<int>(tk.length()) == literal.size()
                && memcmp(m_fileContent + tk.begin(), literal.data(), literal.size()) == 0;
    }
};

static void scanCppFile(void *opaq, CPlusPlus::Lexer &yylex, bool scanForFileTags,
                        bool scanForDependencies)
{
    const QLatin1String includeLiteral("include");
    const QLatin1String importLiteral("import");
    const QLatin1String defineLiteral("define");
    const QLatin1String qobjectLiteral("Q_OBJECT");
    const QLatin1String qgadgetLiteral("Q_GADGET");
    const QLatin1String qnamespaceLiteral("Q_NAMESPACE");
    const QLatin1String pluginMetaDataLiteral("Q_PLUGIN_METADATA");
    const auto opaque = static_cast<Opaq *>(opaq);
    const TokenComparator tc(opaque->fileContent);
    Token tk;
    Token oldTk;
    ScanResult scanResult;

    yylex(&tk);

    while (tk.isNot(T_EOF_SYMBOL)) {
        if (tk.newline() && tk.is(T_POUND)) {
            yylex(&tk);

            if (scanForDependencies && !tk.newline() && tk.is(T_IDENTIFIER)) {
                if (tc.equals(tk, includeLiteral) || tc.equals(tk, importLiteral))
                {
                    yylex.setScanAngleStringLiteralTokens(true);
                    yylex(&tk);
                    yylex.setScanAngleStringLiteralTokens(false);

                    if (!tk.newline() && (tk.is(T_STRING_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL))) {
                        scanResult.size = int(tk.length() - 2);
                        if (tk.is(T_STRING_LITERAL))
                            scanResult.flags = SC_LOCAL_INCLUDE_FLAG;
                        else
                            scanResult.flags = SC_GLOBAL_INCLUDE_FLAG;
                        scanResult.fileName = opaque->fileContent + tk.begin() + 1;
                        opaque->includedFiles.push_back(scanResult);
                    }
                }
            }
        } else if (tk.is(T_IDENTIFIER)) {
            if (scanForFileTags) {
                if (oldTk.is(T_IDENTIFIER) && tc.equals(oldTk, defineLiteral)) {
                    // Someone was clever and redefined Q_OBJECT or Q_PLUGIN_METADATA.
                    // Example: iplugin.h in Qt Creator.
                } else {
                    if (tc.equals(tk, qobjectLiteral) || tc.equals(tk, qgadgetLiteral)  ||
                        tc.equals(tk, qnamespaceLiteral))
                    {
                        opaque->hasQObjectMacro = true;
                    } else if (tc.equals(tk, pluginMetaDataLiteral))
                    {
                        opaque->hasPluginMetaDataMacro = true;
                    }
                    if (!scanForDependencies && opaque->hasQObjectMacro
                        && (opaque->hasPluginMetaDataMacro
                            || opaque->fileType == Opaq::FT_CPP
                            || opaque->fileType == Opaq::FT_OBJCPP))
                        break;
                }
            }

        }
        oldTk = tk;
        yylex(&tk);
    }
}

static void *openScanner(const unsigned short *filePath, const char *fileTags, int flags)
{
    std::unique_ptr<Opaq> opaque(new Opaq);
    opaque->fileName = QString::fromUtf16(filePath);
    const int fileTagsLength = static_cast<int>(std::strlen(fileTags));
    const QList<QByteArray> &tagList = QByteArray::fromRawData(fileTags, fileTagsLength).split(',');
    if (tagList.contains("hpp"))
        opaque->fileType = Opaq::FT_HPP;
    else if (tagList.contains("cpp"))
        opaque->fileType = Opaq::FT_CPP;
    else if (tagList.contains("objcpp"))
        opaque->fileType = Opaq::FT_OBJCPP;
    else
        opaque->fileType = Opaq::FT_UNKNOWN;

    size_t mapl = 0;
#ifdef Q_OS_UNIX
    QString filePathS = opaque->fileName;

    opaque->fd = open(qPrintable(filePathS), O_RDONLY);
    if (opaque->fd == -1) {
        opaque->fd = 0;
        return nullptr;
    }

    struct stat s{};
    int r = fstat(opaque->fd, &s);
    if (r != 0)
        return nullptr;
    mapl = s.st_size;
    opaque->mapl = mapl;

    void *vmap = mmap(nullptr, s.st_size, PROT_READ, MAP_PRIVATE, opaque->fd, 0);
    if (vmap == MAP_FAILED) // NOLINT(cppcoreguidelines-pro-type-cstyle-cast)
        return nullptr;
#else
    opaque->file.setFileName(opaque->fileName);
    if (!opaque->file.open(QFile::ReadOnly))
        return nullptr;

    uchar *vmap = opaque->file.map(0, opaque->file.size());
    mapl = opaque->file.size();
#endif
    if (!vmap)
        return nullptr;

    opaque->fileContent = reinterpret_cast<char *>(vmap);

    // Check for UTF-8 Byte Order Mark (BOM). Skip if found.
    if (mapl >= 3
            && opaque->fileContent[0] == char(0xef)
            && opaque->fileContent[1] == char(0xbb)
            && opaque->fileContent[2] == char(0xbf)) {
        opaque->fileContent += 3;
        mapl -= 3;
    }

    CPlusPlus::Lexer lex(opaque->fileContent, opaque->fileContent + mapl);
    scanCppFile(opaque.get(), lex, flags & ScanForFileTagsFlag, flags & ScanForDependenciesFlag);
    return opaque.release();
}

static void closeScanner(void *ptr)
{
    const auto opaque = static_cast<Opaq *>(ptr);
    delete opaque;
}

static const char *next(void *opaq, int *size, int *flags)
{
    const auto opaque = static_cast<Opaq*>(opaq);
    if (opaque->currentResultIndex < opaque->includedFiles.size()) {
        const ScanResult &result = opaque->includedFiles.at(opaque->currentResultIndex);
        ++opaque->currentResultIndex;
        *size = result.size;
        *flags = result.flags;
        return result.fileName;
    }
    *size = 0;
    *flags = 0;
    return nullptr;
}

static const char **additionalFileTags(void *opaq, int *size)
{
    static const char *thMocCpp[] = { "moc_cpp" };
    static const char *thMocHpp[] = { "moc_hpp" };
    static const char *thMocPluginHpp[] = { "moc_hpp_plugin" };
    static const char *thMocPluginCpp[] = { "moc_cpp_plugin" };

    const auto opaque = static_cast<const Opaq*>(opaq);
    if (opaque->hasQObjectMacro) {
        *size = 1;
        switch (opaque->fileType) {
        case Opaq::FT_CPP:
        case Opaq::FT_OBJCPP:
            return opaque->hasPluginMetaDataMacro ? thMocPluginCpp : thMocCpp;
        case Opaq::FT_HPP:
            return opaque->hasPluginMetaDataMacro ? thMocPluginHpp : thMocHpp;
        default:
            break;
        }
    }
    *size = 0;
    return nullptr;
}

ScannerPlugin includeScanner =
{
    "include_scanner",
    "cpp,cpp_pch_src,c,c_pch_src,objcpp,objcpp_pch_src,objc,objc_pch_src,rc",
    openScanner,
    closeScanner,
    next,
    additionalFileTags,
    ScannerUsesCppIncludePaths | ScannerRecursiveDependencies
};

ScannerPlugin *cppScanners[] = { &includeScanner, nullptr };

static void QbsCppScannerPluginLoad()
{
    qbs::Internal::ScannerPluginManager::instance()->registerPlugins(cppScanners);
}

static void QbsCppScannerPluginUnload()
{
}

QBS_REGISTER_STATIC_PLUGIN(extern "C" CPPSCANNER_EXPORT, qbs_cpp_scanner,
                           QbsCppScannerPluginLoad, QbsCppScannerPluginUnload)

<commit_msg>qt6: do not use QString::fromUtf16(ushort*) overload<commit_after>/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qbs.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "../scanner.h"
#include "cpp_global.h"
#include "Lexer.h"

using namespace CPlusPlus;

#include <tools/qbspluginmanager.h>
#include <tools/scannerpluginmanager.h>

#ifdef Q_OS_UNIX
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#else
#include <QtCore/qfile.h>
#endif

#include <QtCore/qbytearray.h>
#include <QtCore/qlist.h>
#include <QtCore/qstring.h>

#include <cstring>
#include <memory>

struct ScanResult
{
    char *fileName = nullptr;
    int size = 0;
    int flags = 0;
};

struct Opaq
{
    enum FileType
    {
        FT_UNKNOWN, FT_HPP, FT_CPP, FT_C, FT_OBJC, FT_OBJCPP, FT_RC
    };

    Opaq()
        :
#ifdef Q_OS_UNIX
          fd(0),
          mapl(0),
#endif
          fileContent(nullptr),
          fileType(FT_UNKNOWN),
          hasQObjectMacro(false),
          hasPluginMetaDataMacro(false),
          currentResultIndex(0)
    {}

    ~Opaq()
    {
#ifdef Q_OS_UNIX
        if (fileContent)
            munmap(fileContent, mapl);
        if (fd)
            close(fd);
#endif
    }

#ifdef Q_OS_WIN
    QFile file;
#endif
#ifdef Q_OS_UNIX
    int fd;
    size_t mapl;
#endif

    QString fileName;
    char *fileContent;
    FileType fileType;
    QList<ScanResult> includedFiles;
    bool hasQObjectMacro;
    bool hasPluginMetaDataMacro;
    int currentResultIndex;
};

class TokenComparator
{
    const char * const m_fileContent;
public:
    TokenComparator(const char *fileContent)
        : m_fileContent(fileContent)
    {
    }

    bool equals(const Token &tk, const QLatin1String &literal) const
    {
        return static_cast<int>(tk.length()) == literal.size()
                && memcmp(m_fileContent + tk.begin(), literal.data(), literal.size()) == 0;
    }
};

static void scanCppFile(void *opaq, CPlusPlus::Lexer &yylex, bool scanForFileTags,
                        bool scanForDependencies)
{
    const QLatin1String includeLiteral("include");
    const QLatin1String importLiteral("import");
    const QLatin1String defineLiteral("define");
    const QLatin1String qobjectLiteral("Q_OBJECT");
    const QLatin1String qgadgetLiteral("Q_GADGET");
    const QLatin1String qnamespaceLiteral("Q_NAMESPACE");
    const QLatin1String pluginMetaDataLiteral("Q_PLUGIN_METADATA");
    const auto opaque = static_cast<Opaq *>(opaq);
    const TokenComparator tc(opaque->fileContent);
    Token tk;
    Token oldTk;
    ScanResult scanResult;

    yylex(&tk);

    while (tk.isNot(T_EOF_SYMBOL)) {
        if (tk.newline() && tk.is(T_POUND)) {
            yylex(&tk);

            if (scanForDependencies && !tk.newline() && tk.is(T_IDENTIFIER)) {
                if (tc.equals(tk, includeLiteral) || tc.equals(tk, importLiteral))
                {
                    yylex.setScanAngleStringLiteralTokens(true);
                    yylex(&tk);
                    yylex.setScanAngleStringLiteralTokens(false);

                    if (!tk.newline() && (tk.is(T_STRING_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL))) {
                        scanResult.size = int(tk.length() - 2);
                        if (tk.is(T_STRING_LITERAL))
                            scanResult.flags = SC_LOCAL_INCLUDE_FLAG;
                        else
                            scanResult.flags = SC_GLOBAL_INCLUDE_FLAG;
                        scanResult.fileName = opaque->fileContent + tk.begin() + 1;
                        opaque->includedFiles.push_back(scanResult);
                    }
                }
            }
        } else if (tk.is(T_IDENTIFIER)) {
            if (scanForFileTags) {
                if (oldTk.is(T_IDENTIFIER) && tc.equals(oldTk, defineLiteral)) {
                    // Someone was clever and redefined Q_OBJECT or Q_PLUGIN_METADATA.
                    // Example: iplugin.h in Qt Creator.
                } else {
                    if (tc.equals(tk, qobjectLiteral) || tc.equals(tk, qgadgetLiteral)  ||
                        tc.equals(tk, qnamespaceLiteral))
                    {
                        opaque->hasQObjectMacro = true;
                    } else if (tc.equals(tk, pluginMetaDataLiteral))
                    {
                        opaque->hasPluginMetaDataMacro = true;
                    }
                    if (!scanForDependencies && opaque->hasQObjectMacro
                        && (opaque->hasPluginMetaDataMacro
                            || opaque->fileType == Opaq::FT_CPP
                            || opaque->fileType == Opaq::FT_OBJCPP))
                        break;
                }
            }

        }
        oldTk = tk;
        yylex(&tk);
    }
}

static void *openScanner(const unsigned short *filePath, const char *fileTags, int flags)
{
    std::unique_ptr<Opaq> opaque(new Opaq);
    opaque->fileName = QString::fromUtf16(reinterpret_cast<const char16_t *>(filePath));
    const int fileTagsLength = static_cast<int>(std::strlen(fileTags));
    const QList<QByteArray> &tagList = QByteArray::fromRawData(fileTags, fileTagsLength).split(',');
    if (tagList.contains("hpp"))
        opaque->fileType = Opaq::FT_HPP;
    else if (tagList.contains("cpp"))
        opaque->fileType = Opaq::FT_CPP;
    else if (tagList.contains("objcpp"))
        opaque->fileType = Opaq::FT_OBJCPP;
    else
        opaque->fileType = Opaq::FT_UNKNOWN;

    size_t mapl = 0;
#ifdef Q_OS_UNIX
    QString filePathS = opaque->fileName;

    opaque->fd = open(qPrintable(filePathS), O_RDONLY);
    if (opaque->fd == -1) {
        opaque->fd = 0;
        return nullptr;
    }

    struct stat s{};
    int r = fstat(opaque->fd, &s);
    if (r != 0)
        return nullptr;
    mapl = s.st_size;
    opaque->mapl = mapl;

    void *vmap = mmap(nullptr, s.st_size, PROT_READ, MAP_PRIVATE, opaque->fd, 0);
    if (vmap == MAP_FAILED) // NOLINT(cppcoreguidelines-pro-type-cstyle-cast)
        return nullptr;
#else
    opaque->file.setFileName(opaque->fileName);
    if (!opaque->file.open(QFile::ReadOnly))
        return nullptr;

    uchar *vmap = opaque->file.map(0, opaque->file.size());
    mapl = opaque->file.size();
#endif
    if (!vmap)
        return nullptr;

    opaque->fileContent = reinterpret_cast<char *>(vmap);

    // Check for UTF-8 Byte Order Mark (BOM). Skip if found.
    if (mapl >= 3
            && opaque->fileContent[0] == char(0xef)
            && opaque->fileContent[1] == char(0xbb)
            && opaque->fileContent[2] == char(0xbf)) {
        opaque->fileContent += 3;
        mapl -= 3;
    }

    CPlusPlus::Lexer lex(opaque->fileContent, opaque->fileContent + mapl);
    scanCppFile(opaque.get(), lex, flags & ScanForFileTagsFlag, flags & ScanForDependenciesFlag);
    return opaque.release();
}

static void closeScanner(void *ptr)
{
    const auto opaque = static_cast<Opaq *>(ptr);
    delete opaque;
}

static const char *next(void *opaq, int *size, int *flags)
{
    const auto opaque = static_cast<Opaq*>(opaq);
    if (opaque->currentResultIndex < opaque->includedFiles.size()) {
        const ScanResult &result = opaque->includedFiles.at(opaque->currentResultIndex);
        ++opaque->currentResultIndex;
        *size = result.size;
        *flags = result.flags;
        return result.fileName;
    }
    *size = 0;
    *flags = 0;
    return nullptr;
}

static const char **additionalFileTags(void *opaq, int *size)
{
    static const char *thMocCpp[] = { "moc_cpp" };
    static const char *thMocHpp[] = { "moc_hpp" };
    static const char *thMocPluginHpp[] = { "moc_hpp_plugin" };
    static const char *thMocPluginCpp[] = { "moc_cpp_plugin" };

    const auto opaque = static_cast<const Opaq*>(opaq);
    if (opaque->hasQObjectMacro) {
        *size = 1;
        switch (opaque->fileType) {
        case Opaq::FT_CPP:
        case Opaq::FT_OBJCPP:
            return opaque->hasPluginMetaDataMacro ? thMocPluginCpp : thMocCpp;
        case Opaq::FT_HPP:
            return opaque->hasPluginMetaDataMacro ? thMocPluginHpp : thMocHpp;
        default:
            break;
        }
    }
    *size = 0;
    return nullptr;
}

ScannerPlugin includeScanner =
{
    "include_scanner",
    "cpp,cpp_pch_src,c,c_pch_src,objcpp,objcpp_pch_src,objc,objc_pch_src,rc",
    openScanner,
    closeScanner,
    next,
    additionalFileTags,
    ScannerUsesCppIncludePaths | ScannerRecursiveDependencies
};

ScannerPlugin *cppScanners[] = { &includeScanner, nullptr };

static void QbsCppScannerPluginLoad()
{
    qbs::Internal::ScannerPluginManager::instance()->registerPlugins(cppScanners);
}

static void QbsCppScannerPluginUnload()
{
}

QBS_REGISTER_STATIC_PLUGIN(extern "C" CPPSCANNER_EXPORT, qbs_cpp_scanner,
                           QbsCppScannerPluginLoad, QbsCppScannerPluginUnload)

<|endoftext|>


<commit_before>#define RLUA_REPLACE
#include "../rlua.h"
#if defined(_WIN32)
#include <binding/lua_unicode.cpp>
#include <Windows.h>
#include <tlhelp32.h>
#else
#include <bee/lua/binding.h>
#endif
#include <bee/filesystem.h>
#include <bee/platform.h>
#include <signal.h>

namespace rdebug_utility {
    static int fs_absolute(lua_State* L) {
#if defined(_WIN32)
#define FS_ABSOLUTE(path) fs::absolute(path)
#else
#define FS_ABSOLUTE(path) fs::absolute(path).lexically_normal()
#endif
        try {
            auto res = FS_ABSOLUTE(fs::path(bee::lua::tostring<fs::path::string_type>(L, 1))).generic_u8string();
            lua_pushlstring(L, res.data(), res.size());
            return 1;
        } catch (const std::exception& e) {
            return bee::lua::push_error(L, e);
        }
    }
    static int platform_os(lua_State* L) {
        lua_pushstring(L, BEE_OS_NAME);
        return 1;
    }

#if defined(_WIN32)
    static void closeWindow() {
        HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
        if (h != INVALID_HANDLE_VALUE) {
            THREADENTRY32 te;
            te.dwSize = sizeof(te);
            for (BOOL ok = Thread32First(h, &te); ok; ok = Thread32Next(h, &te)) {
                if (te.th32OwnerProcessID == GetCurrentProcessId()) {
                    PostThreadMessageW(te.th32ThreadID, WM_QUIT, 0, 0);
                }
            }
        }
        CloseHandle(h);
    }
    bool isConsoleExe(const wchar_t* exe) {
        HANDLE hExe = CreateFileW(exe, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hExe == 0) {
            return false;
        }
        DWORD read;
        char data[sizeof IMAGE_NT_HEADERS + sizeof IMAGE_DOS_HEADER];
        SetFilePointer(hExe, 0, NULL, FILE_BEGIN);
        if (!ReadFile(hExe, data, sizeof IMAGE_DOS_HEADER, &read, NULL)) {
            CloseHandle(hExe);
            return false;
        }
        SetFilePointer(hExe, ((PIMAGE_DOS_HEADER)data)->e_lfanew, NULL, FILE_BEGIN);
        if (!ReadFile(hExe, data, sizeof IMAGE_NT_HEADERS, &read, NULL)) {
            CloseHandle(hExe);
            return false;
        }
        CloseHandle(hExe);
        return ((PIMAGE_NT_HEADERS)data)->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI;
    }
    static bool isConsoleProcess() {
        wchar_t exe[MAX_PATH] = { 0 };
        GetModuleFileNameW(NULL, exe, MAX_PATH);
        return isConsoleExe(exe);
    }
#endif

    static int closeprocess(lua_State* L) {
#if defined(_WIN32)
        closeWindow();
        if (isConsoleProcess()) {
            raise(SIGINT);
        }
#else
        raise(SIGINT);
#endif
        return 0;
    }
}

RLUA_FUNC
int luaopen_remotedebug_utility(lua_State* L) {
#if defined(_WIN32)
    luaopen_bee_unicode(L);
#else
    lua_newtable(L);
#endif
    luaL_Reg lib[] = {
        {"fs_absolute", rdebug_utility::fs_absolute},
        {"platform_os", rdebug_utility::platform_os},
        {"closeprocess", rdebug_utility::closeprocess},
        {NULL, NULL}};
    luaL_setfuncs(L, lib, 0);
    return 1;
}
<commit_msg>修正一个bug<commit_after>#define RLUA_REPLACE
#include "../rlua.h"
#if defined(_WIN32)
#include <binding/lua_unicode.cpp>
#include <Windows.h>
#include <tlhelp32.h>
#else
#include <bee/lua/binding.h>
#endif
#include <bee/filesystem.h>
#include <bee/platform.h>
#include <signal.h>

namespace rdebug_utility {
    static int fs_absolute(lua_State* L) {
#if defined(_WIN32)
#define FS_ABSOLUTE(path) fs::absolute(path)
#else
#define FS_ABSOLUTE(path) fs::absolute(path).lexically_normal()
#endif
        try {
            auto res = FS_ABSOLUTE(fs::path(bee::lua::tostring<fs::path::string_type>(L, 1))).generic_u8string();
            lua_pushlstring(L, res.data(), res.size());
            return 1;
        } catch (const std::exception& e) {
            return bee::lua::push_error(L, e);
        }
    }
    static int platform_os(lua_State* L) {
        lua_pushstring(L, BEE_OS_NAME);
        return 1;
    }

#if defined(_WIN32)
    static void closeWindow() {
        HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
        if (h != INVALID_HANDLE_VALUE) {
            THREADENTRY32 te;
            te.dwSize = sizeof(te);
            for (BOOL ok = Thread32First(h, &te); ok; ok = Thread32Next(h, &te)) {
                if (te.th32OwnerProcessID == GetCurrentProcessId()) {
                    PostThreadMessageW(te.th32ThreadID, WM_QUIT, 0, 0);
                }
            }
            CloseHandle(h);
        }
    }
    bool isConsoleExe(const wchar_t* exe) {
        HANDLE hExe = CreateFileW(exe, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hExe == 0) {
            return false;
        }
        DWORD read;
        char data[sizeof IMAGE_NT_HEADERS + sizeof IMAGE_DOS_HEADER];
        SetFilePointer(hExe, 0, NULL, FILE_BEGIN);
        if (!ReadFile(hExe, data, sizeof IMAGE_DOS_HEADER, &read, NULL)) {
            CloseHandle(hExe);
            return false;
        }
        SetFilePointer(hExe, ((PIMAGE_DOS_HEADER)data)->e_lfanew, NULL, FILE_BEGIN);
        if (!ReadFile(hExe, data, sizeof IMAGE_NT_HEADERS, &read, NULL)) {
            CloseHandle(hExe);
            return false;
        }
        CloseHandle(hExe);
        return ((PIMAGE_NT_HEADERS)data)->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI;
    }
    static bool isConsoleProcess() {
        wchar_t exe[MAX_PATH] = { 0 };
        GetModuleFileNameW(NULL, exe, MAX_PATH);
        return isConsoleExe(exe);
    }
#endif

    static int closeprocess(lua_State* L) {
#if defined(_WIN32)
        closeWindow();
        if (isConsoleProcess()) {
            raise(SIGINT);
        }
#else
        raise(SIGINT);
#endif
        return 0;
    }
}

RLUA_FUNC
int luaopen_remotedebug_utility(lua_State* L) {
#if defined(_WIN32)
    luaopen_bee_unicode(L);
#else
    lua_newtable(L);
#endif
    luaL_Reg lib[] = {
        {"fs_absolute", rdebug_utility::fs_absolute},
        {"platform_os", rdebug_utility::platform_os},
        {"closeprocess", rdebug_utility::closeprocess},
        {NULL, NULL}};
    luaL_setfuncs(L, lib, 0);
    return 1;
}
<|endoftext|>


<commit_before>#ifndef __TEST__MODELS__MODEL_TEST_FIXTURE_HPP__
#define __TEST__MODELS__MODEL_TEST_FIXTURE_HPP__

#include <gtest/gtest.h>
#include <test/models/utility.hpp>
#include <stan/mcmc/chains.hpp>
#include <utility>
#include <boost/math/distributions/students_t.hpp>
#include <boost/math/distributions/binomial.hpp>

/**
 * Model_Test_Fixture is a test fixture for google test
 * to aid in running models.
 *
 * Derived classes must define:
 *   static std::vector<std::string> get_model_path()
 *   static bool has_data()
 *   - indicates whether the model has data
 */
template <class Derived>
class Model_Test_Fixture : public ::testing::Test {

public:
  static char path_separator;
  static std::string model_path;
  static stan::mcmc::chains<> *chains;
  static size_t num_chains;
  static std::vector<std::string> command_outputs;
  static const size_t skip;
  static size_t iterations;

  /**
   * SetUpTestCase() called by google test once
   * a test case.
   *
   * Sets:
   *  - path_separator: '\' for Windows, '/' for all else.
   *  - base_name:      location of model without ".stan"
   *  - chains:         creates a chains object by reading
   *                    the header of a csv file
   */
  static void SetUpTestCase() {
    model_path = convert_model_path(get_model_path());

    iterations = num_iterations();

    chains = create_chains();
  }

  /**
   * TearDownTestCase() called by google test once
   * a test case.
   *
   * Deletes chains.
   */
  static void TearDownTestCase() {
    delete chains;
  }

  /**
   * Returns the csv file for the chain number.
   *
   * @param chain the chain number
   *
   * @return the file location of the csv file
   */
  static std::string get_csv_file(size_t chain) {
    std::stringstream csv_file;
    csv_file << model_path << "." << chain << ".csv";
    return csv_file.str();
  }

  /**
   * Returns the command to run in a shell on the OS.
   *
   * @param chain the chain number
   *
   * @return a string command that can be run from a shell.
   */
  static std::string get_command(size_t chain) {
    std::stringstream command;
    command << model_path;
    command << " --samples=" << get_csv_file(chain);
    if (has_data()) {
      command << " --data=" << model_path << ".Rdata";
    }
    if (has_init()) {
      command << " --init=" << model_path << "_init.Rdata";
    }
    command << " --iter=" << iterations;
    command << " --refresh=" << iterations;
    return command.str();
  }

  /**
   * Populates the chains object with data from csv files.
   */
  static void default_populate_chains() {
    if (chains->num_kept_samples() == 0U) {
      for (size_t chain = 0U; chain < num_chains; chain++) {
        stan::mcmc::add_chain(*chains, chain, get_csv_file(chain), skip);
      }
    }
  }

  static void populate_chains() {
    Derived::populate_chains();
  }

  static void test_gradient() {
    std::string command = get_command(0U);
    command += " --test_grad";
    std::string command_output;
    EXPECT_NO_THROW(command_output = run_command(command))
      << "Gradient test failed. \n"
      << "\tRan command: " << command << "\n"
      << "\tCommand output: " << command_output;
    //std::cout << "command_output: " << command_output << "\n";
  }

  /**
   * Runs the model num_chains times.
   * Populates the chains object after running the model.
   */
  static void run_model() {
    for (size_t chain = 0; chain < num_chains; chain++) {
      std::string command_output;
      EXPECT_NO_THROW(command_output = run_command(get_command(chain)))
        << "Can not execute command: " << get_command(chain);
      command_outputs.push_back(command_output);
    }
    populate_chains();
  }

  /**
   * Creates a chains object.
   *
   * Runs the model for 0 iterations to read the
   * names and dimensions of the parameters.
   *
   * @return An initialized chains object.
   */
  static stan::mcmc::chains<>* create_chains() {
    std::stringstream command;
    command << get_command(num_chains)
	    << " --iter=0";
    EXPECT_NO_THROW(run_command(command.str()))
      << "Can not build header using: " << command.str();

    std::vector<std::string> names;
    std::vector<std::vector<size_t> > dimss;
    stan::mcmc::read_variables(get_csv_file(num_chains), skip,
                               names, dimss);

    return (new stan::mcmc::chains<>(num_chains, names, dimss));
  }

  /**
   * Return the path to the model (without the extension) as
   * a vector.
   *
   * @return the path to the model
   */
  static std::vector<std::string> get_model_path() {
    return Derived::get_model_path();
  }

  /**
   * Return true if the model has data.
   *
   * @return true if the model has data;
   *         false otherwise.
   */
  static bool has_data() {
    return Derived::has_data();
  }

  /**
   * Return true if the model has an initialization file.
   *
   * @return true if the model has an initialization file;
   *         false otherwise.
   */
  static bool has_init() {
    return Derived::has_init();
  }

  static size_t num_iterations() {
    return Derived::num_iterations();
  }

  static std::vector<std::pair<size_t, double> >
  get_expected_values() {
    return Derived::get_expected_values();
  }

};

template<class Derived>
stan::mcmc::chains<> *Model_Test_Fixture<Derived>::chains;

template<class Derived>
size_t Model_Test_Fixture<Derived>::num_chains = 2;

template<class Derived>
std::string Model_Test_Fixture<Derived>::model_path;

template<class Derived>
std::vector<std::string> Model_Test_Fixture<Derived>::command_outputs;

template<class Derived>
const size_t Model_Test_Fixture<Derived>::skip = 3U;

template<class Derived>
size_t Model_Test_Fixture<Derived>::iterations = 2000U;

TYPED_TEST_CASE_P(Model_Test_Fixture);

TYPED_TEST_P(Model_Test_Fixture, TestGradient) {
  TypeParam::test_gradient();
}

TYPED_TEST_P(Model_Test_Fixture, RunModel) {
  TypeParam::run_model();
}

TYPED_TEST_P(Model_Test_Fixture, ChainsTest) {
  std::vector<std::string> err_message;
  for (size_t chain = 0; chain < TypeParam::num_chains; chain++) {
    std::vector<std::pair<std::string, std::string> > options =
      parse_command_output(TypeParam::command_outputs[chain]);
    parse_command_output(TypeParam::command_outputs[chain]);

    std::string msg = "Seed is : ";
    for (size_t option = 0; option < options.size(); option++) {
      if (options[option].first == "seed")
        msg += options[option].second;
    }
    err_message.push_back(msg);
  }

  stan::mcmc::chains<> *c = TypeParam::chains;
  size_t num_chains = c->num_chains();
  size_t num_params = c->num_params();
  for (size_t chain = 0; chain < num_chains; chain++) {
    for (size_t param = 0; param < num_params; param++) {
      EXPECT_GT(c->variance(chain, param), 0)
        << "Chain " << chain << ", param " << param
        << ": variance is 0" << std::endl
        << err_message[chain];
      // made this 1.2 to fail less often
      EXPECT_LT(c->split_potential_scale_reduction(param), 1.2)
	<< "Chain " << chain << ", param " << param
        << ": split r hat > 1.2" << std::endl
        << err_message[chain];
    }
  }
}

TYPED_TEST_P(Model_Test_Fixture, ExpectedValuesTest) {
  using std::vector;
  using std::pair;
  using std::sqrt;
  using std::fabs;
  using std::setw;

  using boost::math::students_t;
  using boost::math::binomial;
  using boost::math::quantile;

  vector<pair<size_t, double> > expected_values = TypeParam::get_expected_values();
  size_t n = expected_values.size();
  if (n == 0)
    return;

  stan::mcmc::chains<> *c = TypeParam::chains;
  double alpha = 0.005;
  if (n < 3)
    alpha = 0.001;

  int failed = 0;
  std::stringstream err_message;
  for (size_t i = 0; i < n; i++) {
    size_t index = expected_values[i].first;
    double expected_mean = expected_values[i].second;

    double neff = c->effective_sample_size(index);
    double sample_mean = c->mean(index);
    double se = c->sd(index) / sqrt(neff);
    double z = quantile(students_t(neff-1.0), 1 - alpha/2.0);

    // that 2.0 is there to make the test fail less often.
    if (fabs(expected_mean - sample_mean) > z*se * 2.0) {
      failed++;
      // want the error message to have which, what, how
      err_message << "parameter index: " << index
                  << "\n\texpected:    " << setw(10) << expected_mean
                  << "\n\tsampled:     " << setw(10) << sample_mean
		  << "\n\tsd:          " << setw(10) << c->sd(index)
                  << "\n\tneff:        " << setw(10) << neff
                  << "\n\tsplit R.hat: " << setw(10) << c->split_potential_scale_reduction(index)
                  << "\n\tz:           " << setw(10) << z
                  << "\n\tse:          " << setw(10) << se
                  << "\n\n\tfabs(diff) > z * se: "
                  << fabs(expected_mean - sample_mean) << " > " << z*se << "\n\n";
    }
  }

  if (failed == 0)
    return;

  double p = 1 - cdf(binomial(n, alpha), failed);
  // this test should fail less than 0.1% of the time.
  // (if all the parameters are failing independently... ha)
  if (p < 0.001) {
    err_message << "------------------------------------------------------------\n";
    for (size_t chain = 0; chain < TypeParam::num_chains; chain++) {
      std::vector<std::pair<std::string, std::string> > options =
        parse_command_output(TypeParam::command_outputs[chain]);

      for (size_t option = 0; option < options.size(); option++) {
        if (options[option].first == "seed")
          err_message << "seed: " << options[option].second << std::endl;
      }
    }

    EXPECT_EQ(0, failed)
      << "Failed " << failed << " of " << expected_values.size() << " comparisons\n"
      << "p: " << p << std::endl
      << "------------------------------------------------------------\n"
      << err_message.str() << std::endl
      << "------------------------------------------------------------\n";

  }
}

REGISTER_TYPED_TEST_CASE_P(Model_Test_Fixture,
                           TestGradient,
                           RunModel,
                           ChainsTest,
                           ExpectedValuesTest);

#endif
<commit_msg>test-models: updated model fixture<commit_after>#ifndef __TEST__MODELS__MODEL_TEST_FIXTURE_HPP__
#define __TEST__MODELS__MODEL_TEST_FIXTURE_HPP__

#include <gtest/gtest.h>
#include <test/models/utility.hpp>
#include <stan/mcmc/chains.hpp>
#include <utility>
#include <boost/math/distributions/students_t.hpp>
#include <boost/math/distributions/binomial.hpp>

/**
 * Model_Test_Fixture is a test fixture for google test
 * to aid in running models.
 *
 * Derived classes must define:
 *   static std::vector<std::string> get_model_path()
 *   static bool has_data()
 *   - indicates whether the model has data
 */
template <class Derived>
class Model_Test_Fixture : public ::testing::Test {

public:
  static char path_separator;
  static std::string model_path;
  static stan::mcmc::chains<> *chains;
  static size_t num_chains;
  static std::vector<std::string> command_outputs;
  static const size_t skip;
  static size_t iterations;

  /**
   * SetUpTestCase() called by google test once
   * a test case.
   *
   * Sets:
   *  - path_separator: '\' for Windows, '/' for all else.
   *  - base_name:      location of model without ".stan"
   *  - chains:         creates a chains object by reading
   *                    the header of a csv file
   */
  static void SetUpTestCase() {
    model_path = convert_model_path(get_model_path());

    iterations = num_iterations();

    chains = create_chains();
  }

  /**
   * TearDownTestCase() called by google test once
   * a test case.
   *
   * Deletes chains.
   */
  static void TearDownTestCase() {
    delete chains;
  }

  /**
   * Returns the csv file for the chain number.
   *
   * @param chain the chain number
   *
   * @return the file location of the csv file
   */
  static std::string get_csv_file(size_t chain) {
    std::stringstream csv_file;
    csv_file << model_path << "." << chain << ".csv";
    return csv_file.str();
  }

  /**
   * Returns the command to run in a shell on the OS.
   *
   * @param chain the chain number
   *
   * @return a string command that can be run from a shell.
   */
  static std::string get_command(size_t chain) {
    std::stringstream command;
    command << model_path;
    command << " --samples=" << get_csv_file(chain);
    if (has_data()) {
      command << " --data=" << model_path << ".Rdata";
    }
    if (has_init()) {
      command << " --init=" << model_path << "_init.Rdata";
    }
    command << " --iter=" << iterations;
    command << " --refresh=" << iterations;
    return command.str();
  }

  /**
   * Populates the chains object with data from csv files.
   */
  static void default_populate_chains() {
    if (chains->num_kept_samples() == 0U) {
      for (size_t chain = 0U; chain < num_chains; chain++) {
        stan::mcmc::add_chain(*chains, chain, get_csv_file(chain), skip);
      }
    }
  }

  static void populate_chains() {
    Derived::populate_chains();
  }

  static void test_gradient() {
    std::string command = get_command(0U);
    command += " --test_grad";
    std::string command_output;
    EXPECT_NO_THROW(command_output = run_command(command))
      << "Gradient test failed. \n"
      << "\tRan command: " << command << "\n"
      << "\tCommand output: " << command_output;
    //std::cout << "command_output: " << command_output << "\n";
  }

  /**
   * Runs the model num_chains times.
   * Populates the chains object after running the model.
   */
  static void run_model() {
    for (size_t chain = 0; chain < num_chains; chain++) {
      std::string command_output;
      EXPECT_NO_THROW(command_output = run_command(get_command(chain)))
        << "Can not execute command: " << get_command(chain);
      command_outputs.push_back(command_output);
    }
    populate_chains();
  }

  /**
   * Creates a chains object.
   *
   * Runs the model for 0 iterations to read the
   * names and dimensions of the parameters.
   *
   * @return An initialized chains object.
   */
  static stan::mcmc::chains<>* create_chains() {
    std::stringstream command;
    command << get_command(num_chains)
	    << " --iter=0";
    EXPECT_NO_THROW(run_command(command.str()))
      << "Can not build header using: " << command.str();

    std::vector<std::string> names;
    std::vector<std::vector<size_t> > dimss;
    stan::mcmc::read_variables(get_csv_file(num_chains), skip,
                               names, dimss);

    return (new stan::mcmc::chains<>(num_chains, names, dimss));
  }

  /**
   * Return the path to the model (without the extension) as
   * a vector.
   *
   * @return the path to the model
   */
  static std::vector<std::string> get_model_path() {
    return Derived::get_model_path();
  }

  /**
   * Return true if the model has data.
   *
   * @return true if the model has data;
   *         false otherwise.
   */
  static bool has_data() {
    return Derived::has_data();
  }

  /**
   * Return true if the model has an initialization file.
   *
   * @return true if the model has an initialization file;
   *         false otherwise.
   */
  static bool has_init() {
    return Derived::has_init();
  }

  static size_t num_iterations() {
    return Derived::num_iterations();
  }

  static std::vector<std::pair<size_t, double> >
  get_expected_values() {
    return Derived::get_expected_values();
  }

};

template<class Derived>
stan::mcmc::chains<> *Model_Test_Fixture<Derived>::chains;

template<class Derived>
size_t Model_Test_Fixture<Derived>::num_chains = 2;

template<class Derived>
std::string Model_Test_Fixture<Derived>::model_path;

template<class Derived>
std::vector<std::string> Model_Test_Fixture<Derived>::command_outputs;

template<class Derived>
const size_t Model_Test_Fixture<Derived>::skip = 3U;

template<class Derived>
size_t Model_Test_Fixture<Derived>::iterations = 2000U;

TYPED_TEST_CASE_P(Model_Test_Fixture);

TYPED_TEST_P(Model_Test_Fixture, TestGradient) {
  TypeParam::test_gradient();
}

TYPED_TEST_P(Model_Test_Fixture, RunModel) {
  TypeParam::run_model();
}

TYPED_TEST_P(Model_Test_Fixture, ChainsTest) {
  std::vector<std::string> err_message;
  for (size_t chain = 0; chain < TypeParam::num_chains; chain++) {
    std::vector<std::pair<std::string, std::string> > options =
      parse_command_output(TypeParam::command_outputs[chain]);
    parse_command_output(TypeParam::command_outputs[chain]);

    std::string msg = "Seed is : ";
    for (size_t option = 0; option < options.size(); option++) {
      if (options[option].first == "seed")
        msg += options[option].second;
    }
    err_message.push_back(msg);
  }

  stan::mcmc::chains<> *c = TypeParam::chains;
  size_t num_chains = c->num_chains();
  size_t num_params = c->num_params();
  for (size_t chain = 0; chain < num_chains; chain++) {
    for (size_t param = 0; param < num_params; param++) {
      EXPECT_GT(c->variance(chain, param), 0)
        << "Chain " << chain << ", param " << param
        << ": variance is 0" << std::endl
        << err_message[chain];
      // made this 1.2 to fail less often
      EXPECT_LT(c->split_potential_scale_reduction(param), 1.2)
	<< "Chain " << chain << ", param " << param
        << ": split r hat > 1.2" << std::endl
        << err_message[chain];
    }
  }
}

TYPED_TEST_P(Model_Test_Fixture, ExpectedValuesTest) {
  using std::vector;
  using std::pair;
  using std::sqrt;
  using std::fabs;
  using std::setw;

  using boost::math::students_t;
  using boost::math::binomial;
  using boost::math::quantile;

  vector<pair<size_t, double> > expected_values = TypeParam::get_expected_values();
  size_t n = expected_values.size();
  if (n == 0)
    return;

  stan::mcmc::chains<> *c = TypeParam::chains;
  double alpha = 0.005;
  if (n < 3)
    alpha = 0.001;

  int failed = 0;
  std::stringstream err_message;
  for (size_t i = 0; i < n; i++) {
    size_t index = expected_values[i].first;
    double expected_mean = expected_values[i].second;

    double neff = c->effective_sample_size(index);
    double sample_mean = c->mean(index);
    double se = c->sd(index) / sqrt(neff);
    double z = quantile(students_t(neff-1.0), 1 - alpha/2.0);

    // that 2.0 is there to make the test fail less often.
    if (fabs(expected_mean - sample_mean) > z*se * 2.0) {
      failed++;
      // want the error message to have which, what, how
      err_message << "parameter index: " << index
                  << "\n\texpected:    " << setw(10) << expected_mean
                  << "\n\tsampled:     " << setw(10) << sample_mean
		  << "\n\tsd:          " << setw(10) << c->sd(index)
                  << "\n\tneff:        " << setw(10) << neff
                  << "\n\tsplit R.hat: " << setw(10) << c->split_potential_scale_reduction(index)
                  << "\n\tz:           " << setw(10) << z
                  << "\n\tse:          " << setw(10) << se
                  << "\n\n\tfabs(diff) > z * se: "
                  << fabs(expected_mean - sample_mean) << " > " << z*se << "\n\n";
    }
  }

  if (failed == 0)
    return;

  double p = 1 - cdf(binomial(n, alpha), failed);
  // this test should fail less than 0.01% of the time.
  // (if all the parameters are failing independently... ha)
  if (p < 0.0001) {
    err_message << "------------------------------------------------------------\n";
    for (size_t chain = 0; chain < TypeParam::num_chains; chain++) {
      std::vector<std::pair<std::string, std::string> > options =
        parse_command_output(TypeParam::command_outputs[chain]);

      for (size_t option = 0; option < options.size(); option++) {
        if (options[option].first == "seed")
          err_message << "seed: " << options[option].second << std::endl;
      }
    }

    EXPECT_EQ(0, failed)
      << "Failed " << failed << " of " << expected_values.size() << " comparisons\n"
      << "p: " << p << std::endl
      << "------------------------------------------------------------\n"
      << err_message.str() << std::endl
      << "------------------------------------------------------------\n";

  }
}

REGISTER_TYPED_TEST_CASE_P(Model_Test_Fixture,
                           TestGradient,
                           RunModel,
                           ChainsTest,
                           ExpectedValuesTest);

#endif
<|endoftext|>


<commit_before>/* -*- C++ -*- */

/**
 * @file ASPsolverTest.cpp
 * @author Roman Schindlauer
 * @date Thu Jun 30 12:39:40 2005
 *
 * @brief Testsuite class for testing the ASP solver class.
 *
 *
 *
 */

#include "testsuite/dlvhex/ASPsolverTest.h"
#include "dlvhex/errorHandling.h"
#include "dlvhex/globals.h"

// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION(ASPsolverTest);

void
ASPsolverTest::setUp()
{
    solver = new ASPsolver();

    global::optionNoPredicate = 0;
}

void
ASPsolverTest::tearDown()
{
    delete solver;
}

void
ASPsolverTest::testExecution()
{
    //
    // fatal error:
    //
    std::string prg("p.q");
    CPPUNIT_ASSERT_THROW(solver->callSolver(prg), fatalError);
    prg = "p(X):-q.";
    CPPUNIT_ASSERT_THROW(solver->callSolver(prg), fatalError);
    prg = "p(a,b).p(c).";
    CPPUNIT_ASSERT_THROW(solver->callSolver(prg), fatalError);

    //
    // TODO: if we parametrize the solver-executable later, test
    // also the solver existence!
    //
}

void
ASPsolverTest::testResult()
{
    std::string prg;
    GAtomSet *as;

    //
    // no model
    //
    prg = "-p.p.";
    CPPUNIT_ASSERT_NO_THROW(solver->callSolver(prg));
    CPPUNIT_ASSERT(solver->getNextAnswerSet() == NULL);

    //
    // empty model
    //
    prg = "p:-q.";
    CPPUNIT_ASSERT_NO_THROW(solver->callSolver(prg));
    as = solver->getNextAnswerSet();
    CPPUNIT_ASSERT(as->size() == 0);
    CPPUNIT_ASSERT(solver->getNextAnswerSet() == NULL);

    //
    // single model
    //
    prg = "p.q:-p.";
    CPPUNIT_ASSERT_NO_THROW(solver->callSolver(prg));
    as = solver->getNextAnswerSet();
    CPPUNIT_ASSERT(as->size() == 1);
    CPPUNIT_ASSERT(solver->getNextAnswerSet() == NULL);

    //
    // two models
    //
    prg = "p(X):-not q(X),s(X).q(X):-not p(X),s(X).s(a).";
    CPPUNIT_ASSERT_NO_THROW(solver->callSolver(prg));
    as = solver->getNextAnswerSet();
    CPPUNIT_ASSERT(as->size() == 1);
    as = solver->getNextAnswerSet();
    CPPUNIT_ASSERT(as->size() == 1);
    CPPUNIT_ASSERT(solver->getNextAnswerSet() == NULL);

    //
    // strings
    //
    std::string str("\"quoted string, includes some (nasty) special-characters!+#'*[]{}\"");
    prg = "a(" + str + ") :- b. b.";
    CPPUNIT_ASSERT_NO_THROW(solver->callSolver(prg));
    as = solver->getNextAnswerSet();
    CPPUNIT_ASSERT(as->size() == 1);
    CPPUNIT_ASSERT(solver->getNextAnswerSet() == NULL);
    CPPUNIT_ASSERT((*(as->begin())).getArgument(1).getString() == str);

}
<commit_msg>fixed error<commit_after>/* -*- C++ -*- */

/**
 * @file ASPsolverTest.cpp
 * @author Roman Schindlauer
 * @date Thu Jun 30 12:39:40 2005
 *
 * @brief Testsuite class for testing the ASP solver class.
 *
 *
 *
 */

#include "testsuite/dlvhex/ASPsolverTest.h"
#include "dlvhex/errorHandling.h"
#include "dlvhex/globals.h"

// Registers the fixture into the 'registry'
CPPUNIT_TEST_SUITE_REGISTRATION(ASPsolverTest);

void
ASPsolverTest::setUp()
{
    solver = new ASPsolver();

    global::optionNoPredicate = 0;
}

void
ASPsolverTest::tearDown()
{
    delete solver;
}

void
ASPsolverTest::testExecution()
{
    //
    // fatal error:
    //
    std::string prg("p.q");
    CPPUNIT_ASSERT_THROW(solver->callSolver(prg), FatalError);
    prg = "p(X):-q.";
    CPPUNIT_ASSERT_THROW(solver->callSolver(prg), FatalError);
    prg = "p(a,b).p(c).";
    CPPUNIT_ASSERT_THROW(solver->callSolver(prg), FatalError);

    //
    // TODO: if we parametrize the solver-executable later, test
    // also the solver existence!
    //
}

void
ASPsolverTest::testResult()
{
    std::string prg;
    GAtomSet *as;

    //
    // no model
    //
    prg = "-p.p.";
    CPPUNIT_ASSERT_NO_THROW(solver->callSolver(prg));
    CPPUNIT_ASSERT(solver->getNextAnswerSet() == NULL);

    //
    // empty model
    //
    prg = "p:-q.";
    CPPUNIT_ASSERT_NO_THROW(solver->callSolver(prg));
    as = solver->getNextAnswerSet();
    CPPUNIT_ASSERT(as->size() == 0);
    CPPUNIT_ASSERT(solver->getNextAnswerSet() == NULL);

    //
    // single model
    //
    prg = "p.q:-p.";
    CPPUNIT_ASSERT_NO_THROW(solver->callSolver(prg));
    as = solver->getNextAnswerSet();
    CPPUNIT_ASSERT(as->size() == 1);
    CPPUNIT_ASSERT(solver->getNextAnswerSet() == NULL);

    //
    // two models
    //
    prg = "p(X):-not q(X),s(X).q(X):-not p(X),s(X).s(a).";
    CPPUNIT_ASSERT_NO_THROW(solver->callSolver(prg));
    as = solver->getNextAnswerSet();
    CPPUNIT_ASSERT(as->size() == 1);
    as = solver->getNextAnswerSet();
    CPPUNIT_ASSERT(as->size() == 1);
    CPPUNIT_ASSERT(solver->getNextAnswerSet() == NULL);

    //
    // strings
    //
    std::string str("\"quoted string, includes some (nasty) special-characters!+#'*[]{}\"");
    prg = "a(" + str + ") :- b. b.";
    CPPUNIT_ASSERT_NO_THROW(solver->callSolver(prg));
    as = solver->getNextAnswerSet();
    CPPUNIT_ASSERT(as->size() == 1);
    CPPUNIT_ASSERT(solver->getNextAnswerSet() == NULL);
    CPPUNIT_ASSERT((*(as->begin())).getArgument(1).getString() == str);

}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//
// wasm-emscripten-finalize console tool
// Performs Emscripten-specific transforms on .wasm files
//

#include <exception>

#include "abi/js.h"
#include "ir/trapping.h"
#include "support/colors.h"
#include "support/debug.h"
#include "support/file.h"
#include "tool-options.h"
#include "wasm-binary.h"
#include "wasm-emscripten.h"
#include "wasm-io.h"
#include "wasm-validator.h"

#define DEBUG_TYPE "emscripten"

using namespace cashew;
using namespace wasm;

int main(int argc, const char* argv[]) {
  const uint64_t INVALID_BASE = -1;

  std::string infile;
  std::string outfile;
  std::string inputSourceMapFilename;
  std::string outputSourceMapFilename;
  std::string outputSourceMapUrl;
  std::string dataSegmentFile;
  bool emitBinary = true;
  bool debugInfo = false;
  bool DWARF = false;
  bool sideModule = false;
  bool legalizeJavaScriptFFI = true;
  bool bigInt = false;
  bool checkStackOverflow = false;
  uint64_t globalBase = INVALID_BASE;
  bool standaloneWasm = false;
  // TODO: remove after https://github.com/WebAssembly/binaryen/issues/3043
  bool minimizeWasmChanges = false;
  bool noDynCalls = false;
  bool onlyI64DynCalls = false;

  ToolOptions options("wasm-emscripten-finalize",
                      "Performs Emscripten-specific transforms on .wasm files");
  options
    .add("--output",
         "-o",
         "Output file",
         Options::Arguments::One,
         [&outfile](Options*, const std::string& argument) {
           outfile = argument;
           Colors::setEnabled(false);
         })
    .add("--debuginfo",
         "-g",
         "Emit names section in wasm binary (or full debuginfo in wast)",
         Options::Arguments::Zero,
         [&debugInfo](Options*, const std::string&) { debugInfo = true; })
    .add("--dwarf",
         "",
         "Update DWARF debug info",
         Options::Arguments::Zero,
         [&DWARF](Options*, const std::string&) { DWARF = true; })
    .add("--emit-text",
         "-S",
         "Emit text instead of binary for the output file. "
         "In this mode if no output file is specified, we write to stdout.",
         Options::Arguments::Zero,
         [&emitBinary](Options*, const std::string&) { emitBinary = false; })
    .add("--global-base",
         "",
         "The address at which static globals were placed",
         Options::Arguments::One,
         [&globalBase](Options*, const std::string& argument) {
           globalBase = std::stoull(argument);
         })
    // TODO(sbc): Remove this one this argument is no longer passed by
    // emscripten. See https://github.com/emscripten-core/emscripten/issues/8905
    .add("--initial-stack-pointer",
         "",
         "ignored - will be removed in a future release",
         Options::Arguments::One,
         [](Options*, const std::string& argument) {})
    .add("--side-module",
         "",
         "Input is an emscripten side module",
         Options::Arguments::Zero,
         [&sideModule](Options* o, const std::string& argument) {
           sideModule = true;
         })
    .add("--new-pic-abi",
         "",
         "Use new/llvm PIC abi",
         Options::Arguments::Zero,
         [&](Options* o, const std::string& argument) {})
    .add("--input-source-map",
         "-ism",
         "Consume source map from the specified file",
         Options::Arguments::One,
         [&inputSourceMapFilename](Options* o, const std::string& argument) {
           inputSourceMapFilename = argument;
         })
    .add("--no-legalize-javascript-ffi",
         "-nj",
         "Do not fully legalize (i64->i32, "
         "f32->f64) the imports and exports for interfacing with JS",
         Options::Arguments::Zero,
         [&legalizeJavaScriptFFI](Options* o, const std::string&) {
           legalizeJavaScriptFFI = false;
         })
    .add("--bigint",
         "-bi",
         "Assume JS will use wasm/JS BigInt integration, so wasm i64s will "
         "turn into JS BigInts, and there is no need for any legalization at "
         "all (not even minimal legalization of dynCalls)",
         Options::Arguments::Zero,
         [&bigInt](Options* o, const std::string&) { bigInt = true; })
    .add("--output-source-map",
         "-osm",
         "Emit source map to the specified file",
         Options::Arguments::One,
         [&outputSourceMapFilename](Options* o, const std::string& argument) {
           outputSourceMapFilename = argument;
         })
    .add("--output-source-map-url",
         "-osu",
         "Emit specified string as source map URL",
         Options::Arguments::One,
         [&outputSourceMapUrl](Options* o, const std::string& argument) {
           outputSourceMapUrl = argument;
         })
    .add("--separate-data-segments",
         "",
         "Separate data segments to a file",
         Options::Arguments::One,
         [&dataSegmentFile](Options* o, const std::string& argument) {
           dataSegmentFile = argument;
         })
    .add("--check-stack-overflow",
         "",
         "Check for stack overflows every time the stack is extended",
         Options::Arguments::Zero,
         [&checkStackOverflow](Options* o, const std::string&) {
           checkStackOverflow = true;
         })
    .add("--standalone-wasm",
         "",
         "Emit a wasm file that does not depend on JS, as much as possible,"
         " using wasi and other standard conventions etc. where possible",
         Options::Arguments::Zero,
         [&standaloneWasm](Options* o, const std::string&) {
           standaloneWasm = true;
         })
    .add("--minimize-wasm-changes",
         "",
         "Modify the wasm as little as possible. This is useful during "
         "development as we reduce the number of changes to the wasm, as it "
         "lets emscripten control how much modifications to do.",
         Options::Arguments::Zero,
         [&minimizeWasmChanges](Options* o, const std::string&) {
           minimizeWasmChanges = true;
         })
    .add("--no-dyncalls",
         "",
         "",
         Options::Arguments::Zero,
         [&noDynCalls](Options* o, const std::string&) { noDynCalls = true; })
    .add("--dyncalls-i64",
         "",
         "",
         Options::Arguments::Zero,
         [&onlyI64DynCalls](Options* o, const std::string&) {
           onlyI64DynCalls = true;
         })
    .add_positional("INFILE",
                    Options::Arguments::One,
                    [&infile](Options* o, const std::string& argument) {
                      infile = argument;
                    });
  options.parse(argc, argv);

  if (infile == "") {
    Fatal() << "Need to specify an infile\n";
  }

  // We will write the modified wasm if the user asked us to, either by
  // specifying an output file or requesting text output (which goes to stdout
  // by default).
  auto writeOutput = outfile.size() > 0 || !emitBinary;

  Module wasm;
  ModuleReader reader;
  // If we are not writing output then we definitely don't need to read debug
  // info, as it does not affect the metadata we will emit. (However, if we
  // emit output then definitely load the names section so that we roundtrip
  // names properly.)
  reader.setDebugInfo(writeOutput);
  reader.setDWARF(DWARF && writeOutput);
  if (!writeOutput) {
    // If we are not writing the output then all we are doing is simple parsing
    // of metadata from global parts of the wasm such as imports and exports. In
    // that case, it is unnecessary to parse function contents which are the
    // great bulk of the work, and we can skip all that.
    reader.setSkipFunctionBodies(true);
  }
  try {
    reader.read(infile, wasm, inputSourceMapFilename);
  } catch (ParseException& p) {
    p.dump(std::cerr);
    std::cerr << '\n';
    Fatal() << "error in parsing input";
  } catch (MapParseException& p) {
    p.dump(std::cerr);
    std::cerr << '\n';
    Fatal() << "error in parsing wasm source map";
  }

  options.applyFeatures(wasm);

  BYN_TRACE_WITH_TYPE("emscripten-dump", "Module before:\n");
  BYN_DEBUG_WITH_TYPE("emscripten-dump", std::cerr << &wasm);

  EmscriptenGlueGenerator generator(wasm);
  generator.standalone = standaloneWasm;
  generator.sideModule = sideModule;
  generator.minimizeWasmChanges = minimizeWasmChanges;
  generator.onlyI64DynCalls = onlyI64DynCalls;
  generator.noDynCalls = noDynCalls;

  if (!standaloneWasm) {
    // This is also not needed in standalone mode since standalone mode uses
    // crt1.c to invoke the main and is aware of __main_argc_argv mangling.
    generator.renameMainArgcArgv();
  }

  PassRunner passRunner(&wasm, options.passOptions);
  passRunner.setDebug(options.debug);
  passRunner.setDebugInfo(debugInfo);

  if (checkStackOverflow) {
    if (!standaloneWasm) {
      // In standalone mode we don't set a handler at all.. which means
      // just trap on overflow.
      passRunner.options.arguments["stack-check-handler"] =
        "__handle_stack_overflow";
    }
    passRunner.add("stack-check");
  }

  if (!noDynCalls && !standaloneWasm) {
    // If not standalone wasm then JS is relevant and we need dynCalls.
    if (onlyI64DynCalls) {
      passRunner.add("generate-i64-dyncalls");
    } else {
      passRunner.add("generate-dyncalls");
    }
  }

  // Legalize the wasm, if BigInts don't make that moot.
  if (!bigInt) {
    passRunner.add(ABI::getLegalizationPass(
      legalizeJavaScriptFFI ? ABI::LegalizationLevel::Full
                            : ABI::LegalizationLevel::Minimal));
  }

  // Strip target features section (its information is in the metadata)
  passRunner.add("strip-target-features");

  // If DWARF is unused, strip it out. This avoids us keeping it alive
  // until wasm-opt strips it later.
  if (!DWARF) {
    passRunner.add("strip-dwarf");
  }

  passRunner.run();

  if (sideModule) {
    BYN_TRACE("finalizing as side module\n");
    // The emscripten PIC ABI still expects a function named
    // __post_instantiate to be exported by side module.
    if (auto* e = wasm.getExportOrNull(WASM_CALL_CTORS)) {
      e->name = "__post_instantiate";
    }
  }

  BYN_TRACE("generated metadata\n");
  // Substantial changes to the wasm are done, enough to create the metadata.
  std::string metadata = generator.generateEmscriptenMetadata();

  // Finally, separate out data segments if relevant (they may have been needed
  // for metadata).
  if (!dataSegmentFile.empty()) {
    Output memInitFile(dataSegmentFile, Flags::Binary);
    if (globalBase == INVALID_BASE) {
      Fatal() << "globalBase must be set";
    }
    generator.separateDataSegments(&memInitFile, globalBase);
  }

  BYN_TRACE_WITH_TYPE("emscripten-dump", "Module after:\n");
  BYN_DEBUG_WITH_TYPE("emscripten-dump", std::cerr << wasm << '\n');

  if (writeOutput) {
    Output output(outfile, emitBinary ? Flags::Binary : Flags::Text);
    ModuleWriter writer;
    writer.setDebugInfo(debugInfo);
    // writer.setSymbolMap(symbolMap);
    writer.setBinary(emitBinary);
    if (outputSourceMapFilename.size()) {
      writer.setSourceMapFilename(outputSourceMapFilename);
      writer.setSourceMapUrl(outputSourceMapUrl);
    }
    writer.write(wasm, output);
    if (!emitBinary) {
      output << "(;\n";
      output << "--BEGIN METADATA --\n" << metadata << "-- END METADATA --\n";
      output << ";)\n";
    }
  }
  // If we emit text then we emitted the metadata together with that text
  // earlier. Otherwise emit it to stdout.
  if (emitBinary) {
    std::cout << metadata;
  }
  return 0;
}
<commit_msg>Revert the effect of #3689 (#3705)<commit_after>/*
 * Copyright 2017 WebAssembly Community Group participants
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//
// wasm-emscripten-finalize console tool
// Performs Emscripten-specific transforms on .wasm files
//

#include <exception>

#include "abi/js.h"
#include "ir/trapping.h"
#include "support/colors.h"
#include "support/debug.h"
#include "support/file.h"
#include "tool-options.h"
#include "wasm-binary.h"
#include "wasm-emscripten.h"
#include "wasm-io.h"
#include "wasm-validator.h"

#define DEBUG_TYPE "emscripten"

using namespace cashew;
using namespace wasm;

int main(int argc, const char* argv[]) {
  const uint64_t INVALID_BASE = -1;

  std::string infile;
  std::string outfile;
  std::string inputSourceMapFilename;
  std::string outputSourceMapFilename;
  std::string outputSourceMapUrl;
  std::string dataSegmentFile;
  bool emitBinary = true;
  bool debugInfo = false;
  bool DWARF = false;
  bool sideModule = false;
  bool legalizeJavaScriptFFI = true;
  bool bigInt = false;
  bool checkStackOverflow = false;
  uint64_t globalBase = INVALID_BASE;
  bool standaloneWasm = false;
  // TODO: remove after https://github.com/WebAssembly/binaryen/issues/3043
  bool minimizeWasmChanges = false;
  bool noDynCalls = false;
  bool onlyI64DynCalls = false;

  ToolOptions options("wasm-emscripten-finalize",
                      "Performs Emscripten-specific transforms on .wasm files");
  options
    .add("--output",
         "-o",
         "Output file",
         Options::Arguments::One,
         [&outfile](Options*, const std::string& argument) {
           outfile = argument;
           Colors::setEnabled(false);
         })
    .add("--debuginfo",
         "-g",
         "Emit names section in wasm binary (or full debuginfo in wast)",
         Options::Arguments::Zero,
         [&debugInfo](Options*, const std::string&) { debugInfo = true; })
    .add("--dwarf",
         "",
         "Update DWARF debug info",
         Options::Arguments::Zero,
         [&DWARF](Options*, const std::string&) { DWARF = true; })
    .add("--emit-text",
         "-S",
         "Emit text instead of binary for the output file. "
         "In this mode if no output file is specified, we write to stdout.",
         Options::Arguments::Zero,
         [&emitBinary](Options*, const std::string&) { emitBinary = false; })
    .add("--global-base",
         "",
         "The address at which static globals were placed",
         Options::Arguments::One,
         [&globalBase](Options*, const std::string& argument) {
           globalBase = std::stoull(argument);
         })
    // TODO(sbc): Remove this one this argument is no longer passed by
    // emscripten. See https://github.com/emscripten-core/emscripten/issues/8905
    .add("--initial-stack-pointer",
         "",
         "ignored - will be removed in a future release",
         Options::Arguments::One,
         [](Options*, const std::string& argument) {})
    .add("--side-module",
         "",
         "Input is an emscripten side module",
         Options::Arguments::Zero,
         [&sideModule](Options* o, const std::string& argument) {
           sideModule = true;
         })
    .add("--new-pic-abi",
         "",
         "Use new/llvm PIC abi",
         Options::Arguments::Zero,
         [&](Options* o, const std::string& argument) {})
    .add("--input-source-map",
         "-ism",
         "Consume source map from the specified file",
         Options::Arguments::One,
         [&inputSourceMapFilename](Options* o, const std::string& argument) {
           inputSourceMapFilename = argument;
         })
    .add("--no-legalize-javascript-ffi",
         "-nj",
         "Do not fully legalize (i64->i32, "
         "f32->f64) the imports and exports for interfacing with JS",
         Options::Arguments::Zero,
         [&legalizeJavaScriptFFI](Options* o, const std::string&) {
           legalizeJavaScriptFFI = false;
         })
    .add("--bigint",
         "-bi",
         "Assume JS will use wasm/JS BigInt integration, so wasm i64s will "
         "turn into JS BigInts, and there is no need for any legalization at "
         "all (not even minimal legalization of dynCalls)",
         Options::Arguments::Zero,
         [&bigInt](Options* o, const std::string&) { bigInt = true; })
    .add("--output-source-map",
         "-osm",
         "Emit source map to the specified file",
         Options::Arguments::One,
         [&outputSourceMapFilename](Options* o, const std::string& argument) {
           outputSourceMapFilename = argument;
         })
    .add("--output-source-map-url",
         "-osu",
         "Emit specified string as source map URL",
         Options::Arguments::One,
         [&outputSourceMapUrl](Options* o, const std::string& argument) {
           outputSourceMapUrl = argument;
         })
    .add("--separate-data-segments",
         "",
         "Separate data segments to a file",
         Options::Arguments::One,
         [&dataSegmentFile](Options* o, const std::string& argument) {
           dataSegmentFile = argument;
         })
    .add("--check-stack-overflow",
         "",
         "Check for stack overflows every time the stack is extended",
         Options::Arguments::Zero,
         [&checkStackOverflow](Options* o, const std::string&) {
           checkStackOverflow = true;
         })
    .add("--standalone-wasm",
         "",
         "Emit a wasm file that does not depend on JS, as much as possible,"
         " using wasi and other standard conventions etc. where possible",
         Options::Arguments::Zero,
         [&standaloneWasm](Options* o, const std::string&) {
           standaloneWasm = true;
         })
    .add("--minimize-wasm-changes",
         "",
         "Modify the wasm as little as possible. This is useful during "
         "development as we reduce the number of changes to the wasm, as it "
         "lets emscripten control how much modifications to do.",
         Options::Arguments::Zero,
         [&minimizeWasmChanges](Options* o, const std::string&) {
           minimizeWasmChanges = true;
         })
    .add("--no-dyncalls",
         "",
         "",
         Options::Arguments::Zero,
         [&noDynCalls](Options* o, const std::string&) { noDynCalls = true; })
    .add("--dyncalls-i64",
         "",
         "",
         Options::Arguments::Zero,
         [&onlyI64DynCalls](Options* o, const std::string&) {
           onlyI64DynCalls = true;
         })
    .add_positional("INFILE",
                    Options::Arguments::One,
                    [&infile](Options* o, const std::string& argument) {
                      infile = argument;
                    });
  options.parse(argc, argv);

  if (infile == "") {
    Fatal() << "Need to specify an infile\n";
  }

  // We will write the modified wasm if the user asked us to, either by
  // specifying an output file or requesting text output (which goes to stdout
  // by default).
  auto writeOutput = outfile.size() > 0 || !emitBinary;

  Module wasm;
  ModuleReader reader;
  // If we are not writing output then we definitely don't need to read debug
  // info, as it does not affect the metadata we will emit. (However, if we
  // emit output then definitely load the names section so that we roundtrip
  // names properly.)
  reader.setDebugInfo(writeOutput);
  reader.setDWARF(DWARF && writeOutput);
  if (!writeOutput) {
    // If we are not writing the output then all we are doing is simple parsing
    // of metadata from global parts of the wasm such as imports and exports. In
    // that case, it is unnecessary to parse function contents which are the
    // great bulk of the work, and we can skip all that. However, the one
    // exception is pthreads, which does require scanning the code, and so for
    // now we cannot do reader.setSkipFunctionBodies(true); here yet.
  }
  try {
    reader.read(infile, wasm, inputSourceMapFilename);
  } catch (ParseException& p) {
    p.dump(std::cerr);
    std::cerr << '\n';
    Fatal() << "error in parsing input";
  } catch (MapParseException& p) {
    p.dump(std::cerr);
    std::cerr << '\n';
    Fatal() << "error in parsing wasm source map";
  }

  options.applyFeatures(wasm);

  BYN_TRACE_WITH_TYPE("emscripten-dump", "Module before:\n");
  BYN_DEBUG_WITH_TYPE("emscripten-dump", std::cerr << &wasm);

  EmscriptenGlueGenerator generator(wasm);
  generator.standalone = standaloneWasm;
  generator.sideModule = sideModule;
  generator.minimizeWasmChanges = minimizeWasmChanges;
  generator.onlyI64DynCalls = onlyI64DynCalls;
  generator.noDynCalls = noDynCalls;

  if (!standaloneWasm) {
    // This is also not needed in standalone mode since standalone mode uses
    // crt1.c to invoke the main and is aware of __main_argc_argv mangling.
    generator.renameMainArgcArgv();
  }

  PassRunner passRunner(&wasm, options.passOptions);
  passRunner.setDebug(options.debug);
  passRunner.setDebugInfo(debugInfo);

  if (checkStackOverflow) {
    if (!standaloneWasm) {
      // In standalone mode we don't set a handler at all.. which means
      // just trap on overflow.
      passRunner.options.arguments["stack-check-handler"] =
        "__handle_stack_overflow";
    }
    passRunner.add("stack-check");
  }

  if (!noDynCalls && !standaloneWasm) {
    // If not standalone wasm then JS is relevant and we need dynCalls.
    if (onlyI64DynCalls) {
      passRunner.add("generate-i64-dyncalls");
    } else {
      passRunner.add("generate-dyncalls");
    }
  }

  // Legalize the wasm, if BigInts don't make that moot.
  if (!bigInt) {
    passRunner.add(ABI::getLegalizationPass(
      legalizeJavaScriptFFI ? ABI::LegalizationLevel::Full
                            : ABI::LegalizationLevel::Minimal));
  }

  // Strip target features section (its information is in the metadata)
  passRunner.add("strip-target-features");

  // If DWARF is unused, strip it out. This avoids us keeping it alive
  // until wasm-opt strips it later.
  if (!DWARF) {
    passRunner.add("strip-dwarf");
  }

  passRunner.run();

  if (sideModule) {
    BYN_TRACE("finalizing as side module\n");
    // The emscripten PIC ABI still expects a function named
    // __post_instantiate to be exported by side module.
    if (auto* e = wasm.getExportOrNull(WASM_CALL_CTORS)) {
      e->name = "__post_instantiate";
    }
  }

  BYN_TRACE("generated metadata\n");
  // Substantial changes to the wasm are done, enough to create the metadata.
  std::string metadata = generator.generateEmscriptenMetadata();

  // Finally, separate out data segments if relevant (they may have been needed
  // for metadata).
  if (!dataSegmentFile.empty()) {
    Output memInitFile(dataSegmentFile, Flags::Binary);
    if (globalBase == INVALID_BASE) {
      Fatal() << "globalBase must be set";
    }
    generator.separateDataSegments(&memInitFile, globalBase);
  }

  BYN_TRACE_WITH_TYPE("emscripten-dump", "Module after:\n");
  BYN_DEBUG_WITH_TYPE("emscripten-dump", std::cerr << wasm << '\n');

  if (writeOutput) {
    Output output(outfile, emitBinary ? Flags::Binary : Flags::Text);
    ModuleWriter writer;
    writer.setDebugInfo(debugInfo);
    // writer.setSymbolMap(symbolMap);
    writer.setBinary(emitBinary);
    if (outputSourceMapFilename.size()) {
      writer.setSourceMapFilename(outputSourceMapFilename);
      writer.setSourceMapUrl(outputSourceMapUrl);
    }
    writer.write(wasm, output);
    if (!emitBinary) {
      output << "(;\n";
      output << "--BEGIN METADATA --\n" << metadata << "-- END METADATA --\n";
      output << ";)\n";
    }
  }
  // If we emit text then we emitted the metadata together with that text
  // earlier. Otherwise emit it to stdout.
  if (emitBinary) {
    std::cout << metadata;
  }
  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 CodiLime
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <QSettings>
#include <QApplication>
#include <QStandardPaths>
#include <QFileInfo>

#include "util/settings/connection_client.h"

namespace veles {
namespace util {
namespace settings {
namespace connection {

bool default_run_server = true;
QString localhost("127.0.0.1");
QString default_database_file("veles.vdb");
int default_server_port = 3135;
QString default_default_profile("local server");
QString current_profile;

void setDefaultProfile(QString profile) {
  QSettings settings;
  settings.setValue("default_profile", profile);
}

QString currentProfile() {
  if (current_profile.isEmpty()) {
    QSettings settings;
    current_profile = settings.value("default_profile", default_default_profile).toString();
  }
  return current_profile;
}

void setCurrentProfile(QString profile) {
  current_profile = profile;
}

void removeProfile(QString profile) {
  QSettings settings;
  QMap<QString, QVariant> profiles = settings.value("profiles").toMap();
  profiles.remove(profile);
  if (profiles.size() == 0) {
    settings.remove("profiles");
  } else {
    settings.setValue("profiles", profiles);
  }
  if (profile == currentProfile()) {
    auto profiles = profileList();
    if (profiles.empty()) {
      setCurrentProfile(default_default_profile);
    } else {
      setCurrentProfile(profiles[0]);
    }
  }

  if (profile == settings.value("default_profile")) {
    settings.remove("default_profile");
  }
}

QStringList profileList() {
  QSettings settings;
  QMap<QString, QVariant> default_profiles;
  default_profiles[default_default_profile] = QSettings::SettingsMap();
  QMap<QString, QVariant> profiles = settings.value("profiles", default_profiles).toMap();
  return profiles.keys();
}

QVariant profileSettings(QString key, QVariant defaultValue) {
  QSettings settings;
  QMap<QString, QVariant> profiles = settings.value("profiles", QSettings::SettingsMap()).toMap();
  QSettings::SettingsMap profile_settings = profiles.value(currentProfile(), QSettings::SettingsMap()).toMap();
  return profile_settings.value(key, defaultValue);
}

void setProfileSettings(QString key, QVariant value) {
  QSettings settings;
  QMap<QString, QVariant> profiles = settings.value("profiles").toMap();
  QSettings::SettingsMap profile = profiles[currentProfile()].toMap();
  profile[key] = value;
  profiles[currentProfile()] = profile;
  settings.setValue("profiles", profiles);
}

QString uniqueProfileName(QString prefix) {
  auto profile_list = profileList();
  int next_id = 0;
  QString suffix;
  while (profile_list.contains(prefix + suffix)) {
    suffix = " (" + QString::number(next_id++) + ")";
  }
  return prefix + suffix;
}

bool runServerDefault() {
  return default_run_server;
}

bool runServer() {
  return profileSettings("conection.run_server", runServerDefault()).toBool();
}

void setRunServer(bool run_server) {
  setProfileSettings("conection.run_server", run_server);
}

QString serverHostDefault() {
  return localhost;
}

QString serverHost() {
  return profileSettings("conection.server", serverHostDefault()).toString();
}

void setServerHost(QString server_host) {
  setProfileSettings("conection.server", server_host);
}

int serverPortDefault() {
  return default_server_port;
}

int serverPort() {
  return profileSettings("conection.server_port", serverPortDefault()).toInt();
}

void setServerPort(int server_port) {
  setProfileSettings("conection.server_port", server_port);
}

QString clientInterfaceDefault() {
  return localhost;
}

QString clientInterface() {
  return profileSettings("conection.client_interface",
      clientInterfaceDefault()).toString();
}

void setClientInterface(QString client_interface) {
  setProfileSettings("conection.client_interface", client_interface);
}

QString clientName() {
  return profileSettings("conection.client_name", clientNameDefault()).toString();
}

QString clientNameDefault() {
  QString user_name;
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
  user_name = qgetenv("USER");
#elif defined(Q_OS_WIN)
  user_name = qgetenv("USERNAME");
#else
    user_name = "Veles UI";
#endif

  if(user_name.length() == 0) {
    user_name = "Veles UI";
  }

  return user_name;
}

void setClientName(QString client_name) {
  setProfileSettings("conection.client_name", client_name);
}

QString connectionKeyDefault() {
  return QString("");
}

QString connectionKey() {
  return profileSettings("conection.key", connectionKeyDefault()).toString();
}

void setConnectionKey(QString connection_key) {
  QSettings settings;
  setProfileSettings("conection.key", connection_key);
}

QString databaseNameDefault() {
  return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/" + default_database_file;
}

QString databaseName() {
  return profileSettings("conection.database",
      databaseNameDefault()).toString();
}

void setDatabaseName(QString database_name) {
  setProfileSettings("conection.database", database_name);
}

QString serverScriptDefault() {
  QString server_script;
#if defined(Q_OS_WIN)
  server_script = qApp->applicationDirPath() + "/../veles-server/srv.py";
#elif defined(Q_OS_LINUX)
  server_script = qApp->applicationDirPath() + "/../share/veles-server/srv.py";
#else
  server_script = qApp->applicationDirPath() + "/../Resources/veles-server/srv.py";
#endif
  QFileInfo check_file(server_script);
  if (!check_file.exists()) {
    server_script = qApp->applicationDirPath() + "/python/srv.py";
  }
  return server_script;
}

QString serverScript() {
  return profileSettings("connection.server_script",
      serverScriptDefault()).toString();
}

void setServerScript(QString server_script) {
  setProfileSettings("connection.server_script", server_script);
}

}  // namespace connection
}  // namespace settings
}  // namespace util
}  // namespace veles
<commit_msg>Display cleaned path to srv.py<commit_after>/*
 * Copyright 2017 CodiLime
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <QApplication>
#include <QDir>
#include <QSettings>
#include <QStandardPaths>
#include <QFileInfo>

#include "util/settings/connection_client.h"

namespace veles {
namespace util {
namespace settings {
namespace connection {

bool default_run_server = true;
QString localhost("127.0.0.1");
QString default_database_file("veles.vdb");
int default_server_port = 3135;
QString default_default_profile("local server");
QString current_profile;

void setDefaultProfile(QString profile) {
  QSettings settings;
  settings.setValue("default_profile", profile);
}

QString currentProfile() {
  if (current_profile.isEmpty()) {
    QSettings settings;
    current_profile = settings.value("default_profile", default_default_profile).toString();
  }
  return current_profile;
}

void setCurrentProfile(QString profile) {
  current_profile = profile;
}

void removeProfile(QString profile) {
  QSettings settings;
  QMap<QString, QVariant> profiles = settings.value("profiles").toMap();
  profiles.remove(profile);
  if (profiles.size() == 0) {
    settings.remove("profiles");
  } else {
    settings.setValue("profiles", profiles);
  }
  if (profile == currentProfile()) {
    auto profiles = profileList();
    if (profiles.empty()) {
      setCurrentProfile(default_default_profile);
    } else {
      setCurrentProfile(profiles[0]);
    }
  }

  if (profile == settings.value("default_profile")) {
    settings.remove("default_profile");
  }
}

QStringList profileList() {
  QSettings settings;
  QMap<QString, QVariant> default_profiles;
  default_profiles[default_default_profile] = QSettings::SettingsMap();
  QMap<QString, QVariant> profiles = settings.value("profiles", default_profiles).toMap();
  return profiles.keys();
}

QVariant profileSettings(QString key, QVariant defaultValue) {
  QSettings settings;
  QMap<QString, QVariant> profiles = settings.value("profiles", QSettings::SettingsMap()).toMap();
  QSettings::SettingsMap profile_settings = profiles.value(currentProfile(), QSettings::SettingsMap()).toMap();
  return profile_settings.value(key, defaultValue);
}

void setProfileSettings(QString key, QVariant value) {
  QSettings settings;
  QMap<QString, QVariant> profiles = settings.value("profiles").toMap();
  QSettings::SettingsMap profile = profiles[currentProfile()].toMap();
  profile[key] = value;
  profiles[currentProfile()] = profile;
  settings.setValue("profiles", profiles);
}

QString uniqueProfileName(QString prefix) {
  auto profile_list = profileList();
  int next_id = 0;
  QString suffix;
  while (profile_list.contains(prefix + suffix)) {
    suffix = " (" + QString::number(next_id++) + ")";
  }
  return prefix + suffix;
}

bool runServerDefault() {
  return default_run_server;
}

bool runServer() {
  return profileSettings("conection.run_server", runServerDefault()).toBool();
}

void setRunServer(bool run_server) {
  setProfileSettings("conection.run_server", run_server);
}

QString serverHostDefault() {
  return localhost;
}

QString serverHost() {
  return profileSettings("conection.server", serverHostDefault()).toString();
}

void setServerHost(QString server_host) {
  setProfileSettings("conection.server", server_host);
}

int serverPortDefault() {
  return default_server_port;
}

int serverPort() {
  return profileSettings("conection.server_port", serverPortDefault()).toInt();
}

void setServerPort(int server_port) {
  setProfileSettings("conection.server_port", server_port);
}

QString clientInterfaceDefault() {
  return localhost;
}

QString clientInterface() {
  return profileSettings("conection.client_interface",
      clientInterfaceDefault()).toString();
}

void setClientInterface(QString client_interface) {
  setProfileSettings("conection.client_interface", client_interface);
}

QString clientName() {
  return profileSettings("conection.client_name", clientNameDefault()).toString();
}

QString clientNameDefault() {
  QString user_name;
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
  user_name = qgetenv("USER");
#elif defined(Q_OS_WIN)
  user_name = qgetenv("USERNAME");
#else
    user_name = "Veles UI";
#endif

  if(user_name.length() == 0) {
    user_name = "Veles UI";
  }

  return user_name;
}

void setClientName(QString client_name) {
  setProfileSettings("conection.client_name", client_name);
}

QString connectionKeyDefault() {
  return QString("");
}

QString connectionKey() {
  return profileSettings("conection.key", connectionKeyDefault()).toString();
}

void setConnectionKey(QString connection_key) {
  QSettings settings;
  setProfileSettings("conection.key", connection_key);
}

QString databaseNameDefault() {
  return QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) + "/" + default_database_file;
}

QString databaseName() {
  return profileSettings("conection.database",
      databaseNameDefault()).toString();
}

void setDatabaseName(QString database_name) {
  setProfileSettings("conection.database", database_name);
}

QString serverScriptDefault() {
  QString server_script;
#if defined(Q_OS_WIN)
  server_script = qApp->applicationDirPath() + "/../veles-server/srv.py";
#elif defined(Q_OS_LINUX)
  server_script = qApp->applicationDirPath() + "/../share/veles-server/srv.py";
#elif defined(Q_OS_MAC)
  server_script = qApp->applicationDirPath() + "/../Resources/veles-server/srv.py";
#else
  #error OS not supported
#endif
  QFileInfo check_file(server_script);
  if (!check_file.exists()) {
    server_script = qApp->applicationDirPath() + "/python/srv.py";
  }
  return QDir::cleanPath(server_script);
}

QString serverScript() {
  return profileSettings("connection.server_script",
      serverScriptDefault()).toString();
}

void setServerScript(QString server_script) {
  setProfileSettings("connection.server_script", server_script);
}

}  // namespace connection
}  // namespace settings
}  // namespace util
}  // namespace veles
<|endoftext|>