<commit_before>#include "stdafx.h"
#include "AnnEngine.hpp"
#include "AnnLogger.hpp"
using namespace Annwvyn;

AnnEngine* AnnEngine::singleton(NULL);
std::shared_ptr<AnnConsole> AnnEngine::onScreenConsole(nullptr);

AnnEngine* AnnEngine::Instance()
{
	return singleton;
}

std::string AnnEngine::getAnnwvynVersion()
{
	std::stringstream version;
	version << ANN_MAJOR << "." << ANN_MINOR << "." << ANN_PATCH;
	if (ANN_EXPERIMENTAL)
		version << "-experimental";
	return version.str();
}

void AnnEngine::startGameplayLoop()
{
	while (refresh());
}

AnnEngine::AnnEngine(const char title[], std::string hmdCommand) :
	player(nullptr),
	audioEngine(nullptr),
	eventManager(nullptr),
	levelManager(nullptr),
	filesystemManager(nullptr),
	resourceManager(nullptr),
	gameObjectManager(nullptr),
	sceneryManager(nullptr),
	renderer(nullptr),
	povNode(nullptr),
	updateTime(-1),
	canAccessSubSystems(true)
{
	std::cerr << "HMD selection from command line routine retuned : " << hmdCommand << std::endl;

	//Launching initialisation routines :
	if (hmdCommand == "OgreOculusRender"
		|| hmdCommand == "OgreDefaultRender")
	{
		renderer = std::make_shared<OgreOculusRender>(title);
	}
	///else if vive
	else if (hmdCommand == "OgreOpenVRRender")
	{
		MessageBox(NULL,
				   L"The Vive rendering is not implemented yet.\n"
				   L"Sorry for that. ^^\"",
				   L"Error: Vive not implemented. Yet ;-)",
				   MB_ICONERROR);
		exit(ANN_ERR_CANTHMD);
	}
	///else if osvr
	///else if ...
	else
	{
		MessageBox(NULL,
				   L"This program can be used with multiple VR sollution.\n"
				   L"The executable should be launched from the intended launcher.\n"
				   L"If you're trying to launch it by hand, please check if your command line parameter is correct!\n\n"
				   L"Availaible command line parameter : \n\t-oculus\n",
				   L"Error: Cannot understand what HMD you want to use!",
				   MB_ICONERROR);
		exit(ANN_ERR_CANTHMD);
	}

	if (singleton)
	{
		log("Can't create 2 instances of the engine!");
		exit(ANN_ERR_MEMORY);
	}

	renderer->initOgreRoot("Annwvyn.log");

	srand(time(nullptr));
	singleton = this;

	player = std::make_shared< AnnPlayer>();
	renderer->initVrHmd();
	renderer->initPipeline();
	SceneManager = renderer->getSceneManager();

	renderer->showDebug(OgreVRRender::DebugMode::MONOSCOPIC);

	log("Setup Annwvyn's subsystems");

	//Element on this list will be updated in order by the engine each frame
	SubSystemList.push_back(levelManager = std::make_shared<AnnLevelManager>());
	SubSystemList.push_back(gameObjectManager = std::make_shared<AnnGameObjectManager>());

	//Physics engine needs to be declared before the event manager. But we want the physics engine to be updated after the event manager.

	/*The wanted order is
	- event happens (player input, timers...)
	- physics is ticked (stuff move)
	- audio is synced (sonds comes form where they should)
	- then the game can redraw*/

	physicsEngine = std::make_shared<AnnPhysicsEngine>(getSceneManager()->getRootSceneNode(), player, gameObjectManager->Objects, gameObjectManager->Triggers);
	SubSystemList.push_back(eventManager = std::make_shared< AnnEventManager>(renderer->getWindow()));
	SubSystemList.push_back(physicsEngine);
	SubSystemList.push_back(audioEngine = std::make_shared< AnnAudioEngine>());

	//These could be anywere
	SubSystemList.push_back(filesystemManager = std::make_shared<AnnFilesystemManager>(title));
	SubSystemList.push_back(resourceManager = std::make_shared<AnnResourceManager>());
	SubSystemList.push_back(sceneryManager = std::make_shared<AnnSceneryManager>(renderer));

	renderer->initClientHmdRendering();
	povNode = renderer->getCameraInformationNode();
	povNode->setPosition(player->getPosition() +
		AnnVect3(0.0f, player->getEyesHeight(), 0.0f));

	//This subsystem need the povNode object to be initialized. And the Resource manager because it wants a font file and an image background
	SubSystemList.push_back(onScreenConsole = std::make_shared<AnnConsole>());

	log("===================================================", false);
	log("Annwvyn Game Engine - Step into the Other World    ", false);
	log("Free/Libre Game Engine designed for Virtual Reality", false);
	log("Version : " + getAnnwvynVersion(), false);
	log("===================================================", false);
}

AnnEngine::~AnnEngine()
{
	//Some cute log messsages
	log("Game engine stopped. Subsystem are shutting down...");
	log("Good luck with the real world now! :3");
}

//All theses getter are for encapsulation purpose. Calling them directly would make verry long lines of code. Note that there's a whole bunch of macro in AnnEngine.hpp to help with that
std::shared_ptr<AnnEventManager> AnnEngine::getEventManager()
{
	return eventManager;
}

std::shared_ptr<AnnResourceManager> AnnEngine::getResourceManager()
{
	return resourceManager;
}

std::shared_ptr<AnnGameObjectManager> AnnEngine::getGameObjectManager()
{
	return gameObjectManager;
}

std::shared_ptr<AnnSceneryManager> AnnEngine::getSceneryManager()
{
	return sceneryManager;
}

std::shared_ptr<OgreVRRender> AnnEngine::getVRRenderer()
{
	return renderer;
}

std::shared_ptr<AnnLevelManager> AnnEngine::getLevelManager()
{
	return levelManager;
}

std::shared_ptr<AnnPlayer> AnnEngine::getPlayer()
{
	return player;
}

std::shared_ptr<AnnFilesystemManager> AnnEngine::getFileSystemManager()
{
	return filesystemManager;
}

std::shared_ptr<AnnAudioEngine> AnnEngine::getAudioEngine()
{
	return audioEngine;
}

std::shared_ptr<AnnPhysicsEngine> AnnEngine::getPhysicsEngine()
{
	return physicsEngine;
}

//This is static, but actually needs Ogre to be running. So be carefull
void AnnEngine::log(std::string message, bool flag)
{
	Ogre::String messageForLog;

	if (flag)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);
		messageForLog += "Annwvyn - ";
	}
	else
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);

	messageForLog += message;
	Ogre::LogManager::getSingleton().logMessage(messageForLog);
	if (onScreenConsole != nullptr)
		onScreenConsole->append(message);

	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
}

//Don't ask me why this is not part of the Physics engine. Actually it just calls something on the physics engine. Will be probably deleted in the future.
void AnnEngine::initPlayerPhysics()
{
	physicsEngine->initPlayerPhysics(povNode);
}

//Need to be redone.
bool AnnEngine::requestStop()
{
	//pres ESC to quit. Stupid but efficient. I like that.
	if (isKeyDown(OIS::KC_ESCAPE))
		return true;
	//If the user quit the App from the Oculus Home
	if (renderer->shouldQuit())
		return true;
	return false;
}

//This is the most important function of the whole project. It's the heartbeat of the game or app using this engine.
bool AnnEngine::refresh()
{
	//Get the rendering delta time (should be roughly equals to 1/desiredFramerate in seconds)
	updateTime = renderer->getUpdateTime();
	player->engineUpdate(getFrameTime());

	for (auto SubSystem : SubSystemList)
		if (!SubSystem->needUpdate()) continue; //If doen't need update, swith to the next
		else SubSystem->update();				//The "else" keyword is used to not put curly braces, by lazyness and by code style.

	//Update camera from player
	syncPov();

	//Update VR form real world
	renderer->updateTracking();

	//Update view
	renderer->renderAndSubmitFrame();

	//Don't laugh
	return !requestStop();
}

//This just move a node where the other node is. Yes I know about parenting. I had reasons to do it that way, but I forgot.
inline void AnnEngine::syncPov()
{
	povNode->setPosition(player->getPosition());
	povNode->setOrientation(player->getOrientation().toQuaternion());
}

//Bad. Don't use. Register an event listener and use the KeyEvent callback.
inline bool AnnEngine::isKeyDown(OIS::KeyCode key)
{
	if (!eventManager) return false;
	return eventManager->Keyboard->isKeyDown(key);
}

Ogre::SceneNode* AnnEngine::getCamera()
{
	return povNode;
}

Ogre::SceneManager* AnnEngine::getSceneManager()
{
	return SceneManager;
}

unsigned long AnnEngine::getTimeFromStartUp()
{
	return renderer->getTimer()->getMilliseconds();
}

double AnnEngine::getTimeFromStartupSeconds()
{
	return static_cast<double>(getTimeFromStartUp()) / 1000.0;
}

//the delta time of the last frame, not the current one
double AnnEngine::getFrameTime()
{
	return updateTime;
}

//Raw position and orientaiton of the head in world space. This is usefull if you want to mess around with weird stuff. This has been bodged when I integrated a LEAP motion in that mess.
OgrePose AnnEngine::getHmdPose()
{
	if (renderer)
		return renderer->returnPose;
	return OgrePose();
}

//Because Windows and the Win32 platform sucks.
void AnnEngine::openConsole()
{
#ifdef _WIN32

	//Allocate a console for this app
	if (AllocConsole())
	{
		//put stdout on this console;
#pragma warning(disable:4996) //Okay, so for some reason, freopen is "bad" because potentially dangerous. However, since I'm passing static strings here, unless you go hack the DLL, I don't know what harm you can do.
		freopen("CONOUT$", "w", stdout);
#pragma warning(default:4996)
	}

	//Redirect cerr to cout
	std::cerr.rdbuf(std::cout.rdbuf());

	SetConsoleTitle(L"Annwyn Debug Console");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);

#endif
}

//Well, I may make the pointer to the onScreenConsole more accessible.
void AnnEngine::toogleOnScreenConsole()
{
	if (onScreenConsole) onScreenConsole->toogle();
}

bool AnnEngine::appVisibleInHMD()
{
	if (renderer->isVisibleInHmd() == true) // why "== true" ? Because at some point it was returning an ovrBool, wich is the boolean type of the oculus SDK that doesn't cast correctly to a C++ bool. YES. I DON'T KNOW HOW THEY MANAGED TO FFFF TAHT UP.
		return true;
	return false;
}
<commit_msg>move the singleton check<commit_after>#include "stdafx.h"
#include "AnnEngine.hpp"
#include "AnnLogger.hpp"
using namespace Annwvyn;

AnnEngine* AnnEngine::singleton(NULL);
std::shared_ptr<AnnConsole> AnnEngine::onScreenConsole(nullptr);

