<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: X11_droptarget.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: kz $ $Date: 2008-04-03 17:15:57 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dtrans.hxx"

#include <X11_selection.hxx>

using namespace x11;
using namespace rtl;
using namespace com::sun::star::lang;
using namespace com::sun::star::awt;
using namespace com::sun::star::datatransfer;
using namespace com::sun::star::datatransfer::dnd;

DropTarget::DropTarget() :
        ::cppu::WeakComponentImplHelper3<
            XDropTarget,
            XInitialization,
            XServiceInfo
        >( m_aMutex ),
    m_bActive( false ),
    m_nDefaultActions( 0 ),
    m_aTargetWindow( None ),
    m_pSelectionManager( NULL )
{
}

DropTarget::~DropTarget()
{
    if( m_pSelectionManager )
        m_pSelectionManager->deregisterDropTarget( m_aTargetWindow );
}

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

void DropTarget::initialize( const Sequence< Any >& arguments ) throw( ::com::sun::star::uno::Exception )
{
    if( arguments.getLength() > 1 )
    {
        OUString aDisplayName;
        Reference< XDisplayConnection > xConn;
        arguments.getConstArray()[0] >>= xConn;
        if( xConn.is() )
        {
            Any aIdentifier;
            aIdentifier >>= aDisplayName;
        }

        m_pSelectionManager = &SelectionManager::get( aDisplayName );
        m_xSelectionManager = static_cast< XDragSource* >(m_pSelectionManager);
        m_pSelectionManager->initialize( arguments );

        if( m_pSelectionManager->getDisplay() ) // #136582# sanity check
        {
            sal_Size aWindow = None;
            arguments.getConstArray()[1] >>= aWindow;
            m_pSelectionManager->registerDropTarget( aWindow, this );
            m_aTargetWindow = aWindow;
            m_bActive = true;
        }
    }
}

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

void DropTarget::addDropTargetListener( const Reference< XDropTargetListener >& xListener ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    m_aListeners.push_back( xListener );
}

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

void DropTarget::removeDropTargetListener( const Reference< XDropTargetListener >& xListener ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    m_aListeners.remove( xListener );
}

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

sal_Bool DropTarget::isActive() throw()
{
    return m_bActive;
}

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

void DropTarget::setActive( sal_Bool active ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    m_bActive = active;
}

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

sal_Int8 DropTarget::getDefaultActions() throw()
{
    return m_nDefaultActions;
}

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

void DropTarget::setDefaultActions( sal_Int8 actions ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    m_nDefaultActions = actions;
}

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

void DropTarget::drop( const DropTargetDropEvent& dtde ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    ::std::list< Reference< XDropTargetListener > >::iterator it1, it2;
    it1 = m_aListeners.begin();
    while( it1 != m_aListeners.end() )
    {
        it2 = it1;
        it1++;
        (*it2)->drop( dtde );
    }
}

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

void DropTarget::dragEnter( const DropTargetDragEnterEvent& dtde ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    ::std::list< Reference< XDropTargetListener > >::iterator it1, it2;
    it1 = m_aListeners.begin();
    while( it1 != m_aListeners.end() )
    {
        it2 = it1;
        it1++;
        (*it2)->dragEnter( dtde );
    }
}

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

void DropTarget::dragExit( const DropTargetEvent& dte ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    ::std::list< Reference< XDropTargetListener > >::iterator it1, it2;
    it1 = m_aListeners.begin();
    while( it1 != m_aListeners.end() )
    {
        it2 = it1;
        it1++;
        (*it2)->dragExit( dte );
    }
}

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

void DropTarget::dragOver( const DropTargetDragEvent& dtde ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    ::std::list< Reference< XDropTargetListener > >::iterator it1, it2;
    it1 = m_aListeners.begin();
    while( it1 != m_aListeners.end() )
    {
        it2 = it1;
        it1++;
        (*it2)->dragOver( dtde );
    }
}

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

/*
 *  XServiceInfo
 */

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

OUString DropTarget::getImplementationName() throw()
{
    return OUString::createFromAscii(XDND_DROPTARGET_IMPLEMENTATION_NAME);
}

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

sal_Bool DropTarget::supportsService( const OUString& ServiceName ) throw()
{
    Sequence < OUString > SupportedServicesNames = Xdnd_dropTarget_getSupportedServiceNames();

    for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
        if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
            return sal_True;

    return sal_False;
}

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

Sequence< OUString > DropTarget::getSupportedServiceNames() throw()
{
    return Xdnd_dropTarget_getSupportedServiceNames();
}

<commit_msg>INTEGRATION: CWS changefileheader (1.12.38); FILE MERGED 2008/03/31 13:08:51 rt 1.12.38.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: X11_droptarget.cxx,v $
 * $Revision: 1.14 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_dtrans.hxx"

#include <X11_selection.hxx>

using namespace x11;
using namespace rtl;
using namespace com::sun::star::lang;
using namespace com::sun::star::awt;
using namespace com::sun::star::datatransfer;
using namespace com::sun::star::datatransfer::dnd;

DropTarget::DropTarget() :
        ::cppu::WeakComponentImplHelper3<
            XDropTarget,
            XInitialization,
            XServiceInfo
        >( m_aMutex ),
    m_bActive( false ),
    m_nDefaultActions( 0 ),
    m_aTargetWindow( None ),
    m_pSelectionManager( NULL )
{
}

DropTarget::~DropTarget()
{
    if( m_pSelectionManager )
        m_pSelectionManager->deregisterDropTarget( m_aTargetWindow );
}

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

void DropTarget::initialize( const Sequence< Any >& arguments ) throw( ::com::sun::star::uno::Exception )
{
    if( arguments.getLength() > 1 )
    {
        OUString aDisplayName;
        Reference< XDisplayConnection > xConn;
        arguments.getConstArray()[0] >>= xConn;
        if( xConn.is() )
        {
            Any aIdentifier;
            aIdentifier >>= aDisplayName;
        }

        m_pSelectionManager = &SelectionManager::get( aDisplayName );
        m_xSelectionManager = static_cast< XDragSource* >(m_pSelectionManager);
        m_pSelectionManager->initialize( arguments );

        if( m_pSelectionManager->getDisplay() ) // #136582# sanity check
        {
            sal_Size aWindow = None;
            arguments.getConstArray()[1] >>= aWindow;
            m_pSelectionManager->registerDropTarget( aWindow, this );
            m_aTargetWindow = aWindow;
            m_bActive = true;
        }
    }
}

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

void DropTarget::addDropTargetListener( const Reference< XDropTargetListener >& xListener ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    m_aListeners.push_back( xListener );
}

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

void DropTarget::removeDropTargetListener( const Reference< XDropTargetListener >& xListener ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    m_aListeners.remove( xListener );
}

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

sal_Bool DropTarget::isActive() throw()
{
    return m_bActive;
}

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

void DropTarget::setActive( sal_Bool active ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    m_bActive = active;
}

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

sal_Int8 DropTarget::getDefaultActions() throw()
{
    return m_nDefaultActions;
}

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

void DropTarget::setDefaultActions( sal_Int8 actions ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    m_nDefaultActions = actions;
}

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

void DropTarget::drop( const DropTargetDropEvent& dtde ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    ::std::list< Reference< XDropTargetListener > >::iterator it1, it2;
    it1 = m_aListeners.begin();
    while( it1 != m_aListeners.end() )
    {
        it2 = it1;
        it1++;
        (*it2)->drop( dtde );
    }
}

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

void DropTarget::dragEnter( const DropTargetDragEnterEvent& dtde ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    ::std::list< Reference< XDropTargetListener > >::iterator it1, it2;
    it1 = m_aListeners.begin();
    while( it1 != m_aListeners.end() )
    {
        it2 = it1;
        it1++;
        (*it2)->dragEnter( dtde );
    }
}

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

void DropTarget::dragExit( const DropTargetEvent& dte ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    ::std::list< Reference< XDropTargetListener > >::iterator it1, it2;
    it1 = m_aListeners.begin();
    while( it1 != m_aListeners.end() )
    {
        it2 = it1;
        it1++;
        (*it2)->dragExit( dte );
    }
}

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

void DropTarget::dragOver( const DropTargetDragEvent& dtde ) throw()
{
    ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );

    ::std::list< Reference< XDropTargetListener > >::iterator it1, it2;
    it1 = m_aListeners.begin();
    while( it1 != m_aListeners.end() )
    {
        it2 = it1;
        it1++;
        (*it2)->dragOver( dtde );
    }
}

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

/*
 *  XServiceInfo
 */

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

OUString DropTarget::getImplementationName() throw()
{
    return OUString::createFromAscii(XDND_DROPTARGET_IMPLEMENTATION_NAME);
}

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

sal_Bool DropTarget::supportsService( const OUString& ServiceName ) throw()
{
    Sequence < OUString > SupportedServicesNames = Xdnd_dropTarget_getSupportedServiceNames();

    for ( sal_Int32 n = SupportedServicesNames.getLength(); n--; )
        if (SupportedServicesNames[n].compareTo(ServiceName) == 0)
            return sal_True;

    return sal_False;
}

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

Sequence< OUString > DropTarget::getSupportedServiceNames() throw()
{
    return Xdnd_dropTarget_getSupportedServiceNames();
}

<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Kirsten Weber

#ifndef DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH
#define DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH

#include <memory>
#include <type_traits>

#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>

#include <dune/grid/io/file/vtk.hh>

#include <dune/stuff/la/container/interfaces.hh>

#include <dune/gdt/space/interface.hh>

#include "local.hh"

