<commit_before>/***********************************************************************
    filename:   GeometryBufferBase.cpp
    created:    Tue Apr 30 2013
    authors:    Paul D Turner <paul@cegui.org.uk>
                Lukas E Meindl
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 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 <GL/glew.h>

#include "glm/glm.hpp"
#include "glm/gtc/quaternion.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "CEGUI/RendererModules/OpenGL/GeometryBufferBase.h"
#include "CEGUI/RenderEffect.h"
#include "CEGUI/RendererModules/OpenGL/Texture.h"
#include "CEGUI/Vertex.h"
#include "CEGUI/RendererModules/OpenGL/GlmPimpl.h"
#include "CEGUI/ShaderParameterBindings.h"

namespace CEGUI
{
//----------------------------------------------------------------------------//
OpenGLGeometryBufferBase::OpenGLGeometryBufferBase(OpenGLRendererBase& owner, CEGUI::RefCounted<RenderMaterial> renderMaterial) :
    GeometryBuffer(renderMaterial),
    d_owner(&owner),
    d_clipRect(0, 0, 0, 0),
    d_clippingActive(true),
    d_translation(0, 0, 0),
    d_rotation(Quaternion::IDENTITY),
    d_scale(1.0f, 1.0f, 1.0f),
    d_pivot(0, 0, 0),
    d_customTransform(1.0f),
    d_effect(0),
    d_matrix(new mat4Pimpl()),
    d_matrixValid(false),
    d_vertexCount(0)
{
}

//----------------------------------------------------------------------------//
OpenGLGeometryBufferBase::~OpenGLGeometryBufferBase()
{
    delete d_matrix;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setTranslation(const Vector3f& v)
{
    if(d_translation != v)
    {
        d_translation = v;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setRotation(const Quaternion& r)
{
    if(d_rotation != r)
    {
        d_rotation = r;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setScale(const Vector3f& v)
{
    if(d_scale != v)
    {
        d_scale = v;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setPivot(const Vector3f& p)
{
    if(d_pivot != p)
    {
        d_pivot = Vector3f(p.d_x, p.d_y, p.d_z);
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setCustomTransform(const glm::mat4x4& transformation)
{
    if(d_customTransform != transformation)
    {
        d_customTransform = transformation;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setClippingRegion(const Rectf& region)
{
    d_clipRect.top(ceguimax(0.0f, region.top()));
    d_clipRect.left(ceguimax(0.0f, region.left()));
    d_clipRect.bottom(ceguimax(0.0f, region.bottom()));
    d_clipRect.right(ceguimax(0.0f, region.right()));
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setTexture(Texture* texture)
{
    CEGUI::ShaderParameterBindings* shaderParameterBindings = (*d_renderMaterial).getShaderParamBindings();
    shaderParameterBindings->setParameter("texture0", texture);
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::reset()
{
    d_vertexData.clear();
    d_clippingActive = true;
}

//----------------------------------------------------------------------------//
uint OpenGLGeometryBufferBase::getVertexCount() const
{
    return d_vertexData.size();
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setRenderEffect(RenderEffect* effect)
{
    d_effect = effect;
}

//----------------------------------------------------------------------------//
RenderEffect* OpenGLGeometryBufferBase::getRenderEffect()
{
    return d_effect;
}

//----------------------------------------------------------------------------//
const mat4Pimpl* OpenGLGeometryBufferBase::getMatrix() const
{
    if (!d_matrixValid)
        updateMatrix();

    return d_matrix;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::updateMatrix() const
{
    glm::mat4& model_matrix = d_matrix->d_matrix;

    const glm::vec3 final_trans(d_translation.d_x + d_pivot.d_x,
                                d_translation.d_y + d_pivot.d_y,
                                d_translation.d_z + d_pivot.d_z);

    model_matrix = glm::translate(glm::mat4(1.0f), final_trans);

    glm::quat rotationQuat = glm::quat(d_rotation.d_w, d_rotation.d_x, d_rotation.d_y, d_rotation.d_z);
    glm::mat4 rotation_matrix = glm::mat4_cast(rotationQuat);

    glm::mat4 scale_matrix(glm::scale(glm::mat4(1.0f), glm::vec3(d_scale.d_x, d_scale.d_y, d_scale.d_z)));

    model_matrix *= rotation_matrix * scale_matrix;

    glm::vec3 transl = glm::vec3(-d_pivot.d_x, -d_pivot.d_y, -d_pivot.d_z);
    glm::mat4 translMatrix = glm::translate(glm::mat4(1.f), transl);
    model_matrix *=  translMatrix * d_customTransform;

    d_matrixValid = true;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setClippingActive(const bool active)
{
    d_clippingActive = active;
}

//----------------------------------------------------------------------------//
bool OpenGLGeometryBufferBase::isClippingActive() const
{
    return d_clippingActive;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::appendGeometry(const std::vector<float>& vertex_data)
{
    d_vertexData.insert(d_vertexData.end(), vertex_data.begin(), vertex_data.end());
    // Update size of geometry buffer
    d_vertexCount = d_vertexData.size() / getVertexAttributeElementCount();
}

//----------------------------------------------------------------------------//

}

<commit_msg>MOD: Fixed getter return value<commit_after>/***********************************************************************
    filename:   GeometryBufferBase.cpp
    created:    Tue Apr 30 2013
    authors:    Paul D Turner <paul@cegui.org.uk>
                Lukas E Meindl
*************************************************************************/
/***************************************************************************
 *   Copyright (C) 2004 - 2013 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 <GL/glew.h>

#include "glm/glm.hpp"
#include "glm/gtc/quaternion.hpp"
#include "glm/gtc/type_ptr.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "CEGUI/RendererModules/OpenGL/GeometryBufferBase.h"
#include "CEGUI/RenderEffect.h"
#include "CEGUI/RendererModules/OpenGL/Texture.h"
#include "CEGUI/Vertex.h"
#include "CEGUI/RendererModules/OpenGL/GlmPimpl.h"
#include "CEGUI/ShaderParameterBindings.h"

namespace CEGUI
{
//----------------------------------------------------------------------------//
OpenGLGeometryBufferBase::OpenGLGeometryBufferBase(OpenGLRendererBase& owner, CEGUI::RefCounted<RenderMaterial> renderMaterial) :
    GeometryBuffer(renderMaterial),
    d_owner(&owner),
    d_clipRect(0, 0, 0, 0),
    d_clippingActive(true),
    d_translation(0, 0, 0),
    d_rotation(Quaternion::IDENTITY),
    d_scale(1.0f, 1.0f, 1.0f),
    d_pivot(0, 0, 0),
    d_customTransform(1.0f),
    d_effect(0),
    d_matrix(new mat4Pimpl()),
    d_matrixValid(false),
    d_vertexCount(0)
{
}

//----------------------------------------------------------------------------//
OpenGLGeometryBufferBase::~OpenGLGeometryBufferBase()
{
    delete d_matrix;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setTranslation(const Vector3f& v)
{
    if(d_translation != v)
    {
        d_translation = v;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setRotation(const Quaternion& r)
{
    if(d_rotation != r)
    {
        d_rotation = r;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setScale(const Vector3f& v)
{
    if(d_scale != v)
    {
        d_scale = v;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setPivot(const Vector3f& p)
{
    if(d_pivot != p)
    {
        d_pivot = Vector3f(p.d_x, p.d_y, p.d_z);
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setCustomTransform(const glm::mat4x4& transformation)
{
    if(d_customTransform != transformation)
    {
        d_customTransform = transformation;
        d_matrixValid = false;
    }
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setClippingRegion(const Rectf& region)
{
    d_clipRect.top(ceguimax(0.0f, region.top()));
    d_clipRect.left(ceguimax(0.0f, region.left()));
    d_clipRect.bottom(ceguimax(0.0f, region.bottom()));
    d_clipRect.right(ceguimax(0.0f, region.right()));
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setTexture(Texture* texture)
{
    CEGUI::ShaderParameterBindings* shaderParameterBindings = (*d_renderMaterial).getShaderParamBindings();
    shaderParameterBindings->setParameter("texture0", texture);
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::reset()
{
    d_vertexData.clear();
    d_clippingActive = true;
}

//----------------------------------------------------------------------------//
uint OpenGLGeometryBufferBase::getVertexCount() const
{
    return d_vertexCount;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setRenderEffect(RenderEffect* effect)
{
    d_effect = effect;
}

//----------------------------------------------------------------------------//
RenderEffect* OpenGLGeometryBufferBase::getRenderEffect()
{
    return d_effect;
}

//----------------------------------------------------------------------------//
const mat4Pimpl* OpenGLGeometryBufferBase::getMatrix() const
{
    if (!d_matrixValid)
        updateMatrix();

    return d_matrix;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::updateMatrix() const
{
    glm::mat4& model_matrix = d_matrix->d_matrix;

    const glm::vec3 final_trans(d_translation.d_x + d_pivot.d_x,
                                d_translation.d_y + d_pivot.d_y,
                                d_translation.d_z + d_pivot.d_z);

    model_matrix = glm::translate(glm::mat4(1.0f), final_trans);

    glm::quat rotationQuat = glm::quat(d_rotation.d_w, d_rotation.d_x, d_rotation.d_y, d_rotation.d_z);
    glm::mat4 rotation_matrix = glm::mat4_cast(rotationQuat);

    glm::mat4 scale_matrix(glm::scale(glm::mat4(1.0f), glm::vec3(d_scale.d_x, d_scale.d_y, d_scale.d_z)));

    model_matrix *= rotation_matrix * scale_matrix;

    glm::vec3 transl = glm::vec3(-d_pivot.d_x, -d_pivot.d_y, -d_pivot.d_z);
    glm::mat4 translMatrix = glm::translate(glm::mat4(1.f), transl);
    model_matrix *=  translMatrix * d_customTransform;

    d_matrixValid = true;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::setClippingActive(const bool active)
{
    d_clippingActive = active;
}

//----------------------------------------------------------------------------//
bool OpenGLGeometryBufferBase::isClippingActive() const
{
    return d_clippingActive;
}

//----------------------------------------------------------------------------//
void OpenGLGeometryBufferBase::appendGeometry(const std::vector<float>& vertex_data)
{
    d_vertexData.insert(d_vertexData.end(), vertex_data.begin(), vertex_data.end());
    // Update size of geometry buffer
    d_vertexCount = d_vertexData.size() / getVertexAttributeElementCount();
}

//----------------------------------------------------------------------------//

}

<|endoftext|>


<commit_before>#include <cmath>
#include <cstring>
#include "core.h"
#include "tile.h"
#include "core_model.h"
#include "simulator.h"
#include "syscall_model.h"
#include "sync_client.h"
#include "network_types.h"
#include "memory_manager.h"
#include "pin_memory_manager.h"
#include "clock_skew_minimization_object.h"
#include "clock_converter.h"
#include "config.h"
#include "log.h"
#include "dvfs_manager.h"

Core::Core(Tile *tile, core_type_t core_type)
   : _tile(tile)
   , _core_model(NULL)
   , _state(IDLE)
   , _pin_memory_manager(NULL)
   , _enabled(false)
   , _component(CORE)
{

   DVFSManager::getSynchronizationDelay();

   _id = (core_id_t) {_tile->getId(), core_type};
   if (Config::getSingleton()->getEnableCoreModeling())
      _core_model = CoreModel::create(this);

   _sync_client = new SyncClient(this);
   _syscall_model = new SyscallMdl(this);
   _clock_skew_minimization_client =
      ClockSkewMinimizationClient::create(Sim()->getCfg()->getString("clock_skew_minimization/scheme","none"), this);

   if (Config::getSingleton()->isSimulatingSharedMemory())
      _pin_memory_manager = new PinMemoryManager(this);

   initializeMemoryAccessLatencyCounters();

   //initialize frequency and voltage
   int rc = DVFSManager::getInitialFrequencyAndVoltage(CORE, _frequency, _voltage);
   LOG_ASSERT_ERROR(rc == 0, "Error setting initial voltage for frequency(%g)", _frequency);

   _synchronization_delay = Time(Latency(DVFSManager::getSynchronizationDelay(), _frequency));

   LOG_PRINT("Initialized Core.");
}

Core::~Core()
{
   if (_pin_memory_manager)
      delete _pin_memory_manager;

   if (_clock_skew_minimization_client)
      delete _clock_skew_minimization_client;

   delete _syscall_model;
   delete _sync_client;
   delete _core_model;
}

int
Core::coreSendW(int sender, int receiver, char* buffer, int size, carbon_network_t net_type)
{
   PacketType packet_type = getPacketTypeFromUserNetType(net_type);

   core_id_t receiver_core = (core_id_t) {receiver, _id.core_type};

   SInt32 sent = (receiver == CAPI_ENDPOINT_ALL) ?
                 _tile->getNetwork()->netBroadcast(packet_type, buffer, size) :
                 _tile->getNetwork()->netSend(receiver_core, packet_type, buffer, size);

   LOG_ASSERT_ERROR(sent == size, "Bytes Sent(%i), Message Size(%i)", sent, size);

   return (sent == size) ? 0 : -1;
}

int
Core::coreRecvW(int sender, int receiver, char* buffer, int size, carbon_network_t net_type)
{
   PacketType packet_type = getPacketTypeFromUserNetType(net_type);

   core_id_t sender_core = (core_id_t) {sender, _id.core_type};

   NetPacket packet = (sender == CAPI_ENDPOINT_ANY) ?
                      _tile->getNetwork()->netRecvType(packet_type, _id) :
                      _tile->getNetwork()->netRecv(sender_core, _id, packet_type);

   LOG_PRINT("Got packet: from (%i,%i), to (%i,%i), type (%i), len (%i)",
             packet.sender.tile_id, packet.sender.core_type, packet.receiver.tile_id, packet.receiver.core_type,
             (SInt32) packet.type, packet.length);

   LOG_ASSERT_ERROR((unsigned)size == packet.length,
                    "Application requested packet of size: %d, got a packet from %d of size: %d",
                    size, sender, packet.length);

   memcpy(buffer, packet.data, size);

   // De-allocate dynamic memory
   // Is this the best place to de-allocate packet.data ??
   delete [] (Byte*) packet.data;

   return (unsigned)size == packet.length ? 0 : -1;
}

// accessMemory(lock_signal_t lock_signal, mem_op_t mem_op_type, IntPtr address, char* data_buffer, UInt32 data_size, bool push_info)
//
// Arguments:
//   lock_signal :: NONE, LOCK, or UNLOCK
//   mem_op_type :: READ, READ_EX, or WRITE
//   address :: address of location we want to access (read or write)
//   data_buffer :: buffer holding data for WRITE or buffer which must be written on a READ
//   data_size :: size of data we must read/write
//   push_info :: says whether memory info must be pushed to the core model
//
// Return Value:
//   (number of misses, memory access latency) :: the number of cache misses and memory access latency

pair<UInt32, Time>
Core::accessMemory(lock_signal_t lock_signal, mem_op_t mem_op_type, IntPtr address, char* data_buffer, UInt32 data_size, bool push_info)
{
   return initiateMemoryAccess(MemComponent::L1_DCACHE, lock_signal, mem_op_type, address, (Byte*) data_buffer, data_size, push_info);
}

Time
Core::readInstructionMemory(IntPtr address, UInt32 instruction_size)
{
   LOG_PRINT("Instruction: Address(%#lx), Size(%u), Start READ", address, instruction_size);

   Byte buf[instruction_size];
   return initiateMemoryAccess(MemComponent::L1_ICACHE, Core::NONE, Core::READ, address, buf, instruction_size).second;
}

pair<UInt32, Time>
Core::initiateMemoryAccess(MemComponent::Type mem_component, lock_signal_t lock_signal, mem_op_t mem_op_type,
                           IntPtr address, Byte* data_buf, UInt32 data_size,
                           bool push_info, Time time)
{
   LOG_ASSERT_ERROR(Config::getSingleton()->isSimulatingSharedMemory(), "Shared Memory Disabled");

   if (data_size == 0)
   {
      if (push_info)
      {
         DynamicInstructionInfo info = DynamicInstructionInfo::createMemoryInfo(Time(0), address, (mem_op_type == WRITE) ? Operand::WRITE : Operand::READ, 0);
         if (_core_model)
            _core_model->pushDynamicInstructionInfo(info);
      }
      return make_pair<UInt32, Time>(0,Time(0));
   }

   // Setting the initial time
   Time initial_time = (time.getTime() == 0) ? _core_model->getCurrTime() : Time(time);
   Time curr_time = initial_time;

   LOG_PRINT("Time(%llu), %s - ADDR(%#lx), data_size(%u), START",
             initial_time.toNanosec(), ((mem_op_type == READ) ? "READ" : "WRITE"), address, data_size);

   UInt32 num_misses = 0;
   UInt32 cache_line_size = _tile->getMemoryManager()->getCacheLineSize();

   IntPtr begin_addr = address;
   IntPtr end_addr = address + data_size;
   IntPtr begin_addr_aligned = begin_addr - (begin_addr % cache_line_size);
   IntPtr end_addr_aligned = end_addr - (end_addr % cache_line_size);
   Byte *curr_data_buffer_head = (Byte*) data_buf;

   for (IntPtr curr_addr_aligned = begin_addr_aligned; curr_addr_aligned <= end_addr_aligned; curr_addr_aligned += cache_line_size)
   {
      // Access the cache one line at a time
      UInt32 curr_offset;
      UInt32 curr_size;

      // Determine the offset
      if (curr_addr_aligned == begin_addr_aligned)
      {
         curr_offset = begin_addr % cache_line_size;
      }
      else
      {
         curr_offset = 0;
      }

      // Determine the size
      if (curr_addr_aligned == end_addr_aligned)
      {
         curr_size = (end_addr % cache_line_size) - (curr_offset);
         if (curr_size == 0)
         {
            continue;
         }
      }
      else
      {
         curr_size = cache_line_size - (curr_offset);
      }

      LOG_PRINT("Start coreInitiateMemoryAccess: ADDR(%#lx), offset(%u), curr_size(%u), core_id(%i, %i)",
                curr_addr_aligned, curr_offset, curr_size, getId().tile_id, getId().core_type);

      if (!_tile->getMemoryManager()->__coreInitiateMemoryAccess(mem_component, lock_signal, mem_op_type,
                                                                 curr_addr_aligned, curr_offset,
                                                                 curr_data_buffer_head, curr_size,
                                                                 curr_time, push_info))
      {
         // If it is a READ or READ_EX operation,
         //    'coreInitiateMemoryAccess' causes curr_data_buffer_head to be automatically filled in
         // If it is a WRITE operation,
         //    'coreInitiateMemoryAccess' reads the data from curr_data_buffer_head
         num_misses ++;
      }

      LOG_PRINT("End InitiateSharedMemReq: ADDR(%#lx), offset(%u), curr_size(%u), core_id(%i,%i)",
                curr_addr_aligned, curr_offset, curr_size, getId().tile_id, getId().core_type);

      // Increment the buffer head
      curr_data_buffer_head += curr_size;
   }

   // Get the final cycle time
   Time final_time = curr_time;
   LOG_ASSERT_ERROR(final_time >= initial_time, "final_time(%llu) < initial_time(%llu)", final_time.getTime(), initial_time.getTime());

   LOG_PRINT("Time(%llu), %s - ADDR(%#lx), data_size(%u), END",
             final_time.toNanosec(), ((mem_op_type == READ) ? "READ" : "WRITE"), address, data_size);

   // Calculate the round-trip time
   Time memory_access_time = final_time - initial_time;
   incrTotalMemoryAccessLatency(mem_component, memory_access_time);

   // Add synchronization delay
   if (mem_component == MemComponent::L1_ICACHE)
      memory_access_time += getSynchronizationDelay(L1_ICACHE);
   if (mem_component == MemComponent::L1_DCACHE)
      memory_access_time += getSynchronizationDelay(L1_DCACHE);

   if (push_info)
   {
      DynamicInstructionInfo info = DynamicInstructionInfo::createMemoryInfo(memory_access_time, address, (mem_op_type == WRITE) ? Operand::WRITE : Operand::READ, num_misses);
      if (_core_model)
         _core_model->pushDynamicInstructionInfo(info);
   }

   return make_pair<UInt32, Time>(num_misses, memory_access_time);
}

PacketType
Core::getPacketTypeFromUserNetType(carbon_network_t net_type)
{
   switch (net_type)
   {
   case CARBON_NET_USER:
      return USER;

   default:
      LOG_PRINT_ERROR("Unrecognized User Network(%u)", net_type);
      return (PacketType) -1;
   }
}

void
Core::outputSummary(ostream& os, const Time& target_completion_time)
{
   if (_core_model)
      _core_model->outputSummary(os, target_completion_time);

   UInt64 total_instruction_memory_access_latency_in_ns = _total_instruction_memory_access_latency.toNanosec();
   UInt64 total_data_memory_access_latency_in_ns = _total_data_memory_access_latency.toNanosec();

   os << "Shared Memory Model summary: " << endl;
   os << "    Total Memory Accesses: " << _num_instruction_memory_accesses + _num_data_memory_accesses << endl;
   os << "    Average Memory Access Latency (in ns): "
      << (1.0 * (total_instruction_memory_access_latency_in_ns + total_data_memory_access_latency_in_ns) /
                (_num_instruction_memory_accesses + _num_data_memory_accesses))
      << endl;

   os << "    Total Instruction Memory Accesses: " << _num_instruction_memory_accesses << endl;
   os << "    Average Instruction Memory Access Latency (in ns): "
      << 1.0 * total_instruction_memory_access_latency_in_ns / _num_instruction_memory_accesses
      << endl;

   os << "    Total Data Memory Accesses: " << _num_data_memory_accesses << endl;
   os << "    Average Data Memory Access Latency (in ns): "
      << 1.0 * total_data_memory_access_latency_in_ns / _num_data_memory_accesses
      << endl;
}

void
Core::enableModels()
{
   _enabled = true;
   if (_core_model)
      _core_model->enable();
   if (_clock_skew_minimization_client)
      _clock_skew_minimization_client->enable();
}

void
Core::disableModels()
{
   _enabled = false;
   if (_core_model)
      _core_model->disable();
   if (_clock_skew_minimization_client)
      _clock_skew_minimization_client->disable();
}

void
Core::initializeMemoryAccessLatencyCounters()
{
   _num_instruction_memory_accesses = 0;
   _total_instruction_memory_access_latency = Time(0);
   _num_data_memory_accesses = 0;
   _total_data_memory_access_latency = Time(0);
}

void
Core::incrTotalMemoryAccessLatency(MemComponent::Type mem_component, Time memory_access_latency)
{
   if (!_enabled)
      return;

   if (mem_component == MemComponent::L1_ICACHE)
   {
      _num_instruction_memory_accesses ++;
      _total_instruction_memory_access_latency += memory_access_latency;
   }
   else if (mem_component == MemComponent::L1_DCACHE)
   {
      _num_data_memory_accesses ++;
      _total_data_memory_access_latency += memory_access_latency;
   }
   else
   {
      LOG_PRINT_ERROR("Unrecognized mem component(%s)", SPELL_MEMCOMP(mem_component));
   }
}

int
Core::getDVFS(double &frequency, double &voltage)
{
   frequency = _frequency;
   voltage = _voltage;
   return 0;
}

int
Core::setDVFS(double frequency, voltage_option_t voltage_flag, const Time& curr_time)
{
   int rc = DVFSManager::getVoltage(_voltage, voltage_flag, frequency);

   if (rc==0)
   {
      _core_model->setDVFS(_frequency, _voltage, frequency, curr_time);
      _frequency = frequency;
      _synchronization_delay = Time(Latency(DVFSManager::getSynchronizationDelay(), _frequency));
   }
   return rc;
}

Time
Core::getSynchronizationDelay(module_t component)
{
   if (!DVFSManager::hasSameDVFSDomain(_component, component)){
      return _synchronization_delay;
   }
   return Time(0);
}
<commit_msg>[dvfs] Cosmetic changes on core synchronization cost implementation.<commit_after>#include <cmath>
#include <cstring>
#include "core.h"
#include "tile.h"
#include "core_model.h"
#include "simulator.h"
#include "syscall_model.h"
#include "sync_client.h"
#include "network_types.h"
#include "memory_manager.h"
#include "pin_memory_manager.h"
#include "clock_skew_minimization_object.h"
#include "clock_converter.h"
#include "config.h"
#include "log.h"
#include "dvfs_manager.h"

Core::Core(Tile *tile, core_type_t core_type)
   : _tile(tile)
   , _core_model(NULL)
   , _state(IDLE)
   , _pin_memory_manager(NULL)
   , _enabled(false)
   , _component(CORE)
{

   _id = (core_id_t) {_tile->getId(), core_type};
   if (Config::getSingleton()->getEnableCoreModeling())
      _core_model = CoreModel::create(this);

   _sync_client = new SyncClient(this);
   _syscall_model = new SyscallMdl(this);
   _clock_skew_minimization_client =
      ClockSkewMinimizationClient::create(Sim()->getCfg()->getString("clock_skew_minimization/scheme","none"), this);

   if (Config::getSingleton()->isSimulatingSharedMemory())
      _pin_memory_manager = new PinMemoryManager(this);

   initializeMemoryAccessLatencyCounters();

   //initialize frequency and voltage
   int rc = DVFSManager::getInitialFrequencyAndVoltage(CORE, _frequency, _voltage);
   LOG_ASSERT_ERROR(rc == 0, "Error setting initial voltage for frequency(%g)", _frequency);

   _synchronization_delay = Time(Latency(DVFSManager::getSynchronizationDelay(), _frequency));

   LOG_PRINT("Initialized Core.");
}

Core::~Core()
{
   if (_pin_memory_manager)
      delete _pin_memory_manager;

   if (_clock_skew_minimization_client)
      delete _clock_skew_minimization_client;

   delete _syscall_model;
   delete _sync_client;
   delete _core_model;
}

int
Core::coreSendW(int sender, int receiver, char* buffer, int size, carbon_network_t net_type)
{
   PacketType packet_type = getPacketTypeFromUserNetType(net_type);

   core_id_t receiver_core = (core_id_t) {receiver, _id.core_type};

   SInt32 sent = (receiver == CAPI_ENDPOINT_ALL) ?
                 _tile->getNetwork()->netBroadcast(packet_type, buffer, size) :
                 _tile->getNetwork()->netSend(receiver_core, packet_type, buffer, size);

   LOG_ASSERT_ERROR(sent == size, "Bytes Sent(%i), Message Size(%i)", sent, size);

   return (sent == size) ? 0 : -1;
}

int
Core::coreRecvW(int sender, int receiver, char* buffer, int size, carbon_network_t net_type)
{
   PacketType packet_type = getPacketTypeFromUserNetType(net_type);

   core_id_t sender_core = (core_id_t) {sender, _id.core_type};

   NetPacket packet = (sender == CAPI_ENDPOINT_ANY) ?
                      _tile->getNetwork()->netRecvType(packet_type, _id) :
                      _tile->getNetwork()->netRecv(sender_core, _id, packet_type);

   LOG_PRINT("Got packet: from (%i,%i), to (%i,%i), type (%i), len (%i)",
             packet.sender.tile_id, packet.sender.core_type, packet.receiver.tile_id, packet.receiver.core_type,
             (SInt32) packet.type, packet.length);

   LOG_ASSERT_ERROR((unsigned)size == packet.length,
                    "Application requested packet of size: %d, got a packet from %d of size: %d",
                    size, sender, packet.length);

   memcpy(buffer, packet.data, size);

   // De-allocate dynamic memory
   // Is this the best place to de-allocate packet.data ??
   delete [] (Byte*) packet.data;

   return (unsigned)size == packet.length ? 0 : -1;
}

// accessMemory(lock_signal_t lock_signal, mem_op_t mem_op_type, IntPtr address, char* data_buffer, UInt32 data_size, bool push_info)
//
// Arguments:
//   lock_signal :: NONE, LOCK, or UNLOCK
//   mem_op_type :: READ, READ_EX, or WRITE
//   address :: address of location we want to access (read or write)
//   data_buffer :: buffer holding data for WRITE or buffer which must be written on a READ
//   data_size :: size of data we must read/write
//   push_info :: says whether memory info must be pushed to the core model
//
// Return Value:
//   (number of misses, memory access latency) :: the number of cache misses and memory access latency

pair<UInt32, Time>
Core::accessMemory(lock_signal_t lock_signal, mem_op_t mem_op_type, IntPtr address, char* data_buffer, UInt32 data_size, bool push_info)
{
   return initiateMemoryAccess(MemComponent::L1_DCACHE, lock_signal, mem_op_type, address, (Byte*) data_buffer, data_size, push_info);
}

Time
Core::readInstructionMemory(IntPtr address, UInt32 instruction_size)
{
   LOG_PRINT("Instruction: Address(%#lx), Size(%u), Start READ", address, instruction_size);

   Byte buf[instruction_size];
   return initiateMemoryAccess(MemComponent::L1_ICACHE, Core::NONE, Core::READ, address, buf, instruction_size).second;
}

pair<UInt32, Time>
Core::initiateMemoryAccess(MemComponent::Type mem_component, lock_signal_t lock_signal, mem_op_t mem_op_type,
                           IntPtr address, Byte* data_buf, UInt32 data_size,
                           bool push_info, Time time)
{
   LOG_ASSERT_ERROR(Config::getSingleton()->isSimulatingSharedMemory(), "Shared Memory Disabled");

   if (data_size == 0)
   {
      if (push_info)
      {
         DynamicInstructionInfo info = DynamicInstructionInfo::createMemoryInfo(Time(0), address, (mem_op_type == WRITE) ? Operand::WRITE : Operand::READ, 0);
         if (_core_model)
            _core_model->pushDynamicInstructionInfo(info);
      }
      return make_pair<UInt32, Time>(0,Time(0));
   }

   // Setting the initial time
   Time initial_time = (time.getTime() == 0) ? _core_model->getCurrTime() : Time(time);
   Time curr_time = initial_time;

   LOG_PRINT("Time(%llu), %s - ADDR(%#lx), data_size(%u), START",
             initial_time.toNanosec(), ((mem_op_type == READ) ? "READ" : "WRITE"), address, data_size);

   UInt32 num_misses = 0;
   UInt32 cache_line_size = _tile->getMemoryManager()->getCacheLineSize();

   IntPtr begin_addr = address;
   IntPtr end_addr = address + data_size;
   IntPtr begin_addr_aligned = begin_addr - (begin_addr % cache_line_size);
   IntPtr end_addr_aligned = end_addr - (end_addr % cache_line_size);
   Byte *curr_data_buffer_head = (Byte*) data_buf;

   for (IntPtr curr_addr_aligned = begin_addr_aligned; curr_addr_aligned <= end_addr_aligned; curr_addr_aligned += cache_line_size)
   {
      // Access the cache one line at a time
      UInt32 curr_offset;
      UInt32 curr_size;

      // Determine the offset
      if (curr_addr_aligned == begin_addr_aligned)
      {
         curr_offset = begin_addr % cache_line_size;
      }
      else
      {
         curr_offset = 0;
      }

      // Determine the size
      if (curr_addr_aligned == end_addr_aligned)
      {
         curr_size = (end_addr % cache_line_size) - (curr_offset);
         if (curr_size == 0)
         {
            continue;
         }
      }
      else
      {
         curr_size = cache_line_size - (curr_offset);
      }

      LOG_PRINT("Start coreInitiateMemoryAccess: ADDR(%#lx), offset(%u), curr_size(%u), core_id(%i, %i)",
                curr_addr_aligned, curr_offset, curr_size, getId().tile_id, getId().core_type);

      if (!_tile->getMemoryManager()->__coreInitiateMemoryAccess(mem_component, lock_signal, mem_op_type,
                                                                 curr_addr_aligned, curr_offset,
                                                                 curr_data_buffer_head, curr_size,
                                                                 curr_time, push_info))
      {
         // If it is a READ or READ_EX operation,
         //    'coreInitiateMemoryAccess' causes curr_data_buffer_head to be automatically filled in
         // If it is a WRITE operation,
         //    'coreInitiateMemoryAccess' reads the data from curr_data_buffer_head
         num_misses ++;
      }

      LOG_PRINT("End InitiateSharedMemReq: ADDR(%#lx), offset(%u), curr_size(%u), core_id(%i,%i)",
                curr_addr_aligned, curr_offset, curr_size, getId().tile_id, getId().core_type);

      // Increment the buffer head
      curr_data_buffer_head += curr_size;
   }

   // Get the final cycle time
   Time final_time = curr_time;
   LOG_ASSERT_ERROR(final_time >= initial_time, "final_time(%llu) < initial_time(%llu)", final_time.getTime(), initial_time.getTime());

   LOG_PRINT("Time(%llu), %s - ADDR(%#lx), data_size(%u), END",
             final_time.toNanosec(), ((mem_op_type == READ) ? "READ" : "WRITE"), address, data_size);

   // Calculate the round-trip time
   Time memory_access_time = final_time - initial_time;
   incrTotalMemoryAccessLatency(mem_component, memory_access_time);

   // Add synchronization delay
   memory_access_time += getSynchronizationDelay(DVFSManager::convertToModule(mem_component));

   if (push_info)
   {
      DynamicInstructionInfo info = DynamicInstructionInfo::createMemoryInfo(memory_access_time, address, (mem_op_type == WRITE) ? Operand::WRITE : Operand::READ, num_misses);
      if (_core_model)
         _core_model->pushDynamicInstructionInfo(info);
   }

   return make_pair<UInt32, Time>(num_misses, memory_access_time);
}

PacketType
Core::getPacketTypeFromUserNetType(carbon_network_t net_type)
{
   switch (net_type)
   {
   case CARBON_NET_USER:
      return USER;

   default:
      LOG_PRINT_ERROR("Unrecognized User Network(%u)", net_type);
      return (PacketType) -1;
   }
}

void
Core::outputSummary(ostream& os, const Time& target_completion_time)
{
   if (_core_model)
      _core_model->outputSummary(os, target_completion_time);

   UInt64 total_instruction_memory_access_latency_in_ns = _total_instruction_memory_access_latency.toNanosec();
   UInt64 total_data_memory_access_latency_in_ns = _total_data_memory_access_latency.toNanosec();

   os << "Shared Memory Model summary: " << endl;
   os << "    Total Memory Accesses: " << _num_instruction_memory_accesses + _num_data_memory_accesses << endl;
   os << "    Average Memory Access Latency (in ns): "
      << (1.0 * (total_instruction_memory_access_latency_in_ns + total_data_memory_access_latency_in_ns) /
                (_num_instruction_memory_accesses + _num_data_memory_accesses))
      << endl;

   os << "    Total Instruction Memory Accesses: " << _num_instruction_memory_accesses << endl;
   os << "    Average Instruction Memory Access Latency (in ns): "
      << 1.0 * total_instruction_memory_access_latency_in_ns / _num_instruction_memory_accesses
      << endl;

   os << "    Total Data Memory Accesses: " << _num_data_memory_accesses << endl;
   os << "    Average Data Memory Access Latency (in ns): "
      << 1.0 * total_data_memory_access_latency_in_ns / _num_data_memory_accesses
      << endl;
}

void
Core::enableModels()
{
   _enabled = true;
   if (_core_model)
      _core_model->enable();
   if (_clock_skew_minimization_client)
      _clock_skew_minimization_client->enable();
}

void
Core::disableModels()
{
   _enabled = false;
   if (_core_model)
      _core_model->disable();
   if (_clock_skew_minimization_client)
      _clock_skew_minimization_client->disable();
}

void
Core::initializeMemoryAccessLatencyCounters()
{
   _num_instruction_memory_accesses = 0;
   _total_instruction_memory_access_latency = Time(0);
   _num_data_memory_accesses = 0;
   _total_data_memory_access_latency = Time(0);
}

void
Core::incrTotalMemoryAccessLatency(MemComponent::Type mem_component, Time memory_access_latency)
{
   if (!_enabled)
      return;

   if (mem_component == MemComponent::L1_ICACHE)
   {
      _num_instruction_memory_accesses ++;
      _total_instruction_memory_access_latency += memory_access_latency;
   }
   else if (mem_component == MemComponent::L1_DCACHE)
   {
      _num_data_memory_accesses ++;
      _total_data_memory_access_latency += memory_access_latency;
   }
   else
   {
      LOG_PRINT_ERROR("Unrecognized mem component(%s)", SPELL_MEMCOMP(mem_component));
   }
}

int
Core::getDVFS(double &frequency, double &voltage)
{
   frequency = _frequency;
   voltage = _voltage;
   return 0;
}

int
Core::setDVFS(double frequency, voltage_option_t voltage_flag, const Time& curr_time)
{
   int rc = DVFSManager::getVoltage(_voltage, voltage_flag, frequency);

   if (rc==0)
   {
      _core_model->setDVFS(_frequency, _voltage, frequency, curr_time);
      _frequency = frequency;
      _synchronization_delay = Time(Latency(DVFSManager::getSynchronizationDelay(), _frequency));
   }
   return rc;
}

Time
Core::getSynchronizationDelay(module_t component)
{
   if (!DVFSManager::hasSameDVFSDomain(_component, component)){
      return _synchronization_delay;
   }
   return Time(0);
}
<|endoftext|>


<commit_before>#include <QsLog.h>
#include <qnumeric.h>
#include "battery.h"

Battery::Battery(QObject *parent) :
	QObject(parent),
	mMaxChargeCurrent(qQNaN()),
	mMaxDischargeCurrent(qQNaN())
{
}

double Battery::maxChargeCurrent() const
{
	return mMaxChargeCurrent;
}

void Battery::setMaxChargeCurrent(double c)
{
	if (mMaxChargeCurrent == c)
		return;
	mMaxChargeCurrent = c;
	emit maxChargeCurrent();
}

double Battery::maxDischargeCurrent() const
{
	return mMaxDischargeCurrent;
}

void Battery::setMaxDischargeCurrent(double c)
{
	if (mMaxDischargeCurrent == c)
		return;
	mMaxDischargeCurrent = c;
	emit maxDischargeCurrentChanged();
}
<commit_msg>Fixed incorrect signal call<commit_after>#include <QsLog.h>
#include <qnumeric.h>
#include "battery.h"

Battery::Battery(QObject *parent) :
	QObject(parent),
	mMaxChargeCurrent(qQNaN()),
	mMaxDischargeCurrent(qQNaN())
{
}

double Battery::maxChargeCurrent() const
{
	return mMaxChargeCurrent;
}

void Battery::setMaxChargeCurrent(double c)
{
	if (mMaxChargeCurrent == c)
		return;
	mMaxChargeCurrent = c;
	emit maxChargeCurrentChanged();
}

double Battery::maxDischargeCurrent() const
{
	return mMaxDischargeCurrent;
}

void Battery::setMaxDischargeCurrent(double c)
{
	if (mMaxDischargeCurrent == c)
		return;
	mMaxDischargeCurrent = c;
	emit maxDischargeCurrentChanged();
}
<|endoftext|>


<commit_before>#include "registration/linear.h"

namespace MR
{
  namespace Registration
  {

    using namespace App;

    const char* initialisation_choices[] = { "mass", "geometric", "moments", "linear", "none", NULL };

    const OptionGroup rigid_options =
      OptionGroup ("Rigid registration options")

      + Option ("rigid", "the output text file containing the rigid transformation as a 4x4 matrix")
        + Argument ("file").type_file_out ()

      + Option ("rigid_scale", "use a multi-resolution scheme by defining a scale factor for each level "
                               "using comma separated values (Default: 0.5,1)")
        + Argument ("factor").type_sequence_float ()

      + Option ("rigid_niter", "the maximum number of iterations. This can be specified either as a single number "
                               "for all multi-resolution levels, or a single value for each level. (Default: 1000)")
        + Argument ("num").type_sequence_int ()

      + Option ("rigid_smooth_factor", "amount of smoothing before registration (Default: 1.0)")
        + Argument ("num").type_sequence_float ()

      + Option ("rigid_cc", "metric: use cross correlation. default: least squares");

    const OptionGroup affine_options =
        OptionGroup ("Affine registration options")

      + Option ("affine", "the output text file containing the affine transformation that aligns "
        "input image 1 to input image 2 as a 4x4 matrix")
        + Argument ("file").type_file_out ()

      + Option ("affine_2tomidway", "the output text file containing the affine transformation that aligns "
        "image2 to image1 in their common midway space as a 4x4 matrix")
        + Argument ("file").type_file_out ()

      + Option ("affine_1tomidway", "the output text file containing the affine transformation that "
        "aligns image1 to image2 in their common midway space as a 4x4 matrix")
        + Argument ("file").type_file_out ()

      + Option ("affine_scale", "use a multi-resolution scheme by defining a scale factor for each level "
                               "using comma separated values (Default: 0.5,1)")
        + Argument ("factor").type_sequence_float ()

      + Option ("affine_niter", "the maximum number of iterations. This can be specified either as a single number "
                                "for all multi-resolution levels, or a single value for each level. (Default: 1000)")
        + Argument ("num").type_sequence_int ()

      + Option ("affine_smooth_factor", "amount of smoothing before registration (Default: 1.0)")
        + Argument ("num").type_sequence_float ()

      + Option ("affine_loop_density", "density of gradient descent 1 (batch) to 0.0 (max stochastic) (Default: 1.0)")
        + Argument ("num").type_sequence_float ()

      + Option ("affine_cc", "metric: use cross correlation. default: least squares")

      + Option ("affine_robust", "metric: use robust estimator. default: false");

    const OptionGroup syn_options =
      OptionGroup ("SyN registration options")

      + Option ("warp", "the output non-linear warp defined as a deformation field")
        + Argument ("image").type_file_out ()

      + Option ("syn_scale", "use a multi-resolution scheme by defining a scale factor for each level "
                               "using comma separated values (Default: 0.5,1)")
        + Argument ("factor").type_sequence_float ()

      + Option ("syn_niter", "the maximum number of iterations. This can be specified either as a single number "
                               "for all multi-resolution levels, or a single value for each level. (Default: 1000)")
        + Argument ("num").type_sequence_int ()

      + Option ("smooth_grad", "regularise the gradient field with Gaussian smoothing (standard deviation in mm, Default 3 x voxel_size)")
        + Argument ("stdev").type_float ()

      + Option ("smooth_disp", "regularise the displacement field with Gaussian smoothing (standard deviation in mm, Default 0.5 x voxel_size)")
        + Argument ("stdev").type_float ()

      + Option ("grad_step", "the initial gradient step size for SyN registration (Default: 0.12)") //TODO
        + Argument ("num").type_float ();

    const OptionGroup initialisation_options =
        OptionGroup ("Initialisation options")

      + Option ("rigid_init", "initialise either the rigid, affine, or syn registration with the supplied rigid transformation (as a 4x4 matrix)")
        + Argument ("file").type_file_in ()

      + Option ("affine_init", "initialise either the affine, or syn registration with the supplied affine transformation (as a 4x4 matrix)")
        + Argument ("file").type_file_in ()

      + Option ("syn_init", "initialise the syn registration with the supplied warp image (which includes the linear transform)")
        + Argument ("image").type_image_in ()

      + Option ("centre", "for rigid and affine registration only: Initialise the centre of rotation and initial translation. "
                          "Valid choices are: mass (which uses the image center of mass), geometric (geometric image centre), moments (image moments), linear (from linear transformation file specified via rigid_init or affine_init) or none. "
                          "Default: mass (which may not be suited for multi-modality registration).")
        + Argument ("type").type_choice (initialisation_choices);

    const OptionGroup fod_options =
      OptionGroup ("FOD registration options")

      + Option ("directions", "the directions used for FOD reorienation using apodised point spread functions (Default: 60 directions)")
        + Argument ("file", "a list of directions [az el] generated using the gendir command.").type_file_in ()

      + Option ("lmax", "explicitly set the lmax to be used in FOD registration. By default FOD registration will "
                       "use lmax 4 SH coefficients")
        + Argument ("num").type_integer ()

      + Option ("noreorientation", "turn off FOD reorientation. Reorientation is on by default if the number "
                                   "of volumes in the 4th dimension corresponds to the number of coefficients in an "
                                   "antipodally symmetric spherical harmonic series (i.e. 6, 15, 28, 45, 66 etc");
  }
}

<commit_msg>linear.cpp fixed missing affine_repetition option<commit_after>#include "registration/linear.h"

namespace MR
{
  namespace Registration
  {

    using namespace App;

    const char* initialisation_choices[] = { "mass", "geometric", "moments", "linear", "none", NULL };

    const OptionGroup rigid_options =
      OptionGroup ("Rigid registration options")

      + Option ("rigid", "the output text file containing the rigid transformation as a 4x4 matrix")
        + Argument ("file").type_file_out ()

      + Option ("rigid_scale", "use a multi-resolution scheme by defining a scale factor for each level "
                               "using comma separated values (Default: 0.5,1)")
        + Argument ("factor").type_sequence_float ()

      + Option ("rigid_niter", "the maximum number of iterations. This can be specified either as a single number "
                               "for all multi-resolution levels, or a single value for each level. (Default: 1000)")
        + Argument ("num").type_sequence_int ()

      + Option ("rigid_smooth_factor", "amount of smoothing before registration (Default: 1.0)")
        + Argument ("num").type_sequence_float ()

      + Option ("rigid_cc", "metric: use cross correlation. default: least squares");

    const OptionGroup affine_options =
        OptionGroup ("Affine registration options")

      + Option ("affine", "the output text file containing the affine transformation that aligns "
        "input image 1 to input image 2 as a 4x4 matrix")
        + Argument ("file").type_file_out ()

      + Option ("affine_2tomidway", "the output text file containing the affine transformation that aligns "
        "image2 to image1 in their common midway space as a 4x4 matrix")
        + Argument ("file").type_file_out ()

      + Option ("affine_1tomidway", "the output text file containing the affine transformation that "
        "aligns image1 to image2 in their common midway space as a 4x4 matrix")
        + Argument ("file").type_file_out ()

      + Option ("affine_scale", "use a multi-resolution scheme by defining a scale factor for each level "
                               "using comma separated values (Default: 0.5,1)")
        + Argument ("factor").type_sequence_float ()

      + Option ("affine_niter", "the maximum number of iterations. This can be specified either as a single number "
                                "for all multi-resolution levels, or a single value for each level. (Default: 1000)")
        + Argument ("num").type_sequence_int ()

      + Option ("affine_smooth_factor", "amount of smoothing before registration (Default: 1.0)")
        + Argument ("num").type_sequence_float ()

      + Option ("affine_loop_density", "density of gradient descent 1 (batch) to 0.0 (max stochastic) (Default: 1.0)")
        + Argument ("num").type_sequence_float ()

      + Option ("affine_repetitions", "number of repetitions with identical settings for each scale level")
        + Argument ("num").type_sequence_int ()

      + Option ("affine_cc", "metric: use cross correlation. default: least squares")

      + Option ("affine_robust", "metric: use robust estimator. default: false");

    const OptionGroup syn_options =
      OptionGroup ("SyN registration options")

      + Option ("warp", "the output non-linear warp defined as a deformation field")
        + Argument ("image").type_file_out ()

      + Option ("syn_scale", "use a multi-resolution scheme by defining a scale factor for each level "
                               "using comma separated values (Default: 0.5,1)")
        + Argument ("factor").type_sequence_float ()

      + Option ("syn_niter", "the maximum number of iterations. This can be specified either as a single number "
                               "for all multi-resolution levels, or a single value for each level. (Default: 1000)")
        + Argument ("num").type_sequence_int ()

      + Option ("smooth_grad", "regularise the gradient field with Gaussian smoothing (standard deviation in mm, Default 3 x voxel_size)")
        + Argument ("stdev").type_float ()

      + Option ("smooth_disp", "regularise the displacement field with Gaussian smoothing (standard deviation in mm, Default 0.5 x voxel_size)")
        + Argument ("stdev").type_float ()

      + Option ("grad_step", "the initial gradient step size for SyN registration (Default: 0.12)") //TODO
        + Argument ("num").type_float ();

    const OptionGroup initialisation_options =
        OptionGroup ("Initialisation options")

      + Option ("rigid_init", "initialise either the rigid, affine, or syn registration with the supplied rigid transformation (as a 4x4 matrix)")
        + Argument ("file").type_file_in ()

      + Option ("affine_init", "initialise either the affine, or syn registration with the supplied affine transformation (as a 4x4 matrix)")
        + Argument ("file").type_file_in ()

      + Option ("syn_init", "initialise the syn registration with the supplied warp image (which includes the linear transform)")
        + Argument ("image").type_image_in ()

      + Option ("centre", "for rigid and affine registration only: Initialise the centre of rotation and initial translation. "
                          "Valid choices are: mass (which uses the image center of mass), geometric (geometric image centre), moments (image moments), linear (from linear transformation file specified via rigid_init or affine_init) or none. "
                          "Default: mass (which may not be suited for multi-modality registration).")
        + Argument ("type").type_choice (initialisation_choices);

    const OptionGroup fod_options =
      OptionGroup ("FOD registration options")

      + Option ("directions", "the directions used for FOD reorienation using apodised point spread functions (Default: 60 directions)")
        + Argument ("file", "a list of directions [az el] generated using the gendir command.").type_file_in ()

      + Option ("lmax", "explicitly set the lmax to be used in FOD registration. By default FOD registration will "
                       "use lmax 4 SH coefficients")
        + Argument ("num").type_integer ()

      + Option ("noreorientation", "turn off FOD reorientation. Reorientation is on by default if the number "
                                   "of volumes in the 4th dimension corresponds to the number of coefficients in an "
                                   "antipodally symmetric spherical harmonic series (i.e. 6, 15, 28, 45, 66 etc");
  }
}

<|endoftext|>


<commit_before>// call from command line like, for instance:
// root -l 'vincemark.cpp()'

#include <chrono>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <unistd.h>  // usleep
#include <sys/types.h>  // for kill
#include <signal.h>     // for kill

using namespace RooFit;

std::string cut_between(std::string input, std::string before, std::string after) {
  auto before_pos = input.find(before);
  auto after_pos = input.find(after);
  auto cut_pos = before_pos + before.length();
  auto cut_len = after_pos - cut_pos;
  std::string output = input.substr(cut_pos, cut_len);
  return output;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// timing_flag is used to activate only selected timing statements [1-7]
// num_cpu: -1 is special option -> compare overhead communication protocol (wrt 1 cpu)
// parallel_interleave: 0 = blocks of equal size, 1 = interleave
////////////////////////////////////////////////////////////////////////////////////////////////////

void vincemark(std::string workspace_filename,
               int num_cpu=1,
               int optConst=0,
               int parallel_interleave=0,
               bool cpu_affinity=true,
               int seed=1,
               int timing_flag=1,
               bool time_num_ints=false,
               bool fork_timer = false,
               int fork_timer_sleep_us = 100000,
               int print_level=0,
               bool debug=false
               ) {
  if (debug) {
    RooMsgService::instance().addStream(DEBUG);
    // extra possible options: Topic(Generation) Topic(RooFit::Eval), ClassName("RooAbsTestStatistic")
  }

  // int N_parameters(8);  // must be even, means and sigmas have diff ranges

  if (timing_flag > 0) {
    RooJsonListFile outfile;

    outfile.open("timing_meta.json");
    std::string names[13] = {"workspace_filename",
                             "N_chans", "N_bins", "N_nuisance_parameters",
                             "N_events", "num_cpu", "parallel_interleave",
                             "seed", "pid", "time_num_ints",
                             "optConst", "print_level", "timing_flag"};
    outfile.set_member_names(names, names + 13);

    std::string N_channels = cut_between(workspace_filename, "workspace", "channels");
    std::string N_events = cut_between(workspace_filename, "channels", "events");
    std::string N_bins = cut_between(workspace_filename, "events", "bins");
    std::string N_nuisance_parameters = cut_between(workspace_filename, "bins", "nps");

    outfile << workspace_filename << N_channels << N_bins << N_nuisance_parameters
            << N_events << num_cpu << parallel_interleave
            << seed << getpid() << time_num_ints
            << optConst << print_level << timing_flag;
  }

  RooTrace::timing_flag = timing_flag;
  if (time_num_ints) {
    RooTrace::set_time_numInts(kTRUE);
  }

  // plotting configuration
  int obs_plot_x(3);
  int obs_plot_y(2);
  int obs_plot_x_px(1200);
  int obs_plot_y_px(800);

  // other stuff
  int printlevel(print_level);
  int optimizeConst(optConst);
  // int N_timing_loops(3); // not used

  gRandom->SetSeed(seed);

  // Load the workspace data and pdf
  TFile *_file0 = TFile::Open(workspace_filename.c_str());

  RooWorkspace* w = static_cast<RooWorkspace*>(gDirectory->Get("BinnedWorkspace"));
  RooStats::ModelConfig* mc = static_cast<RooStats::ModelConfig*>(w->genobj("ModelConfig"));

  RooAbsPdf* pdf = w->pdf(mc->GetPdf()->GetName()) ;
  RooAbsData * data = w->data("obsData");

  // --- Perform extended ML fit of composite PDF to data ---

  RooJsonListFile outfile;
  RooWallTimer timer;

  if (timing_flag == 1) {
    outfile.open("timing_full_minimize.json");
    outfile.add_member_name("walltime_s")
           .add_member_name("segment")
           .add_member_name("pid");
  }

  Bool_t cpuAffinity;
  if (cpu_affinity) {
    cpuAffinity = kTRUE;
  } else {
    cpuAffinity = kFALSE;
  }

  // for (int it = 0; it < N_timing_loops; ++it)
  {
    RooAbsReal* nll = pdf.createNLL(*data, NumCPU(num_cpu, parallel_interleave),
                                    CPUAffinity(cpuAffinity));//, "Extended");
    RooMinimizer m(*nll);
    // m.setVerbose(1);
    m.setStrategy(0);
    m.setProfile(1);
    m.setPrintLevel(printlevel);
    m.optimizeConst(optimizeConst);

    int pid = -1;

    if (fork_timer) {
      pid = fork();
    }
    if (pid == 0) {
      /* child */
      timer.start();
      while (true) {
        timer.stop();
        std::cout << "TIME: " << timer.timing_s() << "s" << std::endl;
        usleep(fork_timer_sleep_us);
      }
    }
    else {
      /* parent */

      double time_migrad, time_hesse, time_minos;

      if (timing_flag == 1) {
        timer.start();
      }
      // m.hesse();

      m.migrad();

      if (timing_flag == 1) {
        timer.stop();
        std::cout << "TIME migrad: " << timer.timing_s() << "s" << std::endl;
        outfile << timer.timing_s() << "migrad" << getpid();
        time_migrad = timer.timing_s();

        timer.start();
      }

      m.hesse();

      if (timing_flag == 1) {
        timer.stop();
        std::cout << "TIME hesse: " << timer.timing_s() << "s" << std::endl;
        outfile << timer.timing_s() << "hesse" << getpid();
        time_hesse = timer.timing_s();

        timer.start();
      }

      m.minos(mc->GetParametersOfInterest());

      if (timing_flag == 1) {
        timer.stop();
        std::cout << "TIME minos: " << timer.timing_s() << "s" << std::endl;
        outfile << timer.timing_s() << "minos" << getpid();
        time_minos = timer.timing_s();

        outfile << (time_migrad + time_hesse + time_minos) << "migrad+hesse+minos" << getpid();
      }

      if (pid > 0) {
        // a child exists
        kill(pid, SIGKILL);
      }
    }
  }
}
<commit_msg>Some fixes for vincemark<commit_after>// call from command line like, for instance:
// root -l 'vincemark.cpp()'