AnnEngine* AnnEngine::Instance()
{
	return singleton;
}

std::string AnnEngine::getAnnwvynVersion()
{
	std::stringstream version;
	version << ANN_MAJOR << "." << ANN_MINOR << "." << ANN_PATCH;
	if (ANN_EXPERIMENTAL)
		version << "-experimental";
	return version.str();
}

void AnnEngine::startGameplayLoop()
{
	while (refresh());
}

AnnEngine::AnnEngine(const char title[], std::string hmdCommand) :
	player(nullptr),
	audioEngine(nullptr),
	eventManager(nullptr),
	levelManager(nullptr),
	filesystemManager(nullptr),
	resourceManager(nullptr),
	gameObjectManager(nullptr),
	sceneryManager(nullptr),
	renderer(nullptr),
	povNode(nullptr),
	updateTime(-1),
	canAccessSubSystems(true)
{

	if (singleton)
	{
		log("Can't create 2 instances of the engine!");
		exit(ANN_ERR_MEMORY);
	}

	std::cerr << "HMD selection from command line routine retuned : " << hmdCommand << std::endl;

	//Launching initialisation routines :
	if (hmdCommand == "OgreOculusRender"
		|| hmdCommand == "OgreDefaultRender")
	{
		renderer = std::make_shared<OgreOculusRender>(title);
	}
	///else if vive
	else if (hmdCommand == "OgreOpenVRRender")
	{
		MessageBox(NULL,
				   L"The Vive rendering is not implemented yet.\n"
				   L"Sorry for that. ^^\"",
				   L"Error: Vive not implemented. Yet ;-)",
				   MB_ICONERROR);
		exit(ANN_ERR_CANTHMD);
	}
	///else if osvr
	///else if ...
	else
	{
		MessageBox(NULL,
				   L"This program can be used with multiple VR sollution.\n"
				   L"The executable should be launched from the intended launcher.\n"
				   L"If you're trying to launch it by hand, please check if your command line parameter is correct!\n\n"
				   L"Availaible command line parameter : \n\t-oculus\n",
				   L"Error: Cannot understand what HMD you want to use!",
				   MB_ICONERROR);
		exit(ANN_ERR_CANTHMD);
	}

	renderer->initOgreRoot("Annwvyn.log");

	srand(time(nullptr));
	singleton = this;

	player = std::make_shared< AnnPlayer>();
	renderer->initVrHmd();
	renderer->initPipeline();
	SceneManager = renderer->getSceneManager();

	renderer->showDebug(OgreVRRender::DebugMode::MONOSCOPIC);

	log("Setup Annwvyn's subsystems");

	//Element on this list will be updated in order by the engine each frame
	SubSystemList.push_back(levelManager = std::make_shared<AnnLevelManager>());
	SubSystemList.push_back(gameObjectManager = std::make_shared<AnnGameObjectManager>());

	//Physics engine needs to be declared before the event manager. But we want the physics engine to be updated after the event manager.

	/*The wanted order is
	- event happens (player input, timers...)
	- physics is ticked (stuff move)
	- audio is synced (sonds comes form where they should)
	- then the game can redraw*/

	physicsEngine = std::make_shared<AnnPhysicsEngine>(getSceneManager()->getRootSceneNode(), player, gameObjectManager->Objects, gameObjectManager->Triggers);
	SubSystemList.push_back(eventManager = std::make_shared< AnnEventManager>(renderer->getWindow()));
	SubSystemList.push_back(physicsEngine);
	SubSystemList.push_back(audioEngine = std::make_shared< AnnAudioEngine>());

	//These could be anywere
	SubSystemList.push_back(filesystemManager = std::make_shared<AnnFilesystemManager>(title));
	SubSystemList.push_back(resourceManager = std::make_shared<AnnResourceManager>());
	SubSystemList.push_back(sceneryManager = std::make_shared<AnnSceneryManager>(renderer));

	renderer->initClientHmdRendering();
	povNode = renderer->getCameraInformationNode();
	povNode->setPosition(player->getPosition() +
		AnnVect3(0.0f, player->getEyesHeight(), 0.0f));

	//This subsystem need the povNode object to be initialized. And the Resource manager because it wants a font file and an image background
	SubSystemList.push_back(onScreenConsole = std::make_shared<AnnConsole>());

	log("===================================================", false);
	log("Annwvyn Game Engine - Step into the Other World    ", false);
	log("Free/Libre Game Engine designed for Virtual Reality", false);
	log("Version : " + getAnnwvynVersion(), false);
	log("===================================================", false);
}

AnnEngine::~AnnEngine()
{
	//Some cute log messsages
	log("Game engine stopped. Subsystem are shutting down...");
	log("Good luck with the real world now! :3");
}

//All theses getter are for encapsulation purpose. Calling them directly would make verry long lines of code. Note that there's a whole bunch of macro in AnnEngine.hpp to help with that
std::shared_ptr<AnnEventManager> AnnEngine::getEventManager()
{
	return eventManager;
}

std::shared_ptr<AnnResourceManager> AnnEngine::getResourceManager()
{
	return resourceManager;
}

std::shared_ptr<AnnGameObjectManager> AnnEngine::getGameObjectManager()
{
	return gameObjectManager;
}

std::shared_ptr<AnnSceneryManager> AnnEngine::getSceneryManager()
{
	return sceneryManager;
}

std::shared_ptr<OgreVRRender> AnnEngine::getVRRenderer()
{
	return renderer;
}

std::shared_ptr<AnnLevelManager> AnnEngine::getLevelManager()
{
	return levelManager;
}

std::shared_ptr<AnnPlayer> AnnEngine::getPlayer()
{
	return player;
}

std::shared_ptr<AnnFilesystemManager> AnnEngine::getFileSystemManager()
{
	return filesystemManager;
}

std::shared_ptr<AnnAudioEngine> AnnEngine::getAudioEngine()
{
	return audioEngine;
}

std::shared_ptr<AnnPhysicsEngine> AnnEngine::getPhysicsEngine()
{
	return physicsEngine;
}

//This is static, but actually needs Ogre to be running. So be carefull
void AnnEngine::log(std::string message, bool flag)
{
	Ogre::String messageForLog;

	if (flag)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);
		messageForLog += "Annwvyn - ";
	}
	else
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);

	messageForLog += message;
	Ogre::LogManager::getSingleton().logMessage(messageForLog);
	if (onScreenConsole != nullptr)
		onScreenConsole->append(message);

	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_INTENSITY);
}

//Don't ask me why this is not part of the Physics engine. Actually it just calls something on the physics engine. Will be probably deleted in the future.
void AnnEngine::initPlayerPhysics()
{
	physicsEngine->initPlayerPhysics(povNode);
}

//Need to be redone.
bool AnnEngine::requestStop()
{
	//pres ESC to quit. Stupid but efficient. I like that.
	if (isKeyDown(OIS::KC_ESCAPE))
		return true;
	//If the user quit the App from the Oculus Home
	if (renderer->shouldQuit())
		return true;
	return false;
}

//This is the most important function of the whole project. It's the heartbeat of the game or app using this engine.
bool AnnEngine::refresh()
{
	//Get the rendering delta time (should be roughly equals to 1/desiredFramerate in seconds)
	updateTime = renderer->getUpdateTime();
	player->engineUpdate(getFrameTime());

	for (auto SubSystem : SubSystemList)
		if (!SubSystem->needUpdate()) continue; //If doen't need update, swith to the next
		else SubSystem->update();				//The "else" keyword is used to not put curly braces, by lazyness and by code style.

	//Update camera from player
	syncPov();

	//Update VR form real world
	renderer->updateTracking();

	//Update view
	renderer->renderAndSubmitFrame();

	//Don't laugh
	return !requestStop();
}

//This just move a node where the other node is. Yes I know about parenting. I had reasons to do it that way, but I forgot.
inline void AnnEngine::syncPov()
{
	povNode->setPosition(player->getPosition());
	povNode->setOrientation(player->getOrientation().toQuaternion());
}

//Bad. Don't use. Register an event listener and use the KeyEvent callback.
inline bool AnnEngine::isKeyDown(OIS::KeyCode key)
{
	if (!eventManager) return false;
	return eventManager->Keyboard->isKeyDown(key);
}

Ogre::SceneNode* AnnEngine::getCamera()
{
	return povNode;
}

Ogre::SceneManager* AnnEngine::getSceneManager()
{
	return SceneManager;
}

unsigned long AnnEngine::getTimeFromStartUp()
{
	return renderer->getTimer()->getMilliseconds();
}

double AnnEngine::getTimeFromStartupSeconds()
{
	return static_cast<double>(getTimeFromStartUp()) / 1000.0;
}

//the delta time of the last frame, not the current one
double AnnEngine::getFrameTime()
{
	return updateTime;
}

//Raw position and orientaiton of the head in world space. This is usefull if you want to mess around with weird stuff. This has been bodged when I integrated a LEAP motion in that mess.
OgrePose AnnEngine::getHmdPose()
{
	if (renderer)
		return renderer->returnPose;
	return OgrePose();
}

//Because Windows and the Win32 platform sucks.
void AnnEngine::openConsole()
{
#ifdef _WIN32

	//Allocate a console for this app
	if (AllocConsole())
	{
		//put stdout on this console;
#pragma warning(disable:4996) //Okay, so for some reason, freopen is "bad" because potentially dangerous. However, since I'm passing static strings here, unless you go hack the DLL, I don't know what harm you can do.
		freopen("CONOUT$", "w", stdout);
#pragma warning(default:4996)
	}

	//Redirect cerr to cout
	std::cerr.rdbuf(std::cout.rdbuf());

	SetConsoleTitle(L"Annwyn Debug Console");
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);

#endif
}

//Well, I may make the pointer to the onScreenConsole more accessible.
void AnnEngine::toogleOnScreenConsole()
{
	if (onScreenConsole) onScreenConsole->toogle();
}

bool AnnEngine::appVisibleInHMD()
{
	if (renderer->isVisibleInHmd() == true) // why "== true" ? Because at some point it was returning an ovrBool, wich is the boolean type of the oculus SDK that doesn't cast correctly to a C++ bool. YES. I DON'T KNOW HOW THEY MANAGED TO FFFF TAHT UP.
		return true;
	return false;
}
<|endoftext|>


<commit_before>#include <regex>
#include <map>
#include <cstdint>
#include <cstdio>
#include <bitset>
#include <string>
#include <stdexcept>
#include <stack>

#include "Assembler.hpp"
#include "Assembly.hpp"

using namespace std;

const regex Assembler::rTypeExp ("(addu|add|subu|sub|and|or|xor|nor|sltu|slt|sllv|srlv|srav|jr|sll|srl|sra)\\b");
const regex Assembler::iTypeExp ("(addiu|addi|andi|ori|xori|lui|lw|sw|beq|bne|sltiu|slti)\\b");
const regex Assembler::jTypeExp ("(jal|j)\\b");

