<commit_before>/***********************************************************************
 *    filename:   Element.cpp
 *    created:    28/10/2011
 *    author:     Martin Preisler
 *************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2011 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/

#include "CEGUI/Element.h"

#include <boost/test/unit_test.hpp>
#include <boost/timer.hpp>

BOOST_AUTO_TEST_SUITE(Element)

BOOST_AUTO_TEST_CASE(RelativeSizing)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::percent(), 25.0f * CEGUI::UDim::percent()));
    root->addChild(child);

    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(100.0f, 100.0f));
    BOOST_CHECK_EQUAL(child->getPixelSize(), CEGUI::Sizef(50.0f, 25.0f));

    CEGUI::Element* innerChild = new CEGUI::Element();
    child->addChild(innerChild);
    innerChild->setSize(CEGUI::USize(200.0f * CEGUI::UDim::percent(), 100.0f * CEGUI::UDim::percent()));
    BOOST_CHECK_EQUAL(innerChild->getPixelSize(), CEGUI::Sizef(100.0f, 25.0f));

    delete innerChild;
    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(HorizontalLeftAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getHorizontalAlignment(), CEGUI::HA_LEFT);
    BOOST_CHECK_EQUAL(child->getHorizontalAlignment(), CEGUI::HA_LEFT);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 0));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 50, 0));

    child->setPosition(CEGUI::UVector2(10.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(10, 0, 60, 0));
}

BOOST_AUTO_TEST_CASE(HorizontalCentreAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getHorizontalAlignment(), CEGUI::HA_LEFT);
    child->setHorizontalAlignment(CEGUI::HA_CENTRE);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 0));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(25, 0, 75, 0));

    child->setPosition(CEGUI::UVector2(10.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(35, 0, 85, 0));
}

BOOST_AUTO_TEST_CASE(HorizontalRightAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getHorizontalAlignment(), CEGUI::HA_LEFT);
    child->setHorizontalAlignment(CEGUI::HA_RIGHT);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 0));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(50, 0, 100, 0));

    child->setPosition(CEGUI::UVector2(-10.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(40, 0, 90, 0));
}

BOOST_AUTO_TEST_CASE(VerticalTopAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 25.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getVerticalAlignment(), CEGUI::VA_TOP);
    BOOST_CHECK_EQUAL(child->getVerticalAlignment(), CEGUI::VA_TOP);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 100));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 25));

    child->setPosition(CEGUI::UVector2(0.0f * CEGUI::UDim::px(), 5.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 5, 0, 30));
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Added vertical centre and bottom element test cases<commit_after>/***********************************************************************
 *    filename:   Element.cpp
 *    created:    28/10/2011
 *    author:     Martin Preisler
 *************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2011 Paul D Turner & The CEGUI Development Team
 *
 *   Permission is hereby granted, free of charge, to any person obtaining
 *   a copy of this software and associated documentation files (the
 *   "Software"), to deal in the Software without restriction, including
 *   without limitation the rights to use, copy, modify, merge, publish,
 *   distribute, sublicense, and/or sell copies of the Software, and to
 *   permit persons to whom the Software is furnished to do so, subject to
 *   the following conditions:
 *
 *   The above copyright notice and this permission notice shall be
 *   included in all copies or substantial portions of the Software.
 *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 *   OTHER DEALINGS IN THE SOFTWARE.
 ***************************************************************************/

#include "CEGUI/Element.h"

#include <boost/test/unit_test.hpp>
#include <boost/timer.hpp>

BOOST_AUTO_TEST_SUITE(Element)

BOOST_AUTO_TEST_CASE(RelativeSizing)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::percent(), 25.0f * CEGUI::UDim::percent()));
    root->addChild(child);

    BOOST_CHECK_EQUAL(root->getPixelSize(), CEGUI::Sizef(100.0f, 100.0f));
    BOOST_CHECK_EQUAL(child->getPixelSize(), CEGUI::Sizef(50.0f, 25.0f));

    CEGUI::Element* innerChild = new CEGUI::Element();
    child->addChild(innerChild);
    innerChild->setSize(CEGUI::USize(200.0f * CEGUI::UDim::percent(), 100.0f * CEGUI::UDim::percent()));
    BOOST_CHECK_EQUAL(innerChild->getPixelSize(), CEGUI::Sizef(100.0f, 25.0f));

    delete innerChild;
    delete child;
    delete root;
}

BOOST_AUTO_TEST_CASE(HorizontalLeftAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getHorizontalAlignment(), CEGUI::HA_LEFT);
    BOOST_CHECK_EQUAL(child->getHorizontalAlignment(), CEGUI::HA_LEFT);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 0));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 50, 0));

    child->setPosition(CEGUI::UVector2(10.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(10, 0, 60, 0));
}

BOOST_AUTO_TEST_CASE(HorizontalCentreAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getHorizontalAlignment(), CEGUI::HA_LEFT);
    child->setHorizontalAlignment(CEGUI::HA_CENTRE);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 0));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(25, 0, 75, 0));

    child->setPosition(CEGUI::UVector2(10.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(35, 0, 85, 0));
}

BOOST_AUTO_TEST_CASE(HorizontalRightAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(100.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(50.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getHorizontalAlignment(), CEGUI::HA_LEFT);
    child->setHorizontalAlignment(CEGUI::HA_RIGHT);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 100, 0));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(50, 0, 100, 0));

    child->setPosition(CEGUI::UVector2(-10.0f * CEGUI::UDim::px(), 0.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(40, 0, 90, 0));
}

BOOST_AUTO_TEST_CASE(VerticalTopAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 50.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getVerticalAlignment(), CEGUI::VA_TOP);
    BOOST_CHECK_EQUAL(child->getVerticalAlignment(), CEGUI::VA_TOP);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 100));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 50));

    child->setPosition(CEGUI::UVector2(0.0f * CEGUI::UDim::px(), 5.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 5, 0, 55));
}

BOOST_AUTO_TEST_CASE(VerticalCentreAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 50.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getVerticalAlignment(), CEGUI::VA_TOP);
    child->setVerticalAlignment(CEGUI::VA_CENTRE);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 100));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 25, 0, 75));

    child->setPosition(CEGUI::UVector2(0.0f * CEGUI::UDim::px(), 5.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 30, 0, 80));
}

BOOST_AUTO_TEST_CASE(VerticalBottomAlignment)
{
    CEGUI::Element* root = new CEGUI::Element();
    root->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 100 * CEGUI::UDim::px()));
    CEGUI::Element* child = new CEGUI::Element();
    child->setSize(CEGUI::USize(0.0f * CEGUI::UDim::px(), 50.0f * CEGUI::UDim::px()));
    root->addChild(child);

    // even though it is the default at the point of writing the test, we have to make sure this fact doesn't change!
    BOOST_CHECK_EQUAL(root->getVerticalAlignment(), CEGUI::VA_TOP);
    child->setVerticalAlignment(CEGUI::VA_BOTTOM);

    BOOST_CHECK_EQUAL(root->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 0, 0, 100));
    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 50, 0, 100));

    child->setPosition(CEGUI::UVector2(0.0f * CEGUI::UDim::px(), -5.0f * CEGUI::UDim::px()));

    BOOST_CHECK_EQUAL(child->getUnclippedOuterRect().get(), CEGUI::Rectf(0, 45, 0, 95));
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "ElfRelocator.h"
#include "Core/Common.h"
#include "Core/Misc.h"
#include "Util/CRC.h"
#include "Util/Util.h"
#include "Commands/CAssemblerLabel.h"

struct ArFileHeader
{
	char fileName[16];
	char modifactionTime[12];
	char ownerId[6];
	char groupId[6];
	char fileMode[8];
	char fileSize[10];
	char magic[2];
};

struct ArFileEntry
{
	std::wstring name;
	ByteArray data;
};

std::vector<ArFileEntry> loadArArchive(const std::wstring& inputName)
{
	ByteArray input = ByteArray::fromFile(inputName);
	std::vector<ArFileEntry> result;

	if (memcmp(input.data(),"!<arch>\n",8) != 0)
	{
		if (memcmp(input.data(),"\x7F""ELF",4) != 0)
			return result;

		ArFileEntry entry;
		entry.name = getFileNameFromPath(inputName);
		entry.data = input;
		result.push_back(entry);
		return result;
	}

	size_t pos = 8;
	while (pos < input.size())
	{
		ArFileHeader* header = (ArFileHeader*) input.data(pos);
		pos += sizeof(ArFileHeader);

		// get file size
		int size = 0;
		for (int i = 0; i < 10; i++)
		{
			if (header->fileSize[i] == ' ')
				break;

			size = size*10;
			size += (header->fileSize[i]-'0');
		}

		// only ELF files are actually interesting
		if (memcmp(input.data(pos),"\x7F""ELF",4) == 0)
		{
			// get file name
			char fileName[17];
			fileName[16] = 0;
			for (int i = 0; i < 16; i++)
			{
				if (header->fileName[i] == ' ')
				{
					// remove trailing slashes of file names
					if (i > 0 && fileName[i-1] == '/')
						i--;
					fileName[i] = 0;
					break;;
				}

				fileName[i] = header->fileName[i];
			}

			ArFileEntry entry;
			entry.name = convertUtf8ToWString(fileName);
			entry.data = input.mid(pos,size);
			result.push_back(entry);
		}

		pos += size;
		if (pos % 2)
			pos++;
	}

	return result;
}

bool ElfRelocator::init(const std::wstring& inputName)
{
	relocator = Arch->getElfRelocator();
	if (relocator == nullptr)
	{
		Logger::printError(Logger::Error,L"Object importing not supported for this architecture");
		return false;
	}

	auto inputFiles = loadArArchive(inputName);
	if (inputFiles.size() == 0)
	{
		Logger::printError(Logger::Error,L"Could not load library");
		return false;
	}

	for (ArFileEntry& entry: inputFiles)
	{
		ElfRelocatorFile file;

		ElfFile* elf = new ElfFile();
		if (elf->load(entry.data,false) == false)
		{
			Logger::printError(Logger::Error,L"Could not load object file %s",entry.name);
			return false;
		}

		if (elf->getType() != ET_REL)
		{
			Logger::printError(Logger::Error,L"Unexpected ELF type %d in object file %s",elf->getType(),entry.name);
			return false;
		}

		if (elf->getMachine() != relocator->expectedMachine())
		{
			Logger::printError(Logger::Error,L"Unexpected ELF machine %d in object file %s",elf->getMachine(),entry.name);
			return false;
		}

		if (elf->getEndianness() != Arch->getEndianness())
		{
			Logger::printError(Logger::Error,L"Incorrect endianness in object file %s",entry.name);
			return false;
		}

		if (elf->getSegmentCount() != 0)
		{
			Logger::printError(Logger::Error,L"Unexpected segment count %d in object file %s",elf->getSegmentCount(),entry.name);
			return false;
		}

		// load all relevant sections of this file
		for (size_t s = 0; s < elf->getSegmentlessSectionCount(); s++)
		{
			ElfSection* sec = elf->getSegmentlessSection(s);
			if (!(sec->getFlags() & SHF_ALLOC))
				continue;

			if (sec->getType() == SHT_PROGBITS || sec->getType() == SHT_NOBITS || sec->getType() == SHT_INIT_ARRAY)
			{
				ElfRelocatorSection sectionEntry;
				sectionEntry.section = sec;
				sectionEntry.index = s;
				sectionEntry.relSection = nullptr;
				sectionEntry.label = nullptr;

				// search relocation section
				for (size_t k = 0; k < elf->getSegmentlessSectionCount(); k++)
				{
					ElfSection* relSection = elf->getSegmentlessSection(k);
					if (relSection->getType() != SHT_REL)
						continue;
					if (relSection->getInfo() != s)
						continue;

					// got it
					sectionEntry.relSection = relSection;
					break;
				}

				// keep track of constructor sections
				if (sec->getName() == ".ctors" || sec->getName() == ".init_array")
				{
					ElfRelocatorCtor ctor;
					ctor.symbolName = Global.symbolTable.getUniqueLabelName();
					ctor.size = sec->getSize();

					sectionEntry.label = Global.symbolTable.getLabel(ctor.symbolName,-1,-1);
					sectionEntry.label->setDefined(true);

					ctors.push_back(ctor);
				}

				file.sections.push_back(sectionEntry);
			}
		}

		// init exportable symbols
		for (int i = 0; i < elf->getSymbolCount(); i++)
		{
			Elf32_Sym symbol;
			elf->getSymbol(symbol, i);

			if (ELF32_ST_BIND(symbol.st_info) == STB_GLOBAL && symbol.st_shndx != 0)
			{
				ElfRelocatorSymbol symEntry;
				symEntry.type = ELF32_ST_TYPE(symbol.st_info);
				symEntry.name = convertUtf8ToWString(elf->getStrTableString(symbol.st_name));
				symEntry.relativeAddress = symbol.st_value;
				symEntry.section = symbol.st_shndx;
				symEntry.size = symbol.st_size;
				symEntry.label = nullptr;

				file.symbols.push_back(symEntry);
			}
		}

		file.elf = elf;
		file.name = entry.name;
		files.push_back(file);
	}

	return true;
}

