<commit_before>#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <set>

#include <CodeSource.h>
#include <CodeObject.h>
#include <CFGFactory.h>

#include <lib/binutils/VMAInterval.hpp>

#include "CudaCFGFactory.hpp"
#include "CudaFunction.hpp"
#include "CudaBlock.hpp"
#include "CudaCodeSource.hpp"
#include "CFGParser.hpp"
#include "GraphReader.hpp"
#include "ReadCubinCFG.hpp"

using namespace Dyninst;
using namespace ParseAPI;
using namespace SymtabAPI;
using namespace InstructionAPI;

static bool
test_nvdisasm()
{
  // check whether nvdisasm works
  int retval = system("/sw/summitdev/cuda/9.2.148/bin/nvdisasm > /dev/null") == 0;
  if (!retval) {
    std::cout << "WARNING: nvdisasm is not available on your path to analyze control flow in NVIDIA CUBINs" << std::endl;
  }
  return retval;
}

static bool
dumpCubin
(
 const std::string &cubin,
 ElfFile *elfFile
)
{
  int retval = false;
  int fd = open(cubin.c_str(), O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
  if (fd != -1) {
    int len = elfFile->getLength();
    retval = write(fd, elfFile->getMemoryOriginal(), len) == len;
    close(fd);
  }
  return retval;
}

static bool
dumpDot
(
 const std::string &cubin,
 const std::string &dot,
 Dyninst::SymtabAPI::Symtab *the_symtab
)
{
  std::string cmd = "/sw/summitdev/cuda/9.2.148/bin/nvdisasm -cfg -poff " + cubin + " > " + dot;
  // for all symbols
  std::vector<Symbol *> symbols;
  the_symtab->getAllSymbols(symbols);
  if (system(cmd.c_str()) != 0) {  // failed, maybe caused by some functions
    std::vector<size_t> valid_function_index;
    // test valid symbols
    for (auto *symbol : symbols) {
      if (symbol->getType() == Dyninst::SymtabAPI::Symbol::ST_FUNCTION) {
        auto index = symbol->getIndex();
        cmd = "/sw/summitdev/cuda/9.2.148/bin/nvdisasm -fun " +
          std::to_string(index) + " -cfg -poff " + cubin + " > /dev/null";
        if (system(cmd.c_str()) == 0) {
          valid_function_index.push_back(index);
        }
      }
    }
    // only parse valid symbols
    if (!valid_function_index.empty()) {
      cmd = "/sw/summitdev/cuda/9.2.148/bin/nvdisasm -fun ";
      for (auto index : valid_function_index) {
        cmd += std::to_string(index) + ",";
      }
      cmd += " -cfg -poff " + cubin + " > " + dot;
      return system(cmd.c_str()) == 0;
    }
    return false;
  }
  return true;
}

static void
parseDotCFG
(
 const std::string &filename,
 std::vector<CudaParse::Function *> &functions
)
{
  CudaParse::GraphReader graph_reader(filename);
  CudaParse::Graph graph;
  graph_reader.read(graph);
  CudaParse::CFGParser cfg_parser;
  cfg_parser.parse(graph, functions);
}

static void
relocateFunctions
(
 Dyninst::SymtabAPI::Symtab *the_symtab,
 std::vector<CudaParse::Function *> &functions
)
{
  std::vector<Symbol *> symbols;
  the_symtab->getAllSymbols(symbols);
  for (auto *symbol : symbols) {
    for (auto *function : functions) {
      if (function->name == symbol->getMangledName()) {
        auto begin_offset = function->blocks[0]->begin_offset;
        for (auto *block : function->blocks) {
          for (auto *inst : block->insts) {
            inst->offset = (inst->offset - begin_offset) + symbol->getOffset();
          }
          block->address = block->insts[0]->offset;
        }
        function->blocks[0]->address = symbol->getOffset();
        function->address = symbol->getOffset();
      }
    }
  }
}

bool
readCubinCFG
(
 ElfFile *elfFile,
 Dyninst::SymtabAPI::Symtab *the_symtab,
 Dyninst::ParseAPI::CodeSource **code_src,
 Dyninst::ParseAPI::CodeObject **code_obj
)
{
  static bool nvdisasm_usable = test_nvdisasm();
  bool dump_cubin_success = false;
  bool dump_dot_success = false;

  if (nvdisasm_usable) {
    std::string filename = "tmp";
    std::string cubin = filename;
    std::string dot = filename + ".dot";

    dump_cubin_success = dumpCubin(cubin, elfFile);
    if (!dump_cubin_success) {
      std::cout << "WARNING: unable to write a cubin to the file system to analyze its CFG" << std::endl;
    } else {
      dump_dot_success = dumpDot(cubin, dot, the_symtab);
      if (!dump_dot_success) {
        std::cout << "WARNING: unable to use nvdisasm to produce a CFG for a cubin" << std::endl;
      } else {
        // Parse dot cfg
        // relocate instructions according to the
        // relocated symbols in the_symtab
        std::vector<CudaParse::Function *> functions;
        parseDotCFG(dot, functions);
        relocateFunctions(the_symtab, functions);

        CFGFactory *cfg_fact = new CudaCFGFactory(functions);
        *code_src = new CudaCodeSource(functions, the_symtab);
        *code_obj = new CodeObject(*code_src, cfg_fact);
        (*code_obj)->parse();
        return true;
      }
    }
  }

  *code_src = new SymtabCodeSource(the_symtab);
  *code_obj = new CodeObject(*code_src);

  return false;
}
<commit_msg>Remove nvdisasm path<commit_after>#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <set>

#include <CodeSource.h>
#include <CodeObject.h>
#include <CFGFactory.h>

#include <lib/binutils/VMAInterval.hpp>

#include "CudaCFGFactory.hpp"
#include "CudaFunction.hpp"
#include "CudaBlock.hpp"
#include "CudaCodeSource.hpp"
#include "CFGParser.hpp"
#include "GraphReader.hpp"
#include "ReadCubinCFG.hpp"

using namespace Dyninst;
using namespace ParseAPI;
using namespace SymtabAPI;
using namespace InstructionAPI;

static bool
test_nvdisasm()
{
  // check whether nvdisasm works
  int retval = system("nvdisasm > /dev/null") == 0;
  if (!retval) {
    std::cout << "WARNING: nvdisasm is not available on your path to analyze control flow in NVIDIA CUBINs" << std::endl;
  }
  return retval;
}

static bool
dumpCubin
(
 const std::string &cubin,
 ElfFile *elfFile
)
{
  int retval = false;
  int fd = open(cubin.c_str(), O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
  if (fd != -1) {
    int len = elfFile->getLength();
    retval = write(fd, elfFile->getMemoryOriginal(), len) == len;
    close(fd);
  }
  return retval;
}

static bool
dumpDot
(
 const std::string &cubin,
 const std::string &dot,
 Dyninst::SymtabAPI::Symtab *the_symtab
)
{
  std::string cmd = "nvdisasm -cfg -poff " + cubin + " > " + dot;
  // for all symbols
  std::vector<Symbol *> symbols;
  the_symtab->getAllSymbols(symbols);
  if (system(cmd.c_str()) != 0) {  // failed, maybe caused by some functions
    std::vector<size_t> valid_function_index;
    // test valid symbols
    for (auto *symbol : symbols) {
      if (symbol->getType() == Dyninst::SymtabAPI::Symbol::ST_FUNCTION) {
        auto index = symbol->getIndex();
        cmd = "nvdisasm -fun " +
          std::to_string(index) + " -cfg -poff " + cubin + " > /dev/null";
        if (system(cmd.c_str()) == 0) {
          valid_function_index.push_back(index);
        }
      }
    }
    // only parse valid symbols
    if (!valid_function_index.empty()) {
      cmd = "nvdisasm -fun ";
      for (auto index : valid_function_index) {
        cmd += std::to_string(index) + ",";
      }
      cmd += " -cfg -poff " + cubin + " > " + dot;
      return system(cmd.c_str()) == 0;
    }
    return false;
  }
  return true;
}

static void
parseDotCFG
(
 const std::string &filename,
 std::vector<CudaParse::Function *> &functions
)
{
  CudaParse::GraphReader graph_reader(filename);
  CudaParse::Graph graph;
  graph_reader.read(graph);
  CudaParse::CFGParser cfg_parser;
  cfg_parser.parse(graph, functions);
}

static void
relocateFunctions
(
 Dyninst::SymtabAPI::Symtab *the_symtab,
 std::vector<CudaParse::Function *> &functions
)
{
  std::vector<Symbol *> symbols;
  the_symtab->getAllSymbols(symbols);
  for (auto *symbol : symbols) {
    for (auto *function : functions) {
      if (function->name == symbol->getMangledName()) {
        auto begin_offset = function->blocks[0]->begin_offset;
        for (auto *block : function->blocks) {
          for (auto *inst : block->insts) {
            inst->offset = (inst->offset - begin_offset) + symbol->getOffset();
          }
          block->address = block->insts[0]->offset;
        }
        function->blocks[0]->address = symbol->getOffset();
        function->address = symbol->getOffset();
      }
    }
  }
}

bool
readCubinCFG
(
 ElfFile *elfFile,
 Dyninst::SymtabAPI::Symtab *the_symtab,
 Dyninst::ParseAPI::CodeSource **code_src,
 Dyninst::ParseAPI::CodeObject **code_obj
)
{
  static bool nvdisasm_usable = test_nvdisasm();
  bool dump_cubin_success = false;
  bool dump_dot_success = false;

  if (nvdisasm_usable) {
    std::string filename = "tmp";
    std::string cubin = filename;
    std::string dot = filename + ".dot";

    dump_cubin_success = dumpCubin(cubin, elfFile);
    if (!dump_cubin_success) {
      std::cout << "WARNING: unable to write a cubin to the file system to analyze its CFG" << std::endl;
    } else {
      dump_dot_success = dumpDot(cubin, dot, the_symtab);
      if (!dump_dot_success) {
        std::cout << "WARNING: unable to use nvdisasm to produce a CFG for a cubin" << std::endl;
      } else {
        // Parse dot cfg
        // relocate instructions according to the
        // relocated symbols in the_symtab
        std::vector<CudaParse::Function *> functions;
        parseDotCFG(dot, functions);
        relocateFunctions(the_symtab, functions);

        CFGFactory *cfg_fact = new CudaCFGFactory(functions);
        *code_src = new CudaCodeSource(functions, the_symtab);
        *code_obj = new CodeObject(*code_src, cfg_fact);
        (*code_obj)->parse();
        return true;
      }
    }
  }

  *code_src = new SymtabCodeSource(the_symtab);
  *code_obj = new CodeObject(*code_src);

  return false;
}
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2011-2012, John Haddon. All rights reserved.
//  Copyright (c) 2011-2013, Image Engine Design Inc. All rights reserved.
//
//  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 John Haddon nor the names of
//        any other contributors to this software 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.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/bind.hpp"
#include "boost/bind/placeholders.hpp"

#include "IECore/Exception.h"
#include "IECore/SimpleTypedData.h"

#include "Gaffer/ScriptNode.h"
#include "Gaffer/TypedPlug.h"
#include "Gaffer/Action.h"
#include "Gaffer/ApplicationRoot.h"
#include "Gaffer/Context.h"
#include "Gaffer/CompoundPlug.h"
#include "Gaffer/StandardSet.h"

using namespace Gaffer;

namespace Gaffer
{

GAFFER_DECLARECONTAINERSPECIALISATIONS( ScriptContainer, ScriptContainerTypeId )

}

IE_CORE_DEFINERUNTIMETYPED( ScriptNode );

size_t ScriptNode::g_firstPlugIndex = 0;

ScriptNode::ScriptNode( const std::string &name )
	:	Node( name ), m_selection( new StandardSet ), m_undoIterator( m_undoList.end() ), m_context( new Context )
{
	storeIndexOfNextChild( g_firstPlugIndex );

	addChild( new StringPlug( "fileName", Plug::In, "", Plug::Default & ~Plug::Serialisable ) );
	addChild( new BoolPlug( "unsavedChanges", Plug::In, false, Plug::Default & ~Plug::Serialisable ) );

	CompoundPlugPtr frameRangePlug = new CompoundPlug( "frameRange", Plug::In );
	IntPlugPtr frameStartPlug = new IntPlug( "start", Plug::In, 1 );
	IntPlugPtr frameEndPlug = new IntPlug( "end", Plug::In, 100 );
	frameRangePlug->addChild( frameStartPlug );
	frameRangePlug->addChild( frameEndPlug );
	addChild( frameRangePlug );

	m_selection->memberAcceptanceSignal().connect( boost::bind( &ScriptNode::selectionSetAcceptor, this, ::_1, ::_2 ) );

	childRemovedSignal().connect( boost::bind( &ScriptNode::childRemoved, this, ::_1, ::_2 ) );
	plugSetSignal().connect( boost::bind( &ScriptNode::plugSet, this, ::_1 ) );
}

ScriptNode::~ScriptNode()
{
}

bool ScriptNode::acceptsParent( const GraphComponent *potentialParent ) const
{
	return potentialParent->isInstanceOf( ScriptContainer::staticTypeId() );
}

ApplicationRoot *ScriptNode::applicationRoot()
{
	return ancestor<ApplicationRoot>();
}

const ApplicationRoot *ScriptNode::applicationRoot() const
{
	return ancestor<ApplicationRoot>();
}

bool ScriptNode::selectionSetAcceptor( const Set *s, const Set::Member *m )
{
	const Node *n = IECore::runTimeCast<const Node>( m );
	if( !n )
	{
		return false;
	}
	return this->isAncestorOf( n );
}

StandardSet *ScriptNode::selection()
{
	return m_selection.get();
}

const StandardSet *ScriptNode::selection() const
{
	return m_selection;
}

bool ScriptNode::undoAvailable() const
{
	return m_undoIterator != m_undoList.begin();
}

void ScriptNode::undo()
{
	if( !undoAvailable() )
	{
		throw IECore::Exception( "Nothing to undo" );
	}
	m_undoIterator--;
	for( ActionVector::reverse_iterator it=(*m_undoIterator)->rbegin(); it!=(*m_undoIterator)->rend(); it++ )
	{
		(*it)->undoAction();
		{
			UndoContext undoDisabled( this, UndoContext::Disabled );
			unsavedChangesPlug()->setValue( true );
		}
		actionSignal()( this, it->get(), Action::Undo );
	}
}

bool ScriptNode::redoAvailable() const
{
	return m_undoIterator != m_undoList.end();
}

void ScriptNode::redo()
{
	if( !redoAvailable() )
	{
		throw IECore::Exception( "Nothing to redo" );
	}
	for( ActionVector::iterator it=(*m_undoIterator)->begin(); it!=(*m_undoIterator)->end(); it++ )
	{
		(*it)->doAction();
		{
			UndoContext undoDisabled( this, UndoContext::Disabled );
			unsavedChangesPlug()->setValue( true );
		}
		actionSignal()( this, it->get(), Action::Redo );
	}
	m_undoIterator++;
}

ScriptNode::ActionSignal &ScriptNode::actionSignal()
{
	return m_actionSignal;
}

void ScriptNode::copy( const Node *parent, const Set *filter )
{
	ApplicationRoot *app = applicationRoot();
	if( !app )
	{
		throw( "ScriptNode has no ApplicationRoot" );
	}

	std::string s = serialise( parent, filter );
	app->setClipboardContents( new IECore::StringData( s ) );
}

void ScriptNode::cut( Node *parent, const Set *filter )
{
	copy( parent, filter );
	deleteNodes( parent, filter );
}

void ScriptNode::paste( Node *parent )
{
	ApplicationRoot *app = applicationRoot();
	if( !app )
	{
		throw( "ScriptNode has no ApplicationRoot" );
	}

	IECore::ConstStringDataPtr s = IECore::runTimeCast<const IECore::StringData>( app->getClipboardContents() );
	if( s )
	{
		parent = parent ? parent : this;
		// set up something to catch all the newly created nodes
		StandardSetPtr newNodes = new StandardSet;
		parent->childAddedSignal().connect( boost::bind( (bool (StandardSet::*)( IECore::RunTimeTypedPtr ) )&StandardSet::add, newNodes.get(), ::_2 ) );

			// do the paste
			execute( s->readable(), parent );

		// transfer the newly created nodes into the selection
		selection()->clear();
		for( size_t i = 0, e = newNodes->size(); i < e; i++ )
		{
			selection()->add( newNodes->member( i ) );
		}
	}
}

void ScriptNode::deleteNodes( Node *parent, const Set *filter, bool reconnect )
{
	parent = parent ? parent : this;
	// because children are stored as a vector, it's
	// much more efficient to delete those at the end before
	// those at the beginning.
	int i = (int)(parent->children().size()) - 1;
	while( i >= 0 )
	{
		Node *node = parent->getChild<Node>( i );
		if( node && ( !filter || filter->contains( node ) ) )
		{
			// reconnect the inputs and outputs as though the node was disabled
			if ( reconnect && node->enabledPlug() )
			{
				for ( OutputPlugIterator it( node ); it != it.end(); ++it )
				{
					Plug *inPlug = node->correspondingInput( *it );
					if ( !inPlug )
					{
						continue;
					}

					Plug *srcPlug = inPlug->getInput<Plug>();
					if ( !srcPlug )
					{
						continue;
					}

					const Plug::OutputContainer &outputs = (*it)->outputs();
					for ( Plug::OutputContainer::const_iterator oIt = outputs.begin(); oIt != outputs.end(); )
					{
						Plug *dstPlug = *oIt;
						if ( dstPlug && dstPlug->acceptsInput( srcPlug ) )
						{
							oIt++;
							dstPlug->setInput( srcPlug );
						}
					}
				}
			}

			parent->removeChild( node );
		}
		i--;
	}
}

StringPlug *ScriptNode::fileNamePlug()
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

const StringPlug *ScriptNode::fileNamePlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

BoolPlug *ScriptNode::unsavedChangesPlug()
{
	return getChild<BoolPlug>( g_firstPlugIndex + 1 );
}

const BoolPlug *ScriptNode::unsavedChangesPlug() const
{
	return getChild<BoolPlug>( g_firstPlugIndex + 1 );
}

void ScriptNode::execute( const std::string &pythonScript, Node *parent )
{
	throw IECore::Exception( "Cannot execute scripts on a ScriptNode not created in Python." );
}

ScriptNode::ScriptExecutedSignal &ScriptNode::scriptExecutedSignal()
{
	return m_scriptExecutedSignal;
}

PyObject *ScriptNode::evaluate( const std::string &pythonExpression, Node *parent )
{
	throw IECore::Exception( "Cannot execute scripts on a ScriptNode not created in Python." );
}

ScriptNode::ScriptEvaluatedSignal &ScriptNode::scriptEvaluatedSignal()
{
	return m_scriptEvaluatedSignal;
}

std::string ScriptNode::serialise( const Node *parent, const Set *filter ) const
{
	throw IECore::Exception( "Cannot serialise scripts on a ScriptNode not created in Python." );
}

void ScriptNode::load()
{
	throw IECore::Exception( "Cannot load scripts on a ScriptNode not created in Python." );
}

void ScriptNode::save() const
{
	throw IECore::Exception( "Cannot save scripts on a ScriptNode not created in Python." );
}

Context *ScriptNode::context()
{
	return m_context.get();
}

const Context *ScriptNode::context() const
{
	return m_context.get();
}

IntPlug *ScriptNode::frameStartPlug()
{
	return getChild<CompoundPlug>( g_firstPlugIndex + 2 )->getChild<IntPlug>( 0 );
}

const IntPlug *ScriptNode::frameStartPlug() const
{
	return getChild<CompoundPlug>( g_firstPlugIndex + 2 )->getChild<IntPlug>( 0 );
}

IntPlug *ScriptNode::frameEndPlug()
{
	return getChild<CompoundPlug>( g_firstPlugIndex + 2 )->getChild<IntPlug>( 1 );
}

const IntPlug *ScriptNode::frameEndPlug() const
{
	return getChild<CompoundPlug>( g_firstPlugIndex + 2 )->getChild<IntPlug>( 1 );
}

void ScriptNode::childRemoved( GraphComponent *parent, GraphComponent *child )
{
	m_selection->remove( child );
}

void ScriptNode::plugSet( Plug *plug )
{
	/// \todo Should we introduce some plug constraints classes to assist in managing these
	/// kinds of relationships?
	if( plug == frameStartPlug() )
	{
		frameEndPlug()->setValue( std::max( frameEndPlug()->getValue(), frameStartPlug()->getValue() ) );
	}
	else if( plug == frameEndPlug() )
	{
		frameStartPlug()->setValue( std::min( frameStartPlug()->getValue(), frameEndPlug()->getValue() ) );
	}
}
<commit_msg>fixing potential infinite loop<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2011-2012, John Haddon. All rights reserved.
//  Copyright (c) 2011-2013, Image Engine Design Inc. All rights reserved.
//
//  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 John Haddon nor the names of
//        any other contributors to this software 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.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/bind.hpp"
#include "boost/bind/placeholders.hpp"

#include "IECore/Exception.h"
#include "IECore/SimpleTypedData.h"

#include "Gaffer/ScriptNode.h"
#include "Gaffer/TypedPlug.h"
#include "Gaffer/Action.h"
#include "Gaffer/ApplicationRoot.h"
#include "Gaffer/Context.h"
#include "Gaffer/CompoundPlug.h"
#include "Gaffer/StandardSet.h"

using namespace Gaffer;

namespace Gaffer
{

GAFFER_DECLARECONTAINERSPECIALISATIONS( ScriptContainer, ScriptContainerTypeId )

}

IE_CORE_DEFINERUNTIMETYPED( ScriptNode );

size_t ScriptNode::g_firstPlugIndex = 0;

ScriptNode::ScriptNode( const std::string &name )
	:	Node( name ), m_selection( new StandardSet ), m_undoIterator( m_undoList.end() ), m_context( new Context )
{
	storeIndexOfNextChild( g_firstPlugIndex );

	addChild( new StringPlug( "fileName", Plug::In, "", Plug::Default & ~Plug::Serialisable ) );
	addChild( new BoolPlug( "unsavedChanges", Plug::In, false, Plug::Default & ~Plug::Serialisable ) );

	CompoundPlugPtr frameRangePlug = new CompoundPlug( "frameRange", Plug::In );
	IntPlugPtr frameStartPlug = new IntPlug( "start", Plug::In, 1 );
	IntPlugPtr frameEndPlug = new IntPlug( "end", Plug::In, 100 );
	frameRangePlug->addChild( frameStartPlug );
	frameRangePlug->addChild( frameEndPlug );
	addChild( frameRangePlug );

	m_selection->memberAcceptanceSignal().connect( boost::bind( &ScriptNode::selectionSetAcceptor, this, ::_1, ::_2 ) );

	childRemovedSignal().connect( boost::bind( &ScriptNode::childRemoved, this, ::_1, ::_2 ) );
	plugSetSignal().connect( boost::bind( &ScriptNode::plugSet, this, ::_1 ) );
}

ScriptNode::~ScriptNode()
{
}

bool ScriptNode::acceptsParent( const GraphComponent *potentialParent ) const
{
	return potentialParent->isInstanceOf( ScriptContainer::staticTypeId() );
}

ApplicationRoot *ScriptNode::applicationRoot()
{
	return ancestor<ApplicationRoot>();
}

const ApplicationRoot *ScriptNode::applicationRoot() const
{
	return ancestor<ApplicationRoot>();
}

bool ScriptNode::selectionSetAcceptor( const Set *s, const Set::Member *m )
{
	const Node *n = IECore::runTimeCast<const Node>( m );
	if( !n )
	{
		return false;
	}
	return this->isAncestorOf( n );
}

StandardSet *ScriptNode::selection()
{
	return m_selection.get();
}

const StandardSet *ScriptNode::selection() const
{
	return m_selection;
}

bool ScriptNode::undoAvailable() const
{
	return m_undoIterator != m_undoList.begin();
}

void ScriptNode::undo()
{
	if( !undoAvailable() )
	{
		throw IECore::Exception( "Nothing to undo" );
	}
	m_undoIterator--;
	for( ActionVector::reverse_iterator it=(*m_undoIterator)->rbegin(); it!=(*m_undoIterator)->rend(); it++ )
	{
		(*it)->undoAction();
		{
			UndoContext undoDisabled( this, UndoContext::Disabled );
			unsavedChangesPlug()->setValue( true );
		}
		actionSignal()( this, it->get(), Action::Undo );
	}
}

bool ScriptNode::redoAvailable() const
{
	return m_undoIterator != m_undoList.end();
}

void ScriptNode::redo()
{
	if( !redoAvailable() )
	{
		throw IECore::Exception( "Nothing to redo" );
	}
	for( ActionVector::iterator it=(*m_undoIterator)->begin(); it!=(*m_undoIterator)->end(); it++ )
	{
		(*it)->doAction();
		{
			UndoContext undoDisabled( this, UndoContext::Disabled );
			unsavedChangesPlug()->setValue( true );
		}
		actionSignal()( this, it->get(), Action::Redo );
	}
	m_undoIterator++;
}

ScriptNode::ActionSignal &ScriptNode::actionSignal()
{
	return m_actionSignal;
}

void ScriptNode::copy( const Node *parent, const Set *filter )
{
	ApplicationRoot *app = applicationRoot();
	if( !app )
	{
		throw( "ScriptNode has no ApplicationRoot" );
	}

	std::string s = serialise( parent, filter );
	app->setClipboardContents( new IECore::StringData( s ) );
}

void ScriptNode::cut( Node *parent, const Set *filter )
{
	copy( parent, filter );
	deleteNodes( parent, filter );
}

void ScriptNode::paste( Node *parent )
{
	ApplicationRoot *app = applicationRoot();
	if( !app )
	{
		throw( "ScriptNode has no ApplicationRoot" );
	}

	IECore::ConstStringDataPtr s = IECore::runTimeCast<const IECore::StringData>( app->getClipboardContents() );
	if( s )
	{
		parent = parent ? parent : this;
		// set up something to catch all the newly created nodes
		StandardSetPtr newNodes = new StandardSet;
		parent->childAddedSignal().connect( boost::bind( (bool (StandardSet::*)( IECore::RunTimeTypedPtr ) )&StandardSet::add, newNodes.get(), ::_2 ) );

			// do the paste
			execute( s->readable(), parent );

		// transfer the newly created nodes into the selection
		selection()->clear();
		for( size_t i = 0, e = newNodes->size(); i < e; i++ )
		{
			selection()->add( newNodes->member( i ) );
		}
	}
}

void ScriptNode::deleteNodes( Node *parent, const Set *filter, bool reconnect )
{
	parent = parent ? parent : this;
	// because children are stored as a vector, it's
	// much more efficient to delete those at the end before
	// those at the beginning.
	int i = (int)(parent->children().size()) - 1;
	while( i >= 0 )
	{
		Node *node = parent->getChild<Node>( i );
		if( node && ( !filter || filter->contains( node ) ) )
		{
			// reconnect the inputs and outputs as though the node was disabled
			if ( reconnect && node->enabledPlug() )
			{
				for ( OutputPlugIterator it( node ); it != it.end(); ++it )
				{
					Plug *inPlug = node->correspondingInput( *it );
					if ( !inPlug )
					{
						continue;
					}

					Plug *srcPlug = inPlug->getInput<Plug>();
					if ( !srcPlug )
					{
						continue;
					}

					const Plug::OutputContainer &outputs = (*it)->outputs();
					for ( Plug::OutputContainer::const_iterator oIt = outputs.begin(); oIt != outputs.end(); )
					{
						Plug *dstPlug = *oIt;
						if ( dstPlug && dstPlug->acceptsInput( srcPlug ) )
						{
							oIt++;
							dstPlug->setInput( srcPlug );
						}
						else
						{
							oIt++;
						}
					}
				}
			}

			parent->removeChild( node );
		}
		i--;
	}
}

StringPlug *ScriptNode::fileNamePlug()
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

const StringPlug *ScriptNode::fileNamePlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

BoolPlug *ScriptNode::unsavedChangesPlug()
{
	return getChild<BoolPlug>( g_firstPlugIndex + 1 );
}

const BoolPlug *ScriptNode::unsavedChangesPlug() const
{
	return getChild<BoolPlug>( g_firstPlugIndex + 1 );
}

void ScriptNode::execute( const std::string &pythonScript, Node *parent )
{
	throw IECore::Exception( "Cannot execute scripts on a ScriptNode not created in Python." );
}

ScriptNode::ScriptExecutedSignal &ScriptNode::scriptExecutedSignal()
{
	return m_scriptExecutedSignal;
}

PyObject *ScriptNode::evaluate( const std::string &pythonExpression, Node *parent )
{
	throw IECore::Exception( "Cannot execute scripts on a ScriptNode not created in Python." );
}

ScriptNode::ScriptEvaluatedSignal &ScriptNode::scriptEvaluatedSignal()
{
	return m_scriptEvaluatedSignal;
}

std::string ScriptNode::serialise( const Node *parent, const Set *filter ) const
{
	throw IECore::Exception( "Cannot serialise scripts on a ScriptNode not created in Python." );
}

void ScriptNode::load()
{
	throw IECore::Exception( "Cannot load scripts on a ScriptNode not created in Python." );
}

void ScriptNode::save() const
{
	throw IECore::Exception( "Cannot save scripts on a ScriptNode not created in Python." );
}

Context *ScriptNode::context()
{
	return m_context.get();
}

const Context *ScriptNode::context() const
{
	return m_context.get();
}

IntPlug *ScriptNode::frameStartPlug()
{
	return getChild<CompoundPlug>( g_firstPlugIndex + 2 )->getChild<IntPlug>( 0 );
}

const IntPlug *ScriptNode::frameStartPlug() const
{
	return getChild<CompoundPlug>( g_firstPlugIndex + 2 )->getChild<IntPlug>( 0 );
}

IntPlug *ScriptNode::frameEndPlug()
{
	return getChild<CompoundPlug>( g_firstPlugIndex + 2 )->getChild<IntPlug>( 1 );
}

const IntPlug *ScriptNode::frameEndPlug() const
{
	return getChild<CompoundPlug>( g_firstPlugIndex + 2 )->getChild<IntPlug>( 1 );
}

void ScriptNode::childRemoved( GraphComponent *parent, GraphComponent *child )
{
	m_selection->remove( child );
}

void ScriptNode::plugSet( Plug *plug )
{
	/// \todo Should we introduce some plug constraints classes to assist in managing these
	/// kinds of relationships?
	if( plug == frameStartPlug() )
	{
		frameEndPlug()->setValue( std::max( frameEndPlug()->getValue(), frameStartPlug()->getValue() ) );
	}
	else if( plug == frameEndPlug() )
	{
		frameStartPlug()->setValue( std::min( frameStartPlug()->getValue(), frameEndPlug()->getValue() ) );
	}
}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (c) 2004 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifndef _PreComp_
# include <QApplication>
# include <QLocale>
# include <QStyleFactory>
# include <QTextStream>
#endif

#include "DlgGeneralImp.h"
#include "Action.h"
#include "Application.h"
#include "DockWindowManager.h"
#include "MainWindow.h"
#include "PrefWidgets.h"
#include "Language/Translator.h"

using namespace Gui::Dialog;

/* TRANSLATOR Gui::Dialog::DlgGeneralImp */

/**
 *  Constructs a DlgGeneralImp which is a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'
 *
 *  The dialog will by default be modeless, unless you set 'modal' to
 *  true to construct a modal dialog.
 */
DlgGeneralImp::DlgGeneralImp( QWidget* parent )
  : PreferencePage( parent ), watched(0)
{
    this->setupUi(this);
    // hide to fix 0000375: Mac Interface window style setting not saved
    windowStyleLabel->hide();
    WindowStyle->hide();

    // fills the combo box with all available workbenches
    // sorted by their menu text
    QStringList work = Application::Instance->workbenches();
    QMap<QString, QString> menuText;
    for (QStringList::Iterator it = work.begin(); it != work.end(); ++it) {
        QString text = Application::Instance->workbenchMenuText(*it);
        menuText[text] = *it;
    }

    for (QMap<QString, QString>::Iterator it = menuText.begin(); it != menuText.end(); ++it) {
        QPixmap px = Application::Instance->workbenchIcon(it.value());
        if (px.isNull())
            AutoloadModuleCombo->addItem(it.key(), QVariant(it.value()));
        else
            AutoloadModuleCombo->addItem(px, it.key(), QVariant(it.value()));
    }

    // do not save the content but the current item only
    QWidget* dw = DockWindowManager::instance()->getDockWindow("Report view");
    if (dw)
    {
        watched = dw->findChild<QTabWidget*>();
        if (watched)
        {
            for (int i=0; i<watched->count(); i++)
                AutoloadTabCombo->addItem( watched->tabText(i) );
            watched->installEventFilter(this);
        }
    }
    if (!watched) {
        // use separate dock widgets instead of the old tab widget
        tabReportLabel->hide();
        AutoloadTabCombo->hide();
    }
}

/**
 *  Destroys the object and frees any allocated resources
 */
DlgGeneralImp::~DlgGeneralImp()
{
    // no need to delete child widgets, Qt does it all for us
    if (watched)
        watched->removeEventFilter(this);
}

/** Sets the size of the recent file list from the user parameters.
 * @see RecentFilesAction
 * @see StdCmdRecentFiles
 */
void DlgGeneralImp::setRecentFileSize()
{
    RecentFilesAction *recent = getMainWindow()->findChild<RecentFilesAction *>(QLatin1String("recentFiles"));
    if (recent) {
        ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("RecentFiles");
        recent->resizeList(hGrp->GetInt("RecentFiles", 4));
    }
}

void DlgGeneralImp::saveSettings()
{
    int index = AutoloadModuleCombo->currentIndex();
    QVariant data = AutoloadModuleCombo->itemData(index);
    QString startWbName = data.toString();
    App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")->
                          SetASCII("AutoloadModule", startWbName.toLatin1());

    AutoloadTabCombo->onSave();
    RecentFiles->onSave();
    SplashScreen->onSave();

    // set new user defined style
    //(void)QApplication::setStyle(WindowStyle->currentText());

    setRecentFileSize();
    ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("General");
    QString lang = QLocale::languageToString(QLocale::system().language());
    QByteArray language = hGrp->GetASCII("Language", (const char*)lang.toLatin1()).c_str();
    QByteArray current = Languages->itemData(Languages->currentIndex()).toByteArray();
    if (current != language)
    {
        hGrp->SetASCII("Language", current.constData());
        Translator::instance()->activateLanguage(current.constData());
    }

    QVariant size = this->toolbarIconSize->itemData(this->toolbarIconSize->currentIndex());
    int pixel = size.toInt();
    hGrp->SetInt("ToolbarIconSize", pixel);
    getMainWindow()->setIconSize(QSize(pixel,pixel));

    hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow");
    hGrp->SetBool("TiledBackground", this->tiledBackground->isChecked());
    QMdiArea* mdi = getMainWindow()->findChild<QMdiArea*>();
    mdi->setProperty("showImage", this->tiledBackground->isChecked());

    QVariant sheet = this->StyleSheets->itemData(this->StyleSheets->currentIndex());
    if (this->selectedStyleSheet != sheet.toString()) {
        this->selectedStyleSheet = sheet.toString();
        hGrp->SetASCII("StyleSheet", (const char*)sheet.toByteArray());

        if (!sheet.toString().isEmpty()) {
            QFile f(sheet.toString());
            if (f.open(QFile::ReadOnly)) {
                mdi->setBackground(QBrush(Qt::NoBrush));
                QTextStream str(&f);
                qApp->setStyleSheet(str.readAll());

                ActionStyleEvent e(ActionStyleEvent::Clear);
                qApp->sendEvent(getMainWindow(), &e);
            }
        }
    }

    if (sheet.toString().isEmpty()) {
        if (this->tiledBackground->isChecked()) {
            qApp->setStyleSheet(QString());
            ActionStyleEvent e(ActionStyleEvent::Restore);
            qApp->sendEvent(getMainWindow(), &e);
            mdi->setBackground(QPixmap(QLatin1String(":/icons/background.png")));
        }
        else {
            qApp->setStyleSheet(QString());
            ActionStyleEvent e(ActionStyleEvent::Restore);
            qApp->sendEvent(getMainWindow(), &e);
            mdi->setBackground(QBrush(QColor(160,160,160)));
        }
    }

    if (mdi->style())
        mdi->style()->unpolish(qApp);
}

void DlgGeneralImp::loadSettings()
{
    std::string start = App::Application::Config()["StartWorkbench"];
    start = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")->
                                  GetASCII("AutoloadModule", start.c_str());
    QString startWbName = QLatin1String(start.c_str());
    AutoloadModuleCombo->setCurrentIndex(AutoloadModuleCombo->findData(startWbName));

    AutoloadTabCombo->onRestore();
    RecentFiles->onRestore();
    SplashScreen->onRestore();

    // fill up styles
    //
    QStringList styles = QStyleFactory::keys();
    WindowStyle->addItems(styles);
    QString style = QApplication::style()->objectName().toLower();
    int i=0;
    for (QStringList::ConstIterator it = styles.begin(); it != styles.end(); ++it, i++) {
        if (style == (*it).toLower()) {
            WindowStyle->setCurrentIndex( i );
            break;
        }
    }

    // search for the language files
    ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("General");
    QString lang = QLocale::languageToString(QLocale::system().language());
    QByteArray language = hGrp->GetASCII("Language", (const char*)lang.toLatin1()).c_str();
    int index = 1;
    Languages->addItem(QString::fromLatin1("English"), QByteArray("English"));
    TStringMap list = Translator::instance()->supportedLocales();
    for (TStringMap::iterator it = list.begin(); it != list.end(); ++it, index++) {
        QLocale locale(QString::fromLatin1(it->second.c_str()));
        QByteArray lang = it->first.c_str();
        QString langname = QString::fromLatin1(lang.constData());
#if QT_VERSION >= 0x040800
        QString native = locale.nativeLanguageName();
        if (!native.isEmpty()) {
            if (native[0].isLetter())
                native[0] = native[0].toUpper();
            langname = native;
        }
#endif
        Languages->addItem(langname, lang);
        if (language == lang) {
            Languages->setCurrentIndex(index);
        }
    }

    int current = getMainWindow()->iconSize().width();
    this->toolbarIconSize->addItem(tr("Small (%1)").arg(16), QVariant((int)16));
    this->toolbarIconSize->addItem(tr("Medium (%1)").arg(24), QVariant((int)24));
    this->toolbarIconSize->addItem(tr("Large (%1)").arg(32), QVariant((int)32));
    this->toolbarIconSize->addItem(tr("Extra large (%1)").arg(48), QVariant((int)48));
    index = this->toolbarIconSize->findData(QVariant(current));
    if (index > -1) this->toolbarIconSize->setCurrentIndex(index);

    hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow");
    this->tiledBackground->setChecked(hGrp->GetBool("TiledBackground", false));

    // List all .qss/.css files
    QMap<QString, QString> cssFiles;
    QDir dir;
    QStringList filter;
    filter << QString::fromLatin1("*.qss");
    filter << QString::fromLatin1("*.css");
    QFileInfoList fileNames;

    // read from user, resource and built-in directory
    QStringList qssPaths = QDir::searchPaths(QString::fromLatin1("qss"));
    for (QStringList::iterator it = qssPaths.begin(); it != qssPaths.end(); ++it) {
        dir.setPath(*it);
        fileNames = dir.entryInfoList(filter, QDir::Files, QDir::Name);
        for (QFileInfoList::iterator jt = fileNames.begin(); jt != fileNames.end(); ++jt) {
            if (cssFiles.find(jt->baseName()) == cssFiles.end()) {
                cssFiles[jt->baseName()] = jt->absoluteFilePath();
            }
        }
    }

    // now add all unique items
    this->StyleSheets->addItem(tr("No style sheet"), QString::fromLatin1(""));
    for (QMap<QString, QString>::iterator it = cssFiles.begin(); it != cssFiles.end(); ++it) {
        this->StyleSheets->addItem(it.key(), it.value());
    }

    this->selectedStyleSheet = QString::fromLatin1(hGrp->GetASCII("StyleSheet").c_str());
    index = this->StyleSheets->findData(this->selectedStyleSheet);
    if (index > -1) this->StyleSheets->setCurrentIndex(index);
}

void DlgGeneralImp::changeEvent(QEvent *e)
{
    if (e->type() == QEvent::LanguageChange) {
        retranslateUi(this);
        for (int i = 0; i < Languages->count(); i++) {
            QByteArray lang = Languages->itemData(i).toByteArray();
            Languages->setItemText(i, Gui::Translator::tr(lang.constData()));
        }
    } else {
        QWidget::changeEvent(e);
    }
}

bool DlgGeneralImp::eventFilter(QObject* o, QEvent* e)
{
    // make sure that report tabs have been translated
    if (o == watched && e->type() == QEvent::LanguageChange) {
        for (int i=0; i<watched->count(); i++)
            AutoloadTabCombo->setItemText( i, watched->tabText(i) );
    }

    return QWidget::eventFilter(o, e);
}

#include "moc_DlgGeneralImp.cpp"
<commit_msg>Show icon units<commit_after>/***************************************************************************
 *   Copyright (c) 2004 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#ifndef _PreComp_
# include <QApplication>
# include <QLocale>
# include <QStyleFactory>
# include <QTextStream>
#endif

#include "DlgGeneralImp.h"
#include "Action.h"
#include "Application.h"
#include "DockWindowManager.h"
#include "MainWindow.h"
#include "PrefWidgets.h"
#include "Language/Translator.h"

using namespace Gui::Dialog;

/* TRANSLATOR Gui::Dialog::DlgGeneralImp */

/**
 *  Constructs a DlgGeneralImp which is a child of 'parent', with the
 *  name 'name' and widget flags set to 'f'
 *
 *  The dialog will by default be modeless, unless you set 'modal' to
 *  true to construct a modal dialog.
 */
DlgGeneralImp::DlgGeneralImp( QWidget* parent )
  : PreferencePage( parent ), watched(0)
{
    this->setupUi(this);
    // hide to fix 0000375: Mac Interface window style setting not saved
    windowStyleLabel->hide();
    WindowStyle->hide();

    // fills the combo box with all available workbenches
    // sorted by their menu text
    QStringList work = Application::Instance->workbenches();
    QMap<QString, QString> menuText;
    for (QStringList::Iterator it = work.begin(); it != work.end(); ++it) {
        QString text = Application::Instance->workbenchMenuText(*it);
        menuText[text] = *it;
    }

    for (QMap<QString, QString>::Iterator it = menuText.begin(); it != menuText.end(); ++it) {
        QPixmap px = Application::Instance->workbenchIcon(it.value());
        if (px.isNull())
            AutoloadModuleCombo->addItem(it.key(), QVariant(it.value()));
        else
            AutoloadModuleCombo->addItem(px, it.key(), QVariant(it.value()));
    }

    // do not save the content but the current item only
    QWidget* dw = DockWindowManager::instance()->getDockWindow("Report view");
    if (dw)
    {
        watched = dw->findChild<QTabWidget*>();
        if (watched)
        {
            for (int i=0; i<watched->count(); i++)
                AutoloadTabCombo->addItem( watched->tabText(i) );
            watched->installEventFilter(this);
        }
    }
    if (!watched) {
        // use separate dock widgets instead of the old tab widget
        tabReportLabel->hide();
        AutoloadTabCombo->hide();
    }
}

/**
 *  Destroys the object and frees any allocated resources
 */
DlgGeneralImp::~DlgGeneralImp()
{
    // no need to delete child widgets, Qt does it all for us
    if (watched)
        watched->removeEventFilter(this);
}

/** Sets the size of the recent file list from the user parameters.
 * @see RecentFilesAction
 * @see StdCmdRecentFiles
 */
void DlgGeneralImp::setRecentFileSize()
{
    RecentFilesAction *recent = getMainWindow()->findChild<RecentFilesAction *>(QLatin1String("recentFiles"));
    if (recent) {
        ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("RecentFiles");
        recent->resizeList(hGrp->GetInt("RecentFiles", 4));
    }
}

void DlgGeneralImp::saveSettings()
{
    int index = AutoloadModuleCombo->currentIndex();
    QVariant data = AutoloadModuleCombo->itemData(index);
    QString startWbName = data.toString();
    App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")->
                          SetASCII("AutoloadModule", startWbName.toLatin1());

    AutoloadTabCombo->onSave();
    RecentFiles->onSave();
    SplashScreen->onSave();

    // set new user defined style
    //(void)QApplication::setStyle(WindowStyle->currentText());

    setRecentFileSize();
    ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("General");
    QString lang = QLocale::languageToString(QLocale::system().language());
    QByteArray language = hGrp->GetASCII("Language", (const char*)lang.toLatin1()).c_str();
    QByteArray current = Languages->itemData(Languages->currentIndex()).toByteArray();
    if (current != language)
    {
        hGrp->SetASCII("Language", current.constData());
        Translator::instance()->activateLanguage(current.constData());
    }

    QVariant size = this->toolbarIconSize->itemData(this->toolbarIconSize->currentIndex());
    int pixel = size.toInt();
    hGrp->SetInt("ToolbarIconSize", pixel);
    getMainWindow()->setIconSize(QSize(pixel,pixel));

    hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow");
    hGrp->SetBool("TiledBackground", this->tiledBackground->isChecked());
    QMdiArea* mdi = getMainWindow()->findChild<QMdiArea*>();
    mdi->setProperty("showImage", this->tiledBackground->isChecked());

    QVariant sheet = this->StyleSheets->itemData(this->StyleSheets->currentIndex());
    if (this->selectedStyleSheet != sheet.toString()) {
        this->selectedStyleSheet = sheet.toString();
        hGrp->SetASCII("StyleSheet", (const char*)sheet.toByteArray());

        if (!sheet.toString().isEmpty()) {
            QFile f(sheet.toString());
            if (f.open(QFile::ReadOnly)) {
                mdi->setBackground(QBrush(Qt::NoBrush));
                QTextStream str(&f);
                qApp->setStyleSheet(str.readAll());

                ActionStyleEvent e(ActionStyleEvent::Clear);
                qApp->sendEvent(getMainWindow(), &e);
            }
        }
    }

    if (sheet.toString().isEmpty()) {
        if (this->tiledBackground->isChecked()) {
            qApp->setStyleSheet(QString());
            ActionStyleEvent e(ActionStyleEvent::Restore);
            qApp->sendEvent(getMainWindow(), &e);
            mdi->setBackground(QPixmap(QLatin1String(":/icons/background.png")));
        }
        else {
            qApp->setStyleSheet(QString());
            ActionStyleEvent e(ActionStyleEvent::Restore);
            qApp->sendEvent(getMainWindow(), &e);
            mdi->setBackground(QBrush(QColor(160,160,160)));
        }
    }

    if (mdi->style())
        mdi->style()->unpolish(qApp);
}

void DlgGeneralImp::loadSettings()
{
    std::string start = App::Application::Config()["StartWorkbench"];
    start = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")->
                                  GetASCII("AutoloadModule", start.c_str());
    QString startWbName = QLatin1String(start.c_str());
    AutoloadModuleCombo->setCurrentIndex(AutoloadModuleCombo->findData(startWbName));

    AutoloadTabCombo->onRestore();
    RecentFiles->onRestore();
    SplashScreen->onRestore();

    // fill up styles
    //
    QStringList styles = QStyleFactory::keys();
    WindowStyle->addItems(styles);
    QString style = QApplication::style()->objectName().toLower();
    int i=0;
    for (QStringList::ConstIterator it = styles.begin(); it != styles.end(); ++it, i++) {
        if (style == (*it).toLower()) {
            WindowStyle->setCurrentIndex( i );
            break;
        }
    }

    // search for the language files
    ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("General");
    QString lang = QLocale::languageToString(QLocale::system().language());
    QByteArray language = hGrp->GetASCII("Language", (const char*)lang.toLatin1()).c_str();
    int index = 1;
    Languages->addItem(QString::fromLatin1("English"), QByteArray("English"));
    TStringMap list = Translator::instance()->supportedLocales();
    for (TStringMap::iterator it = list.begin(); it != list.end(); ++it, index++) {
        QLocale locale(QString::fromLatin1(it->second.c_str()));
        QByteArray lang = it->first.c_str();
        QString langname = QString::fromLatin1(lang.constData());
#if QT_VERSION >= 0x040800
        QString native = locale.nativeLanguageName();
        if (!native.isEmpty()) {
            if (native[0].isLetter())
                native[0] = native[0].toUpper();
            langname = native;
        }
#endif
        Languages->addItem(langname, lang);
        if (language == lang) {
            Languages->setCurrentIndex(index);
        }
    }

    int current = getMainWindow()->iconSize().width();
    this->toolbarIconSize->addItem(tr("Small (%1px)").arg(16), QVariant((int)16));
    this->toolbarIconSize->addItem(tr("Medium (%1px)").arg(24), QVariant((int)24));
    this->toolbarIconSize->addItem(tr("Large (%1px)").arg(32), QVariant((int)32));
    this->toolbarIconSize->addItem(tr("Extra large (%1px)").arg(48), QVariant((int)48));
    index = this->toolbarIconSize->findData(QVariant(current));
    if (index > -1) this->toolbarIconSize->setCurrentIndex(index);

    hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/MainWindow");
    this->tiledBackground->setChecked(hGrp->GetBool("TiledBackground", false));

    // List all .qss/.css files
    QMap<QString, QString> cssFiles;
    QDir dir;
    QStringList filter;
    filter << QString::fromLatin1("*.qss");
    filter << QString::fromLatin1("*.css");
    QFileInfoList fileNames;

    // read from user, resource and built-in directory
    QStringList qssPaths = QDir::searchPaths(QString::fromLatin1("qss"));
    for (QStringList::iterator it = qssPaths.begin(); it != qssPaths.end(); ++it) {
        dir.setPath(*it);
        fileNames = dir.entryInfoList(filter, QDir::Files, QDir::Name);
        for (QFileInfoList::iterator jt = fileNames.begin(); jt != fileNames.end(); ++jt) {
            if (cssFiles.find(jt->baseName()) == cssFiles.end()) {
                cssFiles[jt->baseName()] = jt->absoluteFilePath();
            }
        }
    }

    // now add all unique items
    this->StyleSheets->addItem(tr("No style sheet"), QString::fromLatin1(""));
    for (QMap<QString, QString>::iterator it = cssFiles.begin(); it != cssFiles.end(); ++it) {
        this->StyleSheets->addItem(it.key(), it.value());
    }

    this->selectedStyleSheet = QString::fromLatin1(hGrp->GetASCII("StyleSheet").c_str());
    index = this->StyleSheets->findData(this->selectedStyleSheet);
    if (index > -1) this->StyleSheets->setCurrentIndex(index);
}

void DlgGeneralImp::changeEvent(QEvent *e)
{
    if (e->type() == QEvent::LanguageChange) {
        retranslateUi(this);
        for (int i = 0; i < Languages->count(); i++) {
            QByteArray lang = Languages->itemData(i).toByteArray();
            Languages->setItemText(i, Gui::Translator::tr(lang.constData()));
        }
    } else {
        QWidget::changeEvent(e);
    }
}

bool DlgGeneralImp::eventFilter(QObject* o, QEvent* e)
{
    // make sure that report tabs have been translated
    if (o == watched && e->type() == QEvent::LanguageChange) {
        for (int i=0; i<watched->count(); i++)
            AutoloadTabCombo->setItemText( i, watched->tabText(i) );
    }

    return QWidget::eventFilter(o, e);
}

#include "moc_DlgGeneralImp.cpp"
<|endoftext|>


<commit_before>//===========================================
//  Lumina-DE source code
//  Copyright (c) 2016, Ken Moore
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================
#include "session.h"

#include <QObject>
#include <QProcess>
#include <QProcessEnvironment>
#include <QDebug>
#include <LuminaUtils.h>

void LSession::stopall(){
  stopping = true;
  for(int i=0; i<PROCS.length(); i++){
    if(PROCS[i]->state()!=QProcess::NotRunning){ PROCS[i]->kill(); }
  }
  QCoreApplication::processEvents();
  for(int i=0; i<PROCS.length(); i++){
    if(PROCS[i]->state()!=QProcess::NotRunning){ PROCS[i]->terminate(); }
  }
  //QCoreApplication::exit(0);
}

void LSession::procFinished(){
  //Go through and check the status on all the procs to determine which one finished
  int stopped = 0;
  for(int i=0; i<PROCS.length(); i++){
    if(PROCS[i]->state()==QProcess::NotRunning){
      stopped++;
      if(!stopping){
        //See if this process is the main desktop binary
        if(PROCS[i]->program().section("/",-1) == "lumina-desktop"){ stopall();  } //start closing down everything
        //else{ PROCS[i]->start(QIODevice::ReadOnly); } //restart the process
        break;
      }
    }
  }
  if(stopping && stopped==PROCS.length()){
    QCoreApplication::exit(0);
  }
}

void LSession::startProcess(QString ID, QString command, QStringList watchfiles){
  QString dir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/logs";
  if(!QFile::exists(dir)){ QDir tmp(dir); tmp.mkpath(dir); }
  QString logfile = dir+"/"+ID+".log";
  if(QFile::exists(logfile+".old")){ QFile::remove(logfile+".old"); }
  if(QFile::exists(logfile)){ QFile::rename(logfile,logfile+".old"); }

  LProcess *proc = new LProcess(ID, watchfiles);
  proc->setProcessChannelMode(QProcess::MergedChannels);
  proc->setProcessEnvironment( QProcessEnvironment::systemEnvironment() );
  proc->setStandardOutputFile(logfile);
  proc->start(command, QIODevice::ReadOnly);
  connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(procFinished()) );
  PROCS << proc;
}

void LSession::start(){
  //First check for a valid installation
  if( !LUtils::isValidBinary("fluxbox") || !LUtils::isValidBinary("lumina-desktop") ){
    exit(1);
  }
  //Window Manager First
  // FLUXBOX BUG BYPASS: if the ~/.fluxbox dir does not exist, it will ignore the given config file
  if( !LUtils::isValidBinary("fluxbox") ){
    qDebug() << "[INCOMPLETE LUMINA INSTALLATION] fluxbox binary is missing - cannot continue";
  }else{
    QString confDir = QString( getenv("XDG_CONFIG_HOME"))+"/lumina-desktop";
    if(!QFile::exists(confDir)){ QDir dir(confDir); dir.mkpath(confDir); }
    if(!QFile::exists(confDir+"/fluxbox-init")){
      QFile::copy(":/fluxboxconf/fluxbox-init-rc",confDir+"/fluxbox-init");
      QFile::setPermissions(confDir+"/fluxbox-init", QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::ReadOther | QFile::ReadGroup);
    }
    // FLUXBOX BUG BYPASS: if the ~/.fluxbox dir does not exist, it will ignore the given config file
    if(!QFile::exists(QDir::homePath()+"/.fluxbox")){
      QDir dir; dir.mkpath(QDir::homePath()+"/.fluxbox");
    }
    QString cmd = "fluxbox -rc "+confDir+"/fluxbox-init -no-slit -no-toolbar";
    startProcess("wm", cmd, QStringList() << confDir+"/fluxbox-init" << confDir+"/fluxbox-keys");
  }
  //Compositing manager
  if(LUtils::isValidBinary("compton")){
    QString set = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/compton.conf";
    if(!QFile::exists(set)){
      QStringList dirs = QString(getenv("XDG_CONFIG_DIRS")).split(":");
      for(int i=0; i<dirs.length(); i++){
        if(QFile::exists(dirs[i]+"/compton.conf")){ QFile::copy(dirs[i]+"/compton.conf", set); break; }
        else if(QFile::exists(dirs[i]+"/compton.conf.sample")){ QFile::copy(dirs[i]+"/compton.conf.sample", set); break; }
      }
    }
    if(!QFile::exists(set)){
      qDebug() << "Using default compton settings";
      startProcess("compositing","compton");
    }else{
      startProcess("compositing","compton --config \""+set+"\"", QStringList() << set);
    }
  }else if(LUtils::isValidBinary("xcompmgr")){ startProcess("compositing","xcompmgr"); }

  //Desktop Next
  startProcess("runtime","lumina-desktop");
  //ScreenSaver
  if(LUtils::isValidBinary("xscreensaver")){ startProcess("screensaver","xscreensaver -no-splash"); }

}
<commit_msg>Fix up the copy/adjustment of the fluxbox config files when initializing the user's settings for Lumina.<commit_after>//===========================================
//  Lumina-DE source code
//  Copyright (c) 2016, Ken Moore
//  Available under the 3-clause BSD license
//  See the LICENSE file for full details
//===========================================
#include "session.h"

#include <QObject>
#include <QProcess>
#include <QProcessEnvironment>
#include <QDebug>
#include <LuminaUtils.h>
#include <LuminaOS.h>

void LSession::stopall(){
  stopping = true;
  for(int i=0; i<PROCS.length(); i++){
    if(PROCS[i]->state()!=QProcess::NotRunning){ PROCS[i]->kill(); }
  }
  QCoreApplication::processEvents();
  for(int i=0; i<PROCS.length(); i++){
    if(PROCS[i]->state()!=QProcess::NotRunning){ PROCS[i]->terminate(); }
  }
  //QCoreApplication::exit(0);
}

void LSession::procFinished(){
  //Go through and check the status on all the procs to determine which one finished
  int stopped = 0;
  for(int i=0; i<PROCS.length(); i++){
    if(PROCS[i]->state()==QProcess::NotRunning){
      stopped++;
      if(!stopping){
        //See if this process is the main desktop binary
        if(PROCS[i]->program().section("/",-1) == "lumina-desktop"){ stopall();  } //start closing down everything
        //else{ PROCS[i]->start(QIODevice::ReadOnly); } //restart the process
        break;
      }
    }
  }
  if(stopping && stopped==PROCS.length()){
    QCoreApplication::exit(0);
  }
}

void LSession::startProcess(QString ID, QString command, QStringList watchfiles){
  QString dir = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/logs";
  if(!QFile::exists(dir)){ QDir tmp(dir); tmp.mkpath(dir); }
  QString logfile = dir+"/"+ID+".log";
  if(QFile::exists(logfile+".old")){ QFile::remove(logfile+".old"); }
  if(QFile::exists(logfile)){ QFile::rename(logfile,logfile+".old"); }

  LProcess *proc = new LProcess(ID, watchfiles);
  proc->setProcessChannelMode(QProcess::MergedChannels);
  proc->setProcessEnvironment( QProcessEnvironment::systemEnvironment() );
  proc->setStandardOutputFile(logfile);
  proc->start(command, QIODevice::ReadOnly);
  connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(procFinished()) );
  PROCS << proc;
}