const regex Assembler::immExp ("([0-9+-]+$)");
const regex Assembler::operandExp ("\\$(\\w+)");
const regex Assembler::operandsExp ("\\$(\\w+),\\s*\\$(\\w+),\\s*\\$(\\w+)");
const regex Assembler::operandWithImmExp ("\\$(\\w+),\\s*([0-9+-]+)$");
const regex Assembler::operandsWithAddrExp ("\\$(\\w+),\\s*([0-9+-]+)\\s*\\(\\$(\\w+)\\)");
const regex Assembler::operandsWithImmExp ("\\$(\\w+),\\s*\\$(\\w+),\\s*([0-9+-]+)");

const map<string, int> Assembler::funcMap = {
    {"addu",    0b100001},
    {"add",     0b100000},
    {"sub",     0b100010},
    {"subu",    0b100011},
    {"and",     0b100100},
    {"or",      0b100101},
    {"xor",     0b100110},
    {"nor",     0b100111},
    {"slt",     0b101010},
    {"sltu",    0b101011},
    {"sll",     0b000000},
    {"srl",     0b000010},
    {"sra",     0b000011},
    {"sllv",    0b000100},
    {"srlv",    0b000110},
    {"srav",    0b000111},
    {"jr",      0b001000}
};
const map<string, int> Assembler::opcodeMap = {
    {"addi",    0b001000},
    {"addiu",   0b001001},
    {"andi",    0b001100},
    {"ori",     0b001101},
    {"xori",    0b001110},
    {"lui",     0b001111},
    {"lw",      0b100011},
    {"sw",      0b101011},
    {"beq",     0b000100},
    {"bne",     0b000101},
    {"slti",    0b001010},
    {"sltiu",   0b001011},
    {"j",       0b000010},
    {"jal",     0b000011}
};

Assembler::Assembler() {

}

Assembler::Assembler(const vector<string> &instOriginal) {
    instTrimmed = instOriginal;
    symbolTable = generateSymbolTable(instTrimmed);

    for (auto inst: instTrimmed) {
        smatch match;
        Assembly assembled;

        if (regex_search(inst, match, rTypeExp)) {
            // R-type
            assembled = getRTypeAssembly(inst, match);
        } else if (regex_search(inst, match, iTypeExp)) {
            // I-type
            assembled = getITypeAssembly(inst, match);
        } else if (regex_search(inst, match, jTypeExp)) {
            // J-type
            assembled = getJTypeAssembly(inst, match);
        }

        instAssembled.push_back(assembled);
    }
}

map<string, int> Assembler::generateSymbolTable(vector<string> &inst) {
    map<string, int> symbolTable;
    stack<string> unMarkedLabels;
    int count = 0;
    for (auto it = inst.begin(); it < inst.end();) {
        trimComment(*it);

        size_t found;
        found = it->find_first_of(':');
        if (found != string::npos) {
            // line contains label
            string labelName = it->substr(0, found);

            if (labelName.size() == 0) throw runtime_error("Zero length label");

            unMarkedLabels.push(labelName);
            *it = it->substr(found + 1);
        }

        if (it->size() == 0) {
            // nothing left
            it = inst.erase(it);
        } else {
            // statement remains

            while (!unMarkedLabels.empty()) {
                string labelName = unMarkedLabels.top();
                if (symbolTable.find(labelName) != symbolTable.end()) {
                    throw runtime_error("Duplicated label name");
                } else {
                    symbolTable[labelName] = count;
                }
                unMarkedLabels.pop();
            }

            count++;
            it++;
        }
    }

    return symbolTable;
}

void Assembler::trimComment(string &inst) {
    size_t found;

    // get rid of line comment
    found = inst.find_first_of('#');
    if (found != string::npos) {
        inst = inst.substr(0, found);
    }

    // get rid of semicolumn and garbage behind it
    found = inst.find_first_of(';');
    if (found != string::npos) {
        inst = inst.substr(0, found);
    }

    // get rid of the leading whitespace
    found = inst.find_last_not_of(" \t");
    if (found != string::npos) {
        inst = inst.substr(0, found + 1);
    }

    // get rid of the trailing whitespace
    found = inst.find_first_not_of(" \t");
    if (found != string::npos) {
        inst = inst.substr(found);
    }
}

Assembly Assembler::getRTypeAssembly(const string &inst, const smatch &match) {
    uint32_t opcode, rs, rt, rd, shamt, func;
    opcode = 0b000000;
    string funcName = match[0];

    string rsName, rtName, rdName, immName;
    smatch operands, operandsWithImm, operand;

    if (regex_search(inst, operands, operandsExp)) {
        // Regular R-type
        // i.e. Assembly with rs, rt, rd
        rsName = operands[2];
        rtName = operands[3];
        rdName = operands[1];
        rs = getOperand(rsName);
        rt = getOperand(rtName);
        rd = getOperand(rdName);
        shamt = 0b00000;
        func = funcMap.at(funcName);
    } else if (regex_search(inst, operandsWithImm, operandsWithImmExp)) {
        // Shift R-type
        // i.e. Assembly with rt, rd, shamt
        rdName = operandsWithImm[2];
        rtName = operandsWithImm[1];
        immName = operandsWithImm[3];
        rs = 0b00000;
        rd = getOperand(rdName);
        rt = getOperand(rtName);
        shamt = stoul(immName);
        func = funcMap.at(funcName);
    } else if (regex_search(inst, operand, operandExp)) {
        // JR
        rsName = operand[1];
        rs = getOperand(rsName);
        rd = 0b00000;
        rt = 0b00000;
        shamt = 0b00000;
        func = funcMap.at(funcName);
    } else {
        // Syntax Error
        cout << "Syntax error with R-type statement:" << endl;
        cout << inst << endl;
    }

    uint32_t instruction = opcode;
    instruction = (instruction << 5) | rs;
    instruction = (instruction << 5) | rt;
    instruction = (instruction << 5) | rd;
    instruction = (instruction << 5) | shamt;
    instruction = (instruction << 6) | func;

    return Assembly(instruction);
}

Assembly Assembler::getITypeAssembly(const string &inst, const smatch &match) {
    uint32_t opcode, rs, rt;
    uint32_t imm;
    uint32_t mask = 0x0000ffff;
    string funcName = match[0];

    string rsName, rtName, immName;
    smatch operandsWithImm, operandWithImm, operandsWithAddr;

    if (regex_search(inst, operandsWithImm, operandsWithImmExp)) {
        // Regular I-type
        // i.e. Assembly with rs, rt, immediate
        opcode = opcodeMap.at(funcName);
        rsName = operandsWithImm[2];
        rtName = operandsWithImm[1];
        immName = operandsWithImm[3];

        rs = getOperand(rsName);
        rt = getOperand(rtName);
        imm = static_cast<uint32_t>(stoi(immName));
    } else if (regex_search(inst, operandWithImm, operandWithImmExp)) {
        // lui
        opcode = opcodeMap.at(funcName);
        rtName = operandWithImm[1];
        immName = operandWithImm[2];

        rs = 0b00000;
        rt = getOperand(rtName);
        imm = static_cast<uint32_t>(stoi(immName));
    } else if (regex_search(inst, operandsWithAddr, operandsWithAddrExp)) {
        // Save load I-type
        opcode = opcodeMap.at(funcName);
        rsName = operandsWithAddr[3];
        rtName = operandsWithAddr[1];
        immName = operandsWithAddr[2];

        rs = getOperand(rsName);
        rt = getOperand(rtName);
        imm = static_cast<uint32_t>(stoi(immName));
    } else {
        // Syntax Error
        cout << "Syntax error with R-type statement:" << endl;
        cout << inst << endl;
    }

    uint32_t instruction = opcode;
    instruction = (instruction << 5) | rs;
    instruction = (instruction << 5) | rt;
    instruction = (instruction << 16) | (imm & mask);

    return Assembly(instruction);
}

Assembly Assembler::getJTypeAssembly(const string &inst, const smatch &match) {
    uint32_t opcode, imm;
    uint32_t mask = 0x03ffffff;
    string funcName = match[0];

    string immName;
    smatch immMatch;
    if (regex_search(inst, immMatch, immExp)) {
        opcode = opcodeMap.at(funcName);
        immName = immMatch[0];
        imm = static_cast<uint32_t>(stoi(immName));
    } else {
        // Syntax Error
        cout << "Syntax error with R-type statement:" << endl;
        cout << inst << endl;
    }

    uint32_t instruction = opcode;
    instruction = (instruction << 26) | (imm & mask);

    return Assembly(instruction);
}

vector<Assembly> Assembler::getInstAssembled() {
    return instAssembled;
}

map<string, int> Assembler::getSymbolTable() {
    return symbolTable;
}

uint32_t Assembler::getOperand(const string &operandName) {
    const static string regNames[] = {
        "zero", "at",
        "v0", "v1", "a0", "a1", "a2", "a3",
        "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
        "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
        "t8", "t9",
        "k0", "k1",
        "gp", "sp", "fp", "ra"
    };

    for (int i = 0; i < 32; ++i) {
        if (regNames[i] == operandName) return i;
    }

    cout << "Unrecongnized reg:" << operandName << endl;
    return -1;
}

ostream &operator<< (ostream &os, const Assembler &assembler) {
    for (auto inst: assembler.instAssembled) {
        os << inst << endl;
    }
    return os;
}
<commit_msg>throw errors instead of print to cout<commit_after>#include <regex>
#include <map>
#include <cstdint>
#include <cstdio>
#include <bitset>
#include <string>
#include <stdexcept>
#include <stack>

#include "Assembler.hpp"
#include "Assembly.hpp"

using namespace std;

const regex Assembler::rTypeExp ("(addu|add|subu|sub|and|or|xor|nor|sltu|slt|sllv|srlv|srav|jr|sll|srl|sra)\\b");
const regex Assembler::iTypeExp ("(addiu|addi|andi|ori|xori|lui|lw|sw|beq|bne|sltiu|slti)\\b");
const regex Assembler::jTypeExp ("(jal|j)\\b");

const regex Assembler::immExp ("([0-9+-]+$)");
const regex Assembler::operandExp ("\\$(\\w+)");
const regex Assembler::operandsExp ("\\$(\\w+),\\s*\\$(\\w+),\\s*\\$(\\w+)");
const regex Assembler::operandWithImmExp ("\\$(\\w+),\\s*([0-9+-]+)$");
const regex Assembler::operandsWithAddrExp ("\\$(\\w+),\\s*([0-9+-]+)\\s*\\(\\$(\\w+)\\)");
const regex Assembler::operandsWithImmExp ("\\$(\\w+),\\s*\\$(\\w+),\\s*([0-9+-]+)");

