<commit_before>/**
 * @file AxisAngle.hpp
 *
 * @author James Goppert <james.goppert@gmail.com>
 */

#pragma once

#include "math.hpp"

namespace matrix
{

template <typename Type>
class Dcm;

template <typename Type>
class Euler;

template <typename Type>
class AxisAngle;

/**
 * AxisAngle class
 *
 * The rotation between two coordinate frames is
 * described by this class.
 */
template<typename Type>
class AxisAngle : public Vector<Type, 3>
{
public:
    typedef Matrix<Type, 3, 1> Matrix31;

    /**
     * Constructor from array
     *
     * @param data_ array
     */
    explicit AxisAngle(const Type data_[3]) :
        Vector<Type, 3>(data_)
    {
    }

    /**
     * Standard constructor
     */
    AxisAngle() = default;

    /**
     * Constructor from Matrix31
     *
     * @param other Matrix31 to copy
     */
    AxisAngle(const Matrix31 &other) :
        Vector<Type, 3>(other)
    {
    }

    /**
     * Constructor from quaternion
     *
     * This sets the instance from a quaternion representing coordinate transformation from
     * frame 2 to frame 1 where the rotation from frame 1 to frame 2 is described
     * by a 3-2-1 intrinsic Tait-Bryan rotation sequence.
     *
     * @param q quaternion
     */
    AxisAngle(const Quaternion<Type> &q)
    {
        AxisAngle &v = *this;
        Type ang = Type(2) * acos(q(0));
        Type mag = sin(ang/2.0f);
        if (fabs(mag) > 0) {
            v(0) = ang*q(1)/mag;
            v(1) = ang*q(2)/mag;
            v(2) = ang*q(3)/mag;
        } else {
            v(0) = 0;
            v(1) = 0;
            v(2) = 0;
        }
    }

    /**
     * Constructor from dcm
     *
     * Instance is initialized from a dcm representing coordinate transformation
     * from frame 2 to frame 1.
     *
     * @param dcm dcm to set quaternion to
     */
    AxisAngle(const Dcm<Type> &dcm)
    {
        AxisAngle &v = *this;
        v = Quaternion<Type>(dcm);
    }

    /**
     * Constructor from euler angles
     *
     * This sets the instance to a quaternion representing coordinate transformation from
     * frame 2 to frame 1 where the rotation from frame 1 to frame 2 is described
     * by a 3-2-1 intrinsic Tait-Bryan rotation sequence.
     *
     * @param euler euler angle instance
     */
    AxisAngle(const Euler<Type> &euler)
    {
        AxisAngle &v = *this;
        v = Quaternion<Type>(euler);
    }

    /**
     * Constructor from 3 axis angle values (unit vector * angle)
     *
     * @param x r_x*angle
     * @param y r_y*angle
     * @param z r_z*angle
     */
    AxisAngle(Type x, Type y, Type z)
    {
        AxisAngle &v = *this;
        v(0) = x;
        v(1) = y;
        v(2) = z;
    }

    /**
     * Constructor from axis and angle
     *
     * @param axis An axis of rotation, normalized if not unit length
     * @param angle The amount to rotate
     */
    AxisAngle(const Matrix31 & axis_, Type angle_)
    {
        AxisAngle &v = *this;
        // make sure axis is a unit vector
        Vector<Type, 3> a = axis_;
        a = a.unit();
        v(0) = a(0)*angle_;
        v(1) = a(1)*angle_;
        v(2) = a(2)*angle_;
    }

    Vector<Type, 3> axis() {
        if (Vector<Type, 3>::norm() > 0) {
            return Vector<Type, 3>::unit();
        } else {
            return Vector3<Type>(1, 0, 0);
        }
    }

    Type angle() {
        return Vector<Type, 3>::norm();
    }
};

typedef AxisAngle<float> AxisAnglef;

} // namespace matrix

/* vim: set et fenc=utf-8 ff=unix sts=0 sw=4 ts=4 : */
<commit_msg>Fix AngleAxis constructors (#117)<commit_after>/**
 * @file AxisAngle.hpp
 *
 * @author James Goppert <james.goppert@gmail.com>
 */

#pragma once

#include "math.hpp"

namespace matrix
{

template <typename Type>
class Dcm;

template <typename Type>
class Euler;

template <typename Type>
class AxisAngle;

/**
 * AxisAngle class
 *
 * The rotation between two coordinate frames is
 * described by this class.
 */
template<typename Type>
class AxisAngle : public Vector<Type, 3>
{
public:
    typedef Matrix<Type, 3, 1> Matrix31;

    /**
     * Constructor from array
     *
     * @param data_ array
     */
    explicit AxisAngle(const Type data_[3]) :
        Vector<Type, 3>(data_)
    {
    }

    /**
     * Standard constructor
     */
    AxisAngle() = default;

    /**
     * Constructor from Matrix31
     *
     * @param other Matrix31 to copy
     */
    AxisAngle(const Matrix31 &other) :
        Vector<Type, 3>(other)
    {
    }

    /**
     * Constructor from quaternion
     *
     * This sets the instance from a quaternion representing coordinate transformation from
     * frame 2 to frame 1 where the rotation from frame 1 to frame 2 is described
     * by a 3-2-1 intrinsic Tait-Bryan rotation sequence.
     *
     * @param q quaternion
     */
    AxisAngle(const Quaternion<Type> &q)
    {
        AxisAngle &v = *this;
        Type mag = Type(sqrt(q(1) * q(1) + q(2) * q(2) + q(3) * q(3)));
        if (fabs(mag) >= Type(1e-10)) {
            v = q.imag() * Type(Type(2) * atan2(mag, q(0)) / mag);
        } else {
            v = q.imag() * Type(Type(2) * Type(sign(q(0))));
        }
    }

    /**
     * Constructor from dcm
     *
     * Instance is initialized from a dcm representing coordinate transformation
     * from frame 2 to frame 1.
     *
     * @param dcm dcm to set quaternion to
     */
    AxisAngle(const Dcm<Type> &dcm)
    {
        AxisAngle &v = *this;
        v = AxisAngle<Type>(Quaternion<Type>(dcm));
    }

    /**
     * Constructor from euler angles
     *
     * This sets the instance to a quaternion representing coordinate transformation from
     * frame 2 to frame 1 where the rotation from frame 1 to frame 2 is described
     * by a 3-2-1 intrinsic Tait-Bryan rotation sequence.
     *
     * @param euler euler angle instance
     */
    AxisAngle(const Euler<Type> &euler)
    {
        AxisAngle &v = *this;
        v = AxisAngle<Type>(Quaternion<Type>(euler));
    }

    /**
     * Constructor from 3 axis angle values (unit vector * angle)
     *
     * @param x r_x*angle
     * @param y r_y*angle
     * @param z r_z*angle
     */
    AxisAngle(Type x, Type y, Type z)
    {
        AxisAngle &v = *this;
        v(0) = x;
        v(1) = y;
        v(2) = z;
    }

    /**
     * Constructor from axis and angle
     *
     * @param axis An axis of rotation, normalized if not unit length
     * @param angle The amount to rotate
     */
    AxisAngle(const Matrix31 & axis_, Type angle_)
    {
        AxisAngle &v = *this;
        // make sure axis is a unit vector
        Vector<Type, 3> a = axis_;
        a = a.unit();
        v(0) = a(0)*angle_;
        v(1) = a(1)*angle_;
        v(2) = a(2)*angle_;
    }

    Vector<Type, 3> axis() {
        if (Vector<Type, 3>::norm() > 0) {
            return Vector<Type, 3>::unit();
        } else {
            return Vector3<Type>(1, 0, 0);
        }
    }

    Type angle() {
        return Vector<Type, 3>::norm();
    }
};

typedef AxisAngle<float> AxisAnglef;

} // namespace matrix

/* vim: set et fenc=utf-8 ff=unix sts=0 sw=4 ts=4 : */
<|endoftext|>


<commit_before>// Copyright (c) 2012, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 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.

#include <cassert>
#include <cstddef>
#include <fstream>
#include <map>
#include <string>

#include "configreader.h"
#include "jit.h"
#include "jump-x86.h"
#include "plugin.h"
#include "version.h"

#ifdef WIN32
	#include <Windows.h>
#else
	#ifndef _GNU_SOURCE
		#define _GNU_SOURCE 1 // for dladdr()
	#endif
	#include <dlfcn.h>
#endif

extern void *pAMXFunctions;

typedef void (*logprintf_t)(const char *format, ...);
static logprintf_t logprintf;

typedef std::map<AMX*, jit::Jitter*> AmxToJitterMap;
static AmxToJitterMap amx_to_jitter;

static JumpX86 amx_Exec_hook;
static JumpX86 amx_GetAddr_hook;

static cell *opcode_list = 0;

static ConfigReader server_cfg("server.cfg");

static int AMXAPI amx_GetAddr_JIT(AMX *amx, cell amx_addr, cell **phys_addr) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	*phys_addr = reinterpret_cast<cell*>(amx->base + hdr->dat + amx_addr);
	return AMX_ERR_NONE;
}

static int AMXAPI amx_Exec_JIT(AMX *amx, cell *retval, int index) {
	#if defined __GNUC__ && !defined WIN32
		if ((amx->flags & AMX_FLAG_BROWSE) == AMX_FLAG_BROWSE) {
			// amx_BrowseRelocate() wants the opcode list.
			assert(::opcode_list != 0);
			*retval = reinterpret_cast<cell>(::opcode_list);
			return AMX_ERR_NONE;
		}
	#endif

	// A Jitter instance associated with this AMX.
	jit::Jitter *jitter = 0;

	// When amx_Exec() is called for the first time attempt to
	// JIT-compile this AMX. In case of compilation failure a null
	// pointer is put into amx_to_jit map to indicate this.
	AmxToJitterMap::iterator iterator = amx_to_jitter.find(amx);
	if (iterator == amx_to_jitter.end()) {
		jitter = new jit::Jitter(amx, ::opcode_list);
		int error = AMX_ERR_NONE;
		try {
			jitter->Compile();
		} catch (const jit::JitError &) {
			try {
				logprintf("[jit] An error occured, this script will run without JIT!");
				throw;
			} catch (const jit::CompileError &e) {
				const jit::AmxInstruction &instr = e.GetInstruction();
				AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
				cell address = reinterpret_cast<cell>(instr.GetIP())
							 - reinterpret_cast<cell>(amx->base + hdr->cod);
				try {
					throw;
				} catch (const jit::InvalidInstructionError &) {
					logprintf("[jit] Error: Invalid instruction at address %08x:", address);
				} catch (const jit::UnsupportedInstructionError &) {
					logprintf("[jit] Error: Unsupported instruction at address %08x:", address);
				} catch (const jit::ObsoleteInstructionError &) {
					logprintf("[jit] Error: Obsolete instruction at address %08x:", address);
				}
				const cell *ip = instr.GetIP();
				logprintf("  %08x %08x %08x %08x %08x %08x ...",
						*ip, *(ip + 1), *(ip + 2), *(ip + 3), *(ip + 4), *(ip + 5));
				error = AMX_ERR_INVINSTR;
			}
		} catch (...) {
			logprintf("[jit] Error: Unknown error");
			throw;
		}
		if (error != AMX_ERR_NONE) {
			delete jitter;
			jitter = 0;
		}
		amx_to_jitter.insert(std::make_pair(amx, jitter));
	}

	if (jitter == 0) {
		// Compilation previously failed, call normal amx_Exec().
		JumpX86::ScopedRemove r(&amx_Exec_hook);
		return amx_Exec(amx, retval, index);
	} else {
		return jitter->CallPublicFunction(index, retval);
	}
}