void LSession::start(){
  //First check for a valid installation
  if( !LUtils::isValidBinary("fluxbox") || !LUtils::isValidBinary("lumina-desktop") ){
    exit(1);
  }
  //Window Manager First
  // FLUXBOX BUG BYPASS: if the ~/.fluxbox dir does not exist, it will ignore the given config file
  if( !LUtils::isValidBinary("fluxbox") ){
    qDebug() << "[INCOMPLETE LUMINA INSTALLATION] fluxbox binary is missing - cannot continue";
  }else{
    QString confDir = QString( getenv("XDG_CONFIG_HOME"))+"/lumina-desktop";
    if(!QFile::exists(confDir)){ QDir dir(confDir); dir.mkpath(confDir); }
    if(!QFile::exists(confDir+"/fluxbox-init")){
      QFile::copy(LOS::LuminaShare()+"/fluxbox-init-rc",confDir+"/fluxbox-init");
      QFile::setPermissions(confDir+"/fluxbox-init", QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::ReadOther | QFile::ReadGroup);
    }
    if(!QFile::exists(confDir+"/fluxbox-keys")){
      QStringList keys = LUtils::readFile(LOS::LuminaShare()+"/fluxbox-keys");
       keys = keys.replaceInStrings("${XDG_CONFIG_HOME}", QString( getenv("XDG_CONFIG_HOME")));
       LUtils::writeFile(confDir+"/fluxbox-keys", keys, true);
      QFile::setPermissions(confDir+"/fluxbox-keys", QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::ReadOther | QFile::ReadGroup);
    }
    // FLUXBOX BUG BYPASS: if the ~/.fluxbox dir does not exist, it will ignore the given config file
    if(!QFile::exists(QDir::homePath()+"/.fluxbox")){
      QDir dir; dir.mkpath(QDir::homePath()+"/.fluxbox");
    }
    QString cmd = "fluxbox -rc "+confDir+"/fluxbox-init -no-slit -no-toolbar";
    startProcess("wm", cmd, QStringList() << confDir+"/fluxbox-init" << confDir+"/fluxbox-keys");
  }
  //Compositing manager
  if(LUtils::isValidBinary("compton")){
    QString set = QString(getenv("XDG_CONFIG_HOME"))+"/lumina-desktop/compton.conf";
    if(!QFile::exists(set)){
      QStringList dirs = QString(getenv("XDG_CONFIG_DIRS")).split(":");
      for(int i=0; i<dirs.length(); i++){
        if(QFile::exists(dirs[i]+"/compton.conf")){ QFile::copy(dirs[i]+"/compton.conf", set); break; }
        else if(QFile::exists(dirs[i]+"/compton.conf.sample")){ QFile::copy(dirs[i]+"/compton.conf.sample", set); break; }
      }
    }
    if(!QFile::exists(set)){
      qDebug() << "Using default compton settings";
      startProcess("compositing","compton");
    }else{
      startProcess("compositing","compton --config \""+set+"\"", QStringList() << set);
    }
  }else if(LUtils::isValidBinary("xcompmgr")){ startProcess("compositing","xcompmgr"); }

  //Desktop Next
  startProcess("runtime","lumina-desktop");
  //ScreenSaver
  if(LUtils::isValidBinary("xscreensaver")){ startProcess("screensaver","xscreensaver -no-splash"); }

}
<|endoftext|>