const map<string, int> Assembler::funcMap = {
    {"addu",    0b100001},
    {"add",     0b100000},
    {"sub",     0b100010},
    {"subu",    0b100011},
    {"and",     0b100100},
    {"or",      0b100101},
    {"xor",     0b100110},
    {"nor",     0b100111},
    {"slt",     0b101010},
    {"sltu",    0b101011},
    {"sll",     0b000000},
    {"srl",     0b000010},
    {"sra",     0b000011},
    {"sllv",    0b000100},
    {"srlv",    0b000110},
    {"srav",    0b000111},
    {"jr",      0b001000}
};
const map<string, int> Assembler::opcodeMap = {
    {"addi",    0b001000},
    {"addiu",   0b001001},
    {"andi",    0b001100},
    {"ori",     0b001101},
    {"xori",    0b001110},
    {"lui",     0b001111},
    {"lw",      0b100011},
    {"sw",      0b101011},
    {"beq",     0b000100},
    {"bne",     0b000101},
    {"slti",    0b001010},
    {"sltiu",   0b001011},
    {"j",       0b000010},
    {"jal",     0b000011}
};

Assembler::Assembler() {

}

Assembler::Assembler(const vector<string> &instOriginal) {
    instTrimmed = instOriginal;
    symbolTable = generateSymbolTable(instTrimmed);

    for (auto inst: instTrimmed) {
        smatch match;
        Assembly assembled;

        if (regex_search(inst, match, rTypeExp)) {
            // R-type
            assembled = getRTypeAssembly(inst, match);
        } else if (regex_search(inst, match, iTypeExp)) {
            // I-type
            assembled = getITypeAssembly(inst, match);
        } else if (regex_search(inst, match, jTypeExp)) {
            // J-type
            assembled = getJTypeAssembly(inst, match);
        }

        instAssembled.push_back(assembled);
    }
}

map<string, int> Assembler::generateSymbolTable(vector<string> &inst) {
    map<string, int> symbolTable;
    stack<string> unMarkedLabels;
    int count = 0;
    for (auto it = inst.begin(); it < inst.end();) {
        trimComment(*it);

        size_t found;
        found = it->find_first_of(':');
        if (found != string::npos) {
            // line contains label
            string labelName = it->substr(0, found);

            if (labelName.size() == 0) throw runtime_error("Zero length label");

            unMarkedLabels.push(labelName);
            *it = it->substr(found + 1);
        }

        if (it->size() == 0) {
            // nothing left
            it = inst.erase(it);
        } else {
            // statement remains

            while (!unMarkedLabels.empty()) {
                string labelName = unMarkedLabels.top();
                if (symbolTable.find(labelName) != symbolTable.end()) {
                    throw runtime_error("Duplicated label name");
                } else {
                    symbolTable[labelName] = count;
                }
                unMarkedLabels.pop();
            }

            count++;
            it++;
        }
    }

    return symbolTable;
}

void Assembler::trimComment(string &inst) {
    size_t found;

    // get rid of line comment
    found = inst.find_first_of('#');
    if (found != string::npos) {
        inst = inst.substr(0, found);
    }

    // get rid of semicolumn and garbage behind it
    found = inst.find_first_of(';');
    if (found != string::npos) {
        inst = inst.substr(0, found);
    }

    // get rid of the leading whitespace
    found = inst.find_last_not_of(" \t");
    if (found != string::npos) {
        inst = inst.substr(0, found + 1);
    }

    // get rid of the trailing whitespace
    found = inst.find_first_not_of(" \t");
    if (found != string::npos) {
        inst = inst.substr(found);
    }
}

Assembly Assembler::getRTypeAssembly(const string &inst, const smatch &match) {
    uint32_t opcode, rs, rt, rd, shamt, func;
    opcode = 0b000000;
    string funcName = match[0];

    string rsName, rtName, rdName, immName;
    smatch operands, operandsWithImm, operand;

    if (regex_search(inst, operands, operandsExp)) {
        // Regular R-type
        // i.e. Assembly with rs, rt, rd
        rsName = operands[2];
        rtName = operands[3];
        rdName = operands[1];
        rs = getOperand(rsName);
        rt = getOperand(rtName);
        rd = getOperand(rdName);
        shamt = 0b00000;
        func = funcMap.at(funcName);
    } else if (regex_search(inst, operandsWithImm, operandsWithImmExp)) {
        // Shift R-type
        // i.e. Assembly with rt, rd, shamt
        rdName = operandsWithImm[2];
        rtName = operandsWithImm[1];
        immName = operandsWithImm[3];
        rs = 0b00000;
        rd = getOperand(rdName);
        rt = getOperand(rtName);
        shamt = stoul(immName);
        func = funcMap.at(funcName);
    } else if (regex_search(inst, operand, operandExp)) {
        // JR
        rsName = operand[1];
        rs = getOperand(rsName);
        rd = 0b00000;
        rt = 0b00000;
        shamt = 0b00000;
        func = funcMap.at(funcName);
    } else {
        // Syntax Error
        throw logic_error("Syntax error with R-type statement: " + inst);
    }

    uint32_t instruction = opcode;
    instruction = (instruction << 5) | rs;
    instruction = (instruction << 5) | rt;
    instruction = (instruction << 5) | rd;
    instruction = (instruction << 5) | shamt;
    instruction = (instruction << 6) | func;

    return Assembly(instruction);
}

Assembly Assembler::getITypeAssembly(const string &inst, const smatch &match) {
    uint32_t opcode, rs, rt;
    uint32_t imm;
    uint32_t mask = 0x0000ffff;
    string funcName = match[0];

    string rsName, rtName, immName;
    smatch operandsWithImm, operandWithImm, operandsWithAddr;

    if (regex_search(inst, operandsWithImm, operandsWithImmExp)) {
        // Regular I-type
        // i.e. Assembly with rs, rt, immediate
        opcode = opcodeMap.at(funcName);
        rsName = operandsWithImm[2];
        rtName = operandsWithImm[1];
        immName = operandsWithImm[3];

        rs = getOperand(rsName);
        rt = getOperand(rtName);
        imm = static_cast<uint32_t>(stoi(immName));
    } else if (regex_search(inst, operandWithImm, operandWithImmExp)) {
        // lui
        opcode = opcodeMap.at(funcName);
        rtName = operandWithImm[1];
        immName = operandWithImm[2];

        rs = 0b00000;
        rt = getOperand(rtName);
        imm = static_cast<uint32_t>(stoi(immName));
    } else if (regex_search(inst, operandsWithAddr, operandsWithAddrExp)) {
        // Save load I-type
        opcode = opcodeMap.at(funcName);
        rsName = operandsWithAddr[3];
        rtName = operandsWithAddr[1];
        immName = operandsWithAddr[2];

        rs = getOperand(rsName);
        rt = getOperand(rtName);
        imm = static_cast<uint32_t>(stoi(immName));
    } else {
        // Syntax Error
        throw logic_error("Syntax error with I-type statement: " + inst);
    }

    uint32_t instruction = opcode;
    instruction = (instruction << 5) | rs;
    instruction = (instruction << 5) | rt;
    instruction = (instruction << 16) | (imm & mask);

    return Assembly(instruction);
}

Assembly Assembler::getJTypeAssembly(const string &inst, const smatch &match) {
    uint32_t opcode, imm;
    uint32_t mask = 0x03ffffff;
    string funcName = match[0];

    string immName;
    smatch immMatch;
    if (regex_search(inst, immMatch, immExp)) {
        opcode = opcodeMap.at(funcName);
        immName = immMatch[0];
        imm = static_cast<uint32_t>(stoi(immName));
    } else {
        // Syntax Error
        throw logic_error("Syntax error with J-type statement: " + inst);
    }

    uint32_t instruction = opcode;
    instruction = (instruction << 26) | (imm & mask);

    return Assembly(instruction);
}

vector<Assembly> Assembler::getInstAssembled() {
    return instAssembled;
}

map<string, int> Assembler::getSymbolTable() {
    return symbolTable;
}

uint32_t Assembler::getOperand(const string &operandName) {
    const static string regNames[] = {
        "zero", "at",
        "v0", "v1", "a0", "a1", "a2", "a3",
        "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
        "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
        "t8", "t9",
        "k0", "k1",
        "gp", "sp", "fp", "ra"
    };

    for (int i = 0; i < 32; ++i) {
        if (regNames[i] == operandName) return i;
    }

    // Syntax Error
    throw logic_error("Unrecongnized reg: " + operandName);
}

ostream &operator<< (ostream &os, const Assembler &assembler) {
    for (auto inst: assembler.instAssembled) {
        os << inst << endl;
    }
    return os;
}
<|endoftext|>


<commit_before>#include "BaseRobot.hpp"
/**
 *
 */
BaseRobot::BaseRobot() {

}

/**
 *
 */
BaseRobot::~BaseRobot() {

}

<commit_msg>Added base robot description<commit_after>#include "BaseRobot.hpp"

/*
 * The base robot
 * The BaseRobot is an abstract class that requires some core methods to be
 * overriden (onQuote, onBar, onAnalysis) so that the robot can run correctly.
 * This class also stores some private objects like the buffers and MQL API.
 */

/**
 *
 */
BaseRobot::BaseRobot() {

}

/**
 *
 */
BaseRobot::~BaseRobot() {

}

<|endoftext|>


<commit_before>#include "CCallback.hpp"

#include <map>

