<commit_before>// -------------------------------------------------------------------------
//    @FileName			:    NFCLogModule.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-12-15
//    @Module           :    NFCLogModule
//    @Desc             :
// -------------------------------------------------------------------------

#define GLOG_NO_ABBREVIATED_SEVERITIES
#include <stdarg.h>
#include "NFCLogModule.h"
#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

unsigned int NFCLogModule::idx = 0;

bool NFCLogModule::CheckLogFileExist(const char* filename)
{
    std::stringstream stream;
    stream << filename << "." << ++idx;
    std::fstream file;
    file.open(stream.str(), std::ios::in);
    if (file)
    {
        return CheckLogFileExist(filename);
    }

    return false;
}

void NFCLogModule::rolloutHandler(const char* filename, std::size_t size)
{
    std::stringstream stream;
    if (!CheckLogFileExist(filename))
    {
        stream << filename << "." << idx;
        rename(filename, stream.str().c_str());
    }
}

NFCLogModule::NFCLogModule(NFIPluginManager* p)
{
    pPluginManager = p;
}

bool NFCLogModule::Init()
{
    mnLogCountTotal = 0;

    el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);
    el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);
#if NF_PLATFORM == NF_PLATFORM_WIN
    el::Configurations conf("log_win.conf");
#else
    el::Configurations conf("log.conf");
#endif
    el::Loggers::reconfigureAllLoggers(conf);
    el::Helpers::installPreRollOutCallback(rolloutHandler);

    return true;
}

bool NFCLogModule::Shut()
{
    el::Helpers::uninstallPreRollOutCallback();

    return true;
}

bool NFCLogModule::BeforeShut()
{
    return true;

}

bool NFCLogModule::AfterInit()
{
    return true;

}

bool NFCLogModule::Execute()
{
    return true;

}

bool NFCLogModule::Log(const NF_LOG_LEVEL nll, const char* format, ...)
{
    mnLogCountTotal++;

    char szBuffer[1024 * 10] = {0};

    va_list args;
    va_start(args, format);
    vsnprintf(szBuffer, sizeof(szBuffer) - 1, format, args);
    va_end(args);

    switch (nll)
    {
        case NFILogModule::NLL_DEBUG_NORMAL:
            LOG(DEBUG) << mnLogCountTotal << " | " << szBuffer;
            break;
        case NFILogModule::NLL_INFO_NORMAL:
            LOG(INFO) << mnLogCountTotal << " | " << szBuffer;
            break;
        case NFILogModule::NLL_WARING_NORMAL:
            LOG(WARNING) << mnLogCountTotal << " | " << szBuffer;
            break;
        case NFILogModule::NLL_ERROR_NORMAL:
        {
            LOG(ERROR) << mnLogCountTotal << " | " << szBuffer;
            //LogStack();
        }
        break;
        case NFILogModule::NLL_FATAL_NORMAL:
            LOG(FATAL) << mnLogCountTotal << " | " << szBuffer;
            break;
        default:
            LOG(INFO) << mnLogCountTotal << " | " << szBuffer;
            break;
    }

    return true;
}

bool NFCLogModule::LogElement(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strElement, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[ELEMENT] Indent[%s] Element[%s] %s %s %d", ident.ToString().c_str(), strElement.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[ELEMENT] Indent[%s] Element[%s] %s", ident.ToString().c_str(), strElement.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogProperty(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strProperty, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[PROPERTY] Indent[%s] Property[%s] %s %s %d", ident.ToString().c_str(), strProperty.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[PROPERTY] Indent[%s] Property[%s] %s", ident.ToString().c_str(), strProperty.c_str(), strDesc.c_str());
    }

    return true;

}

bool NFCLogModule::LogRecord(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strRecord, const std::string& strDesc, const int nRow, const int nCol, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] Row[%d] Col[%d] %s %s %d", ident.ToString().c_str(), strRecord.c_str(), nRow, nCol, strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] Row[%d] Col[%d] %s", ident.ToString().c_str(), strRecord.c_str(), nRow, nCol, strDesc.c_str());
    }

    return true;

}

bool NFCLogModule::LogRecord(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strRecord, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] %s %s %d", ident.ToString().c_str(), strRecord.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] %s", ident.ToString().c_str(), strRecord.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogObject(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[OBJECT] Indent[%s] %s %s %d", ident.ToString().c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[OBJECT] Indent[%s] %s", ident.ToString().c_str(), strDesc.c_str());
    }

    return true;

}

void NFCLogModule::LogStack()
{

    //To Add
    /*
    #ifdef NF_DEBUG_MODE
    time_t t = time(0);
    char szDmupName[MAX_PATH];
    tm* ptm = localtime(&t);

    sprintf(szDmupName, "%d_%d_%d_%d_%d_%d.dmp",  ptm->tm_year + 1900, ptm->tm_mon, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    // 创建Dump文件
    HANDLE hDumpFile = CreateFile(szDmupName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // Dump信息
    MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
    //dumpInfo.ExceptionPointers = pException;
    dumpInfo.ThreadId = GetCurrentThreadId();
    dumpInfo.ClientPointers = TRUE;

    // 写入Dump文件内容
    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

    CloseHandle(hDumpFile);

    #endif
    */
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %s %d", ident.ToString().c_str(), strInfo.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s %s", ident.ToString().c_str(), strInfo.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const int nDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %d %s %d", ident.ToString().c_str(), strInfo.c_str(), nDesc, func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s %d", ident.ToString().c_str(), strInfo.c_str(), nDesc);
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::ostringstream& stream, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %d", ident.ToString().c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s", ident.ToString().c_str());
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const char* func /*= ""*/, int line /*= 0*/)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %d", ident.ToString().c_str(), strInfo.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s", ident.ToString().c_str(), strInfo.c_str());
    }

    return true;
}

bool NFCLogModule::LogDebugFunctionDump(const NFGUID ident, const int nMsg, const std::string& strArg,  const char* func /*= ""*/, const int line /*= 0*/)
{
    //#ifdef NF_DEBUG_MODE
    LogNormal(NFILogModule::NLL_WARING_NORMAL, ident, strArg + "MsgID:", nMsg, func, line);
    //#endif
    return true;
}

bool NFCLogModule::ChangeLogLevel(const std::string& strLevel)
{
    el::Level logLevel = el::LevelHelper::convertFromString(strLevel.c_str());
    el::Logger* pLogger = el::Loggers::getLogger("default");
    if (NULL == pLogger)
    {
        return false;
    }

    el::Configurations* pConfigurations = pLogger->configurations();
    el::base::TypedConfigurations* pTypeConfigurations = pLogger->typedConfigurations();
    if (NULL == pConfigurations)
    {
        return false;
    }

    // log级别为debug, info, warning, error, fatal(级别逐渐提高)
    // 当传入为info时，则高于(包含)info的级别会输出
    // !!!!!! NOTICE:故意没有break，请千万注意 !!!!!!
    switch (logLevel)
    {
        case el::Level::Fatal:
        {
            el::Configuration errorConfiguration(el::Level::Error, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&errorConfiguration);
        }
        case el::Level::Error:
        {
            el::Configuration warnConfiguration(el::Level::Warning, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&warnConfiguration);
        }
        case el::Level::Warning:
        {
            el::Configuration infoConfiguration(el::Level::Info, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&infoConfiguration);
        }
        case el::Level::Info:
        {
            el::Configuration debugConfiguration(el::Level::Debug, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&debugConfiguration);

        }
        case el::Level::Debug:
            break;
        default:
            break;
    }

    el::Loggers::reconfigureAllLoggers(*pConfigurations);
    LogNormal(NFILogModule::NLL_INFO_NORMAL, NFGUID(), "[Log] Change log level", strLevel, __FUNCTION__, __LINE__);
    return true;
}
<commit_msg>log bug fix<commit_after>// -------------------------------------------------------------------------
//    @FileName			:    NFCLogModule.cpp
//    @Author           :    LvSheng.Huang
//    @Date             :    2012-12-15
//    @Module           :    NFCLogModule
//    @Desc             :
// -------------------------------------------------------------------------

#define GLOG_NO_ABBREVIATED_SEVERITIES
#include <stdarg.h>
#include "NFCLogModule.h"
#include "easylogging++.h"

INITIALIZE_EASYLOGGINGPP

unsigned int NFCLogModule::idx = 0;

bool NFCLogModule::CheckLogFileExist(const char* filename)
{
    std::stringstream stream;
    stream << filename << "." << ++idx;
    std::fstream file;
    file.open(stream.str(), std::ios::in);
    if (file)
    {
        return CheckLogFileExist(filename);
    }

    return false;
}

void NFCLogModule::rolloutHandler(const char* filename, std::size_t size)
{
    std::stringstream stream;
    if (!CheckLogFileExist(filename))
    {
        stream << filename << "." << idx;
        rename(filename, stream.str().c_str());
    }
}

NFCLogModule::NFCLogModule(NFIPluginManager* p)
{
    pPluginManager = p;
}

bool NFCLogModule::Init()
{
    mnLogCountTotal = 0;

    el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);
    el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);
#if NF_PLATFORM == NF_PLATFORM_WIN
    el::Configurations conf("log_win.conf");
#else
    el::Configurations conf("log.conf");
#endif
    el::Loggers::reconfigureAllLoggers(conf);
    el::Helpers::installPreRollOutCallback(rolloutHandler);

    return true;
}

bool NFCLogModule::Shut()
{
    el::Helpers::uninstallPreRollOutCallback();

    return true;
}

bool NFCLogModule::BeforeShut()
{
    return true;

}

bool NFCLogModule::AfterInit()
{
    return true;

}

bool NFCLogModule::Execute()
{
    return true;

}

bool NFCLogModule::Log(const NF_LOG_LEVEL nll, const char* format, ...)
{
    mnLogCountTotal++;

    char szBuffer[1024 * 10] = {0};

    va_list args;
    va_start(args, format);
    vsnprintf(szBuffer, sizeof(szBuffer) - 1, format, args);
    va_end(args);

    switch (nll)
    {
        case NFILogModule::NLL_DEBUG_NORMAL:
            LOG(DEBUG) << mnLogCountTotal << " | " << szBuffer;
            break;
        case NFILogModule::NLL_INFO_NORMAL:
            LOG(INFO) << mnLogCountTotal << " | " << szBuffer;
            break;
        case NFILogModule::NLL_WARING_NORMAL:
            LOG(WARNING) << mnLogCountTotal << " | " << szBuffer;
            break;
        case NFILogModule::NLL_ERROR_NORMAL:
        {
            LOG(ERROR) << mnLogCountTotal << " | " << szBuffer;
            //LogStack();
        }
        break;
        case NFILogModule::NLL_FATAL_NORMAL:
            LOG(FATAL) << mnLogCountTotal << " | " << szBuffer;
            break;
        default:
            LOG(INFO) << mnLogCountTotal << " | " << szBuffer;
            break;
    }

    return true;
}

bool NFCLogModule::LogElement(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strElement, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[ELEMENT] Indent[%s] Element[%s] %s %s %d", ident.ToString().c_str(), strElement.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[ELEMENT] Indent[%s] Element[%s] %s", ident.ToString().c_str(), strElement.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogProperty(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strProperty, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[PROPERTY] Indent[%s] Property[%s] %s %s %d", ident.ToString().c_str(), strProperty.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[PROPERTY] Indent[%s] Property[%s] %s", ident.ToString().c_str(), strProperty.c_str(), strDesc.c_str());
    }

    return true;

}

bool NFCLogModule::LogRecord(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strRecord, const std::string& strDesc, const int nRow, const int nCol, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] Row[%d] Col[%d] %s %s %d", ident.ToString().c_str(), strRecord.c_str(), nRow, nCol, strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] Row[%d] Col[%d] %s", ident.ToString().c_str(), strRecord.c_str(), nRow, nCol, strDesc.c_str());
    }

    return true;

}