namespace Dune {
namespace GDT {

template< class SpaceImp, class VectorImp >
class ConstDiscreteFunction
  : public Stuff::LocalizableFunctionInterface< typename SpaceImp::EntityType,
        typename SpaceImp::DomainFieldType, SpaceImp::dimDomain,
        typename SpaceImp::RangeFieldType, SpaceImp::dimRange, SpaceImp::dimRangeCols >
{
  static_assert(std::is_base_of< SpaceInterface< typename SpaceImp::Traits >, SpaceImp >::value,
                "SpaceImp has to be derived from SpaceInterface!");
  static_assert(std::is_base_of< Dune::Stuff::LA::VectorInterface< typename VectorImp::Traits >, VectorImp >::value,
                "VectorImp has to be derived from Stuff::LA::VectorInterface!");
  static_assert(std::is_same< typename SpaceImp::RangeFieldType, typename VectorImp::ScalarType >::value,
                "Types do not match!");
  typedef Stuff::LocalizableFunctionInterface
      < typename SpaceImp::EntityType, typename SpaceImp::DomainFieldType, SpaceImp::dimDomain,
        typename SpaceImp::RangeFieldType, SpaceImp::dimRange, SpaceImp::dimRangeCols >
    BaseType;
  typedef ConstDiscreteFunction< SpaceImp, VectorImp > ThisType;
public:
  typedef SpaceImp                              SpaceType;
  typedef VectorImp                             VectorType;
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  static const unsigned int                   dimDomain = BaseType::dimDomain;
  typedef typename BaseType::DomainFieldType  DomainFieldType;
  typedef typename BaseType::DomainType       DomainType;

  static const unsigned int                     dimRange = BaseType::dimRange;
  static const unsigned int                     dimRangeCols = BaseType::dimRangeCols;
  typedef typename BaseType::RangeFieldType     RangeFieldType;
  typedef typename BaseType::RangeType          RangeType;
  typedef typename BaseType::JacobianRangeType  JacobianRangeType;

  typedef ConstLocalDiscreteFunction< SpaceType, VectorType > ConstLocalDiscreteFunctionType;

  ConstDiscreteFunction(const SpaceType& sp,
                        const VectorType& vec,
                        const std::string nm = "dune.gdt.constdiscretefunction")
    : space_(sp)
    , vector_(vec)
    , name_(nm)
  {
    assert(vector_.size() == space_.mapper().size() && "Given vector has wrong size!");
  }

  ConstDiscreteFunction(const ThisType& other)
    : space_(other.space_)
    , vector_(other.vector_)
    , name_(other.name_)
  {}

  ConstDiscreteFunction(ThisType&& source)
    : space_(source.space_)
    , vector_(source.vector_)
    , name_(std::move(source.name_))
  {}

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

  ~ConstDiscreteFunction() {}

  virtual ThisType* copy() const DS_OVERRIDE
  {
    return new ThisType(*this);
  }

  virtual std::string name() const DS_OVERRIDE
  {
    return name_;
  }

  const SpaceType& space() const
  {
    return space_;
  }

  const VectorType& vector() const
  {
    return vector_;
  }

  ConstLocalDiscreteFunctionType local_discrete_function(const EntityType& entity) const
  {
    assert(space_.grid_view()->indexSet().contains(entity));
    return ConstLocalDiscreteFunctionType(space_, vector_, entity);
  }

  virtual std::unique_ptr< LocalfunctionType > local_function(const EntityType& entity) const DS_OVERRIDE
  {
    return std::unique_ptr< ConstLocalDiscreteFunctionType >
        (new ConstLocalDiscreteFunctionType(local_discrete_function(entity)));
  }

  /**
   * \note  We use the SubsamplingVTKWriter (which is better for higher orders). This means that the grid you see
   *        in the visualization is a refinement of the actual grid!
   */
  void visualize(const std::string filename, VTK::OutputType vtk_output_type = VTK::appendedraw) const
  {
    typedef typename SpaceType::GridViewType GridViewType;
    if (filename.empty()) DUNE_THROW(RangeError, "Empty filename given!");
    auto adapter = std::make_shared< Stuff::Function::VisualizationAdapter< GridViewType, dimRange > >(*this);
    SubsamplingVTKWriter< GridViewType > vtk_writer(*(space_.grid_view()), VTK::nonconforming);
    vtk_writer.addVertexData(adapter);
    vtk_writer.write(filename, vtk_output_type);
  } // ... visualize(...)

protected:
  const SpaceType& space_;
private:
  const VectorType& vector_;
  const std::string name_;
}; // class ConstDiscreteFunction

template< class SpaceImp, class VectorImp >
class DiscreteFunction
  : public ConstDiscreteFunction< SpaceImp, VectorImp >
{
  typedef ConstDiscreteFunction< SpaceImp, VectorImp >  BaseType;
  typedef DiscreteFunction< SpaceImp, VectorImp >       ThisType;
public:
  typedef typename BaseType::SpaceType          SpaceType;
  typedef typename BaseType::VectorType         VectorType;
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  typedef LocalDiscreteFunction< SpaceType, VectorType > LocalDiscreteFunctionType;

  DiscreteFunction(const SpaceType& sp,
                   VectorType& vec,
                   const std::string nm = "dune.gdt.discretefunction")
    : BaseType(sp, vec, nm)
    , vector_(vec)
  {}

  DiscreteFunction(const ThisType& other)
    : BaseType(other)
    , vector_(other.vector_)
  {}

  DiscreteFunction(ThisType&& source)
    : BaseType(std::move(source))
    , vector_(source.vector_)
  {}

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

  ~DiscreteFunction() {}

  virtual ThisType* copy() const DS_OVERRIDE
  {
    return new ThisType(*this);
  }

  VectorType& vector()
  {
    return vector_;
  }

  LocalDiscreteFunctionType local_discrete_function(const EntityType& entity)
  {
    assert(space_.grid_view()->indexSet().contains(entity));
    return LocalDiscreteFunctionType(space_, vector_, entity);
  }

private:
  using BaseType::space_;
  VectorType& vector_;
}; // class DiscreteFunction

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH
<commit_msg>[discretefunction.default] updated visualization * make subsampling optional * delegat work to base type<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//
// Contributors: Kirsten Weber

#ifndef DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH
#define DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH

#include <memory>
#include <type_traits>

#include <dune/common/exceptions.hh>
#include <dune/common/fvector.hh>

#include <dune/grid/io/file/vtk.hh>

#include <dune/stuff/la/container/interfaces.hh>

#include <dune/gdt/space/interface.hh>

#include "local.hh"

namespace Dune {
namespace GDT {

template< class SpaceImp, class VectorImp >
class ConstDiscreteFunction
  : public Stuff::LocalizableFunctionInterface< typename SpaceImp::EntityType,
        typename SpaceImp::DomainFieldType, SpaceImp::dimDomain,
        typename SpaceImp::RangeFieldType, SpaceImp::dimRange, SpaceImp::dimRangeCols >
{
  static_assert(std::is_base_of< SpaceInterface< typename SpaceImp::Traits >, SpaceImp >::value,
                "SpaceImp has to be derived from SpaceInterface!");
  static_assert(std::is_base_of< Dune::Stuff::LA::VectorInterface< typename VectorImp::Traits >, VectorImp >::value,
                "VectorImp has to be derived from Stuff::LA::VectorInterface!");
  static_assert(std::is_same< typename SpaceImp::RangeFieldType, typename VectorImp::ScalarType >::value,
                "Types do not match!");
  typedef Stuff::LocalizableFunctionInterface
      < typename SpaceImp::EntityType, typename SpaceImp::DomainFieldType, SpaceImp::dimDomain,
        typename SpaceImp::RangeFieldType, SpaceImp::dimRange, SpaceImp::dimRangeCols >
    BaseType;
  typedef ConstDiscreteFunction< SpaceImp, VectorImp > ThisType;
public:
  typedef SpaceImp                              SpaceType;
  typedef VectorImp                             VectorType;
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  static const unsigned int                   dimDomain = BaseType::dimDomain;
  typedef typename BaseType::DomainFieldType  DomainFieldType;
  typedef typename BaseType::DomainType       DomainType;

  static const unsigned int                     dimRange = BaseType::dimRange;
  static const unsigned int                     dimRangeCols = BaseType::dimRangeCols;
  typedef typename BaseType::RangeFieldType     RangeFieldType;
  typedef typename BaseType::RangeType          RangeType;
  typedef typename BaseType::JacobianRangeType  JacobianRangeType;

  typedef ConstLocalDiscreteFunction< SpaceType, VectorType > ConstLocalDiscreteFunctionType;

  ConstDiscreteFunction(const SpaceType& sp,
                        const VectorType& vec,
                        const std::string nm = "dune.gdt.constdiscretefunction")
    : space_(sp)
    , vector_(vec)
    , name_(nm)
  {
    assert(vector_.size() == space_.mapper().size() && "Given vector has wrong size!");
  }

  ConstDiscreteFunction(const ThisType& other)
    : space_(other.space_)
    , vector_(other.vector_)
    , name_(other.name_)
  {}

  ConstDiscreteFunction(ThisType&& source)
    : space_(source.space_)
    , vector_(source.vector_)
    , name_(std::move(source.name_))
  {}

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

  ~ConstDiscreteFunction() {}

  virtual ThisType* copy() const DS_OVERRIDE
  {
    return new ThisType(*this);
  }

  virtual std::string name() const DS_OVERRIDE
  {
    return name_;
  }

  const SpaceType& space() const
  {
    return space_;
  }

  const VectorType& vector() const
  {
    return vector_;
  }

  ConstLocalDiscreteFunctionType local_discrete_function(const EntityType& entity) const
  {
    assert(space_.grid_view()->indexSet().contains(entity));
    return ConstLocalDiscreteFunctionType(space_, vector_, entity);
  }

  virtual std::unique_ptr< LocalfunctionType > local_function(const EntityType& entity) const DS_OVERRIDE
  {
    return std::unique_ptr< ConstLocalDiscreteFunctionType >
        (new ConstLocalDiscreteFunctionType(local_discrete_function(entity)));
  }

  void visualize(const std::string filename,
                 const bool subsampling = true,
                 VTK::OutputType vtk_output_type = VTK::appendedraw) const
  {
    BaseType::template visualize< typename SpaceType::GridViewType >(*(space().grid_view()),
                                                                     filename,
                                                                     subsampling,
                                                                     vtk_output_type);
  }

protected:
  const SpaceType& space_;
private:
  const VectorType& vector_;
  const std::string name_;
}; // class ConstDiscreteFunction

template< class SpaceImp, class VectorImp >
class DiscreteFunction
  : public ConstDiscreteFunction< SpaceImp, VectorImp >
{
  typedef ConstDiscreteFunction< SpaceImp, VectorImp >  BaseType;
  typedef DiscreteFunction< SpaceImp, VectorImp >       ThisType;
public:
  typedef typename BaseType::SpaceType          SpaceType;
  typedef typename BaseType::VectorType         VectorType;
  typedef typename BaseType::EntityType         EntityType;
  typedef typename BaseType::LocalfunctionType  LocalfunctionType;

  typedef LocalDiscreteFunction< SpaceType, VectorType > LocalDiscreteFunctionType;

  DiscreteFunction(const SpaceType& sp,
                   VectorType& vec,
                   const std::string nm = "dune.gdt.discretefunction")
    : BaseType(sp, vec, nm)
    , vector_(vec)
  {}

  DiscreteFunction(const ThisType& other)
    : BaseType(other)
    , vector_(other.vector_)
  {}

  DiscreteFunction(ThisType&& source)
    : BaseType(std::move(source))
    , vector_(source.vector_)
  {}

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

  ~DiscreteFunction() {}

  virtual ThisType* copy() const DS_OVERRIDE
  {
    return new ThisType(*this);
  }

  VectorType& vector()
  {
    return vector_;
  }

  LocalDiscreteFunctionType local_discrete_function(const EntityType& entity)
  {
    assert(space_.grid_view()->indexSet().contains(entity));
    return LocalDiscreteFunctionType(space_, vector_, entity);
  }

private:
  using BaseType::space_;
  VectorType& vector_;
}; // class DiscreteFunction

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_DISCRETEFUNCTION_DEFAULT_HH
<|endoftext|>


<commit_before>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include <config.h>

#include "helper.hh"
#include <dune/common/parallel/mpihelper.hh>

int Dune::Stuff::abort_all_mpi_processes() {
#if HAVE_MPI
  return MPI_Abort(MPIHelper::getCommunicator(), 1);
#endif
  return 1;
}
<commit_msg>[common.parallelhelper] don't try to abort solitary mpi procs<commit_after>// This file is part of the dune-stuff project:
//   https://github.com/wwu-numerik/dune-stuff
// Copyright holders: Rene Milk, Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#include <config.h>

#include "helper.hh"
#include <dune/common/parallel/mpihelper.hh>

int Dune::Stuff::abort_all_mpi_processes() {
#if HAVE_MPI
  if (MPIHelper::getCollectiveCommunication().size() > 1)
    return MPI_Abort(MPIHelper::getCommunicator(), 1);
  else
#endif
  return 1;
}
<|endoftext|>


<commit_before>//===- BottomUpClosure.cpp - Compute bottom-up interprocedural closure ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the BUDataStructures class, which represents the
// Bottom-Up Interprocedural closure of the data structure graph over the
// program.  This is useful for applications like pool allocation, but **not**
// applications like alias analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure.h"
#include "llvm/Module.h"
#include "Support/Statistic.h"
#include "Support/Debug.h"
#include "DSCallSiteIterator.h"
using namespace llvm;

namespace {
  Statistic<> MaxSCC("budatastructure", "Maximum SCC Size in Call Graph");
  Statistic<> NumBUInlines("budatastructures", "Number of graphs inlined");
  Statistic<> NumCallEdges("budatastructures", "Number of 'actual' call edges");