static std::string GetModuleNameBySymbol(void *symbol) {
	char module[FILENAME_MAX] = "";
	if (symbol != 0) {
		#ifdef WIN32
			MEMORY_BASIC_INFORMATION mbi;
			VirtualQuery(symbol, &mbi, sizeof(mbi));
			GetModuleFileName((HMODULE)mbi.AllocationBase, module, FILENAME_MAX);
		#else
			Dl_info info;
			dladdr(symbol, &info);
			strcpy(module, info.dli_fname);
		#endif
	}
	return std::string(module);
}

static std::string GetFileName(const std::string &path) {
	std::string::size_type lastSep = path.find_last_of("/\\");
	if (lastSep != std::string::npos) {
		return path.substr(lastSep + 1);
	}
	return path;
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports() {
	return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData) {
	logprintf = (logprintf_t)ppData[PLUGIN_DATA_LOGPRINTF];
	pAMXFunctions = reinterpret_cast<void*>(ppData[PLUGIN_DATA_AMX_EXPORTS]);

	void *funAddr = JumpX86::GetTargetAddress(((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec]);
	if (funAddr != 0) {
		std::string module = GetFileName(GetModuleNameBySymbol(funAddr));
		if (!module.empty() && module != "samp-server.exe" && module != "samp03svr") {
			logprintf("  JIT must be loaded before %s", module.c_str());
			return false;
		}
	}

	std::size_t stack_size = server_cfg.GetOption("jit_stack", 0);
	if (stack_size != 0) {
		jit::Jitter::SetStackSize(stack_size);
	}

	logprintf("  JIT plugin v%s is OK.", PLUGIN_VERSION_STRING);
	return true;
}

PLUGIN_EXPORT void PLUGIN_CALL Unload() {
	for (AmxToJitterMap::iterator it = amx_to_jitter.begin();
			it != amx_to_jitter.end(); ++it) {
		delete it->second;
	}
}

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx) {
	typedef int (AMXAPI *amx_Exec_t)(AMX *amx, cell *retval, int index);
	amx_Exec_t amx_Exec = (amx_Exec_t)((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec];

	typedef int (AMXAPI *amx_GetAddr_t)(AMX *amx, cell amx_addr, cell **phys_addr);
	amx_GetAddr_t amx_GetAddr = (amx_GetAddr_t)((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetAddr];

	#if defined __GNUC__ && !defined WIN32
		// Get opcode list before we hook amx_Exec().
		if (::opcode_list == 0) {
			amx->flags |= AMX_FLAG_BROWSE;
			amx_Exec(amx, reinterpret_cast<cell*>(&opcode_list), 0);
			amx->flags &= ~AMX_FLAG_BROWSE;
		}
	#endif

	if (!amx_Exec_hook.IsInstalled()) {
		amx_Exec_hook.Install(
			(void*)amx_Exec,
			(void*)amx_Exec_JIT);
	}
	if (!amx_GetAddr_hook.IsInstalled()) {
		amx_GetAddr_hook.Install(
			(void*)amx_GetAddr,
			(void*)amx_GetAddr_JIT);
	}

	return AMX_ERR_NONE;
}

PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx) {
	AmxToJitterMap::iterator it = amx_to_jitter.find(amx);
	if (it != amx_to_jitter.end()) {
		delete it->second;
		amx_to_jitter.erase(it);
	}
	return AMX_ERR_NONE;
}
<commit_msg>Remove amx_BrowseRelocate() support code from amx_Exec_JIT()<commit_after>// Copyright (c) 2012, Zeex
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 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.

#include <cassert>
#include <cstddef>
#include <fstream>
#include <map>
#include <string>

#include "configreader.h"
#include "jit.h"
#include "jump-x86.h"
#include "plugin.h"
#include "version.h"

#ifdef WIN32
	#include <Windows.h>
#else
	#ifndef _GNU_SOURCE
		#define _GNU_SOURCE 1 // for dladdr()
	#endif
	#include <dlfcn.h>
#endif

extern void *pAMXFunctions;

typedef void (*logprintf_t)(const char *format, ...);
static logprintf_t logprintf;

typedef std::map<AMX*, jit::Jitter*> AmxToJitterMap;
static AmxToJitterMap amx_to_jitter;

static JumpX86 amx_Exec_hook;
static JumpX86 amx_GetAddr_hook;

static cell *opcode_list = 0;

static ConfigReader server_cfg("server.cfg");

static int AMXAPI amx_GetAddr_JIT(AMX *amx, cell amx_addr, cell **phys_addr) {
	AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
	*phys_addr = reinterpret_cast<cell*>(amx->base + hdr->dat + amx_addr);
	return AMX_ERR_NONE;
}

static int AMXAPI amx_Exec_JIT(AMX *amx, cell *retval, int index) {
	// A Jitter instance associated with this AMX.
	jit::Jitter *jitter = 0;

	// When amx_Exec() is called for the first time attempt to
	// JIT-compile this AMX. In case of compilation failure a null
	// pointer is put into amx_to_jit map to indicate this.
	AmxToJitterMap::iterator iterator = amx_to_jitter.find(amx);
	if (iterator == amx_to_jitter.end()) {
		jitter = new jit::Jitter(amx, ::opcode_list);
		int error = AMX_ERR_NONE;
		try {
			jitter->Compile();
		} catch (const jit::JitError &) {
			try {
				logprintf("[jit] An error occured, this script will run without JIT!");
				throw;
			} catch (const jit::CompileError &e) {
				const jit::AmxInstruction &instr = e.GetInstruction();
				AMX_HEADER *hdr = reinterpret_cast<AMX_HEADER*>(amx->base);
				cell address = reinterpret_cast<cell>(instr.GetIP())
							 - reinterpret_cast<cell>(amx->base + hdr->cod);
				try {
					throw;
				} catch (const jit::InvalidInstructionError &) {
					logprintf("[jit] Error: Invalid instruction at address %08x:", address);
				} catch (const jit::UnsupportedInstructionError &) {
					logprintf("[jit] Error: Unsupported instruction at address %08x:", address);
				} catch (const jit::ObsoleteInstructionError &) {
					logprintf("[jit] Error: Obsolete instruction at address %08x:", address);
				}
				const cell *ip = instr.GetIP();
				logprintf("  %08x %08x %08x %08x %08x %08x ...",
						*ip, *(ip + 1), *(ip + 2), *(ip + 3), *(ip + 4), *(ip + 5));
				error = AMX_ERR_INVINSTR;
			}
		} catch (...) {
			logprintf("[jit] Error: Unknown error");
			throw;
		}
		if (error != AMX_ERR_NONE) {
			delete jitter;
			jitter = 0;
		}
		amx_to_jitter.insert(std::make_pair(amx, jitter));
	}

	if (jitter == 0) {
		// Compilation previously failed, call normal amx_Exec().
		JumpX86::ScopedRemove r(&amx_Exec_hook);
		return amx_Exec(amx, retval, index);
	} else {
		return jitter->CallPublicFunction(index, retval);
	}
}

static std::string GetModuleNameBySymbol(void *symbol) {
	char module[FILENAME_MAX] = "";
	if (symbol != 0) {
		#ifdef WIN32
			MEMORY_BASIC_INFORMATION mbi;
			VirtualQuery(symbol, &mbi, sizeof(mbi));
			GetModuleFileName((HMODULE)mbi.AllocationBase, module, FILENAME_MAX);
		#else
			Dl_info info;
			dladdr(symbol, &info);
			strcpy(module, info.dli_fname);
		#endif
	}
	return std::string(module);
}

static std::string GetFileName(const std::string &path) {
	std::string::size_type lastSep = path.find_last_of("/\\");
	if (lastSep != std::string::npos) {
		return path.substr(lastSep + 1);
	}
	return path;
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports() {
	return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData) {
	logprintf = (logprintf_t)ppData[PLUGIN_DATA_LOGPRINTF];
	pAMXFunctions = reinterpret_cast<void*>(ppData[PLUGIN_DATA_AMX_EXPORTS]);

	void *funAddr = JumpX86::GetTargetAddress(((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec]);
	if (funAddr != 0) {
		std::string module = GetFileName(GetModuleNameBySymbol(funAddr));
		if (!module.empty() && module != "samp-server.exe" && module != "samp03svr") {
			logprintf("  JIT must be loaded before %s", module.c_str());
			return false;
		}
	}

	std::size_t stack_size = server_cfg.GetOption("jit_stack", 0);
	if (stack_size != 0) {
		jit::Jitter::SetStackSize(stack_size);
	}

	logprintf("  JIT plugin v%s is OK.", PLUGIN_VERSION_STRING);
	return true;
}

PLUGIN_EXPORT void PLUGIN_CALL Unload() {
	for (AmxToJitterMap::iterator it = amx_to_jitter.begin();
			it != amx_to_jitter.end(); ++it) {
		delete it->second;
	}
}

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad(AMX *amx) {
	typedef int (AMXAPI *amx_Exec_t)(AMX *amx, cell *retval, int index);
	amx_Exec_t amx_Exec = (amx_Exec_t)((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_Exec];

	typedef int (AMXAPI *amx_GetAddr_t)(AMX *amx, cell amx_addr, cell **phys_addr);
	amx_GetAddr_t amx_GetAddr = (amx_GetAddr_t)((void**)pAMXFunctions)[PLUGIN_AMX_EXPORT_GetAddr];

	#if defined __GNUC__ && !defined WIN32
		// Get opcode list before we hook amx_Exec().
		if (::opcode_list == 0) {
			amx->flags |= AMX_FLAG_BROWSE;
			amx_Exec(amx, reinterpret_cast<cell*>(&opcode_list), 0);
			amx->flags &= ~AMX_FLAG_BROWSE;
		}
	#endif

	if (!amx_Exec_hook.IsInstalled()) {
		amx_Exec_hook.Install(
			(void*)amx_Exec,
			(void*)amx_Exec_JIT);
	}
	if (!amx_GetAddr_hook.IsInstalled()) {
		amx_GetAddr_hook.Install(
			(void*)amx_GetAddr,
			(void*)amx_GetAddr_JIT);
	}

	return AMX_ERR_NONE;
}

PLUGIN_EXPORT int PLUGIN_CALL AmxUnload(AMX *amx) {
	AmxToJitterMap::iterator it = amx_to_jitter.find(amx);
	if (it != amx_to_jitter.end()) {
		delete it->second;
		amx_to_jitter.erase(it);
	}
	return AMX_ERR_NONE;
}
<|endoftext|>


<commit_before>//===- Steensgaard.cpp - Context Insensitive Alias Analysis ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass uses the data structure graphs to implement a simple context
// insensitive alias analysis.  It does this by computing the local analysis
// graphs for all of the functions, then merging them together into a single big
// graph without cloning.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure/DataStructure.h"
#include "llvm/Analysis/DataStructure/DSGraph.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Module.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

namespace {
  class Steens : public ModulePass, public AliasAnalysis {
    DSGraph *ResultGraph;
    DSGraph *GlobalsGraph;  // FIXME: Eliminate globals graph stuff from DNE

    EquivalenceClasses<GlobalValue*> GlobalECs;  // Always empty
  public:
    Steens() : ResultGraph(0), GlobalsGraph(0) {}
    ~Steens() {
      releaseMyMemory();
      assert(ResultGraph == 0 && "releaseMemory not called?");
    }

    //------------------------------------------------
    // Implement the Pass API
    //

    // run - Build up the result graph, representing the pointer graph for the
    // program.
    //
    bool runOnModule(Module &M);

    virtual void releaseMyMemory() { delete ResultGraph; ResultGraph = 0; }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AliasAnalysis::getAnalysisUsage(AU);
      AU.setPreservesAll();                    // Does not transform code...
      AU.addRequired<LocalDataStructures>();   // Uses local dsgraph
    }

    // print - Implement the Pass::print method...
    void print(std::ostream &O, const Module *M) const {
      assert(ResultGraph && "Result graph has not yet been computed!");
      ResultGraph->writeGraphToFile(O, "steensgaards");
    }

    //------------------------------------------------
    // Implement the AliasAnalysis API
    //

    // alias - This is the only method here that does anything interesting...
    AliasResult alias(const Value *V1, unsigned V1Size,
                      const Value *V2, unsigned V2Size);

  private:
    void ResolveFunctionCall(Function *F, const DSCallSite &Call,
                             DSNodeHandle &RetVal);
  };

  // Register the pass...
  RegisterOpt<Steens> X("steens-aa",
                        "Steensgaard's alias analysis (DSGraph based)");

  // Register as an implementation of AliasAnalysis
  RegisterAnalysisGroup<AliasAnalysis, Steens> Y;
}

ModulePass *llvm::createSteensgaardPass() { return new Steens(); }

/// ResolveFunctionCall - Resolve the actual arguments of a call to function F
/// with the specified call site descriptor.  This function links the arguments
/// and the return value for the call site context-insensitively.
///
void Steens::ResolveFunctionCall(Function *F, const DSCallSite &Call,
                                 DSNodeHandle &RetVal) {
  assert(ResultGraph != 0 && "Result graph not allocated!");
  DSGraph::ScalarMapTy &ValMap = ResultGraph->getScalarMap();

  // Handle the return value of the function...
  if (Call.getRetVal().getNode() && RetVal.getNode())
    RetVal.mergeWith(Call.getRetVal());

  // Loop over all pointer arguments, resolving them to their provided pointers
  unsigned PtrArgIdx = 0;
  for (Function::arg_iterator AI = F->arg_begin(), AE = F->arg_end();
       AI != AE && PtrArgIdx < Call.getNumPtrArgs(); ++AI) {
    DSGraph::ScalarMapTy::iterator I = ValMap.find(AI);
    if (I != ValMap.end())    // If its a pointer argument...
      I->second.mergeWith(Call.getPtrArg(PtrArgIdx++));
  }
}

/// run - Build up the result graph, representing the pointer graph for the
/// program.
///
bool Steens::runOnModule(Module &M) {
  InitializeAliasAnalysis(this);
  assert(ResultGraph == 0 && "Result graph already allocated!");
  LocalDataStructures &LDS = getAnalysis<LocalDataStructures>();

  // Create a new, empty, graph...
  ResultGraph = new DSGraph(GlobalECs, getTargetData());
  GlobalsGraph = new DSGraph(GlobalECs, getTargetData());
  ResultGraph->setGlobalsGraph(GlobalsGraph);
  ResultGraph->setPrintAuxCalls();

  // RetValMap - Keep track of the return values for all functions that return
  // valid pointers.
  //
  DSGraph::ReturnNodesTy RetValMap;

  // Loop over the rest of the module, merging graphs for non-external functions
  // into this graph.
  //
  unsigned Count = 0;
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isExternal()) {
      DSGraph::ScalarMapTy ValMap(GlobalECs);
      {  // Scope to free NodeMap memory ASAP
        DSGraph::NodeMapTy NodeMap;
        const DSGraph &FDSG = LDS.getDSGraph(*I);
        ResultGraph->cloneInto(FDSG, ValMap, RetValMap, NodeMap,
                               DSGraph::UpdateInlinedGlobals);
      }

      // Incorporate the inlined Function's ScalarMap into the global
      // ScalarMap...
      DSGraph::ScalarMapTy &GVM = ResultGraph->getScalarMap();
      for (DSGraph::ScalarMapTy::iterator I = ValMap.begin(),
             E = ValMap.end(); I != E; ++I)
        GVM[I->first].mergeWith(I->second);

      if ((++Count & 1) == 0)   // Prune nodes out every other time...
        ResultGraph->removeTriviallyDeadNodes();
    }

  // FIXME: Must recalculate and use the Incomplete markers!!

  // Now that we have all of the graphs inlined, we can go about eliminating
  // call nodes...
  //
  std::list<DSCallSite> &Calls = ResultGraph->getAuxFunctionCalls();
  assert(Calls.empty() && "Aux call list is already in use??");

  // Start with a copy of the original call sites.
  Calls = ResultGraph->getFunctionCalls();

  for (std::list<DSCallSite>::iterator CI = Calls.begin(), E = Calls.end();
       CI != E;) {
    DSCallSite &CurCall = *CI++;

    // Loop over the called functions, eliminating as many as possible...
    std::vector<Function*> CallTargets;
    if (CurCall.isDirectCall())
      CallTargets.push_back(CurCall.getCalleeFunc());
    else
      CurCall.getCalleeNode()->addFullFunctionList(CallTargets);

    for (unsigned c = 0; c != CallTargets.size(); ) {
      // If we can eliminate this function call, do so!
      Function *F = CallTargets[c];
      if (!F->isExternal()) {
        ResolveFunctionCall(F, CurCall, RetValMap[F]);
        CallTargets[c] = CallTargets.back();
        CallTargets.pop_back();
      } else
        ++c;  // Cannot eliminate this call, skip over it...
    }

    if (CallTargets.empty()) {        // Eliminated all calls?
      std::list<DSCallSite>::iterator I = CI;
      Calls.erase(--I);               // Remove entry
    }
  }

  RetValMap.clear();

  // Update the "incomplete" markers on the nodes, ignoring unknownness due to
  // incoming arguments...
  ResultGraph->maskIncompleteMarkers();
  ResultGraph->markIncompleteNodes(DSGraph::IgnoreFormalArgs);

  // Remove any nodes that are dead after all of the merging we have done...
  // FIXME: We should be able to disable the globals graph for steens!
  ResultGraph->removeDeadNodes(DSGraph::KeepUnreachableGlobals);

  DEBUG(print(std::cerr, &M));
  return false;
}

// alias - This is the only method here that does anything interesting...
AliasAnalysis::AliasResult Steens::alias(const Value *V1, unsigned V1Size,
                                         const Value *V2, unsigned V2Size) {
  // FIXME: HANDLE Size argument!
  assert(ResultGraph && "Result graph has not been computed yet!");

  DSGraph::ScalarMapTy &GSM = ResultGraph->getScalarMap();

  DSGraph::ScalarMapTy::iterator I = GSM.find(const_cast<Value*>(V1));
  if (I != GSM.end() && I->second.getNode()) {
    DSNodeHandle &V1H = I->second;
    DSGraph::ScalarMapTy::iterator J=GSM.find(const_cast<Value*>(V2));
    if (J != GSM.end() && J->second.getNode()) {
      DSNodeHandle &V2H = J->second;
      // If the two pointers point to different data structure graph nodes, they
      // cannot alias!
      if (V1H.getNode() != V2H.getNode())    // FIXME: Handle incompleteness!
        return NoAlias;

      // FIXME: If the two pointers point to the same node, and the offsets are
      // different, and the LinkIndex vector doesn't alias the section, then the
      // two pointers do not alias.  We need access size information for the two
      // accesses though!
      //
    }
  }

  // If we cannot determine alias properties based on our graph, fall back on
  // some other AA implementation.
  //
  return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
}
<commit_msg>-steens doesn't use the inlined globals facility.<commit_after>//===- Steensgaard.cpp - Context Insensitive Alias Analysis ---------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass uses the data structure graphs to implement a simple context
// insensitive alias analysis.  It does this by computing the local analysis
// graphs for all of the functions, then merging them together into a single big
// graph without cloning.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure/DataStructure.h"
#include "llvm/Analysis/DataStructure/DSGraph.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Module.h"
#include "llvm/Support/Debug.h"
using namespace llvm;

namespace {
  class Steens : public ModulePass, public AliasAnalysis {
    DSGraph *ResultGraph;
    DSGraph *GlobalsGraph;  // FIXME: Eliminate globals graph stuff from DNE

    EquivalenceClasses<GlobalValue*> GlobalECs;  // Always empty
  public:
    Steens() : ResultGraph(0), GlobalsGraph(0) {}
    ~Steens() {
      releaseMyMemory();
      assert(ResultGraph == 0 && "releaseMemory not called?");
    }

    //------------------------------------------------
    // Implement the Pass API
    //

    // run - Build up the result graph, representing the pointer graph for the
    // program.
    //
    bool runOnModule(Module &M);

    virtual void releaseMyMemory() { delete ResultGraph; ResultGraph = 0; }

    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AliasAnalysis::getAnalysisUsage(AU);
      AU.setPreservesAll();                    // Does not transform code...
      AU.addRequired<LocalDataStructures>();   // Uses local dsgraph
    }

    // print - Implement the Pass::print method...
    void print(std::ostream &O, const Module *M) const {
      assert(ResultGraph && "Result graph has not yet been computed!");
      ResultGraph->writeGraphToFile(O, "steensgaards");
    }

    //------------------------------------------------
    // Implement the AliasAnalysis API
    //

    // alias - This is the only method here that does anything interesting...
    AliasResult alias(const Value *V1, unsigned V1Size,
                      const Value *V2, unsigned V2Size);

  private:
    void ResolveFunctionCall(Function *F, const DSCallSite &Call,
                             DSNodeHandle &RetVal);
  };

  // Register the pass...
  RegisterOpt<Steens> X("steens-aa",
                        "Steensgaard's alias analysis (DSGraph based)");

  // Register as an implementation of AliasAnalysis
  RegisterAnalysisGroup<AliasAnalysis, Steens> Y;
}

ModulePass *llvm::createSteensgaardPass() { return new Steens(); }

/// ResolveFunctionCall - Resolve the actual arguments of a call to function F
/// with the specified call site descriptor.  This function links the arguments
/// and the return value for the call site context-insensitively.
///
void Steens::ResolveFunctionCall(Function *F, const DSCallSite &Call,
                                 DSNodeHandle &RetVal) {
  assert(ResultGraph != 0 && "Result graph not allocated!");
  DSGraph::ScalarMapTy &ValMap = ResultGraph->getScalarMap();

  // Handle the return value of the function...
  if (Call.getRetVal().getNode() && RetVal.getNode())
    RetVal.mergeWith(Call.getRetVal());

  // Loop over all pointer arguments, resolving them to their provided pointers
  unsigned PtrArgIdx = 0;
  for (Function::arg_iterator AI = F->arg_begin(), AE = F->arg_end();
       AI != AE && PtrArgIdx < Call.getNumPtrArgs(); ++AI) {
    DSGraph::ScalarMapTy::iterator I = ValMap.find(AI);
    if (I != ValMap.end())    // If its a pointer argument...
      I->second.mergeWith(Call.getPtrArg(PtrArgIdx++));
  }
}

/// run - Build up the result graph, representing the pointer graph for the
/// program.
///
bool Steens::runOnModule(Module &M) {
  InitializeAliasAnalysis(this);
  assert(ResultGraph == 0 && "Result graph already allocated!");
  LocalDataStructures &LDS = getAnalysis<LocalDataStructures>();

  // Create a new, empty, graph...
  ResultGraph = new DSGraph(GlobalECs, getTargetData());
  GlobalsGraph = new DSGraph(GlobalECs, getTargetData());
  ResultGraph->setGlobalsGraph(GlobalsGraph);
  ResultGraph->setPrintAuxCalls();

  // RetValMap - Keep track of the return values for all functions that return
  // valid pointers.
  //
  DSGraph::ReturnNodesTy RetValMap;

  // Loop over the rest of the module, merging graphs for non-external functions
  // into this graph.
  //
  unsigned Count = 0;
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isExternal()) {
      DSGraph::ScalarMapTy ValMap(GlobalECs);
      {  // Scope to free NodeMap memory ASAP
        DSGraph::NodeMapTy NodeMap;
        const DSGraph &FDSG = LDS.getDSGraph(*I);
        ResultGraph->cloneInto(FDSG, ValMap, RetValMap, NodeMap, 0);
      }

      // Incorporate the inlined Function's ScalarMap into the global
      // ScalarMap...
      DSGraph::ScalarMapTy &GVM = ResultGraph->getScalarMap();
      for (DSGraph::ScalarMapTy::iterator I = ValMap.begin(),
             E = ValMap.end(); I != E; ++I)
        GVM[I->first].mergeWith(I->second);

      if ((++Count & 1) == 0)   // Prune nodes out every other time...
        ResultGraph->removeTriviallyDeadNodes();
    }

  // FIXME: Must recalculate and use the Incomplete markers!!

  // Now that we have all of the graphs inlined, we can go about eliminating
  // call nodes...
  //
  std::list<DSCallSite> &Calls = ResultGraph->getAuxFunctionCalls();
  assert(Calls.empty() && "Aux call list is already in use??");

  // Start with a copy of the original call sites.
  Calls = ResultGraph->getFunctionCalls();

  for (std::list<DSCallSite>::iterator CI = Calls.begin(), E = Calls.end();
       CI != E;) {
    DSCallSite &CurCall = *CI++;

    // Loop over the called functions, eliminating as many as possible...
    std::vector<Function*> CallTargets;
    if (CurCall.isDirectCall())
      CallTargets.push_back(CurCall.getCalleeFunc());
    else
      CurCall.getCalleeNode()->addFullFunctionList(CallTargets);

    for (unsigned c = 0; c != CallTargets.size(); ) {
      // If we can eliminate this function call, do so!
      Function *F = CallTargets[c];
      if (!F->isExternal()) {
        ResolveFunctionCall(F, CurCall, RetValMap[F]);
        CallTargets[c] = CallTargets.back();
        CallTargets.pop_back();
      } else
        ++c;  // Cannot eliminate this call, skip over it...
    }

    if (CallTargets.empty()) {        // Eliminated all calls?
      std::list<DSCallSite>::iterator I = CI;
      Calls.erase(--I);               // Remove entry
    }
  }

  RetValMap.clear();

  // Update the "incomplete" markers on the nodes, ignoring unknownness due to
  // incoming arguments...
  ResultGraph->maskIncompleteMarkers();
  ResultGraph->markIncompleteNodes(DSGraph::IgnoreFormalArgs);

  // Remove any nodes that are dead after all of the merging we have done...
  // FIXME: We should be able to disable the globals graph for steens!
  ResultGraph->removeDeadNodes(DSGraph::KeepUnreachableGlobals);

  DEBUG(print(std::cerr, &M));
  return false;
}

// alias - This is the only method here that does anything interesting...
AliasAnalysis::AliasResult Steens::alias(const Value *V1, unsigned V1Size,
                                         const Value *V2, unsigned V2Size) {
  // FIXME: HANDLE Size argument!
  assert(ResultGraph && "Result graph has not been computed yet!");

  DSGraph::ScalarMapTy &GSM = ResultGraph->getScalarMap();

  DSGraph::ScalarMapTy::iterator I = GSM.find(const_cast<Value*>(V1));
  if (I != GSM.end() && I->second.getNode()) {
    DSNodeHandle &V1H = I->second;
    DSGraph::ScalarMapTy::iterator J=GSM.find(const_cast<Value*>(V2));
    if (J != GSM.end() && J->second.getNode()) {
      DSNodeHandle &V2H = J->second;
      // If the two pointers point to different data structure graph nodes, they
      // cannot alias!
      if (V1H.getNode() != V2H.getNode())    // FIXME: Handle incompleteness!
        return NoAlias;

      // FIXME: If the two pointers point to the same node, and the offsets are
      // different, and the LinkIndex vector doesn't alias the section, then the
      // two pointers do not alias.  We need access size information for the two
      // accesses though!
      //
    }
  }

  // If we cannot determine alias properties based on our graph, fall back on
  // some other AA implementation.
  //
  return AliasAnalysis::alias(V1, V1Size, V2, V2Size);
}
<|endoftext|>


<commit_before>//===- lib/ReaderWriter/ELF/ELFLinkingContext.cpp -------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lld/ReaderWriter/ELFLinkingContext.h"
#include "ELFFile.h"
#include "OrderPass.h"
#include "TargetHandler.h"
#include "lld/Core/Instrumentation.h"
#include "lld/Core/SharedLibraryFile.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Config/config.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"

#if defined(HAVE_CXXABI_H)
#include <cxxabi.h>
#endif

namespace lld {

class CommandLineAbsoluteAtom : public AbsoluteAtom {
public:
  CommandLineAbsoluteAtom(const File &file, StringRef name, uint64_t value)
      : _file(file), _name(name), _value(value) {}

  const File &file() const override { return _file; }
  StringRef name() const override { return _name; }
  uint64_t value() const override { return _value; }
  Scope scope() const override { return scopeGlobal; }

private:
  const File &_file;
  StringRef _name;
  uint64_t _value;
};

class CommandLineUndefinedAtom : public SimpleUndefinedAtom {
public:
  CommandLineUndefinedAtom(const File &f, StringRef name)
      : SimpleUndefinedAtom(f, name) {}

  CanBeNull canBeNull() const override {
    return CanBeNull::canBeNullAtBuildtime;
  }
};

ELFLinkingContext::ELFLinkingContext(
    llvm::Triple triple, std::unique_ptr<TargetHandlerBase> targetHandler)
    : _outputELFType(llvm::ELF::ET_EXEC), _triple(triple),
      _targetHandler(std::move(targetHandler)), _baseAddress(0),
      _isStaticExecutable(false), _noInhibitExec(false), _exportDynamic(false),
      _mergeCommonStrings(false), _useShlibUndefines(true),
      _dynamicLinkerArg(false), _noAllowDynamicLibraries(false),
      _mergeRODataToTextSegment(true), _demangle(true),
      _stripSymbols(false), _alignSegments(true), _collectStats(false),
      _outputMagic(OutputMagic::DEFAULT), _initFunction("_init"),
      _finiFunction("_fini"), _sysrootPath("") {}

void ELFLinkingContext::addPasses(PassManager &pm) {
  pm.add(llvm::make_unique<elf::OrderPass>());
}

uint16_t ELFLinkingContext::getOutputMachine() const {
  switch (getTriple().getArch()) {
  case llvm::Triple::x86:
    return llvm::ELF::EM_386;
  case llvm::Triple::x86_64:
    return llvm::ELF::EM_X86_64;
  case llvm::Triple::hexagon:
    return llvm::ELF::EM_HEXAGON;
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64el:
    return llvm::ELF::EM_MIPS;
  case llvm::Triple::aarch64:
    return llvm::ELF::EM_AARCH64;
  case llvm::Triple::arm:
    return llvm::ELF::EM_ARM;
  default:
    llvm_unreachable("Unhandled arch");
  }
}

StringRef ELFLinkingContext::entrySymbolName() const {
  if (_outputELFType == llvm::ELF::ET_EXEC && _entrySymbolName.empty())
    return "_start";
  return _entrySymbolName;
}

bool ELFLinkingContext::validateImpl(raw_ostream &diagnostics) {
  switch (outputFileType()) {
  case LinkingContext::OutputFileType::YAML:
    _writer = createWriterYAML(*this);
    break;
  case LinkingContext::OutputFileType::Native:
    llvm_unreachable("Unimplemented");
    break;
  default:
    _writer = createWriterELF(this->targetHandler());
    break;
  }
  return true;
}

bool ELFLinkingContext::isDynamic() const {
  switch (_outputELFType) {
  case llvm::ELF::ET_EXEC:
    return !_isStaticExecutable;
  case llvm::ELF::ET_DYN:
    return true;
  }
  return false;
}

bool ELFLinkingContext::isRelativeReloc(const Reference &) const {
  return false;
}

Writer &ELFLinkingContext::writer() const { return *_writer; }

static void buildSearchPath(SmallString<128> &path, StringRef dir,
                            StringRef sysRoot) {
  if (!dir.startswith("=/"))
    path.assign(dir);
  else {
    path.assign(sysRoot);
    path.append(dir.substr(1));
  }
}

ErrorOr<StringRef> ELFLinkingContext::searchLibrary(StringRef libName) const {
  bool hasColonPrefix = libName[0] == ':';
  SmallString<128> path;
  for (StringRef dir : _inputSearchPaths) {
    // Search for dynamic library
    if (!_isStaticExecutable) {
      buildSearchPath(path, dir, _sysrootPath);
      llvm::sys::path::append(path, hasColonPrefix
                                        ? libName.drop_front()
                                        : Twine("lib", libName) + ".so");
      if (llvm::sys::fs::exists(path.str()))
        return StringRef(*new (_allocator) std::string(path.str()));
    }
    // Search for static libraries too
    buildSearchPath(path, dir, _sysrootPath);
    llvm::sys::path::append(path, hasColonPrefix
                                      ? libName.drop_front()
                                      : Twine("lib", libName) + ".a");
    if (llvm::sys::fs::exists(path.str()))
      return StringRef(*new (_allocator) std::string(path.str()));
  }
  if (!llvm::sys::fs::exists(libName))
    return make_error_code(llvm::errc::no_such_file_or_directory);

  return libName;
}

ErrorOr<StringRef> ELFLinkingContext::searchFile(StringRef fileName,
                                                 bool isSysRooted) const {
  SmallString<128> path;
  if (llvm::sys::path::is_absolute(fileName) && isSysRooted) {
    path.assign(_sysrootPath);
    path.append(fileName);
    if (llvm::sys::fs::exists(path.str()))
      return StringRef(*new (_allocator) std::string(path.str()));
  } else if (llvm::sys::fs::exists(fileName))
    return fileName;

  if (llvm::sys::path::is_absolute(fileName))
    return make_error_code(llvm::errc::no_such_file_or_directory);

  for (StringRef dir : _inputSearchPaths) {
    buildSearchPath(path, dir, _sysrootPath);
    llvm::sys::path::append(path, fileName);
    if (llvm::sys::fs::exists(path.str()))
      return StringRef(*new (_allocator) std::string(path.str()));
  }
  return make_error_code(llvm::errc::no_such_file_or_directory);
}

void ELFLinkingContext::createInternalFiles(
    std::vector<std::unique_ptr<File>> &files) const {
  std::unique_ptr<SimpleFile> file(
      new SimpleFile("<internal file for --defsym>"));
  for (auto &i : getAbsoluteSymbols()) {
    StringRef sym = i.first;
    uint64_t val = i.second;
    file->addAtom(*(new (_allocator) CommandLineAbsoluteAtom(*file, sym, val)));
  }
  files.push_back(std::move(file));
  LinkingContext::createInternalFiles(files);
}

std::unique_ptr<File> ELFLinkingContext::createUndefinedSymbolFile() const {
  if (_initialUndefinedSymbols.empty())
    return nullptr;
  std::unique_ptr<SimpleFile> undefinedSymFile(
      new SimpleFile("command line option -u"));
  for (auto undefSymStr : _initialUndefinedSymbols)
    undefinedSymFile->addAtom(*(new (_allocator) CommandLineUndefinedAtom(
        *undefinedSymFile, undefSymStr)));
  return std::move(undefinedSymFile);
}

void ELFLinkingContext::notifySymbolTableCoalesce(const Atom *existingAtom,
                                                  const Atom *newAtom,
                                                  bool &useNew) {
  // First suppose that the `existingAtom` is defined
  // and the `newAtom` is undefined.
  auto *da = dyn_cast<DefinedAtom>(existingAtom);
  auto *ua = dyn_cast<UndefinedAtom>(newAtom);
  if (!da && !ua) {
    // Then try to reverse the assumption.
    da = dyn_cast<DefinedAtom>(newAtom);
    ua = dyn_cast<UndefinedAtom>(existingAtom);
  }

  if (da && ua && da->scope() == Atom::scopeGlobal &&
      isa<SharedLibraryFile>(ua->file()))
    // If strong defined atom coalesces away an atom declared
    // in the shared object the strong atom needs to be dynamically exported.
    // Save its name.
    _dynamicallyExportedSymbols.insert(ua->name());
}

std::string ELFLinkingContext::demangle(StringRef symbolName) const {
  if (!demangleSymbols())
    return symbolName;

  // Only try to demangle symbols that look like C++ symbols
  if (!symbolName.startswith("_Z"))
    return symbolName;

#if defined(HAVE_CXXABI_H)
  SmallString<256> symBuff;
  StringRef nullTermSym = Twine(symbolName).toNullTerminatedStringRef(symBuff);
  const char *cstr = nullTermSym.data();
  int status;
  char *demangled = abi::__cxa_demangle(cstr, nullptr, nullptr, &status);
  if (demangled != NULL) {
    std::string result(demangled);
    // __cxa_demangle() always uses a malloc'ed buffer to return the result.
    free(demangled);
    return result;
  }
#endif

  return symbolName;
}

} // end namespace lld
<commit_msg>[ELF] Set up initial live symbol(s) to avoid incorrect reclaim of atoms.<commit_after>//===- lib/ReaderWriter/ELF/ELFLinkingContext.cpp -------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lld/ReaderWriter/ELFLinkingContext.h"
#include "ELFFile.h"
#include "OrderPass.h"
#include "TargetHandler.h"
#include "lld/Core/Instrumentation.h"
#include "lld/Core/SharedLibraryFile.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Config/config.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"

#if defined(HAVE_CXXABI_H)
#include <cxxabi.h>
#endif

namespace lld {

class CommandLineAbsoluteAtom : public AbsoluteAtom {
public:
  CommandLineAbsoluteAtom(const File &file, StringRef name, uint64_t value)
      : _file(file), _name(name), _value(value) {}

  const File &file() const override { return _file; }
  StringRef name() const override { return _name; }
  uint64_t value() const override { return _value; }
  Scope scope() const override { return scopeGlobal; }

private:
  const File &_file;
  StringRef _name;
  uint64_t _value;
};

class CommandLineUndefinedAtom : public SimpleUndefinedAtom {
public:
  CommandLineUndefinedAtom(const File &f, StringRef name)
      : SimpleUndefinedAtom(f, name) {}

  CanBeNull canBeNull() const override {
    return CanBeNull::canBeNullAtBuildtime;
  }
};

ELFLinkingContext::ELFLinkingContext(
    llvm::Triple triple, std::unique_ptr<TargetHandlerBase> targetHandler)
    : _outputELFType(llvm::ELF::ET_EXEC), _triple(triple),
      _targetHandler(std::move(targetHandler)), _baseAddress(0),
      _isStaticExecutable(false), _noInhibitExec(false), _exportDynamic(false),
      _mergeCommonStrings(false), _useShlibUndefines(true),
      _dynamicLinkerArg(false), _noAllowDynamicLibraries(false),
      _mergeRODataToTextSegment(true), _demangle(true),
      _stripSymbols(false), _alignSegments(true), _collectStats(false),
      _outputMagic(OutputMagic::DEFAULT), _initFunction("_init"),
      _finiFunction("_fini"), _sysrootPath("") {}

void ELFLinkingContext::addPasses(PassManager &pm) {
  pm.add(llvm::make_unique<elf::OrderPass>());
}

uint16_t ELFLinkingContext::getOutputMachine() const {
  switch (getTriple().getArch()) {
  case llvm::Triple::x86:
    return llvm::ELF::EM_386;
  case llvm::Triple::x86_64:
    return llvm::ELF::EM_X86_64;
  case llvm::Triple::hexagon:
    return llvm::ELF::EM_HEXAGON;
  case llvm::Triple::mipsel:
  case llvm::Triple::mips64el:
    return llvm::ELF::EM_MIPS;
  case llvm::Triple::aarch64:
    return llvm::ELF::EM_AARCH64;
  case llvm::Triple::arm:
    return llvm::ELF::EM_ARM;
  default:
    llvm_unreachable("Unhandled arch");
  }
}

StringRef ELFLinkingContext::entrySymbolName() const {
  if (_outputELFType == llvm::ELF::ET_EXEC && _entrySymbolName.empty())
    return "_start";
  return _entrySymbolName;
}

bool ELFLinkingContext::validateImpl(raw_ostream &diagnostics) {
  switch (outputFileType()) {
  case LinkingContext::OutputFileType::YAML:
    _writer = createWriterYAML(*this);
    break;
  case LinkingContext::OutputFileType::Native:
    llvm_unreachable("Unimplemented");
    break;
  default:
    _writer = createWriterELF(this->targetHandler());
    break;
  }

  // If -dead_strip, set up initial live symbols.
  if (deadStrip())
    addDeadStripRoot(entrySymbolName());
  return true;
}

bool ELFLinkingContext::isDynamic() const {
  switch (_outputELFType) {
  case llvm::ELF::ET_EXEC:
    return !_isStaticExecutable;
  case llvm::ELF::ET_DYN:
    return true;
  }
  return false;
}

bool ELFLinkingContext::isRelativeReloc(const Reference &) const {
  return false;
}

Writer &ELFLinkingContext::writer() const { return *_writer; }

static void buildSearchPath(SmallString<128> &path, StringRef dir,
                            StringRef sysRoot) {
  if (!dir.startswith("=/"))
    path.assign(dir);
  else {
    path.assign(sysRoot);
    path.append(dir.substr(1));
  }
}

ErrorOr<StringRef> ELFLinkingContext::searchLibrary(StringRef libName) const {
  bool hasColonPrefix = libName[0] == ':';
  SmallString<128> path;
  for (StringRef dir : _inputSearchPaths) {
    // Search for dynamic library
    if (!_isStaticExecutable) {
      buildSearchPath(path, dir, _sysrootPath);
      llvm::sys::path::append(path, hasColonPrefix
                                        ? libName.drop_front()
                                        : Twine("lib", libName) + ".so");
      if (llvm::sys::fs::exists(path.str()))
        return StringRef(*new (_allocator) std::string(path.str()));
    }
    // Search for static libraries too
    buildSearchPath(path, dir, _sysrootPath);
    llvm::sys::path::append(path, hasColonPrefix
                                      ? libName.drop_front()
                                      : Twine("lib", libName) + ".a");
    if (llvm::sys::fs::exists(path.str()))
      return StringRef(*new (_allocator) std::string(path.str()));
  }
  if (!llvm::sys::fs::exists(libName))
    return make_error_code(llvm::errc::no_such_file_or_directory);

  return libName;
}

ErrorOr<StringRef> ELFLinkingContext::searchFile(StringRef fileName,
                                                 bool isSysRooted) const {
  SmallString<128> path;
  if (llvm::sys::path::is_absolute(fileName) && isSysRooted) {
    path.assign(_sysrootPath);
    path.append(fileName);
    if (llvm::sys::fs::exists(path.str()))
      return StringRef(*new (_allocator) std::string(path.str()));
  } else if (llvm::sys::fs::exists(fileName))
    return fileName;

  if (llvm::sys::path::is_absolute(fileName))
    return make_error_code(llvm::errc::no_such_file_or_directory);

  for (StringRef dir : _inputSearchPaths) {
    buildSearchPath(path, dir, _sysrootPath);
    llvm::sys::path::append(path, fileName);
    if (llvm::sys::fs::exists(path.str()))
      return StringRef(*new (_allocator) std::string(path.str()));
  }
  return make_error_code(llvm::errc::no_such_file_or_directory);
}

void ELFLinkingContext::createInternalFiles(
    std::vector<std::unique_ptr<File>> &files) const {
  std::unique_ptr<SimpleFile> file(
      new SimpleFile("<internal file for --defsym>"));
  for (auto &i : getAbsoluteSymbols()) {
    StringRef sym = i.first;
    uint64_t val = i.second;
    file->addAtom(*(new (_allocator) CommandLineAbsoluteAtom(*file, sym, val)));
  }
  files.push_back(std::move(file));
  LinkingContext::createInternalFiles(files);
}

std::unique_ptr<File> ELFLinkingContext::createUndefinedSymbolFile() const {
  if (_initialUndefinedSymbols.empty())
    return nullptr;
  std::unique_ptr<SimpleFile> undefinedSymFile(
      new SimpleFile("command line option -u"));
  for (auto undefSymStr : _initialUndefinedSymbols)
    undefinedSymFile->addAtom(*(new (_allocator) CommandLineUndefinedAtom(
        *undefinedSymFile, undefSymStr)));
  return std::move(undefinedSymFile);
}

void ELFLinkingContext::notifySymbolTableCoalesce(const Atom *existingAtom,
                                                  const Atom *newAtom,
                                                  bool &useNew) {
  // First suppose that the `existingAtom` is defined
  // and the `newAtom` is undefined.
  auto *da = dyn_cast<DefinedAtom>(existingAtom);
  auto *ua = dyn_cast<UndefinedAtom>(newAtom);
  if (!da && !ua) {
    // Then try to reverse the assumption.
    da = dyn_cast<DefinedAtom>(newAtom);
    ua = dyn_cast<UndefinedAtom>(existingAtom);
  }

  if (da && ua && da->scope() == Atom::scopeGlobal &&
      isa<SharedLibraryFile>(ua->file()))
    // If strong defined atom coalesces away an atom declared
    // in the shared object the strong atom needs to be dynamically exported.
    // Save its name.
    _dynamicallyExportedSymbols.insert(ua->name());
}

std::string ELFLinkingContext::demangle(StringRef symbolName) const {
  if (!demangleSymbols())
    return symbolName;

  // Only try to demangle symbols that look like C++ symbols
  if (!symbolName.startswith("_Z"))
    return symbolName;

#if defined(HAVE_CXXABI_H)
  SmallString<256> symBuff;
  StringRef nullTermSym = Twine(symbolName).toNullTerminatedStringRef(symBuff);
  const char *cstr = nullTermSym.data();
  int status;
  char *demangled = abi::__cxa_demangle(cstr, nullptr, nullptr, &status);
  if (demangled != NULL) {
    std::string result(demangled);
    // __cxa_demangle() always uses a malloc'ed buffer to return the result.
    free(demangled);
    return result;
  }
#endif

  return symbolName;
}

} // end namespace lld
<|endoftext|>


<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

#include <node.h>
#include <map>

#include "keymapping.h"

namespace vscode_keyboard {

class KeyboardCodeToString {
public:
  static KeyboardCodeToString& GetInstance() {
    static KeyboardCodeToString instance;
    return instance;
  }

  std::string ToString(ui::KeyboardCode key_code) {
    std::map<int, std::string>::const_iterator it = keyboardCodeToStringMap.find(key_code);
    if (it == keyboardCodeToStringMap.end()) {
      // unknown key code?
      return "";
    }

    return it->second;
  }

private:
  std::map<int, std::string> keyboardCodeToStringMap;

  KeyboardCodeToString() : keyboardCodeToStringMap() {
    size_t cnt = sizeof(ui::gKeyboardCodeToStringMap) / sizeof(ui::gKeyboardCodeToStringMap[0]);
    for (size_t i = 0; i < cnt; ++i) {
      keyboardCodeToStringMap[ui::gKeyboardCodeToStringMap[i].first] = ui::gKeyboardCodeToStringMap[i].second;
    }
  }
};

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Array;
using v8::Value;

void AddEntry(Isolate* isolate, std::vector<Local<Object>> &result, std::string key_code, Local<String> value, Local<String> withShift, Local<String> withAltGr, Local<String> withShiftAltGr) {
  Local<Object> entry = Object::New(isolate);

  entry->Set(String::NewFromUtf8(isolate, "keyCode"), String::NewFromUtf8(isolate, key_code.c_str()));
  entry->Set(String::NewFromUtf8(isolate, "value"), value);
  entry->Set(String::NewFromUtf8(isolate, "withShift"), withShift);
  entry->Set(String::NewFromUtf8(isolate, "withAltGr"), withAltGr);
  entry->Set(String::NewFromUtf8(isolate, "withShiftAltGr"), withShiftAltGr);

  result.push_back(entry);
}

void GenerateEntries(Isolate* isolate, std::vector<Local<Object>> &result, std::vector<KeyMapping>::iterator it) {
  if (it->value.length() == 0 && it->withShift.length() == 0 && it->withAltGr.length() == 0 && it->withShiftAltGr.length() == 0) {
    return;
  }
  Local<String> keyValue = String::NewFromUtf8(isolate, it->value.c_str());
  Local<String> withShift = String::NewFromUtf8(isolate, it->withShift.c_str());
  Local<String> withAltGr = String::NewFromUtf8(isolate, it->withAltGr.c_str());
  Local<String> withShiftAltGr = String::NewFromUtf8(isolate, it->withShiftAltGr.c_str());
  std::string keyCode = KeyboardCodeToString::GetInstance().ToString(it->key_code);
  if (keyCode == "") {
    // unknown key code?
    return;
  }
  AddEntry(isolate, result, keyCode, keyValue, withShift, withAltGr, withShiftAltGr);
}

void _GetKeyMap(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();

  std::vector<KeyMapping> mapping = GetKeyMapping();

  std::vector<Local<Object>> result;
  for(std::vector<KeyMapping>::iterator it = mapping.begin(); it != mapping.end(); ++it) {
    GenerateEntries(isolate, result, it);
  }

  int resultCount = (int)result.size();
  Local<Array> resultArr = Array::New(isolate, resultCount);
  for (int index = 0; index < resultCount; index++) {
    resultArr->Set(index, result[index]);
  }

  args.GetReturnValue().Set(resultArr);
}

void init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "getKeyMap", _GetKeyMap);
  NODE_SET_METHOD(exports, "getCurrentKeyboardLayout", _GetCurrentKeyboardLayout);
}