#include <chrono>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <unistd.h>  // usleep
#include <sys/types.h>  // for kill
#include <signal.h>     // for kill

using namespace RooFit;

std::string cut_between(std::string input, std::string before, std::string after) {
  auto before_pos = input.find(before);
  auto after_pos = input.find(after);
  auto cut_pos = before_pos + before.length();
  auto cut_len = after_pos - cut_pos;
  std::string output = input.substr(cut_pos, cut_len);
  return output;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// timing_flag is used to activate only selected timing statements [1-7]
// num_cpu: -1 is special option -> compare overhead communication protocol (wrt 1 cpu)
// parallel_interleave: 0 = blocks of equal size, 1 = interleave
////////////////////////////////////////////////////////////////////////////////////////////////////

void vincemark(std::string workspace_filepath,
               int num_cpu=1,
               int optConst=0,
               int parallel_interleave=0,
               bool cpu_affinity=true,
               int seed=1,
               int timing_flag=1,
               bool time_num_ints=false,
               bool fork_timer = false,
               int fork_timer_sleep_us = 100000,
               int print_level=0,
               bool debug=false
               ) {
  if (debug) {
    RooMsgService::instance().addStream(DEBUG);
    // extra possible options: Topic(Generation) Topic(RooFit::Eval), ClassName("RooAbsTestStatistic")
  }

  // int N_parameters(8);  // must be even, means and sigmas have diff ranges

  if (timing_flag > 0) {
    RooJsonListFile outfile;

    outfile.open("timing_meta.json");
    std::string names[13] = {"workspace_filepath",
                             "N_chans", "N_bins", "N_nuisance_parameters",
                             "N_events", "num_cpu", "parallel_interleave",
                             "seed", "pid", "time_num_ints",
                             "optConst", "print_level", "timing_flag"};
    outfile.set_member_names(names, names + 13);

    auto workspace_fn = workspace_filepath.substr(workspace_filepath.rfind("/"));

    std::string N_channels = cut_between(workspace_fn, "workspace", "channels");
    std::string N_events = cut_between(workspace_fn, "channels", "events");
    std::string N_bins = cut_between(workspace_fn, "events", "bins");
    std::string N_nuisance_parameters = cut_between(workspace_fn, "bins", "nps");

    outfile << workspace_filepath << N_channels << N_bins << N_nuisance_parameters
            << N_events << num_cpu << parallel_interleave
            << seed << getpid() << time_num_ints
            << optConst << print_level << timing_flag;
  }

  RooTrace::timing_flag = timing_flag;
  if (time_num_ints) {
    RooTrace::set_time_numInts(kTRUE);
  }

  // plotting configuration
  int obs_plot_x(3);
  int obs_plot_y(2);
  int obs_plot_x_px(1200);
  int obs_plot_y_px(800);

  // other stuff
  int printlevel(print_level);
  int optimizeConst(optConst);
  // int N_timing_loops(3); // not used

  gRandom->SetSeed(seed);

  // Load the workspace data and pdf
  TFile *_file0 = TFile::Open(workspace_filepath.c_str());

  RooWorkspace* w = static_cast<RooWorkspace*>(gDirectory->Get("BinnedWorkspace"));
  RooStats::ModelConfig* mc = static_cast<RooStats::ModelConfig*>(w->genobj("ModelConfig"));

  RooAbsPdf* pdf = w->pdf(mc->GetPdf()->GetName()) ;
  RooAbsData * data = w->data("obsData");

  // --- Perform extended ML fit of composite PDF to data ---

  RooJsonListFile outfile;
  RooWallTimer timer;

  if (timing_flag == 1) {
    outfile.open("timing_full_minimize.json");
    outfile.add_member_name("walltime_s")
           .add_member_name("segment")
           .add_member_name("pid");
  }

  Bool_t cpuAffinity;
  if (cpu_affinity) {
    cpuAffinity = kTRUE;
  } else {
    cpuAffinity = kFALSE;
  }

  // for (int it = 0; it < N_timing_loops; ++it)
  {
    RooAbsReal* nll = pdf->createNLL(*data, NumCPU(num_cpu, parallel_interleave),
                                     CPUAffinity(cpuAffinity));//, "Extended");
    RooMinimizer m(*nll);
    // m.setVerbose(1);
    m.setStrategy(0);
    m.setProfile(1);
    m.setPrintLevel(printlevel);
    m.optimizeConst(optimizeConst);

    int pid = -1;

    if (fork_timer) {
      pid = fork();
    }
    if (pid == 0) {
      /* child */
      timer.start();
      while (true) {
        timer.stop();
        std::cout << "TIME: " << timer.timing_s() << "s" << std::endl;
        usleep(fork_timer_sleep_us);
      }
    }
    else {
      /* parent */

      double time_migrad, time_hesse, time_minos;

      if (timing_flag == 1) {
        timer.start();
      }
      // m.hesse();

      m.migrad();

      if (timing_flag == 1) {
        timer.stop();
        std::cout << "TIME migrad: " << timer.timing_s() << "s" << std::endl;
        outfile << timer.timing_s() << "migrad" << getpid();
        time_migrad = timer.timing_s();

        timer.start();
      }

      m.hesse();

      if (timing_flag == 1) {
        timer.stop();
        std::cout << "TIME hesse: " << timer.timing_s() << "s" << std::endl;
        outfile << timer.timing_s() << "hesse" << getpid();
        time_hesse = timer.timing_s();

        timer.start();
      }

      m.minos(*mc->GetParametersOfInterest());

      if (timing_flag == 1) {
        timer.stop();
        std::cout << "TIME minos: " << timer.timing_s() << "s" << std::endl;
        outfile << timer.timing_s() << "minos" << getpid();
        time_minos = timer.timing_s();

        outfile << (time_migrad + time_hesse + time_minos) << "migrad+hesse+minos" << getpid();
      }

      if (pid > 0) {
        // a child exists
        kill(pid, SIGKILL);
      }
    }
  }
}
<|endoftext|>


<commit_before>/*
    pluginloader.cpp - Kopete Plugin Loader

    Copyright (c) 2002      by Duncan Mac-Vicar Prett <duncan@kde.org>
    Copyright (c) 2002-2003 by Martijn Klingens       <klingens@kde.org>

    Portions of this code based in Noatun plugin code:
    Copyright (c) 2000-2002 The Noatun Developers

    Kopete    (c) 2002-2003 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "pluginloader.h"

#include <qapplication.h>
#include <qdir.h>
#include <qfile.h>

#include <kdebug.h>
#include <kglobal.h>
#include <klocale.h>
#include <knotifyclient.h>
#include <kparts/componentfactory.h>
#include <ksimpleconfig.h>
#include <kstaticdeleter.h>
#include <kstandarddirs.h>
#include <kurl.h>

#include "kopeteplugin.h"

class KopeteLibraryInfo;

// Put the static deleter in its anonymous namespace
namespace
{
	KStaticDeleter<LibraryLoader> sd;
}

bool operator ==(const KopeteLibraryInfo &a, const KopeteLibraryInfo &b)
{
	// Feels like cheating, doesn't it?
	return a.specfile == b.specfile;
}

LibraryLoader* LibraryLoader::s_pluginLoader = 0L;

LibraryLoader* LibraryLoader::pluginLoader()
{
	if( !s_pluginLoader )
		sd.setObject( s_pluginLoader, new LibraryLoader() );

	return s_pluginLoader;
}

LibraryLoader::LibraryLoader()
: QObject( qApp )
{
}

LibraryLoader::~LibraryLoader()
{
	QDictIterator<KopetePlugin> i( mLibHash );
	while( i.current() )
	{
		// Remove causes the iterator to auto-increment, so
		// only increment explicitly when not removing
		if( getInfo( i.currentKey() ).type != QString::fromLatin1( "Kopete/Protocol" ) )
			remove( i.current() );
		else
			++i;
	}
	i.toFirst();
	while( i.current() )
		remove( i.current() );

	kdDebug(14010) << "LibraryLoader::~LibraryLoader(): all plugins removed" << endl;
}

QPtrList<KopetePlugin> LibraryLoader::plugins() const
{
	QPtrList<KopetePlugin> list;
	QDictIterator<KopetePlugin> i( mLibHash );
	for( ; i.current(); ++i )
		list.append( i.current() );

	return list;
}

QValueList<KopeteLibraryInfo> LibraryLoader::loaded() const
{
	QValueList<KopeteLibraryInfo> items;

	QDictIterator<KopetePlugin> i( mLibHash );
	for( ; i.current(); ++i )
	{
		if( mLibHash[ i.currentKey() ] )
			items.append( getInfo( i.currentKey() ) );
	}

	return items;
}

bool LibraryLoader::loadAll()
{
	KConfig *config=KGlobal::config();
	config->setGroup("");
	QStringList modules = config->readListEntry("Plugins");

	// Session management...
/*
	for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i)
	{
		KopeteLibraryInfo info=getInfo(*i);
		if (!info.type.contains("sm"))
			continue;
		loadPlugin( *i );
	}
*/
	// load all the protocols in the first
	for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i)
	{
		KopeteLibraryInfo info=getInfo(*i);
		if( !info.type.contains( QString::fromLatin1( "Kopete/Protocol" ) ) )
			continue;

		if ( !loadPlugin( *i ) )
			kdDebug(14010) << "[LibraryLoader] loading " << (*i) << " failed!" << endl;
	}

	// load all misc plugins
	for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i)
	{
		KopeteLibraryInfo info=getInfo(*i);
		if( !info.type.contains( QString::fromLatin1( "Kopete/Plugin" ) ) )
			continue;

		if ( !loadPlugin( *i ) )
			kdDebug(14010) << "[LibraryLoader] loading " << (*i) << " failed!" << endl;
	}

	return true;
}