  RegisterAnalysis<BUDataStructures>
  X("budatastructure", "Bottom-up Data Structure Analysis");
}

using namespace DS;

// run - Calculate the bottom up data structure graphs for each function in the
// program.
//
bool BUDataStructures::run(Module &M) {
  LocalDataStructures &LocalDSA = getAnalysis<LocalDataStructures>();
  GlobalsGraph = new DSGraph(LocalDSA.getGlobalsGraph());
  GlobalsGraph->setPrintAuxCalls();

  Function *MainFunc = M.getMainFunction();
  if (MainFunc)
    calculateReachableGraphs(MainFunc);

  // Calculate the graphs for any functions that are unreachable from main...
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isExternal() && !DSInfo.count(I)) {
#ifndef NDEBUG
      if (MainFunc)
        std::cerr << "*** Function unreachable from main: "
                  << I->getName() << "\n";
#endif
      calculateReachableGraphs(I);    // Calculate all graphs...
    }

  NumCallEdges += ActualCallees.size();

  // At the end of the bottom-up pass, the globals graph becomes complete.
  // FIXME: This is not the right way to do this, but it is sorta better than
  // nothing!  In particular, externally visible globals and unresolvable call
  // nodes at the end of the BU phase should make things that they point to
  // incomplete in the globals graph.
  //
  GlobalsGraph->removeTriviallyDeadNodes();
  GlobalsGraph->maskIncompleteMarkers();
  return false;
}

void BUDataStructures::calculateReachableGraphs(Function *F) {
  std::vector<Function*> Stack;
  hash_map<Function*, unsigned> ValMap;
  unsigned NextID = 1;
  calculateGraphs(F, Stack, NextID, ValMap);
}

DSGraph &BUDataStructures::getOrCreateGraph(Function *F) {
  // Has the graph already been created?
  DSGraph *&Graph = DSInfo[F];
  if (Graph) return *Graph;

  // Copy the local version into DSInfo...
  Graph = new DSGraph(getAnalysis<LocalDataStructures>().getDSGraph(*F));

  Graph->setGlobalsGraph(GlobalsGraph);
  Graph->setPrintAuxCalls();

  // Start with a copy of the original call sites...
  Graph->getAuxFunctionCalls() = Graph->getFunctionCalls();
  return *Graph;
}

unsigned BUDataStructures::calculateGraphs(Function *F,
                                           std::vector<Function*> &Stack,
                                           unsigned &NextID,
                                     hash_map<Function*, unsigned> &ValMap) {
  assert(!ValMap.count(F) && "Shouldn't revisit functions!");
  unsigned Min = NextID++, MyID = Min;
  ValMap[F] = Min;
  Stack.push_back(F);

  if (F->isExternal()) {   // sprintf, fprintf, sscanf, etc...
    // No callees!
    Stack.pop_back();
    ValMap[F] = ~0;
    return Min;
  }

  DSGraph &Graph = getOrCreateGraph(F);

  // The edges out of the current node are the call site targets...
  for (DSCallSiteIterator I = DSCallSiteIterator::begin_aux(Graph),
         E = DSCallSiteIterator::end_aux(Graph); I != E; ++I) {
    Function *Callee = *I;
    unsigned M;
    // Have we visited the destination function yet?
    hash_map<Function*, unsigned>::iterator It = ValMap.find(Callee);
    if (It == ValMap.end())  // No, visit it now.
      M = calculateGraphs(Callee, Stack, NextID, ValMap);
    else                    // Yes, get it's number.
      M = It->second;
    if (M < Min) Min = M;
  }

  assert(ValMap[F] == MyID && "SCC construction assumption wrong!");
  if (Min != MyID)
    return Min;         // This is part of a larger SCC!

  // If this is a new SCC, process it now.
  if (Stack.back() == F) {           // Special case the single "SCC" case here.
    DEBUG(std::cerr << "Visiting single node SCC #: " << MyID << " fn: "
                    << F->getName() << "\n");
    Stack.pop_back();
    DSGraph &G = getDSGraph(*F);
    DEBUG(std::cerr << "  [BU] Calculating graph for: " << F->getName()<< "\n");
    calculateGraph(G);
    DEBUG(std::cerr << "  [BU] Done inlining: " << F->getName() << " ["
                    << G.getGraphSize() << "+" << G.getAuxFunctionCalls().size()
                    << "]\n");

    if (MaxSCC < 1) MaxSCC = 1;

    // Should we revisit the graph?
    if (DSCallSiteIterator::begin_aux(G) != DSCallSiteIterator::end_aux(G)) {
      ValMap.erase(F);
      return calculateGraphs(F, Stack, NextID, ValMap);
    } else {
      ValMap[F] = ~0U;
    }
    return MyID;

  } else {
    // SCCFunctions - Keep track of the functions in the current SCC
    //
    hash_set<DSGraph*> SCCGraphs;

    Function *NF;
    std::vector<Function*>::iterator FirstInSCC = Stack.end();
    DSGraph *SCCGraph = 0;
    do {
      NF = *--FirstInSCC;
      ValMap[NF] = ~0U;

      // Figure out which graph is the largest one, in order to speed things up
      // a bit in situations where functions in the SCC have widely different
      // graph sizes.
      DSGraph &NFGraph = getDSGraph(*NF);
      SCCGraphs.insert(&NFGraph);
      if (!SCCGraph || SCCGraph->getGraphSize() < NFGraph.getGraphSize())
        SCCGraph = &NFGraph;
    } while (NF != F);

    std::cerr << "Calculating graph for SCC #: " << MyID << " of size: "
              << SCCGraphs.size() << "\n";

    // Compute the Max SCC Size...
    if (MaxSCC < SCCGraphs.size())
      MaxSCC = SCCGraphs.size();

    // First thing first, collapse all of the DSGraphs into a single graph for
    // the entire SCC.  We computed the largest graph, so clone all of the other
    // (smaller) graphs into it.  Discard all of the old graphs.
    //
    for (hash_set<DSGraph*>::iterator I = SCCGraphs.begin(),
           E = SCCGraphs.end(); I != E; ++I) {
      DSGraph &G = **I;
      if (&G != SCCGraph) {
        DSGraph::NodeMapTy NodeMap;
        SCCGraph->cloneInto(G, SCCGraph->getScalarMap(),
                            SCCGraph->getReturnNodes(), NodeMap);
        // Update the DSInfo map and delete the old graph...
        for (DSGraph::ReturnNodesTy::iterator I = G.getReturnNodes().begin(),
               E = G.getReturnNodes().end(); I != E; ++I)
          DSInfo[I->first] = SCCGraph;
        delete &G;
      }
    }

    // Clean up the graph before we start inlining a bunch again...
    SCCGraph->removeDeadNodes(DSGraph::RemoveUnreachableGlobals);

    // Now that we have one big happy family, resolve all of the call sites in
    // the graph...
    calculateGraph(*SCCGraph);
    DEBUG(std::cerr << "  [BU] Done inlining SCC  [" << SCCGraph->getGraphSize()
                    << "+" << SCCGraph->getAuxFunctionCalls().size() << "]\n");

    std::cerr << "DONE with SCC #: " << MyID << "\n";

    // We never have to revisit "SCC" processed functions...

    // Drop the stuff we don't need from the end of the stack
    Stack.erase(FirstInSCC, Stack.end());
    return MyID;
  }

  return MyID;  // == Min
}

// releaseMemory - If the pass pipeline is done with this pass, we can release
// our memory... here...
//
void BUDataStructures::releaseMemory() {
  for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
         E = DSInfo.end(); I != E; ++I) {
    I->second->getReturnNodes().erase(I->first);
    if (I->second->getReturnNodes().empty())
      delete I->second;
  }

  // Empty map so next time memory is released, data structures are not
  // re-deleted.
  DSInfo.clear();
  delete GlobalsGraph;
  GlobalsGraph = 0;
}

void BUDataStructures::calculateGraph(DSGraph &Graph) {
  // Move our call site list into TempFCs so that inline call sites go into the
  // new call site list and doesn't invalidate our iterators!
  std::vector<DSCallSite> TempFCs;
  std::vector<DSCallSite> &AuxCallsList = Graph.getAuxFunctionCalls();
  TempFCs.swap(AuxCallsList);

  DSGraph::ReturnNodesTy &ReturnNodes = Graph.getReturnNodes();

  // Loop over all of the resolvable call sites
  unsigned LastCallSiteIdx = ~0U;
  for (DSCallSiteIterator I = DSCallSiteIterator::begin(TempFCs),
         E = DSCallSiteIterator::end(TempFCs); I != E; ++I) {
    // If we skipped over any call sites, they must be unresolvable, copy them
    // to the real call site list.
    LastCallSiteIdx++;
    for (; LastCallSiteIdx < I.getCallSiteIdx(); ++LastCallSiteIdx)
      AuxCallsList.push_back(TempFCs[LastCallSiteIdx]);
    LastCallSiteIdx = I.getCallSiteIdx();

    // Resolve the current call...
    Function *Callee = *I;
    DSCallSite CS = I.getCallSite();

    if (Callee->isExternal()) {
      // Ignore this case, simple varargs functions we cannot stub out!
    } else if (ReturnNodes.count(Callee)) {
      // Self recursion... simply link up the formal arguments with the
      // actual arguments...
      DEBUG(std::cerr << "    Self Inlining: " << Callee->getName() << "\n");

      // Handle self recursion by resolving the arguments and return value
      Graph.mergeInGraph(CS, *Callee, Graph, 0);

    } else {
      ActualCallees.insert(std::make_pair(CS.getCallSite().getInstruction(),
                                          Callee));

      // Get the data structure graph for the called function.
      //
      DSGraph &GI = getDSGraph(*Callee);  // Graph to inline

      DEBUG(std::cerr << "    Inlining graph for " << Callee->getName()
            << "[" << GI.getGraphSize() << "+"
            << GI.getAuxFunctionCalls().size() << "] into '"
            << Graph.getFunctionNames() << "' [" << Graph.getGraphSize() << "+"
            << Graph.getAuxFunctionCalls().size() << "]\n");

      Graph.mergeInGraph(CS, *Callee, GI,
                         DSGraph::KeepModRefBits |
                         DSGraph::StripAllocaBit | DSGraph::DontCloneCallNodes);
      ++NumBUInlines;

#if 0
      Graph.writeGraphToFile(std::cerr, "bu_" + F.getName() + "_after_" +
                             Callee->getName());
#endif
    }
  }

  // Make sure to catch any leftover unresolvable calls...
  for (++LastCallSiteIdx; LastCallSiteIdx < TempFCs.size(); ++LastCallSiteIdx)
    AuxCallsList.push_back(TempFCs[LastCallSiteIdx]);

  TempFCs.clear();

  // Re-materialize nodes from the globals graph.
  // Do not ignore globals inlined from callees -- they are not up-to-date!
  assert(Graph.getInlinedGlobals().empty());
  Graph.updateFromGlobalGraph();

  // Recompute the Incomplete markers
  Graph.maskIncompleteMarkers();
  Graph.markIncompleteNodes(DSGraph::MarkFormalArgs);

  // Delete dead nodes.  Treat globals that are unreachable but that can
  // reach live nodes as live.
  Graph.removeDeadNodes(DSGraph::KeepUnreachableGlobals);

  //Graph.writeGraphToFile(std::cerr, "bu_" + F.getName());
}
<commit_msg>When we complete the bottom-up pass, make sure to merge the globals in 'main' into the globals graph.<commit_after>//===- BottomUpClosure.cpp - Compute bottom-up interprocedural closure ----===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the BUDataStructures class, which represents the
// Bottom-Up Interprocedural closure of the data structure graph over the
// program.  This is useful for applications like pool allocation, but **not**
// applications like alias analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure.h"
#include "llvm/Module.h"
#include "Support/Statistic.h"
#include "Support/Debug.h"
#include "DSCallSiteIterator.h"
using namespace llvm;

namespace {
  Statistic<> MaxSCC("budatastructure", "Maximum SCC Size in Call Graph");
  Statistic<> NumBUInlines("budatastructures", "Number of graphs inlined");
  Statistic<> NumCallEdges("budatastructures", "Number of 'actual' call edges");