bool NFCLogModule::LogRecord(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strRecord, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] %s %s %d", ident.ToString().c_str(), strRecord.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[RECORD] Indent[%s] Record[%s] %s", ident.ToString().c_str(), strRecord.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogObject(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "[OBJECT] Indent[%s] %s %s %d", ident.ToString().c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "[OBJECT] Indent[%s] %s", ident.ToString().c_str(), strDesc.c_str());
    }

    return true;

}

void NFCLogModule::LogStack()
{

    //To Add
    /*
    #ifdef NF_DEBUG_MODE
    time_t t = time(0);
    char szDmupName[MAX_PATH];
    tm* ptm = localtime(&t);

    sprintf(szDmupName, "%d_%d_%d_%d_%d_%d.dmp",  ptm->tm_year + 1900, ptm->tm_mon, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
    // 创建Dump文件
    HANDLE hDumpFile = CreateFile(szDmupName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    // Dump信息
    MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
    //dumpInfo.ExceptionPointers = pException;
    dumpInfo.ThreadId = GetCurrentThreadId();
    dumpInfo.ClientPointers = TRUE;

    // 写入Dump文件内容
    MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpNormal, &dumpInfo, NULL, NULL);

    CloseHandle(hDumpFile);

    #endif
    */
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const std::string& strDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %s %d", ident.ToString().c_str(), strInfo.c_str(), strDesc.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s %s", ident.ToString().c_str(), strInfo.c_str(), strDesc.c_str());
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const int nDesc, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %d %s %d", ident.ToString().c_str(), strInfo.c_str(), nDesc, func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s %d", ident.ToString().c_str(), strInfo.c_str(), nDesc);
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::ostringstream& stream, const char* func, int line)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %d", ident.ToString().c_str(), stream.str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s", ident.ToString().c_str(), stream.str());
    }

    return true;
}

bool NFCLogModule::LogNormal(const NF_LOG_LEVEL nll, const NFGUID ident, const std::string& strInfo, const char* func /*= ""*/, int line /*= 0*/)
{
    if (line > 0)
    {
        Log(nll, "Indent[%s] %s %s %d", ident.ToString().c_str(), strInfo.c_str(), func, line);
    }
    else
    {
        Log(nll, "Indent[%s] %s", ident.ToString().c_str(), strInfo.c_str());
    }

    return true;
}

bool NFCLogModule::LogDebugFunctionDump(const NFGUID ident, const int nMsg, const std::string& strArg,  const char* func /*= ""*/, const int line /*= 0*/)
{
    //#ifdef NF_DEBUG_MODE
    LogNormal(NFILogModule::NLL_WARING_NORMAL, ident, strArg + "MsgID:", nMsg, func, line);
    //#endif
    return true;
}

