<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: documentdefinition.hxx,v $
 *
 *  $Revision: 1.26 $
 *
 *  last change: $Author: rt $ $Date: 2008-01-30 08:34:51 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _DBA_COREDATAACCESS_DOCUMENTDEFINITION_HXX_
#define _DBA_COREDATAACCESS_DOCUMENTDEFINITION_HXX_

#ifndef _CPPUHELPER_PROPSHLP_HXX
#include <cppuhelper/propshlp.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef DBA_CONTENTHELPER_HXX
#include "ContentHelper.hxx"
#endif
#ifndef COMPHELPER_PROPERTYSTATECONTAINER_HXX
#include <comphelper/propertystatecontainer.hxx>
#endif
#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
#ifndef _DBASHARED_APITOOLS_HXX_
#include "apitools.hxx"
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_
#include <com/sun/star/sdbc/XConnection.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XCOMPONENTLOADER_HPP_
#include <com/sun/star/frame/XComponentLoader.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
#include <com/sun/star/frame/XController.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XSTATECHANGELISTENER_HPP_
#include <com/sun/star/embed/XStateChangeListener.hpp>
#endif

//........................................................................
namespace dbaccess
{
//........................................................................

    class OInterceptor;
    class OEmbeddedClientHelper;
//==========================================================================
//= ODocumentDefinition - a database "document" which is simply a link to a real
//=                   document
//==========================================================================

    typedef ::cppu::ImplHelper1<        ::com::sun::star::embed::XComponentSupplier
                                >   ODocumentDefinition_Base;

class ODocumentDefinition
        :public OContentHelper
        ,public ::comphelper::OPropertyStateContainer
        ,public ::comphelper::OPropertyArrayUsageHelper< ODocumentDefinition >
        ,public ODocumentDefinition_Base
{
    ::com::sun::star::uno::Reference< ::com::sun::star::embed::XEmbeddedObject>         m_xEmbeddedObject;
    ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStateChangeListener >   m_xListener;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFramesSupplier >        m_xDesktop;
    ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >             m_xLastKnownConnection;

    OInterceptor*                                                                       m_pInterceptor;
    sal_Bool                                                                            m_bForm; // <TRUE/> if it is a form
    sal_Bool                                                                            m_bOpenInDesign;
    sal_Bool                                                                            m_bInExecute;
    OEmbeddedClientHelper*                                                              m_pClientHelper;

protected:
    virtual ~ODocumentDefinition();

public:

    ODocumentDefinition(
             const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxContainer
            ,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&
            ,const TContentPtr& _pImpl
            ,sal_Bool _bForm
            ,const ::com::sun::star::uno::Sequence< sal_Int8 >& _aClassID = ::com::sun::star::uno::Sequence< sal_Int8 >()
            ,const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection = ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>()
        );

// com::sun::star::lang::XTypeProvider
    DECLARE_TYPEPROVIDER( );

// ::com::sun::star::uno::XInterface
    DECLARE_XINTERFACE( )

// ::com::sun::star::lang::XServiceInfo
    DECLARE_SERVICE_INFO_STATIC();

// ::com::sun::star::beans::XPropertySet
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(  ) throw(::com::sun::star::uno::RuntimeException);

    // XComponentSupplier
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseable > SAL_CALL getComponent(  ) throw (::com::sun::star::uno::RuntimeException);

// OPropertySetHelper
    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();

    // XCommandProcessor
    virtual ::com::sun::star::uno::Any SAL_CALL execute( const ::com::sun::star::ucb::Command& aCommand, sal_Int32 CommandId, const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& Environment ) throw (::com::sun::star::uno::Exception, ::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::RuntimeException) ;

    // XRename
    virtual void SAL_CALL rename( const ::rtl::OUString& newName ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage> getStorage() const;

    sal_Bool save(sal_Bool _bApprove);
    sal_Bool saveAs();
    void closeObject();
    sal_Bool isModified();
    void fillReportData();
    inline sal_Bool isNewReport() const { return !m_bForm && !m_pImpl->m_aProps.bAsTemplate; }

    /** prepares closing the document component

        The method suspends the controller associated with the document, and saves the document
        if necessary.

        @return
            <TRUE/> if and only if the document component can be closed
    */
    bool prepareClose();

    static ::com::sun::star::uno::Sequence< sal_Int8 > getDefaultDocumentTypeClassId();

    /** does necessary initializations after our embedded object has been switched to ACTIVE
        @param _bOpenedInDesignMode
            determines whether the embedded object has been opened for designing it or for data display
    */
    void impl_onActivateEmbeddedObject();

    /** initializes a newly created view/controller which is displaying our embedded object

        Has only to be called if the respective embedded object has been loaded for design (and
        not for data entry)

        @param  _rxController
            the controller which belongs to the XModel of our (active) embedded object
    */
    void impl_initObjectEditView( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& _rxController );

    /** removes the given frame from the desktop's frame collection
        @raises ::com::sun::star::uno::RuntimeException
    */
    void impl_removeFrameFromDesktop_throw( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& _rxFrame );

    static ::rtl::OUString GetDocumentServiceFromMediaType( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage
                                                    ,const ::rtl::OUString& sEntName
                                                    ,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB
                                                    ,::com::sun::star::uno::Sequence< sal_Int8 >& _rClassId
                                                    );

protected:
    // OPropertyArrayUsageHelper
    virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const;

    virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _rDefault ) const;
    // helper
    virtual void SAL_CALL disposing();

private:
    /** fills the load arguments
    */
    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >
        fillLoadArgs(
            const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection,
            const bool _bSuppressMacros,
            const bool _bReadOnly,
            const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rAdditionalArgs,
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _out_rEmbeddedObjectDescriptor
        );

    /** loads the EmbeddedObject if not already loaded
        @param  _aClassID
            If set, it will be used to create the embedded object.
    */
    void loadEmbeddedObject(
                const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection,
                const ::com::sun::star::uno::Sequence< sal_Int8 >& _aClassID,
                const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rAdditionalArgs,
                const bool _bSuppressMacros,
                const bool _bReadOnly
            );

    /** loads the embedded object, if not already loaded. No new object can be created with this method.
    */
    void    loadEmbeddedObject()
    {
        loadEmbeddedObject(
            NULL,
            ::com::sun::star::uno::Sequence< sal_Int8 >(),
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >(),
            false,
            false
        );
    }

    /** loads the embedded object for preview. Macros will be suppressed, and the document will
        be read-only.
    */
    void    loadEmbeddedObjectForPreview()
    {
        loadEmbeddedObject(
            NULL,
            ::com::sun::star::uno::Sequence< sal_Int8 >(),
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >(),
            true,
            true
        );
    }

    /** searches for read-only flag in the args of the model and sets it to the given value,
        if the value was not found, it will be appended.
        @param  _bReadOnly
            If <TRUE/> the document will be switched to readonly mode
    */
    void updateDocumentTitle();

    void registerProperties();

    //-------------------------------------------------------------------------
    //- commands
    //-------------------------------------------------------------------------

    void onCommandGetDocumentInfo( ::com::sun::star::uno::Any& _rInfo );
    void onCommandInsert( const ::rtl::OUString& _sURL, const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& Environment ) throw( ::com::sun::star::uno::Exception );
    void onCommandPreview( ::com::sun::star::uno::Any& _rImage );
    void onCommandOpenSomething( const ::com::sun::star::uno::Any& _rArgument, const bool _bActivate,
            const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& _rxEnvironment, ::com::sun::star::uno::Any& _out_rComponent );
};

//........................................................................
}   // namespace dbaccess
//........................................................................

#endif // _DBA_COREDATAACCESS_DOCUMENTDEFINITION_HXX_

<commit_msg>INTEGRATION: CWS custommeta (1.24.26); FILE MERGED 2008/02/01 10:33:44 mst 1.24.26.2: RESYNC: (1.24-1.26); FILE MERGED 2008/01/29 13:14:59 mst 1.24.26.1: - dbaccess/source/ui/app/AppDetailPageHelper.cxx:   + adapt to ODocumentInfoPreview interface change   + use XDocumentProperties instead of XDocumentInfo   + incidentally, fixes bug: document information was not displayed at all - dbaccess/source/core/dataaccess/documentdefinition.{hxx,cxx}:   + renamed ODocumentDefinition::onCommandGetDocumentInfo to     onCommandGetDocumentProperties<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: documentdefinition.hxx,v $
 *
 *  $Revision: 1.27 $
 *
 *  last change: $Author: obo $ $Date: 2008-02-26 14:38:02 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _DBA_COREDATAACCESS_DOCUMENTDEFINITION_HXX_
#define _DBA_COREDATAACCESS_DOCUMENTDEFINITION_HXX_