  RegisterAnalysis<BUDataStructures>
  X("budatastructure", "Bottom-up Data Structure Analysis");
}

using namespace DS;

// run - Calculate the bottom up data structure graphs for each function in the
// program.
//
bool BUDataStructures::run(Module &M) {
  LocalDataStructures &LocalDSA = getAnalysis<LocalDataStructures>();
  GlobalsGraph = new DSGraph(LocalDSA.getGlobalsGraph());
  GlobalsGraph->setPrintAuxCalls();

  Function *MainFunc = M.getMainFunction();
  if (MainFunc)
    calculateReachableGraphs(MainFunc);

  // Calculate the graphs for any functions that are unreachable from main...
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isExternal() && !DSInfo.count(I)) {
#ifndef NDEBUG
      if (MainFunc)
        std::cerr << "*** Function unreachable from main: "
                  << I->getName() << "\n";
#endif
      calculateReachableGraphs(I);    // Calculate all graphs...
    }

  NumCallEdges += ActualCallees.size();

  // At the end of the BU phase, clone the BU graph for main into the globals
  // graph to make sure it has everything.
  if (MainFunc) {
    DSGraph &MainGraph = getOrCreateGraph(MainFunc);
    DSScalarMap &MainSM = MainGraph.getScalarMap();
    ReachabilityCloner RC(*GlobalsGraph, MainGraph, DSGraph::StripAllocaBit);

    // Clone everything reachable from globals in the "main" graph into the
    // globals graph.
    for (DSScalarMap::global_iterator I = MainSM.global_begin(),
           E = MainSM.global_end(); I != E; ++I)
      RC.getClonedNH(MainSM[*I]);

  }