NODE_MODULE(addon, init)

} // namespace vscode_keyboard
<commit_msg>Small tweaks<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

#include <node.h>
#include <map>

#include "keymapping.h"

namespace vscode_keyboard {

class KeyboardCodeToString {
public:
  static KeyboardCodeToString& GetInstance() {
    static KeyboardCodeToString instance;
    return instance;
  }

  std::string ToString(ui::KeyboardCode key_code) {
    std::map<int, std::string>::const_iterator it = keyboardCodeToStringMap.find(key_code);
    if (it == keyboardCodeToStringMap.end()) {
      // unknown key code?
      return "";
    }

    return it->second;
  }

private:
  std::map<int, std::string> keyboardCodeToStringMap;

  KeyboardCodeToString() : keyboardCodeToStringMap() {
    size_t cnt = sizeof(ui::gKeyboardCodeToStringMap) / sizeof(ui::gKeyboardCodeToStringMap[0]);
    for (size_t i = 0; i < cnt; ++i) {
      keyboardCodeToStringMap[ui::gKeyboardCodeToStringMap[i].first] = ui::gKeyboardCodeToStringMap[i].second;
    }
  }
};

using v8::FunctionCallbackInfo;
using v8::Isolate;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Array;
using v8::Value;

void _GetKeyMap(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<String> _keyCode = String::NewFromUtf8(isolate, "keyCode");
  Local<String> _value = String::NewFromUtf8(isolate, "value");
  Local<String> _withShift = String::NewFromUtf8(isolate, "withShift");
  Local<String> _withAltGr = String::NewFromUtf8(isolate, "withAltGr");
  Local<String> _withShiftAltGr = String::NewFromUtf8(isolate, "withShiftAltGr");

  std::vector<KeyMapping> mapping = GetKeyMapping();

  std::vector<Local<Object>> result;
  for(std::vector<KeyMapping>::iterator it = mapping.begin(); it != mapping.end(); ++it) {
    if (it->value.length() == 0 && it->withShift.length() == 0 && it->withAltGr.length() == 0 && it->withShiftAltGr.length() == 0) {
      continue;
    }

    std::string keyCode = KeyboardCodeToString::GetInstance().ToString(it->key_code);
    if (keyCode == "") {
      // unknown key code?
      continue;
    }

    Local<Object> entry = Object::New(isolate);

    entry->Set(_keyCode, String::NewFromUtf8(isolate, keyCode.c_str()));
    entry->Set(_value, String::NewFromUtf8(isolate, it->value.c_str()));
    entry->Set(_withShift, String::NewFromUtf8(isolate, it->withShift.c_str()));
    entry->Set(_withAltGr, String::NewFromUtf8(isolate, it->withAltGr.c_str()));
    entry->Set(_withShiftAltGr, String::NewFromUtf8(isolate, it->withShiftAltGr.c_str()));

    result.push_back(entry);
  }

  int resultCount = (int)result.size();
  Local<Array> resultArr = Array::New(isolate, resultCount);
  for (int index = 0; index < resultCount; index++) {
    resultArr->Set(index, result[index]);
  }

  args.GetReturnValue().Set(resultArr);
}

void init(Local<Object> exports) {
  NODE_SET_METHOD(exports, "getKeyMap", _GetKeyMap);
  NODE_SET_METHOD(exports, "getCurrentKeyboardLayout", _GetCurrentKeyboardLayout);
}

NODE_MODULE(addon, init)

} // namespace vscode_keyboard
<|endoftext|>


