<commit_before>/*****************************************************************************
 * wxwidgets.hpp: Common headers for the wxwidges interface
 *****************************************************************************
 * Copyright (C) 1999-2005 the VideoLAN team
 * $Id$
 *
 * Authors: Gildas Bazin <gbazin@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef _WXVLC_WIDGETS_H_
#define _WXVLC_WIDGETS_H_

#ifdef WIN32                                                 /* mingw32 hack */
#undef Yield
#undef CreateDialog
#endif

#ifdef _MSC_VER
// turn off 'identifier was truncated to '255' characters in the debug info'
#   pragma warning( disable:4786 )
#endif

/* Let vlc take care of the i18n stuff */
#define WXINTL_NO_GETTEXT_MACRO

#include <vlc/vlc.h>
#include <vlc/intf.h>
#include "charset.h"

#include <wx/wx.h>
#define SLIDER_MAX_POS 10000

/*
#include <wx/listctrl.h>
#include <wx/textctrl.h>
#include <wx/notebook.h>
#include <wx/spinctrl.h>
#include <wx/dnd.h>
#include <wx/treectrl.h>
#include <wx/gauge.h>
#include <wx/accel.h>
#include <wx/checkbox.h>
#include <wx/wizard.h>
#include <wx/taskbar.h>
#include "vlc_keys.h"
*/
#if (!wxCHECK_VERSION(2,5,0))
typedef long wxTreeItemIdValue;
#endif

DECLARE_LOCAL_EVENT_TYPE( wxEVT_DIALOG, 0 );
DECLARE_LOCAL_EVENT_TYPE( wxEVT_INTF, 1 );

/***************************************************************************
 * I18N macros
 ***************************************************************************/

/*
 * wxU() is used to convert UTF-8 strings (typically from gettext)
 * to unicode strings (wchar_t).
 */
#if wxUSE_UNICODE
#   define wxU(utf8) wxString(utf8, wxConvUTF8)
#else
#   define wxU(utf8) wxString(wxConvUTF8.cMB2WC(utf8), *wxConvCurrent)
#endif

/*
 * wxL2U() use to convert localized “data” strings (while wxU() would convert
 * strings from gettext messages). Nowadays, the core use UTF-8 internally
 * and wxL2U() is only an obsoleted name for wxU().
 */
#define wxL2U(utf8) wxU(utf8)

/*
 * wxFromLocale() is a replacement for LibVLC FromLocale() that accepts
 * a wxString. It was originally introduced because wxString::mb_str()
 * sucks on Linux with Unicode wxWidgets. It then turned out wxWidgets
 * did not support wc_str() when Unicode was not enabled.
 *
 * But heh, that's wxWidgets; you can't really expect it to actually
 * work, let alone work like its documentation says.
 *
 * Did it work, we would be able to catch non-ANSI characters on Windows
 * through wxString::wc_str(); while they are lost when using mb_str().
 * This would be particularly useful to open files whose names contain
 * non-ACP characters.
 */
#if wxUSE_UNICODE
#   define wxFromLocale(wxstring) FromWide(wxstring.wc_str())
#   define wxLocaleFree(string) free(string)
#else
#   define wxFromLocale(wxstring) FromLocale(wxstring.mb_str())
#   define wxLocaleFree(string) LocaleFree(string)
#endif

/* From Locale functions to use for File Drop targets ... go figure */
#ifdef wxUSE_UNICODE
static inline char *wxDnDFromLocale( const wxChar *stupid )
{
    /*
     * In Unicode mode, wxWidgets will encode file names in the locale
     * encoding with each **bytes** (rather than characters) represented
     * by a 32 bits unsigned integer. If you are lucky enough to be using
     * ISO-8859-1 as your local character encoding, that lame encoding
     * scheme happens to be identical to UTF-32 with your arch native
     * byte-endianess. If you are using anything else, including not only
     * UTF-8 but also Windows-1252(!) and ISO-8859-15(!) or any
     * non-western encoding, it obviously fails.
     */
    size_t i = 0;
    while (stupid[i])
        i++;

    char psz_local[i + 1];
    if ((i >= 1) && (stupid[i - 1] == '\n'))
        i--;

    do
        psz_local[i] = stupid[i];
    while (i--);

    return FromLocaleDup( psz_local );
}
#   define wxDnDLocaleFree( string ) free( string )
#else
#   define wxDnDFromLocale( string ) wxFromLocale( string )
#   define wxDnDLocaleFree( string ) wxLocaleFree( string )
#endif

#define WRAPCOUNT 80

#define OPEN_NORMAL 0
#define OPEN_STREAM 1

enum
{
  ID_CONTROLS_TIMER,
  ID_SLIDER_TIMER,
};

namespace wxvlc {
    class WindowSettings;
    class VideoWindow;
};

using namespace wxvlc;

/*****************************************************************************
 * intf_sys_t: description and status of wxwindows interface
 *****************************************************************************/
struct intf_sys_t
{
    /* the wx parent window */
    wxWindow            *p_wxwindow;
    wxIcon              *p_icon;

    /* window settings */
    WindowSettings      *p_window_settings;

    /* special actions */
    vlc_bool_t          b_playing;
    vlc_bool_t          b_intf_show;                /* interface to be shown */

    /* The input thread */
    input_thread_t *    p_input;

    /* The messages window */
    msg_subscription_t* p_sub;                  /* message bank subscription */

    /* Playlist management */
    int                 i_playing;                 /* playlist selected item */
    unsigned            i_playlist_usage;

    /* Send an event to show a dialog */
    void (*pf_show_dialog) ( intf_thread_t *p_intf, int i_dialog, int i_arg,
                             intf_dialog_args_t *p_arg );

    /* Popup menu */
    wxMenu              *p_popup_menu;

    /* Hotkeys */
    int                 i_first_hotkey_event;
    int                 i_hotkeys;

    /* Embedded vout */
    VideoWindow         *p_video_window;
    wxBoxSizer          *p_video_sizer;
    vlc_bool_t          b_video_autosize;

    /* Aout */
    aout_instance_t     *p_aout;
};

wxArrayString SeparateEntries( wxString );
wxWindow *CreateDialogsProvider( intf_thread_t *p_intf, wxWindow *p_parent );

/*
 * wxWindows keeps dead locking because the timer tries to lock the playlist
 * when it's already locked somewhere else in the very wxWindows interface
 * module. Unless someone implements a "vlc_mutex_trylock", we need that.
 */
inline void LockPlaylist( intf_sys_t *p_sys, playlist_t *p_pl )
{
    if( p_sys->i_playlist_usage++ == 0)
        vlc_mutex_lock( &p_pl->object_lock );
}

inline void UnlockPlaylist( intf_sys_t *p_sys, playlist_t *p_pl )
{
    if( --p_sys->i_playlist_usage == 0)
        vlc_mutex_unlock( &p_pl->object_lock );
}

#endif
<commit_msg>frontport [17287] from branch<commit_after>/*****************************************************************************
 * wxwidgets.hpp: Common headers for the wxwidges interface
 *****************************************************************************
 * Copyright (C) 1999-2005 the VideoLAN team
 * $Id$
 *
 * Authors: Gildas Bazin <gbazin@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef _WXVLC_WIDGETS_H_
#define _WXVLC_WIDGETS_H_

#ifdef WIN32                                                 /* mingw32 hack */
#undef Yield
#undef CreateDialog
#endif

#ifdef _MSC_VER
// turn off 'identifier was truncated to '255' characters in the debug info'
#   pragma warning( disable:4786 )
#endif

/* Let vlc take care of the i18n stuff */
#define WXINTL_NO_GETTEXT_MACRO

#include <vlc/vlc.h>
#include <vlc/intf.h>
#include "charset.h"

#include <wx/wx.h>
#define SLIDER_MAX_POS 10000

/*
#include <wx/listctrl.h>
#include <wx/textctrl.h>
#include <wx/notebook.h>
#include <wx/spinctrl.h>
#include <wx/dnd.h>
#include <wx/treectrl.h>
#include <wx/gauge.h>
#include <wx/accel.h>
#include <wx/checkbox.h>
#include <wx/wizard.h>
#include <wx/taskbar.h>
#include "vlc_keys.h"
*/
#if (!wxCHECK_VERSION(2,5,0))
typedef long wxTreeItemIdValue;
#endif

DECLARE_LOCAL_EVENT_TYPE( wxEVT_DIALOG, 0 );
DECLARE_LOCAL_EVENT_TYPE( wxEVT_INTF, 1 );

/***************************************************************************
 * I18N macros
 ***************************************************************************/

/*
 * wxU() is used to convert UTF-8 strings (typically from gettext)
 * to unicode strings (wchar_t).
 */
#if wxUSE_UNICODE
#   define wxU(utf8) wxString(utf8, wxConvUTF8)
#else
#   define wxU(utf8) wxString(wxConvUTF8.cMB2WC(utf8), *wxConvCurrent)
#endif

/*
 * wxL2U() use to convert localized “data” strings (while wxU() would convert
 * strings from gettext messages). Nowadays, the core use UTF-8 internally
 * and wxL2U() is only an obsoleted name for wxU().
 */
#define wxL2U(utf8) wxU(utf8)

/*
 * wxFromLocale() is a replacement for LibVLC FromLocale() that accepts
 * a wxString. It was originally introduced because wxString::mb_str()
 * sucks on Linux with Unicode wxWidgets. It then turned out wxWidgets
 * did not support wc_str() when Unicode was not enabled.
 *
 * But heh, that's wxWidgets; you can't really expect it to actually
 * work, let alone work like its documentation says.
 *
 * Did it work, we would be able to catch non-ANSI characters on Windows
 * through wxString::wc_str(); while they are lost when using mb_str().
 * This would be particularly useful to open files whose names contain
 * non-ACP characters.
 */
#if wxUSE_UNICODE
#   define wxFromLocale(wxstring) FromWide(wxstring.wc_str())
#   define wxLocaleFree(string) free(string)
#else
#   define wxFromLocale(wxstring) FromLocale(wxstring.mb_str())
#   define wxLocaleFree(string) LocaleFree(string)
#endif

/* From Locale functions to use for File Drop targets ... go figure */
#ifdef wxUSE_UNICODE
static inline char *wxDnDFromLocale( const wxChar *stupid )
{
    /*
     * In Unicode mode, wxWidgets will encode file names in the locale
     * encoding with each **bytes** (rather than characters) represented
     * by a 32 bits unsigned integer. If you are lucky enough to be using
     * ISO-8859-1 as your local character encoding, that lame encoding
     * scheme happens to be identical to UTF-32 with your arch native
     * byte-endianess. If you are using anything else, including not only
     * UTF-8 but also Windows-1252(!) and ISO-8859-15(!) or any
     * non-western encoding, it obviously fails.
     */

    wxString str(stupid);
    int i;

    size_t n = str.Len();

    char psz_local[n+1];

    for(i=0;i<n;i++)
        psz_local[i] = stupid[i];
    psz_local[n] = '\0';

    if( psz_local[n-1] == '\n' )
        psz_local[n-1] = '\0';

    return FromLocaleDup( psz_local );
}
#else
#   define wxDnDFromLocale( string ) wxFromLocale( string )
#endif