bool ElfRelocator::exportSymbols()
{
	bool error = false;

	for (ElfRelocatorFile& file: files)
	{
		for (ElfRelocatorSymbol& sym: file.symbols)
		{
			if (sym.label != nullptr)
				continue;

			std::wstring lowered = sym.name;
			std::transform(lowered.begin(), lowered.end(), lowered.begin(), ::towlower);

			sym.label = Global.symbolTable.getLabel(lowered,-1,-1);
			if (sym.label == nullptr)
			{
				Logger::printError(Logger::Error,L"Invalid label name \"%s\"",sym.name);
				error = true;
				continue;
			}

			if (sym.label->isDefined())
			{
				Logger::printError(Logger::Error,L"Label \"%s\" already defined",sym.name);
				error = true;
				continue;
			}

			RelocationData data;
			data.symbolAddress = sym.relativeAddress;
			relocator->setSymbolAddress(data,sym.relativeAddress,sym.type);

			sym.relativeAddress = data.symbolAddress;
			sym.label->setInfo(data.targetSymbolInfo);
			sym.label->setIsData(sym.type == STT_OBJECT);
			sym.label->setUpdateInfo(false);

			sym.label->setValue(0);
			sym.label->setDefined(true);
			sym.label->setOriginalName(sym.name);
		}
	}

	return !error;
}

CAssemblerCommand* ElfRelocator::generateCtor(const std::wstring& ctorName)
{
	CAssemblerCommand* content = relocator->generateCtorStub(ctors);

	CDirectiveFunction* func = new CDirectiveFunction(ctorName,ctorName);
	func->setContent(content);
	return func;
}

void ElfRelocator::loadRelocation(Elf32_Rel& rel, ByteArray& data, int offset, Endianness endianness)
{
	rel.r_offset = data.getDoubleWord(offset + 0x00, endianness);
	rel.r_info   = data.getDoubleWord(offset + 0x04, endianness);
}

bool ElfRelocator::relocateFile(ElfRelocatorFile& file, int64_t& relocationAddress)
{
	ElfFile* elf = file.elf;
	int64_t start = relocationAddress;

	// calculate address for each section
	std::map<int64_t,int64_t> relocationOffsets;
	for (ElfRelocatorSection& entry: file.sections)
	{
		ElfSection* section = entry.section;
		size_t index = entry.index;
		int size = section->getSize();

		while (relocationAddress % section->getAlignment())
			relocationAddress++;

		if (entry.label != nullptr)
			entry.label->setValue(relocationAddress);

		relocationOffsets[index] = relocationAddress;
		relocationAddress += size;
	}

	size_t dataStart = outputData.size();
	outputData.reserveBytes((size_t)(relocationAddress-start));

	// load sections
	bool error = false;
	for (ElfRelocatorSection& entry: file.sections)
	{
		ElfSection* section = entry.section;
		size_t index = entry.index;

		if (section->getType() == SHT_NOBITS)
		{
			// reserveBytes initialized the data to 0 already
			continue;
		}

		ByteArray sectionData = section->getData();

		// relocate if necessary
		ElfSection* relSection = entry.relSection;
		if (relSection != nullptr)
		{
			for (unsigned int relOffset = 0; relOffset < relSection->getSize(); relOffset += sizeof(Elf32_Rel))
			{
				Elf32_Rel rel;
				loadRelocation(rel, relSection->getData(), relOffset, elf->getEndianness());
				int pos = rel.r_offset;

				if (relocator->isDummyRelocationType(rel.getType()))
					continue;

				int symNum = rel.getSymbolNum();
				if (symNum <= 0)
				{
					Logger::queueError(Logger::Warning,L"Invalid symbol num %06X",symNum);
					error = true;
					continue;
				}

				Elf32_Sym sym;
				elf->getSymbol(sym, symNum);
				int symSection = sym.st_shndx;

				RelocationData relData;
				relData.opcode = sectionData.getDoubleWord(pos, elf->getEndianness());
				relData.opcodeOffset = pos+relocationOffsets[index];
				relocator->setSymbolAddress(relData,sym.st_value,sym.st_info & 0xF);

				// externs?
				if (relData.targetSymbolType == STT_NOTYPE && sym.st_shndx == 0)
				{
					std::wstring symName = toWLowercase(elf->getStrTableString(sym.st_name));

					Label* label = Global.symbolTable.getLabel(symName,-1,-1);
					if (label == nullptr)
					{
						Logger::queueError(Logger::Error,L"Invalid external symbol %s",symName);
						error = true;
						continue;
					}
					if (label->isDefined() == false)
					{
						Logger::queueError(Logger::Error,L"Undefined external symbol %s in file %s",symName,file.name);
						error = true;
						continue;
					}

					relData.relocationBase = (unsigned int) label->getValue();
					relData.targetSymbolType = label->isData() ? STT_OBJECT : STT_FUNC;
					relData.targetSymbolInfo = label->getInfo();
				} else {
					relData.relocationBase = relocationOffsets[symSection]+relData.symbolAddress;
				}

				if (relocator->relocateOpcode(rel.getType(),relData) == false)
				{
					Logger::queueError(Logger::Error,relData.errorMessage);
					error = true;
					continue;
				}

				sectionData.replaceDoubleWord(pos,relData.opcode, elf->getEndianness());
			}
		}

		size_t arrayStart = (size_t) (dataStart+relocationOffsets[index]-start);
		memcpy(outputData.data(arrayStart),sectionData.data(),sectionData.size());
	}

	// now update symbols
	for (ElfRelocatorSymbol& sym: file.symbols)
	{
		int64_t oldAddress = sym.relocatedAddress;

		switch (sym.section)
		{
		case SHN_ABS:		// address does not change
			sym.relocatedAddress = sym.relativeAddress;
			break;
		case SHN_COMMON:	// needs to be allocated. relativeAddress gives alignment constraint
			{
				int64_t start = relocationAddress;

				while (relocationAddress % sym.relativeAddress)
					relocationAddress++;

				sym.relocatedAddress = relocationAddress;
				relocationAddress += sym.size;
				outputData.reserveBytes((size_t)(relocationAddress-start));
			}
			break;
		default:			// normal relocated symbol
			sym.relocatedAddress = sym.relativeAddress+relocationOffsets[sym.section];
			break;
		}

		if (sym.label != nullptr)
			sym.label->setValue(sym.relocatedAddress);

		if (oldAddress != sym.relocatedAddress)
			dataChanged = true;
	}

	return !error;
}

bool ElfRelocator::relocate(int64_t& memoryAddress)
{
	int oldCrc = getCrc32(outputData.data(),outputData.size());
	outputData.clear();
	dataChanged = false;

	bool error = false;
	int64_t start = memoryAddress;

	for (ElfRelocatorFile& file: files)
	{
		if (relocateFile(file,memoryAddress) == false)
			error = true;
	}

	int newCrc = getCrc32(outputData.data(),outputData.size());
	if (oldCrc != newCrc)
		dataChanged = true;

	memoryAddress -= start;
	return !error;
}

void ElfRelocator::writeSymbols(SymbolData& symData) const
{
	for (const ElfRelocatorFile& file: files)
	{
		for (const ElfRelocatorSymbol& sym: file.symbols)
		{
			symData.addLabel(sym.relocatedAddress,sym.name);

			switch (sym.type)
			{
			case STT_OBJECT:
				symData.addData(sym.relocatedAddress,sym.size,SymbolData::Data8);
				break;
			case STT_FUNC:
				symData.startFunction(sym.relocatedAddress);
				symData.endFunction(sym.relocatedAddress+sym.size);
				break;
			}
		}
	}
}
<commit_msg>Tweak to external symbol detection in ELF relocator<commit_after>#include "stdafx.h"
#include "ElfRelocator.h"
#include "Core/Common.h"
#include "Core/Misc.h"
#include "Util/CRC.h"
#include "Util/Util.h"
#include "Commands/CAssemblerLabel.h"

struct ArFileHeader
{
	char fileName[16];
	char modifactionTime[12];
	char ownerId[6];
	char groupId[6];
	char fileMode[8];
	char fileSize[10];
	char magic[2];
};

struct ArFileEntry
{
	std::wstring name;
	ByteArray data;
};

std::vector<ArFileEntry> loadArArchive(const std::wstring& inputName)
{
	ByteArray input = ByteArray::fromFile(inputName);
	std::vector<ArFileEntry> result;

	if (memcmp(input.data(),"!<arch>\n",8) != 0)
	{
		if (memcmp(input.data(),"\x7F""ELF",4) != 0)
			return result;

		ArFileEntry entry;
		entry.name = getFileNameFromPath(inputName);
		entry.data = input;
		result.push_back(entry);
		return result;
	}

	size_t pos = 8;
	while (pos < input.size())
	{
		ArFileHeader* header = (ArFileHeader*) input.data(pos);
		pos += sizeof(ArFileHeader);

		// get file size
		int size = 0;
		for (int i = 0; i < 10; i++)
		{
			if (header->fileSize[i] == ' ')
				break;

			size = size*10;
			size += (header->fileSize[i]-'0');
		}

		// only ELF files are actually interesting
		if (memcmp(input.data(pos),"\x7F""ELF",4) == 0)
		{
			// get file name
			char fileName[17];
			fileName[16] = 0;
			for (int i = 0; i < 16; i++)
			{
				if (header->fileName[i] == ' ')
				{
					// remove trailing slashes of file names
					if (i > 0 && fileName[i-1] == '/')
						i--;
					fileName[i] = 0;
					break;;
				}

				fileName[i] = header->fileName[i];
			}

			ArFileEntry entry;
			entry.name = convertUtf8ToWString(fileName);
			entry.data = input.mid(pos,size);
			result.push_back(entry);
		}

		pos += size;
		if (pos % 2)
			pos++;
	}

	return result;
}