KopeteLibraryInfo LibraryLoader::getInfo(const QString &spec) const
{
	QMap<QString, KopeteLibraryInfo>::iterator cached = m_cachedInfo.find(spec);
	if (cached != m_cachedInfo.end() )
		return *cached;

	KopeteLibraryInfo info;
	QString specPath = ( spec[ 0 ] == '/' ) ? spec : KGlobal::dirs()->findResource( "appdata", spec );
	if( !QFile::exists( specPath ) )
		return info;

	KSimpleConfig file( specPath );
	if( spec.find( '/' ) >= 0 )
		info.specfile = KURL( spec ).fileName();
	else
		info.specfile = spec;

	file.setGroup( QString::fromLatin1( "Desktop Entry" ) );

	info.filename = file.readEntry( "X-KDE-Library" );
	info.author   = file.readEntry( "X-Kopete-Author" );
	info.site     = file.readEntry( "X-Kopete-Site" );
	info.email    = file.readEntry( "X-Kopete-Email" );
	info.type     = file.readEntry( "ServiceTypes" );
	info.name     = file.readEntry( "Name" );
	info.comment  = file.readEntry( "Comment" );
	info.license  = file.readEntry( "X-Kopete-License" );
	info.icon     = file.readEntry( "Icon" );

	m_cachedInfo[ spec ] = info;
	return info;
}