<commit_before>/**
 * @file
 *
 * @brief Tests for the getenv library
 *
 * @copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 *
 */

#include <gtest/gtest.h>
#include <kdbgetenv.h>
#include <kdbconfig.h>

namespace ckdb
{
extern pthread_mutex_t elektraGetEnvMutex;
}

TEST (GetEnv, SimpleFork)
{
	using namespace ckdb;
	elektraOpen (nullptr, nullptr);
	setenv ("does-exist", "hello", 1);
	ASSERT_NE (getenv ("does-exist"), static_cast<char *> (nullptr));
	EXPECT_EQ (getenv ("does-exist"), std::string ("hello"));
#if VERBOSE
	pid_t f;
	f = fork ();
	std::cerr << "FORK " << f << std::endl;
#else
	fork ();
#endif
	ASSERT_NE (getenv ("does-exist"), static_cast<char *> (nullptr));
	EXPECT_EQ (getenv ("does-exist"), std::string ("hello"));

#if VERBOSE
	f = fork ();
	std::cerr << "FORK " << f << std::endl;
#else
	fork ();
#endif
	ASSERT_NE (getenv ("does-exist"), static_cast<char *> (nullptr));
	EXPECT_EQ (getenv ("does-exist"), std::string ("hello"));
	elektraClose ();
}