#ifndef _CPPUHELPER_PROPSHLP_HXX
#include <cppuhelper/propshlp.hxx>
#endif
#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef DBA_CONTENTHELPER_HXX
#include "ContentHelper.hxx"
#endif
#ifndef COMPHELPER_PROPERTYSTATECONTAINER_HXX
#include <comphelper/propertystatecontainer.hxx>
#endif
#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
#ifndef _DBASHARED_APITOOLS_HXX_
#include "apitools.hxx"
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_
#include <com/sun/star/sdbc/XConnection.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XCOMPONENTLOADER_HPP_
#include <com/sun/star/frame/XComponentLoader.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
#include <com/sun/star/frame/XController.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XSTATECHANGELISTENER_HPP_
#include <com/sun/star/embed/XStateChangeListener.hpp>
#endif

//........................................................................
namespace dbaccess
{
//........................................................................

    class OInterceptor;
    class OEmbeddedClientHelper;
//==========================================================================
//= ODocumentDefinition - a database "document" which is simply a link to a real
//=                   document
//==========================================================================

    typedef ::cppu::ImplHelper1<        ::com::sun::star::embed::XComponentSupplier
                                >   ODocumentDefinition_Base;

class ODocumentDefinition
        :public OContentHelper
        ,public ::comphelper::OPropertyStateContainer
        ,public ::comphelper::OPropertyArrayUsageHelper< ODocumentDefinition >
        ,public ODocumentDefinition_Base
{
    ::com::sun::star::uno::Reference< ::com::sun::star::embed::XEmbeddedObject>         m_xEmbeddedObject;
    ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStateChangeListener >   m_xListener;
    ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFramesSupplier >        m_xDesktop;
    ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >             m_xLastKnownConnection;

    OInterceptor*                                                                       m_pInterceptor;
    sal_Bool                                                                            m_bForm; // <TRUE/> if it is a form
    sal_Bool                                                                            m_bOpenInDesign;
    sal_Bool                                                                            m_bInExecute;
    OEmbeddedClientHelper*                                                              m_pClientHelper;

protected:
    virtual ~ODocumentDefinition();

public:

    ODocumentDefinition(
             const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _rxContainer
            ,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >&
            ,const TContentPtr& _pImpl
            ,sal_Bool _bForm
            ,const ::com::sun::star::uno::Sequence< sal_Int8 >& _aClassID = ::com::sun::star::uno::Sequence< sal_Int8 >()
            ,const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection = ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>()
        );

// com::sun::star::lang::XTypeProvider
    DECLARE_TYPEPROVIDER( );

// ::com::sun::star::uno::XInterface
    DECLARE_XINTERFACE( )

// ::com::sun::star::lang::XServiceInfo
    DECLARE_SERVICE_INFO_STATIC();

// ::com::sun::star::beans::XPropertySet
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(  ) throw(::com::sun::star::uno::RuntimeException);

    // XComponentSupplier
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloseable > SAL_CALL getComponent(  ) throw (::com::sun::star::uno::RuntimeException);

// OPropertySetHelper
    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();

    // XCommandProcessor
    virtual ::com::sun::star::uno::Any SAL_CALL execute( const ::com::sun::star::ucb::Command& aCommand, sal_Int32 CommandId, const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& Environment ) throw (::com::sun::star::uno::Exception, ::com::sun::star::ucb::CommandAbortedException, ::com::sun::star::uno::RuntimeException) ;

    // XRename
    virtual void SAL_CALL rename( const ::rtl::OUString& newName ) throw (::com::sun::star::sdbc::SQLException, ::com::sun::star::container::ElementExistException, ::com::sun::star::uno::RuntimeException);

    virtual ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage> getStorage() const;

    sal_Bool save(sal_Bool _bApprove);
    sal_Bool saveAs();
    void closeObject();
    sal_Bool isModified();
    void fillReportData();
    inline sal_Bool isNewReport() const { return !m_bForm && !m_pImpl->m_aProps.bAsTemplate; }

    /** prepares closing the document component

        The method suspends the controller associated with the document, and saves the document
        if necessary.

        @return
            <TRUE/> if and only if the document component can be closed
    */
    bool prepareClose();

    static ::com::sun::star::uno::Sequence< sal_Int8 > getDefaultDocumentTypeClassId();

    /** does necessary initializations after our embedded object has been switched to ACTIVE
        @param _bOpenedInDesignMode
            determines whether the embedded object has been opened for designing it or for data display
    */
    void impl_onActivateEmbeddedObject();

    /** initializes a newly created view/controller which is displaying our embedded object

        Has only to be called if the respective embedded object has been loaded for design (and
        not for data entry)

        @param  _rxController
            the controller which belongs to the XModel of our (active) embedded object
    */
    void impl_initObjectEditView( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XController >& _rxController );

    /** removes the given frame from the desktop's frame collection
        @raises ::com::sun::star::uno::RuntimeException
    */
    void impl_removeFrameFromDesktop_throw( const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& _rxFrame );

    static ::rtl::OUString GetDocumentServiceFromMediaType( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage
                                                    ,const ::rtl::OUString& sEntName
                                                    ,const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _xORB
                                                    ,::com::sun::star::uno::Sequence< sal_Int8 >& _rClassId
                                                    );

protected:
    // OPropertyArrayUsageHelper
    virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const;

    virtual void getPropertyDefaultByHandle( sal_Int32 _nHandle, ::com::sun::star::uno::Any& _rDefault ) const;
    // helper
    virtual void SAL_CALL disposing();

private:
    /** fills the load arguments
    */
    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >
        fillLoadArgs(
            const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection,
            const bool _bSuppressMacros,
            const bool _bReadOnly,
            const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rAdditionalArgs,
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _out_rEmbeddedObjectDescriptor
        );

    /** loads the EmbeddedObject if not already loaded
        @param  _aClassID
            If set, it will be used to create the embedded object.
    */
    void loadEmbeddedObject(
                const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection>& _xConnection,
                const ::com::sun::star::uno::Sequence< sal_Int8 >& _aClassID,
                const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& _rAdditionalArgs,
                const bool _bSuppressMacros,
                const bool _bReadOnly
            );

    /** loads the embedded object, if not already loaded. No new object can be created with this method.
    */
    void    loadEmbeddedObject()
    {
        loadEmbeddedObject(
            NULL,
            ::com::sun::star::uno::Sequence< sal_Int8 >(),
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >(),
            false,
            false
        );
    }

    /** loads the embedded object for preview. Macros will be suppressed, and the document will
        be read-only.
    */
    void    loadEmbeddedObjectForPreview()
    {
        loadEmbeddedObject(
            NULL,
            ::com::sun::star::uno::Sequence< sal_Int8 >(),
            ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >(),
            true,
            true
        );
    }

    /** searches for read-only flag in the args of the model and sets it to the given value,
        if the value was not found, it will be appended.
        @param  _bReadOnly
            If <TRUE/> the document will be switched to readonly mode
    */
    void updateDocumentTitle();

    void registerProperties();

    //-------------------------------------------------------------------------
    //- commands
    //-------------------------------------------------------------------------

    void onCommandGetDocumentProperties( ::com::sun::star::uno::Any& _rProps );
    void onCommandInsert( const ::rtl::OUString& _sURL, const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& Environment ) throw( ::com::sun::star::uno::Exception );
    void onCommandPreview( ::com::sun::star::uno::Any& _rImage );
    void onCommandOpenSomething( const ::com::sun::star::uno::Any& _rArgument, const bool _bActivate,
            const ::com::sun::star::uno::Reference< ::com::sun::star::ucb::XCommandEnvironment >& _rxEnvironment, ::com::sun::star::uno::Any& _out_rComponent );
};

//........................................................................
}   // namespace dbaccess
//........................................................................

#endif // _DBA_COREDATAACCESS_DOCUMENTDEFINITION_HXX_

<|endoftext|>


<commit_before>/*!
 *  Copyright (c) 2017 by Contributors
 * \file opencl_module.cc
 */
#include <dmlc/memory_io.h>
#include <tvm/runtime/registry.h>
#include <vector>
#include <string>
#include <unordered_map>
#include "./opencl_common.h"
#include "./opencl_module.h"

namespace tvm {
namespace runtime {

class OpenCLWrappedFunc {
 public:
  // initialize the OpenCL function.
  void Init(OpenCLModuleNode* m,
            std::shared_ptr<ModuleNode> sptr,
            OpenCLModuleNode::KTRefEntry entry,
            std::string func_name,
            std::vector<size_t> arg_size,
            const std::vector<std::string>& thread_axis_tags)  {
    w_ = m->GetGlobalWorkspace().get();
    m_ = m;
    sptr_ = sptr;
    entry_ = entry;
    func_name_ = func_name;
    arg_size_ = arg_size;
    thread_axis_cfg_.Init(arg_size.size(), thread_axis_tags);
  }
  // invoke the function with void arguments
  void operator()(TVMArgs args,
                  TVMRetValue* rv,
                  void** void_args) const {
    cl::OpenCLThreadEntry* t = w_->GetThreadEntry();
    // get the kernel from thread local kernel table.
    if (entry_.kernel_id >= t->kernel_table.size()) {
      t->kernel_table.resize(entry_.kernel_id + 1);
    }
    const auto& e = t->kernel_table[entry_.kernel_id];
    cl_kernel kernel = e.kernel;
    if (kernel == nullptr || e.version != entry_.version) {
      kernel = m_->InstallKernel(w_, t, func_name_, entry_);
    }
    // setup arguments.
    for (cl_uint i = 0; i < arg_size_.size(); ++i) {
      OPENCL_CALL(clSetKernelArg(kernel, i, arg_size_[i], void_args[i]));
    }
    cl_command_queue queue = w_->GetQueue(t->context);
    ThreadWorkLoad wl = thread_axis_cfg_.Extract(args);
    cl_uint work_dim = static_cast<cl_uint>(thread_axis_cfg_.work_dim());
    for (cl_uint i = 0; i < work_dim; ++i) {
      wl.work_size[i] *= wl.work_size[i + 3];
    }
    // launch kernel
    OPENCL_CALL(clEnqueueNDRangeKernel(
        queue, kernel, work_dim, nullptr,
        wl.work_size,
        wl.work_size + 3,
        0, nullptr, nullptr));
  }