bool LibraryLoader::isLoaded( const QString &spec ) const
{
	KopetePlugin *p = mLibHash[ spec ];
	return p;
}

void LibraryLoader::setModules(const QStringList &mods)
{
	KConfig *config=KGlobal::config();
	config->setGroup("");
	config->writeEntry("Plugins", mods);
	KGlobal::config()->sync();
}

QValueList<KopeteLibraryInfo> LibraryLoader::available() const
{
	QValueList<KopeteLibraryInfo> items;
	QStringList files = KGlobal::dirs()->findAllResources( "appdata", QString::fromLatin1( "*.desktop" ), false, true );
	for( QStringList::Iterator i=files.begin(); i!=files.end(); ++i )
		items.append(getInfo(*i));

	return items;
}

bool LibraryLoader::loadPlugin( const QString &spec )
{
	KopetePlugin *plugin = mLibHash[ spec ];
	if( !plugin )
	{
		KopeteLibraryInfo info = getInfo( spec );
		if( info.specfile != spec )
			return false;

		// Get the library loader instance
		KLibLoader *loader = KLibLoader::self();

		KLibrary *lib = loader->library( QFile::encodeName( info.filename) );
		if( !lib )
		{
			kdDebug(14010) << "LibraryLoader::loadPlugin: Error while loading plugin: " << loader->lastErrorMessage() << endl;
			return false;
		}
		plugin = KParts::ComponentFactory::createInstanceFromFactory<KopetePlugin> ( lib->factory(), this );
		mLibHash.insert( spec, plugin );

		connect( plugin, SIGNAL( destroyed( QObject * ) ),
			SLOT( slotPluginDestroyed( QObject * ) ) );

		// Automatically load the i18n catalogue for the plugin
		KGlobal::locale()->insertCatalogue( info.filename );

		plugin->init();

		m_addressBookFields.insert( plugin, plugin->addressBookFields() );

		kdDebug(14010) << "LibraryLoader::loadPlugin: Successfully loaded plugin '" << spec << "'."<< endl;
		emit pluginLoaded( plugin );
		return true;
	}
	else
	{
		kdDebug(14010) << "LibraryLoader::loadPlugin: Plugin '" << spec << "' is already loaded!" << endl;
		return false;
	}
}