bool ElfRelocator::init(const std::wstring& inputName)
{
	relocator = Arch->getElfRelocator();
	if (relocator == nullptr)
	{
		Logger::printError(Logger::Error,L"Object importing not supported for this architecture");
		return false;
	}

	auto inputFiles = loadArArchive(inputName);
	if (inputFiles.size() == 0)
	{
		Logger::printError(Logger::Error,L"Could not load library");
		return false;
	}

	for (ArFileEntry& entry: inputFiles)
	{
		ElfRelocatorFile file;

		ElfFile* elf = new ElfFile();
		if (elf->load(entry.data,false) == false)
		{
			Logger::printError(Logger::Error,L"Could not load object file %s",entry.name);
			return false;
		}

		if (elf->getType() != ET_REL)
		{
			Logger::printError(Logger::Error,L"Unexpected ELF type %d in object file %s",elf->getType(),entry.name);
			return false;
		}

		if (elf->getMachine() != relocator->expectedMachine())
		{
			Logger::printError(Logger::Error,L"Unexpected ELF machine %d in object file %s",elf->getMachine(),entry.name);
			return false;
		}

		if (elf->getEndianness() != Arch->getEndianness())
		{
			Logger::printError(Logger::Error,L"Incorrect endianness in object file %s",entry.name);
			return false;
		}

		if (elf->getSegmentCount() != 0)
		{
			Logger::printError(Logger::Error,L"Unexpected segment count %d in object file %s",elf->getSegmentCount(),entry.name);
			return false;
		}

		// load all relevant sections of this file
		for (size_t s = 0; s < elf->getSegmentlessSectionCount(); s++)
		{
			ElfSection* sec = elf->getSegmentlessSection(s);
			if (!(sec->getFlags() & SHF_ALLOC))
				continue;

			if (sec->getType() == SHT_PROGBITS || sec->getType() == SHT_NOBITS || sec->getType() == SHT_INIT_ARRAY)
			{
				ElfRelocatorSection sectionEntry;
				sectionEntry.section = sec;
				sectionEntry.index = s;
				sectionEntry.relSection = nullptr;
				sectionEntry.label = nullptr;

				// search relocation section
				for (size_t k = 0; k < elf->getSegmentlessSectionCount(); k++)
				{
					ElfSection* relSection = elf->getSegmentlessSection(k);
					if (relSection->getType() != SHT_REL)
						continue;
					if (relSection->getInfo() != s)
						continue;

					// got it
					sectionEntry.relSection = relSection;
					break;
				}

				// keep track of constructor sections
				if (sec->getName() == ".ctors" || sec->getName() == ".init_array")
				{
					ElfRelocatorCtor ctor;
					ctor.symbolName = Global.symbolTable.getUniqueLabelName();
					ctor.size = sec->getSize();

					sectionEntry.label = Global.symbolTable.getLabel(ctor.symbolName,-1,-1);
					sectionEntry.label->setDefined(true);

					ctors.push_back(ctor);
				}

				file.sections.push_back(sectionEntry);
			}
		}

		// init exportable symbols
		for (int i = 0; i < elf->getSymbolCount(); i++)
		{
			Elf32_Sym symbol;
			elf->getSymbol(symbol, i);

			if (ELF32_ST_BIND(symbol.st_info) == STB_GLOBAL && symbol.st_shndx != 0)
			{
				ElfRelocatorSymbol symEntry;
				symEntry.type = ELF32_ST_TYPE(symbol.st_info);
				symEntry.name = convertUtf8ToWString(elf->getStrTableString(symbol.st_name));
				symEntry.relativeAddress = symbol.st_value;
				symEntry.section = symbol.st_shndx;
				symEntry.size = symbol.st_size;
				symEntry.label = nullptr;

				file.symbols.push_back(symEntry);
			}
		}

		file.elf = elf;
		file.name = entry.name;
		files.push_back(file);
	}

	return true;
}

bool ElfRelocator::exportSymbols()
{
	bool error = false;

	for (ElfRelocatorFile& file: files)
	{
		for (ElfRelocatorSymbol& sym: file.symbols)
		{
			if (sym.label != nullptr)
				continue;

			std::wstring lowered = sym.name;
			std::transform(lowered.begin(), lowered.end(), lowered.begin(), ::towlower);

			sym.label = Global.symbolTable.getLabel(lowered,-1,-1);
			if (sym.label == nullptr)
			{
				Logger::printError(Logger::Error,L"Invalid label name \"%s\"",sym.name);
				error = true;
				continue;
			}

			if (sym.label->isDefined())
			{
				Logger::printError(Logger::Error,L"Label \"%s\" already defined",sym.name);
				error = true;
				continue;
			}

			RelocationData data;
			data.symbolAddress = sym.relativeAddress;
			relocator->setSymbolAddress(data,sym.relativeAddress,sym.type);

			sym.relativeAddress = data.symbolAddress;
			sym.label->setInfo(data.targetSymbolInfo);
			sym.label->setIsData(sym.type == STT_OBJECT);
			sym.label->setUpdateInfo(false);

			sym.label->setValue(0);
			sym.label->setDefined(true);
			sym.label->setOriginalName(sym.name);
		}
	}

	return !error;
}

CAssemblerCommand* ElfRelocator::generateCtor(const std::wstring& ctorName)
{
	CAssemblerCommand* content = relocator->generateCtorStub(ctors);

	CDirectiveFunction* func = new CDirectiveFunction(ctorName,ctorName);
	func->setContent(content);
	return func;
}

void ElfRelocator::loadRelocation(Elf32_Rel& rel, ByteArray& data, int offset, Endianness endianness)
{
	rel.r_offset = data.getDoubleWord(offset + 0x00, endianness);
	rel.r_info   = data.getDoubleWord(offset + 0x04, endianness);
}

bool ElfRelocator::relocateFile(ElfRelocatorFile& file, int64_t& relocationAddress)
{
	ElfFile* elf = file.elf;
	int64_t start = relocationAddress;

	// calculate address for each section
	std::map<int64_t,int64_t> relocationOffsets;
	for (ElfRelocatorSection& entry: file.sections)
	{
		ElfSection* section = entry.section;
		size_t index = entry.index;
		int size = section->getSize();

		while (relocationAddress % section->getAlignment())
			relocationAddress++;

		if (entry.label != nullptr)
			entry.label->setValue(relocationAddress);

		relocationOffsets[index] = relocationAddress;
		relocationAddress += size;
	}

	size_t dataStart = outputData.size();
	outputData.reserveBytes((size_t)(relocationAddress-start));

	// load sections
	bool error = false;
	for (ElfRelocatorSection& entry: file.sections)
	{
		ElfSection* section = entry.section;
		size_t index = entry.index;

		if (section->getType() == SHT_NOBITS)
		{
			// reserveBytes initialized the data to 0 already
			continue;
		}

		ByteArray sectionData = section->getData();

		// relocate if necessary
		ElfSection* relSection = entry.relSection;
		if (relSection != nullptr)
		{
			for (unsigned int relOffset = 0; relOffset < relSection->getSize(); relOffset += sizeof(Elf32_Rel))
			{
				Elf32_Rel rel;
				loadRelocation(rel, relSection->getData(), relOffset, elf->getEndianness());
				int pos = rel.r_offset;

				if (relocator->isDummyRelocationType(rel.getType()))
					continue;

				int symNum = rel.getSymbolNum();
				if (symNum <= 0)
				{
					Logger::queueError(Logger::Warning,L"Invalid symbol num %06X",symNum);
					error = true;
					continue;
				}

				Elf32_Sym sym;
				elf->getSymbol(sym, symNum);
				int symSection = sym.st_shndx;

				RelocationData relData;
				relData.opcode = sectionData.getDoubleWord(pos, elf->getEndianness());
				relData.opcodeOffset = pos+relocationOffsets[index];
				relocator->setSymbolAddress(relData,sym.st_value,sym.st_info & 0xF);

				// externs?
				if (sym.st_shndx == 0)
				{
					if (sym.st_name == 0)
					{
						Logger::queueError(Logger::Error, L"Symbol without a name");
						error = true;
						continue;
					}

					std::wstring symName = toWLowercase(elf->getStrTableString(sym.st_name));

					Label* label = Global.symbolTable.getLabel(symName,-1,-1);
					if (label == nullptr)
					{
						Logger::queueError(Logger::Error,L"Invalid external symbol %s",symName);
						error = true;
						continue;
					}
					if (label->isDefined() == false)
					{
						Logger::queueError(Logger::Error,L"Undefined external symbol %s in file %s",symName,file.name);
						error = true;
						continue;
					}

					relData.relocationBase = (unsigned int) label->getValue();
					relData.targetSymbolType = label->isData() ? STT_OBJECT : STT_FUNC;
					relData.targetSymbolInfo = label->getInfo();
				} else {
					relData.relocationBase = relocationOffsets[symSection]+relData.symbolAddress;
				}

				if (relocator->relocateOpcode(rel.getType(),relData) == false)
				{
					Logger::queueError(Logger::Error,relData.errorMessage);
					error = true;
					continue;
				}

				sectionData.replaceDoubleWord(pos,relData.opcode, elf->getEndianness());
			}
		}

		size_t arrayStart = (size_t) (dataStart+relocationOffsets[index]-start);
		memcpy(outputData.data(arrayStart),sectionData.data(),sectionData.size());
	}

	// now update symbols
	for (ElfRelocatorSymbol& sym: file.symbols)
	{
		int64_t oldAddress = sym.relocatedAddress;

		switch (sym.section)
		{
		case SHN_ABS:		// address does not change
			sym.relocatedAddress = sym.relativeAddress;
			break;
		case SHN_COMMON:	// needs to be allocated. relativeAddress gives alignment constraint
			{
				int64_t start = relocationAddress;

				while (relocationAddress % sym.relativeAddress)
					relocationAddress++;

				sym.relocatedAddress = relocationAddress;
				relocationAddress += sym.size;
				outputData.reserveBytes((size_t)(relocationAddress-start));
			}
			break;
		default:			// normal relocated symbol
			sym.relocatedAddress = sym.relativeAddress+relocationOffsets[sym.section];
			break;
		}

		if (sym.label != nullptr)
			sym.label->setValue(sym.relocatedAddress);

		if (oldAddress != sym.relocatedAddress)
			dataChanged = true;
	}

	return !error;
}

bool ElfRelocator::relocate(int64_t& memoryAddress)
{
	int oldCrc = getCrc32(outputData.data(),outputData.size());
	outputData.clear();
	dataChanged = false;

	bool error = false;
	int64_t start = memoryAddress;

	for (ElfRelocatorFile& file: files)
	{
		if (relocateFile(file,memoryAddress) == false)
			error = true;
	}

	int newCrc = getCrc32(outputData.data(),outputData.size());
	if (oldCrc != newCrc)
		dataChanged = true;

	memoryAddress -= start;
	return !error;
}

void ElfRelocator::writeSymbols(SymbolData& symData) const
{
	for (const ElfRelocatorFile& file: files)
	{
		for (const ElfRelocatorSymbol& sym: file.symbols)
		{
			symData.addLabel(sym.relocatedAddress,sym.name);

			switch (sym.type)
			{
			case STT_OBJECT:
				symData.addData(sym.relocatedAddress,sym.size,SymbolData::Data8);
				break;
			case STT_FUNC:
				symData.startFunction(sym.relocatedAddress);
				symData.endFunction(sym.relocatedAddress+sym.size);
				break;
			}
		}
	}
}
<|endoftext|>