#define wxDnDLocaleFree( string ) wxLocaleFree( string )

#define WRAPCOUNT 80

#define OPEN_NORMAL 0
#define OPEN_STREAM 1

enum
{
  ID_CONTROLS_TIMER,
  ID_SLIDER_TIMER,
};

namespace wxvlc {
    class WindowSettings;
    class VideoWindow;
};

using namespace wxvlc;

/*****************************************************************************
 * intf_sys_t: description and status of wxwindows interface
 *****************************************************************************/
struct intf_sys_t
{
    /* the wx parent window */
    wxWindow            *p_wxwindow;
    wxIcon              *p_icon;

    /* window settings */
    WindowSettings      *p_window_settings;

    /* special actions */
    vlc_bool_t          b_playing;
    vlc_bool_t          b_intf_show;                /* interface to be shown */

    /* The input thread */
    input_thread_t *    p_input;

    /* The messages window */
    msg_subscription_t* p_sub;                  /* message bank subscription */

    /* Playlist management */
    int                 i_playing;                 /* playlist selected item */
    unsigned            i_playlist_usage;

    /* Send an event to show a dialog */
    void (*pf_show_dialog) ( intf_thread_t *p_intf, int i_dialog, int i_arg,
                             intf_dialog_args_t *p_arg );

    /* Popup menu */
    wxMenu              *p_popup_menu;

    /* Hotkeys */
    int                 i_first_hotkey_event;
    int                 i_hotkeys;

    /* Embedded vout */
    VideoWindow         *p_video_window;
    wxBoxSizer          *p_video_sizer;
    vlc_bool_t          b_video_autosize;

    /* Aout */
    aout_instance_t     *p_aout;
};

wxArrayString SeparateEntries( wxString );
wxWindow *CreateDialogsProvider( intf_thread_t *p_intf, wxWindow *p_parent );

/*
 * wxWindows keeps dead locking because the timer tries to lock the playlist
 * when it's already locked somewhere else in the very wxWindows interface
 * module. Unless someone implements a "vlc_mutex_trylock", we need that.
 */
inline void LockPlaylist( intf_sys_t *p_sys, playlist_t *p_pl )
{
    if( p_sys->i_playlist_usage++ == 0)
        vlc_mutex_lock( &p_pl->object_lock );
}

inline void UnlockPlaylist( intf_sys_t *p_sys, playlist_t *p_pl )
{
    if( --p_sys->i_playlist_usage == 0)
        vlc_mutex_unlock( &p_pl->object_lock );
}

#endif
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "shaders.h"

const uint32_t WIDTH = 1024u;
const uint32_t HEIGHT = 768u;

static PFN_vkCreateDebugReportCallbackEXT pfnCreateDebugReportCallbackEXT = nullptr;
static PFN_vkDestroyDebugReportCallbackEXT pfnDestroyDebugReportCallbackEXT = nullptr;

static FILE* file = nullptr;

static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report_callback(
    VkDebugReportFlagsEXT flags,
    VkDebugReportObjectTypeEXT objectType,
    uint64_t object,
    size_t location,
    int32_t messageCode,
    const char* pLayerPrefix,
    const char* pMessage,
    void* pUserData)
{
    std::fprintf(file, "%s: %s\n", pLayerPrefix, pMessage);
    return false;
}

static VkDebugReportCallbackEXT create_debug_report_callback(VkInstance vulkan)
{
    pfnCreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
        vkGetInstanceProcAddr(vulkan, "vkCreateDebugReportCallbackEXT")
    );
    pfnDestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
        vkGetInstanceProcAddr(vulkan, "vkDestroyDebugReportCallbackEXT")
    );

#if _DEBUG
    VkDebugReportCallbackCreateInfoEXT info = {};
    info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
    info.flags =
        VK_DEBUG_REPORT_ERROR_BIT_EXT |
        VK_DEBUG_REPORT_WARNING_BIT_EXT |
        VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
    info.pfnCallback = &debug_report_callback;

    VkDebugReportCallbackEXT callback;
    auto error = pfnCreateDebugReportCallbackEXT(vulkan, &info, nullptr, &callback);
    assert(!error);
    return callback;
#else
    return nullptr;
#endif
}

static void error_callback(int error, const char* description)
{
    throw std::runtime_error(description);
}

vk::Instance create_instance()
{
#if _DEBUG
    const auto layerCount = 1;
    const char* layerNames[layerCount] = {"VK_LAYER_LUNARG_standard_validation"};
#else
    const auto layerCount = 0;
    const char **layerNames = nullptr;
#endif

    const auto extensionCount = 3;
    const char* extensionNames[extensionCount] = {
        VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
        VK_KHR_SURFACE_EXTENSION_NAME,
        VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
    };

    return vk::createInstance(
        vk::InstanceCreateInfo()
        .setEnabledLayerCount(layerCount)
        .setPpEnabledLayerNames(layerNames)
        .setEnabledExtensionCount(extensionCount)
        .setPpEnabledExtensionNames(extensionNames)
    );
}

static vk::PhysicalDevice get_physical_device(vk::Instance vulkan)
{
    auto devices = vulkan.enumeratePhysicalDevices();
    assert(devices.size() == 1);

    auto props = devices[0].getProperties();
    std::printf("Using physical device: %s\n", props.deviceName);
    return devices[0];
}

static vk::Device create_device(vk::PhysicalDevice physical_device)
{
    float priorities[] = {0.f};
    auto queueInfo = vk::DeviceQueueCreateInfo()
        .setQueueCount(1)
        .setPQueuePriorities(priorities);

#if _DEBUG
    const auto layerCount = 1;
    const char* layerNames[layerCount] = {"VK_LAYER_LUNARG_standard_validation"};
#else
    const auto layerCount = 0;
    const char **layerNames = nullptr;
#endif

    const auto extensionCount = 1;
    const char* extensionNames[extensionCount] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};

    auto features = vk::PhysicalDeviceFeatures()
        .setShaderClipDistance(true)
        .setShaderCullDistance(true);

    return physical_device.createDevice(
        vk::DeviceCreateInfo()
        .setQueueCreateInfoCount(1)
        .setPQueueCreateInfos(&queueInfo)
        .setEnabledLayerCount(layerCount)
        .setPpEnabledLayerNames(layerNames)
        .setEnabledExtensionCount(1)
        .setPpEnabledExtensionNames(extensionNames)
        .setPEnabledFeatures(&features)
    );
}

static vk::RenderPass create_render_pass(vk::Device device)
{
    auto attachment = vk::AttachmentDescription()
        .setFormat(vk::Format::eB8G8R8A8Unorm)
        .setSamples(vk::SampleCountFlagBits::e1)
        .setLoadOp(vk::AttachmentLoadOp::eClear)
        .setStoreOp(vk::AttachmentStoreOp::eStore)
        .setStencilLoadOp(vk::AttachmentLoadOp::eDontCare)
        .setStencilStoreOp(vk::AttachmentStoreOp::eDontCare)
        .setInitialLayout(vk::ImageLayout::eColorAttachmentOptimal)
        .setFinalLayout(vk::ImageLayout::ePresentSrcKHR);

    auto color_attachment = vk::AttachmentReference()
        .setLayout(vk::ImageLayout::eColorAttachmentOptimal);

    auto subpass = vk::SubpassDescription()
        .setColorAttachmentCount(1)
        .setPColorAttachments(&color_attachment);

    return device.createRenderPass(
        vk::RenderPassCreateInfo()
        .setAttachmentCount(1)
        .setPAttachments(&attachment)
        .setSubpassCount(1)
        .setPSubpasses(&subpass)
    );
}

struct buffer_info
{
    vk::DeviceMemory memory;
    vk::Buffer buffer;

    void destroy(vk::Device device)
    {
        device.destroyBuffer(buffer);
        device.freeMemory(memory);
    }
};

static buffer_info create_buffer(vk::PhysicalDevice physical_device, vk::Device device)
{
    auto desired_flags = vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent;
    auto props = physical_device.getMemoryProperties();

    auto memory_type_index = UINT32_MAX;
    for (auto i = uint32_t(0); i < props.memoryTypeCount; i++)
    {
        if ((props.memoryTypes[i].propertyFlags & desired_flags) == desired_flags)
        {
            memory_type_index = i;
            break;
        }
    }
    assert(memory_type_index != UINT32_MAX);

    auto queue_familiy_index = uint32_t(0);
    auto size = 6 * sizeof(vertex);

    auto memory = device.allocateMemory(
        vk::MemoryAllocateInfo()
        .setAllocationSize(size)
        .setMemoryTypeIndex(memory_type_index)
    );

    auto ptr = reinterpret_cast<vertex*>(device.mapMemory(memory, 0, VK_WHOLE_SIZE));
    ptr[0] = {-1.f, 1.f, 255, 0, 0};
    ptr[1] = {1.f, 1.f, 0, 255, 0};
    ptr[2] = {1.f, -1.f, 0, 0, 255};
    ptr[3] = {1.f, -1.f, 0, 0, 255};
    ptr[4] = {-1.f, -1.f, 0, 255, 0};
    ptr[5] = {-1.f, 1.f, 255, 0, 0};
    device.unmapMemory(memory);

    auto buffer = device.createBuffer(
        vk::BufferCreateInfo()
        .setSize(size)
        .setUsage(vk::BufferUsageFlagBits::eVertexBuffer)
        .setQueueFamilyIndexCount(0)
        .setPQueueFamilyIndices(&queue_familiy_index)
        .setSharingMode(vk::SharingMode::eExclusive)
    );

    auto reqs = device.getBufferMemoryRequirements(buffer);
    assert((reqs.memoryTypeBits & 1u << memory_type_index) == 1u << memory_type_index);

    device.bindBufferMemory(buffer, memory, 0);

    buffer_info info;
    info.memory = memory;
    info.buffer = buffer;
    return info;
}

static vk::CommandBuffer create_command_buffer(vk::Device device, vk::CommandPool command_pool, vk::Image image, vk::RenderPass render_pass, vk::Pipeline pipeline, vk::Framebuffer framebuffer)
{
    auto command_buffer = device.allocateCommandBuffers(
        vk::CommandBufferAllocateInfo()
        .setCommandPool(command_pool)
        .setLevel(vk::CommandBufferLevel::ePrimary)
        .setCommandBufferCount(1)
    )[0];

    command_buffer.begin(vk::CommandBufferBeginInfo()
        .setFlags(vk::CommandBufferUsageFlagBits::eSimultaneousUse));

    auto barrier = vk::ImageMemoryBarrier()
        .setImage(image)
        .setOldLayout(vk::ImageLayout::eUndefined)
        .setNewLayout(vk::ImageLayout::eColorAttachmentOptimal)
        .setSubresourceRange(
            vk::ImageSubresourceRange()
            .setAspectMask(vk::ImageAspectFlagBits::eColor)
            .setLevelCount(VK_REMAINING_MIP_LEVELS)
            .setLayerCount(VK_REMAINING_ARRAY_LAYERS)
        )
        .setDstAccessMask(vk::AccessFlagBits::eColorAttachmentWrite);
    command_buffer.pipelineBarrier(
        vk::PipelineStageFlagBits::eColorAttachmentOutput,
        vk::PipelineStageFlagBits::eColorAttachmentOutput,
        vk::DependencyFlags(),
        {},
        {},
        {barrier}
    );

    auto clear_value = vk::ClearValue()
        .setColor(vk::ClearColorValue().setFloat32({0.f, 0.f, 1.f, 0.f}));

    vk::Rect2D render_area;
    render_area.extent.width = WIDTH;
    render_area.extent.height = HEIGHT;

    command_buffer.beginRenderPass(
        vk::RenderPassBeginInfo()
        .setRenderPass(render_pass)
        .setClearValueCount(1)
        .setPClearValues(&clear_value)
        .setRenderArea(render_area)
        .setFramebuffer(framebuffer),
        vk::SubpassContents::eInline
    );

    command_buffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);

    // TODO draw

    command_buffer.endRenderPass();

    command_buffer.end();

    return command_buffer;
}