bool LibraryLoader::remove( const QString &spec )
{
	KopetePlugin *plugin = mLibHash[ spec ];
	if( !plugin )
		return false;

	remove( plugin );
	return true;
}

bool LibraryLoader::remove( KopetePlugin *p )
{
	if( !p )
		return false;

	kdDebug(14010) << "LibraryLoader::remove: Removing plugin: " << p->pluginId() << endl;

	// Added by Duncan 20/01/2002
	// We need to call unload function for the plugin
	p->unload();
	delete p;

	return false;
}

void LibraryLoader::slotPluginDestroyed( QObject *o )
{
	m_addressBookFields.remove( static_cast<KopetePlugin *>( o ) );

	QDictIterator<KopetePlugin> it( mLibHash );
	for( ; it.current() ; ++it )
	{
		if( it.current() == o )
		{
			mLibHash.remove( it.currentKey() );
			break;
		}
	}

	// FIXME: Most likely most data structures here leak and are bound
	// to cause crashes. Find and identify those.
}

QStringList LibraryLoader::addressBookFields( KopetePlugin *p ) const
{
	if( m_addressBookFields.contains( p ) )
		return m_addressBookFields[ p ];
	else
		return QStringList();
}

KopetePlugin * LibraryLoader::searchByName(const QString &name)
{
	for( QDictIterator<KopetePlugin> i( mLibHash ); i.current(); ++i )
	{
		if (getInfo(i.currentKey()).name==name)
			return (*i);
	}
	return 0L;
}