<commit_before>#include <string.h>
#include <string>
#include <stdio.h>
#include "bsd_string.h"

#include "genesis.h"
#include "g59cmd.h"

static G59 m_g59;
static G11 m_g11;
static Genesis *mp_genesis = NULL;

static char m_name_str[256];
static char m_model_str[256];
static char m_mode = '\0';
static long m_tune_freq = 0;

extern "C"
{
void ShowGUI()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
}
bool InitHW(char *name, char *model, int& type)
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    bool rtn = false;
    type = 0;
    name = NULL;
    model = NULL;
    if (rtn = m_g59.Init())
    {
        mp_genesis = &m_g59;
        strlcpy(m_name_str, m_g59.GetMake().c_str(), sizeof(m_name_str));
        strlcpy(m_model_str, m_g59.GetMake().c_str(), sizeof(m_model_str));
        name = m_name_str;
        model = m_model_str;
        type = 4;
    }
    else if (rtn = m_g11.Init())
    {
        mp_genesis = &m_g11;
        strlcpy(m_name_str, m_g11.GetMake().c_str(), sizeof(m_name_str));
        strlcpy(m_model_str, m_g11.GetMake().c_str(), sizeof(m_model_str));
        name = m_name_str;
        model = m_model_str;
        type = 4;
    }

    return rtn;
}
bool OpenHW()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return true;
}
void CloseHW()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    mp_genesis->Close();
}
int StartHW(long freq)
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return 0;
}
void StopHW()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
}
int SetHWLO(long LOfreq)
{
    fprintf(stderr,"%s:%d LOfreq: %ld\n",__FUNCTION__,__LINE__, LOfreq);
    mp_genesis->SetLO(LOfreq);
    return 0;
}
int GetStatus()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return 0;
}
void SetCallback(void (* Callback)(int, int, float, void *))
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
}
// ext routs
long GetHWLO()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return 0;
}
void TuneChanged(long freq)
{
    fprintf(stderr,"%s:%d freq: %ld\n",__FUNCTION__,__LINE__, freq);
    m_tune_freq = freq;
}
void IFLimitsChanged(long low, long high)
{
    fprintf(stderr,"%s:%d low: %ld, high: %ld\n",__FUNCTION__,__LINE__,low, high);
    long center = (low + high) / 2;
    if(200000 < center)
    {
        mp_genesis->SetLO(center);
    }
}
long GetTune()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return m_tune_freq;
}
char GetMode()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return m_mode;
}
void ModeChanged(char mode)
{
    m_mode = mode;
    fprintf(stderr,"%s:%d %c\n",__FUNCTION__,__LINE__,mode);
}
long GetHWSR()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return 0;
}
void HideGUI()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
}
void RawDataReady(long samprate, int *Ldata, int *Rdata, int numsamples)
{
    fprintf(stderr,"%s:%d samprate:%ld, numsamples:%d\n",__FUNCTION__,__LINE__, samprate, numsamples);
}
void GetFilters(int& loCut, int& hiCut, int& pitch)
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
}
//
int SetModeRxTx(int modeRxTx)
{
    fprintf(stderr,"%s:%d modeRxTx: %d\n",__FUNCTION__,__LINE__, modeRxTx);
    mp_genesis->SetTx((0!=modeRxTx?true:false));
    return 0;
}
int ActivateTx(int magicA, int magicB)
{
    fprintf(stderr,"%s:%d magicA:%d, int magicB:%d\n",__FUNCTION__,__LINE__,magicA, magicB);
    return 0;
}
void VersionInfo(const char *name, int ver_major, int ver_minor)
{
    fprintf(stderr,"%s:%d name:\"%s\", ver_major:%d, ver_minor:%d\n",__FUNCTION__,__LINE__, name, ver_major, ver_minor);
}
} /* extern "C" */
<commit_msg>Playing around with how LO gets set.<commit_after>#include <string.h>
#include <string>
#include <stdio.h>
#include "bsd_string.h"

#include "genesis.h"
#include "g59cmd.h"

static G59 m_g59;
static G11 m_g11;
static Genesis *mp_genesis = NULL;

static char m_name_str[256];
static char m_model_str[256];
static char m_mode = '\0';
static long m_tune_freq = 1800000;
static long m_lo_freq = 1800000;

extern "C"
{
//Foward Decl
int SetHWLO(long LOfreq);

void ShowGUI()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
}
bool InitHW(char *name, char *model, int& type)
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    bool rtn = false;
    type = 0;
    name = NULL;
    model = NULL;
    if (rtn = m_g59.Init())
    {
        mp_genesis = &m_g59;
        strlcpy(m_name_str, m_g59.GetMake().c_str(), sizeof(m_name_str));
        strlcpy(m_model_str, m_g59.GetMake().c_str(), sizeof(m_model_str));
        name = m_name_str;
        model = m_model_str;
        type = 4;
    }
    else if (rtn = m_g11.Init())
    {
        mp_genesis = &m_g11;
        strlcpy(m_name_str, m_g11.GetMake().c_str(), sizeof(m_name_str));
        strlcpy(m_model_str, m_g11.GetMake().c_str(), sizeof(m_model_str));
        name = m_name_str;
        model = m_model_str;
        type = 4;
    }

    return rtn;
}
bool OpenHW()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    SetHWLO(m_lo_freq);
    return true;
}
void CloseHW()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    mp_genesis->Close();
}
int StartHW(long freq)
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return 0;
}
void StopHW()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
}
int SetHWLO(long LOfreq)
{
    fprintf(stderr,"%s:%d LOfreq: %ld\n",__FUNCTION__,__LINE__, LOfreq);
    mp_genesis->SetLO(LOfreq);
    m_lo_freq = LOfreq;
    return 0;
}
int GetStatus()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return 0;
}
void SetCallback(void (* Callback)(int, int, float, void *))
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
}
// ext routs
long GetHWLO()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return m_lo_freq;
}
void TuneChanged(long freq)
{
    fprintf(stderr,"%s:%d freq: %ld\n",__FUNCTION__,__LINE__, freq);
    m_tune_freq = freq;
}
void IFLimitsChanged(long low, long high)
{
    long LOfreq = (low + high)/2;
    fprintf(stderr,"%s:%d low: %ld, high: %ld, LO = %ld\n",__FUNCTION__,__LINE__, low, high, LOfreq);
    if((0 < LOfreq) && (LOfreq != m_lo_freq))
    {
        mp_genesis->SetLO(LOfreq);
        m_lo_freq = LOfreq;
    }

}
long GetTune()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return m_tune_freq;
}
char GetMode()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return m_mode;
}
void ModeChanged(char mode)
{
    m_mode = mode;
    fprintf(stderr,"%s:%d %c\n",__FUNCTION__,__LINE__,mode);
}
long GetHWSR()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
    return 0;
}
void HideGUI()
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
}
void RawDataReady(long samprate, int *Ldata, int *Rdata, int numsamples)
{
    fprintf(stderr,"%s:%d samprate:%ld, numsamples:%d\n",__FUNCTION__,__LINE__, samprate, numsamples);
}
void GetFilters(int& loCut, int& hiCut, int& pitch)
{
    fprintf(stderr,"%s:%d\n",__FUNCTION__,__LINE__);
}
//
int SetModeRxTx(int modeRxTx)
{
    fprintf(stderr,"%s:%d modeRxTx: %d\n",__FUNCTION__,__LINE__, modeRxTx);
    mp_genesis->SetTx((0!=modeRxTx?true:false));
    return 0;
}
int ActivateTx(int magicA, int magicB)
{
    fprintf(stderr,"%s:%d magicA:%d, int magicB:%d\n",__FUNCTION__,__LINE__,magicA, magicB);
    return 0;
}
void VersionInfo(const char *name, int ver_major, int ver_minor)
{
    fprintf(stderr,"%s:%d name:\"%s\", ver_major:%d, ver_minor:%d\n",__FUNCTION__,__LINE__, name, ver_major, ver_minor);
}
} /* extern "C" */
<|endoftext|>


<commit_before>
// The files containing the tree of child classes of |Body| must be included in
// the order of inheritance to avoid circular dependencies.  This class will end
// up being reincluded as part of the implementation of its parent.
#ifndef PRINCIPIA_PHYSICS_MASSIVE_BODY_HPP_
#include "physics/massive_body.hpp"
#else
#ifndef PRINCIPIA_PHYSICS_ROTATING_BODY_HPP_
#define PRINCIPIA_PHYSICS_ROTATING_BODY_HPP_

#include <experimental/optional>
#include <vector>

#include "geometry/grassmann.hpp"
#include "geometry/rotation.hpp"
#include "quantities/named_quantities.hpp"
#include "quantities/quantities.hpp"

namespace principia {
namespace physics {
namespace internal_rotating_body {

using geometry::AngularVelocity;
using geometry::Instant;
using geometry::Rotation;
using geometry::Vector;
using quantities::Angle;
using quantities::AngularFrequency;
using quantities::Length;

template<typename Frame>
class RotatingBody : public MassiveBody {
  static_assert(Frame::is_inertial, "Frame must be inertial");

 public:
  class Parameters {
   public:
    // |reference_angle| is the angle of the prime meridian at
    // |reference_instant|.  |angular_frequency| gives the rate of rotation of
    // the body around the pole (it may be negative, as is the convention for
    // planets and satellites whose rotation is retrograde).  The direction of
    // the pole is specified in |Frame| using |right_ascension_of_pole| and
    // |declination_of_pole|.
    Parameters(Length const& mean_radius,
               Angle const& reference_angle,
               Instant const& reference_instant,
               AngularFrequency const& angular_frequency,
               Angle const& right_ascension_of_pole,
               Angle const& declination_of_pole);

   private:
    Length const mean_radius_;
    Angle const reference_angle_;
    Instant const reference_instant_;
    AngularFrequency const angular_frequency_;
    Angle const right_ascension_of_pole_;
    Angle const declination_of_pole_;
    template<typename F>
    friend class RotatingBody;
  };

  RotatingBody(MassiveBody::Parameters const& massive_body_parameters,
               Parameters const& parameters);
  ~RotatingBody() = default;

  // Returns the radius passed at construction.
  Length mean_radius() const override;

  // Returns the direction defined by the right ascension and declination passed
  // at construction.
  Vector<double, Frame> const& polar_axis() const;

  // Returns the right ascension passed at construction.
  Angle const& right_ascension_of_pole() const;

  // Returns the declination at construction.
  Angle const& declination_of_pole() const;

  // Returns the angular frequency passed at construction.
  AngularFrequency const& angular_frequency() const;

  // Returns the angular velocity defined by the right ascension, declination,
  // and angular frequency passed at construction.
  AngularVelocity<Frame> const& angular_velocity() const;

  // Returns the position at time |t|.
  Angle AngleAt(Instant const& t) const;

  // Returns the rotation relating the reference frame of the surface of this
  // body to |Frame|.  The reference frame of the surface is defined as follows:
  //   - the z axis is the |polar_axis|;
  //   - the x axis points from the centre of the body to the reference
  //     meridian;
  //   - the reference frame has the same handedness as |Frame|.
  // Following this definition,
  //   Displacement<SurfaceFrame>(RadiusLatitudeLongitude(r, φ, λ))
  // converts planetocentric coordinates to a displacement from the body centre
  // in the surface frame.  Note that RadiusLatitudeLongitude should *not* be
  // used for planetographic coordinates, which use a latitude defined from
  // a reference ellipsoid, and a longitude around the negative pole---except
  // for the Earth, the Moon, and the Sun.
  template<typename SurfaceFrame>
  Rotation<SurfaceFrame, Frame> FromSurfaceFrame(Instant const& t) const;