#include "main.cpp"
<commit_msg>fix formatting<commit_after>/**
 * @file
 *
 * @brief Tests for the getenv library
 *
 * @copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 *
 */

#include <gtest/gtest.h>
#include <kdbconfig.h>
#include <kdbgetenv.h>

namespace ckdb
{
extern pthread_mutex_t elektraGetEnvMutex;
}

TEST (GetEnv, SimpleFork)
{
	using namespace ckdb;
	elektraOpen (nullptr, nullptr);
	setenv ("does-exist", "hello", 1);
	ASSERT_NE (getenv ("does-exist"), static_cast<char *> (nullptr));
	EXPECT_EQ (getenv ("does-exist"), std::string ("hello"));
#if VERBOSE
	pid_t f;
	f = fork ();
	std::cerr << "FORK " << f << std::endl;
#else
	fork ();
#endif
	ASSERT_NE (getenv ("does-exist"), static_cast<char *> (nullptr));
	EXPECT_EQ (getenv ("does-exist"), std::string ("hello"));

#if VERBOSE
	f = fork ();
	std::cerr << "FORK " << f << std::endl;
#else
	fork ();
#endif
	ASSERT_NE (getenv ("does-exist"), static_cast<char *> (nullptr));
	EXPECT_EQ (getenv ("does-exist"), std::string ("hello"));
	elektraClose ();
}

