<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "MemoryUsageReporter.h"
#include "MemoryUtils.h"

MemoryUsageReporter::MemoryUsageReporter(const MooseObject * moose_object)
  : _mur_communicator(moose_object->comm()),
    _my_rank(_mur_communicator.rank()),
    _nrank(_mur_communicator.size()),
    _hardware_id(_nrank)
{
  // get total available ram
  _memory_total = MemoryUtils::getTotalRAM();
  if (!_memory_total)
    mooseWarning("Unable to query hardware memory size in ", moose_object->name());

  // gather all per node memory to processor zero
  std::vector<unsigned long long> memory_totals(_nrank);
  _mur_communicator.gather(0, _memory_total, memory_totals);

  sharedMemoryRanksBySplitCommunicator();

  // validate and store per node memory
  if (_my_rank == 0)
    for (std::size_t i = 0; i < _nrank; ++i)
    {
      auto id = _hardware_id[i];
      if (id == _hardware_memory_total.size())
      {
        _hardware_memory_total.resize(id + 1);
        _hardware_memory_total[id] = memory_totals[i];
      }
      else if (_hardware_memory_total[id] != memory_totals[i])
        mooseWarning("Inconsistent total memory reported by ranks on the same hardware node in ",
                     moose_object->name());
    }
}

void
MemoryUsageReporter::sharedMemoryRanksBySplitCommunicator()
{
  // figure out which ranks share memory
  processor_id_type world_rank = 0;
#ifdef LIBMESH_HAVE_MPI
  // create a split communicator among shared memory ranks
  MPI_Comm shmem_raw_comm;
  MPI_Comm_split_type(
      _mur_communicator.get(), MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &shmem_raw_comm);
  Parallel::Communicator shmem_comm(shmem_raw_comm);

  // broadcast the world rank of the sub group root
  world_rank = _my_rank;
  shmem_comm.broadcast(world_rank, 0);
#endif
  std::vector<processor_id_type> world_ranks(_nrank);
  _mur_communicator.gather(0, world_rank, world_ranks);

  // assign a contiguous unique numerical id to each shared memory group on processor zero
  unsigned int id = 0;
  processor_id_type last = world_ranks[0];
  if (_my_rank == 0)
    for (std::size_t i = 0; i < _nrank; ++i)
    {
      if (world_ranks[i] != last)
      {
        last = world_ranks[i];
        id++;
      }
      _hardware_id[i] = id;
    }
}

void
MemoryUsageReporter::sharedMemoryRanksByProcessorname()
{
  // get processor names and assign a unique number to each piece of hardware
  std::string processor_name = MemoryUtils::getMPIProcessorName();

  // gather all names at processor zero
  std::vector<std::string> processor_names(_nrank);
  _mur_communicator.gather(0, processor_name, processor_names);

  // assign a unique numerical id to them on processor zero
  unsigned int id = 0;
  if (_my_rank == 0)
  {
    // map to assign an id to each processor name string
    std::map<std::string, unsigned int> hardware_id_map;
    for (std::size_t i = 0; i < _nrank; ++i)
    {
      // generate or look up unique ID for the current processor name
      auto it = hardware_id_map.lower_bound(processor_names[i]);
      if (it == hardware_id_map.end() || it->first != processor_names[i])
        it = hardware_id_map.emplace_hint(it, processor_names[i], id++);
      _hardware_id[i] = it->second;
    }
  }
}
<commit_msg>Free the comm in MemoryUsageReporter<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "MemoryUsageReporter.h"
#include "MemoryUtils.h"

MemoryUsageReporter::MemoryUsageReporter(const MooseObject * moose_object)
  : _mur_communicator(moose_object->comm()),
    _my_rank(_mur_communicator.rank()),
    _nrank(_mur_communicator.size()),
    _hardware_id(_nrank)
{
  // get total available ram
  _memory_total = MemoryUtils::getTotalRAM();
  if (!_memory_total)
    mooseWarning("Unable to query hardware memory size in ", moose_object->name());

  // gather all per node memory to processor zero
  std::vector<unsigned long long> memory_totals(_nrank);
  _mur_communicator.gather(0, _memory_total, memory_totals);

  sharedMemoryRanksBySplitCommunicator();

  // validate and store per node memory
  if (_my_rank == 0)
    for (std::size_t i = 0; i < _nrank; ++i)
    {
      auto id = _hardware_id[i];
      if (id == _hardware_memory_total.size())
      {
        _hardware_memory_total.resize(id + 1);
        _hardware_memory_total[id] = memory_totals[i];
      }
      else if (_hardware_memory_total[id] != memory_totals[i])
        mooseWarning("Inconsistent total memory reported by ranks on the same hardware node in ",
                     moose_object->name());
    }
}

void
MemoryUsageReporter::sharedMemoryRanksBySplitCommunicator()
{
  // figure out which ranks share memory
  processor_id_type world_rank = 0;
#ifdef LIBMESH_HAVE_MPI
  // create a split communicator among shared memory ranks
  MPI_Comm shmem_raw_comm;
  MPI_Comm_split_type(
      _mur_communicator.get(), MPI_COMM_TYPE_SHARED, 0, MPI_INFO_NULL, &shmem_raw_comm);
  Parallel::Communicator shmem_comm(shmem_raw_comm);

  // broadcast the world rank of the sub group root
  world_rank = _my_rank;
  shmem_comm.broadcast(world_rank, 0);

  MPI_Comm_free(&shmem_raw_comm);
#endif
  std::vector<processor_id_type> world_ranks(_nrank);
  _mur_communicator.gather(0, world_rank, world_ranks);

  // assign a contiguous unique numerical id to each shared memory group on processor zero
  unsigned int id = 0;
  processor_id_type last = world_ranks[0];
  if (_my_rank == 0)
    for (std::size_t i = 0; i < _nrank; ++i)
    {
      if (world_ranks[i] != last)
      {
        last = world_ranks[i];
        id++;
      }
      _hardware_id[i] = id;
    }
}

void
MemoryUsageReporter::sharedMemoryRanksByProcessorname()
{
  // get processor names and assign a unique number to each piece of hardware
  std::string processor_name = MemoryUtils::getMPIProcessorName();

  // gather all names at processor zero
  std::vector<std::string> processor_names(_nrank);
  _mur_communicator.gather(0, processor_name, processor_names);

  // assign a unique numerical id to them on processor zero
  unsigned int id = 0;
  if (_my_rank == 0)
  {
    // map to assign an id to each processor name string
    std::map<std::string, unsigned int> hardware_id_map;
    for (std::size_t i = 0; i < _nrank; ++i)
    {
      // generate or look up unique ID for the current processor name
      auto it = hardware_id_map.lower_bound(processor_names[i]);
      if (it == hardware_id_map.end() || it->first != processor_names[i])
        it = hardware_id_map.emplace_hint(it, processor_names[i], id++);
      _hardware_id[i] = it->second;
    }
  }
}
<|endoftext|>


<commit_before>#ifndef TYPES_H
#define TYPES_H
/*
Defines a set of types for use on the hl-side.
*/

#include"objects.hpp"

class GenericTraverser {
public:
	virtual void traverse(Object::ref&) =0;
	virtual ~GenericTraverser();
};

/*-----------------------------------------------------------------------------
Generic
-----------------------------------------------------------------------------*/

class Generic {
public:

	virtual void traverse_references(GenericTraverser* gt) {
		/*default to having no references to traverse*/
	}

	/*some objects have extra allocated space at their ends
	(e.g. Closure).
 	This virtual function returns the total size of the class
	plus extra allocated space.
	*/
	virtual size_t real_size(void) const =0;

	/*hash functions for table-ident and table-is*/
	virtual size_t hash_ident(void) const {
		return reinterpret_cast<size_t>(this);
	}
	virtual size_t hash_is(void) const {
		return reinterpret_cast<size_t>(this);
	}

	/*broken hearts for GC*/
	virtual void break_heart(Object::ref) =0;

	/*dtor*/
	virtual ~Generic() { }
};

template<class T>
class GenericDerived : class Generic {
public:
	virtual size_t real_size(void) {
		return sizeof(T);
	}
	virtual void break_heart(Generic* to) {
		Generic* gp = this;
		gp->~Generic();
		new((void*) gp) BrokenHeartFor<T>(to);
	};
};

void throw_OverBrokenHeart(Generic*);

class BrokenHeart : class Generic {
public:
	Generic* to;
	virtual bool break_heart(Generic* to) {
		/*already broken - don't break too much!*/
		throw_OverBrokenHeart(to);
	}
};

template<class T>
class BrokenHeartFor : class BrokenHeart {
public:
	virtual bool real_size(void) {
		return sizeof(T);
	}
};

#endif //TYPES_H

<commit_msg>inc/types.hpp: reorganized, corrected major syntax errors, added generic-derived for variadic<commit_after>#ifndef TYPES_H
#define TYPES_H
/*
Defines a set of types for use on the hl-side.
*/

#include"objects.hpp"

class GenericTraverser {
public:
	virtual void traverse(Object::ref&) =0;
	virtual ~GenericTraverser();
};

/*-----------------------------------------------------------------------------
Generic
-----------------------------------------------------------------------------*/

class Generic {
public:

	virtual void traverse_references(GenericTraverser* gt) {
		/*default to having no references to traverse*/
		/*example for Cons:
		gt->traverse(a);
		gt->traverse(d);
		*/
	}

	/*some objects have extra allocated space at their ends
	(e.g. Closure).
 	This virtual function returns the total size of the class
	plus extra allocated space.
	*/
	virtual size_t real_size(void) const =0;

	/*hash functions for table-ident and table-is*/
	virtual size_t hash_ident(void) const {
		return reinterpret_cast<size_t>(this);
	}
	virtual size_t hash_is(void) const {
		return reinterpret_cast<size_t>(this);
	}

	/*broken hearts for GC*/
	virtual void break_heart(Object::ref) =0;

	/*dtor*/
	virtual ~Generic() { }
};

/*-----------------------------------------------------------------------------
Broken Heart tags
-----------------------------------------------------------------------------*/

void throw_OverBrokenHeart(Generic*);

class BrokenHeart : public Generic {
public:
	Generic* to;
	virtual bool break_heart(Generic* to) {
		/*already broken - don't break too much!*/
		throw_OverBrokenHeart(to);
	}
	BrokenHeart(Object::ref nto) : to(nto) { }
};

template<class T>
class BrokenHeartFor : public BrokenHeart {
public:
	virtual bool real_size(void) const {
		return sizeof(T);
	}
	explicit BrokenHeartFor<T>(Object::ref x) : BrokenHeart(x) { }
};