struct swapchain_info
{
    vk::Device device;
    vk::SwapchainKHR swapchain;
    std::vector<vk::Image> images;
    std::vector<vk::ImageView> image_views;
    std::vector<vk::Framebuffer> framebuffers;
    vk::CommandPool command_pool;
    std::vector<vk::CommandBuffer> command_buffers;
    vk::Semaphore acquire_semaphore;
    vk::Semaphore render_semaphore;

    void destroy()
    {
        device.destroySemaphore(render_semaphore);
        device.destroySemaphore(acquire_semaphore);
        device.destroyCommandPool(command_pool);

        for (auto framebuffer : framebuffers)
        {
            device.destroyFramebuffer(framebuffer);
        }

        for (auto image_view : image_views)
        {
            device.destroyImageView(image_view);
        }

        device.destroySwapchainKHR(swapchain);
    }
};

static swapchain_info create_swapchain(vk::PhysicalDevice physical_device, vk::Device device, vk::RenderPass render_pass, vk::Pipeline pipeline, vk::SurfaceKHR surface)
{
    auto supported = physical_device.getSurfaceSupportKHR(0, surface);
    assert(supported);

    auto caps = physical_device.getSurfaceCapabilitiesKHR(surface);

    auto swapchain = device.createSwapchainKHR(
        vk::SwapchainCreateInfoKHR()
        .setSurface(surface)
        .setMinImageCount(2)
        .setImageFormat(vk::Format::eB8G8R8A8Unorm)
        .setImageExtent(caps.currentExtent)
        .setImageArrayLayers(1)
        .setImageUsage(vk::ImageUsageFlagBits::eColorAttachment)
        .setPreTransform(caps.currentTransform)
        .setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque)
        .setClipped(true)
        .setPresentMode(vk::PresentModeKHR::eFifo)
    );

    auto images = device.getSwapchainImagesKHR(swapchain);

    swapchain_info swapchain_info = {};
    swapchain_info.device = device;
    swapchain_info.swapchain = swapchain;
    swapchain_info.images = images;
    swapchain_info.command_pool = device.createCommandPool(vk::CommandPoolCreateInfo());

    for (auto image : images)
    {
        auto view = device.createImageView(
            vk::ImageViewCreateInfo()
            .setFormat(vk::Format::eB8G8R8A8Unorm)
            .setViewType(vk::ImageViewType::e2D)
            .setImage(image)
            .setSubresourceRange(
                vk::ImageSubresourceRange()
                .setAspectMask(vk::ImageAspectFlagBits::eColor)
                .setLevelCount(VK_REMAINING_MIP_LEVELS)
                .setLayerCount(1)
            )
        );
        swapchain_info.image_views.push_back(view);

        auto framebuffer = device.createFramebuffer(
            vk::FramebufferCreateInfo()
            .setRenderPass(render_pass)
            .setAttachmentCount(1)
            .setPAttachments(&view)
            .setWidth(WIDTH)
            .setHeight(HEIGHT)
            .setLayers(1)
        );
        swapchain_info.framebuffers.push_back(framebuffer);

        swapchain_info.command_buffers.push_back(create_command_buffer(
            device,
            swapchain_info.command_pool,
            image,
            render_pass,
            pipeline,
            framebuffer
        ));
    }

    swapchain_info.acquire_semaphore = device.createSemaphore(vk::SemaphoreCreateInfo());
    swapchain_info.render_semaphore = device.createSemaphore(vk::SemaphoreCreateInfo());

    return swapchain_info;
}

static void update(
    vk::Device device,
    const swapchain_info& swapchain,
    vk::Queue queue)
{
    auto current_image = device.acquireNextImageKHR(swapchain.swapchain, UINT64_MAX, swapchain.acquire_semaphore, nullptr).value;

    auto wait_dst_stage_mask = vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput);

    queue.submit({
                     vk::SubmitInfo()
                     .setCommandBufferCount(1)
                     .setPCommandBuffers(&swapchain.command_buffers[current_image])
                     .setPWaitDstStageMask(&wait_dst_stage_mask)
                     .setWaitSemaphoreCount(1)
                     .setPWaitSemaphores(&swapchain.acquire_semaphore)
                     .setSignalSemaphoreCount(1)
                     .setPSignalSemaphores(&swapchain.render_semaphore)
                 }, nullptr);

    queue.presentKHR(
        vk::PresentInfoKHR()
        .setSwapchainCount(1)
        .setPSwapchains(&swapchain.swapchain)
        .setWaitSemaphoreCount(1)
        .setPImageIndices(&current_image)
        .setWaitSemaphoreCount(1)
        .setPWaitSemaphores(&swapchain.render_semaphore)
    );
}

int main(int argc, char** argv)
{
#if _DEBUG
    auto file_ok = fopen_s(&file, "debug_report.log", "w");
    assert(file_ok == 0);
#endif

    auto instance = create_instance();
    auto callback = create_debug_report_callback(instance);
    auto physical_device = get_physical_device(instance);
    auto device = create_device(physical_device);
    auto queue = device.getQueue(0, 0);
    auto render_pass = create_render_pass(device);
    auto buffer = create_buffer(physical_device, device);
    auto pipeline = create_pipeline(device, render_pass, "vert.spv", "frag.spv");

    auto success = glfwInit();
    assert(success);

    glfwSetErrorCallback(error_callback);

    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
    auto window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan renderer", nullptr, nullptr);
    assert(window);

    VkSurfaceKHR surface;
    auto result = glfwCreateWindowSurface(instance, window, nullptr, &surface);
    assert(result == VK_SUCCESS);

    auto swapchain = create_swapchain(physical_device, device, render_pass, pipeline.pipeline, surface);

    while (!glfwWindowShouldClose(window))
    {
        update(device, swapchain, queue);
        glfwPollEvents();
    }

    queue.waitIdle();

    swapchain.destroy();

    instance.destroySurfaceKHR(surface);

    glfwTerminate();

    pipeline.destroy(device);
    buffer.destroy(device);
    device.destroyRenderPass(render_pass);
    device.destroy();
    pfnDestroyDebugReportCallbackEXT(instance, callback, nullptr);
    instance.destroy();

    return EXIT_SUCCESS;
}
<commit_msg>Draw something<commit_after>#include "stdafx.h"
#include "shaders.h"

const uint32_t WIDTH = 1024u;
const uint32_t HEIGHT = 768u;

static PFN_vkCreateDebugReportCallbackEXT pfnCreateDebugReportCallbackEXT = nullptr;
static PFN_vkDestroyDebugReportCallbackEXT pfnDestroyDebugReportCallbackEXT = nullptr;

static FILE* file = nullptr;

static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report_callback(
    VkDebugReportFlagsEXT flags,
    VkDebugReportObjectTypeEXT objectType,
    uint64_t object,
    size_t location,
    int32_t messageCode,
    const char* pLayerPrefix,
    const char* pMessage,
    void* pUserData)
{
    std::fprintf(file, "%s: %s\n", pLayerPrefix, pMessage);
    return false;
}

static VkDebugReportCallbackEXT create_debug_report_callback(VkInstance vulkan)
{
    pfnCreateDebugReportCallbackEXT = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
        vkGetInstanceProcAddr(vulkan, "vkCreateDebugReportCallbackEXT")
    );
    pfnDestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
        vkGetInstanceProcAddr(vulkan, "vkDestroyDebugReportCallbackEXT")
    );

#if _DEBUG
    VkDebugReportCallbackCreateInfoEXT info = {};
    info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
    info.flags =
        VK_DEBUG_REPORT_ERROR_BIT_EXT |
        VK_DEBUG_REPORT_WARNING_BIT_EXT |
        VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
    info.pfnCallback = &debug_report_callback;

    VkDebugReportCallbackEXT callback;
    auto error = pfnCreateDebugReportCallbackEXT(vulkan, &info, nullptr, &callback);
    assert(!error);
    return callback;
#else
    return nullptr;
#endif
}

static void error_callback(int error, const char* description)
{
    throw std::runtime_error(description);
}

vk::Instance create_instance()
{
#if _DEBUG
    const auto layerCount = 1;
    const char* layerNames[layerCount] = {"VK_LAYER_LUNARG_standard_validation"};
#else
    const auto layerCount = 0;
    const char **layerNames = nullptr;
#endif

    const auto extensionCount = 3;
    const char* extensionNames[extensionCount] = {
        VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
        VK_KHR_SURFACE_EXTENSION_NAME,
        VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
    };

    return vk::createInstance(
        vk::InstanceCreateInfo()
        .setEnabledLayerCount(layerCount)
        .setPpEnabledLayerNames(layerNames)
        .setEnabledExtensionCount(extensionCount)
        .setPpEnabledExtensionNames(extensionNames)
    );
}

static vk::PhysicalDevice get_physical_device(vk::Instance vulkan)
{
    auto devices = vulkan.enumeratePhysicalDevices();
    assert(devices.size() == 1);

    auto props = devices[0].getProperties();
    std::printf("Using physical device: %s\n", props.deviceName);
    return devices[0];
}

static vk::Device create_device(vk::PhysicalDevice physical_device)
{
    float priorities[] = {0.f};
    auto queueInfo = vk::DeviceQueueCreateInfo()
        .setQueueCount(1)
        .setPQueuePriorities(priorities);

#if _DEBUG
    const auto layerCount = 1;
    const char* layerNames[layerCount] = {"VK_LAYER_LUNARG_standard_validation"};
#else
    const auto layerCount = 0;
    const char **layerNames = nullptr;
#endif

    const auto extensionCount = 1;
    const char* extensionNames[extensionCount] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};

    auto features = vk::PhysicalDeviceFeatures()
        .setShaderClipDistance(true)
        .setShaderCullDistance(true);

    return physical_device.createDevice(
        vk::DeviceCreateInfo()
        .setQueueCreateInfoCount(1)
        .setPQueueCreateInfos(&queueInfo)
        .setEnabledLayerCount(layerCount)
        .setPpEnabledLayerNames(layerNames)
        .setEnabledExtensionCount(1)
        .setPpEnabledExtensionNames(extensionNames)
        .setPEnabledFeatures(&features)
    );
}