#include "main.cpp"
<|endoftext|>


<commit_before>//! \file
/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the LGPLv3 License.
*/

#include <stdexcept>

#include <api.hpp>
#include <architecture.hpp>
#include <x8664Cpu.hpp>
#include <x86Cpu.hpp>

namespace triton {
  namespace arch {

    Architecture::Architecture() {
      this->arch = ARCH_INVALID;
      this->cpu  = nullptr;
    }

    Architecture::~Architecture() {
      delete this->cpu;
    }

    triton::uint32 Architecture::getArchitecture(void) const {
      return this->arch;
    }

    triton::arch::cpuInterface* Architecture::getCpu(void) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getCpu(): CPU undefined.");
      return this->cpu;
    }

    void Architecture::setArchitecture(triton::uint32 arch) {
      /* Check if the architecture is valid */
      if (!(arch > ARCH_INVALID && arch < ARCH_LAST_ITEM))
        throw std::runtime_error("Architecture::setArchitecture(): Invalid architecture.");

      /* Setup global variables */
      this->arch = arch;

      /* Allocate and init the good arch */
      switch (this->arch) {
        case ARCH_X86_64:
          #if defined(__i386) || defined(_M_IX86)
            throw std::runtime_error("Architecture::setArchitecture(): You cannot analyze 64-bits code on a 32-bits machine.");
          #endif
          /* remove previous CPU instance (when setArchitecture() has been called twice) */
          delete this->cpu;
          /* init the new instance */
          this->cpu = new x86::x8664Cpu();
          if (!this->cpu)
            throw std::runtime_error("Architecture::setArchitecture(): Not enough memory.");
          this->cpu->init();
          break;

        case ARCH_X86:
          /* remove previous CPU instance (when setArchitecture() has been called twice) */
          delete this->cpu;
          /* init the new instance */
          this->cpu = new x86::x86Cpu();
          if (!this->cpu)
            throw std::runtime_error("Architecture::setArchitecture(): Not enough memory.");
          this->cpu->init();
          break;
      }
    }