template<class T>
class BrokenHeartForVariadic : public BrokenHeart {
private:
	size_t sz;
public:
	virtual bool real_size(void) const {
		return sizeof(T) + sz * sizeof(Object::ref);
	}
	BrokenHeartForVariadic<T>(Object::ref x, size_t nsz)
		: BrokenHeart(x), sz(nsz) { }
};

/*-----------------------------------------------------------------------------
Base classes for Generic-derived objects
-----------------------------------------------------------------------------*/

template<class T>
class GenericDerived : public Generic {
public:
	virtual size_t real_size(void) const {
		return sizeof(T);
	}
	virtual void break_heart(Generic* to) {
		Generic* gp = this;
		gp->~Generic();
		new((void*) gp) BrokenHeartFor<T>(to);
	};
};

/*This class implements a variable-size object by informing the
memory system to reserve extra space.
*/
template<class T>
class GenericDerivedVariadic : public Generic {
	GenericDerivedVariadic<T>(); // disallowed!
protected:
	/*number of extra Object::ref's*/
	size_t sz;
	/*used by the derived classes to get access to
	the variadic data at the end of the object.
	*/
	Object::ref& index(size_t i) {
		void* vp = this;
		char* cp = (char*) vp;
		cp = cp + sizeof(T);
		Object::ref* op = (void*) cp;
		return op[i];
	}
	GenericDerivedVariadic<T>(size_t nsz) : sz(nsz) {
		/*clear the extra references*/
		for(size_t i; i < nsz; ++i) {
			index(i) = Object::nil();
		}
	}
public:
	virtual size_t real_size(void) const {
		return sizeof(T) + sz * sizeof(Object::ref);
	}
	virtual void break_heart(Object::ref to) {
		Generic* gp = this;
		size_t nsz = sz; //save this before dtoring!
		gp->~Generic();
		new((void*) gp) BrokenHeartForVariadic<T>(to, nsz);
	}
};

#endif //TYPES_H

<|endoftext|>


<commit_before>/***********************************************************************************
**
** FileManager.cpp
**
** Copyright (C) August 2016 Hotride
**
************************************************************************************
*/
//----------------------------------------------------------------------------------
#include "FileManager.h"
#include "../Wisp/WispApplication.h"

CFileManager g_FileManager;
//----------------------------------------------------------------------------------
CFileManager::CFileManager()
: m_UseVerdata(false), m_UseUOP(false), m_UnicodeFontsCount(0)
{
}
//----------------------------------------------------------------------------------
CFileManager::~CFileManager()
{
}
//----------------------------------------------------------------------------------
bool CFileManager::Load()
{
	if (!g_FileManager.UseUOP)
	{
		 if (!m_ArtIdx.Load(g_App.FilePath("artidx.mul")))
			return false;
		else if (!m_GumpIdx.Load(g_App.FilePath("gumpidx.mul")))
			return false;
		else if (!m_SoundIdx.Load(g_App.FilePath("soundidx.mul")))
			return false;
		else if (!m_ArtMul.Load(g_App.FilePath("art.mul")))
			return false;
		else if (!m_GumpMul.Load(g_App.FilePath("gumpart.mul")))
			return false;
		else if (!m_SoundMul.Load(g_App.FilePath("sound.mul")))
			return false;
	}
	else
	{
		if (!m_artLegacyMUL.Load(g_App.FilePath("artLegacyMUL.uop")))
			return false;
		if (!m_gumpartLegacyMUL.Load(g_App.FilePath("gumpartLegacyMUL.uop")))
			return false;
		if (!m_soundLegacyMUL.Load(g_App.FilePath("soundLegacyMUL.uop")))
			return false;
		if (!m_tileart.Load(g_App.FilePath("tileart.uop")))
			return false;
		if (!m_string_dictionary.Load(g_App.FilePath("string_dictionary.uop")))
			return false;
		if (!m_MultiCollection.Load(g_App.FilePath("MultiCollection.uop")))
			return false;
		if (!m_AnimationSequence.Load(g_App.FilePath("AnimationSequence.uop")))
			return false;
		if (!m_MainMisc.Load(g_App.FilePath("MainMisc.uop")))
			return false;
		IFOR(i, 1, 5)
		{
			if (!m_AnimationFrame[i].Load(g_App.FilePath("AnimationFrame%i.uop", i)))
				return false;
		}
	}
	if (!m_AnimIdx[0].Load(g_App.FilePath("anim.idx")))
		return false;
	if (!m_LightIdx.Load(g_App.FilePath("lightidx.mul")))
		return false;
	else if (!m_MultiIdx.Load(g_App.FilePath("multi.idx")))
		return false;
	else if (!m_SkillsIdx.Load(g_App.FilePath("skills.idx")))
		return false;
	else if (!m_MultiMap.Load(g_App.FilePath("multimap.rle")))
		return false;
	else if (!m_TextureIdx.Load(g_App.FilePath("texidx.mul")))
		return false;
	else if (!m_SpeechMul.Load(g_App.FilePath("speech.mul")))
		return false;
	else if (!m_AnimMul[0].Load(g_App.FilePath("anim.mul")))
		return false;
	else if (!m_AnimdataMul.Load(g_App.FilePath("animdata.mul")))
		return false;
	else if (!m_HuesMul.Load(g_App.FilePath("hues.mul")))
		return false;
	else if (!m_FontsMul.Load(g_App.FilePath("fonts.mul")))
		return false;
	else if (!m_LightMul.Load(g_App.FilePath("light.mul")))
		return false;
	else if (!m_MultiMul.Load(g_App.FilePath("multi.mul")))
		return false;
	else if (!m_PaletteMul.Load(g_App.FilePath("palette.mul")))
		return false;
	else if (!m_RadarcolMul.Load(g_App.FilePath("radarcol.mul")))
		return false;
	else if (!m_SkillsMul.Load(g_App.FilePath("skills.mul")))
		return false;
	else if (!m_TextureMul.Load(g_App.FilePath("texmaps.mul")))
		return false;
	else if (!m_TiledataMul.Load(g_App.FilePath("tiledata.mul")))
		return false;

	m_LangcodeIff.Load(g_App.FilePath("Langcode.iff"));

	IFOR(i, 0, 6)
	{
		if (g_FileManager.UseUOP && i > 1 || !g_FileManager.UseUOP && i > 0)
		{
			if (!m_AnimIdx[i].Load(g_App.FilePath("anim%i.idx", i)))
				return false;
			if (!m_AnimMul[i].Load(g_App.FilePath("anim%i.mul", i)))
				return false;
		}

		if (g_FileManager.UseUOP)
		{
			if (!m_MapUOP[i].Load(g_App.FilePath("map%iLegacyMUL.uop", i)))
				return false;
			if (i == 0 || i == 1 || i == 2 || i == 5)
			{
				if (!m_MapXUOP[i].Load(g_App.FilePath("map%ixLegacyMUL.uop", i)))
					return false;
			}
		}
		else
		{
			m_MapMul[i].Load(g_App.FilePath("map%i.mul", i));
		}

		m_StaticIdx[i].Load(g_App.FilePath("staidx%i.mul", i));
		m_StaticMul[i].Load(g_App.FilePath("statics%i.mul", i));
		m_FacetMul[i].Load(g_App.FilePath("facet0%i.mul", i));
	}

	IFOR(i, 0, 20)
	{
		string s;

		if (i)
			s = g_App.FilePath("unifont%i.mul", i);
		else
			s = g_App.FilePath("unifont.mul");

		if (!m_UnifontMul[i].Load(s))
			break;

		m_UnicodeFontsCount++;
	}

	if (m_UseVerdata && !m_VerdataMul.Load(g_App.FilePath("verdata.mul")))
		m_UseVerdata = false;

	return true;
}
//----------------------------------------------------------------------------------
void CFileManager::Unload()
{

	if (!g_FileManager.UseUOP)
	{
		m_ArtIdx.Unload();
		m_GumpIdx.Unload();
		m_SoundIdx.Unload();
		m_ArtMul.Unload();
		m_GumpMul.Unload();
		m_SoundMul.Unload();
	}
	else
	{
		m_artLegacyMUL.Unload();
		m_gumpartLegacyMUL.Unload();
		m_soundLegacyMUL.Unload();
		m_tileart.Unload();
		m_string_dictionary.Unload();
		m_MultiCollection.Unload();
		m_AnimationSequence.Unload();
		m_MainMisc.Unload();

		IFOR(i, 1, 5)
		{
			m_AnimationFrame[i].Unload();
		}
	}
	m_LightIdx.Unload();
	m_MultiIdx.Unload();
	m_SkillsIdx.Unload();

	m_MultiMap.Unload();
	m_TextureIdx.Unload();
	m_SpeechMul.Unload();
	m_AnimdataMul.Unload();

	m_HuesMul.Unload();
	m_FontsMul.Unload();

	m_LightMul.Unload();
	m_MultiMul.Unload();
	m_PaletteMul.Unload();
	m_RadarcolMul.Unload();
	m_SkillsMul.Unload();

	m_TextureMul.Unload();
	m_TiledataMul.Unload();

	m_LangcodeIff.Unload();

	IFOR(i, 0, 6)
	{
		m_AnimIdx[i].Unload();
		m_AnimMul[i].Unload();
		if (g_FileManager.UseUOP)
		{
			m_MapUOP[i].Unload();
			m_MapXUOP[i].Unload();

		}
		else
			m_MapMul[i].Unload();
		m_StaticIdx[i].Unload();
		m_StaticMul[i].Unload();
		m_FacetMul[i].Unload();
	}

	IFOR(i, 0, 20)
		m_UnifontMul[i].Unload();

	m_VerdataMul.Unload();
}
//----------------------------------------------------------------------------------<commit_msg>Выключил ммапинг AnimationFrame из-за нехватки памяти.<commit_after>/***********************************************************************************
**
** FileManager.cpp
**
** Copyright (C) August 2016 Hotride
**
************************************************************************************
*/
//----------------------------------------------------------------------------------
#include "FileManager.h"
#include "../Wisp/WispApplication.h"