  // Returns the rotation at time |t|.
  Rotation<Frame, Frame> RotationAt(Instant const& t) const;

  // Returns false.
  bool is_massless() const override;

  // Returns true.
  bool is_oblate() const override;

  void WriteToMessage(not_null<serialization::Body*> message) const override;

  void WriteToMessage(
      not_null<serialization::MassiveBody*> message) const override;

  // Fails if the |RotatingBody| extension is absent from the message.
  static not_null<std::unique_ptr<RotatingBody<Frame>>> ReadFromMessage(
      serialization::RotatingBody const& message,
      MassiveBody::Parameters const& massive_body_parameters);

 private:
  Parameters const parameters_;
  Vector<double, Frame> const polar_axis_;
  AngularVelocity<Frame> const angular_velocity_;
};

}  // namespace internal_rotating_body

using internal_rotating_body::RotatingBody;

}  // namespace physics
}  // namespace principia

#include "physics/rotating_body_body.hpp"

#endif  // PRINCIPIA_PHYSICS_ROTATING_BODY_HPP_
#endif  // PRINCIPIA_PHYSICS_MASSIVE_BODY_HPP_
<commit_msg>more comment<commit_after>
// The files containing the tree of child classes of |Body| must be included in
// the order of inheritance to avoid circular dependencies.  This class will end
// up being reincluded as part of the implementation of its parent.
#ifndef PRINCIPIA_PHYSICS_MASSIVE_BODY_HPP_
#include "physics/massive_body.hpp"
#else
#ifndef PRINCIPIA_PHYSICS_ROTATING_BODY_HPP_
#define PRINCIPIA_PHYSICS_ROTATING_BODY_HPP_

#include <experimental/optional>
#include <vector>

#include "geometry/grassmann.hpp"
#include "geometry/rotation.hpp"
#include "quantities/named_quantities.hpp"
#include "quantities/quantities.hpp"

namespace principia {
namespace physics {
namespace internal_rotating_body {

using geometry::AngularVelocity;
using geometry::Instant;
using geometry::Rotation;
using geometry::Vector;
using quantities::Angle;
using quantities::AngularFrequency;
using quantities::Length;

template<typename Frame>
class RotatingBody : public MassiveBody {
  static_assert(Frame::is_inertial, "Frame must be inertial");

 public:
  class Parameters {
   public:
    // |reference_angle| is the angle of the prime meridian at
    // |reference_instant|.  |angular_frequency| gives the rate of rotation of
    // the body around the pole (it may be negative, as is the convention for
    // planets and satellites whose rotation is retrograde).  The direction of
    // the pole is specified in |Frame| using |right_ascension_of_pole| and
    // |declination_of_pole|.
    Parameters(Length const& mean_radius,
               Angle const& reference_angle,
               Instant const& reference_instant,
               AngularFrequency const& angular_frequency,
               Angle const& right_ascension_of_pole,
               Angle const& declination_of_pole);

   private:
    Length const mean_radius_;
    Angle const reference_angle_;
    Instant const reference_instant_;
    AngularFrequency const angular_frequency_;
    Angle const right_ascension_of_pole_;
    Angle const declination_of_pole_;
    template<typename F>
    friend class RotatingBody;
  };

  RotatingBody(MassiveBody::Parameters const& massive_body_parameters,
               Parameters const& parameters);
  ~RotatingBody() = default;

  // Returns the radius passed at construction.
  Length mean_radius() const override;

  // Returns the direction defined by the right ascension and declination passed
  // at construction.
  Vector<double, Frame> const& polar_axis() const;

  // Returns the right ascension passed at construction.
  Angle const& right_ascension_of_pole() const;

  // Returns the declination at construction.
  Angle const& declination_of_pole() const;

  // Returns the angular frequency passed at construction.
  AngularFrequency const& angular_frequency() const;

  // Returns the angular velocity defined by the right ascension, declination,
  // and angular frequency passed at construction.
  AngularVelocity<Frame> const& angular_velocity() const;

  // Returns the position at time |t|.
  Angle AngleAt(Instant const& t) const;

  // Returns the rotation relating the reference frame of the surface of this
  // body to |Frame|.  The reference frame of the surface is defined as follows:
  //   - the z axis is the |polar_axis|;
  //   - the x axis points from the centre of the body to the reference
  //     meridian;
  //   - the reference frame has the same handedness as |Frame|.
  // Following this definition,
  //   Displacement<SurfaceFrame>(RadiusLatitudeLongitude(r, φ, λ))
  // converts planetocentric coordinates to a displacement from the body centre
  // in the surface frame.  Note that RadiusLatitudeLongitude should *not* be
  // used for planetographic coordinates, which use a latitude defined from
  // a reference ellipsoid, and a longitude around the negative pole---except
  // for the Earth, the Moon, and the Sun.
  // In the case of the Earth, see geodetic vs. geocentric latitudes.
  template<typename SurfaceFrame>
  Rotation<SurfaceFrame, Frame> FromSurfaceFrame(Instant const& t) const;

  // Returns the rotation at time |t|.
  Rotation<Frame, Frame> RotationAt(Instant const& t) const;

  // Returns false.
  bool is_massless() const override;

  // Returns true.
  bool is_oblate() const override;

  void WriteToMessage(not_null<serialization::Body*> message) const override;

  void WriteToMessage(
      not_null<serialization::MassiveBody*> message) const override;

  // Fails if the |RotatingBody| extension is absent from the message.
  static not_null<std::unique_ptr<RotatingBody<Frame>>> ReadFromMessage(
      serialization::RotatingBody const& message,
      MassiveBody::Parameters const& massive_body_parameters);

 private:
  Parameters const parameters_;
  Vector<double, Frame> const polar_axis_;
  AngularVelocity<Frame> const angular_velocity_;
};

}  // namespace internal_rotating_body

using internal_rotating_body::RotatingBody;

}  // namespace physics
}  // namespace principia

#include "physics/rotating_body_body.hpp"

#endif  // PRINCIPIA_PHYSICS_ROTATING_BODY_HPP_
#endif  // PRINCIPIA_PHYSICS_MASSIVE_BODY_HPP_
<|endoftext|>


<commit_before>#include "platform.hpp"

#include "../coding/file_writer.hpp"

#include "../std/windows.hpp"

#include <shlobj.h>
#include <sys/stat.h>

static bool GetUserWritableDir(string & outDir)
{
  char pathBuf[MAX_PATH] = {0};
  if (SUCCEEDED(::SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, pathBuf)))
  {
    outDir = pathBuf;
    ::CreateDirectoryA(outDir.c_str(), NULL);
    outDir += "\\MapsWithMe\\";
    ::CreateDirectoryA(outDir.c_str(), NULL);
    return true;
  }
  return false;
}

/// @return Full path to the executable file
static bool GetPathToBinary(string & outPath)
{
  // get path to executable
  char pathBuf[MAX_PATH] = {0};
  if (0 < ::GetModuleFileNameA(NULL, pathBuf, MAX_PATH))
  {
    outPath = pathBuf;
    return true;
  }
  return false;
}

Platform::Platform()
{
  string path;
  CHECK(GetPathToBinary(path), ("Can't get path to binary"));

  // resources path:
  // 1. try to use data folder in the same path as executable
  // 2. if not found, try to use ..\..\..\data (for development only)
  path.erase(path.find_last_of('\\'));
  if (IsFileExists(path + "\\data\\"))
    m_resourcesDir = path + "\\data\\";
  else
  {
#ifndef OMIM_PRODUCTION
    path.erase(path.find_last_of('\\'));
    path.erase(path.find_last_of('\\'));
    if (IsFileExists(path + "\\data\\"))
      m_resourcesDir = path + "\\data\\";
#else
    CHECK(false, ("Can't find resources directory"));
#endif
  }

  // writable path:
  // 1. the same as resources if we have write access to this folder
  // 2. otherwise, use system-specific folder
  try
  {
    FileWriter tmpfile(m_resourcesDir + "mapswithmetmptestfile");
    tmpfile.Write("Hi from Alex!", 13);
    FileWriter::DeleteFileX(m_resourcesDir + "mapswithmetmptestfile");
    m_writableDir = m_resourcesDir;
  }
  catch (FileWriter::RootException const &)
  {
    CHECK(GetUserWritableDir(m_writableDir), ("Can't get writable directory"));
  }

  LOG(LDEBUG, ("Resources Directory:", m_resourcesDir));
  LOG(LDEBUG, ("Writable Directory:", m_writableDir));
}

Platform::~Platform()
{
}

bool Platform::IsFileExists(string const & file) const
{
  struct _stat s;
  return _stat(file.c_str(), &s) == 0;
}

int Platform::CpuCores() const
{
  SYSTEM_INFO sysinfo;
  GetSystemInfo(&sysinfo);
  DWORD numCPU = sysinfo.dwNumberOfProcessors;
  if (numCPU >= 1)
    return static_cast<int>(numCPU);
  return 1;
}

string Platform::UniqueClientId() const
{
  return "@TODO";
}
<commit_msg>[win] Fixed test aflet platform refactoring<commit_after>#include "platform.hpp"

#include "../base/logging.hpp"

#include "../coding/file_writer.hpp"

#include "../std/windows.hpp"

#include <shlobj.h>

static bool GetUserWritableDir(string & outDir)
{
  char pathBuf[MAX_PATH] = {0};
  if (SUCCEEDED(::SHGetFolderPathA(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, pathBuf)))
  {
    outDir = pathBuf;
    ::CreateDirectoryA(outDir.c_str(), NULL);
    outDir += "\\MapsWithMe\\";
    ::CreateDirectoryA(outDir.c_str(), NULL);
    return true;
  }
  return false;
}

/// @return Full path to the executable file
static bool GetPathToBinary(string & outPath)
{
  // get path to executable
  char pathBuf[MAX_PATH] = {0};
  if (0 < ::GetModuleFileNameA(NULL, pathBuf, MAX_PATH))
  {
    outPath = pathBuf;
    return true;
  }
  return false;
}

Platform::Platform()
{
  string path;
  CHECK(GetPathToBinary(path), ("Can't get path to binary"));

  // resources path:
  // 1. try to use data folder in the same path as executable
  // 2. if not found, try to use ..\..\..\data (for development only)
  path.erase(path.find_last_of('\\'));
  if (IsFileExists(path + "\\data\\"))
    m_resourcesDir = path + "\\data\\";
  else
  {
#ifndef OMIM_PRODUCTION
    path.erase(path.find_last_of('\\'));
    path.erase(path.find_last_of('\\'));
    if (IsFileExists(path + "\\data\\"))
      m_resourcesDir = path + "\\data\\";
#else
    CHECK(false, ("Can't find resources directory"));
#endif
  }

  // writable path:
  // 1. the same as resources if we have write access to this folder
  // 2. otherwise, use system-specific folder
  try
  {
    FileWriter tmpfile(m_resourcesDir + "mapswithmetmptestfile");
    tmpfile.Write("Hi from Alex!", 13);
    m_writableDir = m_resourcesDir;
  }
  catch (RootException const &)
  {
    CHECK(GetUserWritableDir(m_writableDir), ("Can't get writable directory"));
  }
  FileWriter::DeleteFileX(m_resourcesDir + "mapswithmetmptestfile");

  LOG(LDEBUG, ("Resources Directory:", m_resourcesDir));
  LOG(LDEBUG, ("Writable Directory:", m_writableDir));
}