    void Architecture::clearArchitecture(void) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::clearArchitecture(): You must define an architecture.");
      this->cpu->clear();
    }

    bool Architecture::isValid(void) {
      if (this->arch == ARCH_INVALID)
        return false;
      return true;
    }

    bool Architecture::isFlag(triton::uint32 regId) {
      if (!this->cpu)
        return false;
      return this->cpu->isFlag(regId);
    }

    bool Architecture::isRegister(triton::uint32 regId) {
      if (!this->cpu)
        return false;
      return this->cpu->isRegister(regId);
    }

    bool Architecture::isRegisterValid(triton::uint32 regId) {
      if (!this->cpu)
        return false;
      return this->cpu->isRegisterValid(regId);
    }

    triton::uint32 Architecture::invalidRegister(void) {
      if (!this->cpu)
        return 0;
      return this->cpu->invalidRegister();
    }

    triton::uint32 Architecture::numberOfRegisters(void) {
      if (!this->cpu)
        return 0;
      return this->cpu->numberOfRegisters();
    }

    triton::uint32 Architecture::registerSize(void) {
      if (!this->cpu)
        return 0;
      return this->cpu->registerSize();
    }

    triton::uint32 Architecture::registerBitSize(void) {
      if (!this->cpu)
        return 0;
      return this->cpu->registerBitSize();
    }

    std::tuple<std::string, triton::uint32, triton::uint32, triton::uint32> Architecture::getRegisterInformation(triton::uint32 reg) {
      std::tuple<std::string, triton::uint32, triton::uint32, triton::uint32> ret;

      std::get<0>(ret) = "unknown"; /* name           */
      std::get<1>(ret) = 0;         /* highest bit    */
      std::get<2>(ret) = 0;         /* lower bit      */
      std::get<3>(ret) = 0;         /* higest reg id  */

      if (this->cpu)
        ret = this->cpu->getRegisterInformation(reg);

      return ret;
    }

    std::set<triton::arch::RegisterOperand*> Architecture::getAllRegisters(void) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getAllRegisters(): You must define an architecture.");
      return this->cpu->getAllRegisters();
    }

    std::set<triton::arch::RegisterOperand*> Architecture::getParentRegisters(void) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getParentRegisters(): You must define an architecture.");
      return this->cpu->getParentRegisters();
    }

    void Architecture::disassembly(triton::arch::Instruction &inst) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::disassembly(): You must define an architecture.");
      this->cpu->disassembly(inst);
    }

    void Architecture::buildSemantics(triton::arch::Instruction &inst) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::disassembly(): You must define an architecture.");

      /* Clear previous expressions if exist */
      inst.symbolicExpressions.clear();

      /* If the symbolic and taint engine are disable we skip the processing */
      if (!triton::api.isSymbolicEngineEnabled() && !triton::api.isTaintEngineEnabled())
        return;

      /* Backup the symbolic engine in the case where only taint is available. */
      if (!triton::api.isSymbolicEngineEnabled())
        triton::api.backupSymbolicEngine();

      /* Processing */
      this->cpu->buildSemantics(inst);

      /* Clear unused data */
      inst.memoryAccess.clear();
      inst.registerState.clear();

      /*
       * If the symbolic engine is disable we delete symbolic
       * expressions and AST nodes. Note that if the taint engine
       * is enable we must compute semanitcs to spread the taint.
       */
      if (!triton::api.isSymbolicEngineEnabled()) {
        std::set<triton::ast::AbstractNode*> uniqueNodes;
        std::vector<triton::engines::symbolic::SymbolicExpression*>::iterator it;
        for (it = inst.symbolicExpressions.begin(); it != inst.symbolicExpressions.end(); it++) {
          triton::api.extractUniqueAstNodes(uniqueNodes, (*it)->getAst());
          triton::api.removeSymbolicExpression((*it)->getId());
        }

        if (!triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::AST_DICTIONARIES)) {
          /* Remove node only if AST_DICTIONARIES is disabled */
          triton::api.freeAstNodes(uniqueNodes);
        }

        inst.symbolicExpressions.clear();
        triton::api.restoreSymbolicEngine();
      }

      /*
       * If the symbolic engine is defined to process symbolic
       * execution only on tainted instructions, we delete all
       * expressions untainted and their AST nodes.
       */
      if (triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::ONLY_ON_TAINTED)) {
        std::set<triton::ast::AbstractNode*> uniqueNodes;
        std::vector<triton::engines::symbolic::SymbolicExpression*> newVector;
        std::vector<triton::engines::symbolic::SymbolicExpression*>::iterator it;
        for (it = inst.symbolicExpressions.begin(); it != inst.symbolicExpressions.end(); it++) {
          if ((*it)->isTainted == triton::engines::taint::UNTAINTED) {
            triton::api.extractUniqueAstNodes(uniqueNodes, (*it)->getAst());
            triton::api.removeSymbolicExpression((*it)->getId());
          }
          else
            newVector.push_back(*it);
        }

        if (!triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::AST_DICTIONARIES)) {
          /* Remove node only if AST_DICTIONARIES is disabled */
          triton::api.freeAstNodes(uniqueNodes);
        }

        inst.symbolicExpressions = newVector;
      }

      /*
       * If the symbolic engine is defined to process symbolic
       * execution only on symbolized expressions, we delete all
       * concrete expressions and their AST nodes.
       */
      if (triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::ONLY_ON_SYMBOLIZED)) {
        std::set<triton::ast::AbstractNode*> uniqueNodes;
        std::vector<triton::engines::symbolic::SymbolicExpression*> newVector;
        std::vector<triton::engines::symbolic::SymbolicExpression*>::iterator it;
        for (it = inst.symbolicExpressions.begin(); it != inst.symbolicExpressions.end(); it++) {
          if ((*it)->getAst()->isSymbolized() == false) {
            triton::api.extractUniqueAstNodes(uniqueNodes, (*it)->getAst());
            triton::api.removeSymbolicExpression((*it)->getId());
          }
          else
            newVector.push_back(*it);
        }

        if (!triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::AST_DICTIONARIES)) {
          /* Remove node only if AST_DICTIONARIES is disabled */
          triton::api.freeAstNodes(uniqueNodes);
        }

        inst.symbolicExpressions = newVector;
      }

    }

    triton::uint8 Architecture::getLastMemoryValue(triton::__uint addr) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getLastMemoryValue(): You must define an architecture.");
      return this->cpu->getLastMemoryValue(addr);
    }

    triton::uint512 Architecture::getLastMemoryValue(triton::arch::MemoryOperand& mem) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getLastMemoryValue(): You must define an architecture.");
      return this->cpu->getLastMemoryValue(mem);
    }

    std::vector<triton::uint8> Architecture::getLastMemoryAreaValue(triton::__uint baseAddr, triton::uint32 size) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getLastMemoryAreaValue(): You must define an architecture.");
      return this->cpu->getLastMemoryAreaValue(baseAddr, size);
    }

    triton::uint512 Architecture::getLastRegisterValue(triton::arch::RegisterOperand& reg) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getLastRegisterValue(): You must define an architecture.");
      return this->cpu->getLastRegisterValue(reg);
    }

    void Architecture::setLastMemoryValue(triton::__uint addr, triton::uint8 value) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::setLastMemoryValue(): You must define an architecture.");
      this->cpu->setLastMemoryValue(addr, value);
    }

    void Architecture::setLastMemoryValue(triton::arch::MemoryOperand& mem) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::setLastMemoryValue(): You must define an architecture.");
      this->cpu->setLastMemoryValue(mem);
    }

    void Architecture::setLastMemoryAreaValue(triton::__uint baseAddr, std::vector<triton::uint8>& values) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::setLastMemoryAreaValue(): You must define an architecture.");
      this->cpu->setLastMemoryAreaValue(baseAddr, values);
    }

    void Architecture::setLastRegisterValue(triton::arch::RegisterOperand& reg) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::setLastRegisterValue(): You must define an architecture.");
      this->cpu->setLastRegisterValue(reg);
    }

  }; /* arch namespace */
}; /* triton namespace */