<commit_before>//
// Copyright(c) 2018 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

//
// latency.cpp : spdlog latency benchmarks
//

#include "benchmark/benchmark.h"

#include "spdlog/spdlog.h"
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"
#include <chrono>

#include "utils.h"
#include <atomic>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <string>
#include <thread>

using namespace std;
using namespace std::chrono;
using namespace spdlog;
using namespace spdlog::sinks;
using namespace utils;

void prepare_logdir()
{
    spdlog::info("Preparing logs_bench directory..");
#ifdef _WIN32
    system("if not exist logs mkdir logs_bench");
    system("del /F /Q logs\\*");
#else
    auto rv = system("mkdir -p logs_bench");
    if (rv != 0)
    {
        throw std::runtime_error("Failed to mkdir -p logs_bench");
    }
    rv = system("rm -f logs_bench/*");
    if (rv != 0)
    {
        throw std::runtime_error("Failed to rm -f logs_bench/*");
    }
#endif
}

void bench_c_string(benchmark::State& state, std::shared_ptr<spdlog::logger> logger)
{
    const char *msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra metus cursus "
                      "lacus placerat congue. Nulla egestas, mauris a tincidunt tempus, enim lectus volutpat mi, eu consequat sem "
                      "libero nec massa. In dapibus ipsum a diam rhoncus gravida. Etiam non dapibus eros. Donec fringilla dui sed "
                      "augue pretium, nec scelerisque est maximus. Nullam convallis, sem nec blandit maximus, nisi turpis ornare "
                      "nisl, sit amet volutpat neque massa eu odio. Maecenas malesuada quam ex, posuere congue nibh turpis duis.";

    for (auto _ : state)
    {
        logger->info(msg);
    }

}