KopetePlugin* LibraryLoader::searchByID( const QString &Id )
{
	QValueList<KopeteLibraryInfo> l = loaded();

	for ( QValueList<KopeteLibraryInfo>::Iterator i = l.begin(); i != l.end(); ++i )
	{
		KopetePlugin *tmp_plug = mLibHash[ ( *i ).specfile ];
		if( QString::fromLatin1( tmp_plug->pluginId() ) == Id )
			return tmp_plug;
	}
	return NULL;
}

QString LibraryLoader::pluginName(KopetePlugin *plugin)
{
	for( QDictIterator<KopetePlugin> i( mLibHash ); i.current(); ++i )
	{
		if (i.current() == plugin)
			return getInfo(i.currentKey()).name;
	}
	return QString::fromLatin1( "ERROR plugin unknown" );
}

QString LibraryLoader::pluginIcon( const QString &pluginId ) const
{
	QDictIterator<KopetePlugin> i( mLibHash );
	for( ; i.current(); ++i )
	{
		if( i.currentKey() == pluginId );
			return getInfo( i.currentKey() ).icon;
	}

	return QString::null;
}

#include <pluginloader.moc>

// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>Need to return success on deletion<commit_after>/*
    pluginloader.cpp - Kopete Plugin Loader

    Copyright (c) 2002      by Duncan Mac-Vicar Prett <duncan@kde.org>
    Copyright (c) 2002-2003 by Martijn Klingens       <klingens@kde.org>

    Portions of this code based in Noatun plugin code:
    Copyright (c) 2000-2002 The Noatun Developers

    Kopete    (c) 2002-2003 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include "pluginloader.h"

#include <qapplication.h>
#include <qdir.h>
#include <qfile.h>