Platform::~Platform()
{
}

bool Platform::IsFileExists(string const & file) const
{
  return ::GetFileAttributesA(file.c_str()) != INVALID_FILE_ATTRIBUTES;
}

int Platform::CpuCores() const
{
  SYSTEM_INFO sysinfo;
  GetSystemInfo(&sysinfo);
  DWORD numCPU = sysinfo.dwNumberOfProcessors;
  if (numCPU >= 1)
    return static_cast<int>(numCPU);
  return 1;
}

string Platform::UniqueClientId() const
{
  return "@TODO";
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qmljsstaticanalysismessage.h"
#include "qmljsconstants.h"

#include <utils/qtcassert.h>

#include <QCoreApplication>

using namespace QmlJS;
using namespace QmlJS::StaticAnalysis;
using namespace QmlJS::Severity;

namespace {

class StaticAnalysisMessages
{
    Q_DECLARE_TR_FUNCTIONS(QmlJS::StaticAnalysisMessages)

public:
    void newMsg(Type type, Enum severity, const QString &message, int placeholders = 0)
    {
        PrototypeMessageData prototype;
        prototype.type = type;
        prototype.severity = severity;
        prototype.message = message;
        prototype.placeholders = placeholders;
        QTC_CHECK(placeholders <= 2);
        QTC_ASSERT(!messages.contains(type), return);
        messages[type] = prototype;
    }

    StaticAnalysisMessages();
    QHash<Type, PrototypeMessageData> messages;
};

static inline QString msgInvalidConstructor(const char *what)
{
    return StaticAnalysisMessages::tr("Do not use '%1' as a constructor.").arg(QLatin1String(what));
}

StaticAnalysisMessages::StaticAnalysisMessages()
{
    // When changing a message or severity, update the documentation, currently
    // in creator-editors.qdoc, accordingly.
    newMsg(ErrInvalidEnumValue, Error,
           tr("Invalid value for enum."));
    newMsg(ErrEnumValueMustBeStringOrNumber, Error,
           tr("Enum value must be a string or a number."));
    newMsg(ErrNumberValueExpected, Error,
           tr("Number value expected."));
    newMsg(ErrBooleanValueExpected, Error,
           tr("Boolean value expected."));
    newMsg(ErrStringValueExpected, Error,
           tr("String value expected."));
    newMsg(ErrInvalidUrl, Error,
           tr("Invalid URL."));
    newMsg(WarnFileOrDirectoryDoesNotExist, Warning,
           tr("File or directory does not exist."));
    newMsg(ErrInvalidColor, Error,
           tr("Invalid color."));
    newMsg(ErrAnchorLineExpected, Error,
           tr("Anchor line expected."));
    newMsg(ErrPropertiesCanOnlyHaveOneBinding, Error,
           tr("Duplicate property binding."));
    newMsg(ErrIdExpected, Error,
           tr("Id expected."));
    newMsg(ErrInvalidId, Error,
           tr("Invalid id."));
    newMsg(ErrDuplicateId, Error,
           tr("Duplicate id."));
    newMsg(ErrInvalidPropertyName, Error,
           tr("Invalid property name '%1'."), 1);
    newMsg(ErrDoesNotHaveMembers, Error,
           tr("'%1' does not have members."), 1);
    newMsg(ErrInvalidMember, Error,
           tr("'%1' is not a member of '%2'."), 2);
    newMsg(WarnAssignmentInCondition, Warning,
           tr("Assignment in condition."));
    newMsg(WarnCaseWithoutFlowControl, Warning,
           tr("Unterminated non-empty case block."));
    newMsg(WarnEval, Warning,
           tr("Do not use 'eval'."));
    newMsg(WarnUnreachable, Warning,
           tr("Unreachable."));
    newMsg(WarnWith, Warning,
           tr("Do not use 'with'."));
    newMsg(WarnComma, Warning,
           tr("Do not use comma expressions."));
    newMsg(WarnAlreadyFormalParameter, Warning,
           tr("'%1' already is a formal parameter."), 1);
    newMsg(WarnUnnecessaryMessageSuppression, Warning,
           tr("Unnecessary message suppression."));
    newMsg(WarnAlreadyFunction, Warning,
           tr("'%1' already is a function."), 1);
    newMsg(WarnVarUsedBeforeDeclaration, Warning,
           tr("var '%1' is used before its declaration."), 1);
    newMsg(WarnAlreadyVar, Warning,
           tr("'%1' already is a var."), 1);
    newMsg(WarnDuplicateDeclaration, Warning,
           tr("'%1' is declared more than once."), 1);
    newMsg(WarnFunctionUsedBeforeDeclaration, Warning,
           tr("Function '%1' is used before its declaration."), 1);
    newMsg(WarnBooleanConstructor, Warning,
           msgInvalidConstructor("Boolean"));
    newMsg(WarnStringConstructor, Warning,
           msgInvalidConstructor("String"));
    newMsg(WarnObjectConstructor, Warning,
           msgInvalidConstructor("Object"));
    newMsg(WarnArrayConstructor, Warning,
           msgInvalidConstructor("Array"));
    newMsg(WarnFunctionConstructor, Warning,
           msgInvalidConstructor("Function"));
    newMsg(HintAnonymousFunctionSpacing, Hint,
           tr("The 'function' keyword and the opening parenthesis should be separated by a single space."));
    newMsg(WarnBlock, Warning,
           tr("Do not use stand-alone blocks."));
    newMsg(WarnVoid, Warning,
           tr("Do not use void expressions."));
    newMsg(WarnConfusingPluses, Warning,
           tr("Confusing pluses."));
    newMsg(WarnConfusingMinuses, Warning,
           tr("Confusing minuses."));
    newMsg(HintDeclareVarsInOneLine, Hint,
           tr("Declare all function vars on a single line."));
    newMsg(HintExtraParentheses, Hint,
           tr("Unnecessary parentheses."));
    newMsg(MaybeWarnEqualityTypeCoercion, MaybeWarning,
           tr("== and != may perform type coercion, use === or !== to avoid it."));
    newMsg(WarnConfusingExpressionStatement, Error,
           tr("Expression statements should be assignments, calls or delete expressions only."));
    newMsg(HintDeclarationsShouldBeAtStartOfFunction, Hint,
           tr("Place var declarations at the start of a function."));
    newMsg(HintOneStatementPerLine, Hint,
           tr("Use only one statement per line."));
    newMsg(ErrUnknownComponent, Error,
           tr("Unknown component."));
    newMsg(ErrCouldNotResolvePrototypeOf, Error,
           tr("Could not resolve the prototype '%1' of '%2'."), 2);
    newMsg(ErrCouldNotResolvePrototype, Error,
           tr("Could not resolve the prototype '%1'."), 1);
    newMsg(ErrPrototypeCycle, Error,
           tr("Prototype cycle, the last non-repeated component is '%1'."), 1);
    newMsg(ErrInvalidPropertyType, Error,
           tr("Invalid property type '%1'."), 1);
    newMsg(WarnEqualityTypeCoercion, Error,
           tr("== and != perform type coercion, use === or !== to avoid it."));
    newMsg(WarnExpectedNewWithUppercaseFunction, Error,
           tr("Calls of functions that start with an uppercase letter should use 'new'."));
    newMsg(WarnNewWithLowercaseFunction, Error,
           tr("Use 'new' only with functions that start with an uppercase letter."));
    newMsg(WarnNumberConstructor, Error,
           msgInvalidConstructor("Function"));
    newMsg(HintBinaryOperatorSpacing, Hint,
           tr("Use spaces around binary operators."));
    newMsg(WarnUnintentinalEmptyBlock, Error,
           tr("Unintentional empty block, use ({}) for empty object literal."));
    newMsg(HintPreferNonVarPropertyType, Hint,
           tr("Use %1 instead of 'var' or 'variant' to improve performance."), 1);
    newMsg(ErrMissingRequiredProperty, Error,
           tr("Missing property '%1'."), 1);
    newMsg(ErrObjectValueExpected, Error,
           tr("Object value expected."));
    newMsg(ErrArrayValueExpected, Error,
           tr("Array value expected."));
    newMsg(ErrDifferentValueExpected, Error,
           tr("%1 value expected."), 1);
    newMsg(ErrSmallerNumberValueExpected, Error,
           tr("Maximum number value is %1."), 1);
    newMsg(ErrLargerNumberValueExpected, Error,
           tr("Minimum number value is %1."), 1);
    newMsg(ErrMaximumNumberValueIsExclusive, Error,
           tr("Maximum number value is exclusive."));
    newMsg(ErrMinimumNumberValueIsExclusive, Error,
           tr("Minimum number value is exclusive."));
    newMsg(ErrInvalidStringValuePattern, Error,
           tr("String value does not match required pattern."));
    newMsg(ErrLongerStringValueExpected, Error,
           tr("Minimum string value length is %1."), 1);
    newMsg(ErrShorterStringValueExpected, Error,
           tr("Maximum string value length is %1."), 1);
    newMsg(ErrInvalidArrayValueLength, Error,
           tr("%1 elements expected in array value."), 1);
    newMsg(WarnImperativeCodeNotEditableInVisualDesigner, Error,
            tr("Imperative code is not supported in the Qt Quick Designer."));
    newMsg(WarnUnsupportedTypeInVisualDesigner, Warning,
            tr("This type is not supported in the Qt Quick Designer."));
    newMsg(WarnReferenceToParentItemNotSupportedByVisualDesigner, Error,
            tr("Reference to parent item cannot be resolved correctly by the Qt Quick Designer."));
    newMsg(WarnUndefinedValueForVisualDesigner, Warning,
            tr("This visual property binding cannot be evaluated in the local context "
               "and might not show up in Qt Quick Designer as expected."));
    newMsg(WarnStatesOnlyInRootItemForVisualDesigner, Warning,
            tr("Qt Quick Designer only supports states in the root item."));
    newMsg(WarnAboutQtQuick1InsteadQtQuick2, Warning,
            tr("Using Qt Quick 1 code model instead of Qt Quick 2."));
}

} // anonymous namespace

Q_GLOBAL_STATIC(StaticAnalysisMessages, messages)

QList<Type> Message::allMessageTypes()
{
    return messages()->messages.keys();
}

Message::Message()
    : type(UnknownType), severity(Hint)
{}

Message::Message(Type type,
                 AST::SourceLocation location,
                 const QString &arg1,
                 const QString &arg2,
                 bool appendTypeId)
    : location(location), type(type)
{
    QTC_ASSERT(messages()->messages.contains(type), return);
    const PrototypeMessageData &prototype = prototypeForMessageType(type);
    severity = prototype.severity;
    message = prototype.message;
    if (prototype.placeholders == 0) {
        if (!arg1.isEmpty() || !arg2.isEmpty())
            qWarning() << "StaticAnalysis message" << type << "expects no arguments";
    } else if (prototype.placeholders == 1) {
        if (arg1.isEmpty() || !arg2.isEmpty())
            qWarning() << "StaticAnalysis message" << type << "expects exactly one argument";
        message = message.arg(arg1);
    } else if (prototype.placeholders == 2) {
        if (arg1.isEmpty() || arg2.isEmpty())
            qWarning() << "StaticAnalysis message" << type << "expects exactly two arguments";
        message = message.arg(arg1, arg2);
    }
    if (appendTypeId)
        message.append(QString::fromLatin1(" (M%1)").arg(QString::number(prototype.type)));
}

bool Message::isValid() const
{
    return type != UnknownType && location.isValid() && !message.isEmpty();
}

DiagnosticMessage Message::toDiagnosticMessage() const
{
    DiagnosticMessage diagnostic;
    switch (severity) {
    case Hint:
    case MaybeWarning:
    case Warning:
        diagnostic.kind = Warning;
        break;
    default:
        diagnostic.kind = Error;
        break;
    }
    diagnostic.loc = location;
    diagnostic.message = message;
    return diagnostic;
}

QString Message::suppressionString() const
{
    return QString::fromLatin1("@disable-check M%1").arg(QString::number(type));
}

QRegExp Message::suppressionPattern()
{
    return QRegExp(QLatin1String("@disable-check M(\\d+)"));
}

const PrototypeMessageData Message::prototypeForMessageType(Type type)
{
     QTC_CHECK(messages()->messages.contains(type));
     const PrototypeMessageData &prototype = messages()->messages.value(type);

     return prototype;
}
<commit_msg>qmljs: correctly set Warnings<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qmljsstaticanalysismessage.h"
#include "qmljsconstants.h"

#include <utils/qtcassert.h>

#include <QCoreApplication>

using namespace QmlJS;
using namespace QmlJS::StaticAnalysis;
using namespace QmlJS::Severity;

namespace {

class StaticAnalysisMessages
{
    Q_DECLARE_TR_FUNCTIONS(QmlJS::StaticAnalysisMessages)

public:
    void newMsg(Type type, Enum severity, const QString &message, int placeholders = 0)
    {
        PrototypeMessageData prototype;
        prototype.type = type;
        prototype.severity = severity;
        prototype.message = message;
        prototype.placeholders = placeholders;
        QTC_CHECK(placeholders <= 2);
        QTC_ASSERT(!messages.contains(type), return);
        messages[type] = prototype;
    }

    StaticAnalysisMessages();
    QHash<Type, PrototypeMessageData> messages;
};

static inline QString msgInvalidConstructor(const char *what)
{
    return StaticAnalysisMessages::tr("Do not use '%1' as a constructor.").arg(QLatin1String(what));
}

StaticAnalysisMessages::StaticAnalysisMessages()
{
    // When changing a message or severity, update the documentation, currently
    // in creator-editors.qdoc, accordingly.
    newMsg(ErrInvalidEnumValue, Error,
           tr("Invalid value for enum."));
    newMsg(ErrEnumValueMustBeStringOrNumber, Error,
           tr("Enum value must be a string or a number."));
    newMsg(ErrNumberValueExpected, Error,
           tr("Number value expected."));
    newMsg(ErrBooleanValueExpected, Error,
           tr("Boolean value expected."));
    newMsg(ErrStringValueExpected, Error,
           tr("String value expected."));
    newMsg(ErrInvalidUrl, Error,
           tr("Invalid URL."));
    newMsg(WarnFileOrDirectoryDoesNotExist, Warning,
           tr("File or directory does not exist."));
    newMsg(ErrInvalidColor, Error,
           tr("Invalid color."));
    newMsg(ErrAnchorLineExpected, Error,
           tr("Anchor line expected."));
    newMsg(ErrPropertiesCanOnlyHaveOneBinding, Error,
           tr("Duplicate property binding."));
    newMsg(ErrIdExpected, Error,
           tr("Id expected."));
    newMsg(ErrInvalidId, Error,
           tr("Invalid id."));
    newMsg(ErrDuplicateId, Error,
           tr("Duplicate id."));
    newMsg(ErrInvalidPropertyName, Error,
           tr("Invalid property name '%1'."), 1);
    newMsg(ErrDoesNotHaveMembers, Error,
           tr("'%1' does not have members."), 1);
    newMsg(ErrInvalidMember, Error,
           tr("'%1' is not a member of '%2'."), 2);
    newMsg(WarnAssignmentInCondition, Warning,
           tr("Assignment in condition."));
    newMsg(WarnCaseWithoutFlowControl, Warning,
           tr("Unterminated non-empty case block."));
    newMsg(WarnEval, Warning,
           tr("Do not use 'eval'."));
    newMsg(WarnUnreachable, Warning,
           tr("Unreachable."));
    newMsg(WarnWith, Warning,
           tr("Do not use 'with'."));
    newMsg(WarnComma, Warning,
           tr("Do not use comma expressions."));
    newMsg(WarnAlreadyFormalParameter, Warning,
           tr("'%1' already is a formal parameter."), 1);
    newMsg(WarnUnnecessaryMessageSuppression, Warning,
           tr("Unnecessary message suppression."));
    newMsg(WarnAlreadyFunction, Warning,
           tr("'%1' already is a function."), 1);
    newMsg(WarnVarUsedBeforeDeclaration, Warning,
           tr("var '%1' is used before its declaration."), 1);
    newMsg(WarnAlreadyVar, Warning,
           tr("'%1' already is a var."), 1);
    newMsg(WarnDuplicateDeclaration, Warning,
           tr("'%1' is declared more than once."), 1);
    newMsg(WarnFunctionUsedBeforeDeclaration, Warning,
           tr("Function '%1' is used before its declaration."), 1);
    newMsg(WarnBooleanConstructor, Warning,
           msgInvalidConstructor("Boolean"));
    newMsg(WarnStringConstructor, Warning,
           msgInvalidConstructor("String"));
    newMsg(WarnObjectConstructor, Warning,
           msgInvalidConstructor("Object"));
    newMsg(WarnArrayConstructor, Warning,
           msgInvalidConstructor("Array"));
    newMsg(WarnFunctionConstructor, Warning,
           msgInvalidConstructor("Function"));
    newMsg(HintAnonymousFunctionSpacing, Hint,
           tr("The 'function' keyword and the opening parenthesis should be separated by a single space."));
    newMsg(WarnBlock, Warning,
           tr("Do not use stand-alone blocks."));
    newMsg(WarnVoid, Warning,
           tr("Do not use void expressions."));
    newMsg(WarnConfusingPluses, Warning,
           tr("Confusing pluses."));
    newMsg(WarnConfusingMinuses, Warning,
           tr("Confusing minuses."));
    newMsg(HintDeclareVarsInOneLine, Hint,
           tr("Declare all function vars on a single line."));
    newMsg(HintExtraParentheses, Hint,
           tr("Unnecessary parentheses."));
    newMsg(MaybeWarnEqualityTypeCoercion, MaybeWarning,
           tr("== and != may perform type coercion, use === or !== to avoid it."));
    newMsg(WarnConfusingExpressionStatement, Error,
           tr("Expression statements should be assignments, calls or delete expressions only."));
    newMsg(HintDeclarationsShouldBeAtStartOfFunction, Hint,
           tr("Place var declarations at the start of a function."));
    newMsg(HintOneStatementPerLine, Hint,
           tr("Use only one statement per line."));
    newMsg(ErrUnknownComponent, Error,
           tr("Unknown component."));
    newMsg(ErrCouldNotResolvePrototypeOf, Error,
           tr("Could not resolve the prototype '%1' of '%2'."), 2);
    newMsg(ErrCouldNotResolvePrototype, Error,
           tr("Could not resolve the prototype '%1'."), 1);
    newMsg(ErrPrototypeCycle, Error,
           tr("Prototype cycle, the last non-repeated component is '%1'."), 1);
    newMsg(ErrInvalidPropertyType, Error,
           tr("Invalid property type '%1'."), 1);
    newMsg(WarnEqualityTypeCoercion, Error,
           tr("== and != perform type coercion, use === or !== to avoid it."));
    newMsg(WarnExpectedNewWithUppercaseFunction, Error,
           tr("Calls of functions that start with an uppercase letter should use 'new'."));
    newMsg(WarnNewWithLowercaseFunction, Error,
           tr("Use 'new' only with functions that start with an uppercase letter."));
    newMsg(WarnNumberConstructor, Error,
           msgInvalidConstructor("Function"));
    newMsg(HintBinaryOperatorSpacing, Hint,
           tr("Use spaces around binary operators."));
    newMsg(WarnUnintentinalEmptyBlock, Error,
           tr("Unintentional empty block, use ({}) for empty object literal."));
    newMsg(HintPreferNonVarPropertyType, Hint,
           tr("Use %1 instead of 'var' or 'variant' to improve performance."), 1);
    newMsg(ErrMissingRequiredProperty, Error,
           tr("Missing property '%1'."), 1);
    newMsg(ErrObjectValueExpected, Error,
           tr("Object value expected."));
    newMsg(ErrArrayValueExpected, Error,
           tr("Array value expected."));
    newMsg(ErrDifferentValueExpected, Error,
           tr("%1 value expected."), 1);
    newMsg(ErrSmallerNumberValueExpected, Error,
           tr("Maximum number value is %1."), 1);
    newMsg(ErrLargerNumberValueExpected, Error,
           tr("Minimum number value is %1."), 1);
    newMsg(ErrMaximumNumberValueIsExclusive, Error,
           tr("Maximum number value is exclusive."));
    newMsg(ErrMinimumNumberValueIsExclusive, Error,
           tr("Minimum number value is exclusive."));
    newMsg(ErrInvalidStringValuePattern, Error,
           tr("String value does not match required pattern."));
    newMsg(ErrLongerStringValueExpected, Error,
           tr("Minimum string value length is %1."), 1);
    newMsg(ErrShorterStringValueExpected, Error,
           tr("Maximum string value length is %1."), 1);
    newMsg(ErrInvalidArrayValueLength, Error,
           tr("%1 elements expected in array value."), 1);
    newMsg(WarnImperativeCodeNotEditableInVisualDesigner, Warning,
            tr("Imperative code is not supported in the Qt Quick Designer."));
    newMsg(WarnUnsupportedTypeInVisualDesigner, Warning,
            tr("This type is not supported in the Qt Quick Designer."));
    newMsg(WarnReferenceToParentItemNotSupportedByVisualDesigner, Warning,
            tr("Reference to parent item cannot be resolved correctly by the Qt Quick Designer."));
    newMsg(WarnUndefinedValueForVisualDesigner, Warning,
            tr("This visual property binding cannot be evaluated in the local context "
               "and might not show up in Qt Quick Designer as expected."));
    newMsg(WarnStatesOnlyInRootItemForVisualDesigner, Warning,
            tr("Qt Quick Designer only supports states in the root item."));
    newMsg(WarnAboutQtQuick1InsteadQtQuick2, Warning,
            tr("Using Qt Quick 1 code model instead of Qt Quick 2."));
}

} // anonymous namespace

Q_GLOBAL_STATIC(StaticAnalysisMessages, messages)

QList<Type> Message::allMessageTypes()
{
    return messages()->messages.keys();
}

Message::Message()
    : type(UnknownType), severity(Hint)
{}

Message::Message(Type type,
                 AST::SourceLocation location,
                 const QString &arg1,
                 const QString &arg2,
                 bool appendTypeId)
    : location(location), type(type)
{
    QTC_ASSERT(messages()->messages.contains(type), return);
    const PrototypeMessageData &prototype = prototypeForMessageType(type);
    severity = prototype.severity;
    message = prototype.message;
    if (prototype.placeholders == 0) {
        if (!arg1.isEmpty() || !arg2.isEmpty())
            qWarning() << "StaticAnalysis message" << type << "expects no arguments";
    } else if (prototype.placeholders == 1) {
        if (arg1.isEmpty() || !arg2.isEmpty())
            qWarning() << "StaticAnalysis message" << type << "expects exactly one argument";
        message = message.arg(arg1);
    } else if (prototype.placeholders == 2) {
        if (arg1.isEmpty() || arg2.isEmpty())
            qWarning() << "StaticAnalysis message" << type << "expects exactly two arguments";
        message = message.arg(arg1, arg2);
    }
    if (appendTypeId)
        message.append(QString::fromLatin1(" (M%1)").arg(QString::number(prototype.type)));
}

bool Message::isValid() const
{
    return type != UnknownType && location.isValid() && !message.isEmpty();
}

DiagnosticMessage Message::toDiagnosticMessage() const
{
    DiagnosticMessage diagnostic;
    switch (severity) {
    case Hint:
    case MaybeWarning:
    case Warning:
        diagnostic.kind = Warning;
        break;
    default:
        diagnostic.kind = Error;
        break;
    }
    diagnostic.loc = location;
    diagnostic.message = message;
    return diagnostic;
}

QString Message::suppressionString() const
{
    return QString::fromLatin1("@disable-check M%1").arg(QString::number(type));
}

QRegExp Message::suppressionPattern()
{
    return QRegExp(QLatin1String("@disable-check M(\\d+)"));
}

const PrototypeMessageData Message::prototypeForMessageType(Type type)
{
     QTC_CHECK(messages()->messages.contains(type));
     const PrototypeMessageData &prototype = messages()->messages.value(type);

     return prototype;
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <fstream>

#include "kms++.h"

#include "test.h"

using namespace std;
using namespace kms;

int main(int argc, char** argv)
{
	if (argc != 5) {
		printf("Usage: %s <file> <width> <height> <fourcc>\n", argv[0]);
		return -1;
	}

	string filename = argv[1];
	uint32_t w = stoi(argv[2]);
	uint32_t h = stoi(argv[3]);
	string modestr = argv[4];

	auto pixfmt = FourCCToPixelFormat(modestr);

	Card card;

	auto conn = card.get_first_connected_connector();
	auto crtc = conn->get_current_crtc();

	auto fb = new DumbFramebuffer(card, w, h, pixfmt);

	ifstream is(filename, ifstream::binary);
	is.read((char*)fb->map(0), fb->size(0));
	is.close();

	Plane* plane = 0;

	for (Plane* p : crtc->get_possible_planes()) {
		if (p->plane_type() != PlaneType::Overlay)
			continue;

		if (!p->supports_format(pixfmt))
			continue;

		plane = p;
		break;
	}

	FAIL_IF(!plane, "available plane not found");

	int r = crtc->set_plane(plane, *fb,
				0, 0, w, h,
				0, 0, w, h);

	ASSERT(r == 0);

	printf("press enter to exit\n");

	getchar();

	delete fb;
}
<commit_msg>kmsview: show multiple frames<commit_after>#include <cstdio>
#include <fstream>
#include <unistd.h>

#include "kms++.h"

#include "test.h"

using namespace std;
using namespace kms;

static void read_frame(ifstream& is, DumbFramebuffer* fb, Crtc* crtc, Plane* plane)
{
	is.read((char*)fb->map(0), fb->size(0));

	int r = crtc->set_plane(plane, *fb,
				0, 0, fb->width(), fb->height(),
				0, 0, fb->width(), fb->height());

	ASSERT(r == 0);
}

int main(int argc, char** argv)
{
	if (argc != 5) {
		printf("Usage: %s <file> <width> <height> <fourcc>\n", argv[0]);
		return -1;
	}

	string filename = argv[1];
	uint32_t w = stoi(argv[2]);
	uint32_t h = stoi(argv[3]);
	string modestr = argv[4];

	auto pixfmt = FourCCToPixelFormat(modestr);

	ifstream is(filename, ifstream::binary);

	is.seekg(0, std::ios::end);
	unsigned fsize = is.tellg();
	is.seekg(0);

	Card card;

	auto conn = card.get_first_connected_connector();
	auto crtc = conn->get_current_crtc();

	auto fb = new DumbFramebuffer(card, w, h, pixfmt);

	Plane* plane = 0;

	for (Plane* p : crtc->get_possible_planes()) {
		if (p->plane_type() != PlaneType::Overlay)
			continue;

		if (!p->supports_format(pixfmt))
			continue;

		plane = p;
		break;
	}

	FAIL_IF(!plane, "available plane not found");

	unsigned num_frames = fsize / fb->size(0);
	printf("file size %u, frames %u\n", fsize, num_frames);

	for (unsigned i = 0; i < num_frames; ++i) {
		printf("frame %d\n", i);
		read_frame(is, fb, crtc, plane);
		usleep(1000*50);
	}

	printf("press enter to exit\n");

	is.close();

	getchar();

	delete fb;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>

#include "bin/builtin.h"
#include "bin/file.h"

class FileHandle {
 public:
  explicit FileHandle(int fd) : fd_(fd) { }
  ~FileHandle() { }
  int fd() const { return fd_; }
  void set_fd(int fd) { fd_ = fd; }

 private:
  int fd_;

  // DISALLOW_COPY_AND_ASSIGN(FileHandle).
  FileHandle(const FileHandle&);
  void operator=(const FileHandle&);
};

File::~File() {
  // Close the file (unless it's a standard stream).
  if (handle_->fd() > STDERR_FILENO) {
    Close();
  }
  delete handle_;
}

void File::Close() {
  ASSERT(handle_->fd() >= 0);
  int err = close(handle_->fd());
  if (err != 0) {
    const int kBufferSize = 1024;
    char error_message[kBufferSize];
    strerror_r(errno, error_message, kBufferSize);
    fprintf(stderr, "%s\n", error_message);
  }
  handle_->set_fd(kClosedFd);
}

bool File::IsClosed() {
  return handle_->fd() == kClosedFd;
}

int64_t File::Read(void* buffer, int64_t num_bytes) {
  ASSERT(handle_->fd() >= 0);
  return read(handle_->fd(), buffer, num_bytes);
}

int64_t File::Write(const void* buffer, int64_t num_bytes) {
  ASSERT(handle_->fd() >= 0);
  return write(handle_->fd(), buffer, num_bytes);
}

off_t File::Position() {
  ASSERT(handle_->fd() >= 0);
  return lseek(handle_->fd(), 0, SEEK_CUR);
}

void File::Flush() {
  ASSERT(handle_->fd() >= 0);
  fsync(handle_->fd());
}

off_t File::Length() {
  ASSERT(handle_->fd() >= 0);
  off_t position = lseek(handle_->fd(), 0, SEEK_CUR);
  if (position < 0) {
    // The file is not capable of seeking. Return an error.
    return -1;
  }
  off_t result = lseek(handle_->fd(), 0, SEEK_END);
  lseek(handle_->fd(), position, SEEK_SET);
  return result;
}

File* File::OpenFile(const char* name, bool writable) {
  int flags = O_RDONLY;
  if (writable) {
    flags = (O_RDWR | O_CREAT | O_TRUNC);
  }
  int fd = open(name, flags, 0666);
  if (fd < 0) {
    return NULL;
  }
  return new File(name, new FileHandle(fd));
}

bool File::FileExists(const char* name) {
  struct stat st;
  if (stat(name, &st) == 0) {
    return S_ISREG(st.st_mode);  // Deal with symlinks?
  } else {
    return false;
  }
}

bool File::IsAbsolutePath(const char* pathname) {
  return (pathname != NULL && pathname[0] == '/');
}

char* File::GetCanonicalPath(const char* pathname) {
  char* abs_path = NULL;
  if (pathname != NULL) {
    abs_path = realpath(pathname, NULL);
    assert(abs_path == NULL || IsAbsolutePath(abs_path));
  }
  return abs_path;
}

const char* File::PathSeparator() {
  return "/";
}

const char* File::StringEscapedPathSeparator() {
  return "/";
}
<commit_msg>Allocate and pass a resolved_path buffer to realpath as older macos versions do not work when a NULL is passed in for resolved_path Review URL: http://codereview.chromium.org//8400070<commit_after>// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>
#include <limits.h>

#include "bin/builtin.h"
#include "bin/file.h"

class FileHandle {
 public:
  explicit FileHandle(int fd) : fd_(fd) { }
  ~FileHandle() { }
  int fd() const { return fd_; }
  void set_fd(int fd) { fd_ = fd; }

 private:
  int fd_;

  // DISALLOW_COPY_AND_ASSIGN(FileHandle).
  FileHandle(const FileHandle&);
  void operator=(const FileHandle&);
};

File::~File() {
  // Close the file (unless it's a standard stream).
  if (handle_->fd() > STDERR_FILENO) {
    Close();
  }
  delete handle_;
}

void File::Close() {
  ASSERT(handle_->fd() >= 0);
  int err = close(handle_->fd());
  if (err != 0) {
    const int kBufferSize = 1024;
    char error_message[kBufferSize];
    strerror_r(errno, error_message, kBufferSize);
    fprintf(stderr, "%s\n", error_message);
  }
  handle_->set_fd(kClosedFd);
}

bool File::IsClosed() {
  return handle_->fd() == kClosedFd;
}

int64_t File::Read(void* buffer, int64_t num_bytes) {
  ASSERT(handle_->fd() >= 0);
  return read(handle_->fd(), buffer, num_bytes);
}

int64_t File::Write(const void* buffer, int64_t num_bytes) {
  ASSERT(handle_->fd() >= 0);
  return write(handle_->fd(), buffer, num_bytes);
}

off_t File::Position() {
  ASSERT(handle_->fd() >= 0);
  return lseek(handle_->fd(), 0, SEEK_CUR);
}

void File::Flush() {
  ASSERT(handle_->fd() >= 0);
  fsync(handle_->fd());
}

off_t File::Length() {
  ASSERT(handle_->fd() >= 0);
  off_t position = lseek(handle_->fd(), 0, SEEK_CUR);
  if (position < 0) {
    // The file is not capable of seeking. Return an error.
    return -1;
  }
  off_t result = lseek(handle_->fd(), 0, SEEK_END);
  lseek(handle_->fd(), position, SEEK_SET);
  return result;
}

File* File::OpenFile(const char* name, bool writable) {
  int flags = O_RDONLY;
  if (writable) {
    flags = (O_RDWR | O_CREAT | O_TRUNC);
  }
  int fd = open(name, flags, 0666);
  if (fd < 0) {
    return NULL;
  }
  return new File(name, new FileHandle(fd));
}

bool File::FileExists(const char* name) {
  struct stat st;
  if (stat(name, &st) == 0) {
    return S_ISREG(st.st_mode);  // Deal with symlinks?
  } else {
    return false;
  }
}

bool File::IsAbsolutePath(const char* pathname) {
  return (pathname != NULL && pathname[0] == '/');
}

char* File::GetCanonicalPath(const char* pathname) {
  char* abs_path = NULL;
  if (pathname != NULL) {
    // On some older MacOs versions the default behaviour of realpath allocating
    // space for the resolved_path when a NULL is passed in does not seem to
    // work, so we explicitly allocate space. The caller is responsible for
    // freeing this space as in a regular realpath call.
    char* resolved_path = reinterpret_cast<char*>(malloc(PATH_MAX+1));
    ASSERT(resolved_path != NULL);
    abs_path = realpath(pathname, resolved_path);
    assert(abs_path == NULL || IsAbsolutePath(abs_path));
  }
  return abs_path;
}

const char* File::PathSeparator() {
  return "/";
}

const char* File::StringEscapedPathSeparator() {
  return "/";
}
<|endoftext|>