static vk::RenderPass create_render_pass(vk::Device device)
{
    auto attachment = vk::AttachmentDescription()
        .setFormat(vk::Format::eB8G8R8A8Unorm)
        .setSamples(vk::SampleCountFlagBits::e1)
        .setLoadOp(vk::AttachmentLoadOp::eClear)
        .setStoreOp(vk::AttachmentStoreOp::eStore)
        .setStencilLoadOp(vk::AttachmentLoadOp::eDontCare)
        .setStencilStoreOp(vk::AttachmentStoreOp::eDontCare)
        .setInitialLayout(vk::ImageLayout::eColorAttachmentOptimal)
        .setFinalLayout(vk::ImageLayout::ePresentSrcKHR);

    auto color_attachment = vk::AttachmentReference()
        .setLayout(vk::ImageLayout::eColorAttachmentOptimal);

    auto subpass = vk::SubpassDescription()
        .setColorAttachmentCount(1)
        .setPColorAttachments(&color_attachment);

    return device.createRenderPass(
        vk::RenderPassCreateInfo()
        .setAttachmentCount(1)
        .setPAttachments(&attachment)
        .setSubpassCount(1)
        .setPSubpasses(&subpass)
    );
}

struct buffer_info
{
    vk::DeviceMemory memory;
    vk::Buffer buffer;

    void destroy(vk::Device device)
    {
        device.destroyBuffer(buffer);
        device.freeMemory(memory);
    }
};

static buffer_info create_buffer(vk::PhysicalDevice physical_device, vk::Device device)
{
    auto desired_flags = vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent;
    auto props = physical_device.getMemoryProperties();

    auto memory_type_index = UINT32_MAX;
    for (auto i = uint32_t(0); i < props.memoryTypeCount; i++)
    {
        if ((props.memoryTypes[i].propertyFlags & desired_flags) == desired_flags)
        {
            memory_type_index = i;
            break;
        }
    }
    assert(memory_type_index != UINT32_MAX);

    auto queue_familiy_index = uint32_t(0);
    auto size = 6 * sizeof(vertex);

    auto memory = device.allocateMemory(
        vk::MemoryAllocateInfo()
        .setAllocationSize(size)
        .setMemoryTypeIndex(memory_type_index)
    );

    auto ptr = reinterpret_cast<vertex*>(device.mapMemory(memory, 0, VK_WHOLE_SIZE));
    ptr[0] = {-1.f, 1.f, 255, 0, 0};
    ptr[1] = {1.f, 1.f, 0, 255, 0};
    ptr[2] = {1.f, -1.f, 0, 0, 255};
    ptr[3] = {1.f, -1.f, 0, 0, 255};
    ptr[4] = {-1.f, -1.f, 255, 255, 0};
    ptr[5] = {-1.f, 1.f, 255, 0, 0};
    device.unmapMemory(memory);

    auto buffer = device.createBuffer(
        vk::BufferCreateInfo()
        .setSize(size)
        .setUsage(vk::BufferUsageFlagBits::eVertexBuffer)
        .setQueueFamilyIndexCount(0)
        .setPQueueFamilyIndices(&queue_familiy_index)
        .setSharingMode(vk::SharingMode::eExclusive)
    );

    auto reqs = device.getBufferMemoryRequirements(buffer);
    assert((reqs.memoryTypeBits & 1u << memory_type_index) == 1u << memory_type_index);

    device.bindBufferMemory(buffer, memory, 0);

    buffer_info info;
    info.memory = memory;
    info.buffer = buffer;
    return info;
}

static vk::CommandBuffer create_command_buffer(vk::Device device, vk::CommandPool command_pool, vk::Image image, vk::RenderPass render_pass, vk::Pipeline pipeline, vk::Framebuffer framebuffer, vk::Buffer buffer)
{
    auto command_buffer = device.allocateCommandBuffers(
        vk::CommandBufferAllocateInfo()
        .setCommandPool(command_pool)
        .setLevel(vk::CommandBufferLevel::ePrimary)
        .setCommandBufferCount(1)
    )[0];

    command_buffer.begin(vk::CommandBufferBeginInfo()
        .setFlags(vk::CommandBufferUsageFlagBits::eSimultaneousUse));

    auto barrier = vk::ImageMemoryBarrier()
        .setImage(image)
        .setOldLayout(vk::ImageLayout::eUndefined)
        .setNewLayout(vk::ImageLayout::eColorAttachmentOptimal)
        .setSubresourceRange(
            vk::ImageSubresourceRange()
            .setAspectMask(vk::ImageAspectFlagBits::eColor)
            .setLevelCount(VK_REMAINING_MIP_LEVELS)
            .setLayerCount(VK_REMAINING_ARRAY_LAYERS)
        )
        .setDstAccessMask(vk::AccessFlagBits::eColorAttachmentWrite);
    command_buffer.pipelineBarrier(
        vk::PipelineStageFlagBits::eColorAttachmentOutput,
        vk::PipelineStageFlagBits::eColorAttachmentOutput,
        vk::DependencyFlags(),
        {},
        {},
        {barrier}
    );

    auto clear_value = vk::ClearValue()
        .setColor(vk::ClearColorValue().setFloat32({0.f, 1.f, 1.f, 1.f}));

    vk::Rect2D render_area;
    render_area.extent.width = WIDTH;
    render_area.extent.height = HEIGHT;

    command_buffer.beginRenderPass(
        vk::RenderPassBeginInfo()
        .setRenderPass(render_pass)
        .setClearValueCount(1)
        .setPClearValues(&clear_value)
        .setRenderArea(render_area)
        .setFramebuffer(framebuffer),
        vk::SubpassContents::eInline
    );

    command_buffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);

    command_buffer.bindVertexBuffers(0, {buffer}, {0});

    command_buffer.draw(6, 1, 0, 0);

    command_buffer.endRenderPass();

    command_buffer.end();

    return command_buffer;
}

struct swapchain_info
{
    vk::Device device;
    vk::SwapchainKHR swapchain;
    std::vector<vk::Image> images;
    std::vector<vk::ImageView> image_views;
    std::vector<vk::Framebuffer> framebuffers;
    vk::CommandPool command_pool;
    std::vector<vk::CommandBuffer> command_buffers;
    vk::Semaphore acquire_semaphore;
    vk::Semaphore render_semaphore;

    void destroy()
    {
        device.destroySemaphore(render_semaphore);
        device.destroySemaphore(acquire_semaphore);
        device.destroyCommandPool(command_pool);

        for (auto framebuffer : framebuffers)
        {
            device.destroyFramebuffer(framebuffer);
        }

        for (auto image_view : image_views)
        {
            device.destroyImageView(image_view);
        }

        device.destroySwapchainKHR(swapchain);
    }
};

static swapchain_info create_swapchain(vk::PhysicalDevice physical_device, vk::Device device, vk::RenderPass render_pass, vk::Pipeline pipeline, vk::SurfaceKHR surface, vk::Buffer buffer)
{
    auto supported = physical_device.getSurfaceSupportKHR(0, surface);
    assert(supported);

    auto caps = physical_device.getSurfaceCapabilitiesKHR(surface);

    auto swapchain = device.createSwapchainKHR(
        vk::SwapchainCreateInfoKHR()
        .setSurface(surface)
        .setMinImageCount(2)
        .setImageFormat(vk::Format::eB8G8R8A8Unorm)
        .setImageExtent(caps.currentExtent)
        .setImageArrayLayers(1)
        .setImageUsage(vk::ImageUsageFlagBits::eColorAttachment)
        .setPreTransform(caps.currentTransform)
        .setCompositeAlpha(vk::CompositeAlphaFlagBitsKHR::eOpaque)
        .setClipped(true)
        .setPresentMode(vk::PresentModeKHR::eFifo)
    );

    auto images = device.getSwapchainImagesKHR(swapchain);

    swapchain_info swapchain_info = {};
    swapchain_info.device = device;
    swapchain_info.swapchain = swapchain;
    swapchain_info.images = images;
    swapchain_info.command_pool = device.createCommandPool(vk::CommandPoolCreateInfo());

    for (auto image : images)
    {
        auto view = device.createImageView(
            vk::ImageViewCreateInfo()
            .setFormat(vk::Format::eB8G8R8A8Unorm)
            .setViewType(vk::ImageViewType::e2D)
            .setImage(image)
            .setSubresourceRange(
                vk::ImageSubresourceRange()
                .setAspectMask(vk::ImageAspectFlagBits::eColor)
                .setLevelCount(VK_REMAINING_MIP_LEVELS)
                .setLayerCount(1)
            )
        );
        swapchain_info.image_views.push_back(view);

        auto framebuffer = device.createFramebuffer(
            vk::FramebufferCreateInfo()
            .setRenderPass(render_pass)
            .setAttachmentCount(1)
            .setPAttachments(&view)
            .setWidth(WIDTH)
            .setHeight(HEIGHT)
            .setLayers(1)
        );
        swapchain_info.framebuffers.push_back(framebuffer);

        swapchain_info.command_buffers.push_back(create_command_buffer(
            device,
            swapchain_info.command_pool,
            image,
            render_pass,
            pipeline,
            framebuffer,
            buffer
        ));
    }

    swapchain_info.acquire_semaphore = device.createSemaphore(vk::SemaphoreCreateInfo());
    swapchain_info.render_semaphore = device.createSemaphore(vk::SemaphoreCreateInfo());

    return swapchain_info;
}

static void update(
    vk::Device device,
    const swapchain_info& swapchain,
    vk::Queue queue)
{
    auto current_image = device.acquireNextImageKHR(swapchain.swapchain, UINT64_MAX, swapchain.acquire_semaphore, nullptr).value;

    auto wait_dst_stage_mask = vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput);

    queue.submit({
                     vk::SubmitInfo()
                     .setCommandBufferCount(1)
                     .setPCommandBuffers(&swapchain.command_buffers[current_image])
                     .setPWaitDstStageMask(&wait_dst_stage_mask)
                     .setWaitSemaphoreCount(1)
                     .setPWaitSemaphores(&swapchain.acquire_semaphore)
                     .setSignalSemaphoreCount(1)
                     .setPSignalSemaphores(&swapchain.render_semaphore)
                 }, nullptr);

    queue.presentKHR(
        vk::PresentInfoKHR()
        .setSwapchainCount(1)
        .setPSwapchains(&swapchain.swapchain)
        .setWaitSemaphoreCount(1)
        .setPImageIndices(&current_image)
        .setWaitSemaphoreCount(1)
        .setPWaitSemaphores(&swapchain.render_semaphore)
    );
}