#include <kdebug.h>
#include <kglobal.h>
#include <klocale.h>
#include <knotifyclient.h>
#include <kparts/componentfactory.h>
#include <ksimpleconfig.h>
#include <kstaticdeleter.h>
#include <kstandarddirs.h>
#include <kurl.h>

#include "kopeteplugin.h"

class KopeteLibraryInfo;

// Put the static deleter in its anonymous namespace
namespace
{
	KStaticDeleter<LibraryLoader> sd;
}

bool operator ==(const KopeteLibraryInfo &a, const KopeteLibraryInfo &b)
{
	// Feels like cheating, doesn't it?
	return a.specfile == b.specfile;
}

LibraryLoader* LibraryLoader::s_pluginLoader = 0L;

LibraryLoader* LibraryLoader::pluginLoader()
{
	if( !s_pluginLoader )
		sd.setObject( s_pluginLoader, new LibraryLoader() );

	return s_pluginLoader;
}

LibraryLoader::LibraryLoader()
: QObject( qApp )
{
}

LibraryLoader::~LibraryLoader()
{
	QDictIterator<KopetePlugin> i( mLibHash );
	while( i.current() )
	{
		// Remove causes the iterator to auto-increment, so
		// only increment explicitly when not removing
		if( getInfo( i.currentKey() ).type != QString::fromLatin1( "Kopete/Protocol" ) )
			remove( i.current() );
		else
			++i;
	}
	i.toFirst();
	while( i.current() )
		remove( i.current() );

	kdDebug(14010) << "LibraryLoader::~LibraryLoader(): all plugins removed" << endl;
}

QPtrList<KopetePlugin> LibraryLoader::plugins() const
{
	QPtrList<KopetePlugin> list;
	QDictIterator<KopetePlugin> i( mLibHash );
	for( ; i.current(); ++i )
		list.append( i.current() );

	return list;
}

QValueList<KopeteLibraryInfo> LibraryLoader::loaded() const
{
	QValueList<KopeteLibraryInfo> items;

	QDictIterator<KopetePlugin> i( mLibHash );
	for( ; i.current(); ++i )
	{
		if( mLibHash[ i.currentKey() ] )
			items.append( getInfo( i.currentKey() ) );
	}

	return items;
}

bool LibraryLoader::loadAll()
{
	KConfig *config=KGlobal::config();
	config->setGroup("");
	QStringList modules = config->readListEntry("Plugins");

	// Session management...
/*
	for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i)
	{
		KopeteLibraryInfo info=getInfo(*i);
		if (!info.type.contains("sm"))
			continue;
		loadPlugin( *i );
	}
*/
	// load all the protocols in the first
	for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i)
	{
		KopeteLibraryInfo info=getInfo(*i);
		if( !info.type.contains( QString::fromLatin1( "Kopete/Protocol" ) ) )
			continue;

		if ( !loadPlugin( *i ) )
			kdDebug(14010) << "[LibraryLoader] loading " << (*i) << " failed!" << endl;
	}

	// load all misc plugins
	for(QStringList::ConstIterator i=modules.begin(); i!=modules.end(); ++i)
	{
		KopeteLibraryInfo info=getInfo(*i);
		if( !info.type.contains( QString::fromLatin1( "Kopete/Plugin" ) ) )
			continue;

		if ( !loadPlugin( *i ) )
			kdDebug(14010) << "[LibraryLoader] loading " << (*i) << " failed!" << endl;
	}

	return true;
}

KopeteLibraryInfo LibraryLoader::getInfo(const QString &spec) const
{
	QMap<QString, KopeteLibraryInfo>::iterator cached = m_cachedInfo.find(spec);
	if (cached != m_cachedInfo.end() )
		return *cached;

	KopeteLibraryInfo info;
	QString specPath = ( spec[ 0 ] == '/' ) ? spec : KGlobal::dirs()->findResource( "appdata", spec );
	if( !QFile::exists( specPath ) )
		return info;

	KSimpleConfig file( specPath );
	if( spec.find( '/' ) >= 0 )
		info.specfile = KURL( spec ).fileName();
	else
		info.specfile = spec;

	file.setGroup( QString::fromLatin1( "Desktop Entry" ) );

	info.filename = file.readEntry( "X-KDE-Library" );
	info.author   = file.readEntry( "X-Kopete-Author" );
	info.site     = file.readEntry( "X-Kopete-Site" );
	info.email    = file.readEntry( "X-Kopete-Email" );
	info.type     = file.readEntry( "ServiceTypes" );
	info.name     = file.readEntry( "Name" );
	info.comment  = file.readEntry( "Comment" );
	info.license  = file.readEntry( "X-Kopete-License" );
	info.icon     = file.readEntry( "Icon" );

	m_cachedInfo[ spec ] = info;
	return info;
}

bool LibraryLoader::isLoaded( const QString &spec ) const
{
	KopetePlugin *p = mLibHash[ spec ];
	return p;
}

void LibraryLoader::setModules(const QStringList &mods)
{
	KConfig *config=KGlobal::config();
	config->setGroup("");
	config->writeEntry("Plugins", mods);
	KGlobal::config()->sync();
}

QValueList<KopeteLibraryInfo> LibraryLoader::available() const
{
	QValueList<KopeteLibraryInfo> items;
	QStringList files = KGlobal::dirs()->findAllResources( "appdata", QString::fromLatin1( "*.desktop" ), false, true );
	for( QStringList::Iterator i=files.begin(); i!=files.end(); ++i )
		items.append(getInfo(*i));

	return items;
}

bool LibraryLoader::loadPlugin( const QString &spec )
{
	KopetePlugin *plugin = mLibHash[ spec ];
	if( !plugin )
	{
		KopeteLibraryInfo info = getInfo( spec );
		if( info.specfile != spec )
			return false;

		// Get the library loader instance
		KLibLoader *loader = KLibLoader::self();

		KLibrary *lib = loader->library( QFile::encodeName( info.filename) );
		if( !lib )
		{
			kdDebug(14010) << "LibraryLoader::loadPlugin: Error while loading plugin: " << loader->lastErrorMessage() << endl;
			return false;
		}
		plugin = KParts::ComponentFactory::createInstanceFromFactory<KopetePlugin> ( lib->factory(), this );
		mLibHash.insert( spec, plugin );

		connect( plugin, SIGNAL( destroyed( QObject * ) ),
			SLOT( slotPluginDestroyed( QObject * ) ) );

		// Automatically load the i18n catalogue for the plugin
		KGlobal::locale()->insertCatalogue( info.filename );

		plugin->init();

		m_addressBookFields.insert( plugin, plugin->addressBookFields() );

		kdDebug(14010) << "LibraryLoader::loadPlugin: Successfully loaded plugin '" << spec << "'."<< endl;
		emit pluginLoaded( plugin );
		return true;
	}
	else
	{
		kdDebug(14010) << "LibraryLoader::loadPlugin: Plugin '" << spec << "' is already loaded!" << endl;
		return false;
	}
}

bool LibraryLoader::remove( const QString &spec )
{
	KopetePlugin *plugin = mLibHash[ spec ];
	if( !plugin )
		return false;

	remove( plugin );
	return true;
}

bool LibraryLoader::remove( KopetePlugin *p )
{
	if( !p )
		return false;

	kdDebug(14010) << "LibraryLoader::remove: Removing plugin: " << p->pluginId() << endl;

	// Added by Duncan 20/01/2002
	// We need to call unload function for the plugin
	p->unload();
	delete p;

	return true;
}

void LibraryLoader::slotPluginDestroyed( QObject *o )
{
	m_addressBookFields.remove( static_cast<KopetePlugin *>( o ) );

	QDictIterator<KopetePlugin> it( mLibHash );
	for( ; it.current() ; ++it )
	{
		if( it.current() == o )
		{
			mLibHash.remove( it.currentKey() );
			break;
		}
	}

	// FIXME: Most likely most data structures here leak and are bound
	// to cause crashes. Find and identify those.
}

QStringList LibraryLoader::addressBookFields( KopetePlugin *p ) const
{
	if( m_addressBookFields.contains( p ) )
		return m_addressBookFields[ p ];
	else
		return QStringList();
}

KopetePlugin * LibraryLoader::searchByName(const QString &name)
{
	for( QDictIterator<KopetePlugin> i( mLibHash ); i.current(); ++i )
	{
		if (getInfo(i.currentKey()).name==name)
			return (*i);
	}
	return 0L;
}

KopetePlugin* LibraryLoader::searchByID( const QString &Id )
{
	QValueList<KopeteLibraryInfo> l = loaded();

	for ( QValueList<KopeteLibraryInfo>::Iterator i = l.begin(); i != l.end(); ++i )
	{
		KopetePlugin *tmp_plug = mLibHash[ ( *i ).specfile ];
		if( QString::fromLatin1( tmp_plug->pluginId() ) == Id )
			return tmp_plug;
	}
	return NULL;
}

QString LibraryLoader::pluginName(KopetePlugin *plugin)
{
	for( QDictIterator<KopetePlugin> i( mLibHash ); i.current(); ++i )
	{
		if (i.current() == plugin)
			return getInfo(i.currentKey()).name;
	}
	return QString::fromLatin1( "ERROR plugin unknown" );
}

QString LibraryLoader::pluginIcon( const QString &pluginId ) const
{
	QDictIterator<KopetePlugin> i( mLibHash );
	for( ; i.current(); ++i )
	{
		if( i.currentKey() == pluginId );
			return getInfo( i.currentKey() ).icon;
	}

	return QString::null;
}

#include <pluginloader.moc>

// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file ExternalLexer.cxx
 ** Support external lexers in DLLs.
 **/
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

#define _WIN32_WINNT  0x0400
#include <windows.h>

#include "Platform.h"
#include "SciLexer.h"
#include "PropSet.h"
#include "Accessor.h"
#include "DocumentAccessor.h"
#include "KeyWords.h"
#include "ExternalLexer.h"

// Initialise the static vars...
int LexerManager::UseCount = 0;
LexerLibrary *LexerManager::first = NULL;
LexerLibrary *LexerManager::last = NULL;
LexerManager *LexerManager::firstlm = NULL;

//------------------------------------------
//
// ExternalLexerModule
//
//------------------------------------------

char **WordListsToStrings(WordList *val[]) {
	int dim = 0;
	while (val[dim])
		dim++;
	char **wls = new char * [dim + 1];
	for (int i = 0;i < dim;i++) {
		SString words;
		words = "";
		for (int n = 0; n < val[i]->len; n++) {
			words += val[i]->words[n];
			if (n != val[i]->len - 1)
				words += " ";
		}
		wls[i] = new char[words.length() + 1];
		strcpy(wls[i], words.c_str());
	}
	wls[dim] = 0;
	return wls;
}

void DeleteWLStrings(char *strs[]) {
	int dim = 0;
	while (strs[dim]) {
		delete strs[dim];
		dim++;
	}
	delete [] strs;
}

void ExternalLexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
                              WordList *keywordlists[], Accessor &styler) {
	if (!fneLexer)
		return ;

	char **kwds = WordListsToStrings(keywordlists);
	char *ps = styler.GetProperties();

	// The accessor passed in is always a DocumentAccessor so this cast and the subsequent
	// access will work. Can not use the stricter dynamic_cast as that requires RTTI.
	DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
	WindowID wID = da.GetWindow();

	fneLexer(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);

	delete ps;
	DeleteWLStrings(kwds);
}

void ExternalLexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
                               WordList *keywordlists[], Accessor &styler) {
	if (!fneFolder)
		return ;

	char **kwds = WordListsToStrings(keywordlists);
	char *ps = styler.GetProperties();

	// The accessor passed in is always a DocumentAccessor so this cast and the subsequent
	// access will work. Can not use the stricter dynamic_cast as that requires RTTI.
	DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
	WindowID wID = da.GetWindow();

	fneFolder(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);

	delete ps;
	DeleteWLStrings(kwds);
}

void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index) {
	fneLexer = fLexer;
	fneFolder = fFolder;
	externalLanguage = index;
}

//------------------------------------------
//
// LexerLibrary
//
//------------------------------------------