bool NFCLogModule::ChangeLogLevel(const std::string& strLevel)
{
    el::Level logLevel = el::LevelHelper::convertFromString(strLevel.c_str());
    el::Logger* pLogger = el::Loggers::getLogger("default");
    if (NULL == pLogger)
    {
        return false;
    }

    el::Configurations* pConfigurations = pLogger->configurations();
    el::base::TypedConfigurations* pTypeConfigurations = pLogger->typedConfigurations();
    if (NULL == pConfigurations)
    {
        return false;
    }

    // log级别为debug, info, warning, error, fatal(级别逐渐提高)
    // 当传入为info时，则高于(包含)info的级别会输出
    // !!!!!! NOTICE:故意没有break，请千万注意 !!!!!!
    switch (logLevel)
    {
        case el::Level::Fatal:
        {
            el::Configuration errorConfiguration(el::Level::Error, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&errorConfiguration);
        }
        case el::Level::Error:
        {
            el::Configuration warnConfiguration(el::Level::Warning, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&warnConfiguration);
        }
        case el::Level::Warning:
        {
            el::Configuration infoConfiguration(el::Level::Info, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&infoConfiguration);
        }
        case el::Level::Info:
        {
            el::Configuration debugConfiguration(el::Level::Debug, el::ConfigurationType::Enabled, "false");
            pConfigurations->set(&debugConfiguration);

        }
        case el::Level::Debug:
            break;
        default:
            break;
    }

    el::Loggers::reconfigureAllLoggers(*pConfigurations);
    LogNormal(NFILogModule::NLL_INFO_NORMAL, NFGUID(), "[Log] Change log level", strLevel, __FUNCTION__, __LINE__);
    return true;
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "PyEvents.h"
#include "PyBZFlag.h"

namespace Python
{

void
PythonHandler::emit (PyObject *arglist, int event)
{
	PyObject *listeners = parent->GetListeners (event);

	if (listeners == NULL || !PyList_Check(listeners)) {
		// FIXME - throw error
		fprintf (stderr, "tick listeners is not a list!\n");
		return;
	}

	// Call out
	int size = PyList_Size (listeners);
	for (int i = 0; i < size; i++) {
		PyObject *handler = PyList_GetItem (listeners, i);
		if (!PyCallable_Check (handler)) {
			// FIXME - throw error
			fprintf (stderr, "%d listener is not callable\n", event);
			Py_DECREF (arglist);
			return;
		}
		PyErr_Clear ();
		PyEval_CallObject (handler, arglist);
		if (PyErr_Occurred ()) {
			PyErr_Print ();
			return;
		}
	}
}

void
CaptureHandler::process (bz_EventData *eventData)
{
	bz_CTFCaptureEventData *ced = (bz_CTFCaptureEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("(iii(fff)fd",
			ced->teamCaped,
			ced->teamCaping,
			ced->playerCaping,
			ced->pos[0],
			ced->pos[1],
			ced->pos[2],
			ced->rot,
			ced->time);
	emit (arglist, bz_eCaptureEvent);
	Py_DECREF (arglist);
}

void
DieHandler::process (bz_EventData *eventData)
{
	bz_PlayerDieEventData *pded = (bz_PlayerDieEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("iiiis(fff)fd",
			pded->playerID,
			pded->teamID,
			pded->killerID,
			pded->killerTeamID,
			pded->flagKilledWith.c_str(),
			pded->pos[0],
			pded->pos[1],
			pded->pos[2],
			pded->rot,
			pded->time);
	emit (arglist, bz_ePlayerDieEvent);
	Py_DECREF (arglist);
}

void
SpawnHandler::process (bz_EventData *eventData)
{
	bz_PlayerSpawnEventData *psed = (bz_PlayerSpawnEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("ii(fff)fd",
			psed->playerID,
			psed->teamID,
			psed->pos[0],
			psed->pos[1],
			psed->pos[2],
			psed->rot,
			psed->time);
	emit (arglist, bz_ePlayerSpawnEvent);
	Py_DECREF (arglist);
}

void
ZoneEntryHandler::process (bz_EventData *eventData)
{
	emit (NULL /* FIXME? */, bz_eZoneEntryEvent);
}

void
ZoneExitHandler::process (bz_EventData *eventData)
{
	emit (NULL /* FIXME? */, bz_eZoneExitEvent);
}

void
JoinHandler::process (bz_EventData *eventData)
{
	bz_PlayerJoinPartEventData *pjped = (bz_PlayerJoinPartEventData*) eventData;
	parent->AddPlayer (pjped->playerID);

	PyObject *arglist = Py_BuildValue ("iissd",
			pjped->playerID,
			pjped->teamID,
			pjped->callsign.c_str (),
			pjped->reason.c_str (),
			pjped->time);

	emit (arglist, bz_ePlayerJoinEvent);
	Py_DECREF (arglist);
}

void
PartHandler::process (bz_EventData *eventData)
{
	bz_PlayerJoinPartEventData *pjped = (bz_PlayerJoinPartEventData*) eventData;
	parent->RemovePlayer (pjped->playerID);

	PyObject *arglist = Py_BuildValue ("iissd",
			pjped->playerID,
			pjped->teamID,
			pjped->callsign.c_str (),
			pjped->reason.c_str (),
			pjped->time);

	emit (arglist, bz_ePlayerPartEvent);
	Py_DECREF (arglist);
}

void
ChatHandler::process (bz_EventData *eventData)
{
	bz_ChatEventData *ced = (bz_ChatEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("iisd",
			ced->from,
			ced->to,
			ced->message.c_str (),
			ced->time);
	emit (arglist, bz_eChatMessageEvent);
	Py_DECREF (arglist);
}

void
UnknownSlashHandler::process (bz_EventData *eventData)
{
	bz_UnknownSlashCommandEventData *usced = (bz_UnknownSlashCommandEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("iosd",
			usced->from,
			usced->handled ? Py_True : Py_False,
			usced->message.c_str (),
			usced->time);
	emit (arglist, bz_eUnknownSlashCommand);
	Py_DECREF (arglist);
}

void
TickHandler::process (bz_EventData *eventData)
{
	bz_TickEventData *ted = (bz_TickEventData*) eventData;

	PyObject *arglist = Py_BuildValue ("(d)", ted->time);
	emit (arglist, bz_eTickEvent);
	Py_DECREF (arglist);
}

};
<commit_msg>finish adding event handlers. haven't yet figured out how to do the events which pass data back into bzfs<commit_after>/* bzflag
 * Copyright (c) 1993 - 2005 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "PyEvents.h"
#include "PyBZFlag.h"

namespace Python
{

void
PythonHandler::emit (PyObject *arglist, int event)
{
	PyObject *listeners = parent->GetListeners (event);

	if (listeners == NULL || !PyList_Check(listeners)) {
		// FIXME - throw error
		fprintf (stderr, "tick listeners is not a list!\n");
		return;
	}

	// Call out
	int size = PyList_Size (listeners);
	for (int i = 0; i < size; i++) {
		PyObject *handler = PyList_GetItem (listeners, i);
		if (!PyCallable_Check (handler)) {
			// FIXME - throw error
			fprintf (stderr, "%d listener is not callable\n", event);
			Py_DECREF (arglist);
			return;
		}
		PyErr_Clear ();
		PyEval_CallObject (handler, arglist);
		if (PyErr_Occurred ()) {
			PyErr_Print ();
			return;
		}
	}
}

void
CaptureHandler::process (bz_EventData *eventData)
{
	bz_CTFCaptureEventData *ced = (bz_CTFCaptureEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("(iii(fff)fd)",
			ced->teamCaped,
			ced->teamCaping,
			ced->playerCaping,
			ced->pos[0],
			ced->pos[1],
			ced->pos[2],
			ced->rot,
			ced->time);
	emit (arglist, bz_eCaptureEvent);
	Py_DECREF (arglist);
}

void
DieHandler::process (bz_EventData *eventData)
{
	bz_PlayerDieEventData *pded = (bz_PlayerDieEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("(iiiis(fff)fd)",
			pded->playerID,
			pded->teamID,
			pded->killerID,
			pded->killerTeamID,
			pded->flagKilledWith.c_str(),
			pded->pos[0],
			pded->pos[1],
			pded->pos[2],
			pded->rot,
			pded->time);
	emit (arglist, bz_ePlayerDieEvent);
	Py_DECREF (arglist);
}

void
SpawnHandler::process (bz_EventData *eventData)
{
	bz_PlayerSpawnEventData *psed = (bz_PlayerSpawnEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("(ii(fff)fd)",
			psed->playerID,
			psed->teamID,
			psed->pos[0],
			psed->pos[1],
			psed->pos[2],
			psed->rot,
			psed->time);
	emit (arglist, bz_ePlayerSpawnEvent);
	Py_DECREF (arglist);
}

void
ZoneEntryHandler::process (bz_EventData *eventData)
{
	emit (NULL /* FIXME? */, bz_eZoneEntryEvent);
}

void
ZoneExitHandler::process (bz_EventData *eventData)
{
	emit (NULL /* FIXME? */, bz_eZoneExitEvent);
}

void
JoinHandler::process (bz_EventData *eventData)
{
	bz_PlayerJoinPartEventData *pjped = (bz_PlayerJoinPartEventData*) eventData;
	parent->AddPlayer (pjped->playerID);

	PyObject *arglist = Py_BuildValue ("(iissd)",
			pjped->playerID,
			pjped->teamID,
			pjped->callsign.c_str (),
			pjped->reason.c_str (),
			pjped->time);

	emit (arglist, bz_ePlayerJoinEvent);
	Py_DECREF (arglist);
}

void
PartHandler::process (bz_EventData *eventData)
{
	bz_PlayerJoinPartEventData *pjped = (bz_PlayerJoinPartEventData*) eventData;
	parent->RemovePlayer (pjped->playerID);

	PyObject *arglist = Py_BuildValue ("(iissd)",
			pjped->playerID,
			pjped->teamID,
			pjped->callsign.c_str (),
			pjped->reason.c_str (),
			pjped->time);

	emit (arglist, bz_ePlayerPartEvent);
	Py_DECREF (arglist);
}

void
ChatHandler::process (bz_EventData *eventData)
{
	bz_ChatEventData *ced = (bz_ChatEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("(iisd)",
			ced->from,
			ced->to,
			ced->message.c_str (),
			ced->time);
	emit (arglist, bz_eChatMessageEvent);
	Py_DECREF (arglist);
}

void
UnknownSlashHandler::process (bz_EventData *eventData)
{
	bz_UnknownSlashCommandEventData *usced = (bz_UnknownSlashCommandEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("(iosd)",
			usced->from,
			usced->handled ? Py_True : Py_False,
			usced->message.c_str (),
			usced->time);
	emit (arglist, bz_eUnknownSlashCommand);
	Py_DECREF (arglist);
}

void
GetSpawnPosHandler::process (bz_EventData *eventData)
{
	bz_GetPlayerSpawnPosEventData *gpsped = (bz_GetPlayerSpawnPosEventData *) eventData;

	// FIXME - this probably has some way to return data to the main program
	PyObject *arglist = Py_BuildValue ("(iio(fff)fd)",
			gpsped->playerID,
			gpsped->teamID,
			gpsped->handled ? Py_True : Py_False,
			gpsped->pos[0],
			gpsped->pos[1],
			gpsped->pos[2],
			gpsped->rot,
			gpsped->time);
	emit (arglist, bz_eGetPlayerSpawnPosEvent);
	Py_DECREF (arglist);
}

void
GetAutoTeamHandler::process (bz_EventData *eventData)
{
	emit (NULL, bz_eGetAutoTeamEvent);
}

void
AllowPlayerHandler::process (bz_EventData *eventData)
{
	bz_AllowPlayerEventData *aped = (bz_AllowPlayerEventData *) eventData;

	// FIXME - this probably has some way to return data to the main program
	PyObject *arglist = Py_BuildValue ("(isssod)",
			aped->playerID,
			aped->callsign.c_str (),
			aped->ipAddress.c_str (),
			aped->reason.c_str (),
			aped->allow ? Py_True : Py_False,
			aped->time);
	emit (arglist, bz_eAllowPlayer);
	Py_DECREF (arglist);
}

void
GenerateWorldHandler::process (bz_EventData *eventData)
{
	bz_GenerateWorldEventData *gwed = (bz_GenerateWorldEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("(ood)",
			gwed->handled ? Py_True : Py_False,
			gwed->ctf ? Py_True : Py_False,
			gwed->time);
	emit (arglist, bz_eGenerateWorldEvent);
	Py_DECREF (arglist);
}

void
GetPlayerInfoHandler::process (bz_EventData *eventData)
{
	bz_GetPlayerInfoEventData *gpied = (bz_GetPlayerInfoEventData *) eventData;

	PyObject *arglist = Py_BuildValue ("",
			gpied->playerID,
			gpied->callsign.c_str (),
			gpied->ipAddress.c_str (),
			gpied->team,
			gpied->admin ? Py_True : Py_False,
			gpied->verified ? Py_True : Py_False,
			gpied->registered ? Py_True : Py_False,
			gpied->time);
	emit (arglist, bz_eGetPlayerInfoEvent);
	Py_DECREF (arglist);
}

void
TickHandler::process (bz_EventData *eventData)
{
	bz_TickEventData *ted = (bz_TickEventData*) eventData;

	PyObject *arglist = Py_BuildValue ("(d)", ted->time);
	emit (arglist, bz_eTickEvent);
	Py_DECREF (arglist);
}

};
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file Indicator.cxx
 ** Defines the style of indicators which are text decorations such as underlining.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <vector>
#include <map>

#include "Platform.h"

#include "Scintilla.h"
#include "XPM.h"
#include "Indicator.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static PRectangle PixelGridAlign(const PRectangle &rc) {
	// Move left and right side to nearest pixel to avoid blurry visuals
	return PRectangle(int(rc.left + 0.5), rc.top, int(rc.right + 0.5), rc.bottom);
}

void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine) {
	surface->PenColour(fore);
	int ymid = (rc.bottom + rc.top) / 2;
	if (style == INDIC_SQUIGGLE) {
		surface->MoveTo(rc.left, rc.top);
		int x = rc.left + 2;
		int y = 2;
		while (x < rc.right) {
			surface->LineTo(x, rc.top + y);
			x += 2;
			y = 2 - y;
		}
		surface->LineTo(rc.right, rc.top + y);	// Finish the line
	} else if (style == INDIC_SQUIGGLEPIXMAP) {
		PRectangle rcSquiggle = PixelGridAlign(rc);

		int width = Platform::Minimum(4000, rcSquiggle.Width());
		RGBAImage image(width, 3, 1.0, 0);
		enum { alphaFull = 0xff, alphaSide = 0x2f, alphaSide2=0x5f };
		for (int x = 0; x < width; x++) {
			if (x%2) {
				// Two halfway columns have a full pixel in middle flanked by light pixels
				image.SetPixel(x, 0, fore, alphaSide);
				image.SetPixel(x, 1, fore, alphaFull);
				image.SetPixel(x, 2, fore, alphaSide);
			} else {
				// Extreme columns have a full pixel at bottom or top and a mid-tone pixel in centre
				image.SetPixel(x, (x%4) ? 0 : 2, fore, alphaFull);
				image.SetPixel(x, 1, fore, alphaSide2);
			}
		}
		surface->DrawRGBAImage(rcSquiggle, image.GetWidth(), image.GetHeight(), image.Pixels());
	} else if (style == INDIC_SQUIGGLELOW) {
		surface->MoveTo(rc.left, rc.top);
		int x = rc.left + 3;
		int y = 0;
		while (x < rc.right) {
			surface->LineTo(x-1, rc.top + y);
			y = 1 - y;
        	surface->LineTo(x, rc.top + y);
			x += 3;
		}
		surface->LineTo(rc.right, rc.top + y);	// Finish the line
	} else if (style == INDIC_TT) {
		surface->MoveTo(rc.left, ymid);
		int x = rc.left + 5;
		while (x < rc.right) {
			surface->LineTo(x, ymid);
			surface->MoveTo(x-3, ymid);
			surface->LineTo(x-3, ymid+2);
			x++;
			surface->MoveTo(x, ymid);
			x += 5;
		}
		surface->LineTo(rc.right, ymid);	// Finish the line
		if (x - 3 <= rc.right) {
			surface->MoveTo(x-3, ymid);
			surface->LineTo(x-3, ymid+2);
		}
	} else if (style == INDIC_DIAGONAL) {
		int x = rc.left;
		while (x < rc.right) {
			surface->MoveTo(x, rc.top+2);
			int endX = x+3;
			int endY = rc.top - 1;
			if (endX > rc.right) {
				endY += endX - rc.right;
				endX = rc.right;
			}
			surface->LineTo(endX, endY);
			x += 4;
		}
	} else if (style == INDIC_STRIKE) {
		surface->MoveTo(rc.left, rc.top - 4);
		surface->LineTo(rc.right, rc.top - 4);
	} else if (style == INDIC_HIDDEN) {
		// Draw nothing
	} else if (style == INDIC_BOX) {
		surface->MoveTo(rc.left, ymid+1);
		surface->LineTo(rc.right, ymid+1);
		surface->LineTo(rc.right, rcLine.top+1);
		surface->LineTo(rc.left, rcLine.top+1);
		surface->LineTo(rc.left, ymid+1);
	} else if (style == INDIC_ROUNDBOX || style == INDIC_STRAIGHTBOX) {
		PRectangle rcBox = rcLine;
		rcBox.top = rcLine.top + 1;
		rcBox.left = rc.left;
		rcBox.right = rc.right;
		surface->AlphaRectangle(rcBox, (style == INDIC_ROUNDBOX) ? 1 : 0, fore, fillAlpha, fore, outlineAlpha, 0);
	} else if (style == INDIC_DOTBOX) {
		PRectangle rcBox = PixelGridAlign(rc);
		rcBox.top = rcLine.top + 1;
		rcBox.bottom = rcLine.bottom;
		// Cap width at 4000 to avoid large allocations when mistakes made
		int width = Platform::Minimum(rcBox.Width(), 4000);
		RGBAImage image(width, rcBox.Height(), 1.0, 0);
		// Draw horizontal lines top and bottom
		for (int x=0; x<width; x++) {
			for (int y=0; y<rcBox.Height(); y += rcBox.Height()-1) {
				image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
			}
		}
		// Draw vertical lines left and right
		for (int y=1; y<rcBox.Height(); y++) {
			for (int x=0; x<width; x += width-1) {
				image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
			}
		}
		surface->DrawRGBAImage(rcBox, image.GetWidth(), image.GetHeight(), image.Pixels());
	} else if (style == INDIC_DASH) {
		int x = rc.left;
		while (x < rc.right) {
			surface->MoveTo(x, ymid);
			surface->LineTo(Platform::Minimum(x + 4, rc.right), ymid);
			x += 7;
		}
	} else if (style == INDIC_DOTS) {
		int x = rc.left;
		while (x < rc.right) {
			PRectangle rcDot(x, ymid, x+1, ymid+1);
			surface->FillRectangle(rcDot, fore);
			x += 2;
		}
	} else {	// Either INDIC_PLAIN or unknown
		surface->MoveTo(rc.left, ymid);
		surface->LineTo(rc.right, ymid);
	}
}

<commit_msg>Avoid poor drawing at right of INDIC_SQUIGGLE.<commit_after>// Scintilla source code edit control
/** @file Indicator.cxx
 ** Defines the style of indicators which are text decorations such as underlining.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <vector>
#include <map>

#include "Platform.h"

#include "Scintilla.h"
#include "XPM.h"
#include "Indicator.h"

#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif

static PRectangle PixelGridAlign(const PRectangle &rc) {
	// Move left and right side to nearest pixel to avoid blurry visuals
	return PRectangle(int(rc.left + 0.5), rc.top, int(rc.right + 0.5), rc.bottom);
}

void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine) {
	surface->PenColour(fore);
	int ymid = (rc.bottom + rc.top) / 2;
	if (style == INDIC_SQUIGGLE) {
		int x = int(rc.left+0.5);
		int xLast = int(rc.right+0.5);
		int y = 0;
		surface->MoveTo(x, rc.top + y);
		while (x < xLast) {
			if ((x + 2) > xLast) {
				if (xLast > x)
					y = 1;
				x = xLast;
			} else {
				x += 2;
				y = 2 - y;
			}
			surface->LineTo(x, rc.top + y);
		}
	} else if (style == INDIC_SQUIGGLEPIXMAP) {
		PRectangle rcSquiggle = PixelGridAlign(rc);

		int width = Platform::Minimum(4000, rcSquiggle.Width());
		RGBAImage image(width, 3, 1.0, 0);
		enum { alphaFull = 0xff, alphaSide = 0x2f, alphaSide2=0x5f };
		for (int x = 0; x < width; x++) {
			if (x%2) {
				// Two halfway columns have a full pixel in middle flanked by light pixels
				image.SetPixel(x, 0, fore, alphaSide);
				image.SetPixel(x, 1, fore, alphaFull);
				image.SetPixel(x, 2, fore, alphaSide);
			} else {
				// Extreme columns have a full pixel at bottom or top and a mid-tone pixel in centre
				image.SetPixel(x, (x%4) ? 0 : 2, fore, alphaFull);
				image.SetPixel(x, 1, fore, alphaSide2);
			}
		}
		surface->DrawRGBAImage(rcSquiggle, image.GetWidth(), image.GetHeight(), image.Pixels());
	} else if (style == INDIC_SQUIGGLELOW) {
		surface->MoveTo(rc.left, rc.top);
		int x = rc.left + 3;
		int y = 0;
		while (x < rc.right) {
			surface->LineTo(x-1, rc.top + y);
			y = 1 - y;
        	surface->LineTo(x, rc.top + y);
			x += 3;
		}
		surface->LineTo(rc.right, rc.top + y);	// Finish the line
	} else if (style == INDIC_TT) {
		surface->MoveTo(rc.left, ymid);
		int x = rc.left + 5;
		while (x < rc.right) {
			surface->LineTo(x, ymid);
			surface->MoveTo(x-3, ymid);
			surface->LineTo(x-3, ymid+2);
			x++;
			surface->MoveTo(x, ymid);
			x += 5;
		}
		surface->LineTo(rc.right, ymid);	// Finish the line
		if (x - 3 <= rc.right) {
			surface->MoveTo(x-3, ymid);
			surface->LineTo(x-3, ymid+2);
		}
	} else if (style == INDIC_DIAGONAL) {
		int x = rc.left;
		while (x < rc.right) {
			surface->MoveTo(x, rc.top+2);
			int endX = x+3;
			int endY = rc.top - 1;
			if (endX > rc.right) {
				endY += endX - rc.right;
				endX = rc.right;
			}
			surface->LineTo(endX, endY);
			x += 4;
		}
	} else if (style == INDIC_STRIKE) {
		surface->MoveTo(rc.left, rc.top - 4);
		surface->LineTo(rc.right, rc.top - 4);
	} else if (style == INDIC_HIDDEN) {
		// Draw nothing
	} else if (style == INDIC_BOX) {
		surface->MoveTo(rc.left, ymid+1);
		surface->LineTo(rc.right, ymid+1);
		surface->LineTo(rc.right, rcLine.top+1);
		surface->LineTo(rc.left, rcLine.top+1);
		surface->LineTo(rc.left, ymid+1);
	} else if (style == INDIC_ROUNDBOX || style == INDIC_STRAIGHTBOX) {
		PRectangle rcBox = rcLine;
		rcBox.top = rcLine.top + 1;
		rcBox.left = rc.left;
		rcBox.right = rc.right;
		surface->AlphaRectangle(rcBox, (style == INDIC_ROUNDBOX) ? 1 : 0, fore, fillAlpha, fore, outlineAlpha, 0);
	} else if (style == INDIC_DOTBOX) {
		PRectangle rcBox = PixelGridAlign(rc);
		rcBox.top = rcLine.top + 1;
		rcBox.bottom = rcLine.bottom;
		// Cap width at 4000 to avoid large allocations when mistakes made
		int width = Platform::Minimum(rcBox.Width(), 4000);
		RGBAImage image(width, rcBox.Height(), 1.0, 0);
		// Draw horizontal lines top and bottom
		for (int x=0; x<width; x++) {
			for (int y=0; y<rcBox.Height(); y += rcBox.Height()-1) {
				image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
			}
		}
		// Draw vertical lines left and right
		for (int y=1; y<rcBox.Height(); y++) {
			for (int x=0; x<width; x += width-1) {
				image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
			}
		}
		surface->DrawRGBAImage(rcBox, image.GetWidth(), image.GetHeight(), image.Pixels());
	} else if (style == INDIC_DASH) {
		int x = rc.left;
		while (x < rc.right) {
			surface->MoveTo(x, ymid);
			surface->LineTo(Platform::Minimum(x + 4, rc.right), ymid);
			x += 7;
		}
	} else if (style == INDIC_DOTS) {
		int x = rc.left;
		while (x < rc.right) {
			PRectangle rcDot(x, ymid, x+1, ymid+1);
			surface->FillRectangle(rcDot, fore);
			x += 2;
		}
	} else {	// Either INDIC_PLAIN or unknown
		surface->MoveTo(rc.left, ymid);
		surface->LineTo(rc.right, ymid);
	}
}

<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

#include "disasm.h"
#include "dis_tables.h"

#define OPCODE(entry) ((BxDisasmOpcodeInfo_t*) entry->OpcodeInfo)
#define OPCODE_TABLE(entry) ((BxDisasmOpcodeTable_t*) entry->OpcodeInfo)

static const unsigned char instruction_has_modrm[512] = {
  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f          */
  /*       -------------------------------          */
  /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
  /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
  /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
  /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,
  /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* A0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* B0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* C0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
  /* D0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,
  /* E0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* F0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,
  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f           */
  /*       -------------------------------           */
           1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0F 00 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 10 */
           1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 0F 20 */
           0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 0F 30 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 40 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 50 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 60 */
           1,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1, /* 0F 70 */
           0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0F 80 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 90 */
           0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1, /* 0F A0 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F B0 */
           1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* 0F C0 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F D0 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F E0 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0  /* 0F F0 */
  /*       -------------------------------           */
  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f           */
};

unsigned disassembler::disasm(bx_bool is_32, bx_bool is_64, bx_address base, bx_address ip, const Bit8u *instr, char *disbuf)
{
  x86_insn insn = decode(is_32, is_64, base, ip, instr, disbuf);
  return insn.ilen;
}

x86_insn disassembler::decode(bx_bool is_32, bx_bool is_64, bx_address base, bx_address ip, const Bit8u *instr, char *disbuf)
{
  if (is_64) is_32 = 1;
  x86_insn insn(is_32, is_64);
  const Bit8u *instruction_begin = instruction = instr;
  resolve_modrm = NULL;
  unsigned b3 = 0;

  db_eip = ip;
  db_base = base; // cs linear base (base for PM & cs<<4 for RM & VM)

  disbufptr = disbuf; // start sprintf()'ing into beginning of buffer

#define SSE_PREFIX_NONE 0
#define SSE_PREFIX_66   1
#define SSE_PREFIX_F2   2
#define SSE_PREFIX_F3   3      /* only one SSE prefix could be used */
  unsigned sse_prefix = SSE_PREFIX_NONE;
  unsigned rex_prefix = 0;

  for(;;)
  {
    insn.b1 = fetch_byte();
    insn.prefixes++;

    switch(insn.b1) {
      case 0x40:     // rex
      case 0x41:
      case 0x42:
      case 0x43:
      case 0x44:
      case 0x45:
      case 0x46:
      case 0x47:
      case 0x48:
      case 0x49:
      case 0x4A:
      case 0x4B:
      case 0x4C:
      case 0x4D:
      case 0x4E:
      case 0x4F:
        if (! is_64) break;
        rex_prefix = insn.b1;
        continue;

      case 0x26:     // ES:
        if (! is_64) insn.seg_override = ES_REG;
        rex_prefix = 0;
        continue;

      case 0x2e:     // CS:
        if (! is_64) insn.seg_override = CS_REG;
        rex_prefix = 0;
        continue;

      case 0x36:     // SS:
        if (! is_64) insn.seg_override = SS_REG;
        rex_prefix = 0;
        continue;

      case 0x3e:     // DS:
        if (! is_64) insn.seg_override = DS_REG;
        rex_prefix = 0;
        continue;

      case 0x64:     // FS:
        insn.seg_override = FS_REG;
        rex_prefix = 0;
        continue;

      case 0x65:     // GS:
        insn.seg_override = GS_REG;
        rex_prefix = 0;
        continue;

      case 0x66:     // operand size override
        if (!insn.os_64) insn.os_32 = !is_32;
        if (!sse_prefix) sse_prefix = SSE_PREFIX_66;
        rex_prefix = 0;
        continue;

      case 0x67:     // address size override
        if (!is_64) insn.as_32 = !is_32;
        insn.as_64 = 0;
        rex_prefix = 0;
        continue;

      case 0xf0:     // lock
        rex_prefix = 0;
        continue;

      case 0xf2:     // repne
        sse_prefix = SSE_PREFIX_F2;
        rex_prefix = 0;
        continue;

      case 0xf3:     // rep
        sse_prefix = SSE_PREFIX_F3;
        rex_prefix = 0;
        continue;

      // no more prefixes
      default:
        break;
    }

    insn.prefixes--;
    break;
  }

  if (insn.b1 == 0x0f)
  {
    insn.b1 = 0x100 | fetch_byte();
  }

  if (rex_prefix) {
    insn.extend8b = 1;
    if (rex_prefix & 0x8) {
      insn.os_64 = 1;
      insn.os_32 = 1;
    }
    if (rex_prefix & 0x4) insn.rex_r = 8;
    if (rex_prefix & 0x2) insn.rex_x = 8;
    if (rex_prefix & 0x1) insn.rex_b = 8;
  }

  const BxDisasmOpcodeTable_t *opcode_table, *entry;

  if (is_64) {
    if (insn.os_64)
      opcode_table = BxDisasmOpcodes64q;
    else if (insn.os_32)
      opcode_table = BxDisasmOpcodes64d;
    else
      opcode_table = BxDisasmOpcodes64w;
  } else {
    if (insn.os_32)
      opcode_table = BxDisasmOpcodes32;
    else
      opcode_table = BxDisasmOpcodes16;
  }

  entry = opcode_table + insn.b1;

  if (instruction_has_modrm[insn.b1])
  {
    // will require 3rd byte for 3-byte opcode
    if (entry->Attr == _GRP3BOP)
      b3 = fetch_byte();

    decode_modrm(&insn);
  }

  int attr = entry->Attr;
  while(attr)
  {
    switch(attr) {
       case _GROUPN:
         entry = &(OPCODE_TABLE(entry)[insn.nnn]);
         break;

       case _GRPSSE:
         if(sse_prefix) insn.prefixes--;
         /* For SSE opcodes, look into another 4 entries table
            with the opcode prefixes (NONE, 0x66, 0xF2, 0xF3) */
         entry = &(OPCODE_TABLE(entry)[sse_prefix]);
         break;

       case _SPLIT11B:
         entry = &(OPCODE_TABLE(entry)[insn.mod != 3]); /* REG/MEM */
         break;

       case _GRPRM:
         entry = &(OPCODE_TABLE(entry)[insn.rm]);
         break;

       case _GRPFP:
         if(insn.mod != 3)
         {
             entry = &(OPCODE_TABLE(entry)[insn.nnn]);
         } else {
             int index = (insn.b1-0xD8)*64 + (insn.modrm & 0x3f);
             entry = &(BxDisasmOpcodeInfoFP[index]);
         }
         break;

       case _GRP3DNOW:
         entry = &(BxDisasm3DNowGroup[peek_byte()]);
         break;

       case _GRP3BOP:
         entry = &(OPCODE_TABLE(entry)[b3]);
         break;

       case _GRP64B:
         entry = &(OPCODE_TABLE(entry)[insn.os_64 ? 2 : insn.os_32]);
         break;

       default:
         printf("Internal disassembler error - unknown attribute !\n");
         return x86_insn(is_32, is_64);
    }

    /* get additional attributes from group table */
    attr = entry->Attr;
  }

#define BRANCH_NOT_TAKEN 0x2E
#define BRANCH_TAKEN     0x3E

  unsigned branch_hint = 0;

  // print prefixes
  for(unsigned i=0;i<insn.prefixes;i++)
  {
    Bit8u prefix_byte = *(instr+i);

    if (prefix_byte == 0xF0) {
      const BxDisasmOpcodeTable_t *prefix = &(opcode_table[prefix_byte]);
      dis_sprintf("%s ", OPCODE(prefix)->IntelOpcode);
    }

    if (prefix_byte == 0xF3 || prefix_byte == 0xF2) {
      if (attr != _GRPSSE) {
        const BxDisasmOpcodeTable_t *prefix = &(opcode_table[prefix_byte]);
        dis_sprintf("%s ", OPCODE(prefix)->IntelOpcode);
      }
    }

    // branch hint for jcc instructions
    if ((insn.b1 >= 0x070 && insn.b1 <= 0x07F) ||
        (insn.b1 >= 0x180 && insn.b1 <= 0x18F))
    {
      if (prefix_byte == BRANCH_NOT_TAKEN || prefix_byte == BRANCH_TAKEN)
        branch_hint = prefix_byte;
    }
  }

  const BxDisasmOpcodeInfo_t *opcode = OPCODE(entry);

  // patch jecx opcode
  if (insn.b1 == 0xE3 && insn.as_32 && !insn.as_64)
    opcode = &Ia_jecxz_Jb;

  // fix nop opcode
  if (insn.b1 == 0x90 && !insn.rex_b) {
    opcode = &Ia_nop;
  }

  // print instruction disassembly
  if (intel_mode)
    print_disassembly_intel(&insn, opcode);
  else
    print_disassembly_att  (&insn, opcode);

  if (branch_hint == BRANCH_NOT_TAKEN)
  {
    dis_sprintf(", not taken");
  }
  else if (branch_hint == BRANCH_TAKEN)
  {
    dis_sprintf(", taken");
  }

  insn.ilen = (unsigned)(instruction - instruction_begin);

  return insn;
}

void disassembler::dis_sprintf(const char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  vsprintf(disbufptr, fmt, ap);
  va_end(ap);

  disbufptr += strlen(disbufptr);
}

void disassembler::dis_putc(char symbol)
{
  *disbufptr++ = symbol;
  *disbufptr = 0;
}
<commit_msg>same optimization in disasam<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////

#include <stdio.h>
#include <stdarg.h>
#include <string.h>

#include "disasm.h"
#include "dis_tables.h"

#define OPCODE(entry) ((BxDisasmOpcodeInfo_t*) entry->OpcodeInfo)
#define OPCODE_TABLE(entry) ((BxDisasmOpcodeTable_t*) entry->OpcodeInfo)

static const unsigned char instruction_has_modrm[512] = {
  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f          */
  /*       -------------------------------          */
  /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
  /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
  /* 20 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
  /* 30 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
  /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* 60 */ 0,0,1,1,0,0,0,0,0,1,0,1,0,0,0,0,
  /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* A0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* B0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* C0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
  /* D0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,
  /* E0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  /* F0 */ 0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,
  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f           */
  /*       -------------------------------           */
           1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,1, /* 0F 00 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 10 */
           1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,1, /* 0F 20 */
           0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0, /* 0F 30 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 40 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 50 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 60 */
           1,1,1,1,1,1,1,0,1,1,0,0,1,1,1,1, /* 0F 70 */
           0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0F 80 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 90 */
           0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1, /* 0F A0 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F B0 */
           1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* 0F C0 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F D0 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F E0 */
           1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0  /* 0F F0 */
  /*       -------------------------------           */
  /*       0 1 2 3 4 5 6 7 8 9 a b c d e f           */
};

unsigned disassembler::disasm(bx_bool is_32, bx_bool is_64, bx_address base, bx_address ip, const Bit8u *instr, char *disbuf)
{
  x86_insn insn = decode(is_32, is_64, base, ip, instr, disbuf);
  return insn.ilen;
}

x86_insn disassembler::decode(bx_bool is_32, bx_bool is_64, bx_address base, bx_address ip, const Bit8u *instr, char *disbuf)
{
  if (is_64) is_32 = 1;
  x86_insn insn(is_32, is_64);
  const Bit8u *instruction_begin = instruction = instr;
  resolve_modrm = NULL;
  unsigned b3 = 0;

  db_eip = ip;
  db_base = base; // cs linear base (base for PM & cs<<4 for RM & VM)

  disbufptr = disbuf; // start sprintf()'ing into beginning of buffer

#define SSE_PREFIX_NONE 0
#define SSE_PREFIX_66   1
#define SSE_PREFIX_F2   2
#define SSE_PREFIX_F3   3      /* only one SSE prefix could be used */
  unsigned sse_prefix = SSE_PREFIX_NONE;
  unsigned rex_prefix = 0;

  for(;;)
  {
    insn.b1 = fetch_byte();
    insn.prefixes++;

    switch(insn.b1) {
      case 0x40:     // rex
      case 0x41:
      case 0x42:
      case 0x43:
      case 0x44:
      case 0x45:
      case 0x46:
      case 0x47:
      case 0x48:
      case 0x49:
      case 0x4A:
      case 0x4B:
      case 0x4C:
      case 0x4D:
      case 0x4E:
      case 0x4F:
        if (! is_64) break;
        rex_prefix = insn.b1;
        continue;

      case 0x26:     // ES:
      case 0x2e:     // CS:
      case 0x36:     // SS:
      case 0x3e:     // DS:
        if (! is_64) insn.seg_override = (insn.b1 >> 3) & 3;
        rex_prefix = 0;
        continue;

      case 0x64:     // FS:
      case 0x65:     // GS:
        insn.seg_override = insn.b1 & 0xf;
        rex_prefix = 0;
        continue;

      case 0x66:     // operand size override
        if (!insn.os_64) insn.os_32 = !is_32;
        if (!sse_prefix) sse_prefix = SSE_PREFIX_66;
        rex_prefix = 0;
        continue;

      case 0x67:     // address size override
        if (!is_64) insn.as_32 = !is_32;
        insn.as_64 = 0;
        rex_prefix = 0;
        continue;

      case 0xf0:     // lock
        rex_prefix = 0;
        continue;

      case 0xf2:     // repne
      case 0xf3:     // rep
        sse_prefix = insn.b1 & 0xf;
        rex_prefix = 0;
        continue;

        sse_prefix = SSE_PREFIX_F3;
        rex_prefix = 0;
        continue;

      // no more prefixes
      default:
        break;
    }

    insn.prefixes--;
    break;
  }

  if (insn.b1 == 0x0f)
  {
    insn.b1 = 0x100 | fetch_byte();
  }

  if (rex_prefix) {
    insn.extend8b = 1;
    if (rex_prefix & 0x8) {
      insn.os_64 = 1;
      insn.os_32 = 1;
    }
    if (rex_prefix & 0x4) insn.rex_r = 8;
    if (rex_prefix & 0x2) insn.rex_x = 8;
    if (rex_prefix & 0x1) insn.rex_b = 8;
  }

  const BxDisasmOpcodeTable_t *opcode_table, *entry;

  if (is_64) {
    if (insn.os_64)
      opcode_table = BxDisasmOpcodes64q;
    else if (insn.os_32)
      opcode_table = BxDisasmOpcodes64d;
    else
      opcode_table = BxDisasmOpcodes64w;
  } else {
    if (insn.os_32)
      opcode_table = BxDisasmOpcodes32;
    else
      opcode_table = BxDisasmOpcodes16;
  }

  entry = opcode_table + insn.b1;

  if (instruction_has_modrm[insn.b1])
  {
    // will require 3rd byte for 3-byte opcode
    if (entry->Attr == _GRP3BOP)
      b3 = fetch_byte();

    decode_modrm(&insn);
  }

  int attr = entry->Attr;
  while(attr)
  {
    switch(attr) {
       case _GROUPN:
         entry = &(OPCODE_TABLE(entry)[insn.nnn]);
         break;

       case _GRPSSE:
         if(sse_prefix) insn.prefixes--;
         /* For SSE opcodes, look into another 4 entries table
            with the opcode prefixes (NONE, 0x66, 0xF2, 0xF3) */
         entry = &(OPCODE_TABLE(entry)[sse_prefix]);
         break;

       case _SPLIT11B:
         entry = &(OPCODE_TABLE(entry)[insn.mod != 3]); /* REG/MEM */
         break;

       case _GRPRM:
         entry = &(OPCODE_TABLE(entry)[insn.rm]);
         break;

       case _GRPFP:
         if(insn.mod != 3)
         {
             entry = &(OPCODE_TABLE(entry)[insn.nnn]);
         } else {
             int index = (insn.b1-0xD8)*64 + (insn.modrm & 0x3f);
             entry = &(BxDisasmOpcodeInfoFP[index]);
         }
         break;

       case _GRP3DNOW:
         entry = &(BxDisasm3DNowGroup[peek_byte()]);
         break;

       case _GRP3BOP:
         entry = &(OPCODE_TABLE(entry)[b3]);
         break;

       case _GRP64B:
         entry = &(OPCODE_TABLE(entry)[insn.os_64 ? 2 : insn.os_32]);
         break;

       default:
         printf("Internal disassembler error - unknown attribute !\n");
         return x86_insn(is_32, is_64);
    }

    /* get additional attributes from group table */
    attr = entry->Attr;
  }

#define BRANCH_NOT_TAKEN 0x2E
#define BRANCH_TAKEN     0x3E

  unsigned branch_hint = 0;

  // print prefixes
  for(unsigned i=0;i<insn.prefixes;i++)
  {
    Bit8u prefix_byte = *(instr+i);

    if (prefix_byte == 0xF0) {
      const BxDisasmOpcodeTable_t *prefix = &(opcode_table[prefix_byte]);
      dis_sprintf("%s ", OPCODE(prefix)->IntelOpcode);
    }

    if (prefix_byte == 0xF3 || prefix_byte == 0xF2) {
      if (attr != _GRPSSE) {
        const BxDisasmOpcodeTable_t *prefix = &(opcode_table[prefix_byte]);
        dis_sprintf("%s ", OPCODE(prefix)->IntelOpcode);
      }
    }

    // branch hint for jcc instructions
    if ((insn.b1 >= 0x070 && insn.b1 <= 0x07F) ||
        (insn.b1 >= 0x180 && insn.b1 <= 0x18F))
    {
      if (prefix_byte == BRANCH_NOT_TAKEN || prefix_byte == BRANCH_TAKEN)
        branch_hint = prefix_byte;
    }
  }

  const BxDisasmOpcodeInfo_t *opcode = OPCODE(entry);

  // patch jecx opcode
  if (insn.b1 == 0xE3 && insn.as_32 && !insn.as_64)
    opcode = &Ia_jecxz_Jb;

  // fix nop opcode
  if (insn.b1 == 0x90 && !insn.rex_b) {
    opcode = &Ia_nop;
  }

  // print instruction disassembly
  if (intel_mode)
    print_disassembly_intel(&insn, opcode);
  else
    print_disassembly_att  (&insn, opcode);

  if (branch_hint == BRANCH_NOT_TAKEN)
  {
    dis_sprintf(", not taken");
  }
  else if (branch_hint == BRANCH_TAKEN)
  {
    dis_sprintf(", taken");
  }

  insn.ilen = (unsigned)(instruction - instruction_begin);

  return insn;
}

void disassembler::dis_sprintf(const char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  vsprintf(disbufptr, fmt, ap);
  va_end(ap);

  disbufptr += strlen(disbufptr);
}

void disassembler::dis_putc(char symbol)
{
  *disbufptr++ = symbol;
  *disbufptr = 0;
}
<|endoftext|>


<commit_before>#include "MainFrame.h"
#include "TitleBar.h"
#include "HoverMoveFilter.h"

MainFrame::MainFrame()
{
    mMousePressed = false;
    setFrameShape(Panel);

    // Make this a borderless window which can't
    // be resized or moved via the window system
    setWindowFlags(Qt::FramelessWindowHint);

    // Event tricks
    setMouseTracking(true);
    setAttribute(Qt::WA_Hover);
    installEventFilter(new HoverMoveFilter(this));

    mTitleBar = new TitleBar(this);

    mMainWindow = new QMainWindow(this);
    mMainWindow->setWindowFlags(Qt::Widget);

    // Creating action
    QAction *action = new QAction(QIcon::fromTheme("document-open"), tr("&Open..."), this);
    action->setShortcuts(QKeySequence::Open);
    action->setStatusTip(tr("Do nothing ;)"));

    // Creating toolbar
    QToolBar *toolbar = new QToolBar(mMainWindow);
    toolbar->addAction(action);
    mMainWindow->addToolBar(toolbar);

    // Creating menu
    QMenu *menu = mMainWindow->menuBar()->addMenu(tr("&File"));
    menu->addAction(action);

    // Creating dock
    QDockWidget *dockWidget = new QDockWidget(tr("Dock Widget"), this);
    QPushButton *pushButton = new QPushButton(QIcon::fromTheme("edit-undo"),"Panic",dockWidget);
    dockWidget->setWidget(pushButton);
    mMainWindow->addDockWidget(Qt::RightDockWidgetArea, dockWidget);

    QVBoxLayout *vbox = new QVBoxLayout(this);
    vbox->addWidget(mTitleBar);
    vbox->setMargin(0);
    vbox->setSpacing(0);

    QVBoxLayout *layout = new QVBoxLayout();
    layout->addWidget(mMainWindow);
    layout->setMargin(WINDOW_MARGIN);
    layout->setSpacing(0);
    vbox->addLayout(layout);
}

void MainFrame::mousePressEvent(QMouseEvent *e)
{
    // mOldPos = e->pos();
    mMousePressed = e->button() == Qt::LeftButton;
    if (mMousePressed) {
        if (left) {
            mClickedPos.setX(e->pos().x());
        }
        if (right) {
            mClickedPos.setX(width() - e->pos().x());
        }
        if (bottom) {
            mClickedPos.setY(height() - e->pos().y());
        }
    }
}

void MainFrame::mouseReleaseEvent(QMouseEvent *e)
{
    if (e->button() == Qt::LeftButton) {
        mMousePressed = false;
    }
}

void MainFrame::mouseMove(QPoint newPos, QPoint oldPos)
{
    if (mMousePressed) {
        int dx = newPos.x() - oldPos.x();
        int dy = newPos.y() - oldPos.y();

        QRect g = geometry();
        QSize minSize = minimumSize();

        // We don't resize if the windows has the minimum size
        if (left) {
            // Fix a bug when you try to resize to less than minimum size and
            // then the mouse goes right again.
            if (dx < 0 && oldPos.x() > mClickedPos.x() ) {
                dx += oldPos.x() - mClickedPos.x();
                if (dx > 0) {
                    dx = 0;
                }
            } else if ( dx > 0 && g.width() - dx < minSize.width()) {
                dx = g.width() - minSize.width();
            }
            g.setLeft(g.left() + dx);
        }

        if (right) {
            // Fix a bug when you try to resize to less than minimum size and
            // then the mouse goes right again.
            if (dx > 0 && (width() - newPos.x() > mClickedPos.x())) {
                dx -= width() - newPos.x() - mClickedPos.x();
                if (dx < 0) {
                    dx = 0;
                }
            }
            g.setRight(g.right() + dx);
        }
        if (bottom) {
            // Fix a bug when you try to resize to less than minimum size and
            // then the mouse goes down again.
            if (dy > 0 && (height() - newPos.y() > mClickedPos.y())) {
                dy -= height() - newPos.y() - mClickedPos.y();
                if (dy < 0) {
                    dy = 0;
                }
            }
            g.setBottom(g.bottom() + dy);
        }

        setGeometry(g);

    } else {
        QRect r = rect();
        left = qAbs(newPos.x()- r.left()) <= WINDOW_MARGIN;
        right = qAbs(newPos.x() - r.right()) <= WINDOW_MARGIN;
        bottom = qAbs(newPos.y() - r.bottom()) <= WINDOW_MARGIN;
        bool hor = left | right;

        if (hor && bottom) {
            if (left)
                setCursor(Qt::SizeBDiagCursor);
            else
                setCursor(Qt::SizeFDiagCursor);
        } else if (hor) {
            setCursor(Qt::SizeHorCursor);
        } else if (bottom) {
            setCursor(Qt::SizeVerCursor);
        } else {
            setCursor(Qt::ArrowCursor);
        }
    }
}
<commit_msg>Don't show resize mouse in title bar<commit_after>#include "MainFrame.h"
#include "TitleBar.h"
#include "HoverMoveFilter.h"

MainFrame::MainFrame()
{
    mMousePressed = false;
    setFrameShape(Panel);

    // Make this a borderless window which can't
    // be resized or moved via the window system
    setWindowFlags(Qt::FramelessWindowHint);

    // Event tricks
    setMouseTracking(true);
    setAttribute(Qt::WA_Hover);
    installEventFilter(new HoverMoveFilter(this));

    mTitleBar = new TitleBar(this);

    mMainWindow = new QMainWindow(this);
    mMainWindow->setWindowFlags(Qt::Widget);

    // Creating action
    QAction *action = new QAction(QIcon::fromTheme("document-open"), tr("&Open..."), this);
    action->setShortcuts(QKeySequence::Open);
    action->setStatusTip(tr("Do nothing ;)"));

    // Creating toolbar
    QToolBar *toolbar = new QToolBar(mMainWindow);
    toolbar->addAction(action);
    mMainWindow->addToolBar(toolbar);

    // Creating menu
    QMenu *menu = mMainWindow->menuBar()->addMenu(tr("&File"));
    menu->addAction(action);

    // Creating dock
    QDockWidget *dockWidget = new QDockWidget(tr("Dock Widget"), this);
    QPushButton *pushButton = new QPushButton(QIcon::fromTheme("edit-undo"),"Panic",dockWidget);
    dockWidget->setWidget(pushButton);
    mMainWindow->addDockWidget(Qt::RightDockWidgetArea, dockWidget);

    QVBoxLayout *vbox = new QVBoxLayout(this);
    vbox->addWidget(mTitleBar);
    vbox->setMargin(0);
    vbox->setSpacing(0);

    QVBoxLayout *layout = new QVBoxLayout();
    layout->addWidget(mMainWindow);
    layout->setMargin(WINDOW_MARGIN);
    layout->setSpacing(0);
    vbox->addLayout(layout);
}

void MainFrame::mousePressEvent(QMouseEvent *e)
{
    // mOldPos = e->pos();
    mMousePressed = e->button() == Qt::LeftButton;
    if (mMousePressed) {
        if (left) {
            mClickedPos.setX(e->pos().x());
        }
        if (right) {
            mClickedPos.setX(width() - e->pos().x());
        }
        if (bottom) {
            mClickedPos.setY(height() - e->pos().y());
        }
    }
}

void MainFrame::mouseReleaseEvent(QMouseEvent *e)
{
    if (e->button() == Qt::LeftButton) {
        mMousePressed = false;
    }
}

void MainFrame::mouseMove(QPoint newPos, QPoint oldPos)
{
    if (mMousePressed) {
        int dx = newPos.x() - oldPos.x();
        int dy = newPos.y() - oldPos.y();

        QRect g = geometry();
        QSize minSize = minimumSize();

        // We don't resize if the windows has the minimum size
        if (left) {
            // Fix a bug when you try to resize to less than minimum size and
            // then the mouse goes right again.
            if (dx < 0 && oldPos.x() > mClickedPos.x() ) {
                dx += oldPos.x() - mClickedPos.x();
                if (dx > 0) {
                    dx = 0;
                }
            } else if ( dx > 0 && g.width() - dx < minSize.width()) {
                dx = g.width() - minSize.width();
            }
            g.setLeft(g.left() + dx);
        }

        if (right) {
            // Fix a bug when you try to resize to less than minimum size and
            // then the mouse goes right again.
            if (dx > 0 && (width() - newPos.x() > mClickedPos.x())) {
                dx -= width() - newPos.x() - mClickedPos.x();
                if (dx < 0) {
                    dx = 0;
                }
            }
            g.setRight(g.right() + dx);
        }
        if (bottom) {
            // Fix a bug when you try to resize to less than minimum size and
            // then the mouse goes down again.
            if (dy > 0 && (height() - newPos.y() > mClickedPos.y())) {
                dy -= height() - newPos.y() - mClickedPos.y();
                if (dy < 0) {
                    dy = 0;
                }
            }
            g.setBottom(g.bottom() + dy);
        }

        setGeometry(g);

    } else {
        QRect r = rect();
        left = qAbs(newPos.x()- r.left()) <= WINDOW_MARGIN &&
            newPos.y() > mTitleBar->height();
        right = qAbs(newPos.x() - r.right()) <= WINDOW_MARGIN &&
            newPos.y() > mTitleBar->height();
        bottom = qAbs(newPos.y() - r.bottom()) <= WINDOW_MARGIN;
        bool hor = left | right;

        if (hor && bottom) {
            if (left)
                setCursor(Qt::SizeBDiagCursor);
            else
                setCursor(Qt::SizeFDiagCursor);
        } else if (hor) {
            setCursor(Qt::SizeHorCursor);
        } else if (bottom) {
            setCursor(Qt::SizeVerCursor);
        } else {
            setCursor(Qt::ArrowCursor);
        }
    }
}
<|endoftext|>


<commit_before>#include "MapOutput.h"

#include "lodepng.h"

#include <fstream>

bool MapOutput::saveAsLUA(const Map& map, string filename)
{
	int size = map.getSize();

	fstream file;
	file.open(filename.c_str(), ios::trunc | ios::out);

	if (!file.is_open())
		return false;

	file << "{\n";

	for (unsigned y = 0; y < size; y++)
	{
		file << "	{";
		for (unsigned x = 0; x < size; x++)
		{
			file << round(map.map[x][y].value * 100) / 100;
			if (x != size - 1)
				file << ", ";
		}
		file << "}";
		if (y != size - 1)
			file << ",";

		file << "\n";
	}

	file << "}";
	file.close();

	return true;
}

bool MapOutput::saveAsJSON(const Map& map, string filename)
{
	int size = map.getSize();

	fstream file;
	file.open(filename.c_str(), ios::trunc | ios::out);

	if (!file.is_open())
		return false;

	file << "[\n";

	for (unsigned y = 0; y < size; y++)
	{
		file << "	[";
		for (unsigned x = 0; x < size; x++)
		{
			file << round(map.map[x][y].value * 100) / 100;
			if (x != size - 1)
				file << ", ";
		}
		file << "]";
		if (y != size - 1)
			file << ",";

		file << "\n";
	}

	file << "]";
	file.close();

	return true;
}

bool MapOutput::saveAsPNG(const Map& map, string filename)
{
	int size = map.getSize();
	auto tiles = map.map;

	std::vector<unsigned char> out;
	out.resize(size * size * 4);

	for (unsigned y = 0; y < size; y++)
	for (unsigned x = 0; x < size; x++)
	{
		out[4 * size * y + 4 * x + 0] = tiles[x][y].getColor().r;
		out[4 * size * y + 4 * x + 1] = tiles[x][y].getColor().g;
		out[4 * size * y + 4 * x + 2] = tiles[x][y].getColor().b;
		out[4 * size * y + 4 * x + 3] = 255;
	}

	if (lodepng::encode(filename, out, size, size) != 0)
		return false;

	return true;
}

bool MapOutput::saveAsOTBM(const Map& map, string filename)
{
	int size = map.getSize();
	auto tiles = map.map;

	int local_x = -1, local_y = -1, local_z = -1;

	FILE* f;

	if (!fopen_s(&f, filename.c_str(), "wb"))
		return false;

	vector<unsigned char> header1{
		0x00, 0x00, 0x00, 0x00,
		0xFE, 0x00, 0x02, 0x00,
		0x00, 0x00 };

	vector<unsigned char> header2{
		0x03, 0x00,

		0x00, 0x00, 0x14, 0x00,
		0x00, 0x00,

		0xFE, 0x02, // OTBM_MAP_DATA node
		0x01, // Description
		0x27, 0x00, // Description length

		0x53,
		0x61, 0x76, 0x65, 0x64,
		0x20, 0x77, 0x69, 0x74,
		0x68, 0x20, 0x52, 0x65,
		0x6D, 0x65, 0x72, 0x65,
		0x27, 0x73, 0x20, 0x4D,

		0x61, 0x70, 0x20, 0x45,
		0x64, 0x69, 0x74, 0x6F,
		0x72, 0x20, 0x33, 0x2E,
		0x30, 0x20, 0x42, 0x45,

		0x54, 0x41,

		0x01, 0x00,	0x00, // Map description
		0x0B, 0x00, 0x00, // Spawn file
		0x0D, 0x00, 0x00  // House file
	};

	vector <unsigned char> footer {
		0xFE, 0x0C, 0xFF,
		0xFE, 0x0F,	0xFF,
		0xFF, 0xFF
	};

	// Writing file
	for (auto hex : header1)
		fputc(hex, f);

	unsigned short otbmMapSize = size;
	if (otbmMapSize < 256)
		otbmMapSize = 256;

	if (size > 250)
	{
		size = 250;
		cout << "Warning: Map size was set to 250x250 SQM, type --help to get more info." << std::endl;
	}

	fwrite(&otbmMapSize, 2, 1, f); // size X
	fwrite(&otbmMapSize, 2, 1, f); // size Y

	for (auto hex : header2)
		fputc(hex, f);

	int z = 7;
	bool first = true;

	for (int y = 0; y < size; y++)
	{
		for (int x = 0; x < size; x++)
		{
			// Check if we should create new node
			if (x < local_x || x >= local_x + 256 ||
				x < local_y || y >= local_y + 256 ||
				z != local_z)
			{
				if (!first)
				{
					// End node
					fputc(0xFF, f);
				}
				first = false;

				// New node
				fputc(0xFE, f); // Node start
				fputc(0x04, f); // Node type

				unsigned short tmp = (local_x = x & 0xFF00);
				fwrite(&tmp, sizeof(unsigned short), 1, f); // start X
				tmp = (local_y = y & 0xFF00);
				fwrite(&tmp, sizeof(unsigned short), 1, f); // start Y
				fputc(local_z = 0x07, f);                   // start Z
			}

			fputc(0xFE, f); // Node start
			fputc(0x05, f); // Node type (OTBM_TILE)

			fputc(static_cast<unsigned char>(x)& 0xFF, f); // Pos X
			fputc(static_cast<unsigned char>(y)& 0xFF, f); // Pos Y

			fputc(0x09, f); // OTBM_ATTR_ITEM

			unsigned short tmp = tiles[x][y].getItemId();
			fwrite(&tmp, sizeof(unsigned short), 1, f); // Item ID

			fputc(0xFF, f); // Node end
		}
	}

	// Closing last node
	if (!first) {
		fputc(0xFF, f);
	}

	for (auto hex : footer)
		fputc(hex, f);

	fclose(f);

	return true;
}<commit_msg>Tweaks in OTBM saving<commit_after>#include "MapOutput.h"

#include "lodepng.h"

#include <fstream>

bool MapOutput::saveAsLUA(const Map& map, string filename)
{
	int size = map.getSize();

	fstream file;
	file.open(filename.c_str(), ios::trunc | ios::out);

	if (!file.is_open())
		return false;

	file << "{\n";

	for (unsigned y = 0; y < size; y++)
	{
		file << "	{";
		for (unsigned x = 0; x < size; x++)
		{
			file << round(map.map[x][y].value * 100) / 100;
			if (x != size - 1)
				file << ", ";
		}
		file << "}";
		if (y != size - 1)
			file << ",";

		file << "\n";
	}

	file << "}";
	file.close();

	return true;
}

bool MapOutput::saveAsJSON(const Map& map, string filename)
{
	int size = map.getSize();

	fstream file;
	file.open(filename.c_str(), ios::trunc | ios::out);

	if (!file.is_open())
		return false;

	file << "[\n";

	for (unsigned y = 0; y < size; y++)
	{
		file << "	[";
		for (unsigned x = 0; x < size; x++)
		{
			file << round(map.map[x][y].value * 100) / 100;
			if (x != size - 1)
				file << ", ";
		}
		file << "]";
		if (y != size - 1)
			file << ",";

		file << "\n";
	}

	file << "]";
	file.close();

	return true;
}

bool MapOutput::saveAsPNG(const Map& map, string filename)
{
	int size = map.getSize();
	auto tiles = map.map;

	std::vector<unsigned char> out;
	out.resize(size * size * 4);

	for (unsigned y = 0; y < size; y++)
	for (unsigned x = 0; x < size; x++)
	{
		out[4 * size * y + 4 * x + 0] = tiles[x][y].getColor().r;
		out[4 * size * y + 4 * x + 1] = tiles[x][y].getColor().g;
		out[4 * size * y + 4 * x + 2] = tiles[x][y].getColor().b;
		out[4 * size * y + 4 * x + 3] = 255;
	}

	if (lodepng::encode(filename, out, size, size) != 0)
		return false;

	return true;
}

/*
	Created by using RME source code and hex editor
*/
bool MapOutput::saveAsOTBM(const Map& map, string filename)
{
	int size = map.getSize();
	auto tiles = map.map;

	int local_x = -1, local_y = -1, local_z = -1;

	FILE* f;

	if (fopen_s(&f, filename.c_str(), "wb"))
		return false;

	vector<unsigned char> header1{
		0x00, 0x00, 0x00, 0x00,
		0xFE, 0x00, 0x02, 0x00,
		0x00, 0x00 };

	vector<unsigned char> header2{
		0x03, 0x00,

		0x00, 0x00, 0x14, 0x00,
		0x00, 0x00,

		0xFE, 0x02, // OTBM_MAP_DATA node
		0x01, 0x00, 0x00, // Map description
		0x01, 0x00,	0x00, // Map description
		0x0B, 0x00, 0x00, // Spawn file
		0x0D, 0x00, 0x00  // House file
	};

	vector <unsigned char> footer {
		0xFE, 0x0C, 0xFF,
		0xFE, 0x0F,	0xFF,
		0xFF, 0xFF
	};

	// Writing file
	for (auto hex : header1)
		fputc(hex, f);

	unsigned short otbmMapSize = size;
	if (otbmMapSize < 256)
		otbmMapSize = 256;

	if (size > 250)
	{
		size = 250;
		cout << "Warning: Map size was set to 250x250 SQM, type --help to get more info." << std::endl;
	}

	fwrite(&otbmMapSize, sizeof(unsigned short), 1, f); // size X
	fwrite(&otbmMapSize, sizeof(unsigned short), 1, f); // size Y

	for (auto hex : header2)
		fputc(hex, f);

	int z = 7;
	bool first = true;

	for (int y = 0; y < size; y++)
	{
		for (int x = 0; x < size; x++)
		{
			// Check if we should create new node
			if (x < local_x || x >= local_x + 256 ||
				x < local_y || y >= local_y + 256 ||
				z != local_z)
			{
				if (!first)
				{
					// End node
					fputc(0xFF, f);
				}
				first = false;

				// New node
				fputc(0xFE, f); // Node start
				fputc(0x04, f); // Node type

				unsigned short tmp = (local_x = x & 0xFF00);
				fwrite(&tmp, sizeof(unsigned short), 1, f); // start X
				tmp = (local_y = y & 0xFF00);
				fwrite(&tmp, sizeof(unsigned short), 1, f); // start Y
				fputc(local_z = 0x07, f);                   // start Z
			}

			fputc(0xFE, f); // Node start
			fputc(0x05, f); // Node type (OTBM_TILE)

			fputc(static_cast<unsigned char>(x)& 0xFF, f); // Pos X
			fputc(static_cast<unsigned char>(y)& 0xFF, f); // Pos Y

			fputc(0x09, f); // OTBM_ATTR_ITEM

			unsigned short tmp = tiles[x][y].getItemId();
			fwrite(&tmp, sizeof(unsigned short), 1, f); // Item ID

			fputc(0xFF, f); // Node end
		}
	}

	// Closing last node
	if (!first) {
		fputc(0xFF, f);
	}

	for (auto hex : footer)
		fputc(hex, f);

	fclose(f);

	return true;
}<|endoftext|>


<commit_before>//===--- SILInliner.cpp - Inlines SIL functions ------------------*- C++ -*-==//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/SILPasses/Utils/SILInliner.h"
#include "llvm/ADT/STLExtras.h"

using namespace swift;

/// \brief Inlines the callee of a given ApplyInst (which must be the value of a
/// FunctionRefInst referencing a function with a known body), into the caller
/// containing the ApplyInst, which must be the same function as provided to the
/// constructor of SILInliner. It only performs one step of inlining: it does
/// not recursively inline functions called by the callee.
///
/// \returns true on success or false if it is unable to inline the function
/// (for any reason).
bool SILInliner::inlineFunction(SILBasicBlock::iterator &I,
                                SILFunction *CalleeFunction,
                                ArrayRef<Substitution> Subs,
                                ArrayRef<SILValue> Args) {
  SILFunction &F = getBuilder().getFunction();
  assert(I->getParent()->getParent() && I->getParent()->getParent() == &F &&
         "Inliner called on apply instruction in wrong function?");
  assert(I != I->getParent()->end() && "Inliner called on a terminator?");
  assert(CalleeFunction->getAbstractCC() != AbstractCC::ObjCMethod &&
         CalleeFunction->getAbstractCC() != AbstractCC::C &&
         "Cannot inline Objective-C method or C function");

  // We can't handle specializations yet.
  if (!Subs.empty())
    return false;

  CalleeEntryBB = CalleeFunction->begin();

  // Compute the SILLocation which should be used by all the inlined
  // instructions.
  Loc = MandatoryInlinedLocation::getMandatoryInlinedLocation(I->getLoc());
  DebugScope = I->getDebugScope();

  // If the caller's BB is not the last BB in the calling function, then keep
  // track of the next BB so we always insert new BBs before it; otherwise,
  // we just leave the new BBs at the end as they are by default.
  auto IBI = llvm::next(SILFunction::iterator(I->getParent()));
  InsertBeforeBB = IBI != F.end() ? IBI : nullptr;

  // Clear argument map and map ApplyInst arguments to the arguments of the
  // callee's entry block.
  ValueMap.clear();
  assert(CalleeEntryBB->bbarg_size() == Args.size() &&
         "Unexpected number of arguments to entry block of function?");
  auto BAI = CalleeEntryBB->bbarg_begin();
  for (auto AI = Args.begin(), AE = Args.end(); AI != AE; ++AI, ++BAI)
    ValueMap.insert(std::make_pair(*BAI, *AI));

  InstructionMap.clear();
  BBMap.clear();
  // Do not allow the entry block to be cloned again
  BBMap.insert(std::make_pair(CalleeEntryBB, nullptr));
  SILBasicBlock::iterator InsertPoint = llvm::next(I);
  getBuilder().setInsertionPoint(InsertPoint);
  // Recursively visit callee's BB in depth-first preorder, starting with the
  // entry block, cloning all instructions other than terminators.
  visitSILBasicBlock(CalleeEntryBB);

  // If the callee's entry block ends in a return, then we can avoid a split.
  if (ReturnInst *RI = dyn_cast<ReturnInst>(CalleeEntryBB->getTerminator())) {
    // Replace all uses of the apply instruction with the operands of the
    // return instruction, appropriately mapped.
    SILValue(I).replaceAllUsesWith(remapValue(RI->getOperand()));
    // And get rid of the no-longer-needed ApplyInst.
    SILBasicBlock::iterator II = I++;
    II->eraseFromParent();
  } else {
    // Otherwise, split the caller's basic block to create a return-to BB.
    SILBasicBlock *CallerBB = I->getParent();
    // Split the BB and do NOT create a branch between the old and new
    // BBs; we will create the appropriate terminator manually later.
    SILBasicBlock *ReturnToBB = CallerBB->splitBasicBlock(InsertPoint);
    // Place the return-to BB after all the other mapped BBs.
    if (InsertBeforeBB)
      F.getBlocks().splice(SILFunction::iterator(InsertBeforeBB), F.getBlocks(),
                           SILFunction::iterator(ReturnToBB));
    else
      F.getBlocks().splice(F.getBlocks().end(), F.getBlocks(),
                           SILFunction::iterator(ReturnToBB));
    // Create an argument on the return-to BB representing the returned value.
    SILValue RetArg = new (F.getModule()) SILArgument(I->getType(0),
                                                      ReturnToBB);
    // Replace all uses of the ApplyInst with the new argument.
    SILValue(I).replaceAllUsesWith(RetArg);
    // And get rid of the no-longer-needed ApplyInst.
    SILBasicBlock::iterator II = I++;
    II->eraseFromParent();

    // Now iterate over the callee BBs and fix up the terminators.
    getBuilder().setInsertionPoint(CallerBB);
    // We already know that the callee's entry block does not terminate with a
    // Return Inst, so it can definitely be cloned with the normal SILCloner
    // visit function.
    visit(CalleeEntryBB->getTerminator());
    for (auto BI = BBMap.begin(), BE = BBMap.end(); BI != BE; ++BI) {
      // Ignore entry block
      if (BI->first == CalleeEntryBB)
        continue;

      getBuilder().setInsertionPoint(BI->second);

      // Modify return terminators to branch to the return-to BB, rather than
      // trying to clone the ReturnInst.
      if (ReturnInst *RI = dyn_cast<ReturnInst>(BI->first->getTerminator())) {
        getBuilder().createBranch(Loc.getValue(), ReturnToBB,
                                  remapValue(RI->getOperand()));
        continue;
      }

      assert(!isa<AutoreleaseReturnInst>(BI->first->getTerminator()) &&
             "Unexpected autorelease return while inlining non-Objective-C "
             "function?");
      // Otherwise use normal visitor, which clones the existing instruction
      // but remaps basic blocks and values.
      visit(BI->first->getTerminator());
    }
  }

  return true;
}

// \brief Recursively visit a callee's BBs in depth-first preorder (only
/// processing blocks on the first visit), mapping newly visited BBs to new BBs
/// in the caller and cloning all instructions into the caller other than
/// terminators (which are handled separately later).
void SILInliner::visitSILBasicBlock(SILBasicBlock* BB) {
  SILFunction &F = getBuilder().getFunction();
  // Iterate over and visit all instructions other than the terminator to clone.
  for (auto I = BB->begin(), E = --BB->end(); I != E; ++I)
    visit(I);
  // Iterate over successors to do the depth-first search.
  for (auto &Succ : BB->getSuccs()) {
    assert (Succ.getBB() != CalleeEntryBB &&
            "Entry block should not be a successor when inlining");
    SILBasicBlock *&MappedBB = BBMap[Succ];
    // Only visit a successor that has not already been visisted.
    if (!MappedBB) {
      // Map the successor to a new BB.
      MappedBB = new (F.getModule()) SILBasicBlock(&F);
      // Create new arguments for each of the original block's arguments.
      for (auto &Arg : Succ.getBB()->getBBArgs()) {
        SILValue MappedArg = new (F.getModule()) SILArgument(Arg->getType(),
                                                             MappedBB);
        ValueMap.insert(std::make_pair(Arg, MappedArg));
      }
      // Also, move the new mapped BB to the right position in the caller
      if (InsertBeforeBB)
        F.getBlocks().splice(SILFunction::iterator(InsertBeforeBB),
                             F.getBlocks(), SILFunction::iterator(MappedBB));
      // Set the insertion point to the new mapped BB
      getBuilder().setInsertionPoint(MappedBB);
      // Recurse into the successor
      visitSILBasicBlock(Succ.getBB());
    }
  }
}
<commit_msg>[sil-inliner] In SILInliner::visitSILBasicBlock, invert for (...) { if (!Cond) { do } } -> for (...) { if (Cond) continue; do }.<commit_after>//===--- SILInliner.cpp - Inlines SIL functions ------------------*- C++ -*-==//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "swift/SILPasses/Utils/SILInliner.h"
#include "llvm/ADT/STLExtras.h"

using namespace swift;

/// \brief Inlines the callee of a given ApplyInst (which must be the value of a
/// FunctionRefInst referencing a function with a known body), into the caller
/// containing the ApplyInst, which must be the same function as provided to the
/// constructor of SILInliner. It only performs one step of inlining: it does
/// not recursively inline functions called by the callee.
///
/// \returns true on success or false if it is unable to inline the function
/// (for any reason).
bool SILInliner::inlineFunction(SILBasicBlock::iterator &I,
                                SILFunction *CalleeFunction,
                                ArrayRef<Substitution> Subs,
                                ArrayRef<SILValue> Args) {
  SILFunction &F = getBuilder().getFunction();
  assert(I->getParent()->getParent() && I->getParent()->getParent() == &F &&
         "Inliner called on apply instruction in wrong function?");
  assert(I != I->getParent()->end() && "Inliner called on a terminator?");
  assert(CalleeFunction->getAbstractCC() != AbstractCC::ObjCMethod &&
         CalleeFunction->getAbstractCC() != AbstractCC::C &&
         "Cannot inline Objective-C method or C function");

  // We can't handle specializations yet.
  if (!Subs.empty())
    return false;

  CalleeEntryBB = CalleeFunction->begin();

  // Compute the SILLocation which should be used by all the inlined
  // instructions.
  Loc = MandatoryInlinedLocation::getMandatoryInlinedLocation(I->getLoc());
  DebugScope = I->getDebugScope();

  // If the caller's BB is not the last BB in the calling function, then keep
  // track of the next BB so we always insert new BBs before it; otherwise,
  // we just leave the new BBs at the end as they are by default.
  auto IBI = llvm::next(SILFunction::iterator(I->getParent()));
  InsertBeforeBB = IBI != F.end() ? IBI : nullptr;

  // Clear argument map and map ApplyInst arguments to the arguments of the
  // callee's entry block.
  ValueMap.clear();
  assert(CalleeEntryBB->bbarg_size() == Args.size() &&
         "Unexpected number of arguments to entry block of function?");
  auto BAI = CalleeEntryBB->bbarg_begin();
  for (auto AI = Args.begin(), AE = Args.end(); AI != AE; ++AI, ++BAI)
    ValueMap.insert(std::make_pair(*BAI, *AI));

  InstructionMap.clear();
  BBMap.clear();
  // Do not allow the entry block to be cloned again
  BBMap.insert(std::make_pair(CalleeEntryBB, nullptr));
  SILBasicBlock::iterator InsertPoint = llvm::next(I);
  getBuilder().setInsertionPoint(InsertPoint);
  // Recursively visit callee's BB in depth-first preorder, starting with the
  // entry block, cloning all instructions other than terminators.
  visitSILBasicBlock(CalleeEntryBB);

  // If the callee's entry block ends in a return, then we can avoid a split.
  if (ReturnInst *RI = dyn_cast<ReturnInst>(CalleeEntryBB->getTerminator())) {
    // Replace all uses of the apply instruction with the operands of the
    // return instruction, appropriately mapped.
    SILValue(I).replaceAllUsesWith(remapValue(RI->getOperand()));
    // And get rid of the no-longer-needed ApplyInst.
    SILBasicBlock::iterator II = I++;
    II->eraseFromParent();
  } else {
    // Otherwise, split the caller's basic block to create a return-to BB.
    SILBasicBlock *CallerBB = I->getParent();
    // Split the BB and do NOT create a branch between the old and new
    // BBs; we will create the appropriate terminator manually later.
    SILBasicBlock *ReturnToBB = CallerBB->splitBasicBlock(InsertPoint);
    // Place the return-to BB after all the other mapped BBs.
    if (InsertBeforeBB)
      F.getBlocks().splice(SILFunction::iterator(InsertBeforeBB), F.getBlocks(),
                           SILFunction::iterator(ReturnToBB));
    else
      F.getBlocks().splice(F.getBlocks().end(), F.getBlocks(),
                           SILFunction::iterator(ReturnToBB));
    // Create an argument on the return-to BB representing the returned value.
    SILValue RetArg = new (F.getModule()) SILArgument(I->getType(0),
                                                      ReturnToBB);
    // Replace all uses of the ApplyInst with the new argument.
    SILValue(I).replaceAllUsesWith(RetArg);
    // And get rid of the no-longer-needed ApplyInst.
    SILBasicBlock::iterator II = I++;
    II->eraseFromParent();

    // Now iterate over the callee BBs and fix up the terminators.
    getBuilder().setInsertionPoint(CallerBB);
    // We already know that the callee's entry block does not terminate with a
    // Return Inst, so it can definitely be cloned with the normal SILCloner
    // visit function.
    visit(CalleeEntryBB->getTerminator());
    for (auto BI = BBMap.begin(), BE = BBMap.end(); BI != BE; ++BI) {
      // Ignore entry block
      if (BI->first == CalleeEntryBB)
        continue;

      getBuilder().setInsertionPoint(BI->second);

      // Modify return terminators to branch to the return-to BB, rather than
      // trying to clone the ReturnInst.
      if (ReturnInst *RI = dyn_cast<ReturnInst>(BI->first->getTerminator())) {
        getBuilder().createBranch(Loc.getValue(), ReturnToBB,
                                  remapValue(RI->getOperand()));
        continue;
      }

      assert(!isa<AutoreleaseReturnInst>(BI->first->getTerminator()) &&
             "Unexpected autorelease return while inlining non-Objective-C "
             "function?");
      // Otherwise use normal visitor, which clones the existing instruction
      // but remaps basic blocks and values.
      visit(BI->first->getTerminator());
    }
  }

  return true;
}

// \brief Recursively visit a callee's BBs in depth-first preorder (only
/// processing blocks on the first visit), mapping newly visited BBs to new BBs
/// in the caller and cloning all instructions into the caller other than
/// terminators (which are handled separately later).
void SILInliner::visitSILBasicBlock(SILBasicBlock* BB) {
  SILFunction &F = getBuilder().getFunction();

  // Clone all instructions in BB except for the terminator.
  for (auto I = BB->begin(), E = --BB->end(); I != E; ++I)
    visit(I);

  // Iterate over successors to do the depth-first search.
  for (auto &Succ : BB->getSuccs()) {
    assert (Succ.getBB() != CalleeEntryBB &&
            "Entry block should not be a successor when inlining");
    SILBasicBlock *&MappedBB = BBMap[Succ];

    // If we have already cloned the given successor, skip it.
    if (MappedBB)
      continue;

    // Otherwise map the successor to a new BB.
    MappedBB = new (F.getModule()) SILBasicBlock(&F);

    // Create new arguments for each of the original block's arguments.
    for (auto &Arg : Succ.getBB()->getBBArgs()) {
      SILValue MappedArg = new (F.getModule()) SILArgument(Arg->getType(),
                                                           MappedBB);
      ValueMap.insert(std::make_pair(Arg, MappedArg));
    }

    // Move the new mapped BB to the right position in the caller if requested.
    if (InsertBeforeBB)
      F.getBlocks().splice(SILFunction::iterator(InsertBeforeBB),
                           F.getBlocks(), SILFunction::iterator(MappedBB));

    // Set the insertion point to the new mapped BB
    getBuilder().setInsertionPoint(MappedBB);

    // Recurse into the successor
    visitSILBasicBlock(Succ.getBB());
  }
}
<|endoftext|>