void bench_logger(benchmark::State& state, std::shared_ptr<spdlog::logger> logger)
{
    int i = 0;
    for (auto _ : state)
    {
        logger->info("Hello logger: msg number {}...............", ++i);
    }
}

int main(int argc, char *argv[])
{

    using spdlog::sinks::null_sink_st ;
    using spdlog::sinks::null_sink_mt ;
    using spdlog::sinks::basic_file_sink_st;
    using spdlog::sinks::basic_file_sink_mt;

    size_t file_size = 30 * 1024 * 1024;
    size_t rotating_files = 5;
    int n_threads = 10;
    int iters = 1000000;

    prepare_logdir();

    //
    // Single threaded bench
    //
    auto null_logger = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_st>());

    benchmark::RegisterBenchmark("null_sink_st-500_bytes_cstr", bench_c_string, null_logger)
           ->UseRealTime()
           ->Iterations(iters);
    benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger)
            ->UseRealTime()
            ->Iterations(iters);

    // basic_st
    auto basic_st = spdlog::basic_logger_st("basic_st", "logs_bench/basic_st.log", true);
    benchmark::RegisterBenchmark("basic_st", bench_logger, std::move(basic_st))
            ->UseRealTime()
            ->Iterations(iters);
    spdlog::drop("basic_st");

    // rotating st
    auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs_bench/rotating_st.log", file_size, rotating_files);
    benchmark::RegisterBenchmark("rotating_st", bench_logger, std::move(rotating_st))
            ->UseRealTime()
            ->Iterations(iters);
    spdlog::drop("rotating_st");

    // daily st
    auto daily_st = spdlog::daily_logger_mt("daily_st", "logs_bench/daily_st.log");
    benchmark::RegisterBenchmark("daily_st", bench_logger, std::move(daily_st))
            ->UseRealTime()
            ->Iterations(iters);
    spdlog::drop("daily_st");

    //
    // Multi threaded bench, 10 using same logger concurrently
    //
    auto null_logger_mt = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_mt>());
    benchmark::RegisterBenchmark("null_sink_mt", bench_logger, null_logger_mt)
            ->Threads(n_threads)
            ->UseRealTime()
            ->Iterations(iters/n_threads);

    // basic_mt
    auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs_bench/basic_mt.log", true);
    benchmark::RegisterBenchmark("basic_mt", bench_logger, std::move(basic_mt))
            ->Threads(n_threads)
            ->UseRealTime()
            ->Iterations(iters/n_threads);
    spdlog::drop("basic_mt");

    // rotating mt
    auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs_bench/rotating_mt.log", file_size, rotating_files);
    benchmark::RegisterBenchmark("rotating_mt", bench_logger, std::move(rotating_mt))
            ->Threads(n_threads)
            ->UseRealTime()
            ->Iterations(iters/n_threads);
    spdlog::drop("rotating_mt");

    // daily mt
    auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs_bench/daily_mt.log");
    benchmark::RegisterBenchmark("daily_mt", bench_logger, std::move(daily_mt))
            ->Threads(n_threads)
            ->UseRealTime()
            ->Iterations(iters/n_threads);
    spdlog::drop("daily_mt");

    benchmark::Initialize(&argc, argv);
    benchmark::RunSpecifiedBenchmarks();

}
<commit_msg>Updated latency tests<commit_after>//
// Copyright(c) 2018 Gabi Melman.
// Distributed under the MIT License (http://opensource.org/licenses/MIT)
//

