<commit_before>#include "syscall_model.h"
#include "sys/syscall.h"
#include "chip.h"
#include "transport.h"

SyscallMdl::SyscallMdl(Network *net)
  : called_enter(false),
    ret_val(0),
    the_network(net)
{
}

void SyscallMdl::runExit(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{
   //if only the code below worked in enter...
   //int return_addr = PIN_GetContextReg(ctx, REG_INST_PTR);
   //return_addr += 2;
   //PIN_SetContextReg(ctx, REG_INST_PTR, return_addr);
   //PIN_ExecuteAt(ctx);

   if(called_enter)
   {
      PIN_SetContextReg(ctx, REG_EAX, ret_val);
      called_enter = false;
   }
}

void SyscallMdl::runEnter(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{
   // Reset the buffers for the new transmission
   recv_buff.clear();
   send_buff.clear();

   int msg_type = MCP_MESSAGE_SYS_CALL;

   int commid;
   commRank(&commid);
   assert( commid >= 0 );

   UInt8 syscall_number = (UInt8) PIN_GetSyscallNumber(ctx, syscall_standard);

   send_buff << msg_type << commid << syscall_number;

   switch(syscall_number)
   {
      case SYS_open:
      {
         char *path = (char *)PIN_GetSyscallArgument(ctx, syscall_standard, 0);
         if(!strcmp(path,"./common/tests/file_io/input"))
         {
            called_enter = true;
            ret_val = marshallOpenCall(ctx, syscall_standard);
         }
         break;
      }
      case SYS_read:
      {
         int fd = PIN_GetSyscallArgument(ctx, syscall_standard, 0);
         if ( fd == 0x08 )
         {
            called_enter = true;
            ret_val = marshallReadCall(ctx, syscall_standard);
         }
         break;
      }

      case SYS_write:
      {
         int fd = PIN_GetSyscallArgument(ctx, syscall_standard, 0);
         if ( fd == 0x08 )
         {
            called_enter = true;
            ret_val = marshallWriteCall(ctx, syscall_standard);
         }
         break;
      }
      case SYS_close:
      {
         int fd = PIN_GetSyscallArgument(ctx, syscall_standard, 0);
         if ( fd == 0x08 )
         {
            called_enter = true;
            ret_val = marshallCloseCall(ctx, syscall_standard);
         }
         break;
      }
      case SYS_access:
         called_enter = true;
         ret_val = marshallAccessCall(ctx, syscall_standard);
         break;

      // case SYS_exit:
      //    cerr << "exit()" << endl;
      //    break;
      case -1:
         break;
      default:
         //         cerr << "SysCall: " << (int)syscall_number << endl;
         break;
   }

   if(called_enter)
      PIN_SetSyscallNumber(ctx, syscall_standard, SYS_getpid);

}

int SyscallMdl::marshallOpenCall(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{
   /*
       Syscall Args
       const char *pathname, int flags

       Transmit Protocol

       Field               Type
       -----------------|--------
       LEN_FNAME           UInt32
       FILE_NAME           char[]
       STATUS_FLAGS        int

       Receive Protocol

       Field               Type
       -----------------|--------
       STATUS              int

   */

   //cerr << "Entering SyscallMdl::marshallOpen()" << endl;

   char *path = (char *) PIN_GetSyscallArgument(ctx, syscall_standard, 0);
   int flags = (int) PIN_GetSyscallArgument(ctx, syscall_standard, 1);
   UInt32 len_fname = strlen(path) + 1;

   cerr << "open(" << path << ")" << endl;

   send_buff << len_fname << make_pair(path, len_fname) << flags;
   the_network->getTransport()->ptSendToMCP((UInt8 *) send_buff.getBuffer(), send_buff.size());

   UInt32 length = 0;
   UInt8 *res_buff = the_network->getTransport()->ptRecvFromMCP(&length);
   assert( length == sizeof(int) );
   recv_buff << make_pair(res_buff, length);

   int status;
   recv_buff >> status;

   return status;
}

int SyscallMdl::marshallReadCall(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{

   /*
       Syscall Args
       int fd, void *buf, size_t count

       Transmit

       Field               Type
       -----------------|--------
       FILE_DESCRIPTOR     int
       COUNT               size_t

       Receive

       Field               Type
       -----------------|--------
       BYTES               int
       BUFFER              void *

   */

   //cerr << "Entering syscall model marshall read" << endl;

   int fd = (int) PIN_GetSyscallArgument(ctx, syscall_standard, 0);
   void *buf = (void *) PIN_GetSyscallArgument(ctx, syscall_standard, 1);
   size_t count = (size_t) PIN_GetSyscallArgument(ctx, syscall_standard, 2);

   cerr << "read(" << fd << hex << ", " << buf << dec << ", " << count << ")" << endl;

   send_buff << fd << count;
   the_network->getTransport()->ptSendToMCP((UInt8 *) send_buff.getBuffer(), send_buff.size());

   //cerr << "sent to mcp " << send_buff.size() << " bytes" << endl;

   UInt32 length = 0;
   UInt8 *res_buff = the_network->getTransport()->ptRecvFromMCP(&length);
   //cerr << "received from mcp" << endl;

   assert( length >= sizeof(int) );
   recv_buff << make_pair(res_buff, length);

   int bytes;
   recv_buff >> bytes;

   if ( bytes != -1 )
   {
      recv_buff >> make_pair(buf, bytes);
   }
   else
   {
      assert( recv_buff.size() == 0 );
   }
   //cerr << "Exiting syscall model marshall read" << endl;

   return bytes;
}

int SyscallMdl::marshallWriteCall(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{
   /*
       Syscall Args
       int fd, void *buf, size_t count

       Transmit

       Field               Type
       -----------------|--------
       FILE_DESCRIPTOR     int
       COUNT               size_t
       BUFFER              char[]

       Receive

       Field               Type
       -----------------|--------
       BYTES               int

   */

   //cerr << "Entering syscall model marshall write" << endl;

   int fd = (int) PIN_GetSyscallArgument(ctx, syscall_standard, 0);
   void *buf = (void *) PIN_GetSyscallArgument(ctx, syscall_standard, 1);
   size_t count = (size_t) PIN_GetSyscallArgument(ctx, syscall_standard, 2);

   cerr << "write(" << fd << hex << ", " << buf << dec << ", " << count << ")" << endl;

   send_buff << fd << count << make_pair(buf, count);
   the_network->getTransport()->ptSendToMCP((UInt8 *) send_buff.getBuffer(), send_buff.size());

   UInt32 length = 0;
   UInt8 *res_buff = the_network->getTransport()->ptRecvFromMCP(&length);
   assert( length == sizeof(int) );
   recv_buff << make_pair(res_buff, length);

   int status;
   recv_buff >> status;

   return status;
}

int SyscallMdl::marshallCloseCall(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{
   /*
       Syscall Args
       int fd, void *buf, size_t count

       Transmit

       Field               Type
       -----------------|--------
       FILE_DESCRIPTOR     int

       Receive

       Field               Type
       -----------------|--------
       STATUS              int

   */

   //cerr << "Entering syscall model marshall close" << endl;

   int fd = (int) PIN_GetSyscallArgument(ctx, syscall_standard, 0);

   cerr << "close(" << fd  << ")" << endl;

   send_buff << fd;
   the_network->getTransport()->ptSendToMCP((UInt8 *) send_buff.getBuffer(), send_buff.size());

   UInt32 length = 0;
   UInt8 *res_buff = the_network->getTransport()->ptRecvFromMCP(&length);
   assert( length == sizeof(int) );
   recv_buff << make_pair(res_buff, length);

   int status;
   recv_buff >> status;

   return status;
}

int SyscallMdl::marshallAccessCall(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{
   //cerr << "Entering SyscallMdl::marshallAccessCall()" << endl;

   char *path = (char *)PIN_GetSyscallArgument(ctx, syscall_standard, 0);
   int mode = (int)PIN_GetSyscallArgument(ctx, syscall_standard, 1);
   UInt32 len_fname = strlen(path) + 1;

   // pack the data
   send_buff << len_fname << make_pair(path, len_fname) << mode;

   // send the data
   the_network->getTransport()->ptSendToMCP((UInt8 *) send_buff.getBuffer(), send_buff.size());

   // get a result
   UInt32 length;
   UInt8 *res_buff = the_network->getTransport()->ptRecvFromMCP(&length);

   // Create a buffer out of the result
   recv_buff << make_pair(res_buff, length);

   // return the result
   int result;
   recv_buff >> result;
   return result;
}

<commit_msg>(syscall) Use RAX if running on x86-64.<commit_after>#include "syscall_model.h"
#include "sys/syscall.h"
#include "chip.h"
#include "transport.h"

SyscallMdl::SyscallMdl(Network *net)
  : called_enter(false),
    ret_val(0),
    the_network(net)
{
}

void SyscallMdl::runExit(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{
   //if only the code below worked in enter...
   //int return_addr = PIN_GetContextReg(ctx, REG_INST_PTR);
   //return_addr += 2;
   //PIN_SetContextReg(ctx, REG_INST_PTR, return_addr);
   //PIN_ExecuteAt(ctx);

   if(called_enter)
   {
#ifdef TARGET_IA32E
      PIN_SetContextReg(ctx, REG_RAX, ret_val);
#else
      PIN_SetContextReg(ctx, REG_EAX, ret_val);
#endif
      called_enter = false;
   }
}

void SyscallMdl::runEnter(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{
   // Reset the buffers for the new transmission
   recv_buff.clear();
   send_buff.clear();

   int msg_type = MCP_MESSAGE_SYS_CALL;

   int commid;
   commRank(&commid);
   assert( commid >= 0 );

   UInt8 syscall_number = (UInt8) PIN_GetSyscallNumber(ctx, syscall_standard);

   send_buff << msg_type << commid << syscall_number;

   switch(syscall_number)
   {
      case SYS_open:
      {
         char *path = (char *)PIN_GetSyscallArgument(ctx, syscall_standard, 0);
         if(!strcmp(path,"./common/tests/file_io/input"))
         {
            called_enter = true;
            ret_val = marshallOpenCall(ctx, syscall_standard);
         }
         break;
      }
      case SYS_read:
      {
         int fd = PIN_GetSyscallArgument(ctx, syscall_standard, 0);
         if ( fd == 0x08 )
         {
            called_enter = true;
            ret_val = marshallReadCall(ctx, syscall_standard);
         }
         break;
      }

      case SYS_write:
      {
         int fd = PIN_GetSyscallArgument(ctx, syscall_standard, 0);
         if ( fd == 0x08 )
         {
            called_enter = true;
            ret_val = marshallWriteCall(ctx, syscall_standard);
         }
         break;
      }
      case SYS_close:
      {
         int fd = PIN_GetSyscallArgument(ctx, syscall_standard, 0);
         if ( fd == 0x08 )
         {
            called_enter = true;
            ret_val = marshallCloseCall(ctx, syscall_standard);
         }
         break;
      }
      case SYS_access:
         called_enter = true;
         ret_val = marshallAccessCall(ctx, syscall_standard);
         break;

      // case SYS_exit:
      //    cerr << "exit()" << endl;
      //    break;
      case -1:
         break;
      default:
         //         cerr << "SysCall: " << (int)syscall_number << endl;
         break;
   }

   if(called_enter)
      PIN_SetSyscallNumber(ctx, syscall_standard, SYS_getpid);

}

int SyscallMdl::marshallOpenCall(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{
   /*
       Syscall Args
       const char *pathname, int flags

       Transmit Protocol

       Field               Type
       -----------------|--------
       LEN_FNAME           UInt32
       FILE_NAME           char[]
       STATUS_FLAGS        int

       Receive Protocol

       Field               Type
       -----------------|--------
       STATUS              int

   */

   //cerr << "Entering SyscallMdl::marshallOpen()" << endl;

   char *path = (char *) PIN_GetSyscallArgument(ctx, syscall_standard, 0);
   int flags = (int) PIN_GetSyscallArgument(ctx, syscall_standard, 1);
   UInt32 len_fname = strlen(path) + 1;

   cerr << "open(" << path << ")" << endl;

   send_buff << len_fname << make_pair(path, len_fname) << flags;
   the_network->getTransport()->ptSendToMCP((UInt8 *) send_buff.getBuffer(), send_buff.size());

   UInt32 length = 0;
   UInt8 *res_buff = the_network->getTransport()->ptRecvFromMCP(&length);
   assert( length == sizeof(int) );
   recv_buff << make_pair(res_buff, length);

   int status;
   recv_buff >> status;

   return status;
}

int SyscallMdl::marshallReadCall(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{

   /*
       Syscall Args
       int fd, void *buf, size_t count

       Transmit

       Field               Type
       -----------------|--------
       FILE_DESCRIPTOR     int
       COUNT               size_t

       Receive

       Field               Type
       -----------------|--------
       BYTES               int
       BUFFER              void *

   */

   //cerr << "Entering syscall model marshall read" << endl;

   int fd = (int) PIN_GetSyscallArgument(ctx, syscall_standard, 0);
   void *buf = (void *) PIN_GetSyscallArgument(ctx, syscall_standard, 1);
   size_t count = (size_t) PIN_GetSyscallArgument(ctx, syscall_standard, 2);

   cerr << "read(" << fd << hex << ", " << buf << dec << ", " << count << ")" << endl;

   send_buff << fd << count;
   the_network->getTransport()->ptSendToMCP((UInt8 *) send_buff.getBuffer(), send_buff.size());

   //cerr << "sent to mcp " << send_buff.size() << " bytes" << endl;

   UInt32 length = 0;
   UInt8 *res_buff = the_network->getTransport()->ptRecvFromMCP(&length);
   //cerr << "received from mcp" << endl;

   assert( length >= sizeof(int) );
   recv_buff << make_pair(res_buff, length);

   int bytes;
   recv_buff >> bytes;

   if ( bytes != -1 )
   {
      recv_buff >> make_pair(buf, bytes);
   }
   else
   {
      assert( recv_buff.size() == 0 );
   }
   //cerr << "Exiting syscall model marshall read" << endl;

   return bytes;
}

int SyscallMdl::marshallWriteCall(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{
   /*
       Syscall Args
       int fd, void *buf, size_t count

       Transmit

       Field               Type
       -----------------|--------
       FILE_DESCRIPTOR     int
       COUNT               size_t
       BUFFER              char[]

       Receive

       Field               Type
       -----------------|--------
       BYTES               int

   */

   //cerr << "Entering syscall model marshall write" << endl;

   int fd = (int) PIN_GetSyscallArgument(ctx, syscall_standard, 0);
   void *buf = (void *) PIN_GetSyscallArgument(ctx, syscall_standard, 1);
   size_t count = (size_t) PIN_GetSyscallArgument(ctx, syscall_standard, 2);

   cerr << "write(" << fd << hex << ", " << buf << dec << ", " << count << ")" << endl;

   send_buff << fd << count << make_pair(buf, count);
   the_network->getTransport()->ptSendToMCP((UInt8 *) send_buff.getBuffer(), send_buff.size());

   UInt32 length = 0;
   UInt8 *res_buff = the_network->getTransport()->ptRecvFromMCP(&length);
   assert( length == sizeof(int) );
   recv_buff << make_pair(res_buff, length);

   int status;
   recv_buff >> status;

   return status;
}

int SyscallMdl::marshallCloseCall(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{
   /*
       Syscall Args
       int fd, void *buf, size_t count

       Transmit

       Field               Type
       -----------------|--------
       FILE_DESCRIPTOR     int

       Receive

       Field               Type
       -----------------|--------
       STATUS              int

   */

   //cerr << "Entering syscall model marshall close" << endl;

   int fd = (int) PIN_GetSyscallArgument(ctx, syscall_standard, 0);

   cerr << "close(" << fd  << ")" << endl;

   send_buff << fd;
   the_network->getTransport()->ptSendToMCP((UInt8 *) send_buff.getBuffer(), send_buff.size());

   UInt32 length = 0;
   UInt8 *res_buff = the_network->getTransport()->ptRecvFromMCP(&length);
   assert( length == sizeof(int) );
   recv_buff << make_pair(res_buff, length);

   int status;
   recv_buff >> status;

   return status;
}

int SyscallMdl::marshallAccessCall(CONTEXT *ctx, SYSCALL_STANDARD syscall_standard)
{
   //cerr << "Entering SyscallMdl::marshallAccessCall()" << endl;

   char *path = (char *)PIN_GetSyscallArgument(ctx, syscall_standard, 0);
   int mode = (int)PIN_GetSyscallArgument(ctx, syscall_standard, 1);
   UInt32 len_fname = strlen(path) + 1;

   // pack the data
   send_buff << len_fname << make_pair(path, len_fname) << mode;

   // send the data
   the_network->getTransport()->ptSendToMCP((UInt8 *) send_buff.getBuffer(), send_buff.size());

   // get a result
   UInt32 length;
   UInt8 *res_buff = the_network->getTransport()->ptRecvFromMCP(&length);

   // Create a buffer out of the result
   recv_buff << make_pair(res_buff, length);

   // return the result
   int result;
   recv_buff >> result;
   return result;
}

<|endoftext|>


<commit_before>#pragma once

#include "SDL.h"
#include <string>
#include <vector>

namespace Oddlib
{
    class IStream;

    class Path
    {
    public:
        Path(const Path&) = delete;
        Path& operator = (const Path&) = delete;
        Path(IStream& pathChunkStream,
             Uint32 collisionDataOffset,
             Uint32 objectIndexTableOffset,
             Uint32 objectDataOffset,
             Uint32 mapXSize,
             Uint32 mapYSize);

        Uint32 XSize() const;
        Uint32 YSize() const;
        const std::string& CameraFileName(Uint32 x, Uint32 y) const;
    private:
        Uint32 mXSize = 0;
        Uint32 mYSize = 0;

        void ReadCameraMap(IStream& stream);

        struct CollisionItem
        {
            Uint16 mX1;
            Uint16 mY1;
            Uint16 mX2;
            Uint16 mY2;
            Uint16 mType;
            // TODO Actually contains links to previous/next collision
            // item link depending on the type and the line length
            Uint16 mUnknown[5];
        };

        void ReadCollisionItems(IStream& stream, Uint32 numberOfCollisionItems);

        std::vector<std::string> mCameras;

        std::vector<CollisionItem> mCollisionItems;
    };
}<commit_msg>check size of structure is correct at build time<commit_after>#pragma once

#include "SDL.h"
#include <string>
#include <vector>

namespace Oddlib
{
    class IStream;

    class Path
    {
    public:
        Path(const Path&) = delete;
        Path& operator = (const Path&) = delete;
        Path(IStream& pathChunkStream,
             Uint32 collisionDataOffset,
             Uint32 objectIndexTableOffset,
             Uint32 objectDataOffset,
             Uint32 mapXSize,
             Uint32 mapYSize);

        Uint32 XSize() const;
        Uint32 YSize() const;
        const std::string& CameraFileName(Uint32 x, Uint32 y) const;
    private:
        Uint32 mXSize = 0;
        Uint32 mYSize = 0;

        void ReadCameraMap(IStream& stream);

        struct CollisionItem
        {
            Uint16 mX1;
            Uint16 mY1;
            Uint16 mX2;
            Uint16 mY2;
            Uint16 mType;
            // TODO Actually contains links to previous/next collision
            // item link depending on the type and the line length
            Uint16 mUnknown[5];
        };
        static_assert(sizeof(CollisionItem) == 20, "Wrong collision item size");

        void ReadCollisionItems(IStream& stream, Uint32 numberOfCollisionItems);

        std::vector<std::string> mCameras;

        std::vector<CollisionItem> mCollisionItems;
    };
}<|endoftext|>


<commit_before>/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "systemc/core/event.hh"

#include <algorithm>
#include <cstring>
#include <utility>

#include "base/logging.hh"
#include "sim/core.hh"
#include "systemc/core/module.hh"
#include "systemc/core/scheduler.hh"

namespace sc_gem5
{

Event::Event(sc_core::sc_event *_sc_event) : Event(_sc_event, "") {}

Event::Event(sc_core::sc_event *_sc_event, const char *_basename) :
    _sc_event(_sc_event), _basename(_basename),
    delayedNotify([this]() { this->notify(); })
{
    Module *p = currentModule();

    if (p)
        parent = p->obj()->sc_obj();
    else if (scheduler.current())
        parent = scheduler.current();
    else
        parent = nullptr;

    if (parent) {
        Object *obj = Object::getFromScObject(parent);
        obj->addChildEvent(_sc_event);
    } else {
        topLevelEvents.emplace(topLevelEvents.end(), _sc_event);
    }

    if (parent)
        _name = std::string(parent->name()) + "." + _basename;
    else
        _name = _basename;

    allEvents.emplace(allEvents.end(), _sc_event);

    // Determine if we're in the hierarchy (created once initialization starts
    // means no).
}

Event::~Event()
{
    if (parent) {
        Object *obj = Object::getFromScObject(parent);
        obj->delChildEvent(_sc_event);
    } else {
        EventsIt it = find(topLevelEvents.begin(), topLevelEvents.end(),
                           _sc_event);
        assert(it != topLevelEvents.end());
        std::swap(*it, topLevelEvents.back());
        topLevelEvents.pop_back();
    }

    EventsIt it = findEvent(_name);
    std::swap(*it, allEvents.back());
    allEvents.pop_back();

    if (delayedNotify.scheduled())
        scheduler.deschedule(&delayedNotify);
}

const std::string &
Event::name() const
{
    return _name;
}

const std::string &
Event::basename() const
{
    return _basename;
}

bool
Event::inHierarchy() const
{
    return _name.length() != 0;
}

sc_core::sc_object *
Event::getParentObject() const
{
    return parent;
}

void
Event::notify()
{
    // An immediate notification overrides any pending delayed notification.
    if (delayedNotify.scheduled())
        scheduler.deschedule(&delayedNotify);

    auto local_sensitivities = sensitivities;
    for (auto s: local_sensitivities)
        s->notify(this);
}

void
Event::notify(const sc_core::sc_time &t)
{
    if (delayedNotify.scheduled()) {
        if (scheduler.delayed(t) >= delayedNotify.when())
            return;

        scheduler.deschedule(&delayedNotify);
    }
    scheduler.schedule(&delayedNotify, t);
}

void
Event::cancel()
{
    if (delayedNotify.scheduled())
        scheduler.deschedule(&delayedNotify);
}

bool
Event::triggered() const
{
    return false;
}

Events topLevelEvents;
Events allEvents;

EventsIt
findEvent(const std::string &name)
{
    EventsIt it;
    for (it = allEvents.begin(); it != allEvents.end(); it++)
        if (!strcmp((*it)->name(), name.c_str()))
            break;

    return it;
}

} // namespace sc_gem5
<commit_msg>systemc: Handle null and omitted event names.<commit_after>/*
 * Copyright 2018 Google, Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#include "systemc/core/event.hh"

#include <algorithm>
#include <cstring>
#include <utility>

#include "base/logging.hh"
#include "sim/core.hh"
#include "systemc/core/module.hh"
#include "systemc/core/scheduler.hh"
#include "systemc/ext/core/sc_main.hh"
#include "systemc/ext/core/sc_module.hh"

namespace sc_gem5
{

Event::Event(sc_core::sc_event *_sc_event) : Event(_sc_event, nullptr) {}

Event::Event(sc_core::sc_event *_sc_event, const char *_basename_cstr) :
    _sc_event(_sc_event), _basename(_basename_cstr ? _basename_cstr : ""),
    delayedNotify([this]() { this->notify(); })
{
    Module *p = currentModule();

    if (_basename == "" && ::sc_core::sc_is_running())
        _basename = ::sc_core::sc_gen_unique_name("event");

    if (p)
        parent = p->obj()->sc_obj();
    else if (scheduler.current())
        parent = scheduler.current();
    else
        parent = nullptr;

    if (parent) {
        Object *obj = Object::getFromScObject(parent);
        obj->addChildEvent(_sc_event);
    } else {
        topLevelEvents.emplace(topLevelEvents.end(), _sc_event);
    }

    if (parent)
        _name = std::string(parent->name()) + "." + _basename;
    else
        _name = _basename;

    allEvents.emplace(allEvents.end(), _sc_event);

    // Determine if we're in the hierarchy (created once initialization starts
    // means no).
}

Event::~Event()
{
    if (parent) {
        Object *obj = Object::getFromScObject(parent);
        obj->delChildEvent(_sc_event);
    } else {
        EventsIt it = find(topLevelEvents.begin(), topLevelEvents.end(),
                           _sc_event);
        assert(it != topLevelEvents.end());
        std::swap(*it, topLevelEvents.back());
        topLevelEvents.pop_back();
    }

    EventsIt it = findEvent(_name);
    std::swap(*it, allEvents.back());
    allEvents.pop_back();

    if (delayedNotify.scheduled())
        scheduler.deschedule(&delayedNotify);
}

const std::string &
Event::name() const
{
    return _name;
}

const std::string &
Event::basename() const
{
    return _basename;
}

bool
Event::inHierarchy() const
{
    return _name.length() != 0;
}

sc_core::sc_object *
Event::getParentObject() const
{
    return parent;
}

void
Event::notify()
{
    // An immediate notification overrides any pending delayed notification.
    if (delayedNotify.scheduled())
        scheduler.deschedule(&delayedNotify);

    auto local_sensitivities = sensitivities;
    for (auto s: local_sensitivities)
        s->notify(this);
}

void
Event::notify(const sc_core::sc_time &t)
{
    if (delayedNotify.scheduled()) {
        if (scheduler.delayed(t) >= delayedNotify.when())
            return;

        scheduler.deschedule(&delayedNotify);
    }
    scheduler.schedule(&delayedNotify, t);
}

void
Event::cancel()
{
    if (delayedNotify.scheduled())
        scheduler.deschedule(&delayedNotify);
}

bool
Event::triggered() const
{
    return false;
}

Events topLevelEvents;
Events allEvents;

EventsIt
findEvent(const std::string &name)
{
    EventsIt it;
    for (it = allEvents.begin(); it != allEvents.end(); it++)
        if (!strcmp((*it)->name(), name.c_str()))
            break;

    return it;
}

} // namespace sc_gem5
<|endoftext|>


<commit_before>#ifndef __QUEUE_HPP_INCLUDED__
#define __QUEUE_HPP_INCLUDED__

#include <cstdint>
#include <fstream>
#include <mutex>

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>

#include "serialization.hpp"

namespace fs = boost::filesystem;

template <typename T>
class BaseQueue
{
private:

    virtual T getElementAt(int64_t index) = 0;

    virtual int64_t getElementSizeAt(int64_t index) = 0;

    virtual int64_t getFirstElementIndex() = 0;

    virtual int64_t getLastElementIndex() = 0;

    class Iterator
    {
    public:

        Iterator(BaseQueue<T> *queue_, int64_t index_)
            : queue(queue_), index(index_)
        {
        }

        T operator*()
        {
            return queue->getElementAt(index);
        }

        Iterator& operator++()
        {
            int64_t size = queue->getElementSizeAt(index);
            index += size;
            return *this;
        }

        bool operator!=(const Iterator& iterator)
        {
            return index != iterator.index;
        }

    private:

        BaseQueue<T> *queue;

        int64_t index;
    };

public:

    virtual void Enqueue(T e) = 0;

    virtual void Dequeue() = 0;

    virtual T Last() = 0;

    Iterator begin()
    {
        return Iterator(this, getFirstElementIndex());
    }

    Iterator end()
    {
        return Iterator(this, getLastElementIndex());
    }
};

template <typename T>
class VolatileQueue : public BaseQueue<T>
{
public:

    void Enqueue(T e)
    {
        data.push_back(e);
    }

    void Dequeue()
    {
        if (!data.empty())
        {
            data.erase(data.begin());
        }
    }

    T Last()
    {
        T empty;
        return data.size() > 0 ? data[data.size() - 1 ] : empty;
    }

private:

    T getElementAt(int64_t index)
    {
        return data[index];
    }

    int64_t getElementSizeAt(int64_t index)
    {
        return 1;
    }

    int64_t getFirstElementIndex()
    {
        return 0;
    }

    int64_t getLastElementIndex()
    {
        return data.size();
    }

    std::vector<T> data;
};

template <typename T>
class PersistentQueue : public BaseQueue<T>
{
public:

    PersistentQueue(std::string filename)
        : PersistentQueue(".", filename)
    {
    }

    PersistentQueue(std::string dirname, std::string filename)
        : file((fs::path(dirname) / fs::path(filename)).string(),
               std::ios::out | std::ios::in | std::ios::app | std::ios::binary),
          stream(file),
          insert_file((fs::path(dirname) / fs::path(filename)).string(),
                       std::ios::in | std::ios::out | std::ios::binary),
          insert_stream(insert_file),
          start_position(0),
          end_position(0),
          mutex()
    {
        SaveOffsets();
        LoadOffsets();
    }

    PersistentQueue(std::iostream& stream)
        : stream(stream),
          insert_stream(stream),
          start_position(0),
          end_position(0),
          mutex()
    {
        SaveOffsets();
        LoadOffsets();
    }

    ~PersistentQueue()
    {
        stream.flush();
    }

    void SaveOffsets()
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            start_position = HEADER_SIZE;
            end_position = UNINITIALIZED;
        }

        //insert_stream.seekp(0, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << start_position;
        insert_stream << std::setw(INDEX_SIZE) << end_position;
        insert_stream.flush();
    }

    void LoadOffsets()
    {
        stream.seekg(0, std::ios::beg);

        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        start_position = std::stoi(buffer);

        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        end_position = std::stoi(buffer);
    }

    void Enqueue(T e)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        std::string element_as_string = Serialize<T>(e);

        LoadOffsets();

        stream.seekg(0, std::ios::end);
        end_position = stream.tellg();

        insert_stream.seekp(INDEX_SIZE, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << end_position;
        insert_stream.flush();

        stream.seekp(0, std::ios::end);
        stream << element_as_string;
        stream.flush();
    }

    void Dequeue()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        LoadOffsets();

        for (T element : *this)
        {
            start_position += Serialize<T>(element).length();
            stream.seekp(0, std::ios::beg);
            stream << std::setw(INDEX_SIZE) << start_position;
            break;
        }
    }

    T Last()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        T empty;
        stream.seekg(0, std::ios::end);
        if (stream.tellg() <= HEADER_SIZE)
        {
            return empty;
        }

        LoadOffsets();

        stream.seekg(end_position, std::ios::beg);

        return Deserialize<T>(stream);
    }

private:

    T getElementAt(int64_t index)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(index, std::ios::beg);
        return Deserialize<T>(stream);
    }

    int64_t getElementSizeAt(int64_t index)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(index, std::ios::beg);
        return Serialize<T>(Deserialize<T>(stream)).length();
    }

    int64_t getFirstElementIndex()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        LoadOffsets();

        return start_position;
    }

    int64_t getLastElementIndex()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(0, std::ios::end);
        return stream.tellg();
    }

    std::fstream file;

    std::iostream& stream;

    std::fstream insert_file;

    std::iostream& insert_stream;

    std::streampos start_position;

    std::streampos end_position;

    std::recursive_mutex mutex;

    constexpr static const int64_t INDEX_SIZE = 10;

    constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 2;

    constexpr static const int64_t UNINITIALIZED = -1;
};

template <typename T>
class RolloverQueue
{
private:

    std::streampos get_start_position()
    {
        stream.seekg(0 * INDEX_SIZE, std::ios::beg);
        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        return static_cast<std::streampos>(std::stoi(buffer));
    }

    std::streampos get_end_position()
    {
        if (file.is_open())
        {
            stream.rdbuf(file.rdbuf());
        }
        stream.seekg(1 * INDEX_SIZE, std::ios::beg);
        std::string buffer(INDEX_SIZE, '\0');
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        return static_cast<std::streampos>(std::stoi(buffer));
    }

    std::streampos get_eof_position()
    {
        stream.seekg(0, std::ios::end);
        return stream.tellg();
    }

    std::fstream file;

    std::iostream& stream;

    std::streampos rollover_size;

    constexpr static const int64_t INDEX_SIZE = 10;

    constexpr static const int64_t UNINITIALIZED = 0;

    constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 2;

    constexpr static const int64_t DEFAULT_ROLLOVER_SIZE = 1000000000;

    class Iterator
    {
    public:

        Iterator(
            std::iostream& stream,
            std::streampos position,
            std::streampos rollover
        )
            : stream(stream),
              position(position),
              rollover(rollover)
        {
        }

        T operator*()
        {
            stream.seekg(position, std::ios::beg);

            return Deserialize<T>(stream);
        }

        Iterator& operator++()
        {
            if (position <= rollover)
            {
                stream.seekg(position, std::ios::beg);
                position += Serialize<T>(Deserialize<T>(stream)).length();
            }
            else
            {
                position = HEADER_SIZE;
            }

            return *this;
        }

        bool operator!=(const Iterator& iterator)
        {
            return position != iterator.position;
        }

    private:

        std::iostream& stream;

        std::streampos position;

        std::streampos rollover;

        constexpr static const int64_t INDEX_SIZE = 10;

        constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 3;
    };

public:

    RolloverQueue(std::string filename)
        : RolloverQueue(".", filename)
    {
    }

    RolloverQueue(
        std::string dirname,
        std::string filename,
        std::streampos rollover_size=DEFAULT_ROLLOVER_SIZE
    ) : file((fs::path(dirname) / fs::path(filename)).string(),
               std::ios::out | std::ios::in | std::ios::binary),
        stream(file),
        rollover_size(rollover_size)
    {
        if (!boost::filesystem::exists((fs::path(dirname) /
                                        fs::path(filename)).string()))
        {
            file.open((fs::path(dirname) / fs::path(filename)).string(),
                       std::ios::out | std::ios::app | std::ios::binary);
            file << std::setw(INDEX_SIZE) << HEADER_SIZE;
            file << std::setw(INDEX_SIZE) << UNINITIALIZED;
            file.flush();
            file.close();
            file.open((fs::path(dirname) / fs::path(filename)).string(),
                       std::ios::out | std::ios::in | std::ios::binary);
        }
    }

    RolloverQueue(
        std::iostream& stream,
        std::streampos rollover_size=DEFAULT_ROLLOVER_SIZE
    ) : stream(stream),
        rollover_size(rollover_size)
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            stream << std::setw(INDEX_SIZE) << HEADER_SIZE;
            stream << std::setw(INDEX_SIZE) << UNINITIALIZED;
        }
    }

    void Enqueue(T e)
    {
        std::string element_as_string = Serialize<T>(e);
        auto size = element_as_string.length();

        std::streampos position = get_end_position();
        if (position == UNINITIALIZED)
        {
            position = HEADER_SIZE;
        }
        else
        {
            stream.seekg(position, std::ios::beg);
            position += Serialize<T>(Deserialize<T>(stream)).length();
        }

        if (rollover_size < position + static_cast<std::streampos>(size))
        {
            std::streampos eof = get_eof_position();

            // rollover and over-write existing entries
            auto start = static_cast<std::streampos>(HEADER_SIZE);
            while (start - HEADER_SIZE < size && start != eof)
            {
                stream.seekg(start, std::ios::beg);
                start += Serialize<T>(Deserialize<T>(stream)).length();
            }

            if (start == eof)
            {
                start = HEADER_SIZE;
            }

            // update start position
            stream.seekp(0 * INDEX_SIZE, std::ios::beg);
            stream << std::setw(INDEX_SIZE) << start;
            stream.flush();
            position = start;
        }

        // flush element
        stream.seekp(position, std::ios::beg);
        stream << element_as_string;
        stream.flush();

        // update end position
        stream.seekp(1 * INDEX_SIZE, std::ios::beg);
        stream << std::setw(INDEX_SIZE) << position;
        stream.flush();
    }

    void Dequeue()
    {
        auto position = get_start_position();
        stream.seekg(position, std::ios::beg);

        auto next = position + static_cast<std::streampos>(
            Serialize<T>(Deserialize<T>(stream)).length());

        stream.seekp(0 * INDEX_SIZE, std::ios::beg);
        stream << std::setw(INDEX_SIZE) << next;
    }

    T Last()
    {
        auto position = get_end_position();

        stream.seekg(position, std::ios::beg);
        return Deserialize<T>(stream);
    }

    Iterator begin()
    {
        return Iterator(stream, get_start_position(), rollover_size);
    }

    Iterator end()
    {
        auto start = get_start_position();
        auto end = get_end_position();
        auto eof = get_eof_position();
        if (end == UNINITIALIZED || end == eof)
        {
            end = start;
        }
        else
        {
            stream.seekg(end, std::ios::beg);
            end += Serialize<T>(Deserialize<T>(stream)).length();
        }
        return Iterator(stream, end, rollover_size);
    }
};

#endif
<commit_msg>Refactor formatting and redundant concatenation<commit_after>#ifndef __QUEUE_HPP_INCLUDED__
#define __QUEUE_HPP_INCLUDED__

#include <cstdint>
#include <fstream>
#include <mutex>

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>

#include "serialization.hpp"

namespace fs = boost::filesystem;

template <typename T>
class BaseQueue
{
private:

    virtual T getElementAt(int64_t index) = 0;

    virtual int64_t getElementSizeAt(int64_t index) = 0;

    virtual int64_t getFirstElementIndex() = 0;

    virtual int64_t getLastElementIndex() = 0;

    class Iterator
    {
    public:

        Iterator(BaseQueue<T> *queue_, int64_t index_)
            : queue(queue_), index(index_)
        {
        }

        T operator*()
        {
            return queue->getElementAt(index);
        }

        Iterator& operator++()
        {
            int64_t size = queue->getElementSizeAt(index);
            index += size;
            return *this;
        }

        bool operator!=(const Iterator& iterator)
        {
            return index != iterator.index;
        }

    private:

        BaseQueue<T> *queue;

        int64_t index;
    };

public:

    virtual void Enqueue(T e) = 0;

    virtual void Dequeue() = 0;

    virtual T Last() = 0;

    Iterator begin()
    {
        return Iterator(this, getFirstElementIndex());
    }

    Iterator end()
    {
        return Iterator(this, getLastElementIndex());
    }
};

template <typename T>
class VolatileQueue : public BaseQueue<T>
{
public:

    void Enqueue(T e)
    {
        data.push_back(e);
    }

    void Dequeue()
    {
        if (!data.empty())
        {
            data.erase(data.begin());
        }
    }

    T Last()
    {
        T empty;
        return data.size() > 0 ? data[data.size() - 1 ] : empty;
    }

private:

    T getElementAt(int64_t index)
    {
        return data[index];
    }

    int64_t getElementSizeAt(int64_t index)
    {
        return 1;
    }

    int64_t getFirstElementIndex()
    {
        return 0;
    }

    int64_t getLastElementIndex()
    {
        return data.size();
    }

    std::vector<T> data;
};

template <typename T>
class PersistentQueue : public BaseQueue<T>
{
public:

    PersistentQueue(std::string filename)
        : PersistentQueue(".", filename)
    {
    }

    PersistentQueue(std::string dirname, std::string filename)
        : file((fs::path(dirname) / fs::path(filename)).string(),
               std::ios::out | std::ios::in | std::ios::app | std::ios::binary),
          stream(file),
          insert_file((fs::path(dirname) / fs::path(filename)).string(),
                       std::ios::in | std::ios::out | std::ios::binary),
          insert_stream(insert_file),
          start_position(0),
          end_position(0),
          mutex()
    {
        SaveOffsets();
        LoadOffsets();
    }

    PersistentQueue(std::iostream& stream)
        : stream(stream),
          insert_stream(stream),
          start_position(0),
          end_position(0),
          mutex()
    {
        SaveOffsets();
        LoadOffsets();
    }

    ~PersistentQueue()
    {
        stream.flush();
    }

    void SaveOffsets()
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            start_position = HEADER_SIZE;
            end_position = UNINITIALIZED;
        }

        //insert_stream.seekp(0, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << start_position;
        insert_stream << std::setw(INDEX_SIZE) << end_position;
        insert_stream.flush();
    }

    void LoadOffsets()
    {
        stream.seekg(0, std::ios::beg);

        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        start_position = std::stoi(buffer);

        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        end_position = std::stoi(buffer);
    }

    void Enqueue(T e)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        std::string element_as_string = Serialize<T>(e);

        LoadOffsets();

        stream.seekg(0, std::ios::end);
        end_position = stream.tellg();

        insert_stream.seekp(INDEX_SIZE, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << end_position;
        insert_stream.flush();

        stream.seekp(0, std::ios::end);
        stream << element_as_string;
        stream.flush();
    }

    void Dequeue()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        LoadOffsets();

        for (T element : *this)
        {
            start_position += Serialize<T>(element).length();
            stream.seekp(0, std::ios::beg);
            stream << std::setw(INDEX_SIZE) << start_position;
            break;
        }
    }

    T Last()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        T empty;
        stream.seekg(0, std::ios::end);
        if (stream.tellg() <= HEADER_SIZE)
        {
            return empty;
        }

        LoadOffsets();

        stream.seekg(end_position, std::ios::beg);

        return Deserialize<T>(stream);
    }

private:

    T getElementAt(int64_t index)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(index, std::ios::beg);
        return Deserialize<T>(stream);
    }

    int64_t getElementSizeAt(int64_t index)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(index, std::ios::beg);
        return Serialize<T>(Deserialize<T>(stream)).length();
    }

    int64_t getFirstElementIndex()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        LoadOffsets();

        return start_position;
    }

    int64_t getLastElementIndex()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(0, std::ios::end);
        return stream.tellg();
    }

    std::fstream file;

    std::iostream& stream;

    std::fstream insert_file;

    std::iostream& insert_stream;

    std::streampos start_position;

    std::streampos end_position;

    std::recursive_mutex mutex;

    constexpr static const int64_t INDEX_SIZE = 10;

    constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 2;

    constexpr static const int64_t UNINITIALIZED = -1;
};

template <typename T>
class RolloverQueue
{
private:

    std::streampos get_start_position()
    {
        stream.seekg(0 * INDEX_SIZE, std::ios::beg);
        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        return static_cast<std::streampos>(std::stoi(buffer));
    }

    std::streampos get_end_position()
    {
        if (file.is_open())
        {
            stream.rdbuf(file.rdbuf());
        }
        stream.seekg(1 * INDEX_SIZE, std::ios::beg);
        std::string buffer(INDEX_SIZE, '\0');
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        return static_cast<std::streampos>(std::stoi(buffer));
    }

    std::streampos get_eof_position()
    {
        stream.seekg(0, std::ios::end);
        return stream.tellg();
    }

    std::fstream file;

    std::iostream& stream;

    std::streampos rollover_size;

    constexpr static const int64_t INDEX_SIZE = 10;

    constexpr static const int64_t UNINITIALIZED = 0;

    constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 2;

    constexpr static const int64_t DEFAULT_ROLLOVER_SIZE = 1000000000;

    class Iterator
    {
    public:

        Iterator(
            std::iostream& stream,
            std::streampos position,
            std::streampos rollover
        )
            : stream(stream),
              position(position),
              rollover(rollover)
        {
        }

        T operator*()
        {
            stream.seekg(position, std::ios::beg);

            return Deserialize<T>(stream);
        }

        Iterator& operator++()
        {
            if (position <= rollover)
            {
                stream.seekg(position, std::ios::beg);
                position += Serialize<T>(Deserialize<T>(stream)).length();
            }
            else
            {
                position = HEADER_SIZE;
            }

            return *this;
        }

        bool operator!=(const Iterator& iterator)
        {
            return position != iterator.position;
        }

    private:

        std::iostream& stream;

        std::streampos position;

        std::streampos rollover;

        constexpr static const int64_t INDEX_SIZE = 10;

        constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 3;
    };

public:

    RolloverQueue(std::string filename)
        : RolloverQueue(".", filename)
    {
    }

    RolloverQueue(
        std::string dirname,
        std::string filename,
        std::streampos rollover_size=DEFAULT_ROLLOVER_SIZE
    ) : file((boost::filesystem::path(dirname) /
              boost::filesystem::path(filename)).string(),
               std::ios::out | std::ios::in | std::ios::binary),
        stream(file),
        rollover_size(rollover_size)
    {
        auto path = (boost::filesystem::path(dirname) /
                     boost::filesystem::path(filename)).string();
        if (!boost::filesystem::exists(path))
        {
            file.open(path, std::ios::out | std::ios::app | std::ios::binary);
            file << std::setw(INDEX_SIZE) << HEADER_SIZE;
            file << std::setw(INDEX_SIZE) << UNINITIALIZED;
            file.flush();
            file.close();
            file.open(path, std::ios::out | std::ios::in | std::ios::binary);
        }
    }

    RolloverQueue(
        std::iostream& stream,
        std::streampos rollover_size=DEFAULT_ROLLOVER_SIZE
    ) : stream(stream),
        rollover_size(rollover_size)
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            stream << std::setw(INDEX_SIZE) << HEADER_SIZE;
            stream << std::setw(INDEX_SIZE) << UNINITIALIZED;
        }
    }

    void Enqueue(T e)
    {
        std::string element_as_string = Serialize<T>(e);
        auto size = element_as_string.length();

        std::streampos position = get_end_position();
        if (position == UNINITIALIZED)
        {
            position = HEADER_SIZE;
        }
        else
        {
            stream.seekg(position, std::ios::beg);
            position += Serialize<T>(Deserialize<T>(stream)).length();
        }

        if (rollover_size < position + static_cast<std::streampos>(size))
        {
            std::streampos eof = get_eof_position();

            // rollover and over-write existing entries
            auto start = static_cast<std::streampos>(HEADER_SIZE);
            while (start - HEADER_SIZE < size && start != eof)
            {
                stream.seekg(start, std::ios::beg);
                start += Serialize<T>(Deserialize<T>(stream)).length();
            }

            if (start == eof)
            {
                start = HEADER_SIZE;
            }

            // update start position
            stream.seekp(0 * INDEX_SIZE, std::ios::beg);
            stream << std::setw(INDEX_SIZE) << start;
            stream.flush();
            position = start;
        }

        // flush element
        stream.seekp(position, std::ios::beg);
        stream << element_as_string;
        stream.flush();

        // update end position
        stream.seekp(1 * INDEX_SIZE, std::ios::beg);
        stream << std::setw(INDEX_SIZE) << position;
        stream.flush();
    }

    void Dequeue()
    {
        auto position = get_start_position();
        stream.seekg(position, std::ios::beg);

        auto next = position + static_cast<std::streampos>(
            Serialize<T>(Deserialize<T>(stream)).length());

        stream.seekp(0 * INDEX_SIZE, std::ios::beg);
        stream << std::setw(INDEX_SIZE) << next;
    }

    T Last()
    {
        auto position = get_end_position();

        stream.seekg(position, std::ios::beg);
        return Deserialize<T>(stream);
    }

    Iterator begin()
    {
        return Iterator(stream, get_start_position(), rollover_size);
    }

    Iterator end()
    {
        auto start = get_start_position();
        auto end = get_end_position();
        auto eof = get_eof_position();
        if (end == UNINITIALIZED || end == eof)
        {
            end = start;
        }
        else
        {
            stream.seekg(end, std::ios::beg);
            end += Serialize<T>(Deserialize<T>(stream)).length();
        }
        return Iterator(stream, end, rollover_size);
    }
};

#endif
<|endoftext|>


<commit_before>/*
* 2013+ Copyright (c) Andrey Kashin <kashin.andrej@gmail.com>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/

#ifndef REACT_HPP
#define REACT_HPP

#include <memory>

#include "react/call_tree.hpp"
#include "react/updater.hpp"
#include "react/aggregator.hpp"

#include "react.h"

namespace react {

class action_guard {
public:
	explicit action_guard(int action_code);
	action_guard(const action_guard &other) = delete;
	~action_guard();

	action_guard &operator =(const action_guard &other) = delete;

	void stop();

private:
	std::unique_ptr<react::action_guard_t> m_action_guard;
};

const actions_set_t &get_actions_set();

void add_stat_impl(const std::string &key, const react::stat_value_t &value);

template<typename T>
void add_stat(const std::string &key, const T &value) {
	add_stat_impl(key, react::stat_value_t(value));
}

void add_stat(const std::string &key, const char *value);

std::shared_ptr<aggregator_t> create_subthread_aggregator();

} // namespace react

#endif // REACT_HPP
<commit_msg>api: Docs added.<commit_after>/*
* 2013+ Copyright (c) Andrey Kashin <kashin.andrej@gmail.com>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/

#ifndef REACT_HPP
#define REACT_HPP

#include <memory>

#include "react/call_tree.hpp"
#include "react/updater.hpp"
#include "react/aggregator.hpp"

#include "react.h"

namespace react {

/*!
 * \brief Wrapper for action_guard_t with binded updater from local context
 */
class action_guard {
public:
	/*!
	 * \brief Creates action_guard and starts action with \a action_code
	 * \param Code of started action
	 */
	explicit action_guard(int action_code);

	action_guard(const action_guard &other) = delete;

	/*!
	 * \brief Stops guarded action.
	 */
	~action_guard();

	action_guard &operator =(const action_guard &other) = delete;

	/*!
	 * \brief Allows to stop action manually
	 */
	void stop();

private:
	/*!
	 * \brief Wrapped action_guard_t
	 */
	std::unique_ptr<react::action_guard_t> m_action_guard;
};

/*!
 * \brief Returns current context actions set
 * \return Current context action set
 */
const actions_set_t &get_actions_set();

/*!
 * \internal
 *
 * \brief Adds new stat to current call tree
 * \param key Name of stat
 * \param value Value of stat
 */
void add_stat_impl(const std::string &key, const react::stat_value_t &value);

/*!
 * \brief Template wrapper for add_stat_impl. Avoids specifying value type manually.
 */
template<typename T>
void add_stat(const std::string &key, const T &value) {
	add_stat_impl(key, react::stat_value_t(value));
}

/*!
 * \brief Template specification for add_stat that handles char* correctly.
 */
void add_stat(const std::string &key, const char *value);

/*!
 * \brief Creates aggregator that can be passed to subthread in order to monitor it
 *          and merge result of monitoring with current thread context
 * \return Returns shared_ptr to newly created aggregator for subthread
 */
std::shared_ptr<aggregator_t> create_subthread_aggregator();

} // namespace react

#endif // REACT_HPP
<|endoftext|>


<commit_before>#ifndef __SGE_NODE_MANAGER_HPP
#define __SGE_NODE_MANAGER_HPP

#include <sge/node.hpp>
#include <map>

namespace sge
{
    class NodeManager
    {
        public:
            NodeManager(Engine &engine);

            template <class NodeType>
            std::shared_ptr<NodeType> create(const std::string &nodename)
            {
                std::shared_ptr<NodeType> node = std::make_shared<NodeType>(nodename, engine);
                nodes[node] = false;
                return node;
            }

            void garbage_collect();

        private:
            void mark(std::shared_ptr<Node> root);

        private:
            Engine &engine;
            std::map<std::shared_ptr<Node>, bool> nodes;

    };
}

#endif /* __SGE_NODE_MANAGER_HPP */
<commit_msg>:fix: missing call to node init method<commit_after>#ifndef __SGE_NODE_MANAGER_HPP
#define __SGE_NODE_MANAGER_HPP

#include <sge/node.hpp>
#include <map>

namespace sge
{
    class NodeManager
    {
        public:
            NodeManager(Engine &engine);

            template <class NodeType>
            std::shared_ptr<NodeType> create(const std::string &nodename)
            {
                std::shared_ptr<NodeType> node = std::make_shared<NodeType>(nodename, engine);
                node->init();
                nodes[node] = false;
                return node;
            }

            void garbage_collect();

        private:
            void mark(std::shared_ptr<Node> root);

        private:
            Engine &engine;
            std::map<std::shared_ptr<Node>, bool> nodes;

    };
}

#endif /* __SGE_NODE_MANAGER_HPP */
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qt4projectconfigwidget.h"

#include "makestep.h"
#include "qmakestep.h"
#include "qt4project.h"
#include "qt4projectmanagerconstants.h"
#include "qt4projectmanager.h"
#include "ui_qt4projectconfigwidget.h"

#include <coreplugin/icore.h>
#include <coreplugin/mainwindow.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/buildconfiguration.h>
#include <extensionsystem/pluginmanager.h>

#include <QtGui/QFileDialog>

namespace {
bool debug = false;
}

using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;

Qt4ProjectConfigWidget::Qt4ProjectConfigWidget(Qt4Project *project)
    : BuildConfigWidget(),
      m_pro(project)
{
    QVBoxLayout *vbox = new QVBoxLayout(this);
    vbox->setMargin(0);
    m_detailsContainer = new Utils::DetailsWidget(this);
    vbox->addWidget(m_detailsContainer);
    QWidget *details = new QWidget(m_detailsContainer);
    m_detailsContainer->setWidget(details);
    m_ui = new Ui::Qt4ProjectConfigWidget();
    m_ui->setupUi(details);

    m_browseButton = m_ui->shadowBuildDirEdit->buttonAtIndex(0);
    // TODO refix the layout

    m_ui->shadowBuildDirEdit->setPromptDialogTitle(tr("Shadow Build Directory"));
    m_ui->shadowBuildDirEdit->setExpectedKind(Utils::PathChooser::Directory);
    m_ui->invalidQtWarningLabel->setVisible(false);

    connect(m_ui->nameLineEdit, SIGNAL(textEdited(QString)),
            this, SLOT(changeConfigName(QString)));

    connect(m_ui->shadowBuildCheckBox, SIGNAL(clicked(bool)),
            this, SLOT(shadowBuildCheckBoxClicked(bool)));

    connect(m_ui->shadowBuildDirEdit, SIGNAL(beforeBrowsing()),
            this, SLOT(onBeforeBeforeShadowBuildDirBrowsed()));

    connect(m_ui->shadowBuildDirEdit, SIGNAL(changed(QString)),
            this, SLOT(shadowBuildLineEditTextChanged()));

    connect(m_ui->qtVersionComboBox, SIGNAL(currentIndexChanged(QString)),
            this, SLOT(qtVersionComboBoxCurrentIndexChanged(QString)));

    connect(m_ui->toolChainComboBox, SIGNAL(activated(int)),
            this, SLOT(selectToolChain(int)));

    connect(m_ui->importLabel, SIGNAL(linkActivated(QString)),
            this, SLOT(importLabelClicked()));

    connect(m_ui->manageQtVersionPushButtons, SIGNAL(clicked()),
            this, SLOT(manageQtVersions()));

    QtVersionManager *vm = QtVersionManager::instance();

    connect(vm, SIGNAL(qtVersionsChanged()),
            this, SLOT(setupQtVersionsComboBox()));
    connect(vm, SIGNAL(qtVersionsChanged()),
            this, SLOT(updateDetails()));
}

Qt4ProjectConfigWidget::~Qt4ProjectConfigWidget()
{
    delete m_ui;
}

void Qt4ProjectConfigWidget::updateDetails()
{
    ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(m_buildConfiguration);
    QtVersion *version = m_pro->qtVersion(bc);
    QString versionString;
    if (m_pro->qtVersionId(bc) == 0) {
        versionString = tr("Default Qt Version (%1)").arg(version->name());
    } else if(version){
        versionString = version->name();
    } else {
        versionString = tr("No Qt Version set");
    }
    // Qt Version, Build Directory and Toolchain
    m_detailsContainer->setSummaryText(tr("using Qt version: %1
"
                                 "with tool chain %2
"
                                 "building in %3")
                              .arg(versionString,
                                   ProjectExplorer::ToolChain::toolChainName(m_pro->toolChainType(bc)),
                                   QDir::toNativeSeparators(m_pro->buildDirectory(bc))));
}

void Qt4ProjectConfigWidget::manageQtVersions()
{
    Core::ICore *core = Core::ICore::instance();
    core->showOptionsDialog(Constants::QT_CATEGORY, Constants::QTVERSION_PAGE);
}

QString Qt4ProjectConfigWidget::displayName() const
{
    return tr("General");
}

void Qt4ProjectConfigWidget::init(const QString &buildConfiguration)
{
    if (debug)
        qDebug() << "Qt4ProjectConfigWidget::init() for"<<buildConfiguration;

    m_buildConfiguration = buildConfiguration;
    ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(buildConfiguration);
    m_ui->nameLineEdit->setText(bc->displayName());

    setupQtVersionsComboBox();

    bool shadowBuild = bc->value("useShadowBuild").toBool();
    m_ui->shadowBuildCheckBox->setChecked(shadowBuild);
    m_ui->shadowBuildDirEdit->setEnabled(shadowBuild);
    m_browseButton->setEnabled(shadowBuild);
    m_ui->shadowBuildDirEdit->setPath(m_pro->buildDirectory(bc));
    updateImportLabel();
    updateToolChainCombo();
    updateDetails();
}

void Qt4ProjectConfigWidget::changeConfigName(const QString &newName)
{
    m_pro->setDisplayNameFor(
            m_pro->buildConfiguration(m_buildConfiguration), newName);
}

void Qt4ProjectConfigWidget::setupQtVersionsComboBox()
{
    if (m_buildConfiguration.isEmpty()) // not yet initialized
        return;

    disconnect(m_ui->qtVersionComboBox, SIGNAL(currentIndexChanged(QString)),
        this, SLOT(qtVersionComboBoxCurrentIndexChanged(QString)));

    QtVersionManager *vm = QtVersionManager::instance();

    m_ui->qtVersionComboBox->clear();
    m_ui->qtVersionComboBox->addItem(tr("Default Qt Version (%1)").arg(vm->defaultVersion()->name()), 0);

    int qtVersionId = m_pro->qtVersionId(m_pro->buildConfiguration(m_buildConfiguration));

    if (qtVersionId == 0) {
        m_ui->qtVersionComboBox->setCurrentIndex(0);
        m_ui->invalidQtWarningLabel->setVisible(false);
    }
    // Add Qt Versions to the combo box
    const QList<QtVersion *> &versions = vm->versions();
    for (int i = 0; i < versions.size(); ++i) {
        m_ui->qtVersionComboBox->addItem(versions.at(i)->name(), versions.at(i)->uniqueId());

        if (versions.at(i)->uniqueId() == qtVersionId) {
            m_ui->qtVersionComboBox->setCurrentIndex(i + 1);
            m_ui->invalidQtWarningLabel->setVisible(!versions.at(i)->isValid());
        }
    }

    // And connect again
    connect(m_ui->qtVersionComboBox, SIGNAL(currentIndexChanged(QString)),
        this, SLOT(qtVersionComboBoxCurrentIndexChanged(QString)));
}

void Qt4ProjectConfigWidget::onBeforeBeforeShadowBuildDirBrowsed()
{
    QString initialDirectory = QFileInfo(m_pro->file()->fileName()).absolutePath();
    if (!initialDirectory.isEmpty())
        m_ui->shadowBuildDirEdit->setInitialBrowsePathBackup(initialDirectory);
}

void Qt4ProjectConfigWidget::shadowBuildCheckBoxClicked(bool checked)
{
    m_ui->shadowBuildDirEdit->setEnabled(checked);
    m_browseButton->setEnabled(checked);
    bool b = m_ui->shadowBuildCheckBox->isChecked();
    ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(m_buildConfiguration);
    bc->setValue("useShadowBuild", b);
    if (b)
        bc->setValue("buildDirectory", m_ui->shadowBuildDirEdit->path());
    else
        bc->setValue("buildDirectory", QVariant(QString::null));
    updateDetails();
}

void Qt4ProjectConfigWidget::updateImportLabel()
{
    bool visible = false;

    // we only show if we actually have a qmake and makestep
    if (m_pro->qmakeStep() && m_pro->makeStep()) {
        ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(m_buildConfiguration);
        QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(m_pro->buildDirectory(bc));
        QtVersion *version = m_pro->qtVersion(bc);
        // check that there's a makefile
        if (!qmakePath.isEmpty()) {
            // and that the qmake path is different from the current version
            if (qmakePath != (version ? version->qmakeCommand() : QString())) {
                // import enable
                visible = true;
            } else {
                // check that the qmake flags, arguments match
                visible = !m_pro->compareBuildConfigurationToImportFrom(bc, m_pro->buildDirectory(bc));
            }
        } else {
            visible = false;
        }
    }

    m_ui->importLabel->setVisible(visible);
}

void Qt4ProjectConfigWidget::shadowBuildLineEditTextChanged()
{
    ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(m_buildConfiguration);
    if (bc->value("buildDirectory").toString() == m_ui->shadowBuildDirEdit->path())
        return;
    bc->setValue("buildDirectory", m_ui->shadowBuildDirEdit->path());
    // if the directory already exists
    // check if we have a build in there and
    // offer to import it
    updateImportLabel();

    m_pro->invalidateCachedTargetInformation();
    updateDetails();
}

void Qt4ProjectConfigWidget::importLabelClicked()
{
    if (!m_pro->qmakeStep() || !m_pro->makeStep())
        return;
    ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(m_buildConfiguration);
    QString directory = m_pro->buildDirectory(bc);
    if (!directory.isEmpty()) {
        QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(directory);
        if (!qmakePath.isEmpty()) {
            QtVersionManager *vm = QtVersionManager::instance();
            QtVersion *version = vm->qtVersionForQMakeBinary(qmakePath);
            if (!version) {
                version = new QtVersion(qmakePath);
                vm->addVersion(version);
            }

            QPair<QtVersion::QmakeBuildConfig, QStringList> result =
                    QtVersionManager::scanMakeFile(directory, version->defaultBuildConfig());
            QtVersion::QmakeBuildConfig qmakeBuildConfig = result.first;
            QStringList additionalArguments = result.second;

            QString versionSpec = version->sourcePath() + "/mkspecs/" + version->mkspec();
            QString parsedSpec = Qt4Project::extractSpecFromArgumentList(additionalArguments);
            QString parsedSpecOrginal = parsedSpec;
            if (QFileInfo(parsedSpec).isRelative())
                parsedSpec = QDir::cleanPath(directory + "/" + parsedSpec);
            additionalArguments = Qt4Project::removeSpecFromArgumentList(additionalArguments);
            if (parsedSpec != versionSpec) {
                additionalArguments.prepend(parsedSpecOrginal);
                additionalArguments.prepend("-spec");
            }

            // So we got all the information now apply it...
            m_pro->setQtVersion(bc, version->uniqueId());
            // Combo box will be updated at the end

            QMakeStep *qmakeStep = m_pro->qmakeStep();
            qmakeStep->setQMakeArguments(m_buildConfiguration, additionalArguments);
            MakeStep *makeStep = m_pro->makeStep();

            bc->setValue("buildConfiguration", int(qmakeBuildConfig));
            // Adjust command line arguments, this is ugly as hell
            // If we are switching to BuildAll we want "release" in there and no "debug"
            // or "debug" in there and no "release"
            // If we are switching to not BuildAl we want neither "release" nor "debug" in there
            QStringList makeCmdArguments = makeStep->value(m_buildConfiguration, "makeargs").toStringList();
            bool debug = qmakeBuildConfig & QtVersion::DebugBuild;
            if (qmakeBuildConfig & QtVersion::BuildAll) {
                makeCmdArguments.removeAll(debug ? "release" : "debug");
                if (!makeCmdArguments.contains(debug ? "debug" : "release"))
                    makeCmdArguments.append(debug ? "debug" : "release");
            } else {
                makeCmdArguments.removeAll("debug");
                makeCmdArguments.removeAll("release");
            }
            makeStep->setMakeArguments(m_buildConfiguration, makeCmdArguments);
        }
    }
    setupQtVersionsComboBox();
    updateDetails();
}

void Qt4ProjectConfigWidget::qtVersionComboBoxCurrentIndexChanged(const QString &)
{
    //Qt Version
    int newQtVersion;
    if (m_ui->qtVersionComboBox->currentIndex() == 0) {
        newQtVersion = 0;
    } else {
        newQtVersion = m_ui->qtVersionComboBox->itemData(m_ui->qtVersionComboBox->currentIndex()).toInt();
    }
    QtVersionManager *vm = QtVersionManager::instance();
    bool isValid = vm->version(newQtVersion)->isValid();
    m_ui->invalidQtWarningLabel->setVisible(!isValid);
    if (newQtVersion != m_pro->qtVersionId(m_pro->buildConfiguration(m_buildConfiguration))) {
        m_pro->setQtVersion(m_pro->buildConfiguration(m_buildConfiguration), newQtVersion);
        updateToolChainCombo();
        m_pro->update();
    }
    updateDetails();
}

void Qt4ProjectConfigWidget::updateToolChainCombo()
{
    m_ui->toolChainComboBox->clear();
    ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(m_buildConfiguration);
    QList<ProjectExplorer::ToolChain::ToolChainType> toolchains = m_pro->qtVersion(bc)->possibleToolChainTypes();
    using namespace ProjectExplorer;
    foreach (ToolChain::ToolChainType toolchain, toolchains) {
        m_ui->toolChainComboBox->addItem(ToolChain::toolChainName(toolchain), qVariantFromValue(toolchain));
    }
    m_ui->toolChainComboBox->setEnabled(toolchains.size() > 1);
    setToolChain(toolchains.indexOf(m_pro->toolChainType(bc)));
}

void Qt4ProjectConfigWidget::selectToolChain(int index)
{
    setToolChain(index);
    m_pro->update();
}

void Qt4ProjectConfigWidget::setToolChain(int index)
{
    ProjectExplorer::ToolChain::ToolChainType selectedToolChainType =
        m_ui->toolChainComboBox->itemData(index,
            Qt::UserRole).value<ProjectExplorer::ToolChain::ToolChainType>();
    m_pro->setToolChainType(m_pro->buildConfiguration(m_buildConfiguration), selectedToolChainType);
    if (m_ui->toolChainComboBox->currentIndex() != index)
        m_ui->toolChainComboBox->setCurrentIndex(index);
    updateDetails();
}
<commit_msg>Fix importing via "import settings" label addind a unecessary -spec<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qt4projectconfigwidget.h"

#include "makestep.h"
#include "qmakestep.h"
#include "qt4project.h"
#include "qt4projectmanagerconstants.h"
#include "qt4projectmanager.h"
#include "ui_qt4projectconfigwidget.h"

#include <coreplugin/icore.h>
#include <coreplugin/mainwindow.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/buildconfiguration.h>
#include <extensionsystem/pluginmanager.h>

#include <QtGui/QFileDialog>

namespace {
bool debug = false;
}

using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;

Qt4ProjectConfigWidget::Qt4ProjectConfigWidget(Qt4Project *project)
    : BuildConfigWidget(),
      m_pro(project)
{
    QVBoxLayout *vbox = new QVBoxLayout(this);
    vbox->setMargin(0);
    m_detailsContainer = new Utils::DetailsWidget(this);
    vbox->addWidget(m_detailsContainer);
    QWidget *details = new QWidget(m_detailsContainer);
    m_detailsContainer->setWidget(details);
    m_ui = new Ui::Qt4ProjectConfigWidget();
    m_ui->setupUi(details);

    m_browseButton = m_ui->shadowBuildDirEdit->buttonAtIndex(0);
    // TODO refix the layout

    m_ui->shadowBuildDirEdit->setPromptDialogTitle(tr("Shadow Build Directory"));
    m_ui->shadowBuildDirEdit->setExpectedKind(Utils::PathChooser::Directory);
    m_ui->invalidQtWarningLabel->setVisible(false);

    connect(m_ui->nameLineEdit, SIGNAL(textEdited(QString)),
            this, SLOT(changeConfigName(QString)));

    connect(m_ui->shadowBuildCheckBox, SIGNAL(clicked(bool)),
            this, SLOT(shadowBuildCheckBoxClicked(bool)));

    connect(m_ui->shadowBuildDirEdit, SIGNAL(beforeBrowsing()),
            this, SLOT(onBeforeBeforeShadowBuildDirBrowsed()));

    connect(m_ui->shadowBuildDirEdit, SIGNAL(changed(QString)),
            this, SLOT(shadowBuildLineEditTextChanged()));

    connect(m_ui->qtVersionComboBox, SIGNAL(currentIndexChanged(QString)),
            this, SLOT(qtVersionComboBoxCurrentIndexChanged(QString)));

    connect(m_ui->toolChainComboBox, SIGNAL(activated(int)),
            this, SLOT(selectToolChain(int)));

    connect(m_ui->importLabel, SIGNAL(linkActivated(QString)),
            this, SLOT(importLabelClicked()));

    connect(m_ui->manageQtVersionPushButtons, SIGNAL(clicked()),
            this, SLOT(manageQtVersions()));

    QtVersionManager *vm = QtVersionManager::instance();

    connect(vm, SIGNAL(qtVersionsChanged()),
            this, SLOT(setupQtVersionsComboBox()));
    connect(vm, SIGNAL(qtVersionsChanged()),
            this, SLOT(updateDetails()));
}

Qt4ProjectConfigWidget::~Qt4ProjectConfigWidget()
{
    delete m_ui;
}

void Qt4ProjectConfigWidget::updateDetails()
{
    ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(m_buildConfiguration);
    QtVersion *version = m_pro->qtVersion(bc);
    QString versionString;
    if (m_pro->qtVersionId(bc) == 0) {
        versionString = tr("Default Qt Version (%1)").arg(version->name());
    } else if(version){
        versionString = version->name();
    } else {
        versionString = tr("No Qt Version set");
    }
    // Qt Version, Build Directory and Toolchain
    m_detailsContainer->setSummaryText(tr("using Qt version: %1
"
                                 "with tool chain %2
"
                                 "building in %3")
                              .arg(versionString,
                                   ProjectExplorer::ToolChain::toolChainName(m_pro->toolChainType(bc)),
                                   QDir::toNativeSeparators(m_pro->buildDirectory(bc))));
}

void Qt4ProjectConfigWidget::manageQtVersions()
{
    Core::ICore *core = Core::ICore::instance();
    core->showOptionsDialog(Constants::QT_CATEGORY, Constants::QTVERSION_PAGE);
}

QString Qt4ProjectConfigWidget::displayName() const
{
    return tr("General");
}

void Qt4ProjectConfigWidget::init(const QString &buildConfiguration)
{
    if (debug)
        qDebug() << "Qt4ProjectConfigWidget::init() for"<<buildConfiguration;

    m_buildConfiguration = buildConfiguration;
    ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(buildConfiguration);
    m_ui->nameLineEdit->setText(bc->displayName());

    setupQtVersionsComboBox();

    bool shadowBuild = bc->value("useShadowBuild").toBool();
    m_ui->shadowBuildCheckBox->setChecked(shadowBuild);
    m_ui->shadowBuildDirEdit->setEnabled(shadowBuild);
    m_browseButton->setEnabled(shadowBuild);
    m_ui->shadowBuildDirEdit->setPath(m_pro->buildDirectory(bc));
    updateImportLabel();
    updateToolChainCombo();
    updateDetails();
}

void Qt4ProjectConfigWidget::changeConfigName(const QString &newName)
{
    m_pro->setDisplayNameFor(
            m_pro->buildConfiguration(m_buildConfiguration), newName);
}

void Qt4ProjectConfigWidget::setupQtVersionsComboBox()
{
    if (m_buildConfiguration.isEmpty()) // not yet initialized
        return;

    disconnect(m_ui->qtVersionComboBox, SIGNAL(currentIndexChanged(QString)),
        this, SLOT(qtVersionComboBoxCurrentIndexChanged(QString)));

    QtVersionManager *vm = QtVersionManager::instance();

    m_ui->qtVersionComboBox->clear();
    m_ui->qtVersionComboBox->addItem(tr("Default Qt Version (%1)").arg(vm->defaultVersion()->name()), 0);

    int qtVersionId = m_pro->qtVersionId(m_pro->buildConfiguration(m_buildConfiguration));

    if (qtVersionId == 0) {
        m_ui->qtVersionComboBox->setCurrentIndex(0);
        m_ui->invalidQtWarningLabel->setVisible(false);
    }
    // Add Qt Versions to the combo box
    const QList<QtVersion *> &versions = vm->versions();
    for (int i = 0; i < versions.size(); ++i) {
        m_ui->qtVersionComboBox->addItem(versions.at(i)->name(), versions.at(i)->uniqueId());

        if (versions.at(i)->uniqueId() == qtVersionId) {
            m_ui->qtVersionComboBox->setCurrentIndex(i + 1);
            m_ui->invalidQtWarningLabel->setVisible(!versions.at(i)->isValid());
        }
    }

    // And connect again
    connect(m_ui->qtVersionComboBox, SIGNAL(currentIndexChanged(QString)),
        this, SLOT(qtVersionComboBoxCurrentIndexChanged(QString)));
}

void Qt4ProjectConfigWidget::onBeforeBeforeShadowBuildDirBrowsed()
{
    QString initialDirectory = QFileInfo(m_pro->file()->fileName()).absolutePath();
    if (!initialDirectory.isEmpty())
        m_ui->shadowBuildDirEdit->setInitialBrowsePathBackup(initialDirectory);
}

void Qt4ProjectConfigWidget::shadowBuildCheckBoxClicked(bool checked)
{
    m_ui->shadowBuildDirEdit->setEnabled(checked);
    m_browseButton->setEnabled(checked);
    bool b = m_ui->shadowBuildCheckBox->isChecked();
    ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(m_buildConfiguration);
    bc->setValue("useShadowBuild", b);
    if (b)
        bc->setValue("buildDirectory", m_ui->shadowBuildDirEdit->path());
    else
        bc->setValue("buildDirectory", QVariant(QString::null));
    updateDetails();
}

void Qt4ProjectConfigWidget::updateImportLabel()
{
    bool visible = false;

    // we only show if we actually have a qmake and makestep
    if (m_pro->qmakeStep() && m_pro->makeStep()) {
        ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(m_buildConfiguration);
        QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(m_pro->buildDirectory(bc));
        QtVersion *version = m_pro->qtVersion(bc);
        // check that there's a makefile
        if (!qmakePath.isEmpty()) {
            // and that the qmake path is different from the current version
            if (qmakePath != (version ? version->qmakeCommand() : QString())) {
                // import enable
                visible = true;
            } else {
                // check that the qmake flags, arguments match
                visible = !m_pro->compareBuildConfigurationToImportFrom(bc, m_pro->buildDirectory(bc));
            }
        } else {
            visible = false;
        }
    }

    m_ui->importLabel->setVisible(visible);
}

void Qt4ProjectConfigWidget::shadowBuildLineEditTextChanged()
{
    ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(m_buildConfiguration);
    if (bc->value("buildDirectory").toString() == m_ui->shadowBuildDirEdit->path())
        return;
    bc->setValue("buildDirectory", m_ui->shadowBuildDirEdit->path());
    // if the directory already exists
    // check if we have a build in there and
    // offer to import it
    updateImportLabel();

    m_pro->invalidateCachedTargetInformation();
    updateDetails();
}

void Qt4ProjectConfigWidget::importLabelClicked()
{
    if (!m_pro->qmakeStep() || !m_pro->makeStep())
        return;
    ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(m_buildConfiguration);
    QString directory = m_pro->buildDirectory(bc);
    if (!directory.isEmpty()) {
        QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(directory);
        if (!qmakePath.isEmpty()) {
            QtVersionManager *vm = QtVersionManager::instance();
            QtVersion *version = vm->qtVersionForQMakeBinary(qmakePath);
            if (!version) {
                version = new QtVersion(qmakePath);
                vm->addVersion(version);
            }

            QPair<QtVersion::QmakeBuildConfig, QStringList> result =
                    QtVersionManager::scanMakeFile(directory, version->defaultBuildConfig());
            QtVersion::QmakeBuildConfig qmakeBuildConfig = result.first;
            QStringList additionalArguments = result.second;

            QString versionSpec = version->sourcePath() + "/mkspecs/" + version->mkspec();
            QString parsedSpec = Qt4Project::extractSpecFromArgumentList(additionalArguments);

            if (parsedSpec.isEmpty()) {
                // using the default spec, don't modify additional arguments
            } else {
                QString parsedSpecOrginal = parsedSpec;
                if (QFileInfo(parsedSpec).isRelative())
                    parsedSpec = QDir::cleanPath(directory + "/" + parsedSpec);
                additionalArguments = Qt4Project::removeSpecFromArgumentList(additionalArguments);
                if (parsedSpec != versionSpec) {
                    additionalArguments.prepend(parsedSpecOrginal);
                    additionalArguments.prepend("-spec");
                }
            }

            // So we got all the information now apply it...
            m_pro->setQtVersion(bc, version->uniqueId());
            // Combo box will be updated at the end

            QMakeStep *qmakeStep = m_pro->qmakeStep();
            qmakeStep->setQMakeArguments(m_buildConfiguration, additionalArguments);
            MakeStep *makeStep = m_pro->makeStep();

            bc->setValue("buildConfiguration", int(qmakeBuildConfig));
            // Adjust command line arguments, this is ugly as hell
            // If we are switching to BuildAll we want "release" in there and no "debug"
            // or "debug" in there and no "release"
            // If we are switching to not BuildAl we want neither "release" nor "debug" in there
            QStringList makeCmdArguments = makeStep->value(m_buildConfiguration, "makeargs").toStringList();
            bool debug = qmakeBuildConfig & QtVersion::DebugBuild;
            if (qmakeBuildConfig & QtVersion::BuildAll) {
                makeCmdArguments.removeAll(debug ? "release" : "debug");
                if (!makeCmdArguments.contains(debug ? "debug" : "release"))
                    makeCmdArguments.append(debug ? "debug" : "release");
            } else {
                makeCmdArguments.removeAll("debug");
                makeCmdArguments.removeAll("release");
            }
            makeStep->setMakeArguments(m_buildConfiguration, makeCmdArguments);
        }
    }
    setupQtVersionsComboBox();
    updateDetails();
}

void Qt4ProjectConfigWidget::qtVersionComboBoxCurrentIndexChanged(const QString &)
{
    //Qt Version
    int newQtVersion;
    if (m_ui->qtVersionComboBox->currentIndex() == 0) {
        newQtVersion = 0;
    } else {
        newQtVersion = m_ui->qtVersionComboBox->itemData(m_ui->qtVersionComboBox->currentIndex()).toInt();
    }
    QtVersionManager *vm = QtVersionManager::instance();
    bool isValid = vm->version(newQtVersion)->isValid();
    m_ui->invalidQtWarningLabel->setVisible(!isValid);
    if (newQtVersion != m_pro->qtVersionId(m_pro->buildConfiguration(m_buildConfiguration))) {
        m_pro->setQtVersion(m_pro->buildConfiguration(m_buildConfiguration), newQtVersion);
        updateToolChainCombo();
        m_pro->update();
    }
    updateDetails();
}

void Qt4ProjectConfigWidget::updateToolChainCombo()
{
    m_ui->toolChainComboBox->clear();
    ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(m_buildConfiguration);
    QList<ProjectExplorer::ToolChain::ToolChainType> toolchains = m_pro->qtVersion(bc)->possibleToolChainTypes();
    using namespace ProjectExplorer;
    foreach (ToolChain::ToolChainType toolchain, toolchains) {
        m_ui->toolChainComboBox->addItem(ToolChain::toolChainName(toolchain), qVariantFromValue(toolchain));
    }
    m_ui->toolChainComboBox->setEnabled(toolchains.size() > 1);
    setToolChain(toolchains.indexOf(m_pro->toolChainType(bc)));
}

void Qt4ProjectConfigWidget::selectToolChain(int index)
{
    setToolChain(index);
    m_pro->update();
}

void Qt4ProjectConfigWidget::setToolChain(int index)
{
    ProjectExplorer::ToolChain::ToolChainType selectedToolChainType =
        m_ui->toolChainComboBox->itemData(index,
            Qt::UserRole).value<ProjectExplorer::ToolChain::ToolChainType>();
    m_pro->setToolChainType(m_pro->buildConfiguration(m_buildConfiguration), selectedToolChainType);
    if (m_ui->toolChainComboBox->currentIndex() != index)
        m_ui->toolChainComboBox->setCurrentIndex(index);
    updateDetails();
}
<|endoftext|>