 private:
  // global workspace.
  cl::OpenCLWorkspace* w_;
  // The module
  OpenCLModuleNode* m_;
  // resource handle
  std::shared_ptr<ModuleNode> sptr_;
  // global kernel id in the kernel table.
  OpenCLModuleNode::KTRefEntry entry_;
  // The name of the function.
  std::string func_name_;
  // convert code for void argument
  std::vector<size_t> arg_size_;
  // thread axis config
  ThreadAxisConfig thread_axis_cfg_;
};

OpenCLModuleNode::~OpenCLModuleNode() {
  {
    // free the kernel ids in global table.
    std::lock_guard<std::mutex> lock(workspace_->mu);
    for (auto& kv : kid_map_) {
      workspace_->free_kernel_ids.push_back(kv.second.kernel_id);
    }
  }
  // free the kernels
  for (cl_kernel k : kernels_) {
    OPENCL_CALL(clReleaseKernel(k));
  }
  if (program_) {
    OPENCL_CALL(clReleaseProgram(program_));
  }
}

const std::shared_ptr<cl::OpenCLWorkspace>& OpenCLModuleNode::GetGlobalWorkspace() {
  return cl::OpenCLWorkspace::Global();
}

const char* OpenCLModuleNode::type_key() const {
  return "opencl";
}

PackedFunc OpenCLModuleNode::GetFunction(
    const std::string& name,
    const std::shared_ptr<ModuleNode>& sptr_to_self) {
  CHECK_EQ(sptr_to_self.get(), this);
  CHECK_NE(name, symbol::tvm_module_main)
      << "Device function do not have main";
  auto it = fmap_.find(name);
  if (it == fmap_.end()) return PackedFunc();
  const FunctionInfo& info = it->second;
  OpenCLWrappedFunc f;
  std::vector<size_t> arg_size(info.arg_types.size());
  for (size_t i = 0; i < info.arg_types.size(); ++i) {
    TVMType t = info.arg_types[i];
    CHECK_EQ(t.lanes, 1U);
    if (t.code == kHandle) {
      // specially store pointer type size in OpenCL driver
      arg_size[i] = sizeof(void*);
    } else {
      uint32_t bits = t.bits;
      CHECK_EQ(bits % 8, 0U);
      arg_size[i] = bits / 8;
    }
  }
  // initialize the wrapped func.
  f.Init(this, sptr_to_self, kid_map_.at(name),
         name, arg_size, info.thread_axis_tags);
  return PackFuncVoidAddr(f, info.arg_types);
}

void OpenCLModuleNode::SaveToFile(const std::string& file_name,
                                  const std::string& format) {
  std::string fmt = GetFileFormat(file_name, format);
  CHECK_EQ(fmt, fmt_)
      << "Can only save to format=" << fmt_;
  std::string meta_file = GetMetaFilePath(file_name);
  SaveMetaDataToFile(meta_file, fmap_);
  SaveBinaryToFile(file_name, data_);
}

void OpenCLModuleNode::SaveToBinary(dmlc::Stream* stream) {
  stream->Write(fmt_);
  stream->Write(fmap_);
  stream->Write(data_);
}

std::string OpenCLModuleNode::GetSource(const std::string& format) {
  if (format == fmt_) return data_;
  if (fmt_ == "cl") {
    return data_;
  } else {
    return source_;
  }
}

void OpenCLModuleNode::Init() {
  workspace_ = GetGlobalWorkspace();
  workspace_->Init();
  CHECK(workspace_->context != nullptr) << "No OpenCL device";
  if (fmt_ == "cl") {
    const char* s = data_.c_str();
    size_t len = data_.length();
    cl_int err;
    program_ = clCreateProgramWithSource(
        workspace_->context, 1, &s, &len, &err);
    OPENCL_CHECK_ERROR(err);
  } else if (fmt_ == "xclbin" || fmt_ == "awsxclbin") {
    const unsigned char* s = (const unsigned char *)data_.c_str();
    size_t len = data_.length();
    cl_int err;
    program_ = clCreateProgramWithBinary(
        workspace_->context, 1, &(workspace_->devices[0]), &len, &s, NULL, &err);
    if (err != CL_SUCCESS) {
      LOG(ERROR) << "OpenCL Error: " << cl::CLGetErrorString(err);
    }
  } else {
    LOG(FATAL) << "Unknown OpenCL format " << fmt_;
  }
  device_built_flag_.resize(workspace_->devices.size(), false);
  // initialize the kernel id, need to lock global table.
  std::lock_guard<std::mutex> lock(workspace_->mu);
  for (const auto& kv : fmap_) {
    const std::string& key = kv.first;
    KTRefEntry e;
    if (workspace_->free_kernel_ids.size() != 0) {
      e.kernel_id = workspace_->free_kernel_ids.back();
      workspace_->free_kernel_ids.pop_back();
    } else {
      e.kernel_id = workspace_->num_registered_kernels++;
    }
    e.version = workspace_->timestamp++;
    kid_map_[key] = e;
  }
}

cl_kernel OpenCLModuleNode::InstallKernel(cl::OpenCLWorkspace* w,
                                          cl::OpenCLThreadEntry* t,
                                          const std::string& func_name,
                                          const KTRefEntry& e) {
  std::lock_guard<std::mutex> lock(build_lock_);
  int device_id = t->context.device_id;
  if (!device_built_flag_[device_id]) {
    // build program
    cl_int err;
    cl_device_id dev = w->devices[device_id];
    err = clBuildProgram(program_, 1, &dev, nullptr, nullptr, nullptr);
    if (err != CL_SUCCESS) {
      size_t len;
      std::string log;
      clGetProgramBuildInfo(
          program_, dev, CL_PROGRAM_BUILD_LOG, 0, nullptr, &len);
      log.resize(len);
      clGetProgramBuildInfo(
          program_, dev, CL_PROGRAM_BUILD_LOG, len, &log[0], nullptr);
      LOG(FATAL) << "OpenCL build error for device=" << dev << log;
    }
    device_built_flag_[device_id] = true;
  }
  // build kernel
  cl_int err;
  cl_kernel kernel = clCreateKernel(program_, func_name.c_str(), &err);
  OPENCL_CHECK_ERROR(err);
  t->kernel_table[e.kernel_id].kernel = kernel;
  t->kernel_table[e.kernel_id].version = e.version;
  kernels_.push_back(kernel);
  return kernel;
}

Module OpenCLModuleCreate(
    std::string data,
    std::string fmt,
    std::unordered_map<std::string, FunctionInfo> fmap,
    std::string source) {
  std::shared_ptr<OpenCLModuleNode> n =
      std::make_shared<OpenCLModuleNode>(data, fmt, fmap, source);
  n->Init();
  return Module(n);
}

// Load module from module.
Module OpenCLModuleLoadFile(const std::string& file_name,
                            const std::string& format) {
  std::string data;
  std::unordered_map<std::string, FunctionInfo> fmap;
  std::string fmt = GetFileFormat(file_name, format);
  std::string meta_file = GetMetaFilePath(file_name);
  LoadBinaryFromFile(file_name, &data);
  LoadMetaDataFromFile(meta_file, &fmap);
  return OpenCLModuleCreate(data, fmt, fmap, std::string());
}

Module OpenCLModuleLoadBinary(void* strm) {
  dmlc::Stream* stream = static_cast<dmlc::Stream*>(strm);
  std::string data;
  std::unordered_map<std::string, FunctionInfo> fmap;
  std::string fmt;
  stream->Read(&fmt);
  stream->Read(&fmap);
  stream->Read(&data);
  return OpenCLModuleCreate(data, fmt, fmap, std::string());
}

TVM_REGISTER_GLOBAL("module.loadfile_cl")
.set_body([](TVMArgs args, TVMRetValue* rv) {
    *rv = OpenCLModuleLoadFile(args[0], args[1]);
  });

TVM_REGISTER_GLOBAL("module.loadfile_clbin")
.set_body([](TVMArgs args, TVMRetValue* rv) {
    *rv = OpenCLModuleLoadFile(args[0], args[1]);
  });

TVM_REGISTER_GLOBAL("module.loadbinary_opencl")
.set_body([](TVMArgs args, TVMRetValue* rv) {
    *rv = OpenCLModuleLoadBinary(args[0]);
  });
}  // namespace runtime
}  // namespace tvm
<commit_msg>[RUNTIME][OPENCL] Create program lazily when the program is built (#1408)<commit_after>/*!
 *  Copyright (c) 2017 by Contributors
 * \file opencl_module.cc
 */
#include <dmlc/memory_io.h>
#include <tvm/runtime/registry.h>
#include <vector>
#include <string>
#include <unordered_map>
#include "./opencl_common.h"
#include "./opencl_module.h"

namespace tvm {
namespace runtime {

class OpenCLWrappedFunc {
 public:
  // initialize the OpenCL function.
  void Init(OpenCLModuleNode* m,
            std::shared_ptr<ModuleNode> sptr,
            OpenCLModuleNode::KTRefEntry entry,
            std::string func_name,
            std::vector<size_t> arg_size,
            const std::vector<std::string>& thread_axis_tags)  {
    w_ = m->GetGlobalWorkspace().get();
    m_ = m;
    sptr_ = sptr;
    entry_ = entry;
    func_name_ = func_name;
    arg_size_ = arg_size;
    thread_axis_cfg_.Init(arg_size.size(), thread_axis_tags);
  }
  // invoke the function with void arguments
  void operator()(TVMArgs args,
                  TVMRetValue* rv,
                  void** void_args) const {
    cl::OpenCLThreadEntry* t = w_->GetThreadEntry();
    // get the kernel from thread local kernel table.
    if (entry_.kernel_id >= t->kernel_table.size()) {
      t->kernel_table.resize(entry_.kernel_id + 1);
    }
    const auto& e = t->kernel_table[entry_.kernel_id];
    cl_kernel kernel = e.kernel;
    if (kernel == nullptr || e.version != entry_.version) {
      kernel = m_->InstallKernel(w_, t, func_name_, entry_);
    }
    // setup arguments.
    for (cl_uint i = 0; i < arg_size_.size(); ++i) {
      OPENCL_CALL(clSetKernelArg(kernel, i, arg_size_[i], void_args[i]));
    }
    cl_command_queue queue = w_->GetQueue(t->context);
    ThreadWorkLoad wl = thread_axis_cfg_.Extract(args);
    cl_uint work_dim = static_cast<cl_uint>(thread_axis_cfg_.work_dim());
    for (cl_uint i = 0; i < work_dim; ++i) {
      wl.work_size[i] *= wl.work_size[i + 3];
    }
    // launch kernel
    OPENCL_CALL(clEnqueueNDRangeKernel(
        queue, kernel, work_dim, nullptr,
        wl.work_size,
        wl.work_size + 3,
        0, nullptr, nullptr));
  }

 private:
  // global workspace.
  cl::OpenCLWorkspace* w_;
  // The module
  OpenCLModuleNode* m_;
  // resource handle
  std::shared_ptr<ModuleNode> sptr_;
  // global kernel id in the kernel table.
  OpenCLModuleNode::KTRefEntry entry_;
  // The name of the function.
  std::string func_name_;
  // convert code for void argument
  std::vector<size_t> arg_size_;
  // thread axis config
  ThreadAxisConfig thread_axis_cfg_;
};

OpenCLModuleNode::~OpenCLModuleNode() {
  {
    // free the kernel ids in global table.
    std::lock_guard<std::mutex> lock(workspace_->mu);
    for (auto& kv : kid_map_) {
      workspace_->free_kernel_ids.push_back(kv.second.kernel_id);
    }
  }
  // free the kernels
  for (cl_kernel k : kernels_) {
    OPENCL_CALL(clReleaseKernel(k));
  }
  if (program_) {
    OPENCL_CALL(clReleaseProgram(program_));
  }
}

const std::shared_ptr<cl::OpenCLWorkspace>& OpenCLModuleNode::GetGlobalWorkspace() {
  return cl::OpenCLWorkspace::Global();
}

const char* OpenCLModuleNode::type_key() const {
  return "opencl";
}

PackedFunc OpenCLModuleNode::GetFunction(
    const std::string& name,
    const std::shared_ptr<ModuleNode>& sptr_to_self) {
  CHECK_EQ(sptr_to_self.get(), this);
  CHECK_NE(name, symbol::tvm_module_main)
      << "Device function do not have main";
  auto it = fmap_.find(name);
  if (it == fmap_.end()) return PackedFunc();
  const FunctionInfo& info = it->second;
  OpenCLWrappedFunc f;
  std::vector<size_t> arg_size(info.arg_types.size());
  for (size_t i = 0; i < info.arg_types.size(); ++i) {
    TVMType t = info.arg_types[i];
    CHECK_EQ(t.lanes, 1U);
    if (t.code == kHandle) {
      // specially store pointer type size in OpenCL driver
      arg_size[i] = sizeof(void*);
    } else {
      uint32_t bits = t.bits;
      CHECK_EQ(bits % 8, 0U);
      arg_size[i] = bits / 8;
    }
  }
  // initialize the wrapped func.
  f.Init(this, sptr_to_self, kid_map_.at(name),
         name, arg_size, info.thread_axis_tags);
  return PackFuncVoidAddr(f, info.arg_types);
}

void OpenCLModuleNode::SaveToFile(const std::string& file_name,
                                  const std::string& format) {
  std::string fmt = GetFileFormat(file_name, format);
  CHECK_EQ(fmt, fmt_)
      << "Can only save to format=" << fmt_;
  std::string meta_file = GetMetaFilePath(file_name);
  SaveMetaDataToFile(meta_file, fmap_);
  SaveBinaryToFile(file_name, data_);
}

void OpenCLModuleNode::SaveToBinary(dmlc::Stream* stream) {
  stream->Write(fmt_);
  stream->Write(fmap_);
  stream->Write(data_);
}

std::string OpenCLModuleNode::GetSource(const std::string& format) {
  if (format == fmt_) return data_;
  if (fmt_ == "cl") {
    return data_;
  } else {
    return source_;
  }
}

void OpenCLModuleNode::Init() {
  workspace_ = GetGlobalWorkspace();
  workspace_->Init();
  CHECK(workspace_->context != nullptr) << "No OpenCL device";
  device_built_flag_.resize(workspace_->devices.size(), false);
  // initialize the kernel id, need to lock global table.
  std::lock_guard<std::mutex> lock(workspace_->mu);
  for (const auto& kv : fmap_) {
    const std::string& key = kv.first;
    KTRefEntry e;
    if (workspace_->free_kernel_ids.size() != 0) {
      e.kernel_id = workspace_->free_kernel_ids.back();
      workspace_->free_kernel_ids.pop_back();
    } else {
      e.kernel_id = workspace_->num_registered_kernels++;
    }
    e.version = workspace_->timestamp++;
    kid_map_[key] = e;
  }
}

cl_kernel OpenCLModuleNode::InstallKernel(cl::OpenCLWorkspace* w,
                                          cl::OpenCLThreadEntry* t,
                                          const std::string& func_name,
                                          const KTRefEntry& e) {
  std::lock_guard<std::mutex> lock(build_lock_);
  int device_id = t->context.device_id;
  if (!device_built_flag_[device_id]) {
    // create program
    if (fmt_ == "cl") {
      if (program_ == nullptr) {
        const char* s = data_.c_str();
        size_t len = data_.length();
        cl_int err;
        program_ = clCreateProgramWithSource(w->context, 1, &s, &len, &err);
        OPENCL_CHECK_ERROR(err);
      }
    } else if (fmt_ == "xclbin" || fmt_ == "awsxclbin") {
      const unsigned char* s = (const unsigned char *)data_.c_str();
      size_t len = data_.length();
      cl_int err;
      cl_device_id dev = w->devices[device_id];
      program_ = clCreateProgramWithBinary(w->context, 1, &dev, &len, &s, NULL, &err);
      OPENCL_CHECK_ERROR(err);
    } else {
      LOG(FATAL) << "Unknown OpenCL format " << fmt_;
    }
    // build program
    cl_int err;
    cl_device_id dev = w->devices[device_id];
    err = clBuildProgram(program_, 1, &dev, nullptr, nullptr, nullptr);
    if (err != CL_SUCCESS) {
      size_t len;
      std::string log;
      clGetProgramBuildInfo(
          program_, dev, CL_PROGRAM_BUILD_LOG, 0, nullptr, &len);
      log.resize(len);
      clGetProgramBuildInfo(
          program_, dev, CL_PROGRAM_BUILD_LOG, len, &log[0], nullptr);
      LOG(FATAL) << "OpenCL build error for device=" << dev << log;
    }
    device_built_flag_[device_id] = true;
  }
  // build kernel
  cl_int err;
  cl_kernel kernel = clCreateKernel(program_, func_name.c_str(), &err);
  OPENCL_CHECK_ERROR(err);
  t->kernel_table[e.kernel_id].kernel = kernel;
  t->kernel_table[e.kernel_id].version = e.version;
  kernels_.push_back(kernel);
  return kernel;
}

Module OpenCLModuleCreate(
    std::string data,
    std::string fmt,
    std::unordered_map<std::string, FunctionInfo> fmap,
    std::string source) {
  std::shared_ptr<OpenCLModuleNode> n =
      std::make_shared<OpenCLModuleNode>(data, fmt, fmap, source);
  n->Init();
  return Module(n);
}

// Load module from module.
Module OpenCLModuleLoadFile(const std::string& file_name,
                            const std::string& format) {
  std::string data;
  std::unordered_map<std::string, FunctionInfo> fmap;
  std::string fmt = GetFileFormat(file_name, format);
  std::string meta_file = GetMetaFilePath(file_name);
  LoadBinaryFromFile(file_name, &data);
  LoadMetaDataFromFile(meta_file, &fmap);
  return OpenCLModuleCreate(data, fmt, fmap, std::string());
}

Module OpenCLModuleLoadBinary(void* strm) {
  dmlc::Stream* stream = static_cast<dmlc::Stream*>(strm);
  std::string data;
  std::unordered_map<std::string, FunctionInfo> fmap;
  std::string fmt;
  stream->Read(&fmt);
  stream->Read(&fmap);
  stream->Read(&data);
  return OpenCLModuleCreate(data, fmt, fmap, std::string());
}

TVM_REGISTER_GLOBAL("module.loadfile_cl")
.set_body([](TVMArgs args, TVMRetValue* rv) {
    *rv = OpenCLModuleLoadFile(args[0], args[1]);
  });

TVM_REGISTER_GLOBAL("module.loadfile_clbin")
.set_body([](TVMArgs args, TVMRetValue* rv) {
    *rv = OpenCLModuleLoadFile(args[0], args[1]);
  });

TVM_REGISTER_GLOBAL("module.loadbinary_opencl")
.set_body([](TVMArgs args, TVMRetValue* rv) {
    *rv = OpenCLModuleLoadBinary(args[0]);
  });
}  // namespace runtime
}  // namespace tvm
<|endoftext|>


<commit_before>#include "renderer.hpp"

#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

#include "addr_space.hpp"
#include "address.hpp"
#include "const.hpp"
#include "cpu.hpp"
#include "cursor.hpp"
#include "instruction.hpp"
#include "printer.hpp"
#include "ram.hpp"
#include "util.hpp"

using namespace std;

/*
 * Only public method. Also static. It creates new object every time
 * it gets called.
 */
vector<vector<string>> Renderer::renderState(const Printer &printerIn,
                                             const Ram &ramIn,
                                             const Cpu &cpuIn,
                                             const Cursor &cursorIn,
                                             const View &viewIn) {
  Renderer instance(printerIn, ramIn, cpuIn, cursorIn, viewIn);
  vector<vector<string>> out;
  for (vector<string> line : viewIn.lines) {
    out.push_back(instance.insertActualValues(line));
  }
  return out;
}

vector<string> Renderer::insertActualValues(vector<string> lineIn) {
  vector<bool> highlightedChars = getHighlightedLocations(lineIn);
  vector<string> lineOut;
  for (string cIn : lineIn) {
    string sOut;
    bool charIsALightbulb = ALL_INDICATORS.count(cIn);
    if (charIsALightbulb) {
      sOut = getLightbulb(cIn);
    } else {
      sOut = cIn;
    }
    lineOut.push_back(sOut);
  }
  return insertEscSeqences(lineOut, highlightedChars);
}

vector<string> Renderer::insertEscSeqences(
    vector<string> lineWithoutEscapeSeqences, vector<bool> highlightedChars) {
  vector<string> lineOut;
  bool insideHighlightBlock = false;
  for (size_t i = 0; i < lineWithoutEscapeSeqences.size(); i++) {
    bool firstCharInsideBlock = highlightedChars[i] && !insideHighlightBlock;
    if (firstCharInsideBlock) {
      lineOut.insert(lineOut.end(), HIGHLIGHT_ESC_VEC.begin(),
                     HIGHLIGHT_ESC_VEC.end());
      insideHighlightBlock = true;
    }
    bool firstCharOutsideBlock = !highlightedChars[i] && insideHighlightBlock;
    if (firstCharOutsideBlock) {
      lineOut.insert(lineOut.end(), HIGHLIGHT_END_ESC_VEC.begin(),
                     HIGHLIGHT_END_ESC_VEC.end());
      insideHighlightBlock = false;
    }
    lineOut.push_back(lineWithoutEscapeSeqences[i]);
  }
  return lineOut;
}

/////////////////////////////////
/// GET HIGHLIGHTED LOCATIONS ///
/////////////////////////////////

vector<bool> Renderer::getHighlightedLocations(vector<string> lineIn) {
  vector<bool> highlightedLocations (lineIn.size(), false);
  highlightPc(highlightedLocations, lineIn);
  if (executionEnded()) {
    return highlightedLocations;
  }
  highlightCursor(highlightedLocations, lineIn);
  Instruction *inst = getInstruction();
  bool cursorOnData = inst == NULL;
  if (cursorOnData) {
    highlightPointingInstructions(highlightedLocations, lineIn);
    return highlightedLocations;
  }
  highlightOperator(highlightedLocations, lineIn, inst);
  if (inst->adr.space == CODE) {
    highlightCodeWord(highlightedLocations, lineIn, inst);
  } else if (inst->adr.space == DATA) {
    highlightDataWord(highlightedLocations, lineIn, inst);
  }
  return highlightedLocations;
}

void Renderer::highlightPc(vector<bool> &highlightedLocations,
                                   vector<string> &lineIn) {
  if (executionHasntStarted() || pcHighlighted) {
    return;
  }
  for (size_t i = 0; i < lineIn.size(); i++) {
    if (lineIn[i] == CODE_ADR_INDICATOR) {
      int index = switchIndex[CODE_ADR_INDICATOR];
      if (pcPointingToAddress(index)) {
        highlightedLocations[i] = true;
        pcHighlighted = true;
        return;
      }
    }
  }
}

void Renderer::highlightCursor(vector<bool> &highlightedLocations,
                                       vector<string> &lineIn) {
  if (!executionHasntStarted() || cursorHighlighted) {
    return;
  }
  if (cursor.getAddressSpace() == CODE) {
    findCursor(highlightedLocations, lineIn, CODE_INDICATOR);
  } else if (cursor.getAddressSpace() == DATA) {
    findCursor(highlightedLocations, lineIn, DATA_INDICATOR);
  }
}

void Renderer::findCursor(vector<bool> &highlightedLocations,
                                  vector<string> &lineIn, string c) {
  int indexDelta = 0;
  for (size_t i = 0; i < lineIn.size(); i++) {
    if (lineIn[i] == c) {
      int lightbulbIndex = switchIndex[c] + indexDelta++;
      if (cursor.getAbsoluteBitIndex() == lightbulbIndex) {
        highlightedLocations[i] = true;
        cursorHighlighted = true;
        return;
      }
    }
  }
}

void Renderer::highlightPointingInstructions(vector<bool> &highlightedLocations,
                                             vector<string> &lineIn) {
  set<int> *pointingInstructions = getIndexesOfPointingInstructions();
  for (size_t i = 0; i < lineIn.size(); i++) {
    if (lineIn[i] == CODE_INDICATOR) {
      int addressValue = switchIndex[CODE_INDICATOR] / WORD_SIZE;
      if (pointingInstructions->count(addressValue)) {
        highlightedLocations[i] = true;
      }
    }
  }
}

void Renderer::highlightOperator(vector<bool> &highlightedLocations,
                                         vector<string> &lineIn,
                                         Instruction *inst) {
  string exclude;
  if (inst->isLogic()) {
    exclude = LOGIC_OPS_INDICATOR[min(inst->logicIndex, 8)];
  }
  if (inst->index == INC_DEC_OPS_INDEX) {
    if (inst->logicIndex <= 7) {
      exclude = "INC";
    } else {
      exclude = "DEC";
    }
  }
  string label = " " + inst->label;
  label.append(11 - inst->label.length(), ' ');
  highlightLabel(highlightedLocations, lineIn, Util::stringToVecOfString(label),
                 Util::stringToVecOfString(exclude));
}

void Renderer::highlightCodeWord(vector<bool> &highlightedLocations,
                                        vector<string> &lineIn,
                                        Instruction *inst) {
  if (inst->adr.val == LAST_ADDRESS) {
    vector<string> stopLabel = Util::stringToVecOfString(LAST_CODE_ADDR_LABEL);
    highlightLabel(highlightedLocations, lineIn, stopLabel, {});
    return;
  }
  highlightWord(highlightedLocations, lineIn, CODE_INDICATOR, CODE);
}

void Renderer::highlightDataWord(vector<bool> &highlightedLocations,
                                         vector<string> &lineIn,
                                         Instruction *inst) {
  if (inst->adr.val == LAST_ADDRESS) {
    vector<string> inOutLabel = Util::stringToVecOfString(LAST_DATA_ADDR_LABEL);
    highlightLabel(highlightedLocations, lineIn, inOutLabel, {});
    return;
  }
  highlightWord(highlightedLocations, lineIn, DATA_INDICATOR, DATA);
}

void Renderer::highlightWord(vector<bool> &highlightedLocations,
                                     vector<string> &lineIn, string indicator,
                                     AddrSpace addrSpace) {
  for (size_t i = 0; i < lineIn.size(); i++) {
    if (lineIn[i] == indicator) {
      int addressValue = switchIndex[indicator] / WORD_SIZE;
      Address adr = Address(addrSpace, Util::getBoolNibb(addressValue));
      if (instructionPointingToAddress(adr)) {
        highlightedLocations[i] = !highlightedLocations[i];
      }
    }
  }
}

void Renderer::highlightLabel(vector<bool> &highlightedLocations,
                                     vector<string> &lineIn,
                                     vector<string> label,
                                     vector<string> exclude) {
  auto it = search(begin(lineIn), end(lineIn), begin(label), end(label));
  int labelPosition = it - lineIn.begin();
  bool notFound = it == end(lineIn);
  if (notFound) {
    return;
  }
  size_t excludePosition = numeric_limits<size_t>::max();
  if (!exclude.empty()) {
    it = search(begin(label), end(label), begin(exclude), end(exclude));
    excludePosition = it - label.begin();
  }
  for (size_t i = labelPosition; i < labelPosition + label.size(); i++) {
    bool highlight = (i < labelPosition + excludePosition ||
                      i >= labelPosition + excludePosition + exclude.size());
    if (highlight) {
      highlightedLocations[i] = true;
    }
  }
}

/////////////////////
/// GET LIGHTBULB ///
/////////////////////

string Renderer::getLightbulb(string cIn) {
  int i = switchIndex[cIn]++;
  if (cIn == CODE_INDICATOR) {
      return getCodeBit(i);
  } else if (cIn == DATA_INDICATOR) {
      return getDataBit(i);
  } else if (cIn == REGISTER_INDICATOR) {
      return view.getLightbulb(cpu.getRegister().at(i));
  } else if (cIn == CODE_ADR_INDICATOR) {
      return getAdrIndicator(CODE, i);
  } else if (cIn == DATA_ADR_INDICATOR) {
      return getAdrIndicator(DATA, i);
  } else if (cIn == OUTPUT_INDICATOR) {
      return getFormattedOutput(i);
  }
  cerr << "There was an error parsing a drawing file.";
  cerr << " Problem with char" << cIn << ". Will ignore it.";
  return " ";
}

string Renderer::getCodeBit(int i) {
  return getBit(CODE, i);
}

string Renderer::getDataBit(int i) {
  return getBit(DATA, i);
}

string Renderer::getBit(AddrSpace space, int i) {
  pair<int, int> coord = convertIndexToCoordinates(i);
  bool state = ram.state.at(space).at(coord.second).at(coord.first);
  return view.getLightbulb(state);
}

pair<int, int> Renderer::convertIndexToCoordinates(int index) {
  int y = index / WORD_SIZE;
  int x = index % WORD_SIZE;
  return pair<int, int>(x, y);
}

bool Renderer::pcPointingToAddress(int adr) {
  if (executionHasntStarted()) {
    return false;
  }
  return Util::getInt(cpu.getPc()) == adr;
}

string Renderer::getAdrIndicator(AddrSpace addrSpace, int index) {
  Address indicatorsAddress = Address(addrSpace, Util::getBoolNibb(index));
  bool addressReferenced = isAddressReferencedFirstOrder(indicatorsAddress);
  return view.getLightbulb(addressReferenced);
}

string Renderer::getFormattedOutput(int i) {
  if (printer.getPrinterOutput().length() <= (unsigned) i) {
    return " ";
  } else {
    return string(1, printer.getPrinterOutput().at(i));
  }
}

///////////////////////
/// GET INSTRUCTION ///
///////////////////////

Instruction* Renderer::getInstruction() {
  bool noActiveInstruction = !machineActive() &&
                             cursor.getAddressSpace() == DATA;
  if (noActiveInstruction) {
    return NULL;
  }
  if (instruction.size() == 0) {
    instruction.push_back(initializeInstruction());
  }
  return &instruction[0];
}

bool Renderer::machineActive() {
  return !(executionHasntStarted() || executionEnded());
}

bool Renderer::executionHasntStarted() {
  return cpu.getCycle() == 0;
}

bool Renderer::executionEnded() {
  return Util::getInt(cpu.getPc()) == RAM_SIZE;
}

Instruction Renderer::initializeInstruction() {
  if (machineActive()) {
    return cpu.getInstruction();
  } else {
    return Instruction(cursor.getWord(), EMPTY_WORD, &ram);
  }
}

bool Renderer::instructionHasId(int id) {
  Instruction *inst = getInstruction();
  if (inst == NULL) {
    return false;
  }
  return inst->index == id;
}

/*
 * Is instruction pointing to passed address in passed address space.
 */
bool Renderer::instructionPointingToAddress(Address adr) {
  Instruction *inst = getInstruction();
  if (inst == NULL) {
    return false;
  }
  return inst->adr == adr;
}

set<int>* Renderer::getIndexesOfPointingInstructions() {
  if (pointingInstructions.empty()) {
    pointingInstructions = generatePointingInstructions();
    if (pointingInstructions.empty()) {
      pointingInstructions.insert(-1);
    }
  }
  return &pointingInstructions;
}

set<int> Renderer::generatePointingInstructions() {
  vector<Instruction> *allInstructions = getEffectiveInstructions();
  set<int> out;
  int i = 0;
  for (Instruction inst : *allInstructions) {
    if (inst.adr == cursor.getAddress()) {
      out.insert(i);
    }
    i++;
  }
  return out;
}

vector<Instruction>* Renderer::getEffectiveInstructions() {
  if (!effectiveInstructionsInitialized) {
    vector<Instruction> *allInstructions = getAllInstructions();
    int lastNonemptyInst = -1;
    int i = 0;
    for (Instruction inst : *allInstructions) {
      if (inst.val != EMPTY_WORD) {
        lastNonemptyInst = i;
      }
      i++;
    }
    bool somePresent = lastNonemptyInst != -1;
    if (somePresent) {
      effectiveInstructions = vector<Instruction>(
          allInstructions->begin(),
          allInstructions->begin() + lastNonemptyInst+1);
    }
    effectiveInstructionsInitialized = true;
  }
  return &effectiveInstructions;
}

vector<Instruction>* Renderer::getAllInstructions() {
  if (allInstructions.empty()) {
    for (vector<bool> word : ram.state.at(CODE)) {
      Instruction inst = Instruction(word, cpu.getRegister(), &ram);
      allInstructions.push_back(inst);
    }
  }
  return &allInstructions;
}

bool Renderer::isAddressReferencedFirstOrder(Address adr) {
  vector<Instruction> *instructions = getAllInstructions();
  for (Instruction inst : *instructions) {
    vector<Address> aaa = inst.firstOrderAdr;
    bool isReferenced = find(aaa.begin(), aaa.end(), adr) != aaa.end();
    if (isReferenced) {
      return true;
    }
  }
  return false;
}<commit_msg>Address indicator isn't turn on by empty instructions<commit_after>#include "renderer.hpp"

#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

#include "addr_space.hpp"
#include "address.hpp"
#include "const.hpp"
#include "cpu.hpp"
#include "cursor.hpp"
#include "instruction.hpp"
#include "printer.hpp"
#include "ram.hpp"
#include "util.hpp"

using namespace std;

/*
 * Only public method. Also static. It creates new object every time
 * it gets called.
 */
vector<vector<string>> Renderer::renderState(const Printer &printerIn,
                                             const Ram &ramIn,
                                             const Cpu &cpuIn,
                                             const Cursor &cursorIn,
                                             const View &viewIn) {
  Renderer instance(printerIn, ramIn, cpuIn, cursorIn, viewIn);
  vector<vector<string>> out;
  for (vector<string> line : viewIn.lines) {
    out.push_back(instance.insertActualValues(line));
  }
  return out;
}

vector<string> Renderer::insertActualValues(vector<string> lineIn) {
  vector<bool> highlightedChars = getHighlightedLocations(lineIn);
  vector<string> lineOut;
  for (string cIn : lineIn) {
    string sOut;
    bool charIsALightbulb = ALL_INDICATORS.count(cIn);
    if (charIsALightbulb) {
      sOut = getLightbulb(cIn);
    } else {
      sOut = cIn;
    }
    lineOut.push_back(sOut);
  }
  return insertEscSeqences(lineOut, highlightedChars);
}

vector<string> Renderer::insertEscSeqences(
    vector<string> lineWithoutEscapeSeqences, vector<bool> highlightedChars) {
  vector<string> lineOut;
  bool insideHighlightBlock = false;
  for (size_t i = 0; i < lineWithoutEscapeSeqences.size(); i++) {
    bool firstCharInsideBlock = highlightedChars[i] && !insideHighlightBlock;
    if (firstCharInsideBlock) {
      lineOut.insert(lineOut.end(), HIGHLIGHT_ESC_VEC.begin(),
                     HIGHLIGHT_ESC_VEC.end());
      insideHighlightBlock = true;
    }
    bool firstCharOutsideBlock = !highlightedChars[i] && insideHighlightBlock;
    if (firstCharOutsideBlock) {
      lineOut.insert(lineOut.end(), HIGHLIGHT_END_ESC_VEC.begin(),
                     HIGHLIGHT_END_ESC_VEC.end());
      insideHighlightBlock = false;
    }
    lineOut.push_back(lineWithoutEscapeSeqences[i]);
  }
  return lineOut;
}

/////////////////////////////////
/// GET HIGHLIGHTED LOCATIONS ///
/////////////////////////////////

vector<bool> Renderer::getHighlightedLocations(vector<string> lineIn) {
  vector<bool> highlightedLocations (lineIn.size(), false);
  highlightPc(highlightedLocations, lineIn);
  if (executionEnded()) {
    return highlightedLocations;
  }
  highlightCursor(highlightedLocations, lineIn);
  Instruction *inst = getInstruction();
  bool cursorOnData = inst == NULL;
  if (cursorOnData) {
    highlightPointingInstructions(highlightedLocations, lineIn);
    return highlightedLocations;
  }
  highlightOperator(highlightedLocations, lineIn, inst);
  if (inst->adr.space == CODE) {
    highlightCodeWord(highlightedLocations, lineIn, inst);
  } else if (inst->adr.space == DATA) {
    highlightDataWord(highlightedLocations, lineIn, inst);
  }
  return highlightedLocations;
}

void Renderer::highlightPc(vector<bool> &highlightedLocations,
                                   vector<string> &lineIn) {
  if (executionHasntStarted() || pcHighlighted) {
    return;
  }
  for (size_t i = 0; i < lineIn.size(); i++) {
    if (lineIn[i] == CODE_ADR_INDICATOR) {
      int index = switchIndex[CODE_ADR_INDICATOR];
      if (pcPointingToAddress(index)) {
        highlightedLocations[i] = true;
        pcHighlighted = true;
        return;
      }
    }
  }
}

void Renderer::highlightCursor(vector<bool> &highlightedLocations,
                                       vector<string> &lineIn) {
  if (!executionHasntStarted() || cursorHighlighted) {
    return;
  }
  if (cursor.getAddressSpace() == CODE) {
    findCursor(highlightedLocations, lineIn, CODE_INDICATOR);
  } else if (cursor.getAddressSpace() == DATA) {
    findCursor(highlightedLocations, lineIn, DATA_INDICATOR);
  }
}

void Renderer::findCursor(vector<bool> &highlightedLocations,
                                  vector<string> &lineIn, string c) {
  int indexDelta = 0;
  for (size_t i = 0; i < lineIn.size(); i++) {
    if (lineIn[i] == c) {
      int lightbulbIndex = switchIndex[c] + indexDelta++;
      if (cursor.getAbsoluteBitIndex() == lightbulbIndex) {
        highlightedLocations[i] = true;
        cursorHighlighted = true;
        return;
      }
    }
  }
}

void Renderer::highlightPointingInstructions(vector<bool> &highlightedLocations,
                                             vector<string> &lineIn) {
  set<int> *pointingInstructions = getIndexesOfPointingInstructions();
  for (size_t i = 0; i < lineIn.size(); i++) {
    if (lineIn[i] == CODE_INDICATOR) {
      int addressValue = switchIndex[CODE_INDICATOR] / WORD_SIZE;
      if (pointingInstructions->count(addressValue)) {
        highlightedLocations[i] = true;
      }
    }
  }
}

void Renderer::highlightOperator(vector<bool> &highlightedLocations,
                                         vector<string> &lineIn,
                                         Instruction *inst) {
  string exclude;
  if (inst->isLogic()) {
    exclude = LOGIC_OPS_INDICATOR[min(inst->logicIndex, 8)];
  }
  if (inst->index == INC_DEC_OPS_INDEX) {
    if (inst->logicIndex <= 7) {
      exclude = "INC";
    } else {
      exclude = "DEC";
    }
  }
  string label = " " + inst->label;
  label.append(11 - inst->label.length(), ' ');
  highlightLabel(highlightedLocations, lineIn, Util::stringToVecOfString(label),
                 Util::stringToVecOfString(exclude));
}

void Renderer::highlightCodeWord(vector<bool> &highlightedLocations,
                                        vector<string> &lineIn,
                                        Instruction *inst) {
  if (inst->adr.val == LAST_ADDRESS) {
    vector<string> stopLabel = Util::stringToVecOfString(LAST_CODE_ADDR_LABEL);
    highlightLabel(highlightedLocations, lineIn, stopLabel, {});
    return;
  }
  highlightWord(highlightedLocations, lineIn, CODE_INDICATOR, CODE);
}

void Renderer::highlightDataWord(vector<bool> &highlightedLocations,
                                         vector<string> &lineIn,
                                         Instruction *inst) {
  if (inst->adr.val == LAST_ADDRESS) {
    vector<string> inOutLabel = Util::stringToVecOfString(LAST_DATA_ADDR_LABEL);
    highlightLabel(highlightedLocations, lineIn, inOutLabel, {});
    return;
  }
  highlightWord(highlightedLocations, lineIn, DATA_INDICATOR, DATA);
}

void Renderer::highlightWord(vector<bool> &highlightedLocations,
                                     vector<string> &lineIn, string indicator,
                                     AddrSpace addrSpace) {
  for (size_t i = 0; i < lineIn.size(); i++) {
    if (lineIn[i] == indicator) {
      int addressValue = switchIndex[indicator] / WORD_SIZE;
      Address adr = Address(addrSpace, Util::getBoolNibb(addressValue));
      if (instructionPointingToAddress(adr)) {
        highlightedLocations[i] = !highlightedLocations[i];
      }
    }
  }
}

void Renderer::highlightLabel(vector<bool> &highlightedLocations,
                                     vector<string> &lineIn,
                                     vector<string> label,
                                     vector<string> exclude) {
  auto it = search(begin(lineIn), end(lineIn), begin(label), end(label));
  int labelPosition = it - lineIn.begin();
  bool notFound = it == end(lineIn);
  if (notFound) {
    return;
  }
  size_t excludePosition = numeric_limits<size_t>::max();
  if (!exclude.empty()) {
    it = search(begin(label), end(label), begin(exclude), end(exclude));
    excludePosition = it - label.begin();
  }
  for (size_t i = labelPosition; i < labelPosition + label.size(); i++) {
    bool highlight = (i < labelPosition + excludePosition ||
                      i >= labelPosition + excludePosition + exclude.size());
    if (highlight) {
      highlightedLocations[i] = true;
    }
  }
}

/////////////////////
/// GET LIGHTBULB ///
/////////////////////

string Renderer::getLightbulb(string cIn) {
  int i = switchIndex[cIn]++;
  if (cIn == CODE_INDICATOR) {
      return getCodeBit(i);
  } else if (cIn == DATA_INDICATOR) {
      return getDataBit(i);
  } else if (cIn == REGISTER_INDICATOR) {
      return view.getLightbulb(cpu.getRegister().at(i));
  } else if (cIn == CODE_ADR_INDICATOR) {
      return getAdrIndicator(CODE, i);
  } else if (cIn == DATA_ADR_INDICATOR) {
      return getAdrIndicator(DATA, i);
  } else if (cIn == OUTPUT_INDICATOR) {
      return getFormattedOutput(i);
  }
  cerr << "There was an error parsing a drawing file.";
  cerr << " Problem with char" << cIn << ". Will ignore it.";
  return " ";
}

string Renderer::getCodeBit(int i) {
  return getBit(CODE, i);
}

string Renderer::getDataBit(int i) {
  return getBit(DATA, i);
}

string Renderer::getBit(AddrSpace space, int i) {
  pair<int, int> coord = convertIndexToCoordinates(i);
  bool state = ram.state.at(space).at(coord.second).at(coord.first);
  return view.getLightbulb(state);
}

pair<int, int> Renderer::convertIndexToCoordinates(int index) {
  int y = index / WORD_SIZE;
  int x = index % WORD_SIZE;
  return pair<int, int>(x, y);
}

bool Renderer::pcPointingToAddress(int adr) {
  if (executionHasntStarted()) {
    return false;
  }
  return Util::getInt(cpu.getPc()) == adr;
}

string Renderer::getAdrIndicator(AddrSpace addrSpace, int index) {
  Address indicatorsAddress = Address(addrSpace, Util::getBoolNibb(index));
  bool addressReferenced = isAddressReferencedFirstOrder(indicatorsAddress);
  return view.getLightbulb(addressReferenced);
}

string Renderer::getFormattedOutput(int i) {
  if (printer.getPrinterOutput().length() <= (unsigned) i) {
    return " ";
  } else {
    return string(1, printer.getPrinterOutput().at(i));
  }
}

///////////////////////
/// GET INSTRUCTION ///
///////////////////////

Instruction* Renderer::getInstruction() {
  bool noActiveInstruction = !machineActive() &&
                             cursor.getAddressSpace() == DATA;
  if (noActiveInstruction) {
    return NULL;
  }
  if (instruction.size() == 0) {
    instruction.push_back(initializeInstruction());
  }
  return &instruction[0];
}

bool Renderer::machineActive() {
  return !(executionHasntStarted() || executionEnded());
}

bool Renderer::executionHasntStarted() {
  return cpu.getCycle() == 0;
}

bool Renderer::executionEnded() {
  return Util::getInt(cpu.getPc()) == RAM_SIZE;
}

Instruction Renderer::initializeInstruction() {
  if (machineActive()) {
    return cpu.getInstruction();
  } else {
    return Instruction(cursor.getWord(), EMPTY_WORD, &ram);
  }
}

bool Renderer::instructionHasId(int id) {
  Instruction *inst = getInstruction();
  if (inst == NULL) {
    return false;
  }
  return inst->index == id;
}

/*
 * Is instruction pointing to passed address in passed address space.
 */
bool Renderer::instructionPointingToAddress(Address adr) {
  Instruction *inst = getInstruction();
  if (inst == NULL) {
    return false;
  }
  return inst->adr == adr;
}

set<int>* Renderer::getIndexesOfPointingInstructions() {
  if (pointingInstructions.empty()) {
    pointingInstructions = generatePointingInstructions();
    if (pointingInstructions.empty()) {
      pointingInstructions.insert(-1);
    }
  }
  return &pointingInstructions;
}

set<int> Renderer::generatePointingInstructions() {
  vector<Instruction> *allInstructions = getEffectiveInstructions();
  set<int> out;
  int i = 0;
  for (Instruction inst : *allInstructions) {
    if (inst.adr == cursor.getAddress()) {
      out.insert(i);
    }
    i++;
  }
  return out;
}

/*
 * Doesn't include empty instructions from last non-empty on.
 */
vector<Instruction>* Renderer::getEffectiveInstructions() {
  if (!effectiveInstructionsInitialized) {
    vector<Instruction> *allInstructions = getAllInstructions();
    int lastNonemptyInst = -1;
    int i = 0;
    for (Instruction inst : *allInstructions) {
      if (inst.val != EMPTY_WORD) {
        lastNonemptyInst = i;
      }
      i++;
    }
    bool somePresent = lastNonemptyInst != -1;
    if (somePresent) {
      effectiveInstructions = vector<Instruction>(
          allInstructions->begin(),
          allInstructions->begin() + lastNonemptyInst+1);
    }
    effectiveInstructionsInitialized = true;
  }
  return &effectiveInstructions;
}

vector<Instruction>* Renderer::getAllInstructions() {
  if (allInstructions.empty()) {
    for (vector<bool> word : ram.state.at(CODE)) {
      Instruction inst = Instruction(word, cpu.getRegister(), &ram);
      allInstructions.push_back(inst);
    }
  }
  return &allInstructions;
}

bool Renderer::isAddressReferencedFirstOrder(Address adr) {
  vector<Instruction> *instructions = getEffectiveInstructions();
  for (Instruction inst : *instructions) {
    vector<Address> aaa = inst.firstOrderAdr;
    bool isReferenced = find(aaa.begin(), aaa.end(), adr) != aaa.end();
    if (isReferenced) {
      return true;
    }
  }
  return false;
}<|endoftext|>


<commit_before>#include <map>
#include <string>
#include <iostream>

#include <docopt/docopt.h>

#include "serve.hpp"
#include "simple_commands.hpp"

int main(int argc, char * argv[])
{
    static const char usage[] =
R"(Remote SimGrid command-line tool.

Usage:
  rsg serve <platform-file> [--port=<port>] [-- <sg-options>...]
  rsg add-actor <actor-name> <sg-host>
                [--hostname=<host>] [--port=<port>] [--no-autoconnect]
                [--] <command> [<command-args>...]
  rsg start [--hostname=<host>] [--port=<port>]
  rsg status [--hostname=<host>] [--port=<port>] [--retry-timeout=<ms>]
  rsg kill [--hostname=<host>] [--reason=<reason>] [--port=<port>]
  rsg --help

Options:
  -h --hostname <host>  Server's hostname [default: 127.0.0.1].
  -p --port <port>      Server's TCP port [default: 35000].
  --retry-timeout <ms>  If set, retry connection until timeout in milliseconds.
)";

    // Parse CLI arguments.
    auto args = docopt::docopt(usage, { argv + 1, argv + argc }, true);

    // Check argument validity
    std::string server_hostname = args["--hostname"].asString();
    int server_port = args["--port"].asLong();

    // Debug printing, should be removed.
    /*std::cout << "Arguments:" << std::endl;
    for(auto const & arg : args) {
        std::cout << "  " << arg.first << ": " << arg.second << std::endl;
    }*/

    // Manage subcommands.
    int return_code = 0;
    if (args["serve"].asBool())
    {
        std::string platform_file = args["<platform-file>"].asString();
        std::vector<std::string> simgrid_options = args["<sg-options>"].asStringList();
        return_code = serve(platform_file, server_port, simgrid_options);
    }
    else if (args["kill"].asBool())
    {
        std::string kill_reason = "";
        if (args["--reason"].isString())
            kill_reason = args["--reason"].asString();
        return_code = kill(server_hostname, server_port, kill_reason);
    }
    else if (args["start"].asBool())
    {
        return_code = start(server_hostname, server_port);
    }
    else if (args["status"].asBool())
    {
        int retry_timeout_ms = 0;
        if (args["--retry-timeout"].isString())
            retry_timeout_ms = args["--retry-timeout"].asLong();
        return_code = status(server_hostname, server_port, retry_timeout_ms);
    }
    else if (args["add-actor"].asBool())
    {
        std::string actor_name = args["<actor-name>"].asString();
        std::string vhost_name = args["<sg-host>"].asString();
        bool autoconnect = !args["--no-autoconnect"].asBool();
        std::string command = args["<command>"].asString();
        std::vector<std::string> command_args = args["<command-args>"].asStringList();
        return_code = add_actor(server_hostname, server_port, actor_name, vhost_name,
            autoconnect, command, command_args);
    }

    return return_code;
}
<commit_msg>[rsg] serve --daemon<commit_after>#include <map>
#include <string>
#include <iostream>