<commit_msg>Tmp fix about the Python's double free<commit_after>//! \file
/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the LGPLv3 License.
*/

#include <stdexcept>

#include <api.hpp>
#include <architecture.hpp>
#include <x8664Cpu.hpp>
#include <x86Cpu.hpp>

namespace triton {
  namespace arch {

    Architecture::Architecture() {
      this->arch = ARCH_INVALID;
      this->cpu  = nullptr;
    }

    Architecture::~Architecture() {
      //delete this->cpu;
    }

    triton::uint32 Architecture::getArchitecture(void) const {
      return this->arch;
    }

    triton::arch::cpuInterface* Architecture::getCpu(void) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getCpu(): CPU undefined.");
      return this->cpu;
    }

    void Architecture::setArchitecture(triton::uint32 arch) {
      /* Check if the architecture is valid */
      if (!(arch > ARCH_INVALID && arch < ARCH_LAST_ITEM))
        throw std::runtime_error("Architecture::setArchitecture(): Invalid architecture.");

      /* Setup global variables */
      this->arch = arch;

      /* Allocate and init the good arch */
      switch (this->arch) {
        case ARCH_X86_64:
          #if defined(__i386) || defined(_M_IX86)
            throw std::runtime_error("Architecture::setArchitecture(): You cannot analyze 64-bits code on a 32-bits machine.");
          #endif
          /* remove previous CPU instance (when setArchitecture() has been called twice) */
          delete this->cpu;
          /* init the new instance */
          this->cpu = new x86::x8664Cpu();
          if (!this->cpu)
            throw std::runtime_error("Architecture::setArchitecture(): Not enough memory.");
          this->cpu->init();
          break;

        case ARCH_X86:
          /* remove previous CPU instance (when setArchitecture() has been called twice) */
          delete this->cpu;
          /* init the new instance */
          this->cpu = new x86::x86Cpu();
          if (!this->cpu)
            throw std::runtime_error("Architecture::setArchitecture(): Not enough memory.");
          this->cpu->init();
          break;
      }
    }