//
// latency.cpp : spdlog latency benchmarks
//

#include "benchmark/benchmark.h"

#include "spdlog/spdlog.h"
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/null_sink.h"
#include "spdlog/sinks/rotating_file_sink.h"

void prepare_logdir()
{
    spdlog::info("Preparing latency_logs directory..");
#ifdef _WIN32
    system("if not exist logs mkdir latency_logs");
    system("del /F /Q logs\\*");
#else
    auto rv = system("mkdir -p latency_logs");
    if (rv != 0)
    {
        throw std::runtime_error("Failed to mkdir -p latency_logs");
    }
    rv = system("rm -f latency_logs/*");
    if (rv != 0)
    {
        throw std::runtime_error("Failed to rm -f latency_logs/*");
    }
#endif
}

void bench_c_string(benchmark::State &state, std::shared_ptr<spdlog::logger> logger)
{
    const char *msg = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pharetra metus cursus "
                      "lacus placerat congue. Nulla egestas, mauris a tincidunt tempus, enim lectus volutpat mi, eu consequat sem "
                      "libero nec massa. In dapibus ipsum a diam rhoncus gravida. Etiam non dapibus eros. Donec fringilla dui sed "
                      "augue pretium, nec scelerisque est maximus. Nullam convallis, sem nec blandit maximus, nisi turpis ornare "
                      "nisl, sit amet volutpat neque massa eu odio. Maecenas malesuada quam ex, posuere congue nibh turpis duis.";

    for (auto _ : state)
    {
        logger->info(msg);
    }
}