CFileManager g_FileManager;
//----------------------------------------------------------------------------------
CFileManager::CFileManager()
: m_UseVerdata(false), m_UseUOP(false), m_UnicodeFontsCount(0)
{
}
//----------------------------------------------------------------------------------
CFileManager::~CFileManager()
{
}
//----------------------------------------------------------------------------------
bool CFileManager::Load()
{
	if (!g_FileManager.UseUOP)
	{
		 if (!m_ArtIdx.Load(g_App.FilePath("artidx.mul")))
			return false;
		else if (!m_GumpIdx.Load(g_App.FilePath("gumpidx.mul")))
			return false;
		else if (!m_SoundIdx.Load(g_App.FilePath("soundidx.mul")))
			return false;
		else if (!m_ArtMul.Load(g_App.FilePath("art.mul")))
			return false;
		else if (!m_GumpMul.Load(g_App.FilePath("gumpart.mul")))
			return false;
		else if (!m_SoundMul.Load(g_App.FilePath("sound.mul")))
			return false;
	}
	else
	{
		if (!m_artLegacyMUL.Load(g_App.FilePath("artLegacyMUL.uop")))
			return false;
		if (!m_gumpartLegacyMUL.Load(g_App.FilePath("gumpartLegacyMUL.uop")))
			return false;
		if (!m_soundLegacyMUL.Load(g_App.FilePath("soundLegacyMUL.uop")))
			return false;
		if (!m_tileart.Load(g_App.FilePath("tileart.uop")))
			return false;
		if (!m_string_dictionary.Load(g_App.FilePath("string_dictionary.uop")))
			return false;
		if (!m_MultiCollection.Load(g_App.FilePath("MultiCollection.uop")))
			return false;
		if (!m_AnimationSequence.Load(g_App.FilePath("AnimationSequence.uop")))
			return false;
		if (!m_MainMisc.Load(g_App.FilePath("MainMisc.uop")))
			return false;
		/*IFOR(i, 1, 5)
		{
			if (!m_AnimationFrame[i].Load(g_App.FilePath("AnimationFrame%i.uop", i)))
				return false;
		}*/
	}
	if (!m_AnimIdx[0].Load(g_App.FilePath("anim.idx")))
		return false;
	if (!m_LightIdx.Load(g_App.FilePath("lightidx.mul")))
		return false;
	else if (!m_MultiIdx.Load(g_App.FilePath("multi.idx")))
		return false;
	else if (!m_SkillsIdx.Load(g_App.FilePath("skills.idx")))
		return false;
	else if (!m_MultiMap.Load(g_App.FilePath("multimap.rle")))
		return false;
	else if (!m_TextureIdx.Load(g_App.FilePath("texidx.mul")))
		return false;
	else if (!m_SpeechMul.Load(g_App.FilePath("speech.mul")))
		return false;
	else if (!m_AnimMul[0].Load(g_App.FilePath("anim.mul")))
		return false;
	else if (!m_AnimdataMul.Load(g_App.FilePath("animdata.mul")))
		return false;
	else if (!m_HuesMul.Load(g_App.FilePath("hues.mul")))
		return false;
	else if (!m_FontsMul.Load(g_App.FilePath("fonts.mul")))
		return false;
	else if (!m_LightMul.Load(g_App.FilePath("light.mul")))
		return false;
	else if (!m_MultiMul.Load(g_App.FilePath("multi.mul")))
		return false;
	else if (!m_PaletteMul.Load(g_App.FilePath("palette.mul")))
		return false;
	else if (!m_RadarcolMul.Load(g_App.FilePath("radarcol.mul")))
		return false;
	else if (!m_SkillsMul.Load(g_App.FilePath("skills.mul")))
		return false;
	else if (!m_TextureMul.Load(g_App.FilePath("texmaps.mul")))
		return false;
	else if (!m_TiledataMul.Load(g_App.FilePath("tiledata.mul")))
		return false;

	m_LangcodeIff.Load(g_App.FilePath("Langcode.iff"));

	IFOR(i, 0, 6)
	{
		if (g_FileManager.UseUOP && i > 1 || !g_FileManager.UseUOP && i > 0)
		{
			if (!m_AnimIdx[i].Load(g_App.FilePath("anim%i.idx", i)))
				return false;
			if (!m_AnimMul[i].Load(g_App.FilePath("anim%i.mul", i)))
				return false;
		}

		if (g_FileManager.UseUOP)
		{
			if (!m_MapUOP[i].Load(g_App.FilePath("map%iLegacyMUL.uop", i)))
				return false;
			if (i == 0 || i == 1 || i == 2 || i == 5)
			{
				if (!m_MapXUOP[i].Load(g_App.FilePath("map%ixLegacyMUL.uop", i)))
					return false;
			}
		}
		else
		{
			m_MapMul[i].Load(g_App.FilePath("map%i.mul", i));
		}

		m_StaticIdx[i].Load(g_App.FilePath("staidx%i.mul", i));
		m_StaticMul[i].Load(g_App.FilePath("statics%i.mul", i));
		m_FacetMul[i].Load(g_App.FilePath("facet0%i.mul", i));
	}

	IFOR(i, 0, 20)
	{
		string s;

		if (i)
			s = g_App.FilePath("unifont%i.mul", i);
		else
			s = g_App.FilePath("unifont.mul");

		if (!m_UnifontMul[i].Load(s))
			break;

		m_UnicodeFontsCount++;
	}

	if (m_UseVerdata && !m_VerdataMul.Load(g_App.FilePath("verdata.mul")))
		m_UseVerdata = false;

	return true;
}
//----------------------------------------------------------------------------------
void CFileManager::Unload()
{

	if (!g_FileManager.UseUOP)
	{
		m_ArtIdx.Unload();
		m_GumpIdx.Unload();
		m_SoundIdx.Unload();
		m_ArtMul.Unload();
		m_GumpMul.Unload();
		m_SoundMul.Unload();
	}
	else
	{
		m_artLegacyMUL.Unload();
		m_gumpartLegacyMUL.Unload();
		m_soundLegacyMUL.Unload();
		m_tileart.Unload();
		m_string_dictionary.Unload();
		m_MultiCollection.Unload();
		m_AnimationSequence.Unload();
		m_MainMisc.Unload();

		IFOR(i, 1, 5)
		{
			m_AnimationFrame[i].Unload();
		}
	}
	m_LightIdx.Unload();
	m_MultiIdx.Unload();
	m_SkillsIdx.Unload();

	m_MultiMap.Unload();
	m_TextureIdx.Unload();
	m_SpeechMul.Unload();
	m_AnimdataMul.Unload();

	m_HuesMul.Unload();
	m_FontsMul.Unload();

	m_LightMul.Unload();
	m_MultiMul.Unload();
	m_PaletteMul.Unload();
	m_RadarcolMul.Unload();
	m_SkillsMul.Unload();

	m_TextureMul.Unload();
	m_TiledataMul.Unload();

	m_LangcodeIff.Unload();

	IFOR(i, 0, 6)
	{
		m_AnimIdx[i].Unload();
		m_AnimMul[i].Unload();
		if (g_FileManager.UseUOP)
		{
			m_MapUOP[i].Unload();
			m_MapXUOP[i].Unload();

		}
		else
			m_MapMul[i].Unload();
		m_StaticIdx[i].Unload();
		m_StaticMul[i].Unload();
		m_FacetMul[i].Unload();
	}

	IFOR(i, 0, 20)
		m_UnifontMul[i].Unload();

	m_VerdataMul.Unload();
}
//----------------------------------------------------------------------------------<|endoftext|>


<commit_before>#include "ghost/config.h"
#include "ghost/types.h"
#include "ghost/densemat.h"
#include "ghost/util.h"
#include "ghost/math.h"
#include "ghost/tsmttsm_kahan.h"
#include "ghost/tsmttsm_kahan_gen.h"

#include <map>

using namespace std;

static bool operator<(const ghost_tsmttsm_kahan_parameters_t &a, const ghost_tsmttsm_kahan_parameters_t &b)
{
    return ghost_hash(a.dt,a.wcols,ghost_hash(a.vcols,a.impl,0)) < ghost_hash(b.dt,b.wcols,ghost_hash(b.vcols,b.impl,0));
}

static map<ghost_tsmttsm_kahan_parameters_t, ghost_tsmttsm_kahan_kernel_t> ghost_tsmttsm_kahan_kernels;