#include <string.h>

#include <docopt/docopt.h>

#include "serve.hpp"
#include "simple_commands.hpp"

int main(int argc, char * argv[])
{
    static const char usage[] =
R"(Remote SimGrid command-line tool.

Usage:
  rsg serve <platform-file> [--port=<port>] [--daemon] [-- <sg-options>...]
  rsg add-actor <actor-name> <sg-host>
                [--hostname=<host>] [--port=<port>] [--no-autoconnect]
                [--] <command> [<command-args>...]
  rsg start [--hostname=<host>] [--port=<port>]
  rsg status [--hostname=<host>] [--port=<port>] [--retry-timeout=<ms>]
  rsg kill [--hostname=<host>] [--reason=<reason>] [--port=<port>]
  rsg --help

Options:
  -h --hostname <host>  Server's hostname [default: 127.0.0.1].
  -p --port <port>      Server's TCP port [default: 35000].
  -d --daemon           Run as a deamon — i.e., in background.
  --retry-timeout <ms>  If set, retry connection until timeout in milliseconds.
)";

    // Parse CLI arguments.
    auto args = docopt::docopt(usage, { argv + 1, argv + argc }, true);

    // Check argument validity
    std::string server_hostname = args["--hostname"].asString();
    int server_port = args["--port"].asLong();

    // Debug printing, should be removed.
    /*std::cout << "Arguments:" << std::endl;
    for(auto const & arg : args) {
        std::cout << "  " << arg.first << ": " << arg.second << std::endl;
    }*/

    // Manage subcommands.
    int return_code = 0;
    if (args["serve"].asBool())
    {
        std::string platform_file = args["<platform-file>"].asString();
        std::vector<std::string> simgrid_options = args["<sg-options>"].asStringList();

        if (args["--daemon"].asBool()) {
            if (daemon(1, 1) != 0) {
                printf("Could not daemon: %s\n", strerror(errno));
                return 1;
            }
        }

        return_code = serve(platform_file, server_port, simgrid_options);
    }
    else if (args["kill"].asBool())
    {
        std::string kill_reason = "";
        if (args["--reason"].isString())
            kill_reason = args["--reason"].asString();
        return_code = kill(server_hostname, server_port, kill_reason);
    }
    else if (args["start"].asBool())
    {
        return_code = start(server_hostname, server_port);
    }
    else if (args["status"].asBool())
    {
        int retry_timeout_ms = 0;
        if (args["--retry-timeout"].isString())
            retry_timeout_ms = args["--retry-timeout"].asLong();
        return_code = status(server_hostname, server_port, retry_timeout_ms);
    }
    else if (args["add-actor"].asBool())
    {
        std::string actor_name = args["<actor-name>"].asString();
        std::string vhost_name = args["<sg-host>"].asString();
        bool autoconnect = !args["--no-autoconnect"].asBool();
        std::string command = args["<command>"].asString();
        std::vector<std::string> command_args = args["<command-args>"].asStringList();
        return_code = add_actor(server_hostname, server_port, actor_name, vhost_name,
            autoconnect, command, command_args);
    }

    return return_code;
}
<|endoftext|>