int main(int argc, char** argv)
{
#if _DEBUG
    auto file_ok = fopen_s(&file, "debug_report.log", "w");
    assert(file_ok == 0);
#endif

    auto instance = create_instance();
    auto callback = create_debug_report_callback(instance);
    auto physical_device = get_physical_device(instance);
    auto device = create_device(physical_device);
    auto queue = device.getQueue(0, 0);
    auto render_pass = create_render_pass(device);
    auto buffer = create_buffer(physical_device, device);
    auto pipeline = create_pipeline(device, render_pass, "vert.spv", "frag.spv");

    auto success = glfwInit();
    assert(success);

    glfwSetErrorCallback(error_callback);

    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
    auto window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan renderer", nullptr, nullptr);
    assert(window);

    VkSurfaceKHR surface;
    auto result = glfwCreateWindowSurface(instance, window, nullptr, &surface);
    assert(result == VK_SUCCESS);

    auto swapchain = create_swapchain(physical_device, device, render_pass, pipeline.pipeline, surface, buffer.buffer);

    while (!glfwWindowShouldClose(window))
    {
        update(device, swapchain, queue);
        glfwPollEvents();
    }

    queue.waitIdle();

    swapchain.destroy();

    instance.destroySurfaceKHR(surface);

    glfwTerminate();

    pipeline.destroy(device);
    buffer.destroy(device);
    device.destroyRenderPass(render_pass);
    device.destroy();
    pfnDestroyDebugReportCallbackEXT(instance, callback, nullptr);
    instance.destroy();

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#ifndef BPMODULE_GUARD_EXCEPTION__ASSERT_HPP_
#define BPMODULE_GUARD_EXCEPTION__ASSERT_HPP_

#include "bpmodule/pragma.h"

namespace bpmodule {
namespace exception {

PRAGMA_WARNING_PUSH
PRAGMA_WARNING_IGNORE_UNUSED_PARAMETERS

/*! \brief Asserts that a condition is true, throwing an exception if it is not
 *
 * If \p condition is false, an exception of type EX is thrown.
 * The \p description and \p args are forwarded to the constructor
 * of the exception.
 */
template<typename EX, typename ... Targs>
void Assert(bool condition, const std::string & description, Targs &&... args)
{
    #ifndef NDEBUG
    if(!condition)
        throw EX(description, std::forward<Targs>(args)...);
    #endif
}

PRAGMA_WARNING_POP

} // close namespace exception
} // close namespace bpmodule

#endif

<commit_msg>Add missing header to assert<commit_after>#ifndef BPMODULE_GUARD_EXCEPTION__ASSERT_HPP_
#define BPMODULE_GUARD_EXCEPTION__ASSERT_HPP_

#include <string>

#include "bpmodule/pragma.h"

namespace bpmodule {
namespace exception {

PRAGMA_WARNING_PUSH
PRAGMA_WARNING_IGNORE_UNUSED_PARAMETERS

/*! \brief Asserts that a condition is true, throwing an exception if it is not
 *
 * If \p condition is false, an exception of type EX is thrown.
 * The \p description and \p args are forwarded to the constructor
 * of the exception.
 */
template<typename EX, typename ... Targs>
void Assert(bool condition, const std::string & description, Targs &&... args)
{
    #ifndef NDEBUG
    if(!condition)
        throw EX(description, std::forward<Targs>(args)...);
    #endif
}

PRAGMA_WARNING_POP

} // close namespace exception
} // close namespace bpmodule

#endif

<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.1  2002/02/01 22:22:51  peiyongz
 * Initial revision
 *
 * Revision 1.1  2001/11/02 14:08:40  knoaman
 * Add support for identity constraints.
 *
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/validators/schema/identity/ValueStoreCache.hpp>
#include <xercesc/validators/schema/identity/ValueStore.hpp>
#include <xercesc/validators/schema/SchemaElementDecl.hpp>
#include <xercesc/util/HashPtr.hpp>

// ---------------------------------------------------------------------------
//  ValueStoreCache: Constructors and Destructor
// ---------------------------------------------------------------------------
ValueStoreCache::ValueStoreCache()
    : fValueStores(0)
    , fGlobalICMap(0)
    , fIC2ValueStoreMap(0)
    , fGlobalMapStack(0)
{
    try {
        init();
    }
    catch(...) {
        cleanUp();
        throw;
    }
}

ValueStoreCache::~ValueStoreCache()
{
    cleanUp();
}

// ---------------------------------------------------------------------------
//  ValueStoreCache: Document handling methods
// ---------------------------------------------------------------------------
void ValueStoreCache::startDocument() {

    fIC2ValueStoreMap->removeAll();
    fGlobalICMap->removeAll();
    fValueStores->removeAllElements();
    fGlobalMapStack->removeAllElements();
}

void ValueStoreCache::startElement() {

    fGlobalMapStack->push(fGlobalICMap);
    fGlobalICMap = new RefHashTableOf<ValueStore>(13, false, new HashPtr());
}

void ValueStoreCache::endElement() {

    if (fGlobalMapStack->empty()) {
        return; // must be an invalid doc!
    }

    RefHashTableOf<ValueStore>* oldMap = fGlobalMapStack->pop();
    RefHashTableOfEnumerator<ValueStore> mapEnum(oldMap);
//    Janitor<RefHashTableOf<ValueStore> > janMap(oldMap);

    while (mapEnum.hasMoreElements()) {

        ValueStore& oldVal = mapEnum.nextElement();
        IdentityConstraint* ic = oldVal.getIdentityConstraint();
        ValueStore* currVal = fGlobalICMap->get(ic);

        if (!currVal) {
            fGlobalICMap->put(ic, &oldVal);
        }
        else {
            currVal->append(&oldVal);
        }
    }
    delete oldMap;
}

// ---------------------------------------------------------------------------
//  ValueStoreCache: Helper methods
// ---------------------------------------------------------------------------
void ValueStoreCache::cleanUp() {

    delete fIC2ValueStoreMap;
    delete fGlobalICMap;
    delete fGlobalMapStack;
    delete fValueStores;
}

void ValueStoreCache::init() {

    fValueStores = new RefVectorOf<ValueStore>(8);
    fGlobalICMap = new RefHashTableOf<ValueStore>(13, false, new HashPtr());
    fIC2ValueStoreMap = new RefHashTableOf<ValueStore>(13, false, new HashPtr());
    fGlobalMapStack = new RefStackOf<RefHashTableOf<ValueStore> >(8);
}

void ValueStoreCache::initValueStoresFor(SchemaElementDecl* const elemDecl) {

    // initialize value stores for unique fields
    unsigned int icCount = elemDecl->getIdentityConstraintCount();

    for (unsigned int i=0; i<icCount; i++) {

        IdentityConstraint* ic = elemDecl->getIdentityConstraintAt(i);
        ValueStore* valueStore = fIC2ValueStoreMap->get(ic);

        if (valueStore && ic->getType() != IdentityConstraint::KEYREF) {
            continue;
        }

        valueStore = new ValueStore(ic, fScanner);
        fValueStores->addElement(valueStore);
        fIC2ValueStoreMap->put(ic, valueStore);
    }
}

void ValueStoreCache::transplant(IdentityConstraint* const ic) {

    if (ic->getType() == IdentityConstraint::KEYREF) {
        return;
    }

    ValueStore* newVals = fIC2ValueStoreMap->get(ic);
    ValueStore* currVals = fGlobalICMap->get(ic);

    fIC2ValueStoreMap->removeKey(ic);

    if (currVals) {
        currVals->append(newVals);
    } else {
        fGlobalICMap->put(ic, newVals);
    }
}

/**
  * End of file ValueStoreCache.cpp
  */

<commit_msg>Fix for ValueStore's null pointer.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xerces" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache\@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation, and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com .  For more information
 * on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

/*
 * $Log$
 * Revision 1.2  2002/08/26 23:48:09  knoaman
 * Fix for ValueStore's null pointer.
 *
 * Revision 1.1.1.1  2002/02/01 22:22:51  peiyongz
 * sane_include
 *
 * Revision 1.1  2001/11/02 14:08:40  knoaman
 * Add support for identity constraints.
 *
 */

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------
#include <xercesc/validators/schema/identity/ValueStoreCache.hpp>
#include <xercesc/validators/schema/identity/ValueStore.hpp>
#include <xercesc/validators/schema/SchemaElementDecl.hpp>
#include <xercesc/util/HashPtr.hpp>

// ---------------------------------------------------------------------------
//  ValueStoreCache: Constructors and Destructor
// ---------------------------------------------------------------------------
ValueStoreCache::ValueStoreCache()
    : fValueStores(0)
    , fGlobalICMap(0)
    , fIC2ValueStoreMap(0)
    , fGlobalMapStack(0)
{
    try {
        init();
    }
    catch(...) {
        cleanUp();
        throw;
    }
}

ValueStoreCache::~ValueStoreCache()
{
    cleanUp();
}

// ---------------------------------------------------------------------------
//  ValueStoreCache: Document handling methods
// ---------------------------------------------------------------------------
void ValueStoreCache::startDocument() {

    fIC2ValueStoreMap->removeAll();
    fGlobalICMap->removeAll();
    fValueStores->removeAllElements();
    fGlobalMapStack->removeAllElements();
}

void ValueStoreCache::startElement() {

    fGlobalMapStack->push(fGlobalICMap);
    fGlobalICMap = new RefHashTableOf<ValueStore>(13, false, new HashPtr());
}

void ValueStoreCache::endElement() {

    if (fGlobalMapStack->empty()) {
        return; // must be an invalid doc!
    }

    RefHashTableOf<ValueStore>* oldMap = fGlobalMapStack->pop();
    RefHashTableOfEnumerator<ValueStore> mapEnum(oldMap);
//    Janitor<RefHashTableOf<ValueStore> > janMap(oldMap);

    while (mapEnum.hasMoreElements()) {

        ValueStore& oldVal = mapEnum.nextElement();
        IdentityConstraint* ic = oldVal.getIdentityConstraint();
        ValueStore* currVal = fGlobalICMap->get(ic);

        if (!currVal) {
            fGlobalICMap->put(ic, &oldVal);
        }
        else {
            currVal->append(&oldVal);
        }
    }
    delete oldMap;
}

// ---------------------------------------------------------------------------
//  ValueStoreCache: Helper methods
// ---------------------------------------------------------------------------
void ValueStoreCache::cleanUp() {

    delete fIC2ValueStoreMap;
    delete fGlobalICMap;
    delete fGlobalMapStack;
    delete fValueStores;
}

void ValueStoreCache::init() {

    fValueStores = new RefVectorOf<ValueStore>(8);
    fGlobalICMap = new RefHashTableOf<ValueStore>(13, false, new HashPtr());
    fIC2ValueStoreMap = new RefHashTableOf<ValueStore>(13, false, new HashPtr());
    fGlobalMapStack = new RefStackOf<RefHashTableOf<ValueStore> >(8);
}

void ValueStoreCache::initValueStoresFor(SchemaElementDecl* const elemDecl) {

    // initialize value stores for unique fields
    unsigned int icCount = elemDecl->getIdentityConstraintCount();

    for (unsigned int i=0; i<icCount; i++) {

        IdentityConstraint* ic = elemDecl->getIdentityConstraintAt(i);
        ValueStore* valueStore = fIC2ValueStoreMap->get(ic);

        if (valueStore && ic->getType() != IdentityConstraint::KEYREF) {
            continue;
        }

        valueStore = new ValueStore(ic, fScanner);
        fValueStores->addElement(valueStore);
        fIC2ValueStoreMap->put(ic, valueStore);
    }
}

void ValueStoreCache::transplant(IdentityConstraint* const ic) {

    if (ic->getType() == IdentityConstraint::KEYREF) {
        return;
    }

    ValueStore* newVals = fIC2ValueStoreMap->get(ic);
    ValueStore* currVals = fGlobalICMap->get(ic);

    fIC2ValueStoreMap->removeKey(ic);

    if (currVals) {
        currVals->append(newVals);
    } else {
        fGlobalICMap->put(ic, newVals);
    }

    ValueStore* valueStore = new ValueStore(ic, fScanner);
    fValueStores->addElement(valueStore);
    fIC2ValueStoreMap->put(ic, valueStore);
}

/**
  * End of file ValueStoreCache.cpp
  */

<|endoftext|>


<commit_before>#include "term_buffer.h"
#include "term_window.h"
#include "term_cell.h"

#include "cap_manager.h"
#include "string_utils.h"

#include <iostream>
#include <iterator> // for ostream_iterator

DEFINE_CAP(enable_mode);
DEFINE_CAP(disable_mode);
DEFINE_CAP(enter_bold_mode);
DEFINE_CAP(enter_reverse_mode);
DEFINE_CAP(keypad_xmit);
DEFINE_CAP(exit_standout_mode);
DEFINE_CAP(enter_ca_mode);
DEFINE_CAP(exit_ca_mode);
DEFINE_CAP(exit_alt_charset_mode);
DEFINE_CAP(enter_alt_charset_mode);
DEFINE_CAP(enter_alt_charset_mode_british);
DEFINE_CAP(exit_alt_charset_mode_g1_british);
DEFINE_CAP(enter_alt_charset_mode_g1);
DEFINE_CAP(enter_alt_charset_mode_g1_british);
DEFINE_CAP(shift_in_to_charset_mode_g0);
DEFINE_CAP(shift_in_to_charset_mode_g1);

static
const
wchar_t
line_drawing_map[] = {
    0x25c6,  // ` => diamond
    0x2592,  // a => checkerboard
    0x2409,  // b => HT symbol
    0x240c,  // c => FF symbol
    0x240d,  // d => CR symbol
    0x240a,  // e => LF symbol
    0x00b0,  // f => degree
    0x00b1,  // g => plus/minus
    0x2424,  // h => NL symbol
    0x240b,  // i => VT symbol
    0x2518,  // j => downright corner
    0x2510,  // k => upright corner
    0x250c,  // l => upleft corner
    0x2514,  // m => downleft corner
    0x253c,  // n => cross
    0x23ba,  // o => scan line 1/9
    0x23bb,  // p => scan line 3/9
    0x2500,  // q => horizontal line (also scan line 5/9)
    0x23bc,  // r => scan line 7/9
    0x23bd,  // s => scan line 9/9
    0x251c,  // t => left t
    0x2524,  // u => right t
    0x2534,  // v => bottom t
    0x252c,  // w => top t
    0x2502,  // x => vertical line
    0x2264,  // y => <=
    0x2265,  // z => >=
    0x03c0,  // { => pi
    0x2260,  // | => not equal
    0x00a3,  // } => pound currency sign
    0x00b7,  // ~ => bullet
};

static
wchar_t translate_char(wchar_t c) {
    if (c >= 96 && c < 126)
        return line_drawing_map[c - 96];
    return c;
}

static
wchar_t translate_char_british(wchar_t c) {
    if (c == '#')
        return 0x00a3;

    return c;
}

void enable_mode(term_data_context_s & term_context,
                 const term_data_param_list & params) {
    auto mode = params[0];

    const term_data_param_list empty_params {};

    if (mode == 25) {
        handle_cap(term_context, "cursor_normal", params);
    }
    else if (mode == 40){
        term_context.dec_mode = true;
        term_context.force_column = true;
        resize_terminal(term_context);
    }
    else if (mode == 3) {
        if (term_context.dec_mode){
            term_context.force_column = true;
            term_context.force_column_count = 132;
            resize_terminal(term_context);

            handle_cap(term_context, "clr_eos", empty_params);
            handle_cap(term_context, "cursor_home", empty_params);
        }
    }
    else if (mode == 5) {
        term_context.cell_template->AddMode(TermCell::Reverse);
    }
    else if (mode == 6) {
        term_context.origin_mode = true;
        handle_cap(term_context, "cursor_home", empty_params);
    }
    else if (mode == 7) {
        term_context.auto_wrap = true;
    }
    else {
        std::cerr << "enable mode not implemented, with params:["
                  << join(params, ",");
        std::cerr << "]" << std::endl;
    }
}

void disable_mode(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    auto mode = params[0];

    const term_data_param_list empty_params {};

    if (mode == 25) {
        handle_cap(term_context, "cursor_invisible", params);
    }
    else if (mode == 40){
        term_context.dec_mode = false;
        term_context.force_column = false;
        resize_terminal(term_context);
    }
    else if (mode == 3) {
        if (term_context.dec_mode){
            term_context.force_column = true;
            term_context.force_column_count = 80;
            resize_terminal(term_context);

            handle_cap(term_context, "clr_eos", empty_params);
            handle_cap(term_context, "cursor_home", empty_params);
        }
    }
    else if (mode == 5) {
        term_context.cell_template->RemoveMode(TermCell::Reverse);
    }
    else if (mode == 6) {
        term_context.origin_mode = false;
        handle_cap(term_context, "cursor_home", empty_params);
    }
    else if (mode == 7) {
        term_context.auto_wrap = false;
    }
    else if (mode == 12) {
        if (term_context.cap_debug) {
            std::cerr << "disable cursor blinking" << std::endl;
        }
    }
    else {
        std::cerr << "disable mode not implemented, with params:["
                  << join(params, ",");
        std::cerr << "]" << std::endl;
    }
}

void enter_bold_mode(term_data_context_s & term_context,
                     const term_data_param_list & params) {
    (void)params;
    term_context.cell_template->AddMode(TermCell::Bold);
}
void keypad_xmit(term_data_context_s & term_context,
                 const term_data_param_list & params) {
    (void)params;
    term_context.keypad_transmit_mode = true;
}
void enter_reverse_mode(term_data_context_s & term_context,
                        const term_data_param_list & params) {
    (void)params;
    term_context.cell_template->AddMode(TermCell::Reverse);
}

void exit_standout_mode(term_data_context_s & term_context,
                        const term_data_param_list & params) {
    (void)params;
    term_context.cell_template->SetMode(term_context.default_cell_template->GetMode());
}

void enter_ca_mode(term_data_context_s & term_context,
                   const term_data_param_list & params) {
    (void)params;
    term_context.saved_cell_template = term_context.cell_template;
    term_context.cell_template = term_context.term_buffer->CreateCellWithDefaults();
    term_context.term_buffer->EnableAlterBuffer(true);
}
void exit_ca_mode(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.cell_template = term_context.saved_cell_template;
    term_context.term_buffer->EnableAlterBuffer(false);
}

void exit_alt_charset_mode(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    term_context.charset_modes_translate[0] = nullptr;
    exit_standout_mode(term_context, params);
}
void enter_alt_charset_mode(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.charset_modes_translate[0] = translate_char;
}
void enter_alt_charset_mode_british(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.charset_modes_translate[0] = translate_char_british;
}
void enter_alt_charset_mode_g1(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.charset_modes_translate[1] = translate_char;
}
void enter_alt_charset_mode_g1_british(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.charset_modes_translate[1] = translate_char_british;
}
void exit_alt_charset_mode_g1_british(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    term_context.charset_modes_translate[1] = nullptr;
    exit_standout_mode(term_context, params);
}
void shift_in_to_charset_mode_g0(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.charset_mode = 0;
}
void shift_in_to_charset_mode_g1(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.charset_mode = 1;
}
<commit_msg>handle mode 1047, 1048 1049<commit_after>#include "term_buffer.h"
#include "term_window.h"
#include "term_cell.h"

#include "cap_manager.h"
#include "string_utils.h"

#include <iostream>
#include <iterator> // for ostream_iterator

DEFINE_CAP(enable_mode);
DEFINE_CAP(disable_mode);
DEFINE_CAP(enter_bold_mode);
DEFINE_CAP(enter_reverse_mode);
DEFINE_CAP(keypad_xmit);
DEFINE_CAP(exit_standout_mode);
DEFINE_CAP(enter_ca_mode);
DEFINE_CAP(exit_ca_mode);
DEFINE_CAP(exit_alt_charset_mode);
DEFINE_CAP(enter_alt_charset_mode);
DEFINE_CAP(enter_alt_charset_mode_british);
DEFINE_CAP(exit_alt_charset_mode_g1_british);
DEFINE_CAP(enter_alt_charset_mode_g1);
DEFINE_CAP(enter_alt_charset_mode_g1_british);
DEFINE_CAP(shift_in_to_charset_mode_g0);
DEFINE_CAP(shift_in_to_charset_mode_g1);

static
const
wchar_t
line_drawing_map[] = {
    0x25c6,  // ` => diamond
    0x2592,  // a => checkerboard
    0x2409,  // b => HT symbol
    0x240c,  // c => FF symbol
    0x240d,  // d => CR symbol
    0x240a,  // e => LF symbol
    0x00b0,  // f => degree
    0x00b1,  // g => plus/minus
    0x2424,  // h => NL symbol
    0x240b,  // i => VT symbol
    0x2518,  // j => downright corner
    0x2510,  // k => upright corner
    0x250c,  // l => upleft corner
    0x2514,  // m => downleft corner
    0x253c,  // n => cross
    0x23ba,  // o => scan line 1/9
    0x23bb,  // p => scan line 3/9
    0x2500,  // q => horizontal line (also scan line 5/9)
    0x23bc,  // r => scan line 7/9
    0x23bd,  // s => scan line 9/9
    0x251c,  // t => left t
    0x2524,  // u => right t
    0x2534,  // v => bottom t
    0x252c,  // w => top t
    0x2502,  // x => vertical line
    0x2264,  // y => <=
    0x2265,  // z => >=
    0x03c0,  // { => pi
    0x2260,  // | => not equal
    0x00a3,  // } => pound currency sign
    0x00b7,  // ~ => bullet
};

static
wchar_t translate_char(wchar_t c) {
    if (c >= 96 && c < 126)
        return line_drawing_map[c - 96];
    return c;
}

static
wchar_t translate_char_british(wchar_t c) {
    if (c == '#')
        return 0x00a3;

    return c;
}

void enable_mode(term_data_context_s & term_context,
                 const term_data_param_list & params) {
    auto mode = params[0];

    const term_data_param_list empty_params {};

    if (mode == 25) {
        handle_cap(term_context, "cursor_normal", params);
    }
    else if (mode == 40){
        term_context.dec_mode = true;
        term_context.force_column = true;
        resize_terminal(term_context);
    }
    else if (mode == 3) {
        if (term_context.dec_mode){
            term_context.force_column = true;
            term_context.force_column_count = 132;
            resize_terminal(term_context);

            handle_cap(term_context, "clr_eos", empty_params);
            handle_cap(term_context, "cursor_home", empty_params);
        }
    }
    else if (mode == 5) {
        term_context.cell_template->AddMode(TermCell::Reverse);
    }
    else if (mode == 6) {
        term_context.origin_mode = true;
        handle_cap(term_context, "cursor_home", empty_params);
    }
    else if (mode == 7) {
        term_context.auto_wrap = true;
    }
    else if (mode == 1047) {
        if (term_context.cap_debug) {
            std::cerr << "enable alter buffer" << std::endl;
        }
        handle_cap(term_context, "enter_ca_mode", empty_params);
    }
    else if (mode == 1048) {
        if (term_context.cap_debug) {
            std::cerr << "save cursor" << std::endl;
        }
        handle_cap(term_context, "save_cursor", empty_params);
    }
    else if (mode == 1049) {
        if (term_context.cap_debug) {
            std::cerr << "enter alter buffer and save cursor" << std::endl;
        }
        handle_cap(term_context, "save_cursor", empty_params);
        handle_cap(term_context, "enter_ca_mode", empty_params);
    }
    else {
        std::cerr << "enable mode not implemented, with params:["
                  << join(params, ",");
        std::cerr << "]" << std::endl;
    }
}

void disable_mode(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    auto mode = params[0];

    const term_data_param_list empty_params {};

    if (mode == 25) {
        handle_cap(term_context, "cursor_invisible", params);
    }
    else if (mode == 40){
        term_context.dec_mode = false;
        term_context.force_column = false;
        resize_terminal(term_context);
    }
    else if (mode == 3) {
        if (term_context.dec_mode){
            term_context.force_column = true;
            term_context.force_column_count = 80;
            resize_terminal(term_context);

            handle_cap(term_context, "clr_eos", empty_params);
            handle_cap(term_context, "cursor_home", empty_params);
        }
    }
    else if (mode == 5) {
        term_context.cell_template->RemoveMode(TermCell::Reverse);
    }
    else if (mode == 6) {
        term_context.origin_mode = false;
        handle_cap(term_context, "cursor_home", empty_params);
    }
    else if (mode == 7) {
        term_context.auto_wrap = false;
    }
    else if (mode == 12) {
        if (term_context.cap_debug) {
            std::cerr << "disable cursor blinking" << std::endl;
        }
    }
    else if (mode == 1047) {
        if (term_context.cap_debug) {
            std::cerr << "disable alter buffer" << std::endl;
        }
        handle_cap(term_context, "exit_ca_mode", empty_params);
    }
    else if (mode == 1048) {
        if (term_context.cap_debug) {
            std::cerr << "restore cursor" << std::endl;
        }
        handle_cap(term_context, "restore_cursor", empty_params);
    }
    else if (mode == 1049) {
        if (term_context.cap_debug) {
            std::cerr << "disable alter buffer and restore cursor" << std::endl;
        }
        handle_cap(term_context, "exit_ca_mode", empty_params);
        handle_cap(term_context, "restore_cursor", empty_params);
    }
    else {
        std::cerr << "disable mode not implemented, with params:["
                  << join(params, ",");
        std::cerr << "]" << std::endl;
    }
}

void enter_bold_mode(term_data_context_s & term_context,
                     const term_data_param_list & params) {
    (void)params;
    term_context.cell_template->AddMode(TermCell::Bold);
}
void keypad_xmit(term_data_context_s & term_context,
                 const term_data_param_list & params) {
    (void)params;
    term_context.keypad_transmit_mode = true;
}
void enter_reverse_mode(term_data_context_s & term_context,
                        const term_data_param_list & params) {
    (void)params;
    term_context.cell_template->AddMode(TermCell::Reverse);
}

void exit_standout_mode(term_data_context_s & term_context,
                        const term_data_param_list & params) {
    (void)params;
    term_context.cell_template->SetMode(term_context.default_cell_template->GetMode());
}

void enter_ca_mode(term_data_context_s & term_context,
                   const term_data_param_list & params) {
    (void)params;
    term_context.saved_cell_template = term_context.cell_template;
    term_context.cell_template = term_context.term_buffer->CreateCellWithDefaults();
    term_context.term_buffer->EnableAlterBuffer(true);
}
void exit_ca_mode(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.cell_template = term_context.saved_cell_template;
    term_context.term_buffer->EnableAlterBuffer(false);
}

void exit_alt_charset_mode(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    term_context.charset_modes_translate[0] = nullptr;
    exit_standout_mode(term_context, params);
}
void enter_alt_charset_mode(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.charset_modes_translate[0] = translate_char;
}
void enter_alt_charset_mode_british(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.charset_modes_translate[0] = translate_char_british;
}
void enter_alt_charset_mode_g1(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.charset_modes_translate[1] = translate_char;
}
void enter_alt_charset_mode_g1_british(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.charset_modes_translate[1] = translate_char_british;
}
void exit_alt_charset_mode_g1_british(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    term_context.charset_modes_translate[1] = nullptr;
    exit_standout_mode(term_context, params);
}
void shift_in_to_charset_mode_g0(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.charset_mode = 0;
}
void shift_in_to_charset_mode_g1(term_data_context_s & term_context,
                  const term_data_param_list & params) {
    (void)params;
    term_context.charset_mode = 1;
}
<|endoftext|>


<commit_before>///////////////////////////////////////////////////////////////////////////////
//
// File FilterCellHistoryPoints.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Outputs values at specific points during time-stepping.
//
///////////////////////////////////////////////////////////////////////////////

#include <LibUtilities/Memory/NekMemoryManager.hpp>
#include <iomanip>
#include <CardiacEPSolver/Filters/FilterCellHistoryPoints.h>

namespace Nektar
{
    namespace SolverUtils
    {
        std::string FilterCellHistoryPoints::className = GetFilterFactory().RegisterCreatorFunction("CellHistoryPoints", FilterCellHistoryPoints::create);

        /**
         *
         */
        FilterCellHistoryPoints::FilterCellHistoryPoints(
            const LibUtilities::SessionReaderSharedPtr &pSession,
            const std::map<std::string, std::string> &pParams) :
            FilterHistoryPoints(pSession, pParams)
        {
        }

        /**
         *
         */
        FilterCellHistoryPoints::~FilterCellHistoryPoints()
        {

        }

        /**
         *
         */
        void FilterCellHistoryPoints::v_Update(const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields, const NekDouble &time)
        {
            // Only output every m_outputFrequency.
            if ((m_index++) % m_outputFrequency)
            {
                return;
            }

            int j         = 0;
            int k         = 0;
            int numPoints = m_historyPoints.size();
            int numFields = m_cell->GetNumCellVariables();
            LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
            Array<OneD, NekDouble> data(numPoints*numFields, 0.0);
            Array<OneD, NekDouble> gloCoord(3, 0.0);
            std::list<std::pair<SpatialDomains::PointGeomSharedPtr, Array<OneD, NekDouble> > >::iterator x;

            Array<OneD, NekDouble> physvals;
            Array<OneD, NekDouble> locCoord;
            int expId;

            // Pull out data values field by field
            for (j = 0; j < numFields; ++j)
            {
                if(m_isHomogeneous1D)
                {
                    for (k = 0, x = m_historyList.begin(); x != m_historyList.end();
                         ++x, ++k)
                    {
                        locCoord = (*x).second;
                        expId    = (*x).first->GetVid();

                        physvals = pFields[j]->GetPlane(m_outputPlane)->UpdatePhys() + pFields[j]->GetPhys_Offset(expId);

                        // transform elemental data if required.
                        if(pFields[j]->GetPhysState() == false)
                        {
                            pFields[j]->GetPlane(m_outputPlane)->GetExp(expId)->BwdTrans(pFields[j]->GetPlane(m_outputPlane)->GetCoeffs() + pFields[j]->GetCoeff_Offset(expId),physvals);
                        }

                        // interpolate point can do with zero plane methods
                        data[m_historyLocalPointMap[k]*numFields+j] = pFields[j]->GetExp(expId)->StdPhysEvaluate(locCoord,physvals);

                    }
                }
                else
                {
                    for (k = 0, x = m_historyList.begin(); x != m_historyList.end(); ++x, ++k)
                    {
                        locCoord = (*x).second;
                        expId    = (*x).first->GetVid();

                        physvals = m_cell->GetCellSolution(j) + pFields[0]->GetPhys_Offset(expId);

                        // interpolate point
                        data[m_historyLocalPointMap[k]*numFields+j] = pFields[0]->GetExp(expId)->StdPhysEvaluate(locCoord,physvals);
                    }
                }
            }

            // Exchange history data
            // This could be improved to reduce communication but works for now
            vComm->AllReduce(data, LibUtilities::ReduceSum);

            // Only the root process writes out history data
            if (vComm->GetRank() == 0)
            {

                // Write data values point by point
                for (k = 0; k < m_historyPoints.size(); ++k)
                {
                    m_outputStream.width(8);
                    m_outputStream << setprecision(6) << time;
                    for (int j = 0; j < numFields; ++j)
                    {
                        m_outputStream.width(25);
                        m_outputStream << setprecision(16) << data[k*numFields+j];
                    }
                    m_outputStream << endl;
                }
            }
        }

    }
}
<commit_msg>Fixed bug in homogeneous code for Cell history filter.<commit_after>///////////////////////////////////////////////////////////////////////////////
//
// File FilterCellHistoryPoints.cpp
//
// For more information, please see: http://www.nektar.info
//
// The MIT License
//
// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
// Department of Aeronautics, Imperial College London (UK), and Scientific
// Computing and Imaging Institute, University of Utah (USA).
//
// License for the specific language governing rights and limitations under
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//
// Description: Outputs values at specific points during time-stepping.
//
///////////////////////////////////////////////////////////////////////////////

#include <LibUtilities/Memory/NekMemoryManager.hpp>
#include <iomanip>
#include <CardiacEPSolver/Filters/FilterCellHistoryPoints.h>

namespace Nektar
{
    namespace SolverUtils
    {
        std::string FilterCellHistoryPoints::className = GetFilterFactory().RegisterCreatorFunction("CellHistoryPoints", FilterCellHistoryPoints::create);

        /**
         *
         */
        FilterCellHistoryPoints::FilterCellHistoryPoints(
            const LibUtilities::SessionReaderSharedPtr &pSession,
            const std::map<std::string, std::string> &pParams) :
            FilterHistoryPoints(pSession, pParams)
        {
        }

        /**
         *
         */
        FilterCellHistoryPoints::~FilterCellHistoryPoints()
        {

        }

        /**
         *
         */
        void FilterCellHistoryPoints::v_Update(const Array<OneD, const MultiRegions::ExpListSharedPtr> &pFields, const NekDouble &time)
        {
            // Only output every m_outputFrequency.
            if ((m_index++) % m_outputFrequency)
            {
                return;
            }

            int j         = 0;
            int k         = 0;
            int numPoints = m_historyPoints.size();
            int numFields = m_cell->GetNumCellVariables();
            LibUtilities::CommSharedPtr vComm = pFields[0]->GetComm();
            Array<OneD, NekDouble> data(numPoints*numFields, 0.0);
            Array<OneD, NekDouble> gloCoord(3, 0.0);
            std::list<std::pair<SpatialDomains::PointGeomSharedPtr, Array<OneD, NekDouble> > >::iterator x;

            Array<OneD, NekDouble> physvals;
            Array<OneD, NekDouble> locCoord;
            int expId;
            int nppp = 0; // Number of points per plane

            // Pull out data values field by field
            for (j = 0; j < numFields; ++j)
            {
                if(m_isHomogeneous1D)
                {
                    for (k = 0, x = m_historyList.begin(); x != m_historyList.end();
                         ++x, ++k)
                    {
                        locCoord = (*x).second;
                        expId    = (*x).first->GetVid();
                        nppp     = pFields[0]->GetPlane(0)->GetTotPoints();

                        physvals = m_cell->GetCellSolution(j) + m_outputPlane*nppp + pFields[j]->GetPhys_Offset(expId);

                        // interpolate point can do with zero plane methods
                        data[m_historyLocalPointMap[k]*numFields+j] = pFields[0]->GetExp(expId)->StdPhysEvaluate(locCoord,physvals);

                    }
                }
                else
                {
                    for (k = 0, x = m_historyList.begin(); x != m_historyList.end(); ++x, ++k)
                    {
                        locCoord = (*x).second;
                        expId    = (*x).first->GetVid();

                        physvals = m_cell->GetCellSolution(j) + pFields[0]->GetPhys_Offset(expId);

                        // interpolate point
                        data[m_historyLocalPointMap[k]*numFields+j] = pFields[0]->GetExp(expId)->StdPhysEvaluate(locCoord,physvals);
                    }
                }
            }

            // Exchange history data
            // This could be improved to reduce communication but works for now
            vComm->AllReduce(data, LibUtilities::ReduceSum);

            // Only the root process writes out history data
            if (vComm->GetRank() == 0)
            {

                // Write data values point by point
                for (k = 0; k < m_historyPoints.size(); ++k)
                {
                    m_outputStream.width(8);
                    m_outputStream << setprecision(6) << time;
                    for (int j = 0; j < numFields; ++j)
                    {
                        m_outputStream.width(25);
                        m_outputStream << setprecision(16) << data[k*numFields+j];
                    }
                    m_outputStream << endl;
                }
            }
        }

    }
}
<|endoftext|>


<commit_before>//===-- WebAssemblyAddMissingPrototypes.cpp - Fix prototypeless functions -===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Add prototypes to prototypes-less functions.
///
/// WebAssembly has strict function prototype checking so we need functions
/// declarations to match the call sites.  Clang treats prototype-less functions
/// as varargs (foo(...)) which happens to work on existing platforms but
/// doesn't under WebAssembly.  This pass will find all the call sites of each
/// prototype-less function, ensure they agree, and then set the signature
/// on the function declaration accordingly.
///
//===----------------------------------------------------------------------===//

#include "WebAssembly.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

#define DEBUG_TYPE "wasm-add-missing-prototypes"

namespace {
class WebAssemblyAddMissingPrototypes final : public ModulePass {
  StringRef getPassName() const override {
    return "Add prototypes to prototypes-less functions";
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    ModulePass::getAnalysisUsage(AU);
  }

  bool runOnModule(Module &M) override;

public:
  static char ID;
  WebAssemblyAddMissingPrototypes() : ModulePass(ID) {}
};
} // End anonymous namespace

char WebAssemblyAddMissingPrototypes::ID = 0;
INITIALIZE_PASS(WebAssemblyAddMissingPrototypes, DEBUG_TYPE,
                "Add prototypes to prototypes-less functions", false, false)

ModulePass *llvm::createWebAssemblyAddMissingPrototypes() {
  return new WebAssemblyAddMissingPrototypes();
}

bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
  LLVM_DEBUG(dbgs() << "runnning AddMissingPrototypes\n");

  std::vector<std::pair<Function*, Function*>> Replacements;

  // Find all the prototype-less function declarations
  for (Function &F : M) {
    if (!F.isDeclaration() || !F.hasFnAttribute("no-prototype"))
      continue;

    LLVM_DEBUG(dbgs() << "Found no-prototype function: " << F.getName() << "\n");

    // When clang emits prototype-less C functions it uses (...), i.e. varargs
    // function that take no arguments (have no sentinel).  When we see a
    // no-prototype attribute we expect the function have these properties.
    if (!F.isVarArg())
      report_fatal_error(
          "Functions with 'no-prototype' attribute must take varargs: " +
          F.getName());
    if (F.getFunctionType()->getNumParams() != 0)
      report_fatal_error(
          "Functions with 'no-prototype' attribute should not have params: " +
          F.getName());

    // Create a function prototype based on the first call site (first bitcast)
    // that we find.
    FunctionType *NewType = nullptr;
    Function* NewF = nullptr;
    for (Use &U : F.uses()) {
      LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n");
      if (BitCastOperator *BC = dyn_cast<BitCastOperator>(U.getUser())) {
        FunctionType *DestType =
            cast<FunctionType>(BC->getDestTy()->getPointerElementType());

        // Create a new function with the correct type
        NewType = DestType;
        NewF = Function::Create(NewType, F.getLinkage(), F.getName());
        NewF->setAttributes(F.getAttributes());
        NewF->removeFnAttr("no-prototype");
        break;
      }
    }

    if (!NewType) {
      LLVM_DEBUG(
          dbgs() << "could not derive a function prototype from usage: " +
                        F.getName() + "\n");
      continue;
    }

    for (Use &U : F.uses()) {
      if (BitCastOperator *BC = dyn_cast<BitCastOperator>(U.getUser())) {
        FunctionType *DestType =
            cast<FunctionType>(BC->getDestTy()->getPointerElementType());
        if (NewType != DestType) {
          report_fatal_error(
              "Prototypeless function used with conflicting signatures: " +
              F.getName());
        }
        BC->replaceAllUsesWith(NewF);
        Replacements.emplace_back(&F, NewF);
      } else {
        dbgs() << *U.getUser()->getType() << "\n";
        U.getUser()->dump();
        report_fatal_error(
            "unexpected use of prototypeless function: " + F.getName() + "\n");
      }
    }
  }

  // Finally replace the old function declarations with the new ones
  for (auto &Pair : Replacements) {
    Function* Old = Pair.first;
    Function* New = Pair.second;
    Old->eraseFromParent();
    M.getFunctionList().push_back(New);
  }

  return !Replacements.empty();
}
<commit_msg>[WebAssembly] Only call llvm::value::dump() in debug build.<commit_after>//===-- WebAssemblyAddMissingPrototypes.cpp - Fix prototypeless functions -===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Add prototypes to prototypes-less functions.
///
/// WebAssembly has strict function prototype checking so we need functions
/// declarations to match the call sites.  Clang treats prototype-less functions
/// as varargs (foo(...)) which happens to work on existing platforms but
/// doesn't under WebAssembly.  This pass will find all the call sites of each
/// prototype-less function, ensure they agree, and then set the signature
/// on the function declaration accordingly.
///
//===----------------------------------------------------------------------===//