  // At the end of the bottom-up pass, the globals graph becomes complete.
  // FIXME: This is not the right way to do this, but it is sorta better than
  // nothing!  In particular, externally visible globals and unresolvable call
  // nodes at the end of the BU phase should make things that they point to
  // incomplete in the globals graph.
  //
  GlobalsGraph->removeTriviallyDeadNodes();
  GlobalsGraph->maskIncompleteMarkers();
  return false;
}

void BUDataStructures::calculateReachableGraphs(Function *F) {
  std::vector<Function*> Stack;
  hash_map<Function*, unsigned> ValMap;
  unsigned NextID = 1;
  calculateGraphs(F, Stack, NextID, ValMap);
}

DSGraph &BUDataStructures::getOrCreateGraph(Function *F) {
  // Has the graph already been created?
  DSGraph *&Graph = DSInfo[F];
  if (Graph) return *Graph;

  // Copy the local version into DSInfo...
  Graph = new DSGraph(getAnalysis<LocalDataStructures>().getDSGraph(*F));

  Graph->setGlobalsGraph(GlobalsGraph);
  Graph->setPrintAuxCalls();

  // Start with a copy of the original call sites...
  Graph->getAuxFunctionCalls() = Graph->getFunctionCalls();
  return *Graph;
}

unsigned BUDataStructures::calculateGraphs(Function *F,
                                           std::vector<Function*> &Stack,
                                           unsigned &NextID,
                                     hash_map<Function*, unsigned> &ValMap) {
  assert(!ValMap.count(F) && "Shouldn't revisit functions!");
  unsigned Min = NextID++, MyID = Min;
  ValMap[F] = Min;
  Stack.push_back(F);

  if (F->isExternal()) {   // sprintf, fprintf, sscanf, etc...
    // No callees!
    Stack.pop_back();
    ValMap[F] = ~0;
    return Min;
  }

  DSGraph &Graph = getOrCreateGraph(F);

  // The edges out of the current node are the call site targets...
  for (DSCallSiteIterator I = DSCallSiteIterator::begin_aux(Graph),
         E = DSCallSiteIterator::end_aux(Graph); I != E; ++I) {
    Function *Callee = *I;
    unsigned M;
    // Have we visited the destination function yet?
    hash_map<Function*, unsigned>::iterator It = ValMap.find(Callee);
    if (It == ValMap.end())  // No, visit it now.
      M = calculateGraphs(Callee, Stack, NextID, ValMap);
    else                    // Yes, get it's number.
      M = It->second;
    if (M < Min) Min = M;
  }

  assert(ValMap[F] == MyID && "SCC construction assumption wrong!");
  if (Min != MyID)
    return Min;         // This is part of a larger SCC!

  // If this is a new SCC, process it now.
  if (Stack.back() == F) {           // Special case the single "SCC" case here.
    DEBUG(std::cerr << "Visiting single node SCC #: " << MyID << " fn: "
                    << F->getName() << "\n");
    Stack.pop_back();
    DSGraph &G = getDSGraph(*F);
    DEBUG(std::cerr << "  [BU] Calculating graph for: " << F->getName()<< "\n");
    calculateGraph(G);
    DEBUG(std::cerr << "  [BU] Done inlining: " << F->getName() << " ["
                    << G.getGraphSize() << "+" << G.getAuxFunctionCalls().size()
                    << "]\n");

    if (MaxSCC < 1) MaxSCC = 1;

    // Should we revisit the graph?
    if (DSCallSiteIterator::begin_aux(G) != DSCallSiteIterator::end_aux(G)) {
      ValMap.erase(F);
      return calculateGraphs(F, Stack, NextID, ValMap);
    } else {
      ValMap[F] = ~0U;
    }
    return MyID;

  } else {
    // SCCFunctions - Keep track of the functions in the current SCC
    //
    hash_set<DSGraph*> SCCGraphs;

    Function *NF;
    std::vector<Function*>::iterator FirstInSCC = Stack.end();
    DSGraph *SCCGraph = 0;
    do {
      NF = *--FirstInSCC;
      ValMap[NF] = ~0U;

      // Figure out which graph is the largest one, in order to speed things up
      // a bit in situations where functions in the SCC have widely different
      // graph sizes.
      DSGraph &NFGraph = getDSGraph(*NF);
      SCCGraphs.insert(&NFGraph);
      if (!SCCGraph || SCCGraph->getGraphSize() < NFGraph.getGraphSize())
        SCCGraph = &NFGraph;
    } while (NF != F);

    std::cerr << "Calculating graph for SCC #: " << MyID << " of size: "
              << SCCGraphs.size() << "\n";

    // Compute the Max SCC Size...
    if (MaxSCC < SCCGraphs.size())
      MaxSCC = SCCGraphs.size();

    // First thing first, collapse all of the DSGraphs into a single graph for
    // the entire SCC.  We computed the largest graph, so clone all of the other
    // (smaller) graphs into it.  Discard all of the old graphs.
    //
    for (hash_set<DSGraph*>::iterator I = SCCGraphs.begin(),
           E = SCCGraphs.end(); I != E; ++I) {
      DSGraph &G = **I;
      if (&G != SCCGraph) {
        DSGraph::NodeMapTy NodeMap;
        SCCGraph->cloneInto(G, SCCGraph->getScalarMap(),
                            SCCGraph->getReturnNodes(), NodeMap);
        // Update the DSInfo map and delete the old graph...
        for (DSGraph::ReturnNodesTy::iterator I = G.getReturnNodes().begin(),
               E = G.getReturnNodes().end(); I != E; ++I)
          DSInfo[I->first] = SCCGraph;
        delete &G;
      }
    }

    // Clean up the graph before we start inlining a bunch again...
    SCCGraph->removeDeadNodes(DSGraph::RemoveUnreachableGlobals);

    // Now that we have one big happy family, resolve all of the call sites in
    // the graph...
    calculateGraph(*SCCGraph);
    DEBUG(std::cerr << "  [BU] Done inlining SCC  [" << SCCGraph->getGraphSize()
                    << "+" << SCCGraph->getAuxFunctionCalls().size() << "]\n");

    std::cerr << "DONE with SCC #: " << MyID << "\n";

    // We never have to revisit "SCC" processed functions...

    // Drop the stuff we don't need from the end of the stack
    Stack.erase(FirstInSCC, Stack.end());
    return MyID;
  }

  return MyID;  // == Min
}

// releaseMemory - If the pass pipeline is done with this pass, we can release
// our memory... here...
//
void BUDataStructures::releaseMemory() {
  for (hash_map<Function*, DSGraph*>::iterator I = DSInfo.begin(),
         E = DSInfo.end(); I != E; ++I) {
    I->second->getReturnNodes().erase(I->first);
    if (I->second->getReturnNodes().empty())
      delete I->second;
  }

  // Empty map so next time memory is released, data structures are not
  // re-deleted.
  DSInfo.clear();
  delete GlobalsGraph;
  GlobalsGraph = 0;
}

void BUDataStructures::calculateGraph(DSGraph &Graph) {
  // Move our call site list into TempFCs so that inline call sites go into the
  // new call site list and doesn't invalidate our iterators!
  std::vector<DSCallSite> TempFCs;
  std::vector<DSCallSite> &AuxCallsList = Graph.getAuxFunctionCalls();
  TempFCs.swap(AuxCallsList);

  DSGraph::ReturnNodesTy &ReturnNodes = Graph.getReturnNodes();

  // Loop over all of the resolvable call sites
  unsigned LastCallSiteIdx = ~0U;
  for (DSCallSiteIterator I = DSCallSiteIterator::begin(TempFCs),
         E = DSCallSiteIterator::end(TempFCs); I != E; ++I) {
    // If we skipped over any call sites, they must be unresolvable, copy them
    // to the real call site list.
    LastCallSiteIdx++;
    for (; LastCallSiteIdx < I.getCallSiteIdx(); ++LastCallSiteIdx)
      AuxCallsList.push_back(TempFCs[LastCallSiteIdx]);
    LastCallSiteIdx = I.getCallSiteIdx();

    // Resolve the current call...
    Function *Callee = *I;
    DSCallSite CS = I.getCallSite();

    if (Callee->isExternal()) {
      // Ignore this case, simple varargs functions we cannot stub out!
    } else if (ReturnNodes.count(Callee)) {
      // Self recursion... simply link up the formal arguments with the
      // actual arguments...
      DEBUG(std::cerr << "    Self Inlining: " << Callee->getName() << "\n");

      // Handle self recursion by resolving the arguments and return value
      Graph.mergeInGraph(CS, *Callee, Graph, 0);

    } else {
      ActualCallees.insert(std::make_pair(CS.getCallSite().getInstruction(),
                                          Callee));

      // Get the data structure graph for the called function.
      //
      DSGraph &GI = getDSGraph(*Callee);  // Graph to inline

      DEBUG(std::cerr << "    Inlining graph for " << Callee->getName()
            << "[" << GI.getGraphSize() << "+"
            << GI.getAuxFunctionCalls().size() << "] into '"
            << Graph.getFunctionNames() << "' [" << Graph.getGraphSize() << "+"
            << Graph.getAuxFunctionCalls().size() << "]\n");

      Graph.mergeInGraph(CS, *Callee, GI,
                         DSGraph::KeepModRefBits |
                         DSGraph::StripAllocaBit | DSGraph::DontCloneCallNodes);
      ++NumBUInlines;

#if 0
      Graph.writeGraphToFile(std::cerr, "bu_" + F.getName() + "_after_" +
                             Callee->getName());
#endif
    }
  }

  // Make sure to catch any leftover unresolvable calls...
  for (++LastCallSiteIdx; LastCallSiteIdx < TempFCs.size(); ++LastCallSiteIdx)
    AuxCallsList.push_back(TempFCs[LastCallSiteIdx]);

  TempFCs.clear();

  // Re-materialize nodes from the globals graph.
  // Do not ignore globals inlined from callees -- they are not up-to-date!
  assert(Graph.getInlinedGlobals().empty());
  Graph.updateFromGlobalGraph();

  // Recompute the Incomplete markers
  Graph.maskIncompleteMarkers();
  Graph.markIncompleteNodes(DSGraph::MarkFormalArgs);

  // Delete dead nodes.  Treat globals that are unreachable but that can
  // reach live nodes as live.
  Graph.removeDeadNodes(DSGraph::KeepUnreachableGlobals);

  //Graph.writeGraphToFile(std::cerr, "bu_" + F.getName());
}
<|endoftext|>


<commit_before>//
//  translator.cpp
//  koberi-c
//
//  Created by Filip Peterek on 31/10/2016.
//  Copyright © 2016 Filip Peterek. All rights reserved.
//

#include "translator.hpp"

Translator::Translator(std::vector<token> & vectorRef) : _tokens(vectorRef) /* Call the reference constructor */ {

    _output.open("output.c");

    if (not _output) {

        throw file_not_opened("output.c");

    }

}

void Translator::checkType(std::string & type) {

    if (not (dataTypes >> type)) {
        throw bad_type("Invalid data type " + type);
    }

}

void Translator::mangleName(std::string & name, std::vector<parameter> & params) {

    if (name == "main") { return; }

    name.insert(0, "_");

    for (auto & i : params) {

        name += "_" + i.type;

    }

}

void Translator::parseParams(unsigned long long beginning, std::vector<parameter> & params) {

    for (unsigned long long i = beginning + 1; _tokens[i] != tokType::closingPar and _tokens[i+1] != tokType::closingPar; i += 2) {

        if (_tokens[i] == tokType::closingPar or _tokens[i+1] == tokType::closingPar) { break; }
        params.emplace_back();
        params.back().type = _tokens[i].value;
        checkType(params.back().type);
        params.back().value = _tokens[i+1].value;

    }

}

parameter Translator::parseSexp(unsigned long long sexpBeginning) {

    parameter expr;

    std::vector<parameter> params;
    std::string funName = _tokens[sexpBeginning + 1].value;

    unsigned long long iter = sexpBeginning + 2; /* sexpBeginning is parenthesis, sexpBeginning + 1 is function name,
                                                    sexpBeginning + 2 is the first param */

    for (unsigned int parenCounter = 1; parenCounter != 0; ++iter ) {

        /* Recursively parse sexps nested in other sexps */
        /* if (parenCounter == 1 and token == '(') {} so only the first expression is parsed in this function call,
           expressions nested in other expressions will be parsed recursively */

        if (_tokens[iter] == tokType::openingPar and parenCounter == 1) {

            ++parenCounter;
            params.emplace_back(parseSexp(iter));

        }
        else if (_tokens[iter] == tokType::openingPar) { ++parenCounter; }
        else if (_tokens[iter] == tokType::closingPar) { --parenCounter; }
        else if (parenCounter == 1) { params.emplace_back(_tokens[iter].value); }

    }

    if (dataTypes >> funName and params.size()) {
        if (params.size() == 1) {
            expr = expr::variableDeclaration(funName, params[0].value);
        }
        else {
            expr = expr::variableDeclaration(funName, params[0].value, params[1].value);
        }
        _localVars.emplace(funName, params[0].value);
    } else if (funName == "toNum" and params.size() == 1 and expr::native_types >> params[0].type) {
        expr = expr::conversionToNum(params[0]);
    } else if (funName == "toInt" and params.size() == 1 and expr::native_types >> params[0].type) {
        expr = expr::conversionToInt(params[0]);
    } else if (expr::unary_operators >> funName and params.size() == 1) {
        expr = expr::unaryOperator(params[0], funName);
    } else if (expr::binary_operators >> funName and (params[0].type == "int" or params[0].type == "double")) {
        expr = expr::binaryOperator(params, funName);
    } else if ((funName == "while" or funName == "if") and params.size() > 1) {
        expr.value = funName + params[0].value + " {\n";
        expr.type = "void";
        for (size_t i = 1; i < params.size(); ++i) {
            expr.value += params[i].value + ";\n";
        }
        expr.value += "}";
    }
    else {

        for (auto & i : _localVars) {

            std::cout << i.first << " - " << i.second << std::endl;

        }

        if (params.size()) {
            goto x; /* Eww, but is there a better, readable way? */
        }

        /* Check if it's a variable, otherwise call a function */

        try {
            expr.type = _localVars.at(funName);
            expr.value = funName;
            return expr;
        } catch(const std::out_of_range & e) {
            /* Do nothing, just go to next step */
        }

        try {
            expr.type = _globalVars.at(funName);
            expr.value = funName;
            return expr;
        } catch(const std::out_of_range & e) {
            /* Do nothing, just go to next step */
        }

    x:

        mangleName(funName, params);

        try {
            expr.type = _functions.at(funName);
        } catch (const std::exception & e) {
            throw undeclared_function_call("Invalid call to function " + funName);
        }

        std::stringstream ss;

        ss << funName << "(";

        size_t size = params.size();
        for (size_t i = 0; i < size; ++i) {
            ss << params[i].value << ((i != size - 1) ? ", " : "");
        }
        ss << ")";
    }

    return expr;

}

void Translator::parseSexps(unsigned long long firstSexp) {

    unsigned long long parenCounter = 0;
    unsigned long long iter = firstSexp;
    std::vector<unsigned long long> sexps;
    token tok;

    do {

        tok = _tokens[iter];

        if (tok == tokType::openingPar) { ++parenCounter; }
        else if (tok == tokType::closingPar) { --parenCounter; }

        if (parenCounter == 1 and tok == tokType::openingPar) {
            sexps.emplace_back(iter); }

        ++iter;

    } while (parenCounter);

    for (unsigned long long i : sexps) {

        /* Appending a semicolon at the end - semicolons after if () {} don't do anything, but  */
        /*  the compiler would probably miss the semicolon after an assignment                  */
        /* In the end, there might be too many useless semicolons, but whatever                 */
        /* If you wanna help battle the semicolon inflation, don't comment your Kobeři-C code   */
        _output << parseSexp(i).value << ";" << std::endl;

    }

}

void Translator::parseFun(unsigned long long funBeginning, unsigned long long funEnd) {

    _localVars = std::unordered_map<std::string, std::string>();

#if PRINT_FUNCTIONS_TOKENS
    for (unsigned long long i = funcBeginning; i < funcEnd; ++i) {
        print(_tokens[i].value);
    }
#endif

    std::string type = _tokens[funBeginning + 1].value;
    checkType(type);

    std::string name = _tokens[funBeginning + 2].value;
    std::vector<parameter> params;

    parseParams(funBeginning + 3, params);

    for (parameter & p : params) {
        _localVars.emplace(p.value, p.type);
    }

    mangleName(name, params); /* The name of main won't be mangled */

    if (name == "main") {
        _output << "int main(int argc, const char * argv[]) {\n";
    }
    else {

        _output << ((type == "int") ? "ll" : type) << " " << name << "(";

        size_t size = params.size();
        for (size_t i = 0; i < size; ++i) {
            _output << (params[i].type == "int" ? "ll" : params[i].type) << " " << params[i].value << ((i != size - 1) ? ", " : "");
        }
        if (not size) { _output << "void"; }
        _output << ") {\n";

    }

    unsigned long long sexp = 0;

    /* funBeginning = (; funBeginning + 1 = data type; funBeginning + 2 = name; funBeginning + 3 = ( */
    /* Find location of first s-expression */
    for (sexp = funBeginning + 3; _tokens[sexp] != tokType::closingPar; ++sexp);

    parseSexps(sexp + 1);

    _output << "}\n\n";

}

void Translator::varDeclaration(unsigned long long declBeginning, unsigned long long declEnd) {

    std::stringstream ss;

    if (declEnd - declBeginning < 4) { /* 0 for (; 1 for (); 2 for (global); 3 for (global type); 4 for (global type name);
                                          At least 4 tokens are needed to declare a global variable */

        for (unsigned long long i = declBeginning; i < declEnd; ++i) {
            ss << (_tokens[i] != tokType::openingPar ? "" : " ") << _tokens[i].value;
        }

        throw invalid_declaration("Invalid variable declaration:" + ss.str());

    }

    std::string type = _tokens[declBeginning + 2].value;
    checkType(type);

    std::string name = _tokens[declBeginning + 3].value;

    ss << (type == "int" ? "ll" : type) << " " << name;

    if (_tokens[declBeginning + 4] != tokType::closingPar) {
        ss << " = " << _tokens[declBeginning + 4].value;
    }

    ss << ";";

#ifdef OUTPUT_GLOBAL_VARIABLE_DECLARATION
    print(ss.str());
#endif

    _output << ss.str() << std::endl;

    _globalVars.emplace(name, type);

}

void Translator::funDeclaration(unsigned long long declBeginning, unsigned long long declEnd) {

    std::string type = _tokens[declBeginning + 1].value;
    checkType(type);

    std::string name = _tokens[declBeginning + 2].value;
    if (name == "main" and type != "int") { throw invalid_declaration("Main must return int. "); }
    std::vector<parameter> params;

    parseParams(declBeginning + 3, params);
    mangleName(name, params);
    _functions.emplace(name, type);

    std::stringstream ss;
    if (name != "main") {
        ss << (type == "int" ? "ll" : type) << " " << name << "(";
    } else {
        _output << "int main(int argc, const char * argv[]);" << std::endl;
#ifdef OUTPUT_FUNCTION_DECLARATION
        print("int main(int argc, const char * argv[]);");
#endif
        return;
    }
    size_t size = params.size();

    for (size_t i = 0; i < size; ++i) {

        ss << (params[i].type == "int" ? "ll" : params[i].type) << " " << params[i].value << ((i != size - 1) ? ", " : "");

    }
    if (not size) { ss << "void"; }
    ss << ");";

    _output << ss.str() << std::endl;

#ifdef OUTPUT_FUNCTION_DECLARATION
    print(ss.str());
#endif

}

void Translator::parseDeclarations() {

    _output << "/* User defined function declarations and global variables. */\n\n";

    unsigned long long parens = 0;
    unsigned long long declBeginning = 0, declEnd = 0;

    for (unsigned long long i = 0; i < _tokens.size(); ++i) {

        if (_tokens[i].type == tokType::openingPar) {

            ++parens;
            if (parens == 1) { declBeginning = i; }

        }
        else if (_tokens[i].type == tokType::closingPar) {

            --parens;

        }

        if (not parens) {

            declEnd = i;
            declaration(declBeginning, declEnd);

        }

    } /* For */

    _output << "\n"; /* Output two newlines after function declarations, mostly for readability */

}

void Translator::declaration(unsigned long long declBeginning, unsigned long long declEnd) {

    if (_tokens[declBeginning + 1].value == "global") {

        varDeclaration(declBeginning, declEnd);

    } else {

        funDeclaration(declBeginning, declEnd);

    }

}

void Translator::libs() {

    _output << "#include <stdio.h>\n"
            << "#include <stdlib.h>\n"
            << "#include <math.h>\n"
            << "#include <time.h>\n"
            << "\n"
            << std::endl;

}

void Translator::typedefs() {

    _output << "typedef double num;\n"
            << "typedef long long ll;\n"
            << std::endl;

}

void Translator::functions() {

    _output << "/* Kobeři-c standard library functions */\n\n"
            << "char * __numToStr(num param) { \n"
            << "    char * temp = (char *) malloc(50);\n"
            << "    sprintf(temp, \"%f\", param);\n"
            << "    return temp;\n"
            << "}\n\n"
            << "char * __intToStr(ll param) {\n"
            << "    char * temp = (char *) malloc(50);\n"
            << "    sprintf(temp, \"%f\", param);\n"
            << "    return temp;\n"
            << "}\n\n" << std::flush;

}

void Translator::parseDefinitions() {

    _output << "/* User defined function definitions */\n" << std::endl;

    unsigned long long parens = 0;
    unsigned long long defBeginning = 0, defEnd = 0;

    for (int i = 0; i < _tokens.size(); ++i) {

        if (_tokens[i].type == tokType::openingPar) {

            ++parens;
            if (parens == 1) { defBeginning = i; }

        }
        else if (_tokens[i].type == tokType::closingPar) {

            --parens;

        }

        if (not parens) {
            defEnd = i;
            definition(defBeginning, defEnd);
        }

    } /* For */

}

void Translator::definition(unsigned long long defBeginning, unsigned long long defEnd) {

    if (_tokens[defBeginning + 1].value != "global") {
        parseFun(defBeginning, defEnd);
    }

}

void Translator::translate() {

    libs();
    typedefs();
    functions();

    parseDeclarations();
    parseDefinitions();

}
<commit_msg>I was supposed to delete that<commit_after>//
//  translator.cpp
//  koberi-c
//
//  Created by Filip Peterek on 31/10/2016.
//  Copyright © 2016 Filip Peterek. All rights reserved.
//

#include "translator.hpp"

Translator::Translator(std::vector<token> & vectorRef) : _tokens(vectorRef) /* Call the reference constructor */ {

    _output.open("output.c");

    if (not _output) {

        throw file_not_opened("output.c");

    }

}

void Translator::checkType(std::string & type) {

    if (not (dataTypes >> type)) {
        throw bad_type("Invalid data type " + type);
    }

}

void Translator::mangleName(std::string & name, std::vector<parameter> & params) {

    if (name == "main") { return; }

    name.insert(0, "_");

    for (auto & i : params) {

        name += "_" + i.type;

    }

}

void Translator::parseParams(unsigned long long beginning, std::vector<parameter> & params) {

    for (unsigned long long i = beginning + 1; _tokens[i] != tokType::closingPar and _tokens[i+1] != tokType::closingPar; i += 2) {

        if (_tokens[i] == tokType::closingPar or _tokens[i+1] == tokType::closingPar) { break; }
        params.emplace_back();
        params.back().type = _tokens[i].value;
        checkType(params.back().type);
        params.back().value = _tokens[i+1].value;

    }

}

parameter Translator::parseSexp(unsigned long long sexpBeginning) {

    parameter expr;

    std::vector<parameter> params;
    std::string funName = _tokens[sexpBeginning + 1].value;

    unsigned long long iter = sexpBeginning + 2; /* sexpBeginning is parenthesis, sexpBeginning + 1 is function name,
                                                    sexpBeginning + 2 is the first param */

    for (unsigned int parenCounter = 1; parenCounter != 0; ++iter ) {

        /* Recursively parse sexps nested in other sexps */
        /* if (parenCounter == 1 and token == '(') {} so only the first expression is parsed in this function call,
           expressions nested in other expressions will be parsed recursively */

        if (_tokens[iter] == tokType::openingPar and parenCounter == 1) {

            ++parenCounter;
            params.emplace_back(parseSexp(iter));

        }
        else if (_tokens[iter] == tokType::openingPar) { ++parenCounter; }
        else if (_tokens[iter] == tokType::closingPar) { --parenCounter; }
        else if (parenCounter == 1) { params.emplace_back(_tokens[iter].value); }

    }

    if (dataTypes >> funName and params.size()) {
        if (params.size() == 1) {
            expr = expr::variableDeclaration(funName, params[0].value);
        }
        else {
            expr = expr::variableDeclaration(funName, params[0].value, params[1].value);
        }
        _localVars.emplace(funName, params[0].value);
    } else if (funName == "toNum" and params.size() == 1 and expr::native_types >> params[0].type) {
        expr = expr::conversionToNum(params[0]);
    } else if (funName == "toInt" and params.size() == 1 and expr::native_types >> params[0].type) {
        expr = expr::conversionToInt(params[0]);
    } else if (expr::unary_operators >> funName and params.size() == 1) {
        expr = expr::unaryOperator(params[0], funName);
    } else if (expr::binary_operators >> funName and (params[0].type == "int" or params[0].type == "double")) {
        expr = expr::binaryOperator(params, funName);
    } else if ((funName == "while" or funName == "if") and params.size() > 1) {
        expr.value = funName + params[0].value + " {\n";
        expr.type = "void";
        for (size_t i = 1; i < params.size(); ++i) {
            expr.value += params[i].value + ";\n";
        }
        expr.value += "}";
    }
    else {

        if (params.size()) {
            goto x; /* Eww, but is there a better, readable way? */
        }

        /* Check if it's a variable, otherwise call a function */

        try {
            expr.type = _localVars.at(funName);
            expr.value = funName;
            return expr;
        } catch(const std::out_of_range & e) {
            /* Do nothing, just go to next step */
        }

        try {
            expr.type = _globalVars.at(funName);
            expr.value = funName;
            return expr;
        } catch(const std::out_of_range & e) {
            /* Do nothing, just go to next step */
        }

    x:

        mangleName(funName, params);

        try {
            expr.type = _functions.at(funName);
        } catch (const std::exception & e) {
            throw undeclared_function_call("Invalid call to function " + funName);
        }

        std::stringstream ss;

        ss << funName << "(";

        size_t size = params.size();
        for (size_t i = 0; i < size; ++i) {
            ss << params[i].value << ((i != size - 1) ? ", " : "");
        }
        ss << ")";
    }

    return expr;

}

void Translator::parseSexps(unsigned long long firstSexp) {

    unsigned long long parenCounter = 0;
    unsigned long long iter = firstSexp;
    std::vector<unsigned long long> sexps;
    token tok;

    do {

        tok = _tokens[iter];

        if (tok == tokType::openingPar) { ++parenCounter; }
        else if (tok == tokType::closingPar) { --parenCounter; }

        if (parenCounter == 1 and tok == tokType::openingPar) {
            sexps.emplace_back(iter); }

        ++iter;

    } while (parenCounter);

    for (unsigned long long i : sexps) {

        /* Appending a semicolon at the end - semicolons after if () {} don't do anything, but  */
        /*  the compiler would probably miss the semicolon after an assignment                  */
        /* In the end, there might be too many useless semicolons, but whatever                 */
        /* If you wanna help battle the semicolon inflation, don't comment your Kobeři-C code   */
        _output << parseSexp(i).value << ";" << std::endl;

    }

}

void Translator::parseFun(unsigned long long funBeginning, unsigned long long funEnd) {

    _localVars = std::unordered_map<std::string, std::string>();

#if PRINT_FUNCTIONS_TOKENS
    for (unsigned long long i = funcBeginning; i < funcEnd; ++i) {
        print(_tokens[i].value);
    }
#endif

    std::string type = _tokens[funBeginning + 1].value;
    checkType(type);

    std::string name = _tokens[funBeginning + 2].value;
    std::vector<parameter> params;

    parseParams(funBeginning + 3, params);

    for (parameter & p : params) {
        _localVars.emplace(p.value, p.type);
    }

    mangleName(name, params); /* The name of main won't be mangled */

    if (name == "main") {
        _output << "int main(int argc, const char * argv[]) {\n";
    }
    else {

        _output << ((type == "int") ? "ll" : type) << " " << name << "(";

        size_t size = params.size();
        for (size_t i = 0; i < size; ++i) {
            _output << (params[i].type == "int" ? "ll" : params[i].type) << " " << params[i].value << ((i != size - 1) ? ", " : "");
        }
        if (not size) { _output << "void"; }
        _output << ") {\n";

    }

    unsigned long long sexp = 0;

    /* funBeginning = (; funBeginning + 1 = data type; funBeginning + 2 = name; funBeginning + 3 = ( */
    /* Find location of first s-expression */
    for (sexp = funBeginning + 3; _tokens[sexp] != tokType::closingPar; ++sexp);

    parseSexps(sexp + 1);

    _output << "}\n\n";

}

void Translator::varDeclaration(unsigned long long declBeginning, unsigned long long declEnd) {

    std::stringstream ss;

    if (declEnd - declBeginning < 4) { /* 0 for (; 1 for (); 2 for (global); 3 for (global type); 4 for (global type name);
                                          At least 4 tokens are needed to declare a global variable */

        for (unsigned long long i = declBeginning; i < declEnd; ++i) {
            ss << (_tokens[i] != tokType::openingPar ? "" : " ") << _tokens[i].value;
        }

        throw invalid_declaration("Invalid variable declaration:" + ss.str());

    }

    std::string type = _tokens[declBeginning + 2].value;
    checkType(type);

    std::string name = _tokens[declBeginning + 3].value;

    ss << (type == "int" ? "ll" : type) << " " << name;

    if (_tokens[declBeginning + 4] != tokType::closingPar) {
        ss << " = " << _tokens[declBeginning + 4].value;
    }

    ss << ";";

#ifdef OUTPUT_GLOBAL_VARIABLE_DECLARATION
    print(ss.str());
#endif

    _output << ss.str() << std::endl;

    _globalVars.emplace(name, type);

}

void Translator::funDeclaration(unsigned long long declBeginning, unsigned long long declEnd) {

    std::string type = _tokens[declBeginning + 1].value;
    checkType(type);

    std::string name = _tokens[declBeginning + 2].value;
    if (name == "main" and type != "int") { throw invalid_declaration("Main must return int. "); }
    std::vector<parameter> params;

    parseParams(declBeginning + 3, params);
    mangleName(name, params);
    _functions.emplace(name, type);

    std::stringstream ss;
    if (name != "main") {
        ss << (type == "int" ? "ll" : type) << " " << name << "(";
    } else {
        _output << "int main(int argc, const char * argv[]);" << std::endl;
#ifdef OUTPUT_FUNCTION_DECLARATION
        print("int main(int argc, const char * argv[]);");
#endif
        return;
    }
    size_t size = params.size();

    for (size_t i = 0; i < size; ++i) {

        ss << (params[i].type == "int" ? "ll" : params[i].type) << " " << params[i].value << ((i != size - 1) ? ", " : "");

    }
    if (not size) { ss << "void"; }
    ss << ");";

    _output << ss.str() << std::endl;

#ifdef OUTPUT_FUNCTION_DECLARATION
    print(ss.str());
#endif

}

void Translator::parseDeclarations() {

    _output << "/* User defined function declarations and global variables. */\n\n";

    unsigned long long parens = 0;
    unsigned long long declBeginning = 0, declEnd = 0;

    for (unsigned long long i = 0; i < _tokens.size(); ++i) {

        if (_tokens[i].type == tokType::openingPar) {

            ++parens;
            if (parens == 1) { declBeginning = i; }

        }
        else if (_tokens[i].type == tokType::closingPar) {

            --parens;

        }

        if (not parens) {

            declEnd = i;
            declaration(declBeginning, declEnd);

        }

    } /* For */

    _output << "\n"; /* Output two newlines after function declarations, mostly for readability */

}

void Translator::declaration(unsigned long long declBeginning, unsigned long long declEnd) {

    if (_tokens[declBeginning + 1].value == "global") {

        varDeclaration(declBeginning, declEnd);

    } else {

        funDeclaration(declBeginning, declEnd);

    }

}

void Translator::libs() {

    _output << "#include <stdio.h>\n"
            << "#include <stdlib.h>\n"
            << "#include <math.h>\n"
            << "#include <time.h>\n"
            << "\n"
            << std::endl;

}

void Translator::typedefs() {

    _output << "typedef double num;\n"
            << "typedef long long ll;\n"
            << std::endl;

}

void Translator::functions() {

    _output << "/* Kobeři-c standard library functions */\n\n"
            << "char * __numToStr(num param) { \n"
            << "    char * temp = (char *) malloc(50);\n"
            << "    sprintf(temp, \"%f\", param);\n"
            << "    return temp;\n"
            << "}\n\n"
            << "char * __intToStr(ll param) {\n"
            << "    char * temp = (char *) malloc(50);\n"
            << "    sprintf(temp, \"%f\", param);\n"
            << "    return temp;\n"
            << "}\n\n" << std::flush;

}

void Translator::parseDefinitions() {

    _output << "/* User defined function definitions */\n" << std::endl;

    unsigned long long parens = 0;
    unsigned long long defBeginning = 0, defEnd = 0;

    for (int i = 0; i < _tokens.size(); ++i) {

        if (_tokens[i].type == tokType::openingPar) {

            ++parens;
            if (parens == 1) { defBeginning = i; }

        }
        else if (_tokens[i].type == tokType::closingPar) {

            --parens;

        }

        if (not parens) {
            defEnd = i;
            definition(defBeginning, defEnd);
        }

    } /* For */

}

void Translator::definition(unsigned long long defBeginning, unsigned long long defEnd) {

    if (_tokens[defBeginning + 1].value != "global") {
        parseFun(defBeginning, defEnd);
    }

}

void Translator::translate() {

    libs();
    typedefs();
    functions();

    parseDeclarations();
    parseDefinitions();

}
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

#include <TROOT.h>
#include <TSystem.h>
#include <TInterpreter.h>
#include <TChain.h>
#include <TFile.h>
#include <TList.h>

#include "AliAnalysisTaskSE.h"
#include "AliAnalysisManager.h"
#include "AliESDEvent.h"
#include "AliESD.h"
#include "AliAODEvent.h"
#include "AliAODHeader.h"
#include "AliAODTracklets.h"
#include "AliVEvent.h"
#include "AliAODHandler.h"
#include "AliAODInputHandler.h"
#include "AliMCEventHandler.h"
#include "AliInputEventHandler.h"
#include "AliMCEvent.h"
#include "AliStack.h"
#include "AliLog.h"

ClassImp(AliAnalysisTaskSE)

////////////////////////////////////////////////////////////////////////
AliAODHeader*    AliAnalysisTaskSE::fgAODHeader        = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODTracks        = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODVertices      = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODV0s           = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODPMDClusters   = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODJets          = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODFMDClusters   = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODCaloClusters  = NULL;
AliAODTracklets* AliAnalysisTaskSE::fgAODTracklets     = NULL;

AliAnalysisTaskSE::AliAnalysisTaskSE():
    AliAnalysisTask(),
    fDebug(0),
    fEntry(0),
    fInputEvent(0x0),
    fInputHandler(0x0),
    fOutputAOD(0x0),
    fMCEvent(0x0),
    fTreeA(0x0)
{
  // Default constructor
}

AliAnalysisTaskSE::AliAnalysisTaskSE(const char* name):
    AliAnalysisTask(name, "AnalysisTaskSE"),
    fDebug(0),
    fEntry(0),
    fInputEvent(0x0),
    fInputHandler(0x0),
    fOutputAOD(0x0),
    fMCEvent(0x0),
    fTreeA(0x0)
{
  // Default constructor
    DefineInput (0, TChain::Class());
    DefineOutput(0,  TTree::Class());
}

AliAnalysisTaskSE::AliAnalysisTaskSE(const AliAnalysisTaskSE& obj):
    AliAnalysisTask(obj),
    fDebug(0),
    fEntry(0),
    fInputEvent(0x0),
    fInputHandler(0x0),
    fOutputAOD(0x0),
    fMCEvent(0x0),
    fTreeA(0x0)
{
// Copy constructor
    fDebug        = obj.fDebug;
    fEntry        = obj.fEntry;
    fInputEvent   = obj.fInputEvent;
    fInputHandler = obj.fInputHandler;
    fOutputAOD    = obj.fOutputAOD;
    fMCEvent      = obj.fMCEvent;
    fTreeA        = obj.fTreeA;
    printf("Constructor (3) \n");
}

AliAnalysisTaskSE& AliAnalysisTaskSE::operator=(const AliAnalysisTaskSE& other)
{
// Assignment
    AliAnalysisTask::operator=(other);
    fDebug        = other.fDebug;
    fEntry        = other.fEntry;
    fInputEvent   = other.fInputEvent;
    fInputHandler = other.fInputHandler;
    fOutputAOD    = other.fOutputAOD;
    fMCEvent      = other.fMCEvent;
    fTreeA        = other.fTreeA;
    return *this;
}

void AliAnalysisTaskSE::ConnectInputData(Option_t* /*option*/)
{
// Connect the input data
    if (fDebug > 1) printf("AnalysisTaskSE::ConnectInputData() \n");
//
//  ESD
//
    fInputHandler = (AliInputEventHandler*)
         ((AliAnalysisManager::GetAnalysisManager())->GetInputEventHandler());
//
//  Monte Carlo
//
    AliMCEventHandler*    mcH = 0;
    mcH = (AliMCEventHandler*) ((AliAnalysisManager::GetAnalysisManager())->GetMCtruthEventHandler());
    if (mcH) fMCEvent = mcH->MCEvent();

    if (fInputHandler) {
         fInputEvent = fInputHandler->GetEvent();
    } else if( fMCEvent ) {
         AliWarning("No Input Event Handler connected, only MC Truth Event Handler") ;
    } else {
         AliError("No Input Event Handler connected") ;
         return ;
    }
}

void AliAnalysisTaskSE::CreateOutputObjects()
{
// Create the output container
//
//  Default AOD
    if (fDebug > 1) printf("AnalysisTaskSE::CreateOutPutData() \n");

    AliAODHandler* handler = (AliAODHandler*)
         ((AliAnalysisManager::GetAnalysisManager())->GetOutputEventHandler());

    // Check if AOD replication has been required

    if (handler) {
	fOutputAOD   = handler->GetAOD();
	fTreeA = handler->GetTree();
	if (!(handler->IsStandard())) {
	    if ((handler->NeedsHeaderReplication()) && !(fgAODHeader))
		{
		    if (fDebug > 1) AliInfo("Replicating header");
		    fgAODHeader = new AliAODHeader;
		    handler->AddBranch("AliAODHeader", &fgAODHeader);
		}
	    if ((handler->NeedsTracksBranchReplication()) && !(fgAODTracks))
	    {
		if (fDebug > 1) AliInfo("Replicating track branch\n");
		fgAODTracks = new TClonesArray("AliAODTrack",500);
		handler->AddBranch("TClonesArray", &fgAODTracks);
	    }
	    if ((handler->NeedsVerticesBranchReplication()) && !(fgAODVertices))
	    {
		if (fDebug > 1) AliInfo("Replicating vertices branch\n");
		fgAODVertices = new TClonesArray("AliAODVertex",500);
		handler->AddBranch("TClonesArray", &fgAODVertices);
	    }
	    if ((handler->NeedsV0sBranchReplication()) && !(fgAODV0s))
	    {
		if (fDebug > 1) AliInfo("Replicating V0s branch\n");
		fgAODV0s = new TClonesArray("AliAODv0",500);
		handler->AddBranch("TClonesArray", &fgAODV0s);
	    }
	    if ((handler->NeedsTrackletsBranchReplication()) && !(fgAODTracklets))
	    {
		if (fDebug > 1) AliInfo("Replicating Tracklets branch\n");
		fgAODTracklets = new AliAODTracklets("AliAODTracklets","AliAODTracklets");
		handler->AddBranch("AliAODTracklets", &fgAODTracklets);
	    }
	    if ((handler->NeedsPMDClustersBranchReplication()) && !(fgAODPMDClusters))
	    {
		if (fDebug > 1) AliInfo("Replicating PMDClusters branch\n");
		fgAODPMDClusters = new TClonesArray("AliAODPmdCluster",500);
		handler->AddBranch("TClonesArray", &fgAODPMDClusters);
	    }
	    if ((handler->NeedsJetsBranchReplication()) && !(fgAODJets))
	    {
		if (fDebug > 1) AliInfo("Replicating Jets branch\n");
		fgAODJets = new TClonesArray("AliAODJet",500);
		handler->AddBranch("TClonesArray", &fgAODJets);
	    }
	    if ((handler->NeedsFMDClustersBranchReplication()) && !(fgAODFMDClusters))
	    {
		AliInfo("Replicating FMDClusters branch\n");
		fgAODFMDClusters = new TClonesArray("AliAODFmdCluster",500);
		handler->AddBranch("TClonesArray", &fgAODFMDClusters);
	    }
	    if ((handler->NeedsCaloClustersBranchReplication()) && !(fgAODCaloClusters))
	    {
		if (fDebug > 1) AliInfo("Replicating CaloClusters branch\n");
		fgAODCaloClusters = new TClonesArray("AliAODCaloCluster",500);
		handler->AddBranch("TClonesArray", &fgAODCaloClusters);
	    }
	}
    } else {
	AliWarning("No AOD Event Handler connected.") ;
    }
    UserCreateOutputObjects();
}

void AliAnalysisTaskSE::Exec(Option_t* option)
{
//
// Exec analysis of one event
    if (fDebug > 1) AliInfo("AliAnalysisTaskSE::Exec() \n");
    if( fInputHandler )
       fEntry = fInputHandler->GetReadEntry();
    else if( fMCEvent )
       fEntry = fMCEvent->Header()->GetEvent();
    if ( !((Entry()-1)%100) && fDebug > 0)
         AliInfo(Form("%s ----> Processing event # %lld", CurrentFileName(), Entry()));

    AliAODHandler* handler = (AliAODHandler*)
	((AliAnalysisManager::GetAnalysisManager())->GetOutputEventHandler());
    AliAODInputHandler* aodH = dynamic_cast<AliAODInputHandler*>(fInputHandler);

    if (handler && aodH) {
	if (!(handler->IsStandard()) && !(handler->AODIsReplicated())) {
	    if ((handler->NeedsHeaderReplication()) && (fgAODHeader))
	    {
		fgAODHeader = dynamic_cast<AliAODHeader*>(InputEvent()->GetHeader());
	    }
	    if ((handler->NeedsTracksBranchReplication()) && (fgAODTracks))
	    {
		TClonesArray* tracks = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetTracks();
		new (fgAODTracks) TClonesArray(*tracks);
	    }
	    if ((handler->NeedsVerticesBranchReplication()) && (fgAODVertices))
	    {
		TClonesArray* vertices = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetVertices();
		new (fgAODVertices) TClonesArray(*vertices);
	    }
	    if ((handler->NeedsV0sBranchReplication()) && (fgAODV0s))
	    {
		TClonesArray* V0s = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetV0s();
		new (fgAODV0s) TClonesArray(*V0s);
	    }
	    if ((handler->NeedsTrackletsBranchReplication()) && (fgAODTracklets))
	    {
		    fgAODTracklets = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetTracklets();
	    }
	    if ((handler->NeedsPMDClustersBranchReplication()) && (fgAODPMDClusters))
	    {
		TClonesArray* PMDClusters = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetPmdClusters();
		new (fgAODPMDClusters) TClonesArray(*PMDClusters);
	    }
	    if ((handler->NeedsJetsBranchReplication()) && (fgAODJets))
	    {
		TClonesArray* Jets = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetJets();
		new (fgAODJets) TClonesArray(*Jets);
	    }
	    if ((handler->NeedsFMDClustersBranchReplication()) && (fgAODFMDClusters))
	    {
		TClonesArray* FMDClusters = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetFmdClusters();
		new (fgAODFMDClusters) TClonesArray(*FMDClusters);
	    }
	    if ((handler->NeedsCaloClustersBranchReplication()) && (fgAODCaloClusters))
	    {
		TClonesArray* CaloClusters = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetCaloClusters();
		new (fgAODCaloClusters) TClonesArray(*CaloClusters);
	    }
	    //
	    handler->SetAODIsReplicated();

	}
    }

// Call the user analysis
    UserExec(option);
    PostData(0, fTreeA);

}

const char* AliAnalysisTaskSE::CurrentFileName()
{
// Returns the current file name
    if( fInputHandler )
      return fInputHandler->GetTree()->GetCurrentFile()->GetName();
    else if( fMCEvent )
      return ((AliMCEventHandler*) ((AliAnalysisManager::GetAnalysisManager())->GetMCtruthEventHandler()))->TreeK()->GetCurrentFile()->GetName();
    else return "";
}

void AliAnalysisTaskSE::AddAODBranch(const char* cname, void* addobj)
{
    // Add a new branch to the aod tree
    AliAODHandler* handler = (AliAODHandler*)
	((AliAnalysisManager::GetAnalysisManager())->GetOutputEventHandler());
    if (handler) {
	handler->AddBranch(cname, addobj);
    }
}
<commit_msg>Correct names for replicated branches. (R. Arnaldi)<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

#include <TROOT.h>
#include <TSystem.h>
#include <TInterpreter.h>
#include <TChain.h>
#include <TFile.h>
#include <TList.h>

#include "AliAnalysisTaskSE.h"
#include "AliAnalysisManager.h"
#include "AliESDEvent.h"
#include "AliESD.h"
#include "AliAODEvent.h"
#include "AliAODHeader.h"
#include "AliAODTracklets.h"
#include "AliVEvent.h"
#include "AliAODHandler.h"
#include "AliAODInputHandler.h"
#include "AliMCEventHandler.h"
#include "AliInputEventHandler.h"
#include "AliMCEvent.h"
#include "AliStack.h"
#include "AliLog.h"

ClassImp(AliAnalysisTaskSE)

////////////////////////////////////////////////////////////////////////
AliAODHeader*    AliAnalysisTaskSE::fgAODHeader        = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODTracks        = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODVertices      = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODV0s           = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODPMDClusters   = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODJets          = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODFMDClusters   = NULL;
TClonesArray*    AliAnalysisTaskSE::fgAODCaloClusters  = NULL;
AliAODTracklets* AliAnalysisTaskSE::fgAODTracklets     = NULL;

AliAnalysisTaskSE::AliAnalysisTaskSE():
    AliAnalysisTask(),
    fDebug(0),
    fEntry(0),
    fInputEvent(0x0),
    fInputHandler(0x0),
    fOutputAOD(0x0),
    fMCEvent(0x0),
    fTreeA(0x0)
{
  // Default constructor
}

AliAnalysisTaskSE::AliAnalysisTaskSE(const char* name):
    AliAnalysisTask(name, "AnalysisTaskSE"),
    fDebug(0),
    fEntry(0),
    fInputEvent(0x0),
    fInputHandler(0x0),
    fOutputAOD(0x0),
    fMCEvent(0x0),
    fTreeA(0x0)
{
  // Default constructor
    DefineInput (0, TChain::Class());
    DefineOutput(0,  TTree::Class());
}

AliAnalysisTaskSE::AliAnalysisTaskSE(const AliAnalysisTaskSE& obj):
    AliAnalysisTask(obj),
    fDebug(0),
    fEntry(0),
    fInputEvent(0x0),
    fInputHandler(0x0),
    fOutputAOD(0x0),
    fMCEvent(0x0),
    fTreeA(0x0)
{
// Copy constructor
    fDebug        = obj.fDebug;
    fEntry        = obj.fEntry;
    fInputEvent   = obj.fInputEvent;
    fInputHandler = obj.fInputHandler;
    fOutputAOD    = obj.fOutputAOD;
    fMCEvent      = obj.fMCEvent;
    fTreeA        = obj.fTreeA;
    printf("Constructor (3) \n");
}

AliAnalysisTaskSE& AliAnalysisTaskSE::operator=(const AliAnalysisTaskSE& other)
{
// Assignment
    AliAnalysisTask::operator=(other);
    fDebug        = other.fDebug;
    fEntry        = other.fEntry;
    fInputEvent   = other.fInputEvent;
    fInputHandler = other.fInputHandler;
    fOutputAOD    = other.fOutputAOD;
    fMCEvent      = other.fMCEvent;
    fTreeA        = other.fTreeA;
    return *this;
}

void AliAnalysisTaskSE::ConnectInputData(Option_t* /*option*/)
{
// Connect the input data
    if (fDebug > 1) printf("AnalysisTaskSE::ConnectInputData() \n");
//
//  ESD
//
    fInputHandler = (AliInputEventHandler*)
         ((AliAnalysisManager::GetAnalysisManager())->GetInputEventHandler());
//
//  Monte Carlo
//
    AliMCEventHandler*    mcH = 0;
    mcH = (AliMCEventHandler*) ((AliAnalysisManager::GetAnalysisManager())->GetMCtruthEventHandler());
    if (mcH) fMCEvent = mcH->MCEvent();

    if (fInputHandler) {
         fInputEvent = fInputHandler->GetEvent();
    } else if( fMCEvent ) {
         AliWarning("No Input Event Handler connected, only MC Truth Event Handler") ;
    } else {
         AliError("No Input Event Handler connected") ;
         return ;
    }
}

void AliAnalysisTaskSE::CreateOutputObjects()
{
// Create the output container
//
//  Default AOD
    if (fDebug > 1) printf("AnalysisTaskSE::CreateOutPutData() \n");

    AliAODHandler* handler = (AliAODHandler*)
         ((AliAnalysisManager::GetAnalysisManager())->GetOutputEventHandler());

    // Check if AOD replication has been required

    if (handler) {
	fOutputAOD   = handler->GetAOD();
	fTreeA = handler->GetTree();
	if (!(handler->IsStandard())) {
	    if ((handler->NeedsHeaderReplication()) && !(fgAODHeader))
		{
		 if (fDebug > 1) AliInfo("Replicating header");
		 fgAODHeader = new AliAODHeader;
		 handler->AddBranch("AliAODHeader", &fgAODHeader);
		}
	    if ((handler->NeedsTracksBranchReplication()) && !(fgAODTracks))
	    {
		if (fDebug > 1) AliInfo("Replicating track branch\n");
		fgAODTracks = new TClonesArray("AliAODTrack",500);
		fgAODTracks->SetName("tracks");
		handler->AddBranch("TClonesArray", &fgAODTracks);
	    }
	    if ((handler->NeedsVerticesBranchReplication()) && !(fgAODVertices))
	    {
		if (fDebug > 1) AliInfo("Replicating vertices branch\n");
		fgAODVertices = new TClonesArray("AliAODVertex",500);
		fgAODVertices->SetName("vertices");
		handler->AddBranch("TClonesArray", &fgAODVertices);
	    }
	    if ((handler->NeedsV0sBranchReplication()) && !(fgAODV0s))
	    {
		if (fDebug > 1) AliInfo("Replicating V0s branch\n");
		fgAODV0s = new TClonesArray("AliAODv0",500);
		fgAODV0s->SetName("v0s");
		handler->AddBranch("TClonesArray", &fgAODV0s);
	    }
	    if ((handler->NeedsTrackletsBranchReplication()) && !(fgAODTracklets))
	    {
		if (fDebug > 1) AliInfo("Replicating Tracklets branch\n");
		fgAODTracklets = new AliAODTracklets("tracklets","tracklets");
		handler->AddBranch("AliAODTracklets", &fgAODTracklets);
	    }
	    if ((handler->NeedsPMDClustersBranchReplication()) && !(fgAODPMDClusters))
	    {
		if (fDebug > 1) AliInfo("Replicating PMDClusters branch\n");
		fgAODPMDClusters = new TClonesArray("AliAODPmdCluster",500);
		fgAODPMDClusters->SetName("pmdClusters");
		handler->AddBranch("TClonesArray", &fgAODPMDClusters);
	    }
	    if ((handler->NeedsJetsBranchReplication()) && !(fgAODJets))
	    {
		if (fDebug > 1) AliInfo("Replicating Jets branch\n");
		fgAODJets = new TClonesArray("AliAODJet",500);
		fgAODJets->SetName("jets");
		handler->AddBranch("TClonesArray", &fgAODJets);
	    }
	    if ((handler->NeedsFMDClustersBranchReplication()) && !(fgAODFMDClusters))
	    {
		AliInfo("Replicating FMDClusters branch\n");
		fgAODFMDClusters = new TClonesArray("AliAODFmdCluster",500);
		fgAODFMDClusters->SetName("fmdClusters");
		handler->AddBranch("TClonesArray", &fgAODFMDClusters);
	    }
	    if ((handler->NeedsCaloClustersBranchReplication()) && !(fgAODCaloClusters))
	    {
		if (fDebug > 1) AliInfo("Replicating CaloClusters branch\n");
		fgAODCaloClusters = new TClonesArray("AliAODCaloCluster",500);
		fgAODCaloClusters->SetName("caloClusters");
		handler->AddBranch("TClonesArray", &fgAODCaloClusters);
	    }
	}
    } else {
	AliWarning("No AOD Event Handler connected.") ;
    }
    UserCreateOutputObjects();
}

void AliAnalysisTaskSE::Exec(Option_t* option)
{
//
// Exec analysis of one event
    if (fDebug > 1) AliInfo("AliAnalysisTaskSE::Exec() \n");
    if( fInputHandler )
       fEntry = fInputHandler->GetReadEntry();
    else if( fMCEvent )
       fEntry = fMCEvent->Header()->GetEvent();
    if ( !((Entry()-1)%100) && fDebug > 0)
         AliInfo(Form("%s ----> Processing event # %lld", CurrentFileName(), Entry()));

    AliAODHandler* handler = (AliAODHandler*)
	((AliAnalysisManager::GetAnalysisManager())->GetOutputEventHandler());
    AliAODInputHandler* aodH = dynamic_cast<AliAODInputHandler*>(fInputHandler);

    if (handler && aodH) {
	if (!(handler->IsStandard()) && !(handler->AODIsReplicated())) {
	    if ((handler->NeedsHeaderReplication()) && (fgAODHeader))
	    {
		fgAODHeader = dynamic_cast<AliAODHeader*>(InputEvent()->GetHeader());
	    }
	    if ((handler->NeedsTracksBranchReplication()) && (fgAODTracks))
	    {
		TClonesArray* tracks = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetTracks();
		new (fgAODTracks) TClonesArray(*tracks);
	    }
	    if ((handler->NeedsVerticesBranchReplication()) && (fgAODVertices))
	    {
		TClonesArray* vertices = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetVertices();
		new (fgAODVertices) TClonesArray(*vertices);
	    }
	    if ((handler->NeedsV0sBranchReplication()) && (fgAODV0s))
	    {
		TClonesArray* V0s = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetV0s();
		new (fgAODV0s) TClonesArray(*V0s);
	    }
	    if ((handler->NeedsTrackletsBranchReplication()) && (fgAODTracklets))
	    {
		    fgAODTracklets = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetTracklets();
	    }
	    if ((handler->NeedsPMDClustersBranchReplication()) && (fgAODPMDClusters))
	    {
		TClonesArray* PMDClusters = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetPmdClusters();
		new (fgAODPMDClusters) TClonesArray(*PMDClusters);
	    }
	    if ((handler->NeedsJetsBranchReplication()) && (fgAODJets))
	    {
		TClonesArray* Jets = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetJets();
		new (fgAODJets) TClonesArray(*Jets);
	    }
	    if ((handler->NeedsFMDClustersBranchReplication()) && (fgAODFMDClusters))
	    {
		TClonesArray* FMDClusters = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetFmdClusters();
		new (fgAODFMDClusters) TClonesArray(*FMDClusters);
	    }
	    if ((handler->NeedsCaloClustersBranchReplication()) && (fgAODCaloClusters))
	    {
		TClonesArray* CaloClusters = (dynamic_cast<AliAODEvent*>(InputEvent()))->GetCaloClusters();
		new (fgAODCaloClusters) TClonesArray(*CaloClusters);
	    }
	    //
	    handler->SetAODIsReplicated();

	}
    }

// Call the user analysis
    UserExec(option);
    PostData(0, fTreeA);

}

const char* AliAnalysisTaskSE::CurrentFileName()
{
// Returns the current file name
    if( fInputHandler )
      return fInputHandler->GetTree()->GetCurrentFile()->GetName();
    else if( fMCEvent )
      return ((AliMCEventHandler*) ((AliAnalysisManager::GetAnalysisManager())->GetMCtruthEventHandler()))->TreeK()->GetCurrentFile()->GetName();
    else return "";
}

void AliAnalysisTaskSE::AddAODBranch(const char* cname, void* addobj)
{
    // Add a new branch to the aod tree
    AliAODHandler* handler = (AliAODHandler*)
	((AliAnalysisManager::GetAnalysisManager())->GetOutputEventHandler());
    if (handler) {
	handler->AddBranch(cname, addobj);
    }
}
<|endoftext|>