ghost_error_t ghost_tsmttsm_kahan_valid(ghost_densemat_t *x, ghost_densemat_t *v, const char * transv,
ghost_densemat_t *w, const char *transw, void *alpha, void *beta, int reduce, int printerror)
{
    if (w->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("w must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("v must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (x->traits.storage != GHOST_DENSEMAT_COLMAJOR) {
        if (printerror) {
            ERROR_LOG("x must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.datatype != w->traits.datatype || v->traits.datatype != x->traits.datatype) {
        if (printerror) {
            ERROR_LOG("Different data types!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.flags & GHOST_DENSEMAT_SCATTERED || w->traits.flags & GHOST_DENSEMAT_SCATTERED || x->traits.flags & GHOST_DENSEMAT_SCATTERED) {
        if (printerror) {
            ERROR_LOG("Scattered densemats not supported!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (reduce != GHOST_GEMM_ALL_REDUCE) {
        if (printerror) {
            ERROR_LOG("Only Allreduce supported currently!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (!strncasecmp(transv,"N",1)) {
        if (printerror) {
            ERROR_LOG("v must be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (strncasecmp(transw,"N",1)) {
        if (printerror) {
            ERROR_LOG("w must not be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }

    UNUSED(alpha);
    UNUSED(beta);

    return GHOST_SUCCESS;
}

ghost_error_t ghost_tsmttsm_kahan(ghost_densemat_t *x, ghost_densemat_t *v, ghost_densemat_t *w, void *alpha, void *beta,int reduce,int conjv)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_MATH);
    ghost_error_t ret;

    if ((ret = ghost_tsmttsm_kahan_valid(x,v,"T",w,"N",alpha,beta,reduce,1)) != GHOST_SUCCESS) {
        return ret;
    }

    if (ghost_tsmttsm_kahan_kernels.empty()) {
#include "tsmttsm_kahan.def"
    }

    ghost_tsmttsm_kahan_parameters_t p;
    ghost_tsmttsm_kahan_kernel_t kernel = NULL;

    p.impl = GHOST_IMPLEMENTATION_PLAIN;

    p.dt = x->traits.datatype;

    p.vcols = v->traits.ncols;
    p.wcols = w->traits.ncols;
    kernel = ghost_tsmttsm_kahan_kernels[p];

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary block sizes");
        p.wcols = -1;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kahan_kernels[p];
    }

    kernel = ghost_tsmttsm_kahan_kernels[p];

    if (!kernel) {
        INFO_LOG("Could not find Kahan-TSMTTSM kernel with %d %d %d. Fallback to GEMM",p.dt,p.wcols,p.vcols);
        return GHOST_ERR_INVALID_ARG;

            //return ghost_gemm(x,v,"T",w,"N",alpha,beta,GHOST_GEMM_ALL_REDUCE,GHOST_GEMM_NOT_SPECIAL);
    }

    ret = kernel(x,v,w,alpha,beta,conjv);

#ifdef GHOST_HAVE_INSTR_TIMING
    ghost_gemm_perf_args_t tsmttsm_perfargs;
    tsmttsm_perfargs.xcols = p.wcols;
    tsmttsm_perfargs.vcols = p.vcols;
    tsmttsm_perfargs.vrows = v->context->gnrows;
    tsmttsm_perfargs.dt = x->traits.datatype;
    ghost_timing_set_perfFunc(__ghost_functag,ghost_gemm_perf_GFs,(void *)&tsmttsm_perfargs,sizeof(tsmttsm_perfargs),"GF/s");
#endif

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_MATH);

    return ret;
}

<commit_msg>fallback to GEMM<commit_after>#include "ghost/config.h"
#include "ghost/types.h"
#include "ghost/densemat.h"
#include "ghost/util.h"
#include "ghost/math.h"
#include "ghost/tsmttsm_kahan.h"
#include "ghost/tsmttsm_kahan_gen.h"

#include <map>

using namespace std;

static bool operator<(const ghost_tsmttsm_kahan_parameters_t &a, const ghost_tsmttsm_kahan_parameters_t &b)
{
    return ghost_hash(a.dt,a.wcols,ghost_hash(a.vcols,a.impl,0)) < ghost_hash(b.dt,b.wcols,ghost_hash(b.vcols,b.impl,0));
}

static map<ghost_tsmttsm_kahan_parameters_t, ghost_tsmttsm_kahan_kernel_t> ghost_tsmttsm_kahan_kernels;

ghost_error_t ghost_tsmttsm_kahan_valid(ghost_densemat_t *x, ghost_densemat_t *v, const char * transv,
ghost_densemat_t *w, const char *transw, void *alpha, void *beta, int reduce, int printerror)
{
    if (w->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("w must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.storage != GHOST_DENSEMAT_ROWMAJOR) {
        if (printerror) {
            ERROR_LOG("v must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (x->traits.storage != GHOST_DENSEMAT_COLMAJOR) {
        if (printerror) {
            ERROR_LOG("x must be stored row-major!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.datatype != w->traits.datatype || v->traits.datatype != x->traits.datatype) {
        if (printerror) {
            ERROR_LOG("Different data types!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (x->traits.location != GHOST_LOCATION_HOST || v->traits.location != GHOST_LOCATION_HOST || w->traits.location != GHOST_LOCATION_HOST) {
        if (printerror) {
            ERROR_LOG("TSMTTSM only implemented for host densemats!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (v->traits.flags & GHOST_DENSEMAT_SCATTERED || w->traits.flags & GHOST_DENSEMAT_SCATTERED || x->traits.flags & GHOST_DENSEMAT_SCATTERED) {
        if (printerror) {
            ERROR_LOG("Scattered densemats not supported!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (reduce != GHOST_GEMM_ALL_REDUCE) {
        if (printerror) {
            ERROR_LOG("Only Allreduce supported currently!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (!strncasecmp(transv,"N",1)) {
        if (printerror) {
            ERROR_LOG("v must be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }
    if (strncasecmp(transw,"N",1)) {
        if (printerror) {
            ERROR_LOG("w must not be transposed!");
        }
        return GHOST_ERR_INVALID_ARG;
    }

    UNUSED(alpha);
    UNUSED(beta);

    return GHOST_SUCCESS;
}

ghost_error_t ghost_tsmttsm_kahan(ghost_densemat_t *x, ghost_densemat_t *v, ghost_densemat_t *w, void *alpha, void *beta,int reduce,int conjv)
{
    GHOST_FUNC_ENTER(GHOST_FUNCTYPE_MATH);
    ghost_error_t ret;

    if ((ret = ghost_tsmttsm_kahan_valid(x,v,"T",w,"N",alpha,beta,reduce,1)) != GHOST_SUCCESS) {
        INFO_LOG("TSMTTSM-Kahan cannot be applied. Checking whether (non-Kahan) GEMM is fine!");
        if ((ret = ghost_gemm_valid(x,v,"T",w,"N",alpha,beta,reduce,GHOST_GEMM_DEFAULT,1)) != GHOST_SUCCESS) {
            ERROR_LOG("GEMM cannot be applied!");
            return ret;
        } else {
            return ghost_gemm(x,v,"T",w,"N",alpha,beta,reduce,GHOST_GEMM_NOT_SPECIAL);
        }
    }

    if (ghost_tsmttsm_kahan_kernels.empty()) {
#include "tsmttsm_kahan.def"
    }

    ghost_tsmttsm_kahan_parameters_t p;
    ghost_tsmttsm_kahan_kernel_t kernel = NULL;

    p.impl = GHOST_IMPLEMENTATION_PLAIN;

    p.dt = x->traits.datatype;

    p.vcols = v->traits.ncols;
    p.wcols = w->traits.ncols;
    kernel = ghost_tsmttsm_kahan_kernels[p];

    if (!kernel) {
        PERFWARNING_LOG("Try kernel with arbitrary block sizes");
        p.wcols = -1;
        p.vcols = -1;
        kernel = ghost_tsmttsm_kahan_kernels[p];
    }

    kernel = ghost_tsmttsm_kahan_kernels[p];

    if (!kernel) {
        INFO_LOG("Could not find Kahan-TSMTTSM kernel with %d %d %d. Fallback to GEMM",p.dt,p.wcols,p.vcols);
        return GHOST_ERR_INVALID_ARG;

            //return ghost_gemm(x,v,"T",w,"N",alpha,beta,GHOST_GEMM_ALL_REDUCE,GHOST_GEMM_NOT_SPECIAL);
    }

    ret = kernel(x,v,w,alpha,beta,conjv);

#ifdef GHOST_HAVE_INSTR_TIMING
    ghost_gemm_perf_args_t tsmttsm_perfargs;
    tsmttsm_perfargs.xcols = p.wcols;
    tsmttsm_perfargs.vcols = p.vcols;
    tsmttsm_perfargs.vrows = v->context->gnrows;
    tsmttsm_perfargs.dt = x->traits.datatype;
    ghost_timing_set_perfFunc(__ghost_functag,ghost_gemm_perf_GFs,(void *)&tsmttsm_perfargs,sizeof(tsmttsm_perfargs),"GF/s");
#endif

    GHOST_FUNC_EXIT(GHOST_FUNCTYPE_MATH);

    return ret;
}

<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2002 MandrakeSoft S.A.
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

/////////////////////////////////////////////////////////////////////////
//
// Todo
//  . Currently supported by sdl, wxGTK and x11. Check if other guis need mapping.
//  . Tables look-up should be optimised.
//

#include "bochs.h"

// Table of bochs "BX_KEY_*" symbols
// the table must be in BX_KEY_* order
char *bx_key_symbol[BX_KEY_NBKEYS] = {
  "BX_KEY_CTRL_L",         "BX_KEY_SHIFT_L",        "BX_KEY_F1",
  "BX_KEY_F2",             "BX_KEY_F3",             "BX_KEY_F4",
  "BX_KEY_F5",             "BX_KEY_F6",             "BX_KEY_F7",
  "BX_KEY_F8",             "BX_KEY_F9",             "BX_KEY_F10",
  "BX_KEY_F11",            "BX_KEY_F12",            "BX_KEY_CTRL_R",
  "BX_KEY_SHIFT_R",        "BX_KEY_CAPS_LOCK",      "BX_KEY_NUM_LOCK",
  "BX_KEY_ALT_L",          "BX_KEY_ALT_R",          "BX_KEY_A",
  "BX_KEY_B",              "BX_KEY_C",              "BX_KEY_D",
  "BX_KEY_E",              "BX_KEY_F",              "BX_KEY_G",
  "BX_KEY_H",              "BX_KEY_I",              "BX_KEY_J",
  "BX_KEY_K",              "BX_KEY_L",              "BX_KEY_M",
  "BX_KEY_N",              "BX_KEY_O",              "BX_KEY_P",
  "BX_KEY_Q",              "BX_KEY_R",              "BX_KEY_S",
  "BX_KEY_T",              "BX_KEY_U",              "BX_KEY_V",
  "BX_KEY_W",              "BX_KEY_X",              "BX_KEY_Y",
  "BX_KEY_Z",              "BX_KEY_0",              "BX_KEY_1",
  "BX_KEY_2",              "BX_KEY_3",              "BX_KEY_4",
  "BX_KEY_5",              "BX_KEY_6",              "BX_KEY_7",
  "BX_KEY_8",              "BX_KEY_9",              "BX_KEY_ESC",
  "BX_KEY_SPACE",          "BX_KEY_SINGLE_QUOTE",   "BX_KEY_COMMA",
  "BX_KEY_PERIOD",         "BX_KEY_SLASH",          "BX_KEY_SEMICOLON",
  "BX_KEY_EQUALS",         "BX_KEY_LEFT_BRACKET",   "BX_KEY_BACKSLASH",
  "BX_KEY_RIGHT_BRACKET",  "BX_KEY_MINUS",          "BX_KEY_GRAVE",
  "BX_KEY_BACKSPACE",      "BX_KEY_ENTER",          "BX_KEY_TAB",
  "BX_KEY_LEFT_BACKSLASH", "BX_KEY_PRINT",          "BX_KEY_SCRL_LOCK",
  "BX_KEY_PAUSE",          "BX_KEY_INSERT",         "BX_KEY_DELETE",
  "BX_KEY_HOME",           "BX_KEY_END",            "BX_KEY_PAGE_UP",
  "BX_KEY_PAGE_DOWN",      "BX_KEY_KP_ADD",         "BX_KEY_KP_SUBTRACT",
  "BX_KEY_KP_END",         "BX_KEY_KP_DOWN",        "BX_KEY_KP_PAGE_DOWN",
  "BX_KEY_KP_LEFT",        "BX_KEY_KP_RIGHT",       "BX_KEY_KP_HOME",
  "BX_KEY_KP_UP",          "BX_KEY_KP_PAGE_UP",     "BX_KEY_KP_INSERT",
  "BX_KEY_KP_DELETE",      "BX_KEY_KP_5",           "BX_KEY_UP",
  "BX_KEY_DOWN",           "BX_KEY_LEFT",           "BX_KEY_RIGHT",
  "BX_KEY_KP_ENTER",       "BX_KEY_KP_MULTIPLY",    "BX_KEY_KP_DIVIDE",
  "BX_KEY_WIN_L",          "BX_KEY_WIN_R",          "BX_KEY_MENU",
  "BX_KEY_ALT_SYSREQ",     "BX_KEY_CTRL_BREAK",     "BX_KEY_INT_BACK",
  "BX_KEY_INT_FORWARD",    "BX_KEY_INT_STOP",       "BX_KEY_INT_MAIL",
  "BX_KEY_INT_SEARCH",     "BX_KEY_INT_FAV",        "BX_KEY_INT_HOME",
  "BX_KEY_POWER_MYCOMP",   "BX_KEY_POWER_CALC",     "BX_KEY_POWER_SLEEP",
  "BX_KEY_POWER_POWER",    "BX_KEY_POWER_WAKE",
  };

bx_keymap_c bx_keymap;

#define LOG_THIS bx_keymap.

bx_keymap_c::bx_keymap_c(void)
{
    put("KMAP");

    keymapCount = 0;
    keymapTable = (BXKeyEntry *)NULL;

}

bx_keymap_c::~bx_keymap_c(void)
{
    if(keymapTable != NULL) {
      free(keymapTable);
      keymapTable = (BXKeyEntry *)NULL;
      }
    keymapCount = 0;
}

    void
bx_keymap_c::loadKeymap(Bit32u stringToSymbol(const char*))
{
  if(bx_options.keyboard.OuseMapping->get()) {
    loadKeymap(stringToSymbol,bx_options.keyboard.Okeymap->getptr());
    }
}

bx_bool
bx_keymap_c::isKeymapLoaded ()
{
  return (keymapCount > 0);
}

///////////////////
// I'll add these to the keymap object in a minute.
static unsigned char *lineptr = NULL;
static int lineCount;

static void
init_parse ()
{
  lineCount = 0;
}

static void
init_parse_line (char *line_to_parse)
{
  // chop off newline
  lineptr = (unsigned char *)line_to_parse;
  char *nl;
  if( (nl = strchr(line_to_parse,'\n')) != NULL) {
    *nl = 0;
  }
}

static Bit32s
get_next_word (char *output)
{
  char *copyp = output;
  // find first nonspace
  while (*lineptr && isspace (*lineptr))
    lineptr++;
  if (!*lineptr)
    return -1;  // nothing but spaces until end of line
  if (*lineptr == '#')
    return -1;  // nothing but a comment
  // copy nonspaces into the output
  while (*lineptr && !isspace (*lineptr))
    *copyp++ = *lineptr++;
  *copyp=0;  // null terminate the copy
  // there must be at least one nonspace, since that's why we stopped the
  // first loop!
  BX_ASSERT (copyp != output);
  return 0;
}

static Bit32s
get_next_keymap_line (FILE *fp, char *bxsym, char *modsym, Bit32s *ascii, char *hostsym)
{
  char line[256];
  char buf[256];
  line[0] = 0;
  while (1) {
    lineCount++;
    if (!fgets(line, sizeof(line)-1, fp)) return -1;  // EOF
    init_parse_line (line);
    if (get_next_word (bxsym) >= 0) {
      modsym[0] = 0;
      char *p;
      if ((p = strchr (bxsym, '+')) != NULL) {
	*p = 0;  // truncate bxsym.
	p++;  // move one char beyond the +
	strcpy (modsym, p);  // copy the rest to modsym
      }
      if (get_next_word (buf) < 0) {
	BX_PANIC (("keymap line %d: expected 3 columns", lineCount));
	return -1;
      }
      if (buf[0] == '\'' && buf[2] == '\'' && buf[3]==0) {
	*ascii = (Bit8u) buf[1];
      } else if (!strcmp(buf, "space")) {
	*ascii = ' ';
      } else if (!strcmp(buf, "return")) {
	*ascii = '\n';
      } else if (!strcmp(buf, "tab")) {
	*ascii = '\t';
      } else if (!strcmp(buf, "backslash")) {
	*ascii = '\\';
      } else if (!strcmp(buf, "apostrophe")) {
	*ascii = '\'';
      } else if (!strcmp(buf, "none")) {
	*ascii = -1;
      } else {
	BX_PANIC (("keymap line %d: ascii equivalent is \"%s\" but it must be char constant like 'x', or one of space,tab,return,none", lineCount, buf));
      }
      if (get_next_word (hostsym) < 0) {
        BX_PANIC (("keymap line %d: expected 3 columns", lineCount));
	return -1;
      }
      return 0;
    }
    // no words on this line, keep reading.
  }
}

    void
bx_keymap_c::loadKeymap(Bit32u stringToSymbol(const char*), const char* filename)
{
    FILE   *keymapFile;
    char baseSym[256], modSym[256], hostSym[256];
    Bit32s ascii;
    Bit32u baseKey, modKey, hostKey;
    struct stat status;

    if (stat(filename, &status)) {
      BX_PANIC(("Can not stat keymap file '%s'.",filename));
      }

    if (!(S_ISREG(status.st_mode))) {
      BX_PANIC(("Keymap file '%s' is not a file",filename));
      }

    if((keymapFile = fopen(filename,"r"))==NULL) {
      BX_PANIC(("Can not open keymap file '%s'.",filename));
      }

    BX_INFO(("Loading keymap from '%s'",filename));
    init_parse ();

    // Read keymap file one line at a time
    while(1) {
      if (get_next_keymap_line (keymapFile,
            baseSym, modSym, &ascii, hostSym) < 0) { break; }

      // convert X_KEY_* symbols to values
      baseKey = convertStringToBXKey(baseSym);
      modKey = convertStringToBXKey(modSym);
      hostKey = 0;
      if (stringToSymbol != NULL)
        hostKey = stringToSymbol(hostSym);

      BX_DEBUG (("baseKey='%s' (%d), modSym='%s' (%d), ascii=%d, guisym='%s' (%d)", baseSym, baseKey, modSym, modKey, ascii, hostSym, hostKey));

      // Check if data is valid
      if( baseKey==BX_KEYMAP_UNKNOWN ) {
        BX_PANIC (("line %d: unknown BX_KEY constant '%s'",lineCount,baseSym));
        continue;
        }

      if( hostKey==BX_KEYMAP_UNKNOWN ) {
        BX_PANIC (("line %d: unknown host key name '%s'",lineCount,hostSym));
        continue;
        }

      keymapTable=(BXKeyEntry*)realloc(keymapTable,(keymapCount+1) * sizeof(BXKeyEntry));

      if(keymapTable==NULL)
        BX_PANIC(("Can not allocate memory for keymap table."));

      keymapTable[keymapCount].baseKey=baseKey;
      keymapTable[keymapCount].modKey=modKey;
      keymapTable[keymapCount].ascii=ascii;
      keymapTable[keymapCount].hostKey=hostKey;

      keymapCount++;
      }

    BX_INFO(("Loaded %d symbols",keymapCount));

    fclose(keymapFile);
}

    Bit32u
bx_keymap_c::convertStringToBXKey(const char* string)
{
    Bit16u i;

    // We look through the bx_key_symbol table to find the searched string
    for (i=0; i<BX_KEY_NBKEYS; i++) {
      if (strcmp(string,bx_key_symbol[i])==0) {
        return i;
        }
      }

    // Key is not known
    return BX_KEYMAP_UNKNOWN;
}

    BXKeyEntry *
bx_keymap_c::findHostKey(Bit32u key)
{
    Bit16u i;

    // We look through the keymap table to find the searched key
    for (i=0; i<keymapCount; i++) {
      if (keymapTable[i].hostKey == key) {
	BX_DEBUG (("key 0x%02x matches hostKey for entry #%d", key, i));
        return &keymapTable[i];
        }
      }
    BX_DEBUG (("key %02x matches no entries", key));

    // Return default
    return NULL;
}

    BXKeyEntry *
bx_keymap_c::findAsciiChar(Bit8u ch)
{
    Bit16u i;
    BX_DEBUG (("findAsciiChar (0x%02x)", ch));

    // We look through the keymap table to find the searched key
    for (i=0; i<keymapCount; i++) {
      if (keymapTable[i].ascii == ch) {
	BX_DEBUG (("key %02x matches ascii for entry #%d", ch, i));
        return &keymapTable[i];
        }
      }
    BX_DEBUG (("key 0x%02x matches no entries", ch));

    // Return default
    return NULL;
}

    char *
bx_keymap_c::getBXKeyName(Bit32u key)
{
    return bx_key_symbol[key & 0x7fffffff];
}
<commit_msg>- panic message for unknown key symbols improved<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2002 MandrakeSoft S.A.
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

/////////////////////////////////////////////////////////////////////////
//
// Todo
//  . Currently supported by sdl, wxGTK and x11. Check if other guis need mapping.
//  . Tables look-up should be optimised.
//

#include "bochs.h"

// Table of bochs "BX_KEY_*" symbols
// the table must be in BX_KEY_* order
char *bx_key_symbol[BX_KEY_NBKEYS] = {
  "BX_KEY_CTRL_L",         "BX_KEY_SHIFT_L",        "BX_KEY_F1",
  "BX_KEY_F2",             "BX_KEY_F3",             "BX_KEY_F4",
  "BX_KEY_F5",             "BX_KEY_F6",             "BX_KEY_F7",
  "BX_KEY_F8",             "BX_KEY_F9",             "BX_KEY_F10",
  "BX_KEY_F11",            "BX_KEY_F12",            "BX_KEY_CTRL_R",
  "BX_KEY_SHIFT_R",        "BX_KEY_CAPS_LOCK",      "BX_KEY_NUM_LOCK",
  "BX_KEY_ALT_L",          "BX_KEY_ALT_R",          "BX_KEY_A",
  "BX_KEY_B",              "BX_KEY_C",              "BX_KEY_D",
  "BX_KEY_E",              "BX_KEY_F",              "BX_KEY_G",
  "BX_KEY_H",              "BX_KEY_I",              "BX_KEY_J",
  "BX_KEY_K",              "BX_KEY_L",              "BX_KEY_M",
  "BX_KEY_N",              "BX_KEY_O",              "BX_KEY_P",
  "BX_KEY_Q",              "BX_KEY_R",              "BX_KEY_S",
  "BX_KEY_T",              "BX_KEY_U",              "BX_KEY_V",
  "BX_KEY_W",              "BX_KEY_X",              "BX_KEY_Y",
  "BX_KEY_Z",              "BX_KEY_0",              "BX_KEY_1",
  "BX_KEY_2",              "BX_KEY_3",              "BX_KEY_4",
  "BX_KEY_5",              "BX_KEY_6",              "BX_KEY_7",
  "BX_KEY_8",              "BX_KEY_9",              "BX_KEY_ESC",
  "BX_KEY_SPACE",          "BX_KEY_SINGLE_QUOTE",   "BX_KEY_COMMA",
  "BX_KEY_PERIOD",         "BX_KEY_SLASH",          "BX_KEY_SEMICOLON",
  "BX_KEY_EQUALS",         "BX_KEY_LEFT_BRACKET",   "BX_KEY_BACKSLASH",
  "BX_KEY_RIGHT_BRACKET",  "BX_KEY_MINUS",          "BX_KEY_GRAVE",
  "BX_KEY_BACKSPACE",      "BX_KEY_ENTER",          "BX_KEY_TAB",
  "BX_KEY_LEFT_BACKSLASH", "BX_KEY_PRINT",          "BX_KEY_SCRL_LOCK",
  "BX_KEY_PAUSE",          "BX_KEY_INSERT",         "BX_KEY_DELETE",
  "BX_KEY_HOME",           "BX_KEY_END",            "BX_KEY_PAGE_UP",
  "BX_KEY_PAGE_DOWN",      "BX_KEY_KP_ADD",         "BX_KEY_KP_SUBTRACT",
  "BX_KEY_KP_END",         "BX_KEY_KP_DOWN",        "BX_KEY_KP_PAGE_DOWN",
  "BX_KEY_KP_LEFT",        "BX_KEY_KP_RIGHT",       "BX_KEY_KP_HOME",
  "BX_KEY_KP_UP",          "BX_KEY_KP_PAGE_UP",     "BX_KEY_KP_INSERT",
  "BX_KEY_KP_DELETE",      "BX_KEY_KP_5",           "BX_KEY_UP",
  "BX_KEY_DOWN",           "BX_KEY_LEFT",           "BX_KEY_RIGHT",
  "BX_KEY_KP_ENTER",       "BX_KEY_KP_MULTIPLY",    "BX_KEY_KP_DIVIDE",
  "BX_KEY_WIN_L",          "BX_KEY_WIN_R",          "BX_KEY_MENU",
  "BX_KEY_ALT_SYSREQ",     "BX_KEY_CTRL_BREAK",     "BX_KEY_INT_BACK",
  "BX_KEY_INT_FORWARD",    "BX_KEY_INT_STOP",       "BX_KEY_INT_MAIL",
  "BX_KEY_INT_SEARCH",     "BX_KEY_INT_FAV",        "BX_KEY_INT_HOME",
  "BX_KEY_POWER_MYCOMP",   "BX_KEY_POWER_CALC",     "BX_KEY_POWER_SLEEP",
  "BX_KEY_POWER_POWER",    "BX_KEY_POWER_WAKE",
  };

bx_keymap_c bx_keymap;

#define LOG_THIS bx_keymap.

bx_keymap_c::bx_keymap_c(void)
{
    put("KMAP");

    keymapCount = 0;
    keymapTable = (BXKeyEntry *)NULL;

}

bx_keymap_c::~bx_keymap_c(void)
{
    if(keymapTable != NULL) {
      free(keymapTable);
      keymapTable = (BXKeyEntry *)NULL;
      }
    keymapCount = 0;
}

    void
bx_keymap_c::loadKeymap(Bit32u stringToSymbol(const char*))
{
  if(bx_options.keyboard.OuseMapping->get()) {
    loadKeymap(stringToSymbol,bx_options.keyboard.Okeymap->getptr());
    }
}

bx_bool
bx_keymap_c::isKeymapLoaded ()
{
  return (keymapCount > 0);
}

///////////////////
// I'll add these to the keymap object in a minute.
static unsigned char *lineptr = NULL;
static int lineCount;

static void
init_parse ()
{
  lineCount = 0;
}

static void
init_parse_line (char *line_to_parse)
{
  // chop off newline
  lineptr = (unsigned char *)line_to_parse;
  char *nl;
  if( (nl = strchr(line_to_parse,'\n')) != NULL) {
    *nl = 0;
  }
}

static Bit32s
get_next_word (char *output)
{
  char *copyp = output;
  // find first nonspace
  while (*lineptr && isspace (*lineptr))
    lineptr++;
  if (!*lineptr)
    return -1;  // nothing but spaces until end of line
  if (*lineptr == '#')
    return -1;  // nothing but a comment
  // copy nonspaces into the output
  while (*lineptr && !isspace (*lineptr))
    *copyp++ = *lineptr++;
  *copyp=0;  // null terminate the copy
  // there must be at least one nonspace, since that's why we stopped the
  // first loop!
  BX_ASSERT (copyp != output);
  return 0;
}

static Bit32s
get_next_keymap_line (FILE *fp, char *bxsym, char *modsym, Bit32s *ascii, char *hostsym)
{
  char line[256];
  char buf[256];
  line[0] = 0;
  while (1) {
    lineCount++;
    if (!fgets(line, sizeof(line)-1, fp)) return -1;  // EOF
    init_parse_line (line);
    if (get_next_word (bxsym) >= 0) {
      modsym[0] = 0;
      char *p;
      if ((p = strchr (bxsym, '+')) != NULL) {
	*p = 0;  // truncate bxsym.
	p++;  // move one char beyond the +
	strcpy (modsym, p);  // copy the rest to modsym
      }
      if (get_next_word (buf) < 0) {
	BX_PANIC (("keymap line %d: expected 3 columns", lineCount));
	return -1;
      }
      if (buf[0] == '\'' && buf[2] == '\'' && buf[3]==0) {
	*ascii = (Bit8u) buf[1];
      } else if (!strcmp(buf, "space")) {
	*ascii = ' ';
      } else if (!strcmp(buf, "return")) {
	*ascii = '\n';
      } else if (!strcmp(buf, "tab")) {
	*ascii = '\t';
      } else if (!strcmp(buf, "backslash")) {
	*ascii = '\\';
      } else if (!strcmp(buf, "apostrophe")) {
	*ascii = '\'';
      } else if (!strcmp(buf, "none")) {
	*ascii = -1;
      } else {
	BX_PANIC (("keymap line %d: ascii equivalent is \"%s\" but it must be char constant like 'x', or one of space,tab,return,none", lineCount, buf));
      }
      if (get_next_word (hostsym) < 0) {
        BX_PANIC (("keymap line %d: expected 3 columns", lineCount));
	return -1;
      }
      return 0;
    }
    // no words on this line, keep reading.
  }
}

    void
bx_keymap_c::loadKeymap(Bit32u stringToSymbol(const char*), const char* filename)
{
    FILE   *keymapFile;
    char baseSym[256], modSym[256], hostSym[256];
    Bit32s ascii;
    Bit32u baseKey, modKey, hostKey;
    struct stat status;

    if (stat(filename, &status)) {
      BX_PANIC(("Can not stat keymap file '%s'.",filename));
      }

    if (!(S_ISREG(status.st_mode))) {
      BX_PANIC(("Keymap file '%s' is not a file",filename));
      }

    if((keymapFile = fopen(filename,"r"))==NULL) {
      BX_PANIC(("Can not open keymap file '%s'.",filename));
      }

    BX_INFO(("Loading keymap from '%s'",filename));
    init_parse ();

    // Read keymap file one line at a time
    while(1) {
      if (get_next_keymap_line (keymapFile,
            baseSym, modSym, &ascii, hostSym) < 0) { break; }

      // convert X_KEY_* symbols to values
      baseKey = convertStringToBXKey(baseSym);
      modKey = convertStringToBXKey(modSym);
      hostKey = 0;
      if (stringToSymbol != NULL)
        hostKey = stringToSymbol(hostSym);

      BX_DEBUG (("baseKey='%s' (%d), modSym='%s' (%d), ascii=%d, guisym='%s' (%d)", baseSym, baseKey, modSym, modKey, ascii, hostSym, hostKey));

      // Check if data is valid
      if( baseKey==BX_KEYMAP_UNKNOWN ) {
        BX_PANIC (("line %d: unknown BX_KEY constant '%s'",lineCount,baseSym));
        continue;
        }

      if( hostKey==BX_KEYMAP_UNKNOWN ) {
        BX_PANIC (("line %d: unknown host key name '%s' (wrong keymap ?)",lineCount,hostSym));
        continue;
        }

      keymapTable=(BXKeyEntry*)realloc(keymapTable,(keymapCount+1) * sizeof(BXKeyEntry));

      if(keymapTable==NULL)
        BX_PANIC(("Can not allocate memory for keymap table."));

      keymapTable[keymapCount].baseKey=baseKey;
      keymapTable[keymapCount].modKey=modKey;
      keymapTable[keymapCount].ascii=ascii;
      keymapTable[keymapCount].hostKey=hostKey;

      keymapCount++;
      }

    BX_INFO(("Loaded %d symbols",keymapCount));

    fclose(keymapFile);
}

    Bit32u
bx_keymap_c::convertStringToBXKey(const char* string)
{
    Bit16u i;

    // We look through the bx_key_symbol table to find the searched string
    for (i=0; i<BX_KEY_NBKEYS; i++) {
      if (strcmp(string,bx_key_symbol[i])==0) {
        return i;
        }
      }

    // Key is not known
    return BX_KEYMAP_UNKNOWN;
}

    BXKeyEntry *
bx_keymap_c::findHostKey(Bit32u key)
{
    Bit16u i;

    // We look through the keymap table to find the searched key
    for (i=0; i<keymapCount; i++) {
      if (keymapTable[i].hostKey == key) {
	BX_DEBUG (("key 0x%02x matches hostKey for entry #%d", key, i));
        return &keymapTable[i];
        }
      }
    BX_DEBUG (("key %02x matches no entries", key));

    // Return default
    return NULL;
}

    BXKeyEntry *
bx_keymap_c::findAsciiChar(Bit8u ch)
{
    Bit16u i;
    BX_DEBUG (("findAsciiChar (0x%02x)", ch));

    // We look through the keymap table to find the searched key
    for (i=0; i<keymapCount; i++) {
      if (keymapTable[i].ascii == ch) {
	BX_DEBUG (("key %02x matches ascii for entry #%d", ch, i));
        return &keymapTable[i];
        }
      }
    BX_DEBUG (("key 0x%02x matches no entries", ch));

    // Return default
    return NULL;
}

    char *
bx_keymap_c::getBXKeyName(Bit32u key)
{
    return bx_key_symbol[key & 0x7fffffff];
}
<|endoftext|>


<commit_before>#include <enumerate.hpp>

#include "test_helpers.hpp"

#include <vector>
#include <string>
#include <iterator>
#include <utility>
#include <sstream>

namespace Catch {
template <typename A, typename B>
std::string toString( const std::pair<A, B>& p) {
    std::ostringstream oss;
    oss << '{' << p.first << ", " << p.second << '}';
    return oss.str();
}
}

#include "catch.hpp"

using Vec = std::vector<std::pair<std::size_t, char>>;
using iter::enumerate;

using itertest::BasicIterable;
using itertest::SolidInt;

TEST_CASE("Basic Function", "[enumerate]") {
    std::string str = "abc";
    auto e = enumerate(str);
    Vec v(std::begin(e), std::end(e));
    Vec vc{{0, 'a'}, {1, 'b'}, {2, 'c'}};

    REQUIRE( v == vc );
}

TEST_CASE("Empty", "[enumerate]") {
    std::string emp{};
    auto e = enumerate(emp);
    Vec v(std::begin(e), std::end(e));

    REQUIRE( v.empty() );
}

TEST_CASE("Modifications through enumerate affect container", "[enumerate]") {
    std::vector<int> v{1, 2, 3, 4};
    std::vector<int> vc(v.size(), -1);
    for (auto&& p : enumerate(v)){
        p.second = -1;
    }

    REQUIRE( v == vc );
}

TEST_CASE("Static array works", "[enumerate]") {
    char arr[] = {'w', 'x', 'y'};

    SECTION("Conversion to vector") {
        auto e = enumerate(arr);
        Vec v(std::begin(e), std::end(e));
        Vec vc{{0, 'w'}, {1, 'x'}, {2, 'y'}};
        REQUIRE( v == vc );
    }

    SECTION("Modification through enumerate") {
        for (auto&& p : enumerate(arr)) {
            p.second = 'z';
        }
        std::vector<char> v(std::begin(arr), std::end(arr));
        decltype(v) vc(v.size(), 'z');
        REQUIRE( v == vc );
    }
}

TEST_CASE("initializer_list works", "[enumerate]") {
    auto e = enumerate({'a', 'b', 'c'});
    Vec v(std::begin(e), std::end(e));
    Vec vc{{0, 'a'}, {1, 'b'}, {2, 'c'}};
    REQUIRE( v == vc );
}

TEST_CASE("binds reference when it should", "[enumerate]") {
    BasicIterable<char> bi{'x', 'y', 'z'};
    auto e = enumerate(bi);
    (void)e;
    REQUIRE_FALSE( bi.was_moved_from() );
}

TEST_CASE("moves rvalues into enumerable object", "[enumerate]") {
    BasicIterable<char> bi{'x', 'y', 'z'};
    auto e = enumerate(std::move(bi));
    REQUIRE( bi.was_moved_from());
    (void)e;
}

TEST_CASE("Doesn't move or copy elements of iterable", "[enumerate]") {
    constexpr SolidInt arr[] = {6, 7, 8};
    for (auto&& i : enumerate(arr)) {
        (void)i;
    }
}
<commit_msg>adds enumerate test with const sequence<commit_after>#include <enumerate.hpp>

#include "test_helpers.hpp"

#include <vector>
#include <string>
#include <iterator>
#include <utility>
#include <sstream>

namespace Catch {
template <typename A, typename B>
std::string toString( const std::pair<A, B>& p) {
    std::ostringstream oss;
    oss << '{' << p.first << ", " << p.second << '}';
    return oss.str();
}
}

#include "catch.hpp"

using Vec = std::vector<std::pair<std::size_t, char>>;
using iter::enumerate;

using itertest::BasicIterable;
using itertest::SolidInt;

TEST_CASE("Basic Function", "[enumerate]") {
    std::string str = "abc";
    auto e = enumerate(str);
    Vec v(std::begin(e), std::end(e));
    Vec vc{{0, 'a'}, {1, 'b'}, {2, 'c'}};

    REQUIRE( v == vc );
}

TEST_CASE("Empty", "[enumerate]") {
    std::string emp{};
    auto e = enumerate(emp);
    Vec v(std::begin(e), std::end(e));

    REQUIRE( v.empty() );
}

TEST_CASE("Modifications through enumerate affect container", "[enumerate]") {
    std::vector<int> v{1, 2, 3, 4};
    std::vector<int> vc(v.size(), -1);
    for (auto&& p : enumerate(v)){
        p.second = -1;
    }

    REQUIRE( v == vc );
}

TEST_CASE("Static array works", "[enumerate]") {
    char arr[] = {'w', 'x', 'y'};

    SECTION("Conversion to vector") {
        auto e = enumerate(arr);
        Vec v(std::begin(e), std::end(e));
        Vec vc{{0, 'w'}, {1, 'x'}, {2, 'y'}};
        REQUIRE( v == vc );
    }

    SECTION("Modification through enumerate") {
        for (auto&& p : enumerate(arr)) {
            p.second = 'z';
        }
        std::vector<char> v(std::begin(arr), std::end(arr));
        decltype(v) vc(v.size(), 'z');
        REQUIRE( v == vc );
    }
}

TEST_CASE("initializer_list works", "[enumerate]") {
    auto e = enumerate({'a', 'b', 'c'});
    Vec v(std::begin(e), std::end(e));
    Vec vc{{0, 'a'}, {1, 'b'}, {2, 'c'}};
    REQUIRE( v == vc );
}

TEST_CASE("binds reference when it should", "[enumerate]") {
    BasicIterable<char> bi{'x', 'y', 'z'};
    auto e = enumerate(bi);
    (void)e;
    REQUIRE_FALSE( bi.was_moved_from() );
}

TEST_CASE("moves rvalues into enumerable object", "[enumerate]") {
    BasicIterable<char> bi{'x', 'y', 'z'};
    auto e = enumerate(std::move(bi));
    REQUIRE( bi.was_moved_from());
    (void)e;
}

TEST_CASE("Works with const iterable", "[enumerate]") {
    const std::string s{"ace"};
    auto e = enumerate(s);
    Vec v(std::begin(e), std::end(e));
    Vec vc{{0, 'a'}, {1, 'c'}, {2, 'e'}};
    REQUIRE( v == vc );
}

TEST_CASE("Doesn't move or copy elements of iterable", "[enumerate]") {
    constexpr SolidInt arr[] = {6, 7, 8};
    for (auto&& i : enumerate(arr)) {
        (void)i;
    }
}
<|endoftext|>


<commit_before>/*
 * This file is part of the LibreOffice project.
 *
 * Based on LLVM/Clang.
 *
 * This file is distributed under the University of Illinois Open Source
 * License. See LICENSE.TXT for details.
 *
 */

#include "pluginhandler.hxx"

#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendPluginRegistry.h>
#include <clang/Lex/PPCallbacks.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

/*
This source file manages all plugin actions. It is not necessary to modify this
file when adding new actions.
*/
namespace loplugin
{

struct PluginData
    {
    Plugin* (*create)( CompilerInstance&, Rewriter& );
    Plugin* object;
    const char* optionName;
    bool isRewriter;
    };

const int MAX_PLUGINS = 100;
static PluginData plugins[ MAX_PLUGINS ];
static int pluginCount = 0;
static bool pluginObjectsCreated = false;

PluginHandler::PluginHandler( CompilerInstance& compiler, const vector< string >& args )
    : compiler( compiler )
    , rewriter( compiler.getSourceManager(), compiler.getLangOpts())
    , scope( "mainfile" )
    {
    bool wasPlugin = false;
    for( vector< string >::const_iterator it = args.begin();
         it != args.end();
         ++it )
        {
        if( it->size() >= 2 && (*it)[ 0 ] == '-' && (*it)[ 1 ] == '-' )
            handleOption( it->substr( 2 ));
        else
            {
            createPlugin( *it );
            wasPlugin = true;
            }
        }
    if( !wasPlugin )
        createPlugin( "" ); // = all non-rewriters
    pluginObjectsCreated = true;
    }

PluginHandler::~PluginHandler()
    {
    for( int i = 0;
         i < pluginCount;
         ++i )
        if( plugins[ i ].object != NULL )
            {
            // PPCallbacks is owned by preprocessor object, don't delete those
            if( dynamic_cast< PPCallbacks* >( plugins[ i ].object ) == NULL )
                delete plugins[ i ].object;
            }
    }

void PluginHandler::handleOption( const string& option )
    {
    if( option.substr( 0, 6 ) == "scope=" )
        {
        scope = option.substr( 6 );
        if( scope == "mainfile" || scope == "all" )
            ; // ok
        else
            {
            struct stat st;
            if( stat(( SRCDIR "/" + scope ).c_str(), &st ) != 0 || !S_ISDIR( st.st_mode ))
                report( DiagnosticsEngine::Fatal, "unknown scope %0 (no such module directory)" ) << scope;
            }
        }
    else
        report( DiagnosticsEngine::Fatal, "unknown option %0" ) << option;
    }

void PluginHandler::createPlugin( const string& name )
    {
    for( int i = 0;
         i < pluginCount;
         ++i )
        {
        if( name.empty())  // no plugin given -> create non-writer plugins
            {
            if( !plugins[ i ].isRewriter )
                plugins[ i ].object = plugins[ i ].create( compiler, rewriter );
            }
        else if( plugins[ i ].optionName == name )
            {
            plugins[ i ].object = plugins[ i ].create( compiler, rewriter );
            return;
            }
        }
    if( !name.empty())
        report( DiagnosticsEngine::Fatal, "unknown plugin tool %0" ) << name;
    }

void PluginHandler::registerPlugin( Plugin* (*create)( CompilerInstance&, Rewriter& ), const char* optionName, bool isRewriter )
    {
    assert( !pluginObjectsCreated );
    assert( pluginCount < MAX_PLUGINS );
    plugins[ pluginCount ].create = create;
    plugins[ pluginCount ].object = NULL;
    plugins[ pluginCount ].optionName = optionName;
    plugins[ pluginCount ].isRewriter = isRewriter;
    ++pluginCount;
    }

DiagnosticBuilder PluginHandler::report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc )
    {
    return Plugin::report( level, message, compiler, loc );
    }

void PluginHandler::HandleTranslationUnit( ASTContext& context )
    {
    if( context.getDiagnostics().hasErrorOccurred())
        return;
    for( int i = 0;
         i < pluginCount;
         ++i )
        {
        if( plugins[ i ].object != NULL )
            plugins[ i ].object->run();
        }
    for( Rewriter::buffer_iterator it = rewriter.buffer_begin();
         it != rewriter.buffer_end();
         ++it )
        {
        const FileEntry* e = context.getSourceManager().getFileEntryForID( it->first );
        /* Check where the file actually is, and warn about cases where modification
           most probably doesn't matter (generated files in workdir).
           The order here is important, as OUTDIR and WORKDIR are often in SRCDIR/BUILDDIR,
           and BUILDDIR is sometimes in SRCDIR. */
        string modifyFile;
        const char* pathWarning = NULL;
        bool skip = false;
        if( strncmp( e->getName(), OUTDIR "/", strlen( OUTDIR "/" )) == 0 )
            {
            /* Try to find a matching file for a file in solver/ (include files
               are usually included from there rather than from the source dir) if possible. */
            if( strncmp( e->getName(), OUTDIR "/inc/", strlen( OUTDIR ) + strlen( "/inc/" )) == 0 )
                {
                string filename( e->getName());
                int modulePos = strlen( OUTDIR ) + strlen( "/inc/" );
                size_t moduleEnd = filename.find( '/', modulePos );
                if( moduleEnd != string::npos )
                    {
                    modifyFile = SRCDIR "/" + filename.substr( modulePos, moduleEnd - modulePos )
                        + "/inc/" + filename.substr( modulePos );
                    }
                }
            if( modifyFile.empty())
                pathWarning = "modified source in solver/ : %0";
            }
        else if( strncmp( e->getName(), WORKDIR "/", strlen( WORKDIR "/" )) == 0 )
            pathWarning = "modified source in workdir/ : %0";
        else if( strcmp( SRCDIR, BUILDDIR ) != 0 && strncmp( e->getName(), BUILDDIR "/", strlen( BUILDDIR "/" )) == 0 )
            pathWarning = "modified source in build dir : %0";
        else if( strncmp( e->getName(), SRCDIR "/", strlen( SRCDIR "/" )) == 0 )
            ; // ok
        else
            {
            pathWarning = "modified source in unknown location, not modifying : %0";
            skip = true;
            }
        if( modifyFile.empty())
            modifyFile = e->getName();
        // Check whether the modified file is in the wanted scope (done after path checking above), so
        // that files mapped from OUTDIR to SRCDIR are included.
        if( scope == "mainfile" )
            {
            if( it->first != context.getSourceManager().getMainFileID())
                continue;
            }
        else if( scope == "all" )
            ; // ok
        else // scope is module
            {
            if( strncmp( modifyFile.c_str(), ( SRCDIR "/" + scope + "/" ).c_str(), ( SRCDIR "/" + scope + "/" ).size()) != 0 )
                continue;
            }
        // Warn only now, so that files not in scope do not cause warnings.
        if( pathWarning != NULL )
            report( DiagnosticsEngine::Warning, pathWarning ) << e->getName();
        if( skip )
            continue;
        char* filename = new char[ modifyFile.length() + 100 ];
        sprintf( filename, "%s.new.%d", modifyFile.c_str(), getpid());
        string error;
        bool ok = false;
        raw_fd_ostream ostream( filename, error );
        if( error.empty())
            {
            it->second.write( ostream );
            ostream.close();
            if( !ostream.has_error() && rename( filename, modifyFile.c_str()) == 0 )
                ok = true;
            }
        ostream.clear_error();
        unlink( filename );
        if( !ok )
            report( DiagnosticsEngine::Error, "cannot write modified source to %0 (%1)" ) << modifyFile << error;
        delete[] filename;
        }
    }

ASTConsumer* LibreOfficeAction::CreateASTConsumer( CompilerInstance& Compiler, StringRef )
    {
    return new PluginHandler( Compiler, _args );
    }

bool LibreOfficeAction::ParseArgs( const CompilerInstance&, const vector< string >& args )
    {
    _args = args;
    return true;
    }

static FrontendPluginRegistry::Add< loplugin::LibreOfficeAction > X( "loplugin", "LibreOffice compile check plugin" );

} // namespace
<commit_msg>Adapt UPDATE_FILES=<module> to headers being moved to include/<commit_after>/*
 * This file is part of the LibreOffice project.
 *
 * Based on LLVM/Clang.
 *
 * This file is distributed under the University of Illinois Open Source
 * License. See LICENSE.TXT for details.
 *
 */

#include "pluginhandler.hxx"

#include <clang/Frontend/CompilerInstance.h>
#include <clang/Frontend/FrontendPluginRegistry.h>
#include <clang/Lex/PPCallbacks.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>

/*
This source file manages all plugin actions. It is not necessary to modify this
file when adding new actions.
*/

namespace
{

bool isPrefix( const string& prefix, const string& full)
    {
    return full.compare(0, prefix.size(), prefix) == 0;
    }

}

namespace loplugin
{

struct PluginData
    {
    Plugin* (*create)( CompilerInstance&, Rewriter& );
    Plugin* object;
    const char* optionName;
    bool isRewriter;
    };

const int MAX_PLUGINS = 100;
static PluginData plugins[ MAX_PLUGINS ];
static int pluginCount = 0;
static bool pluginObjectsCreated = false;

PluginHandler::PluginHandler( CompilerInstance& compiler, const vector< string >& args )
    : compiler( compiler )
    , rewriter( compiler.getSourceManager(), compiler.getLangOpts())
    , scope( "mainfile" )
    {
    bool wasPlugin = false;
    for( vector< string >::const_iterator it = args.begin();
         it != args.end();
         ++it )
        {
        if( it->size() >= 2 && (*it)[ 0 ] == '-' && (*it)[ 1 ] == '-' )
            handleOption( it->substr( 2 ));
        else
            {
            createPlugin( *it );
            wasPlugin = true;
            }
        }
    if( !wasPlugin )
        createPlugin( "" ); // = all non-rewriters
    pluginObjectsCreated = true;
    }

PluginHandler::~PluginHandler()
    {
    for( int i = 0;
         i < pluginCount;
         ++i )
        if( plugins[ i ].object != NULL )
            {
            // PPCallbacks is owned by preprocessor object, don't delete those
            if( dynamic_cast< PPCallbacks* >( plugins[ i ].object ) == NULL )
                delete plugins[ i ].object;
            }
    }

void PluginHandler::handleOption( const string& option )
    {
    if( option.substr( 0, 6 ) == "scope=" )
        {
        scope = option.substr( 6 );
        if( scope == "mainfile" || scope == "all" )
            ; // ok
        else
            {
            struct stat st;
            if( stat(( SRCDIR "/" + scope ).c_str(), &st ) != 0 || !S_ISDIR( st.st_mode ))
                report( DiagnosticsEngine::Fatal, "unknown scope %0 (no such module directory)" ) << scope;
            }
        }
    else
        report( DiagnosticsEngine::Fatal, "unknown option %0" ) << option;
    }

void PluginHandler::createPlugin( const string& name )
    {
    for( int i = 0;
         i < pluginCount;
         ++i )
        {
        if( name.empty())  // no plugin given -> create non-writer plugins
            {
            if( !plugins[ i ].isRewriter )
                plugins[ i ].object = plugins[ i ].create( compiler, rewriter );
            }
        else if( plugins[ i ].optionName == name )
            {
            plugins[ i ].object = plugins[ i ].create( compiler, rewriter );
            return;
            }
        }
    if( !name.empty())
        report( DiagnosticsEngine::Fatal, "unknown plugin tool %0" ) << name;
    }

void PluginHandler::registerPlugin( Plugin* (*create)( CompilerInstance&, Rewriter& ), const char* optionName, bool isRewriter )
    {
    assert( !pluginObjectsCreated );
    assert( pluginCount < MAX_PLUGINS );
    plugins[ pluginCount ].create = create;
    plugins[ pluginCount ].object = NULL;
    plugins[ pluginCount ].optionName = optionName;
    plugins[ pluginCount ].isRewriter = isRewriter;
    ++pluginCount;
    }

DiagnosticBuilder PluginHandler::report( DiagnosticsEngine::Level level, StringRef message, SourceLocation loc )
    {
    return Plugin::report( level, message, compiler, loc );
    }

void PluginHandler::HandleTranslationUnit( ASTContext& context )
    {
    if( context.getDiagnostics().hasErrorOccurred())
        return;
    for( int i = 0;
         i < pluginCount;
         ++i )
        {
        if( plugins[ i ].object != NULL )
            plugins[ i ].object->run();
        }
    for( Rewriter::buffer_iterator it = rewriter.buffer_begin();
         it != rewriter.buffer_end();
         ++it )
        {
        const FileEntry* e = context.getSourceManager().getFileEntryForID( it->first );
        /* Check where the file actually is, and warn about cases where modification
           most probably doesn't matter (generated files in workdir).
           The order here is important, as OUTDIR and WORKDIR are often in SRCDIR/BUILDDIR,
           and BUILDDIR is sometimes in SRCDIR. */
        string modifyFile;
        const char* pathWarning = NULL;
        bool skip = false;
        if( strncmp( e->getName(), OUTDIR "/", strlen( OUTDIR "/" )) == 0 )
            {
            /* Try to find a matching file for a file in solver/ (include files
               are usually included from there rather than from the source dir) if possible. */
            if( strncmp( e->getName(), OUTDIR "/inc/", strlen( OUTDIR ) + strlen( "/inc/" )) == 0 )
                {
                string filename( e->getName());
                int modulePos = strlen( OUTDIR ) + strlen( "/inc/" );
                size_t moduleEnd = filename.find( '/', modulePos );
                if( moduleEnd != string::npos )
                    {
                    modifyFile = SRCDIR "/" + filename.substr( modulePos, moduleEnd - modulePos )
                        + "/inc/" + filename.substr( modulePos );
                    }
                }
            if( modifyFile.empty())
                pathWarning = "modified source in solver/ : %0";
            }
        else if( strncmp( e->getName(), WORKDIR "/", strlen( WORKDIR "/" )) == 0 )
            pathWarning = "modified source in workdir/ : %0";
        else if( strcmp( SRCDIR, BUILDDIR ) != 0 && strncmp( e->getName(), BUILDDIR "/", strlen( BUILDDIR "/" )) == 0 )
            pathWarning = "modified source in build dir : %0";
        else if( strncmp( e->getName(), SRCDIR "/", strlen( SRCDIR "/" )) == 0 )
            ; // ok
        else
            {
            pathWarning = "modified source in unknown location, not modifying : %0";
            skip = true;
            }
        if( modifyFile.empty())
            modifyFile = e->getName();
        // Check whether the modified file is in the wanted scope (done after path checking above), so
        // that files mapped from OUTDIR to SRCDIR are included.
        if( scope == "mainfile" )
            {
            if( it->first != context.getSourceManager().getMainFileID())
                continue;
            }
        else if( scope == "all" )
            ; // ok
        else // scope is module
            {
            if( !( isPrefix( SRCDIR "/" + scope + "/", modifyFile ) || isPrefix( SRCDIR "/include/" + scope + "/", modifyFile ) ) )
                continue;
            }
        // Warn only now, so that files not in scope do not cause warnings.
        if( pathWarning != NULL )
            report( DiagnosticsEngine::Warning, pathWarning ) << e->getName();
        if( skip )
            continue;
        char* filename = new char[ modifyFile.length() + 100 ];
        sprintf( filename, "%s.new.%d", modifyFile.c_str(), getpid());
        string error;
        bool ok = false;
        raw_fd_ostream ostream( filename, error );
        if( error.empty())
            {
            it->second.write( ostream );
            ostream.close();
            if( !ostream.has_error() && rename( filename, modifyFile.c_str()) == 0 )
                ok = true;
            }
        ostream.clear_error();
        unlink( filename );
        if( !ok )
            report( DiagnosticsEngine::Error, "cannot write modified source to %0 (%1)" ) << modifyFile << error;
        delete[] filename;
        }
    }

ASTConsumer* LibreOfficeAction::CreateASTConsumer( CompilerInstance& Compiler, StringRef )
    {
    return new PluginHandler( Compiler, _args );
    }

bool LibreOfficeAction::ParseArgs( const CompilerInstance&, const vector< string >& args )
    {
    _args = args;
    return true;
    }

static FrontendPluginRegistry::Add< loplugin::LibreOfficeAction > X( "loplugin", "LibreOffice compile check plugin" );

} // namespace
<|endoftext|>