Callback_t CCallback::Create(
	AMX *amx, string name, string format, cell *params, cell param_offset, CCallback::Error &error)
{
	error = CCallback::Error::NONE;
	if (amx == nullptr)
	{
		error = CCallback::Error::INVALID_AMX;
		return nullptr;
	}

	if (params == nullptr)
	{
		error = CCallback::Error::INVALID_PARAMETERS;
		return nullptr;
	}

	if (name.empty())
	{
		error = CCallback::Error::EMPTY_NAME;
		return nullptr;
	}

	int cb_idx = -1;
	if (amx_FindPublic(amx, name.c_str(), &cb_idx) != AMX_ERR_NONE)
	{
		error = CCallback::Error::NOT_FOUND;
		return nullptr;
	}

	CCallback::ParamList_t param_list;
	if (format.empty() == false)
	{
		if (static_cast<cell>(params[0] / sizeof(cell)) < param_offset)
		{
			error = CCallback::Error::INVALID_PARAM_OFFSET;
			return nullptr;
		}

		cell param_idx = 0;
		cell *address_ptr = nullptr;
		cell *array_addr_ptr = nullptr;

		for (auto c = format.begin(); c != format.end(); ++c)
		{
			switch (*c)
			{
			case 'd': //decimal
			case 'i': //integer
			{
				amx_GetAddr(amx, params[param_offset + param_idx], &address_ptr);
				cell value = *address_ptr;
				if (array_addr_ptr != nullptr)
				{
					if (value <= 0)
					{
						//TODO: error: invalid array size
						return nullptr;
					}
					cell *copied_array = static_cast<cell *>(malloc(value * sizeof(cell)));
					memcpy(copied_array, array_addr_ptr, value * sizeof(cell));

					param_list.push(std::make_tuple('a', std::make_tuple(copied_array, value)));
					array_addr_ptr = nullptr;
				}
				param_list.push(std::make_tuple('c', value));
			}	break;
			case 'f': //float
			case 'b': //bool
				if (array_addr_ptr != nullptr)
				{
					//TODO: error: expected 'd'/'i' specifier for array size
					return nullptr;
				}
				amx_GetAddr(amx, params[param_offset + param_idx], &address_ptr);
				param_list.push(std::make_tuple('c', *address_ptr));
				break;
			case 's': //string
				if (array_addr_ptr != nullptr)
				{
					//TODO: error: expected 'd'/'i' specifier for array size
					return nullptr;
				}
				param_list.push(std::make_tuple('s', amx_GetCppString(amx, params[param_offset + param_idx])));
				break;
			case 'a': //array
				if (array_addr_ptr != nullptr)
				{
					//TODO: error: expected 'd'/'i' specifier for array size
					return nullptr;
				}
				amx_GetAddr(amx, params[param_offset + param_idx], &array_addr_ptr);
				break;
			case 'r': //reference
				if (array_addr_ptr != nullptr)
				{
					//TODO: error: expected 'd'/'i' specifier for array size
					return nullptr;
				}
				amx_GetAddr(amx, params[param_offset + param_idx], &address_ptr);
				param_list.push(std::make_tuple('r', address_ptr));
				break;
			default:
				error = CCallback::Error::INVALID_FORMAT_SPECIFIER;
				return nullptr;
			}
			param_idx++;
		}

		if (array_addr_ptr != nullptr)
		{
			//TODO: error: no length specified after 'a' specifier
			return nullptr;
		}
	}

	return std::make_shared<CCallback>(amx, cb_idx, std::move(param_list));
}

bool CCallback::Execute()
{
	//the user could unload a filterscript between CCallback creation and
	//execution, so we better check if the AMX instance is still valid
	if (CCallbackManager::Get()->IsValidAmx(m_AmxInstance) == false)
		return false;

	if (m_Executed == true)
		return false; //can't execute the same callback more than once because m_Params is emptied

	cell amx_address = -1;
	while (m_Params.empty() == false)
	{
		cell tmp_addr;
		auto &param = m_Params.top();
		boost::any &param_val = std::get<1>(param);
		switch (std::get<0>(param))
		{
			case 'c': //cell
				amx_Push(m_AmxInstance, boost::any_cast<cell>(param_val));
				break;
			case 's': //string
				amx_PushString(m_AmxInstance, &tmp_addr, nullptr,
					boost::any_cast<string>(param_val).c_str(), 0, 0);

				if (amx_address < 0)
					amx_address = tmp_addr;
				break;
			case 'a': //array
			{
				auto array_tuple = boost::any_cast<tuple<cell *, cell>>(param_val);
				cell *array_addr = std::get<0>(array_tuple);
				cell array_size = std::get<1>(array_tuple);
				amx_PushArray(m_AmxInstance, &tmp_addr, nullptr, array_addr, array_size);
				free(array_addr);

				if (amx_address < 0)
					amx_address = tmp_addr;
			} break;
			case 'r': //reference
				amx_PushAddress(m_AmxInstance, boost::any_cast<cell *>(param_val));
				break;
		}
		m_Params.pop();
	}

	amx_Exec(m_AmxInstance, nullptr, m_AmxCallbackIndex);
	if (amx_address >= 0)
		amx_Release(m_AmxInstance, amx_address);

	m_Executed = true;
	return true;
}

bool CCallbackManager::GetErrorString(CCallback::Error error, string &dest)
{
	static const std::map<CCallback::Error, string> error_list{
			{ CCallback::Error::INVALID_AMX, "Invalid AMX" },
			{ CCallback::Error::INVALID_PARAMETERS, "Invalid parameters" },
			{ CCallback::Error::INVALID_PARAM_OFFSET, "Parameter count does not match format specifier length" },
			{ CCallback::Error::INVALID_FORMAT_SPECIFIER, "Invalid format specifier" },
			{ CCallback::Error::EMPTY_NAME, "Empty name specified" },
			{ CCallback::Error::NOT_FOUND, "Callback does not exist" }
	};

	auto error_it = error_list.find(error);
	if (error_it != error_list.end())
	{
		dest = error_it->second;
		return true;
	}
	return false;
}
<commit_msg>lowercase error messages<commit_after>#include "CCallback.hpp"

#include <map>

Callback_t CCallback::Create(
	AMX *amx, string name, string format, cell *params, cell param_offset, CCallback::Error &error)
{
	error = CCallback::Error::NONE;
	if (amx == nullptr)
	{
		error = CCallback::Error::INVALID_AMX;
		return nullptr;
	}

	if (params == nullptr)
	{
		error = CCallback::Error::INVALID_PARAMETERS;
		return nullptr;
	}

	if (name.empty())
	{
		error = CCallback::Error::EMPTY_NAME;
		return nullptr;
	}

	int cb_idx = -1;
	if (amx_FindPublic(amx, name.c_str(), &cb_idx) != AMX_ERR_NONE)
	{
		error = CCallback::Error::NOT_FOUND;
		return nullptr;
	}

	CCallback::ParamList_t param_list;
	if (format.empty() == false)
	{
		if (static_cast<cell>(params[0] / sizeof(cell)) < param_offset)
		{
			error = CCallback::Error::INVALID_PARAM_OFFSET;
			return nullptr;
		}

		cell param_idx = 0;
		cell *address_ptr = nullptr;
		cell *array_addr_ptr = nullptr;

		for (auto c = format.begin(); c != format.end(); ++c)
		{
			switch (*c)
			{
			case 'd': //decimal
			case 'i': //integer
			{
				amx_GetAddr(amx, params[param_offset + param_idx], &address_ptr);
				cell value = *address_ptr;
				if (array_addr_ptr != nullptr)
				{
					if (value <= 0)
					{
						//TODO: error: invalid array size
						return nullptr;
					}
					cell *copied_array = static_cast<cell *>(malloc(value * sizeof(cell)));
					memcpy(copied_array, array_addr_ptr, value * sizeof(cell));

					param_list.push(std::make_tuple('a', std::make_tuple(copied_array, value)));
					array_addr_ptr = nullptr;
				}
				param_list.push(std::make_tuple('c', value));
			}	break;
			case 'f': //float
			case 'b': //bool
				if (array_addr_ptr != nullptr)
				{
					//TODO: error: expected 'd'/'i' specifier for array size
					return nullptr;
				}
				amx_GetAddr(amx, params[param_offset + param_idx], &address_ptr);
				param_list.push(std::make_tuple('c', *address_ptr));
				break;
			case 's': //string
				if (array_addr_ptr != nullptr)
				{
					//TODO: error: expected 'd'/'i' specifier for array size
					return nullptr;
				}
				param_list.push(std::make_tuple('s', amx_GetCppString(amx, params[param_offset + param_idx])));
				break;
			case 'a': //array
				if (array_addr_ptr != nullptr)
				{
					//TODO: error: expected 'd'/'i' specifier for array size
					return nullptr;
				}
				amx_GetAddr(amx, params[param_offset + param_idx], &array_addr_ptr);
				break;
			case 'r': //reference
				if (array_addr_ptr != nullptr)
				{
					//TODO: error: expected 'd'/'i' specifier for array size
					return nullptr;
				}
				amx_GetAddr(amx, params[param_offset + param_idx], &address_ptr);
				param_list.push(std::make_tuple('r', address_ptr));
				break;
			default:
				error = CCallback::Error::INVALID_FORMAT_SPECIFIER;
				return nullptr;
			}
			param_idx++;
		}

		if (array_addr_ptr != nullptr)
		{
			//TODO: error: no length specified after 'a' specifier
			return nullptr;
		}
	}

	return std::make_shared<CCallback>(amx, cb_idx, std::move(param_list));
}

bool CCallback::Execute()
{
	//the user could unload a filterscript between CCallback creation and
	//execution, so we better check if the AMX instance is still valid
	if (CCallbackManager::Get()->IsValidAmx(m_AmxInstance) == false)
		return false;

	if (m_Executed == true)
		return false; //can't execute the same callback more than once because m_Params is emptied

	cell amx_address = -1;
	while (m_Params.empty() == false)
	{
		cell tmp_addr;
		auto &param = m_Params.top();
		boost::any &param_val = std::get<1>(param);
		switch (std::get<0>(param))
		{
			case 'c': //cell
				amx_Push(m_AmxInstance, boost::any_cast<cell>(param_val));
				break;
			case 's': //string
				amx_PushString(m_AmxInstance, &tmp_addr, nullptr,
					boost::any_cast<string>(param_val).c_str(), 0, 0);

				if (amx_address < 0)
					amx_address = tmp_addr;
				break;
			case 'a': //array
			{
				auto array_tuple = boost::any_cast<tuple<cell *, cell>>(param_val);
				cell *array_addr = std::get<0>(array_tuple);
				cell array_size = std::get<1>(array_tuple);
				amx_PushArray(m_AmxInstance, &tmp_addr, nullptr, array_addr, array_size);
				free(array_addr);

				if (amx_address < 0)
					amx_address = tmp_addr;
			} break;
			case 'r': //reference
				amx_PushAddress(m_AmxInstance, boost::any_cast<cell *>(param_val));
				break;
		}
		m_Params.pop();
	}

	amx_Exec(m_AmxInstance, nullptr, m_AmxCallbackIndex);
	if (amx_address >= 0)
		amx_Release(m_AmxInstance, amx_address);

	m_Executed = true;
	return true;
}

bool CCallbackManager::GetErrorString(CCallback::Error error, string &dest)
{
	static const std::map<CCallback::Error, string> error_list{
			{ CCallback::Error::INVALID_AMX, "invalid AMX" },
			{ CCallback::Error::INVALID_PARAMETERS, "invalid parameters" },
			{ CCallback::Error::INVALID_PARAM_OFFSET, "parameter count does not match format specifier length" },
			{ CCallback::Error::INVALID_FORMAT_SPECIFIER, "invalid format specifier" },
			{ CCallback::Error::EMPTY_NAME, "empty name specified" },
			{ CCallback::Error::NOT_FOUND, "callback does not exist" }
	};

	auto error_it = error_list.find(error);
	if (error_it != error_list.end())
	{
		dest = error_it->second;
		return true;
	}
	return false;
}
<|endoftext|>