#include "WebAssembly.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Pass.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

#define DEBUG_TYPE "wasm-add-missing-prototypes"

namespace {
class WebAssemblyAddMissingPrototypes final : public ModulePass {
  StringRef getPassName() const override {
    return "Add prototypes to prototypes-less functions";
  }

  void getAnalysisUsage(AnalysisUsage &AU) const override {
    AU.setPreservesCFG();
    ModulePass::getAnalysisUsage(AU);
  }

  bool runOnModule(Module &M) override;

public:
  static char ID;
  WebAssemblyAddMissingPrototypes() : ModulePass(ID) {}
};
} // End anonymous namespace

char WebAssemblyAddMissingPrototypes::ID = 0;
INITIALIZE_PASS(WebAssemblyAddMissingPrototypes, DEBUG_TYPE,
                "Add prototypes to prototypes-less functions", false, false)

ModulePass *llvm::createWebAssemblyAddMissingPrototypes() {
  return new WebAssemblyAddMissingPrototypes();
}

bool WebAssemblyAddMissingPrototypes::runOnModule(Module &M) {
  LLVM_DEBUG(dbgs() << "runnning AddMissingPrototypes\n");

  std::vector<std::pair<Function*, Function*>> Replacements;

  // Find all the prototype-less function declarations
  for (Function &F : M) {
    if (!F.isDeclaration() || !F.hasFnAttribute("no-prototype"))
      continue;

    LLVM_DEBUG(dbgs() << "Found no-prototype function: " << F.getName() << "\n");

    // When clang emits prototype-less C functions it uses (...), i.e. varargs
    // function that take no arguments (have no sentinel).  When we see a
    // no-prototype attribute we expect the function have these properties.
    if (!F.isVarArg())
      report_fatal_error(
          "Functions with 'no-prototype' attribute must take varargs: " +
          F.getName());
    if (F.getFunctionType()->getNumParams() != 0)
      report_fatal_error(
          "Functions with 'no-prototype' attribute should not have params: " +
          F.getName());

    // Create a function prototype based on the first call site (first bitcast)
    // that we find.
    FunctionType *NewType = nullptr;
    Function* NewF = nullptr;
    for (Use &U : F.uses()) {
      LLVM_DEBUG(dbgs() << "prototype-less use: " << F.getName() << "\n");
      if (BitCastOperator *BC = dyn_cast<BitCastOperator>(U.getUser())) {
        FunctionType *DestType =
            cast<FunctionType>(BC->getDestTy()->getPointerElementType());

        // Create a new function with the correct type
        NewType = DestType;
        NewF = Function::Create(NewType, F.getLinkage(), F.getName());
        NewF->setAttributes(F.getAttributes());
        NewF->removeFnAttr("no-prototype");
        break;
      }
    }

    if (!NewType) {
      LLVM_DEBUG(
          dbgs() << "could not derive a function prototype from usage: " +
                        F.getName() + "\n");
      continue;
    }

    for (Use &U : F.uses()) {
      if (BitCastOperator *BC = dyn_cast<BitCastOperator>(U.getUser())) {
        FunctionType *DestType =
            cast<FunctionType>(BC->getDestTy()->getPointerElementType());
        if (NewType != DestType) {
          report_fatal_error(
              "Prototypeless function used with conflicting signatures: " +
              F.getName());
        }
        BC->replaceAllUsesWith(NewF);
        Replacements.emplace_back(&F, NewF);
      } else {
        dbgs() << *U.getUser()->getType() << "\n";
#ifndef NDEBUG
        U.getUser()->dump();
#endif
        report_fatal_error(
            "unexpected use of prototypeless function: " + F.getName() + "\n");
      }
    }
  }

  // Finally replace the old function declarations with the new ones
  for (auto &Pair : Replacements) {
    Function* Old = Pair.first;
    Function* New = Pair.second;
    Old->eraseFromParent();
    M.getFunctionList().push_back(New);
  }

  return !Replacements.empty();
}
<|endoftext|>