void bench_logger(benchmark::State &state, std::shared_ptr<spdlog::logger> logger)
{
    int i = 0;
    for (auto _ : state)
    {
        logger->info("Hello logger: msg number {}...............", ++i);
    }
}

int main(int argc, char *argv[])
{

    spdlog::set_pattern("[tid %t] %v");
    using spdlog::sinks::basic_file_sink_mt;
    using spdlog::sinks::basic_file_sink_st;
    using spdlog::sinks::null_sink_mt;
    using spdlog::sinks::null_sink_st;

    size_t file_size = 30 * 1024 * 1024;
    size_t rotating_files = 5;
    int n_threads = benchmark::CPUInfo::Get().num_cpus;

    prepare_logdir();

    // Single threaded benchmarks
    auto disabled_logger = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_mt>());
    disabled_logger->set_level(spdlog::level::off);
    benchmark::RegisterBenchmark("disabled-level", bench_logger, disabled_logger)->UseRealTime();

    auto null_logger_st = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_st>());
    benchmark::RegisterBenchmark("null_sink_st (500_bytes c_str)", bench_c_string, std::move(null_logger_st))->UseRealTime();

    benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger_st);

    // basic_st
    auto basic_st = spdlog::basic_logger_st("basic_st", "latency_logs/basic_st.log", true);
    benchmark::RegisterBenchmark("basic_st", bench_logger, std::move(basic_st))->UseRealTime();
    spdlog::drop("basic_st");

    // rotating st
    auto rotating_st = spdlog::rotating_logger_st("rotating_st", "latency_logs/rotating_st.log", file_size, rotating_files);
    benchmark::RegisterBenchmark("rotating_st", bench_logger, std::move(rotating_st))->UseRealTime();
    spdlog::drop("rotating_st");

    // daily st
    auto daily_st = spdlog::daily_logger_mt("daily_st", "latency_logs/daily_st.log");
    benchmark::RegisterBenchmark("daily_st", bench_logger, std::move(daily_st))->UseRealTime();
    spdlog::drop("daily_st");

    //    //
    //    // Multi threaded bench, 10 loggers using same logger concurrently
    //    //
    auto null_logger_mt = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_mt>());
    benchmark::RegisterBenchmark("null_sink_mt", bench_logger, null_logger_mt)->Threads(n_threads)->UseRealTime();

    // basic_mt
    auto basic_mt = spdlog::basic_logger_mt("basic_mt", "latency_logs/basic_mt.log", true);
    benchmark::RegisterBenchmark("basic_mt", bench_logger, std::move(basic_mt))->Threads(n_threads)->UseRealTime();
    spdlog::drop("basic_mt");

    // rotating mt
    auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "latency_logs/rotating_mt.log", file_size, rotating_files);
    benchmark::RegisterBenchmark("rotating_mt", bench_logger, std::move(rotating_mt))->Threads(n_threads)->UseRealTime();
    spdlog::drop("rotating_mt");

    // daily mt
    auto daily_mt = spdlog::daily_logger_mt("daily_mt", "latency_logs/daily_mt.log");
    benchmark::RegisterBenchmark("daily_mt", bench_logger, std::move(daily_mt))->Threads(n_threads)->UseRealTime();
    spdlog::drop("daily_mt");

    // async
    auto queue_size = 1024 * 1024 * 3;
    auto tp = std::make_shared<spdlog::details::thread_pool>(queue_size, 1);
    auto async_logger = std::make_shared<spdlog::async_logger>(
        "async_logger", std::make_shared<null_sink_mt>(), std::move(tp), spdlog::async_overflow_policy::overrun_oldest);
    benchmark::RegisterBenchmark("async_logger", bench_logger, async_logger)->Threads(n_threads)->UseRealTime();

    benchmark::Initialize(&argc, argv);
    benchmark::RunSpecifiedBenchmarks();
}
<|endoftext|>


<commit_before>/*
 *
 * Author: Jeffrey Leung
 * Last edited: 2015-09-19
 *
 * This C++ file contains the implementation of the Labyrinth class, which uses
 * the Room class to create a 2-d mapping for a game.
 *
 */

#include <cmath>
#include <iostream>
#include <stdexcept>

#include "../include/room_properties.hpp"
#include "../include/room.hpp"
#include "../include/coordinate.hpp"
#include "../include/labyrinth.hpp"

// CONSTRUCTOR/DESTRUCTOR:

// Parameterized constructor
// An exception is thrown if:
//   A size of 0 is given (invalid_argument)
Labyrinth::Labyrinth( unsigned int x_size, unsigned int y_size )
{
  bool x_empty;
  if( x_size == 0 )
  {
    x_empty = true;
  }
  else
  {
    x_empty = false;
  }

  bool y_empty;
  if( y_size == 0 )
  {
    y_empty = true;
  }
  else
  {
    y_empty = false;
  }

  if( x_empty && y_empty )
  {
    throw std::invalid_argument( "Error: Labyrinth() was given empty x and "\
      "y sizes." );
  }
  else if( x_empty )
  {
    throw std::invalid_argument( "Error: Labyrinth() was given an empty "\
      "x size." );
  }
  else if( y_empty )
  {
    throw std::invalid_argument( "Error: Labyrinth() was given an empty "\
      "y size." );
  }

  rooms_ = new Room*[ y_size ];
  for( unsigned int i = 0; i < y_size; ++i )
  {
    rooms_[i] = new Room[ x_size ];
  }

  x_size_ = x_size;
  y_size_ = y_size;
}

// Destructor
Labyrinth::~Labyrinth()
{
  for( unsigned int i = 0; i < y_size_; ++i )
  {
    delete [] rooms_[i];
  }
  delete [] rooms_;
}

// SETUP:

// This method connects two Rooms by breaking their walls.
// An exception is thrown if:
//   The Rooms are already connected (logic_error)
//   The Rooms are the same (logic_error)
//   The Rooms are not adjacent (logic_error)
//   One or both Rooms are outside the Labyrinth (invalid_argument)
void Labyrinth::ConnectRooms( Coordinate rm_1, Coordinate rm_2 )
{
  if( rm_1 == rm_2 )
  {
    throw std::logic_error( "Error: ConnectRooms() was given the same "\
      "coordinate for the two Rooms." );
  }

  else if( !WithinBounds(rm_1) || !WithinBounds(rm_2) )
  {
    if( !WithinBounds(rm_1) )
    {
      if( !WithinBounds(rm_2) )
      {
        throw std::invalid_argument( "Error: ConnectRooms() was given invalid "\
          "coordinates for both rm_1 and rm_2." );
      }
      else
      {
        throw std::invalid_argument( "Error: ConnectRooms() was given "\
          "an invalid coordinate for rm_1." );
      }
    }

    else
    {
      throw std::invalid_argument( "Error: ConnectRooms() was given an "\
        "invalid coordinate for rm_2." );
    }
  }

  else if( !IsAdjacent(rm_1, rm_2) )
  {
    throw std::logic_error( "Error: ConnectRooms() was given two coordinates "\
      "which are not adjacent, and therefore cannot be connected." );
  }

  unsigned int x_distance = rm_2.x - rm_1.x;
  unsigned int y_distance = rm_2.y - rm_1.y;

  Direction break_wall_1;
  Direction break_wall_2;

  if( x_distance == 0 )
  {
    if( y_distance > 0 )  // rm_1 is north of rm_2
    {
      break_wall_1 = Direction::kSouth;
      break_wall_2 = Direction::kNorth;
    }
    else  // rm_1 is south of rm_2
    {
      break_wall_1 = Direction::kNorth;
      break_wall_2 = Direction::kSouth;
    }
  }

  else if( y_distance == 0 )
  {
    if( x_distance > 0 )  // rm_1 is west of rm_2
    {
      break_wall_1 = Direction::kEast;
      break_wall_2 = Direction::kWest;
    }
    else  // rm_1 is east of rm_2
    {
      break_wall_1 = Direction::kWest;
      break_wall_2 = Direction::kEast;
    }
  }

  else
  {
    throw std::logic_error( "Error: ConnectRooms() called IsAdjacent(), "\
      "which should have evaluated to false, but did not." );
  }

  RoomAt(rm_1).BreakWall(break_wall_1);
  RoomAt(rm_2).BreakWall(break_wall_2);
  return;
}

// PRIVATE METHODS:

// This private method returns a reference to the Room at the given
// coordinate.
// An exception is thrown if:
//   The Room is outside the Labyrinth (invalid_argument)
Room& Labyrinth::RoomAt( Coordinate rm )
{
  if( !WithinBounds(rm) )
  {
    throw std::invalid_argument( "Error: RoomAt() was given an invalid "\
      "coordinate for rm." );
  }
  return rooms_[rm.x][rm.y];
}

// This private method returns true if the Room is within the bounds of
// the Labyrinth, and false otherwise.
bool Labyrinth::WithinBounds( Coordinate rm )
{
  return(    0 < rm.x    &&
          rm.x < x_size_ &&
             0 < rm.y    &&
          rm.y < y_size_ );
}

// This private method returns true if the two Rooms are adjacent, and
// false otherwise.
// An exception is thrown if:
//   One or both Rooms are outside the Labyrinth (invalid_argument)
//   The same Room is given twice (logic_error)
bool Labyrinth::IsAdjacent( Coordinate rm_1, Coordinate rm_2 )
{
  if( !WithinBounds(rm_1) )
  {
    if( !WithinBounds(rm_2) )
    {
      throw std::invalid_argument( "Error: IsAdjacent() was given invalid "\
      "coordinates for both rm_1 and rm_2." );
    }
    else
    {
      throw std::invalid_argument( "Error: IsAdjacent() was given an invalid "\
      "coordinate for rm_1." );
    }
  }
  else if( !WithinBounds(rm_2) )
  {
    throw std::invalid_argument( "Error: IsAdjacent() was given an invalid "\
      "coordinate for rm_2." );
  }

  if( rm_1 == rm_2 )
  {
    throw std::logic_error( "Error: IsAdjacent() was given the same "\
      "coordinate for the Rooms." );
  }

  unsigned int x_distance = abs( rm_1.x - rm_2.x );
  unsigned int y_distance = abs( rm_1.y - rm_2.y );

  if( ( x_distance == 0 && y_distance == 1 ) ||
      ( x_distance == 1 && y_distance == 0 ) )
  {
    return true;
  }
  return false;
}
<commit_msg>Labyrinth: Making check for empty size more concise.<commit_after>/*
 *
 * Author: Jeffrey Leung
 * Last edited: 2015-09-19
 *
 * This C++ file contains the implementation of the Labyrinth class, which uses
 * the Room class to create a 2-d mapping for a game.
 *
 */

#include <cmath>
#include <iostream>
#include <stdexcept>

#include "../include/room_properties.hpp"
#include "../include/room.hpp"
#include "../include/coordinate.hpp"
#include "../include/labyrinth.hpp"

// CONSTRUCTOR/DESTRUCTOR:

// Parameterized constructor
// An exception is thrown if:
//   A size of 0 is given (invalid_argument)
Labyrinth::Labyrinth( unsigned int x_size, unsigned int y_size )
{
  if( x_size == 0 )
  {
    if( y_size == 0 )
    {
      throw std::invalid_argument( "Error: Labyrinth() was given empty x and "\
        "y sizes." );
    }
    else
    {
      throw std::invalid_argument( "Error: Labyrinth() was given an empty "\
        "x size." );
    }
  }
  else if( y_size == 0 )
  {
    throw std::invalid_argument( "Error: Labyrinth() was given an empty "\
      "y size." );
  }

  rooms_ = new Room*[ y_size ];
  for( unsigned int i = 0; i < y_size; ++i )
  {
    rooms_[i] = new Room[ x_size ];
  }

  x_size_ = x_size;
  y_size_ = y_size;
}