<commit_before>/**
  @file main.cpp
*/
#include "ktx.h"
#include <TextureConverter.h>
#include <FreeImage.h>
#include <stdio.h>
#include <string>
#include <iostream>

/** Print the program usage.
*/
void PrintUsage() {
  std::cout << "ATCConv ver.0.1" << std::endl;
  std::cout << "Convert PNG(24/32bit) image to KTX(ATC/ETC1 compressed format) image." << std::endl;
  std::cout << std::endl;
  std::cout << "usage: atcconv.exe [infile] [outfile]" << std::endl;
  std::cout << std::endl;
  std::cout << "  infile : input PNG(24/32bit) file path." << std::endl;
  std::cout << "  outfile: output KTX file path." << std::endl;
  std::cout << "           if not passed this option, use the infile that has replaced" << std::endl;
  std::cout << "           extention ot '.ktx'." << std::endl;
}

/** Get bytes per pixel from the format.

  @param format Q_FORMAT_???

  @return byte per pixel.
*/
uint32_t GetBytePerPixel(uint32_t format) {
  switch (format) {
  case Q_FORMAT_RGB_8I: return 3;
  default:
  case Q_FORMAT_RGBA_8I: return 4;
  }
}

/** Create TQonvertImage structure.

  @param data    the pointer to the raw image data.
  @param w       the pixel width of the image.
  @param h       the pixel height of the image.
  @param foramt  Q_FORMAT_???

  @return TQonvertImage object created with the parameter.
*/
TQonvertImage TQonvertImage_Create( void* data, uint32_t w, uint32_t h, uint32_t format = Q_FORMAT_RGBA_8I) {
  TQonvertImage n;
  n.nWidth = w;
  n.nHeight = h;
  n.nFormat = format;
  n.pFormatFlags = nullptr;
  n.nDataSize = data ? w * h * GetBytePerPixel(format) : 0;
  n.pData = reinterpret_cast<unsigned char*>(data);
  n.compressionOptions = nullptr;
  return n;
}

/** The entry point.
*/
int main(int argc, char** argv) {
  std::string infilename;
  std::string outfilename;
  for (int i = 1; i < argc; ++i) {
	if (infilename.empty()) {
	  infilename = argv[i];
	} else if (outfilename.empty()) {
	  outfilename = argv[i];
	  break;
	}
  }
  if (infilename.empty()) {
	PrintUsage();
	return 0;
  }
  if (outfilename.empty()) {
	outfilename = infilename;
	auto dotPos = outfilename.find_last_of('.');
	if (dotPos != std::string::npos) {
	  outfilename.erase(dotPos, std::string::npos);
	}
	outfilename += ".ktx";
  }

#ifdef FREE_IMAGE_STATIC_LIBRARY
  FreeImage_Initialise(FALSE);
#endif // FREE_ISTATIC_LIBRARY

  FIBITMAP* dib = FreeImage_Load(FIF_PNG, infilename.c_str(), PNG_DEFAULT);
  if (!dib) {
	std::cout << "Can't read '" << infilename << "'." << std::endl;
	return 1;
  }

  const uint32_t width = FreeImage_GetWidth(dib);
  const uint32_t height = FreeImage_GetHeight(dib);
  const uint32_t bitPerPixel = FreeImage_GetBPP(dib);
  const uint32_t destFormat = bitPerPixel == 32 ? Q_FORMAT_ATC_RGBA_INTERPOLATED_ALPHA : Q_FORMAT_ETC1_RGB8;

  TQonvertImage  src = TQonvertImage_Create(FreeImage_GetBits(dib), width, height);
  TQonvertImage  dest = TQonvertImage_Create(nullptr, width, height, destFormat);
  std::vector<uint8_t> buf;
  buf.resize(width * height * 4, 0);
  dest.nDataSize = static_cast<unsigned int>(buf.size());
  dest.pData = &buf[0];
  {
    const int result = Qonvert(&src, &dest);
    if (result != Q_SUCCESS) {
	  std::cout << "Can't convert '" << infilename << "'." << std::endl;
	  FreeImage_Unload(dib);
	  return 2;
    }
  }
  FreeImage_Unload(dib);

  KTX::Header ktxheader;
  KTX::initialize(&ktxheader, width, height, bitPerPixel == 32 ? KTX::Format_ATC_I : KTX::Format_ETC1);
  FILE* fp;
  {
	const errno_t result = fopen_s(&fp, outfilename.c_str(), "wb");
	if (result != 0) {
	  std::cout << "Can't open '" << outfilename << std::endl;
	  return 3;
	}
  }
  fwrite(&ktxheader, 1, sizeof(KTX::Header), fp);
  fwrite(&dest.nDataSize, 1, 4, fp);
  fwrite(dest.pData, 1, dest.nDataSize, fp);
  fclose(fp);

#ifdef FREE_IMAGE_STATIC_LIBRARY
  FreeImage_Deinitialise();
#endif // FREE_ISTATIC_LIBRARY
}
<commit_msg>Implement the output format selection.<commit_after>/**
  @file main.cpp
*/
#include "ktx.h"
#include <TextureConverter.h>
#include <FreeImage.h>
#include <stdio.h>
#include <string>
#include <iostream>

/** Print the program usage.
*/
void PrintUsage() {
  std::cout << "ATCConv ver.0.1" << std::endl;
  std::cout << "Convert PNG(24/32bit) image to KTX(ATC/ETC1 compressed format) image." << std::endl;
  std::cout << std::endl;
  std::cout << "usage: atcconv.exe [infile] [outfile]" << std::endl;
  std::cout << std::endl;
  std::cout << "  infile : input PNG(24/32bit) file path." << std::endl;
  std::cout << "  outfile: output KTX file path." << std::endl;
  std::cout << "           if not passed this option, use the infile that has replaced" << std::endl;
  std::cout << "           extention ot '.ktx'." << std::endl;
}

/** Get bytes per pixel from the format.

  @param format Q_FORMAT_???

  @return byte per pixel.
*/
uint32_t GetBytePerPixel(uint32_t format) {
  switch (format) {
  case Q_FORMAT_RGB_8I: return 3;
  default:
  case Q_FORMAT_RGBA_8I: return 4;
  }
}

/** Get the OpenGL format from Q_FORMAT_???.

  @param  qformat  Q_FORMAT_???. It is the TextureConverter format type.

  @return The corresponding OpenGL format of the qformat.
*/
uint32_t GetOpenGLTextureFormat(uint32_t qformat) {
  switch (qformat) {
  case Q_FORMAT_ETC1_RGB8: return KTX::Format_ETC1;
  case Q_FORMAT_ATC_RGBA_EXPLICIT_ALPHA: return KTX::Format_ATC_E;
  default:
  case Q_FORMAT_ATC_RGBA_INTERPOLATED_ALPHA: return KTX::Format_ATC_I;
  }
}

/** Create TQonvertImage structure.

  @param data    the pointer to the raw image data.
  @param w       the pixel width of the image.
  @param h       the pixel height of the image.
  @param foramt  Q_FORMAT_???

  @return TQonvertImage object created with the parameter.
*/
TQonvertImage TQonvertImage_Create( void* data, uint32_t w, uint32_t h, uint32_t format = Q_FORMAT_RGBA_8I) {
  TQonvertImage n;
  n.nWidth = w;
  n.nHeight = h;
  n.nFormat = format;
  n.pFormatFlags = nullptr;
  n.nDataSize = data ? w * h * GetBytePerPixel(format) : 0;
  n.pData = reinterpret_cast<unsigned char*>(data);
  n.compressionOptions = nullptr;
  return n;
}

struct ArgToFormat {
  const char* argname;
  uint32_t format;
};
static const ArgToFormat argToFormatList[] = {
  { "atce", Q_FORMAT_ATC_RGBA_EXPLICIT_ALPHA },
  { "atci", Q_FORMAT_ATC_RGBA_INTERPOLATED_ALPHA },
  { "etc1", Q_FORMAT_ETC1_RGB8 },
};
static const uint32_t Q_FORMAT_UNKNOWN = 0xffffffffU;