    void Architecture::clearArchitecture(void) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::clearArchitecture(): You must define an architecture.");
      this->cpu->clear();
    }

    bool Architecture::isValid(void) {
      if (this->arch == ARCH_INVALID)
        return false;
      return true;
    }

    bool Architecture::isFlag(triton::uint32 regId) {
      if (!this->cpu)
        return false;
      return this->cpu->isFlag(regId);
    }

    bool Architecture::isRegister(triton::uint32 regId) {
      if (!this->cpu)
        return false;
      return this->cpu->isRegister(regId);
    }

    bool Architecture::isRegisterValid(triton::uint32 regId) {
      if (!this->cpu)
        return false;
      return this->cpu->isRegisterValid(regId);
    }

    triton::uint32 Architecture::invalidRegister(void) {
      if (!this->cpu)
        return 0;
      return this->cpu->invalidRegister();
    }

    triton::uint32 Architecture::numberOfRegisters(void) {
      if (!this->cpu)
        return 0;
      return this->cpu->numberOfRegisters();
    }

    triton::uint32 Architecture::registerSize(void) {
      if (!this->cpu)
        return 0;
      return this->cpu->registerSize();
    }

    triton::uint32 Architecture::registerBitSize(void) {
      if (!this->cpu)
        return 0;
      return this->cpu->registerBitSize();
    }

    std::tuple<std::string, triton::uint32, triton::uint32, triton::uint32> Architecture::getRegisterInformation(triton::uint32 reg) {
      std::tuple<std::string, triton::uint32, triton::uint32, triton::uint32> ret;

      std::get<0>(ret) = "unknown"; /* name           */
      std::get<1>(ret) = 0;         /* highest bit    */
      std::get<2>(ret) = 0;         /* lower bit      */
      std::get<3>(ret) = 0;         /* higest reg id  */

      if (this->cpu)
        ret = this->cpu->getRegisterInformation(reg);

      return ret;
    }

    std::set<triton::arch::RegisterOperand*> Architecture::getAllRegisters(void) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getAllRegisters(): You must define an architecture.");
      return this->cpu->getAllRegisters();
    }

    std::set<triton::arch::RegisterOperand*> Architecture::getParentRegisters(void) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getParentRegisters(): You must define an architecture.");
      return this->cpu->getParentRegisters();
    }

    void Architecture::disassembly(triton::arch::Instruction &inst) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::disassembly(): You must define an architecture.");
      this->cpu->disassembly(inst);
    }

    void Architecture::buildSemantics(triton::arch::Instruction &inst) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::disassembly(): You must define an architecture.");

      /* Clear previous expressions if exist */
      inst.symbolicExpressions.clear();

      /* If the symbolic and taint engine are disable we skip the processing */
      if (!triton::api.isSymbolicEngineEnabled() && !triton::api.isTaintEngineEnabled())
        return;

      /* Backup the symbolic engine in the case where only taint is available. */
      if (!triton::api.isSymbolicEngineEnabled())
        triton::api.backupSymbolicEngine();

      /* Processing */
      this->cpu->buildSemantics(inst);

      /* Clear unused data */
      inst.memoryAccess.clear();
      inst.registerState.clear();

      /*
       * If the symbolic engine is disable we delete symbolic
       * expressions and AST nodes. Note that if the taint engine
       * is enable we must compute semanitcs to spread the taint.
       */
      if (!triton::api.isSymbolicEngineEnabled()) {
        std::set<triton::ast::AbstractNode*> uniqueNodes;
        std::vector<triton::engines::symbolic::SymbolicExpression*>::iterator it;
        for (it = inst.symbolicExpressions.begin(); it != inst.symbolicExpressions.end(); it++) {
          triton::api.extractUniqueAstNodes(uniqueNodes, (*it)->getAst());
          triton::api.removeSymbolicExpression((*it)->getId());
        }

        if (!triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::AST_DICTIONARIES)) {
          /* Remove node only if AST_DICTIONARIES is disabled */
          triton::api.freeAstNodes(uniqueNodes);
        }

        inst.symbolicExpressions.clear();
        triton::api.restoreSymbolicEngine();
      }

      /*
       * If the symbolic engine is defined to process symbolic
       * execution only on tainted instructions, we delete all
       * expressions untainted and their AST nodes.
       */
      if (triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::ONLY_ON_TAINTED)) {
        std::set<triton::ast::AbstractNode*> uniqueNodes;
        std::vector<triton::engines::symbolic::SymbolicExpression*> newVector;
        std::vector<triton::engines::symbolic::SymbolicExpression*>::iterator it;
        for (it = inst.symbolicExpressions.begin(); it != inst.symbolicExpressions.end(); it++) {
          if ((*it)->isTainted == triton::engines::taint::UNTAINTED) {
            triton::api.extractUniqueAstNodes(uniqueNodes, (*it)->getAst());
            triton::api.removeSymbolicExpression((*it)->getId());
          }
          else
            newVector.push_back(*it);
        }

        if (!triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::AST_DICTIONARIES)) {
          /* Remove node only if AST_DICTIONARIES is disabled */
          triton::api.freeAstNodes(uniqueNodes);
        }

        inst.symbolicExpressions = newVector;
      }

      /*
       * If the symbolic engine is defined to process symbolic
       * execution only on symbolized expressions, we delete all
       * concrete expressions and their AST nodes.
       */
      if (triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::ONLY_ON_SYMBOLIZED)) {
        std::set<triton::ast::AbstractNode*> uniqueNodes;
        std::vector<triton::engines::symbolic::SymbolicExpression*> newVector;
        std::vector<triton::engines::symbolic::SymbolicExpression*>::iterator it;
        for (it = inst.symbolicExpressions.begin(); it != inst.symbolicExpressions.end(); it++) {
          if ((*it)->getAst()->isSymbolized() == false) {
            triton::api.extractUniqueAstNodes(uniqueNodes, (*it)->getAst());
            triton::api.removeSymbolicExpression((*it)->getId());
          }
          else
            newVector.push_back(*it);
        }

        if (!triton::api.isSymbolicOptimizationEnabled(triton::engines::symbolic::AST_DICTIONARIES)) {
          /* Remove node only if AST_DICTIONARIES is disabled */
          triton::api.freeAstNodes(uniqueNodes);
        }

        inst.symbolicExpressions = newVector;
      }

    }

    triton::uint8 Architecture::getLastMemoryValue(triton::__uint addr) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getLastMemoryValue(): You must define an architecture.");
      return this->cpu->getLastMemoryValue(addr);
    }

    triton::uint512 Architecture::getLastMemoryValue(triton::arch::MemoryOperand& mem) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getLastMemoryValue(): You must define an architecture.");
      return this->cpu->getLastMemoryValue(mem);
    }

    std::vector<triton::uint8> Architecture::getLastMemoryAreaValue(triton::__uint baseAddr, triton::uint32 size) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getLastMemoryAreaValue(): You must define an architecture.");
      return this->cpu->getLastMemoryAreaValue(baseAddr, size);
    }

    triton::uint512 Architecture::getLastRegisterValue(triton::arch::RegisterOperand& reg) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::getLastRegisterValue(): You must define an architecture.");
      return this->cpu->getLastRegisterValue(reg);
    }

    void Architecture::setLastMemoryValue(triton::__uint addr, triton::uint8 value) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::setLastMemoryValue(): You must define an architecture.");
      this->cpu->setLastMemoryValue(addr, value);
    }

    void Architecture::setLastMemoryValue(triton::arch::MemoryOperand& mem) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::setLastMemoryValue(): You must define an architecture.");
      this->cpu->setLastMemoryValue(mem);
    }

    void Architecture::setLastMemoryAreaValue(triton::__uint baseAddr, std::vector<triton::uint8>& values) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::setLastMemoryAreaValue(): You must define an architecture.");
      this->cpu->setLastMemoryAreaValue(baseAddr, values);
    }

    void Architecture::setLastRegisterValue(triton::arch::RegisterOperand& reg) {
      if (!this->cpu)
        throw std::runtime_error("Architecture::setLastRegisterValue(): You must define an architecture.");
      this->cpu->setLastRegisterValue(reg);
    }

  }; /* arch namespace */
}; /* triton namespace */

<|endoftext|>


<commit_before>//==============================================================================
// ForwardEulerSolver plugin
//==============================================================================

#include "forwardeulersolverplugin.h"

//==============================================================================

namespace OpenCOR {
namespace ForwardEulerSolver {

//==============================================================================

PLUGININFO_FUNC ForwardEulerSolverPluginInfo()
{
    Descriptions descriptions;

    descriptions.insert("en", "An implementation of the Forward Euler method to solve ODEs");
    descriptions.insert("fr", "Une implmentation de la mthode Forward Euler pour rsoudres des EDOs");

    return PluginInfo(PluginInfo::V001,
                      PluginInfo::General,
                      PluginInfo::Simulation,
                      true,
                      QStringList() << "Core",
                      descriptions);
}

//==============================================================================

Q_EXPORT_PLUGIN2(ForwardEulerSolver, ForwardEulerSolverPlugin)

//==============================================================================

QString ForwardEulerSolverPlugin::solverName() const
{
    return tr("Forward Euler");
}

//==============================================================================

}   // namespace ForwardEulerSolver
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Minor cleaning up (#57).<commit_after>//==============================================================================
// ForwardEulerSolver plugin
//==============================================================================

#include "forwardeulersolverplugin.h"

//==============================================================================

namespace OpenCOR {
namespace ForwardEulerSolver {

//==============================================================================

PLUGININFO_FUNC ForwardEulerSolverPluginInfo()
{
    Descriptions descriptions;

    descriptions.insert("en", "An implementation of the Forward Euler method to solve ODEs");
    descriptions.insert("fr", "Une implmentation de la mthode Forward Euler pour rsoudres des EDOs");

    return PluginInfo(PluginInfo::V001,
                      PluginInfo::General,
                      PluginInfo::Simulation,
                      true,
                      QStringList(),
                      descriptions);
}

//==============================================================================

Q_EXPORT_PLUGIN2(ForwardEulerSolver, ForwardEulerSolverPlugin)

//==============================================================================

QString ForwardEulerSolverPlugin::solverName() const
{
    return tr("Forward Euler");
}

//==============================================================================

}   // namespace ForwardEulerSolver
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>//  illarionserver - server for the game Illarion
//  Copyright 2011 Illarion e.V.
//
//  This file is part of illarionserver.
//
//  illarionserver is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  illarionserver 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 Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with illarionserver.  If not, see <http://www.gnu.org/licenses/>.

#include "InitialConnection.hpp"

#include "Config.hpp"
#include "Logger.hpp"
#include "netinterface/NetInterface.hpp"

#include <cstdlib>
#include <memory>
#include <thread>

auto InitialConnection::create() -> std::shared_ptr<InitialConnection> {
    std::shared_ptr<InitialConnection> ptr(new InitialConnection());
    std::thread servicethread([shared_this = ptr->shared_from_this()] { shared_this->run_service(); });
    servicethread.detach();
    return ptr;
}

auto InitialConnection::getNewPlayers() -> NewPlayerVector & { return newPlayers; }

void InitialConnection::run_service() {
    try {
        using boost::asio::ip::tcp;

        int port = Config::instance().port;

        auto endpoint = tcp::endpoint(tcp::v4(), port);
        acceptor = std::make_unique<tcp::acceptor>(io_service, endpoint);
        auto newConnection = std::make_shared<NetInterface>(io_service);
        using std::placeholders::_1;
        acceptor->async_accept(newConnection->getSocket(),
                               [shared_this = shared_from_this(), newConnection](auto &&PH1) {
                                   shared_this->accept_connection(newConnection, PH1);
                               });
        Logger::info(LogFacility::Other) << "Starting the io service." << Log::end;
        io_service.run();
    } catch (const boost::system::system_error &e) {
        Logger::critical(LogFacility::Other) << "Failed to start io service: " << e.what() << Log::end;
        std::abort();
    }
}

void InitialConnection::accept_connection(const std::shared_ptr<NetInterface> &connection,
                                          const boost::system::error_code &error) {
    if (!error) {
        if (connection->activate()) {
            newPlayers.push_back(connection);
        } else {
            Logger::error(LogFacility::Other) << "Error while activating connection!" << Log::end;
        }

        auto newConnection = std::make_shared<NetInterface>(io_service);
        using std::placeholders::_1;
        acceptor->async_accept(newConnection->getSocket(),
                               [shared_this = shared_from_this(), newConnection](auto &&PH1) {
                                   shared_this->accept_connection(newConnection, PH1);
                               });
    } else {
        Logger::error(LogFacility::Other) << "Could not accept connection: " << error.message() << Log::end;
    }
}

InitialConnection::~InitialConnection() { io_service.stop(); }
<commit_msg>Exit with failure instead of abort to prevent core dump<commit_after>//  illarionserver - server for the game Illarion
//  Copyright 2011 Illarion e.V.
//
//  This file is part of illarionserver.
//
//  illarionserver is free software: you can redistribute it and/or modify
//  it under the terms of the GNU Affero General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  illarionserver 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 Affero General Public License for more details.
//
//  You should have received a copy of the GNU Affero General Public License
//  along with illarionserver.  If not, see <http://www.gnu.org/licenses/>.

#include "InitialConnection.hpp"

#include "Config.hpp"
#include "Logger.hpp"
#include "netinterface/NetInterface.hpp"

#include <cstdlib>
#include <memory>
#include <thread>

auto InitialConnection::create() -> std::shared_ptr<InitialConnection> {
    std::shared_ptr<InitialConnection> ptr(new InitialConnection());
    std::thread servicethread([shared_this = ptr->shared_from_this()] { shared_this->run_service(); });
    servicethread.detach();
    return ptr;
}

auto InitialConnection::getNewPlayers() -> NewPlayerVector & { return newPlayers; }

void InitialConnection::run_service() {
    try {
        using boost::asio::ip::tcp;

        int port = Config::instance().port;

        auto endpoint = tcp::endpoint(tcp::v4(), port);
        acceptor = std::make_unique<tcp::acceptor>(io_service, endpoint);
        auto newConnection = std::make_shared<NetInterface>(io_service);
        using std::placeholders::_1;
        acceptor->async_accept(newConnection->getSocket(),
                               [shared_this = shared_from_this(), newConnection](auto &&PH1) {
                                   shared_this->accept_connection(newConnection, PH1);
                               });
        Logger::info(LogFacility::Other) << "Starting the io service." << Log::end;
        io_service.run();
    } catch (const boost::system::system_error &e) {
        Logger::critical(LogFacility::Other) << "Failed to start io service: " << e.what() << Log::end;
        std::exit(EXIT_FAILURE);
    }
}

void InitialConnection::accept_connection(const std::shared_ptr<NetInterface> &connection,
                                          const boost::system::error_code &error) {
    if (!error) {
        if (connection->activate()) {
            newPlayers.push_back(connection);
        } else {
            Logger::error(LogFacility::Other) << "Error while activating connection!" << Log::end;
        }

        auto newConnection = std::make_shared<NetInterface>(io_service);
        using std::placeholders::_1;
        acceptor->async_accept(newConnection->getSocket(),
                               [shared_this = shared_from_this(), newConnection](auto &&PH1) {
                                   shared_this->accept_connection(newConnection, PH1);
                               });
    } else {
        Logger::error(LogFacility::Other) << "Could not accept connection: " << error.message() << Log::end;
    }
}

InitialConnection::~InitialConnection() { io_service.stop(); }
<|endoftext|>