LexerLibrary::LexerLibrary(LPCTSTR ModuleName) {
	// Initialise some members...
	first = NULL;
	last = NULL;

	// Load the DLL
	m_hModule = LoadLibrary(ModuleName);
	if (m_hModule) {
		m_sModuleName = ModuleName;
		GetLexerCountFn GetLexerCount = (GetLexerCountFn)GetProcAddress(m_hModule, "GetLexerCount");

		if (GetLexerCount) {
			ExternalLexerModule *lex;
			LexerMinder *lm;

			// Find functions in the DLL
			GetLexerNameFn GetLexerName = (GetLexerNameFn)GetProcAddress(m_hModule, "GetLexerName");
			ExtLexerFunction Lexer = (ExtLexerFunction)GetProcAddress(m_hModule, "Lex");
			ExtFoldFunction Folder = (ExtFoldFunction)GetProcAddress(m_hModule, "Fold");

			// Assign a buffer for the lexer name.
			char lexname[100];
			strcpy(lexname, "");

			int nl = GetLexerCount();

			for (int i = 0; i < nl; i++) {
				GetLexerName(i, lexname, 100);
				lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);

				// Create a LexerMinder so we don't leak the ExternalLexerModule...
				lm = new LexerMinder;
				lm->self = lex;
				lm->next = NULL;
				if (first != NULL) {
					last->next = lm;
					last = lm;
				} else {
					first = lm;
					last = lm;
				}

				// The external lexer needs to know how to call into its DLL to
				// do its lexing and folding, we tell it here. Folder may be null.
				lex->SetExternal(Lexer, Folder, i);

			}
		}
	}
	next = NULL;
}

LexerLibrary::~LexerLibrary() {
	Release();
}

void LexerLibrary::Release() {
	//TODO maintain a list of lexers created, and delete them!
	LexerMinder *lm;
	LexerMinder *next;
	lm = first;
	while (NULL != lm) {
		next = lm->next;
		delete lm->self;
		delete lm;
		lm = next;
	}

	first = NULL;
	last = NULL;

	// Release the DLL
	if (NULL != m_hModule) {
		FreeLibrary(m_hModule);
	}
}

//------------------------------------------
//
// LexerManager
//
//------------------------------------------

int FindLastSlash(char *inp) {
	int i;
	int ret = -1;
	for (i = strlen(inp) - 1; i >= 0; i--) {
		if (inp[i] == '\\' || inp[i] == '/') {
			// if you don't like break:
			/*
			if (ret == -1)
			*/
			ret = i;
			break;
		}
	}
	return ret;
}

LexerManager::LexerManager() {

	UseCount++;
	if (1 == UseCount) {
		firstlm = this;
		m_bLoaded = false;
	}
}

void LexerManager::EnumerateLexers() {
	HANDLE hFind;
	WIN32_FIND_DATA FindFileData;

	char path[MAX_PATH + 1];

	GetModuleFileName(GetModuleHandle(NULL), path, MAX_PATH);

	int i = FindLastSlash(path);

	if (i == -1)
		i = strlen(path);

	SString sPath(path, 0, i);

	// Ensure a trailing slash...
	if ( sPath[sPath.size() - 1] != '/' && sPath[sPath.size() - 1] != '\\' ) {
		sPath += '\\';
	}

	SString sPattern(sPath);

	sPattern.append("*.lexer");

	hFind = FindFirstFile(sPattern.c_str(), &FindFileData);
	if (hFind != INVALID_HANDLE_VALUE) {
		//Found the first file...
		BOOL found = TRUE;
		SString to_open;

		while (found) {
			to_open = sPath;
			to_open += FindFileData.cFileName;
			LexerLibrary *lib = new LexerLibrary(to_open.c_str());
			if (NULL != first) {
				last->next = lib;
				last = lib;
			} else {
				first = lib;
				last = lib;
			}
			found = FindNextFile(hFind, &FindFileData);
		}

		FindClose(hFind);

	}
}

LexerManager::~LexerManager() {
	// If this is the last LexerManager to be freed then
	// we delete all of our LexerLibrarys.
	UseCount--;
	if (0 == UseCount) {
		if (NULL != first) {
			LexerLibrary *cur = first;
			LexerLibrary *next = first->next;
			while (cur) {
				delete cur;
				cur = next;
			}
			first = NULL;
			last = NULL;
		}
	}
	if (this == firstlm)
		firstlm = NULL;
}

void LexerManager::Load()
{
	if(!m_bLoaded)
	{
		m_bLoaded = true;
		EnumerateLexers();
	}
}

// Return a LexerManager, or create one and then return it.
LexerManager *LexerManager::GetInstance() {
	if(!firstlm)
		firstlm = new LexerManager;
	return firstlm;
}

LMMinder::~LMMinder()
{
	LexerManager *rem = LexerManager::firstlm;
	if(rem)
		delete rem;
}

LMMinder minder;
<commit_msg>Changed append method to +=.<commit_after>// Scintilla source code edit control
/** @file ExternalLexer.cxx
 ** Support external lexers in DLLs.
 **/
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

#define _WIN32_WINNT  0x0400
#include <windows.h>

#include "Platform.h"
#include "SciLexer.h"
#include "PropSet.h"
#include "Accessor.h"
#include "DocumentAccessor.h"
#include "KeyWords.h"
#include "ExternalLexer.h"

// Initialise the static vars...
int LexerManager::UseCount = 0;
LexerLibrary *LexerManager::first = NULL;
LexerLibrary *LexerManager::last = NULL;
LexerManager *LexerManager::firstlm = NULL;

//------------------------------------------
//
// ExternalLexerModule
//
//------------------------------------------

char **WordListsToStrings(WordList *val[]) {
	int dim = 0;
	while (val[dim])
		dim++;
	char **wls = new char * [dim + 1];
	for (int i = 0;i < dim;i++) {
		SString words;
		words = "";
		for (int n = 0; n < val[i]->len; n++) {
			words += val[i]->words[n];
			if (n != val[i]->len - 1)
				words += " ";
		}
		wls[i] = new char[words.length() + 1];
		strcpy(wls[i], words.c_str());
	}
	wls[dim] = 0;
	return wls;
}

void DeleteWLStrings(char *strs[]) {
	int dim = 0;
	while (strs[dim]) {
		delete strs[dim];
		dim++;
	}
	delete [] strs;
}

void ExternalLexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
                              WordList *keywordlists[], Accessor &styler) {
	if (!fneLexer)
		return ;

	char **kwds = WordListsToStrings(keywordlists);
	char *ps = styler.GetProperties();

	// The accessor passed in is always a DocumentAccessor so this cast and the subsequent
	// access will work. Can not use the stricter dynamic_cast as that requires RTTI.
	DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
	WindowID wID = da.GetWindow();

	fneLexer(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);

	delete ps;
	DeleteWLStrings(kwds);
}

void ExternalLexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
                               WordList *keywordlists[], Accessor &styler) {
	if (!fneFolder)
		return ;

	char **kwds = WordListsToStrings(keywordlists);
	char *ps = styler.GetProperties();

	// The accessor passed in is always a DocumentAccessor so this cast and the subsequent
	// access will work. Can not use the stricter dynamic_cast as that requires RTTI.
	DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
	WindowID wID = da.GetWindow();

	fneFolder(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);

	delete ps;
	DeleteWLStrings(kwds);
}

void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index) {
	fneLexer = fLexer;
	fneFolder = fFolder;
	externalLanguage = index;
}

//------------------------------------------
//
// LexerLibrary
//
//------------------------------------------

LexerLibrary::LexerLibrary(LPCTSTR ModuleName) {
	// Initialise some members...
	first = NULL;
	last = NULL;

	// Load the DLL
	m_hModule = LoadLibrary(ModuleName);
	if (m_hModule) {
		m_sModuleName = ModuleName;
		GetLexerCountFn GetLexerCount = (GetLexerCountFn)GetProcAddress(m_hModule, "GetLexerCount");

		if (GetLexerCount) {
			ExternalLexerModule *lex;
			LexerMinder *lm;

			// Find functions in the DLL
			GetLexerNameFn GetLexerName = (GetLexerNameFn)GetProcAddress(m_hModule, "GetLexerName");
			ExtLexerFunction Lexer = (ExtLexerFunction)GetProcAddress(m_hModule, "Lex");
			ExtFoldFunction Folder = (ExtFoldFunction)GetProcAddress(m_hModule, "Fold");

			// Assign a buffer for the lexer name.
			char lexname[100];
			strcpy(lexname, "");

			int nl = GetLexerCount();

			for (int i = 0; i < nl; i++) {
				GetLexerName(i, lexname, 100);
				lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);

				// Create a LexerMinder so we don't leak the ExternalLexerModule...
				lm = new LexerMinder;
				lm->self = lex;
				lm->next = NULL;
				if (first != NULL) {
					last->next = lm;
					last = lm;
				} else {
					first = lm;
					last = lm;
				}

				// The external lexer needs to know how to call into its DLL to
				// do its lexing and folding, we tell it here. Folder may be null.
				lex->SetExternal(Lexer, Folder, i);

			}
		}
	}
	next = NULL;
}

LexerLibrary::~LexerLibrary() {
	Release();
}

void LexerLibrary::Release() {
	//TODO maintain a list of lexers created, and delete them!
	LexerMinder *lm;
	LexerMinder *next;
	lm = first;
	while (NULL != lm) {
		next = lm->next;
		delete lm->self;
		delete lm;
		lm = next;
	}

	first = NULL;
	last = NULL;

	// Release the DLL
	if (NULL != m_hModule) {
		FreeLibrary(m_hModule);
	}
}

//------------------------------------------
//
// LexerManager
//
//------------------------------------------

int FindLastSlash(char *inp) {
	int i;
	int ret = -1;
	for (i = strlen(inp) - 1; i >= 0; i--) {
		if (inp[i] == '\\' || inp[i] == '/') {
			// if you don't like break:
			/*
			if (ret == -1)
			*/
			ret = i;
			break;
		}
	}
	return ret;
}

LexerManager::LexerManager() {

	UseCount++;
	if (1 == UseCount) {
		firstlm = this;
		m_bLoaded = false;
	}
}

void LexerManager::EnumerateLexers() {
	HANDLE hFind;
	WIN32_FIND_DATA FindFileData;

	char path[MAX_PATH + 1];

	GetModuleFileName(GetModuleHandle(NULL), path, MAX_PATH);

	int i = FindLastSlash(path);

	if (i == -1)
		i = strlen(path);

	SString sPath(path, 0, i);

	// Ensure a trailing slash...
	if ( sPath[sPath.size() - 1] != '/' && sPath[sPath.size() - 1] != '\\' ) {
		sPath += '\\';
	}

	SString sPattern(sPath);
	sPattern += "*.lexer";

	hFind = FindFirstFile(sPattern.c_str(), &FindFileData);
	if (hFind != INVALID_HANDLE_VALUE) {
		//Found the first file...
		BOOL found = TRUE;
		SString to_open;

		while (found) {
			to_open = sPath;
			to_open += FindFileData.cFileName;
			LexerLibrary *lib = new LexerLibrary(to_open.c_str());
			if (NULL != first) {
				last->next = lib;
				last = lib;
			} else {
				first = lib;
				last = lib;
			}
			found = FindNextFile(hFind, &FindFileData);
		}

		FindClose(hFind);

	}
}

LexerManager::~LexerManager() {
	// If this is the last LexerManager to be freed then
	// we delete all of our LexerLibrarys.
	UseCount--;
	if (0 == UseCount) {
		if (NULL != first) {
			LexerLibrary *cur = first;
			LexerLibrary *next = first->next;
			while (cur) {
				delete cur;
				cur = next;
			}
			first = NULL;
			last = NULL;
		}
	}
	if (this == firstlm)
		firstlm = NULL;
}

void LexerManager::Load()
{
	if(!m_bLoaded)
	{
		m_bLoaded = true;
		EnumerateLexers();
	}
}

// Return a LexerManager, or create one and then return it.
LexerManager *LexerManager::GetInstance() {
	if(!firstlm)
		firstlm = new LexerManager;
	return firstlm;
}

LMMinder::~LMMinder()
{
	LexerManager *rem = LexerManager::firstlm;
	if(rem)
		delete rem;
}

LMMinder minder;
<|endoftext|>