// Destructor
Labyrinth::~Labyrinth()
{
  for( unsigned int i = 0; i < y_size_; ++i )
  {
    delete [] rooms_[i];
  }
  delete [] rooms_;
}

// SETUP:

// This method connects two Rooms by breaking their walls.
// An exception is thrown if:
//   The Rooms are already connected (logic_error)
//   The Rooms are the same (logic_error)
//   The Rooms are not adjacent (logic_error)
//   One or both Rooms are outside the Labyrinth (invalid_argument)
void Labyrinth::ConnectRooms( Coordinate rm_1, Coordinate rm_2 )
{
  if( rm_1 == rm_2 )
  {
    throw std::logic_error( "Error: ConnectRooms() was given the same "\
      "coordinate for the two Rooms." );
  }

  else if( !WithinBounds(rm_1) || !WithinBounds(rm_2) )
  {
    if( !WithinBounds(rm_1) )
    {
      if( !WithinBounds(rm_2) )
      {
        throw std::invalid_argument( "Error: ConnectRooms() was given invalid "\
          "coordinates for both rm_1 and rm_2." );
      }
      else
      {
        throw std::invalid_argument( "Error: ConnectRooms() was given "\
          "an invalid coordinate for rm_1." );
      }
    }

    else
    {
      throw std::invalid_argument( "Error: ConnectRooms() was given an "\
        "invalid coordinate for rm_2." );
    }
  }

  else if( !IsAdjacent(rm_1, rm_2) )
  {
    throw std::logic_error( "Error: ConnectRooms() was given two coordinates "\
      "which are not adjacent, and therefore cannot be connected." );
  }

  unsigned int x_distance = rm_2.x - rm_1.x;
  unsigned int y_distance = rm_2.y - rm_1.y;

  Direction break_wall_1;
  Direction break_wall_2;

  if( x_distance == 0 )
  {
    if( y_distance > 0 )  // rm_1 is north of rm_2
    {
      break_wall_1 = Direction::kSouth;
      break_wall_2 = Direction::kNorth;
    }
    else  // rm_1 is south of rm_2
    {
      break_wall_1 = Direction::kNorth;
      break_wall_2 = Direction::kSouth;
    }
  }

  else if( y_distance == 0 )
  {
    if( x_distance > 0 )  // rm_1 is west of rm_2
    {
      break_wall_1 = Direction::kEast;
      break_wall_2 = Direction::kWest;
    }
    else  // rm_1 is east of rm_2
    {
      break_wall_1 = Direction::kWest;
      break_wall_2 = Direction::kEast;
    }
  }

  else
  {
    throw std::logic_error( "Error: ConnectRooms() called IsAdjacent(), "\
      "which should have evaluated to false, but did not." );
  }

  RoomAt(rm_1).BreakWall(break_wall_1);
  RoomAt(rm_2).BreakWall(break_wall_2);
  return;
}

// PRIVATE METHODS:

// This private method returns a reference to the Room at the given
// coordinate.
// An exception is thrown if:
//   The Room is outside the Labyrinth (invalid_argument)
Room& Labyrinth::RoomAt( Coordinate rm )
{
  if( !WithinBounds(rm) )
  {
    throw std::invalid_argument( "Error: RoomAt() was given an invalid "\
      "coordinate for rm." );
  }
  return rooms_[rm.x][rm.y];
}

// This private method returns true if the Room is within the bounds of
// the Labyrinth, and false otherwise.
bool Labyrinth::WithinBounds( Coordinate rm )
{
  return(    0 < rm.x    &&
          rm.x < x_size_ &&
             0 < rm.y    &&
          rm.y < y_size_ );
}

// This private method returns true if the two Rooms are adjacent, and
// false otherwise.
// An exception is thrown if:
//   One or both Rooms are outside the Labyrinth (invalid_argument)
//   The same Room is given twice (logic_error)
bool Labyrinth::IsAdjacent( Coordinate rm_1, Coordinate rm_2 )
{
  if( !WithinBounds(rm_1) )
  {
    if( !WithinBounds(rm_2) )
    {
      throw std::invalid_argument( "Error: IsAdjacent() was given invalid "\
      "coordinates for both rm_1 and rm_2." );
    }
    else
    {
      throw std::invalid_argument( "Error: IsAdjacent() was given an invalid "\
      "coordinate for rm_1." );
    }
  }
  else if( !WithinBounds(rm_2) )
  {
    throw std::invalid_argument( "Error: IsAdjacent() was given an invalid "\
      "coordinate for rm_2." );
  }

  if( rm_1 == rm_2 )
  {
    throw std::logic_error( "Error: IsAdjacent() was given the same "\
      "coordinate for the Rooms." );
  }

  unsigned int x_distance = abs( rm_1.x - rm_2.x );
  unsigned int y_distance = abs( rm_1.y - rm_2.y );

  if( ( x_distance == 0 && y_distance == 1 ) ||
      ( x_distance == 1 && y_distance == 0 ) )
  {
    return true;
  }
  return false;
}
<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	cursor.cxx
 *
 *   DESCRIPTION
 *      implementation of the pqxx::Cursor class.
 *   pqxx::Cursor represents a database cursor.
 *
 * Copyright (c) 2001-2004, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#include "pqxx/compiler.h"

#include <cstdlib>

#include "pqxx/cursor"
#include "pqxx/result"
#include "pqxx/transaction"

using namespace PGSTD;

int pqxx::cursor_base::get_unique_cursor_num()
{
  if (!m_context) throw logic_error("libpqxx internal error: "
      "cursor in get_unique_cursor_num() has no transaction");
  return m_context->GetUniqueCursorNum();
}

unsigned char pqxx::cursor_base::s_dummy;

pqxx::icursorstream::icursorstream(pqxx::transaction_base &context,
    const string &query,
    const string &basename,
    size_type stride) :
  cursor_base(&context, basename),
  m_stride(stride)
{
  set_stride(stride);
  declare(query);
}

void pqxx::icursorstream::set_stride(size_type n)
{
  if (n < 1)
    throw invalid_argument("Attempt to set cursor stride to " + to_string(n));
  m_stride = n;
}

void pqxx::icursorstream::declare(const string &query)
{
  m_context->exec("DECLARE \"" + name() + "\" "
      		"NO SCROLL CURSOR FOR " + query + " FOR READ ONLY",
	"[DECLARE "+name()+"]");
}

pqxx::result pqxx::icursorstream::fetch()
{
  result r(m_context->exec("FETCH "+to_string(m_stride)+" IN \""+name()+"\""));
  if (r.empty()) m_done = true;
  return r;
}

pqxx::icursorstream &pqxx::icursorstream::ignore(streamsize n)
{
  m_context->exec("MOVE " + to_string(n) + " IN \"" + name() + "\"");
  return *this;
}

<commit_msg>Fixed incompatibility with pre-7.4 backends<commit_after>/*-------------------------------------------------------------------------
 *
 *   FILE
 *	cursor.cxx
 *
 *   DESCRIPTION
 *      implementation of the pqxx::Cursor class.
 *   pqxx::Cursor represents a database cursor.
 *
 * Copyright (c) 2001-2004, Jeroen T. Vermeulen <jtv@xs4all.nl>
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 *
 *-------------------------------------------------------------------------
 */
#include "pqxx/compiler.h"

#include <cstdlib>

#include "pqxx/cursor"
#include "pqxx/result"
#include "pqxx/transaction"

using namespace PGSTD;

int pqxx::cursor_base::get_unique_cursor_num()
{
  if (!m_context) throw logic_error("libpqxx internal error: "
      "cursor in get_unique_cursor_num() has no transaction");
  return m_context->GetUniqueCursorNum();
}

unsigned char pqxx::cursor_base::s_dummy;

pqxx::icursorstream::icursorstream(pqxx::transaction_base &context,
    const string &query,
    const string &basename,
    size_type stride) :
  cursor_base(&context, basename),
  m_stride(stride)
{
  set_stride(stride);
  declare(query);
}

void pqxx::icursorstream::set_stride(size_type n)
{
  if (n < 1)
    throw invalid_argument("Attempt to set cursor stride to " + to_string(n));
  m_stride = n;
}

void pqxx::icursorstream::declare(const string &query)
{
  // TODO: Add NO SCROLL if backend supports it (7.4 or better)
  stringstream cq, qn;
  cq << "DECLARE \"" << name() << "\" CURSOR FOR " << query << " FOR READ ONLY";
  qn << "[DECLARE " << name() << ']';
  m_context->exec(cq, qn.str());
}

pqxx::result pqxx::icursorstream::fetch()
{
  result r(m_context->exec("FETCH "+to_string(m_stride)+" IN \""+name()+"\""));
  if (r.empty()) m_done = true;
  return r;
}

pqxx::icursorstream &pqxx::icursorstream::ignore(streamsize n)
{
  m_context->exec("MOVE " + to_string(n) + " IN \"" + name() + "\"");
  return *this;
}

<|endoftext|>


<commit_before>#include "lib/Scope.h"
#include "lib/Function.h"

namespace snow {
	Scope::Scope(const Handle<Function>& func) :
		ThinObject(scope_prototype()),
		m_Function(func)
	{
		m_Locals = new Array;
	}

	bool Scope::has_local(const std::string& name) {
		if (name == "self") {
			return m_Self != NULL;
		} else {
			return local_map().find(name) != local_map().end();
		}
	}

	VALUE Scope::get_local(const std::string& name) {
		if (name == "self" && m_Self != NULL)
			return m_Self;

		auto iter = local_map().find(name);
		if (iter == local_map().end())
			return nil();

		auto idx = iter->second;
		return m_Locals->get_by_index(idx);
	}

	VALUE Scope::set_local(const std::string& name, const ValueHandle& val) {
		if (name == "self") {
			error("Trying to set `self'!");
			TRAP();
		}

		auto iter = local_map().find(name);
		int64_t idx;
		if (iter == local_map().end()) {
			idx = local_map().size();
			local_map()[name] = idx;
		} else {
			idx = iter->second;
		}

		return m_Locals->set_by_index(idx, val);
	}

	static Handle<Object> ScopePrototype;

	// TODO: Some more scope prototype functions.

	Handle<Object>& scope_prototype() {
		if (ScopePrototype)
			goto done;
		ScopePrototype = new Object;
done:
		return ScopePrototype;
	}
}<commit_msg>ScopePrototype tiny cleanup fix<commit_after>#include "lib/Scope.h"
#include "lib/Function.h"

namespace snow {
	Scope::Scope(const Handle<Function>& func) :
		ThinObject(scope_prototype()),
		m_Function(func)
	{
		m_Locals = new Array;
	}

	bool Scope::has_local(const std::string& name) {
		if (name == "self") {
			return m_Self != NULL;
		} else {
			return local_map().find(name) != local_map().end();
		}
	}

	VALUE Scope::get_local(const std::string& name) {
		if (name == "self" && m_Self != NULL)
			return m_Self;

		auto iter = local_map().find(name);
		if (iter == local_map().end())
			return nil();

		auto idx = iter->second;
		return m_Locals->get_by_index(idx);
	}

	VALUE Scope::set_local(const std::string& name, const ValueHandle& val) {
		if (name == "self") {
			error("Trying to set `self'!");
			TRAP();
		}

		auto iter = local_map().find(name);
		int64_t idx;
		if (iter == local_map().end()) {
			idx = local_map().size();
			local_map()[name] = idx;
		} else {
			idx = iter->second;
		}

		return m_Locals->set_by_index(idx, val);
	}

	static Handle<Object> ScopePrototype = NULL;

	// TODO: Some more scope prototype functions.

	Handle<Object>& scope_prototype() {
		if (ScopePrototype)
			return ScopePrototype;
		ScopePrototype = new Object;
		return ScopePrototype;
	}
}<|endoftext|>


<commit_before><commit_msg>grr vc++<commit_after><|endoftext|>