/** The entry point.
*/
int main(int argc, char** argv) {
  std::string infilename;
  std::string outfilename;
  uint32_t outputFormat = Q_FORMAT_UNKNOWN;
  for (int i = 1; i < argc; ++i) {
    if (argv[i][0] == '-') {
      if (argv[i][1] == 'f' || argv[i][1] == 'F' && (argc >= i + 1)) {
        static const ArgToFormat* const end = argToFormatList + sizeof(argToFormatList) / sizeof(argToFormatList[0]);
        for (const ArgToFormat* itr = argToFormatList; itr != end; ++itr) {
          if (strcmp(itr->argname, argv[i + 1]) == 0) {
            outputFormat = itr->format;
            break;
          }
        }
        if (outputFormat == Q_FORMAT_UNKNOWN) {
          std::cout << "Error: '" << argv[i + 1] << "' is unknown format." << std::endl;
          return 1;
        }
        ++i;
      }
      continue;
    }
	if (infilename.empty()) {
	  infilename = argv[i];
	} else if (outfilename.empty()) {
	  outfilename = argv[i];
	  break;
	}
  }
  if (outputFormat == Q_FORMAT_UNKNOWN) {
    outputFormat = Q_FORMAT_ATC_RGBA_INTERPOLATED_ALPHA;
  }
  if (infilename.empty()) {
	PrintUsage();
	return 0;
  }
  if (outfilename.empty()) {
	outfilename = infilename;
	auto dotPos = outfilename.find_last_of('.');
	if (dotPos != std::string::npos) {
	  outfilename.erase(dotPos, std::string::npos);
	}
	outfilename += ".ktx";
  }

#ifdef FREE_IMAGE_STATIC_LIBRARY
  FreeImage_Initialise(FALSE);
#endif // FREE_ISTATIC_LIBRARY

  FIBITMAP* dib = FreeImage_Load(FIF_PNG, infilename.c_str(), PNG_DEFAULT);
  if (!dib) {
	std::cout << "Can't read '" << infilename << "'." << std::endl;
	return 1;
  }

  const uint32_t width = FreeImage_GetWidth(dib);
  const uint32_t height = FreeImage_GetHeight(dib);
  const uint32_t bitPerPixel = FreeImage_GetBPP(dib);

  TFormatFlags srcFlags = { 0 };
  srcFlags.nMaskRed   = FreeImage_GetRedMask(dib);
  srcFlags.nMaskGreen = FreeImage_GetGreenMask(dib);
  srcFlags.nMaskBlue  = FreeImage_GetBlueMask(dib);
  srcFlags.nMaskAlpha = 0xff000000U;
  TQonvertImage  src = TQonvertImage_Create(FreeImage_GetBits(dib), width, height);
  src.pFormatFlags = &srcFlags;

  TFormatFlags destFlags = { 0 };
  destFlags.nFlipY = TRUE;
  TQonvertImage  dest = TQonvertImage_Create(nullptr, width, height, outputFormat);
  dest.pFormatFlags = &destFlags;
  {
    // At First, dest.pData is nullptr.
    // Qonvert return the required buffer size in dest.nDataSize.
    const int result = Qonvert(&src, &dest);
    if (result != Q_SUCCESS) {
      std::cout << "Can't convert '" << infilename << "'." << std::endl;
      FreeImage_Unload(dib);
      return 2;
    }
  }
  // Allocate the destination buffer using the size information returnd from Qonvert.
  std::vector<uint8_t> buf;
  buf.resize(dest.nDataSize);
  dest.pData = &buf[0];
  {
    // This time, Qonvert can really convert the image.
    const int result = Qonvert(&src, &dest);
    if (result != Q_SUCCESS) {
      std::cout << "Can't convert '" << infilename << "'." << std::endl;
      FreeImage_Unload(dib);
      return 2;
    }
  }
  FreeImage_Unload(dib);

  KTX::Header ktxheader;
  KTX::initialize(&ktxheader, width, height, GetOpenGLTextureFormat(outputFormat));
  FILE* fp;
  {
	const errno_t result = fopen_s(&fp, outfilename.c_str(), "wb");
	if (result != 0) {
	  std::cout << "Can't open '" << outfilename << std::endl;
	  return 3;
	}
  }
  fwrite(&ktxheader, 1, sizeof(KTX::Header), fp);
  fwrite(&dest.nDataSize, 1, 4, fp);
  fwrite(dest.pData, 1, dest.nDataSize, fp);
  fclose(fp);

#ifdef FREE_IMAGE_STATIC_LIBRARY
  FreeImage_Deinitialise();
#endif // FREE_ISTATIC_LIBRARY
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/io/p9_io_dmi_read_erepair.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file p9_io_dmi_read_erepair.C
/// @brief Read eRepair.
///----------------------------------------------------------------------------
/// *HWP HWP Owner        : Chris Steffen <cwsteffen@us.ibm.com>
/// *HWP HWP Backup Owner : Gary Peterson <garyp@us.ibm.com>
/// *HWP FW Owner         : Jamie Knight <rjknight@us.ibm.com>
/// *HWP Team             : IO
/// *HWP Level            : 2
/// *HWP Consumed by      : FSP:HB
///----------------------------------------------------------------------------
///
/// @verbatim
/// High-level procedure flow:
///
/// A HWP that runs Read eRepair. This procedure reads the current bad
/// lanes and passes by reference the lane numbers in a vector.
///
/// Procedure Prereq:
///     - System clocks are running.
///
/// @endverbatim
///----------------------------------------------------------------------------

// ----------------------------------------------------------------------------
// Includes
// ----------------------------------------------------------------------------
#include "p9_io_dmi_read_erepair.H"
#include "p9_io_scom.H"
#include "p9_io_regs.H"

// ----------------------------------------------------------------------------
// Procedure Function
// ----------------------------------------------------------------------------

/**
 * @brief A HWP that runs Read eRepair. This procedure reads the current bad
 * lanes and passes by reference the lane numbers in a vector.  The rx vectors
 * will return to the caller (PRD or e-repair) the bad lane numbers on this
 * endpoint.  The caller will duplicate the found rx bad lanes to the
 * corresponding tx bad lanes on the connected target.
 * @param[in]  i_target        Reference to Target
 * @param[out] o_bad_lanes     Vector of bad lanes
 * @retval     ReturnCode
 */
fapi2::ReturnCode p9_io_dmi_read_erepair(
    const fapi2::Target < fapi2::TARGET_TYPE_DMI >& i_target,
    std::vector< uint8_t >&                         o_bad_lanes)
{
    FAPI_IMP("p9_io_dmi_read_erepair: Entering.");
    const uint8_t GRP3             = 3;
    const uint8_t  LN0             = 0;
    const uint16_t BAD_LANES_3PLUS = 3;
    const uint16_t BAD_LANES_2     = 2;
    const uint16_t BAD_LANES_1     = 1;
    const uint16_t BAD_LANES_0     = 0;
    uint64_t       l_data          = 0;

    o_bad_lanes.clear();

    FAPI_TRY(io::read(EDIP_RX_GLBSM_STAT9_E_PG, i_target, GRP3, LN0, l_data),
             "Reading Bad Lane Code Failed.");

    FAPI_DBG("Bad Lane Code: %d", io::get(EDIP_RX_BAD_LANE_CODE, l_data));

    switch(io::get(EDIP_RX_BAD_LANE_CODE, l_data))
    {
        case BAD_LANES_3PLUS:
            FAPI_DBG("Bad Lane: Three or more bad lanes found.");

        // We will intentionally fall through to collect bad lane 1 & 2.
        case BAD_LANES_2:
            FAPI_DBG("Bad Lane 2: %d", io::get(EDIP_RX_BAD_LANE2, l_data));
            o_bad_lanes.push_back((uint8_t)io::get(EDIP_RX_BAD_LANE2, l_data));

        // We will intentionally fall through to collect bad lane 1.
        case BAD_LANES_1:
            FAPI_DBG("Bad Lane 1: %d", io::get(EDIP_RX_BAD_LANE1, l_data));
            o_bad_lanes.push_back((uint8_t)io::get(EDIP_RX_BAD_LANE1, l_data));
            break;

        case BAD_LANES_0:
            FAPI_DBG("No Bad Lanes");

        default:
            break;
    }

fapi_try_exit:
    FAPI_IMP("p9_io_dmi_read_erepair: Exiting.");
    return fapi2::current_err;
}
<commit_msg>I/O Metadata Cleanup<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/io/p9_io_dmi_read_erepair.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file p9_io_dmi_read_erepair.C
/// @brief Read eRepair.
///----------------------------------------------------------------------------
/// *HWP HWP Owner        : Chris Steffen <cwsteffen@us.ibm.com>
/// *HWP HWP Backup Owner : Gary Peterson <garyp@us.ibm.com>
/// *HWP FW Owner         : Jamie Knight <rjknight@us.ibm.com>
/// *HWP Team             : IO
/// *HWP Level            : 3
/// *HWP Consumed by      : FSP:HB
///----------------------------------------------------------------------------
///
/// @verbatim
/// High-level procedure flow:
///
/// A HWP that runs Read eRepair. This procedure reads the current bad
/// lanes and passes by reference the lane numbers in a vector.
///
/// Procedure Prereq:
///     - System clocks are running.
///
/// @endverbatim
///----------------------------------------------------------------------------

// ----------------------------------------------------------------------------
// Includes
// ----------------------------------------------------------------------------
#include "p9_io_dmi_read_erepair.H"
#include "p9_io_scom.H"
#include "p9_io_regs.H"

// ----------------------------------------------------------------------------
// Procedure Function
// ----------------------------------------------------------------------------

/**
 * @brief A HWP that runs Read eRepair. This procedure reads the current bad
 * lanes and passes by reference the lane numbers in a vector.  The rx vectors
 * will return to the caller (PRD or e-repair) the bad lane numbers on this
 * endpoint.  The caller will duplicate the found rx bad lanes to the
 * corresponding tx bad lanes on the connected target.
 * @param[in]  i_target        Reference to Target
 * @param[out] o_bad_lanes     Vector of bad lanes
 * @retval     ReturnCode
 */
fapi2::ReturnCode p9_io_dmi_read_erepair(
    const fapi2::Target < fapi2::TARGET_TYPE_DMI >& i_target,
    std::vector< uint8_t >&                         o_bad_lanes)
{
    FAPI_IMP("p9_io_dmi_read_erepair: Entering.");
    const uint8_t GRP3             = 3;
    const uint8_t  LN0             = 0;
    const uint16_t BAD_LANES_3PLUS = 3;
    const uint16_t BAD_LANES_2     = 2;
    const uint16_t BAD_LANES_1     = 1;
    const uint16_t BAD_LANES_0     = 0;
    uint64_t       l_data          = 0;

    o_bad_lanes.clear();

    FAPI_TRY(io::read(EDIP_RX_GLBSM_STAT9_E_PG, i_target, GRP3, LN0, l_data),
             "Reading Bad Lane Code Failed.");

    FAPI_DBG("Bad Lane Code: %d", io::get(EDIP_RX_BAD_LANE_CODE, l_data));

    switch(io::get(EDIP_RX_BAD_LANE_CODE, l_data))
    {
        case BAD_LANES_3PLUS:
            FAPI_DBG("Bad Lane: Three or more bad lanes found.");

        // We will intentionally fall through to collect bad lane 1 & 2.
        case BAD_LANES_2:
            FAPI_DBG("Bad Lane 2: %d", io::get(EDIP_RX_BAD_LANE2, l_data));
            o_bad_lanes.push_back((uint8_t)io::get(EDIP_RX_BAD_LANE2, l_data));

        // We will intentionally fall through to collect bad lane 1.
        case BAD_LANES_1:
            FAPI_DBG("Bad Lane 1: %d", io::get(EDIP_RX_BAD_LANE1, l_data));
            o_bad_lanes.push_back((uint8_t)io::get(EDIP_RX_BAD_LANE1, l_data));
            break;

        case BAD_LANES_0:
            FAPI_DBG("No Bad Lanes");

        default:
            break;
    }

fapi_try_exit:
    FAPI_IMP("p9_io_dmi_read_erepair: Exiting.");
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/ecc/ecc_traits.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
<commit_msg>Adding ECC syndrome register access functions<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/ecc/ecc_traits.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file ecc_traits.C
/// @brief Traits class for the MC ECC syndrome registers
///
// *HWP HWP Owner: Louis Stermole <stermole@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: FSP:HB

#include <fapi2.H>
#include <lib/ecc/ecc_traits.H>

namespace mss
{

// we need these declarations here in order for the linker to see the definitions
// in the eccTraits class
constexpr const uint64_t eccTraits<fapi2::TARGET_TYPE_MCA>::MAINLINE_NCE_REGS[];
constexpr const uint64_t eccTraits<fapi2::TARGET_TYPE_MCA>::MAINLINE_RCE_REGS[];
constexpr const uint64_t eccTraits<fapi2::TARGET_TYPE_MCA>::MAINLINE_MPE_REGS[];
constexpr const uint64_t eccTraits<fapi2::TARGET_TYPE_MCA>::MAINLINE_UE_REGS[];
constexpr const uint64_t eccTraits<fapi2::TARGET_TYPE_MCA>::MAINLINE_AUE_REGS[];
constexpr const uint64_t eccTraits<fapi2::TARGET_TYPE_MCA>::ERROR_VECTOR_REGS[];

} // close namespace mss
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/utils/mss_pair.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file mss_pair.H
/// @brief Creates a pair class that has a constexpr constructor
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: HB:FSP

#ifndef _MSS_PAIR_CONST_H_
#define _MSS_PAIR_CONST_H_

#include <fapi2.H>
#include <lib/utils/find.H>
#include <lib/utils/c_str.H>

namespace mss
{

///
/// @brief a version of std::pair that has a constexpr constructor
/// allows for MUCH cleaner code and code that can be run at compile time
/// @tparam T1 - type of first
/// @tparam T2 - type of second
///
template <typename T1, typename T2>
struct pair
{
    // forces the user to initialize the values
    pair() = delete;

    // disables the copy constructor
    pair( const pair<T1, T2>& i_rhs) = delete;

    ///
    /// @brief default destructor
    ///
    ~pair() = default;

    ///
    /// @brief constexpr constructor
    /// @param[in] i_first - input to the first internal variable
    /// @param[in] i_second - input to the second internal variable
    ///
    constexpr pair(const T1& i_first, const T2& i_second) :
        first(i_first),
        second(i_second)
    {}

    // not using iv_ to keep this as close as possible to pair
    T1 first;
    T2 second;
};

}
#endif
<commit_msg>Add c_str generic API and update makefiles<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/memory/lib/utils/mss_pair.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

///
/// @file mss_pair.H
/// @brief Creates a pair class that has a constexpr constructor
///
// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
// *HWP HWP Backup: Brian Silver <bsilver@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 2
// *HWP Consumed by: HB:FSP

#ifndef _MSS_PAIR_CONST_H_
#define _MSS_PAIR_CONST_H_

#include <fapi2.H>
#include <lib/utils/find.H>
#include <c_str.H>

namespace mss
{

///
/// @brief a version of std::pair that has a constexpr constructor
/// allows for MUCH cleaner code and code that can be run at compile time
/// @tparam T1 - type of first
/// @tparam T2 - type of second
///
template <typename T1, typename T2>
struct pair
{
    // forces the user to initialize the values
    pair() = delete;

    // disables the copy constructor
    pair( const pair<T1, T2>& i_rhs) = delete;

    ///
    /// @brief default destructor
    ///
    ~pair() = default;

    ///
    /// @brief constexpr constructor
    /// @param[in] i_first - input to the first internal variable
    /// @param[in] i_second - input to the second internal variable
    ///
    constexpr pair(const T1& i_first, const T2& i_second) :
        first(i_first),
        second(i_second)
    {}

    // not using iv_ to keep this as close as possible to pair
    T1 first;
    T2 second;
};

}
#endif
<|endoftext|>


<commit_before><commit_msg>Fix constraint for skipping Lod Level<commit_after><|endoftext|>


<commit_before>/****************************************************************************
** libebml : parse EBML files, see http://embl.sourceforge.net/
**
** <file/class description>
**
** Copyright (C) 2002-2010 Steve Lhomme.  All rights reserved.
**
** This file is part of libebml.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
** See http://www.gnu.org/licenses/lgpl-2.1.html for LGPL licensing information.
**
** Contact license@matroska.org if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/

/*!
  \file
  \version \$Id$
  \author Steve Lhomme     <robux4 @ users.sf.net>
*/

#include <cassert>

#include "ebml/EbmlFloat.h"

START_LIBEBML_NAMESPACE

EbmlFloat::EbmlFloat(const EbmlFloat::Precision prec)
  :EbmlElement(0, false)
{
  SetPrecision(prec);
}

EbmlFloat::EbmlFloat(const double aDefaultValue, const EbmlFloat::Precision prec)
  :EbmlElement(0, true), Value(aDefaultValue), DefaultValue(aDefaultValue)
{
  SetDefaultIsSet();
  SetPrecision(prec);
}

EbmlFloat::EbmlFloat(const EbmlFloat & ElementToClone)
  :EbmlElement(ElementToClone)
  ,Value(ElementToClone.Value)
  ,DefaultValue(ElementToClone.DefaultValue)
{
}

void EbmlFloat::SetDefaultValue(double aValue)
{
  assert(!DefaultISset());
  DefaultValue = aValue;
  SetDefaultIsSet();
}

double EbmlFloat::DefaultVal() const
{
  assert(DefaultISset());
  return DefaultValue;
}

EbmlFloat::operator float() const {return float(Value);}
EbmlFloat::operator double() const {return double(Value);}

double EbmlFloat::GetValue() const {return Value;}

EbmlFloat & EbmlFloat::SetValue(double NewValue) {
  return *this = NewValue;
}

/*!
  \todo handle exception on errors
  \todo handle 10 bits precision
*/
filepos_t EbmlFloat::RenderData(IOCallback & output, bool /* bForceRender */, bool /* bWithDefault */)
{
  assert(GetSize() == 4 || GetSize() == 8);

  if (GetSize() == 4) {
    float val = Value;
    int Tmp;
    memcpy(&Tmp, &val, 4);
    big_int32 TmpToWrite(Tmp);
    output.writeFully(&TmpToWrite.endian(), GetSize());
  } else if (GetSize() == 8) {
    double val = Value;
    int64 Tmp;
    memcpy(&Tmp, &val, 8);
    big_int64 TmpToWrite(Tmp);
    output.writeFully(&TmpToWrite.endian(), GetSize());
  }

  return GetSize();
}

uint64 EbmlFloat::UpdateSize(bool bWithDefault, bool  /* bForceRender */)
{
  if (!bWithDefault && IsDefaultValue())
    return 0;
  return GetSize();
}

/*!
  \todo remove the hack for possible endianess pb (test on little & big endian)
*/
filepos_t EbmlFloat::ReadData(IOCallback & input, ScopeMode ReadFully)
{
  if (ReadFully != SCOPE_NO_DATA) {
    binary Buffer[20];
    assert(GetSize() <= 20);
    input.readFully(Buffer, GetSize());

    if (GetSize() == 4) {
      big_int32 TmpRead;
      TmpRead.Eval(Buffer);
      int32 tmpp = int32(TmpRead);
      float val;
      memcpy(&val, &tmpp, 4);
      Value = val;
      SetValueIsSet();
    } else if (GetSize() == 8) {
      big_int64 TmpRead;
      TmpRead.Eval(Buffer);
      int64 tmpp = int64(TmpRead);
      double val;
      memcpy(&val, &tmpp, 8);
      Value = val;
      SetValueIsSet();
    }
  }

  return GetSize();
}

bool EbmlFloat::IsSmallerThan(const EbmlElement *Cmp) const
{
  if (EbmlId(*this) == EbmlId(*Cmp))
    return this->Value < static_cast<const EbmlFloat *>(Cmp)->Value;
  else
    return false;
}

END_LIBEBML_NAMESPACE
<commit_msg>explicitly cast float to double to avoid warning with -Wdouble-promotion<commit_after>/****************************************************************************
** libebml : parse EBML files, see http://embl.sourceforge.net/
**
** <file/class description>
**
** Copyright (C) 2002-2010 Steve Lhomme.  All rights reserved.
**
** This file is part of libebml.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
** See http://www.gnu.org/licenses/lgpl-2.1.html for LGPL licensing information.
**
** Contact license@matroska.org if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/

/*!
  \file
  \version \$Id$
  \author Steve Lhomme     <robux4 @ users.sf.net>
*/

#include <cassert>

#include "ebml/EbmlFloat.h"

START_LIBEBML_NAMESPACE

EbmlFloat::EbmlFloat(const EbmlFloat::Precision prec)
  :EbmlElement(0, false)
{
  SetPrecision(prec);
}

EbmlFloat::EbmlFloat(const double aDefaultValue, const EbmlFloat::Precision prec)
  :EbmlElement(0, true), Value(aDefaultValue), DefaultValue(aDefaultValue)
{
  SetDefaultIsSet();
  SetPrecision(prec);
}

EbmlFloat::EbmlFloat(const EbmlFloat & ElementToClone)
  :EbmlElement(ElementToClone)
  ,Value(ElementToClone.Value)
  ,DefaultValue(ElementToClone.DefaultValue)
{
}

void EbmlFloat::SetDefaultValue(double aValue)
{
  assert(!DefaultISset());
  DefaultValue = aValue;
  SetDefaultIsSet();
}

double EbmlFloat::DefaultVal() const
{
  assert(DefaultISset());
  return DefaultValue;
}

EbmlFloat::operator float() const {return float(Value);}
EbmlFloat::operator double() const {return double(Value);}

double EbmlFloat::GetValue() const {return Value;}

EbmlFloat & EbmlFloat::SetValue(double NewValue) {
  return *this = NewValue;
}

/*!
  \todo handle exception on errors
  \todo handle 10 bits precision
*/
filepos_t EbmlFloat::RenderData(IOCallback & output, bool /* bForceRender */, bool /* bWithDefault */)
{
  assert(GetSize() == 4 || GetSize() == 8);

  if (GetSize() == 4) {
    float val = Value;
    int Tmp;
    memcpy(&Tmp, &val, 4);
    big_int32 TmpToWrite(Tmp);
    output.writeFully(&TmpToWrite.endian(), GetSize());
  } else if (GetSize() == 8) {
    double val = Value;
    int64 Tmp;
    memcpy(&Tmp, &val, 8);
    big_int64 TmpToWrite(Tmp);
    output.writeFully(&TmpToWrite.endian(), GetSize());
  }

  return GetSize();
}

uint64 EbmlFloat::UpdateSize(bool bWithDefault, bool  /* bForceRender */)
{
  if (!bWithDefault && IsDefaultValue())
    return 0;
  return GetSize();
}

/*!
  \todo remove the hack for possible endianess pb (test on little & big endian)
*/
filepos_t EbmlFloat::ReadData(IOCallback & input, ScopeMode ReadFully)
{
  if (ReadFully != SCOPE_NO_DATA) {
    binary Buffer[20];
    assert(GetSize() <= 20);
    input.readFully(Buffer, GetSize());

    if (GetSize() == 4) {
      big_int32 TmpRead;
      TmpRead.Eval(Buffer);
      int32 tmpp = int32(TmpRead);
      float val;
      memcpy(&val, &tmpp, 4);
      Value = static_cast<double>(val);
      SetValueIsSet();
    } else if (GetSize() == 8) {
      big_int64 TmpRead;
      TmpRead.Eval(Buffer);
      int64 tmpp = int64(TmpRead);
      double val;
      memcpy(&val, &tmpp, 8);
      Value = val;
      SetValueIsSet();
    }
  }

  return GetSize();
}

bool EbmlFloat::IsSmallerThan(const EbmlElement *Cmp) const
{
  if (EbmlId(*this) == EbmlId(*Cmp))
    return this->Value < static_cast<const EbmlFloat *>(Cmp)->Value;
  else
    return false;
}

END_LIBEBML_NAMESPACE
<|endoftext|>