<commit_before>#include "directories.h"
#include "logging.h"
#include <algorithm>
#include <unordered_set>
#include "source.h"

#include <iostream> //TODO: remove
using namespace std; //TODO: remove

namespace sigc {
#ifndef SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
  template <typename Functor>
  struct functor_trait<Functor, false> {
    typedef decltype (::sigc::mem_fun(std::declval<Functor&>(),
                                      &Functor::operator())) _intermediate;
    typedef typename _intermediate::result_type result_type;
    typedef Functor functor_type;
  };
#else
  SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
#endif
}

Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
  tree_store = Gtk::TreeStore::create(column_record);
  set_model(tree_store);
  append_column("", column_record.name);
  auto renderer=dynamic_cast<Gtk::CellRendererText*>(get_column(0)->get_first_cell());
  get_column(0)->add_attribute(renderer->property_foreground_rgba(), column_record.color);

  tree_store->set_sort_column(column_record.id, Gtk::SortType::SORT_ASCENDING);
  set_enable_search(true); //TODO: why does this not work in OS X?
  set_search_column(column_record.name);

  signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column){
    auto iter = tree_store->get_iter(path);
    if (iter) {
      auto filesystem_path=iter->get_value(column_record.path);
      if(filesystem_path!="") {
        if (boost::filesystem::is_directory(boost::filesystem::path(filesystem_path))) {
          row_expanded(path) ? collapse_row(path) : expand_row(path, false);
        } else {
          if(on_row_activated)
            on_row_activated(filesystem_path);
        }
      }
    }
  });

  signal_test_expand_row().connect([this](const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path){
    if(iter->children().begin()->get_value(column_record.path)=="") {
      update_mutex.lock();
      add_path(iter->get_value(column_record.path), *iter);
      update_mutex.unlock();
    }
    return false;
  });
  signal_row_collapsed().connect([this](const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path){
    update_mutex.lock();
    auto directory_str=iter->get_value(column_record.path).string();
    for(auto it=last_write_times.begin();it!=last_write_times.end();) {
      if(directory_str==it->first.substr(0, directory_str.size()))
        it=last_write_times.erase(it);
      else
        it++;
    }
    update_mutex.unlock();
    auto children=iter->children();
    if(children) {
      while(children) {
        tree_store->erase(children.begin());
      }
      auto child=tree_store->append(iter->children());
      child->set_value(column_record.name, std::string("(empty)"));
      Gdk::RGBA rgba;
      rgba.set_rgba(0.5, 0.5, 0.5);
      child->set_value(column_record.color, rgba);
    }
  });

  update_dispatcher.connect([this](){
    update_mutex.lock();
    for(auto &path: update_paths) {
      if(last_write_times.count(path)>0)
        add_path(path, last_write_times.at(path).first);
    }
    update_paths.clear();
    update_mutex.unlock();
  });

  update_thread=std::thread([this](){
    while(!stop_update_thread) {
      std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      update_mutex.lock();
      if(update_paths.size()==0) {
        for(auto it=last_write_times.begin();it!=last_write_times.end();) {
          boost::system::error_code ec;
          auto last_write_time=boost::filesystem::last_write_time(it->first, ec);
          if(!ec) {
            if(it->second.second<last_write_time) {
              update_paths.emplace_back(it->first);
            }
            it++;
          }
          else
            it=last_write_times.erase(it);
        }
        if(update_paths.size()>0)
          update_dispatcher();
      }
      update_mutex.unlock();
    }
  });
}

Directories::~Directories() {
  stop_update_thread=true;
  update_thread.join();
}

void Directories::open(const boost::filesystem::path& dir_path) {
  JDEBUG("start");
  if(dir_path.empty())
    return;

  tree_store->clear();
  update_mutex.lock();
  last_write_times.clear();
  update_paths.clear();
  update_mutex.unlock();

  cmake=std::unique_ptr<CMake>(new CMake(dir_path));
  CMake::create_default_build(cmake->project_path);
  auto project=cmake->get_functions_parameters("project");
  if(project.size()>0 && project[0].second.size()>0)
    get_column(0)->set_title(project[0].second[0]);
  else
    get_column(0)->set_title("");
  update_mutex.lock();
  add_path(dir_path, Gtk::TreeModel::Row());
  update_mutex.unlock();

  current_path=dir_path;

 JDEBUG("end");
}

void Directories::update() {
 JDEBUG("start");
  update_mutex.lock();
  for(auto &last_write_time: last_write_times) {
    add_path(last_write_time.first, last_write_time.second.first);
  }
  update_mutex.unlock();
 JDEBUG("end");
}

void Directories::select(const boost::filesystem::path &path) {
 JDEBUG("start");
  if(current_path=="")
    return;

  if(path.generic_string().substr(0, current_path.generic_string().size()+1)!=current_path.generic_string()+'/')
    return;

  std::list<boost::filesystem::path> paths;
  boost::filesystem::path parent_path;
  if(boost::filesystem::is_directory(path))
    parent_path=path;
  else
    parent_path=path.parent_path();
  paths.emplace_front(parent_path);
  while(parent_path!=current_path) {
    parent_path=parent_path.parent_path();
    paths.emplace_front(parent_path);
  }

  for(auto &a_path: paths) {
    tree_store->foreach_iter([this, &a_path](const Gtk::TreeModel::iterator& iter){
      if(iter->get_value(column_record.path)==a_path) {
        update_mutex.lock();
        add_path(a_path, *iter);
        update_mutex.unlock();
        return true;
      }
      return false;
    });
  }

  tree_store->foreach_iter([this, &path](const Gtk::TreeModel::iterator& iter){
    if(iter->get_value(column_record.path)==path) {
      auto tree_path=Gtk::TreePath(iter);
      expand_to_path(tree_path);
      set_cursor(tree_path);
      return true;
    }
    return false;
  });
 JDEBUG("end");
}

void Directories::add_path(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &parent) {
  boost::system::error_code ec;
  auto last_write_time=boost::filesystem::last_write_time(dir_path, ec);
  if(ec)
    return;
  last_write_times[dir_path.string()]={parent, last_write_time};
  std::unique_ptr<Gtk::TreeNodeChildren> children; //Gtk::TreeNodeChildren is missing default constructor...
  if(parent)
    children=std::unique_ptr<Gtk::TreeNodeChildren>(new Gtk::TreeNodeChildren(parent.children()));
  else
    children=std::unique_ptr<Gtk::TreeNodeChildren>(new Gtk::TreeNodeChildren(tree_store->children()));
  if(*children) {
    if(children->begin()->get_value(column_record.path)=="")
      tree_store->erase(children->begin());
  }
  std::unordered_set<std::string> not_deleted;
  boost::filesystem::directory_iterator end_it;
  for(boost::filesystem::directory_iterator it(dir_path);it!=end_it;it++) {
    auto filename=it->path().filename().string();
    bool already_added=false;
    if(*children) {
      for(auto &child: *children) {
        if(child->get_value(column_record.name)==filename) {
          not_deleted.emplace(filename);
          already_added=true;
          break;
        }
      }
    }
    if(!already_added) {
      auto child = tree_store->append(*children);
      not_deleted.emplace(filename);
      child->set_value(column_record.name, filename);
      child->set_value(column_record.path, it->path());
      if (boost::filesystem::is_directory(it->path())) {
        child->set_value(column_record.id, "a"+filename);
        auto grandchild=tree_store->append(child->children());
        grandchild->set_value(column_record.name, std::string("(empty)"));
        Gdk::RGBA rgba;
        rgba.set_rgba(0.5, 0.5, 0.5);
        grandchild->set_value(column_record.color, rgba);
      }
      else {
        child->set_value(column_record.id, "b"+filename);

        auto language=Source::guess_language(it->path().filename());
        if(!language) {
          Gdk::RGBA rgba;
          rgba.set_rgba(0.5, 0.5, 0.5);
          child->set_value(column_record.color, rgba);
        }
      }
    }
  }
  if(*children) {
    for(auto it=children->begin();it!=children->end();) {
      if(not_deleted.count(it->get_value(column_record.name))==0) {
        it=tree_store->erase(it);
      }
      else
        it++;
    }
  }
  if(!*children) {
    auto child=tree_store->append(*children);
    child->set_value(column_record.name, std::string("(empty)"));
    Gdk::RGBA rgba;
    rgba.set_rgba(0.5, 0.5, 0.5);
    child->set_value(column_record.color, rgba);
  }
}
<commit_msg>Project title in directories should now correctly contain _ if any<commit_after>#include "directories.h"
#include "logging.h"
#include <algorithm>
#include <unordered_set>
#include "source.h"

#include <iostream> //TODO: remove
using namespace std; //TODO: remove

namespace sigc {
#ifndef SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
  template <typename Functor>
  struct functor_trait<Functor, false> {
    typedef decltype (::sigc::mem_fun(std::declval<Functor&>(),
                                      &Functor::operator())) _intermediate;
    typedef typename _intermediate::result_type result_type;
    typedef Functor functor_type;
  };
#else
  SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
#endif
}

Directories::Directories() : Gtk::TreeView(), stop_update_thread(false) {
  tree_store = Gtk::TreeStore::create(column_record);
  set_model(tree_store);
  append_column("", column_record.name);
  auto renderer=dynamic_cast<Gtk::CellRendererText*>(get_column(0)->get_first_cell());
  get_column(0)->add_attribute(renderer->property_foreground_rgba(), column_record.color);

  tree_store->set_sort_column(column_record.id, Gtk::SortType::SORT_ASCENDING);
  set_enable_search(true); //TODO: why does this not work in OS X?
  set_search_column(column_record.name);

  signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column){
    auto iter = tree_store->get_iter(path);
    if (iter) {
      auto filesystem_path=iter->get_value(column_record.path);
      if(filesystem_path!="") {
        if (boost::filesystem::is_directory(boost::filesystem::path(filesystem_path))) {
          row_expanded(path) ? collapse_row(path) : expand_row(path, false);
        } else {
          if(on_row_activated)
            on_row_activated(filesystem_path);
        }
      }
    }
  });

  signal_test_expand_row().connect([this](const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path){
    if(iter->children().begin()->get_value(column_record.path)=="") {
      update_mutex.lock();
      add_path(iter->get_value(column_record.path), *iter);
      update_mutex.unlock();
    }
    return false;
  });
  signal_row_collapsed().connect([this](const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path){
    update_mutex.lock();
    auto directory_str=iter->get_value(column_record.path).string();
    for(auto it=last_write_times.begin();it!=last_write_times.end();) {
      if(directory_str==it->first.substr(0, directory_str.size()))
        it=last_write_times.erase(it);
      else
        it++;
    }
    update_mutex.unlock();
    auto children=iter->children();
    if(children) {
      while(children) {
        tree_store->erase(children.begin());
      }
      auto child=tree_store->append(iter->children());
      child->set_value(column_record.name, std::string("(empty)"));
      Gdk::RGBA rgba;
      rgba.set_rgba(0.5, 0.5, 0.5);
      child->set_value(column_record.color, rgba);
    }
  });

  update_dispatcher.connect([this](){
    update_mutex.lock();
    for(auto &path: update_paths) {
      if(last_write_times.count(path)>0)
        add_path(path, last_write_times.at(path).first);
    }
    update_paths.clear();
    update_mutex.unlock();
  });

  update_thread=std::thread([this](){
    while(!stop_update_thread) {
      std::this_thread::sleep_for(std::chrono::milliseconds(1000));
      update_mutex.lock();
      if(update_paths.size()==0) {
        for(auto it=last_write_times.begin();it!=last_write_times.end();) {
          boost::system::error_code ec;
          auto last_write_time=boost::filesystem::last_write_time(it->first, ec);
          if(!ec) {
            if(it->second.second<last_write_time) {
              update_paths.emplace_back(it->first);
            }
            it++;
          }
          else
            it=last_write_times.erase(it);
        }
        if(update_paths.size()>0)
          update_dispatcher();
      }
      update_mutex.unlock();
    }
  });
}

Directories::~Directories() {
  stop_update_thread=true;
  update_thread.join();
}

void Directories::open(const boost::filesystem::path& dir_path) {
  JDEBUG("start");
  if(dir_path.empty())
    return;

  tree_store->clear();
  update_mutex.lock();
  last_write_times.clear();
  update_paths.clear();
  update_mutex.unlock();

  cmake=std::unique_ptr<CMake>(new CMake(dir_path));
  CMake::create_default_build(cmake->project_path);
  auto project=cmake->get_functions_parameters("project");
  if(project.size()>0 && project[0].second.size()>0) {
    auto title=project[0].second[0];
    //TOTO: report that set_title does not handle '_' correctly?
    size_t pos=0;
    while((pos=title.find('_', pos))!=std::string::npos) {
      title.replace(pos, 1, "__");
      pos+=2;
    }
    get_column(0)->set_title(title);
  }
  else
    get_column(0)->set_title("");
  update_mutex.lock();
  add_path(dir_path, Gtk::TreeModel::Row());
  update_mutex.unlock();

  current_path=dir_path;

 JDEBUG("end");
}

void Directories::update() {
 JDEBUG("start");
  update_mutex.lock();
  for(auto &last_write_time: last_write_times) {
    add_path(last_write_time.first, last_write_time.second.first);
  }
  update_mutex.unlock();
 JDEBUG("end");
}

void Directories::select(const boost::filesystem::path &path) {
 JDEBUG("start");
  if(current_path=="")
    return;

  if(path.generic_string().substr(0, current_path.generic_string().size()+1)!=current_path.generic_string()+'/')
    return;

  std::list<boost::filesystem::path> paths;
  boost::filesystem::path parent_path;
  if(boost::filesystem::is_directory(path))
    parent_path=path;
  else
    parent_path=path.parent_path();
  paths.emplace_front(parent_path);
  while(parent_path!=current_path) {
    parent_path=parent_path.parent_path();
    paths.emplace_front(parent_path);
  }

  for(auto &a_path: paths) {
    tree_store->foreach_iter([this, &a_path](const Gtk::TreeModel::iterator& iter){
      if(iter->get_value(column_record.path)==a_path) {
        update_mutex.lock();
        add_path(a_path, *iter);
        update_mutex.unlock();
        return true;
      }
      return false;
    });
  }

  tree_store->foreach_iter([this, &path](const Gtk::TreeModel::iterator& iter){
    if(iter->get_value(column_record.path)==path) {
      auto tree_path=Gtk::TreePath(iter);
      expand_to_path(tree_path);
      set_cursor(tree_path);
      return true;
    }
    return false;
  });
 JDEBUG("end");
}

void Directories::add_path(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &parent) {
  boost::system::error_code ec;
  auto last_write_time=boost::filesystem::last_write_time(dir_path, ec);
  if(ec)
    return;
  last_write_times[dir_path.string()]={parent, last_write_time};
  std::unique_ptr<Gtk::TreeNodeChildren> children; //Gtk::TreeNodeChildren is missing default constructor...
  if(parent)
    children=std::unique_ptr<Gtk::TreeNodeChildren>(new Gtk::TreeNodeChildren(parent.children()));
  else
    children=std::unique_ptr<Gtk::TreeNodeChildren>(new Gtk::TreeNodeChildren(tree_store->children()));
  if(*children) {
    if(children->begin()->get_value(column_record.path)=="")
      tree_store->erase(children->begin());
  }
  std::unordered_set<std::string> not_deleted;
  boost::filesystem::directory_iterator end_it;
  for(boost::filesystem::directory_iterator it(dir_path);it!=end_it;it++) {
    auto filename=it->path().filename().string();
    bool already_added=false;
    if(*children) {
      for(auto &child: *children) {
        if(child->get_value(column_record.name)==filename) {
          not_deleted.emplace(filename);
          already_added=true;
          break;
        }
      }
    }
    if(!already_added) {
      auto child = tree_store->append(*children);
      not_deleted.emplace(filename);
      child->set_value(column_record.name, filename);
      child->set_value(column_record.path, it->path());
      if (boost::filesystem::is_directory(it->path())) {
        child->set_value(column_record.id, "a"+filename);
        auto grandchild=tree_store->append(child->children());
        grandchild->set_value(column_record.name, std::string("(empty)"));
        Gdk::RGBA rgba;
        rgba.set_rgba(0.5, 0.5, 0.5);
        grandchild->set_value(column_record.color, rgba);
      }
      else {
        child->set_value(column_record.id, "b"+filename);

        auto language=Source::guess_language(it->path().filename());
        if(!language) {
          Gdk::RGBA rgba;
          rgba.set_rgba(0.5, 0.5, 0.5);
          child->set_value(column_record.color, rgba);
        }
      }
    }
  }
  if(*children) {
    for(auto it=children->begin();it!=children->end();) {
      if(not_deleted.count(it->get_value(column_record.name))==0) {
        it=tree_store->erase(it);
      }
      else
        it++;
    }
  }
  if(!*children) {
    auto child=tree_store->append(*children);
    child->set_value(column_record.name, std::string("(empty)"));
    Gdk::RGBA rgba;
    rgba.set_rgba(0.5, 0.5, 0.5);
    child->set_value(column_record.color, rgba);
  }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: admininvokationpage.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: ihi $ $Date: 2008-01-14 14:33:22 $
 *
 *  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_extensions.hxx"

#ifndef EXTENSIONS_ABP_ADMINDIALOG_INVOKATION_PAGE_HXX
#include "admininvokationpage.hxx"
#endif
#ifndef EXTENSIONS_ABSPILOT_HXX
#include "abspilot.hxx"
#endif
#ifndef EXTENSIONS_ABP_ADMININVOKATIONIMPL_HXX
#include "admininvokationimpl.hxx"
#endif

//.........................................................................
namespace abp
{
//.........................................................................

    //=====================================================================
    //= AdminDialogInvokationPage
    //=====================================================================
    AdminDialogInvokationPage::AdminDialogInvokationPage( OAddessBookSourcePilot* _pParent )
        :AddressBookSourcePage(_pParent, ModuleRes(RID_PAGE_ADMININVOKATION))
        ,m_aExplanation         (this, ModuleRes(FT_ADMINEXPLANATION))
        ,m_aInvokeAdminDialog   (this, ModuleRes(PB_INVOKE_ADMIN_DIALOG))
        ,m_aErrorMessage        (this, ModuleRes(FT_ERROR))
        ,m_bSuccessfullyExecutedDialog(sal_False)
    {
        FreeResource();

        m_aInvokeAdminDialog.SetClickHdl( LINK(this, AdminDialogInvokationPage, OnInvokeAdminDialog) );
    }

    //---------------------------------------------------------------------
    void AdminDialogInvokationPage::ActivatePage()
    {
        AddressBookSourcePage::ActivatePage();
        m_aInvokeAdminDialog.GrabFocus();
    }

    //---------------------------------------------------------------------
    void AdminDialogInvokationPage::implUpdateErrorMessage()
    {
        const sal_Bool bIsConnected = getDialog()->getDataSource().isConnected();
        m_aErrorMessage.Show( !bIsConnected );
    }

    //---------------------------------------------------------------------
    void AdminDialogInvokationPage::initializePage()
    {
        AddressBookSourcePage::initializePage();
        m_aErrorMessage.Hide();
            // if we're entering this page, we assume we had no connection trial with this data source
    }

    //---------------------------------------------------------------------
    sal_Bool AdminDialogInvokationPage::commitPage( COMMIT_REASON _eReason )
    {
        return AddressBookSourcePage::commitPage( _eReason );
    }

    //---------------------------------------------------------------------
    void AdminDialogInvokationPage::implTryConnect()
    {
        getDialog()->connectToDataSource( sal_True );

        // show our error message if and only if we could not connect
        implUpdateErrorMessage();

        // the status of the next button may have changed
        implCheckNextButton();

        // automatically go to the next page (if successfully connected)
        if ( determineNextButtonState() )
            getDialog()->travelNext();
    }

    //---------------------------------------------------------------------
    sal_Bool AdminDialogInvokationPage::determineNextButtonState()
    {
        return AddressBookSourcePage::determineNextButtonState() && getDialog()->getDataSource().isConnected();
    }

    //---------------------------------------------------------------------
    IMPL_LINK( AdminDialogInvokationPage, OnInvokeAdminDialog, void*, /*NOTINTERESTEDIN*/ )
    {
        OAdminDialogInvokation aInvokation( getORB(), getDialog()->getDataSource().getDataSource(), getDialog() );
        if ( aInvokation.invokeAdministration( AST_LDAP == getSettings().eType ) )
        {
            // try to connect to this data source
            implTryConnect();
        }

        return 0L;
    }

//.........................................................................
}   // namespace abp
//.........................................................................

<commit_msg>INTEGRATION: CWS odbmacros2 (1.7.114); FILE MERGED 2008/02/11 11:14:55 fs 1.7.114.5: IWizardPage is COMMIT_REASON is deprecated - replace usages with CommitPageReason, while I have an svtools-incompatible CWS 2008/02/04 20:02:16 fs 1.7.114.4: more roadmap/wizard re-factoring: implUpdateNextButton superseded by update(Dialog)TravelUI 2008/02/04 13:08:53 fs 1.7.114.3: RESYNC: (1.7-1.8); FILE MERGED 2008/01/30 13:21:09 fs 1.7.114.2: canAdvance made const 2008/01/15 09:52:42 fs 1.7.114.1: some re-factoring of OWizardMachine, RoadmapWizard and derived classes, to prepare the migration UI for #i49133#<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: admininvokationpage.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: kz $ $Date: 2008-03-06 18:36:58 $
 *
 *  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_extensions.hxx"

#ifndef EXTENSIONS_ABP_ADMINDIALOG_INVOKATION_PAGE_HXX
#include "admininvokationpage.hxx"
#endif
#ifndef EXTENSIONS_ABSPILOT_HXX
#include "abspilot.hxx"
#endif
#ifndef EXTENSIONS_ABP_ADMININVOKATIONIMPL_HXX
#include "admininvokationimpl.hxx"
#endif

//.........................................................................
namespace abp
{
//.........................................................................

    //=====================================================================
    //= AdminDialogInvokationPage
    //=====================================================================
    AdminDialogInvokationPage::AdminDialogInvokationPage( OAddessBookSourcePilot* _pParent )
        :AddressBookSourcePage(_pParent, ModuleRes(RID_PAGE_ADMININVOKATION))
        ,m_aExplanation         (this, ModuleRes(FT_ADMINEXPLANATION))
        ,m_aInvokeAdminDialog   (this, ModuleRes(PB_INVOKE_ADMIN_DIALOG))
        ,m_aErrorMessage        (this, ModuleRes(FT_ERROR))
        ,m_bSuccessfullyExecutedDialog(sal_False)
    {
        FreeResource();

        m_aInvokeAdminDialog.SetClickHdl( LINK(this, AdminDialogInvokationPage, OnInvokeAdminDialog) );
    }

    //---------------------------------------------------------------------
    void AdminDialogInvokationPage::ActivatePage()
    {
        AddressBookSourcePage::ActivatePage();
        m_aInvokeAdminDialog.GrabFocus();
    }

    //---------------------------------------------------------------------
    void AdminDialogInvokationPage::implUpdateErrorMessage()
    {
        const sal_Bool bIsConnected = getDialog()->getDataSource().isConnected();
        m_aErrorMessage.Show( !bIsConnected );
    }

    //---------------------------------------------------------------------
    void AdminDialogInvokationPage::initializePage()
    {
        AddressBookSourcePage::initializePage();
        m_aErrorMessage.Hide();
            // if we're entering this page, we assume we had no connection trial with this data source
    }

    //---------------------------------------------------------------------
    void AdminDialogInvokationPage::implTryConnect()
    {
        getDialog()->connectToDataSource( sal_True );

        // show our error message if and only if we could not connect
        implUpdateErrorMessage();

        // the status of the next button may have changed
        updateDialogTravelUI();

        // automatically go to the next page (if successfully connected)
        if ( canAdvance() )
            getDialog()->travelNext();
    }

    //---------------------------------------------------------------------
    bool AdminDialogInvokationPage::canAdvance() const
    {
        return AddressBookSourcePage::canAdvance() && getDialog()->getDataSource().isConnected();
    }

    //---------------------------------------------------------------------
    IMPL_LINK( AdminDialogInvokationPage, OnInvokeAdminDialog, void*, /*NOTINTERESTEDIN*/ )
    {
        OAdminDialogInvokation aInvokation( getORB(), getDialog()->getDataSource().getDataSource(), getDialog() );
        if ( aInvokation.invokeAdministration( AST_LDAP == getSettings().eType ) )
        {
            // try to connect to this data source
            implTryConnect();
        }

        return 0L;
    }

//.........................................................................
}   // namespace abp
//.........................................................................

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: updateprotocol.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2007-01-29 16:00:14 $
 *
 *  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_extensions.hxx"

#ifndef _COM_SUN_STAR_XML_XPATH_XXPATHAPI_HPP_
#include <com/sun/star/xml/xpath/XXPathAPI.hpp>
#endif

#include "updateprotocol.hxx"

#include <rtl/ref.hxx>
#include <rtl/uri.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <rtl/bootstrap.hxx>
#include <osl/process.h>

#include <cppuhelper/implbase1.hxx>

namespace css = com::sun::star ;
namespace deployment = css::deployment ;
namespace lang = css::lang ;
namespace uno = css::uno ;
namespace task = css::task ;
namespace xml = css::xml ;

#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))

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

static bool
getBootstrapData(
    uno::Sequence< ::rtl::OUString > & rRepositoryList,
    ::rtl::OUString & rBuildID,
    ::rtl::OUString & rInstallSetID)
{
    rtl::OUString aPath, aPath2;
    if( osl_getExecutableFile(&aPath.pData) != osl_Process_E_None )
        return false;

    sal_uInt32 lastIndex = aPath.lastIndexOf('/');
    if ( lastIndex > 0 )
    {
        aPath = aPath.copy( 0, lastIndex+1 );
        aPath += UNISTRING( SAL_CONFIGFILE( "version" ) );
    }

    rtl::Bootstrap aVersionFile(aPath);
    aVersionFile.getFrom(UNISTRING("ProductBuildid"), rBuildID, rtl::OUString());
    aVersionFile.getFrom(UNISTRING("UpdateID"), rInstallSetID, rtl::OUString());

    rtl::OUString aValue;
    aVersionFile.getFrom(UNISTRING("UpdateURL"), aValue, rtl::OUString());
    if( aValue.getLength() > 0 )
    {
        rRepositoryList.realloc(1);
        rRepositoryList[0] = aValue;
    }

    return true;
}

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

// Returns 'true' if successfully connected to the update server
bool
checkForUpdates(
    uno::Reference< uno::XComponentContext > const & rxContext,
    uno::Reference< task::XInteractionHandler > const & rxInteractionHandler,
    rtl::OUString& rUpdateURL, rtl::OUString& rVersionFound,
    uno::Reference< deployment::XUpdateInformationProvider >& rUpdateInfoProvider)
{
    OSL_TRACE("checking for updates ..\n");

    ::rtl::OUString myArch;
    ::rtl::OUString myOS;

    rtl::Bootstrap::get(UNISTRING("_OS"), myOS);
    rtl::Bootstrap::get(UNISTRING("_ARCH"), myArch);

    uno::Sequence< ::rtl::OUString > aRepositoryList;
    ::rtl::OUString aBuildID;
    ::rtl::OUString aInstallSetID;

    if( ! ( getBootstrapData(aRepositoryList, aBuildID, aInstallSetID) && (aRepositoryList.getLength() > 0) ) )
        return false;

    if( !rxContext.is() )
        throw uno::RuntimeException(
            UNISTRING( "checkForUpdates: empty component context" ), uno::Reference< uno::XInterface >() );

    OSL_ASSERT( rxContext->getServiceManager().is() );

    // the update information provider
    rUpdateInfoProvider =  deployment::UpdateInformationProvider::create( rxContext );

    // XPath implementation
    uno::Reference< xml::xpath::XXPathAPI > xXPath(
        rxContext->getServiceManager()->createInstanceWithContext( UNISTRING( "com.sun.star.xml.xpath.XPathAPI" ), rxContext ),
        uno::UNO_QUERY_THROW);

    xXPath->registerNS( UNISTRING("inst"), UNISTRING("http://installation.openoffice.org/description") );

    if( rxInteractionHandler.is() )
        rUpdateInfoProvider->setInteractionHandler(rxInteractionHandler);

    try
    {
        uno::Sequence< uno::Reference< xml::dom::XElement > > aUpdateInfoList =
            rUpdateInfoProvider->getUpdateInformation( aRepositoryList, aInstallSetID );

        rtl::OUStringBuffer aBuffer;
        aBuffer.appendAscii("/child::inst:description[inst:os=\'");
        aBuffer.append( myOS );
        aBuffer.appendAscii("\' and inst:arch=\'");
        aBuffer.append( myArch );
        aBuffer.appendAscii("\' and inst:buildid>");
        aBuffer.append( aBuildID );
        aBuffer.appendAscii("]");

        rtl::OUString aXPathExpression = aBuffer.makeStringAndClear();

        sal_Int32 nmax = aUpdateInfoList.getLength();
        for( sal_Int32 n = 0; n < nmax; ++n )
        {
            uno::Reference< xml::dom::XNode > xNode( aUpdateInfoList[n].get() );
            uno::Reference< xml::dom::XNodeList > xNodeList =
                xXPath->selectNodeList(xNode, aXPathExpression + UNISTRING("/inst:update/attribute::src"));

            sal_Int32 imax = xNodeList->getLength();
            for( sal_Int32 i = 0; i < imax; ++i )
            {
                uno::Reference< xml::dom::XNode > xNode2( xNodeList->item(i) );

                if( xNode2.is() && rUpdateURL.getLength() == 0 )
                    rUpdateURL = xNode2->getNodeValue();
            }

            uno::Reference< xml::dom::XNode > xNode2 =
                xXPath->selectSingleNode(xNode, aXPathExpression + UNISTRING("/inst:buildid/text()"));

            if( xNode2.is() )
                rVersionFound = xNode2->getNodeValue();

            if( rUpdateURL.getLength() > 0 )
                return true;
        }
    }
    catch( ... )
    {
        return false;
    }

    return true;
}
<commit_msg>INTEGRATION: CWS updchk06 (1.5.40); FILE MERGED 2007/06/29 15:33:37 obr 1.5.40.7: #i72386# create file name from effective url 2007/06/29 11:25:58 obr 1.5.40.6: fixed compiler warning 2007/06/29 10:39:57 obr 1.5.40.5: #i72386# finalized release note support 2007/06/28 23:42:03 obr 1.5.40.4: #i72386# reworked locking code and added support for description 2007/06/27 12:40:15 obr 1.5.40.3: #i72386# added initial support for release notes 2007/06/08 14:02:00 obr 1.5.40.2: #i72386# extract download type and a few bug fixes 2007/06/06 09:58:46 obr 1.5.40.1: #i72386# major rework to integrate download & install<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: updateprotocol.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-06 14:38:58 $
 *
 *  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_extensions.hxx"

#ifndef _COM_SUN_STAR_XML_XPATH_XXPATHAPI_HPP_
#include <com/sun/star/xml/xpath/XXPathAPI.hpp>
#endif

#include "updateprotocol.hxx"

#ifndef _COM_SUN_STAR_DEPLOYMENT_UPDATEINFORMATINENTRY_HPP_
#include <com/sun/star/deployment/UpdateInformationEntry.hpp>
#endif

#include <rtl/ref.hxx>
#include <rtl/uri.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/ustrbuf.hxx>
#include <rtl/bootstrap.hxx>
#include <osl/process.h>

#include <cppuhelper/implbase1.hxx>

namespace css = com::sun::star ;
namespace container = css::container ;
namespace deployment = css::deployment ;
namespace lang = css::lang ;
namespace uno = css::uno ;
namespace task = css::task ;
namespace xml = css::xml ;

#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))

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

static bool
getBootstrapData(
    uno::Sequence< ::rtl::OUString > & rRepositoryList,
    ::rtl::OUString & rBuildID,
    ::rtl::OUString & rInstallSetID)
{
    rtl::OUString aPath, aPath2;
    if( osl_getExecutableFile(&aPath.pData) != osl_Process_E_None )
        return false;

    sal_uInt32 lastIndex = aPath.lastIndexOf('/');
    if ( lastIndex > 0 )
    {
        aPath = aPath.copy( 0, lastIndex+1 );
        aPath += UNISTRING( SAL_CONFIGFILE( "version" ) );
    }

    rtl::Bootstrap aVersionFile(aPath);
    aVersionFile.getFrom(UNISTRING("ProductBuildid"), rBuildID, rtl::OUString());
    aVersionFile.getFrom(UNISTRING("UpdateID"), rInstallSetID, rtl::OUString());

    rtl::OUString aValue;
    aVersionFile.getFrom(UNISTRING("UpdateURL"), aValue, rtl::OUString());
    if( aValue.getLength() > 0 )
    {
        rRepositoryList.realloc(1);
        rRepositoryList[0] = aValue;
    }

    return true;
}

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

// Returns 'true' if successfully connected to the update server
bool
checkForUpdates(
    UpdateInfo& o_rUpdateInfo,
    uno::Reference< uno::XComponentContext > const & rxContext,
    uno::Reference< task::XInteractionHandler > const & rxInteractionHandler,
    const uno::Reference< deployment::XUpdateInformationProvider >& rUpdateInfoProvider)
{
    OSL_TRACE("checking for updates ..\n");

    ::rtl::OUString myArch;
    ::rtl::OUString myOS;

    rtl::Bootstrap::get(UNISTRING("_OS"), myOS);
    rtl::Bootstrap::get(UNISTRING("_ARCH"), myArch);

    uno::Sequence< ::rtl::OUString > aRepositoryList;
    ::rtl::OUString aBuildID;
    ::rtl::OUString aInstallSetID;

    if( ! ( getBootstrapData(aRepositoryList, aBuildID, aInstallSetID) && (aRepositoryList.getLength() > 0) ) )
        return false;

    if( !rxContext.is() )
        throw uno::RuntimeException(
            UNISTRING( "checkForUpdates: empty component context" ), uno::Reference< uno::XInterface >() );

    OSL_ASSERT( rxContext->getServiceManager().is() );

    // XPath implementation
    uno::Reference< xml::xpath::XXPathAPI > xXPath(
        rxContext->getServiceManager()->createInstanceWithContext( UNISTRING( "com.sun.star.xml.xpath.XPathAPI" ), rxContext ),
        uno::UNO_QUERY_THROW);

    xXPath->registerNS( UNISTRING("inst"), UNISTRING("http://installation.openoffice.org/description") );

    if( rxInteractionHandler.is() )
        rUpdateInfoProvider->setInteractionHandler(rxInteractionHandler);

    try
    {
        uno::Reference< container::XEnumeration > aUpdateInfoEnumeration =
            rUpdateInfoProvider->getUpdateInformationEnumeration( aRepositoryList, aInstallSetID );

        rtl::OUStringBuffer aBuffer;
        aBuffer.appendAscii("/child::inst:description[inst:os=\'");
        aBuffer.append( myOS );
        aBuffer.appendAscii("\' and inst:arch=\'");
        aBuffer.append( myArch );
        aBuffer.appendAscii("\' and inst:buildid>");
        aBuffer.append( aBuildID );
        aBuffer.appendAscii("]");

        rtl::OUString aXPathExpression = aBuffer.makeStringAndClear();

        while( aUpdateInfoEnumeration->hasMoreElements() )
        {
            deployment::UpdateInformationEntry aEntry;

            if( aUpdateInfoEnumeration->nextElement() >>= aEntry )
            {
                uno::Reference< xml::dom::XNode > xNode( aEntry.UpdateDocument.get() );
                uno::Reference< xml::dom::XNodeList > xNodeList =
                    xXPath->selectNodeList(xNode, aXPathExpression + UNISTRING("/inst:update/attribute::src"));

/*
                o_rUpdateInfo.Sources.push_back( DownloadSource(true,
                    UNISTRING("http://openoffice.bouncer.osuosl.org/?product=OpenOffice.org&os=solarissparcwjre&lang=en-US&version=2.2.1") ) );
*/

                sal_Int32 i, imax = xNodeList->getLength();
                for( i = 0; i < imax; ++i )
                {
                    uno::Reference< xml::dom::XNode > xNode2( xNodeList->item(i) );

                    if( xNode2.is() )
                    {
                        uno::Reference< xml::dom::XElement > xParent(xNode2->getParentNode(), uno::UNO_QUERY_THROW);
                        rtl::OUString aType = xParent->getAttribute(UNISTRING("type"));
                        bool bIsDirect = ( sal_False == aType.equalsIgnoreAsciiCaseAscii("text/html") );

                        o_rUpdateInfo.Sources.push_back( DownloadSource(bIsDirect, xNode2->getNodeValue()) );
                    }
                }

                uno::Reference< xml::dom::XNode > xNode2 =
                    xXPath->selectSingleNode(xNode, aXPathExpression + UNISTRING("/inst:version/text()"));

                if( xNode2.is() )
                    o_rUpdateInfo.Version = xNode2->getNodeValue();

                xNode2 = xXPath->selectSingleNode(xNode, aXPathExpression + UNISTRING("/inst:buildid/text()"));

                if( xNode2.is() )
                    o_rUpdateInfo.BuildId = xNode2->getNodeValue();

                o_rUpdateInfo.Description = aEntry.Description;

                // Release Notes
                xNodeList = xXPath->selectNodeList(xNode, aXPathExpression + UNISTRING("/inst:relnote"));
                imax = xNodeList->getLength();
                for( i = 0; i < imax; ++i )
                {
                    uno::Reference< xml::dom::XElement > xRelNote(xNodeList->item(i), uno::UNO_QUERY);
                    if( xRelNote.is() )
                    {
                        sal_Int32 pos = xRelNote->getAttribute(UNISTRING("pos")).toInt32();

                        ReleaseNote aRelNote((sal_uInt8) pos, xRelNote->getAttribute(UNISTRING("src")));

                        if( xRelNote->hasAttribute(UNISTRING("src2")) )
                        {
                            pos = xRelNote->getAttribute(UNISTRING("pos2")).toInt32();
                            aRelNote.Pos2 = (sal_Int8) pos;
                            aRelNote.URL2 = xRelNote->getAttribute(UNISTRING("src2"));
                        }

                        o_rUpdateInfo.ReleaseNotes.push_back(aRelNote);
                    }
                }
/*
                o_rUpdateInfo.ReleaseNotes.push_back(
                    ReleaseNote(1, UNISTRING("http://qa.openoffice.org/tests/online_update_test.html"))
                );
*/

                if( o_rUpdateInfo.Sources.size() > 0 )
                    return true;
            }
        }
    }
    catch( ... )
    {
        return false;
    }

    return true;
}
<|endoftext|>


<commit_before>// Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "paddle/fluid/framework/details/memory_optimize_pass.h"
#include <algorithm>
#include <atomic>
#include <deque>
#include <fstream>
#include <iostream>
#include <iterator>
#include <memory>
#include <queue>
#include <sstream>
#include <string>
#include <type_traits>
#include <vector>
#include "gflags/gflags.h"
#include "paddle/fluid/framework/data_type.h"
#include "paddle/fluid/framework/ir/graph.h"
#include "paddle/fluid/framework/ir/graph_helper.h"

DEFINE_bool(enable_subgraph_optimize, false,
            "SubGraph also reuse global graph variables, it will reduce the "
            "memory occupation"
            "but a higher risk of memory reuse error. default disabled.");
DEFINE_string(memory_optimize_debug, "",
              "debug the operator output variable when do the variable reuse."
              "memory reuse pass."
              "only for debug, default disabled.");

namespace paddle {
namespace framework {
namespace details {

std::unique_ptr<ir::Graph> MemoryOptimizePass::ApplyImpl(
    std::unique_ptr<ir::Graph> graph) const {
  auto nodes = graph->Nodes();
  CollectSkipVarsSet(nodes);

  cfg_.reset(new details::ControlFlowGraph(*graph));
  cfg_->LiveVariableAnalysis();
  InitSSAGraphNodes();

  int reuse_id = 0;
  for (size_t idx = 0; idx < cfg_->Ops().size(); ++idx) {
    auto& op = cfg_->Ops()[idx];
    auto* op_desc = op->Op();
    // some op in graph has no op desc
    if (op_desc == nullptr) continue;
    if (OpHasSubBlock(op_desc)) {
      if (FLAGS_enable_subgraph_optimize) {
        SubGraphOptimize(op_desc);
      } else {
        VLOG(3) << op->Name()
                << " has subblock, but disable subgraph optimize. skipped.";
        continue;
      }
    }

    for (auto& var : op->outputs) {
      if (var->IsVar() && !var->IsCtrlVar() && skip_set_.count(var->Name())) {
        VLOG(3) << "Skip set contains variable of " << var->Name()
                << "disable reuse on it. skipped";
        continue;
      }
      if (NodeCanReused(var) && cfg_->Use(op).count(var->Name()) == 0) {
        ir::Node* cache = pool_.FindBestFitNode(var);
        while (cache != nullptr && var->Name() == cache->Name()) {
          VLOG(3) << "The same cache variable is cascade reused. "
                  << cache->Name() << " is re-filled to the pool after "
                  << "the reused op is finished. Current op can not "
                  << "replace it again. Skip this candidate.";
          cache = pool_.FindNextBestFitNode(var, cache);
        }
        if (var->Name() == FLAGS_memory_optimize_debug) {
          VLOG(3) << "start match var " << DebugString(var) << " of op "
                  << op->Name();
          VLOG(3) << pool_.ToString();
          VLOG(3) << "matched in pool : "
                  << ((cache == nullptr) ? "False" : "True");
        }

        if (cache != nullptr) {
          int node_idx_in_pool = pool_.GetNodeIndexInPool(cache);
          VLOG(3) << string::Sprintf(
              "!!! %s,  %s => %s, cache idx %d, pool size %d",
              std::to_string(reuse_id++), DebugString(var), DebugString(cache),
              node_idx_in_pool, static_cast<int>(pool_.size()));
          // NOTE(dzhwinter): update the ProgramDesc/IR Graph
          // and the CFG Graph on the fly.
          //
          // IR Graph define the dependence relationship between nodes.
          //
          // ProgramDesc defines the input/output vars. Its used in
          // CreateOp, CreateVar when running happens.
          //
          // CFG Graph store the liveness information, when reuse happens
          // we also need to update the variable liveness.
          const std::string var_name = var->Name();
          const std::string cache_name = cache->Name();

          cfg_->RenameVarInCFGGraph(var_name, cache_name, idx);
          RenameVarInGraphDesc(var_name, cache_name, idx);
          RenameVarInGraphNode(var_name, cache_name, idx, graph.get());
          pool_.Erase(cache_name);
        }
      }
    }
    // fill the pool
    for (auto var : cfg_->LiveIn(op)) {
      if (cfg_->LiveOut(op).count(var) == 0) {
        ir::Node* var_node = cfg_->GetNodeByName(var, op);
        if (var_node == nullptr || var_node->IsCtrlVar()) continue;
        if (NodeCanReused(var_node) && !pool_.Has(var_node)) {
          pool_.Insert(var_node);
        }
      }
    }
  }
  graph->ResolveHazard(var_nodes_);

  return graph;
}

void MemoryOptimizePass::SubGraphOptimize(OpDesc* op_desc) const {
  // conditional block, while op and their grad op
  auto* sub_block_desc =
      AttrReader(op_desc->GetAttrMap()).Get<BlockDesc*>("sub_block");

  // create a mirror block to construct an IR Graph.
  ProgramDesc prog;
  auto* copy_block = prog.MutableBlock(0);
  for (auto* op : sub_block_desc->AllOps()) {
    auto* copy_op = copy_block->AppendOp();
    copy_op->CopyFrom(*op);
    copy_op->Flush();
  }

  for (auto* var : sub_block_desc->AllVars()) {
    auto* copy_var = copy_block->Var(var->Name());
    copy_var->SetDataType(var->GetDataType());
    // only lod tensor can be reused. So ignore the multiple dims case.
    copy_var->SetType(var->GetType());
    copy_var->SetShape(var->GetShape());
    copy_var->SetPersistable(var->Persistable());
  }

  ir::Graph sub_graph(prog);
  std::unordered_set<ir::Node*> sub_graph_all_ops;
  FilterVariables(sub_graph.Nodes(), [&](ir::Node* var) {
    // sub_graph_all_ops.emplace(var);
    if (var->IsVar() && !var->IsCtrlVar()) {
      sub_graph_all_ops.emplace(var);
    }
  });
  int sub_reuse_id = 0;
  // subgraph nodes is unordered, reuse need to follow the desc order.
  // find the right op node through the descs
  for (auto* sub_op_desc : sub_block_desc->AllOps()) {
    ir::Node* sub_op = nullptr;
    for (auto* node : sub_graph_all_ops) {
      if (node->Op() == sub_op_desc) {
        sub_op = node;
        break;
      }
    }
    PADDLE_ENFORCE(sub_op != nullptr);
    for (auto* var : sub_op->outputs) {
      if (NodeCanReused(var)) {
        ir::Node* cache = pool_.FindBestFitNode(var);
        if (cache != nullptr) {
          if (var->Var()->GetDataType() != cache->Var()->GetDataType()) {
            continue;
          }
          int node_idx_in_pool = pool_.GetNodeIndexInPool(cache);
          VLOG(3) << string::Sprintf(
              "!!! %s,  %s => %s, cache idx %d, pool size %d",
              std::to_string(sub_reuse_id++), DebugString(var),
              DebugString(cache), node_idx_in_pool,
              static_cast<int>(pool_.size()));
          // NOTE(dzh): subblock is not in IR graph. Modify the block_desc
          // immediately to make the subblock variable reuse strategy take
          // effect. Because it is a single op in graph. No need to
          // update the ir nodes.
          sub_op_desc->Rename(var->Name(), cache->Name());
          if (sub_op_desc->Block()->HasVar(var->Name())) {
            sub_op_desc->Block()->RemoveVar(var->Name());
          }
        }
      }
    }
  }
}

void MemoryOptimizePass::CollectSkipVarsSet(
    const std::unordered_set<ir::Node*>& nodes) const {
  auto update_skip_set = [&](OpDesc* op_desc) {
    auto inputs = op_desc->InputArgumentNames();
    auto outputs = op_desc->OutputArgumentNames();
    skip_set_.insert(inputs.begin(), inputs.end());
    skip_set_.insert(outputs.begin(), outputs.end());
  };
  for (auto& op : nodes) {
    if (!op->IsOp() || op->Op() == nullptr) continue;
    auto* op_desc = op->Op();
    // NOTE(dzhwinter):
    // current block can not reuse next level block vars.
    if (OpHasSubBlock(op_desc)) update_skip_set(op_desc);
    // NOTE(dzhwinter):
    // distributed ops input/output name need to
    // keep same bettwen trainer/pserver
    if (op_desc->Type() == "send") update_skip_set(op_desc);
    if (op_desc->Type() == "recv") update_skip_set(op_desc);
    if (op_desc->Type() == "prefetch") update_skip_set(op_desc);
  }
}

void MemoryOptimizePass::RenameVarInGraphDesc(const std::string& var,
                                              const std::string& cache_var,
                                              size_t idx) const {
  for (size_t i = idx; i < cfg_->Ops().size(); ++i) {
    auto* op = cfg_->Ops()[i];
    PADDLE_ENFORCE(op->IsOp() && op->Op());
    auto* op_desc = op->Op();
    op_desc->RenameInput(var, cache_var);
    op_desc->RenameOutput(var, cache_var);
    if (op_desc->Block()->HasVar(var)) op_desc->Block()->RemoveVar(var);
    op_desc->Flush();
  }
}

void MemoryOptimizePass::InitSSAGraphNodes() const {
  std::unordered_map<std::string, std::unordered_set<ir::Node*>> all_vars;
  if (var_nodes_.empty()) {
    for (auto* op : cfg_->Ops()) {
      for (auto* node : op->inputs) {
        if (all_vars[node->Name()].count(node) == 0) {
          all_vars[node->Name()].emplace(node);
          var_nodes_[node->Name()].emplace_back(node);
        }
      }
      for (auto* node : op->outputs) {
        if (all_vars[node->Name()].count(node) == 0) {
          all_vars[node->Name()].emplace(node);
          var_nodes_[node->Name()].emplace_back(node);
        }
      }
    }
  }
}

void MemoryOptimizePass::RenameVarInGraphNode(const std::string& var,
                                              const std::string& cache_var,
                                              size_t idx,
                                              ir::Graph* graph) const {
  // if replace happens, we need to create a newer version cache_var
  // but use the same dims/data_type with var.
  PADDLE_ENFORCE(var_nodes_[var].size() >= 1 &&
                 var_nodes_[var].at(0)->Var() != nullptr);
  std::unique_ptr<VarDesc> var_desc(new VarDesc(*var_nodes_[var].at(0)->Var()));
  var_desc->SetName(cache_var);

  for (size_t i = idx; i < cfg_->Ops().size(); ++i) {
    auto* op = cfg_->Ops()[i];

    // redirect the input to the latest version of cache_var
    for (auto* node : op->inputs) {
      if (node->Name() == var) {
        ir::Node* cache_node = var_nodes_[cache_var].back();

        // swap node to cache_node
        cache_node->outputs.insert(cache_node->outputs.end(),
                                   node->outputs.begin(), node->outputs.end());
        PADDLE_ENFORCE(node->inputs.size() == 1 && node->inputs[0]->IsOp());
        auto* prev_op = node->inputs[0];
        std::replace(prev_op->outputs.begin(), prev_op->outputs.end(), node,
                     cache_node);
        for (auto* next_op : node->outputs) {
          std::replace(next_op->inputs.begin(), next_op->inputs.end(), node,
                       cache_node);
        }

        // erase unused node
        auto& nodes = var_nodes_.at(var);
        nodes.erase(std::remove(nodes.begin(), nodes.end(), node), nodes.end());
        graph->RemoveNode(node);
      }
    }

    // if we need to rename the output,
    // always create a newer version of cache_var
    for (auto* node : op->outputs) {
      if (node->Name() == var) {
        ir::Node* cache_node = graph->CreateVarNode(var_desc.get());
        var_nodes_[cache_var].emplace_back(cache_node);

        // swap node to cache node
        cache_node->outputs.insert(cache_node->outputs.end(),
                                   node->outputs.begin(), node->outputs.end());
        cache_node->inputs.emplace_back(op);
        std::replace(op->outputs.begin(), op->outputs.end(), node, cache_node);
        for (auto* next_op : node->outputs) {
          std::replace(next_op->inputs.begin(), next_op->inputs.end(), node,
                       cache_node);
        }

        // erase unused node
        auto& nodes = var_nodes_.at(var);
        nodes.erase(std::remove(nodes.begin(), nodes.end(), node), nodes.end());
        graph->RemoveNode(node);
      }
    }
  }
}

}  // namespace details
}  // namespace framework
}  // namespace paddle

REGISTER_PASS(memory_optimize_pass,
              paddle::framework::details::MemoryOptimizePass)
    .RequireGraphAttr(paddle::framework::details::kAllOpDescs);
<commit_msg>fix default value. test=develop<commit_after>// Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "paddle/fluid/framework/details/memory_optimize_pass.h"
#include <algorithm>
#include <atomic>
#include <deque>
#include <fstream>
#include <iostream>
#include <iterator>
#include <memory>
#include <queue>
#include <sstream>
#include <string>
#include <type_traits>
#include <vector>
#include "gflags/gflags.h"
#include "paddle/fluid/framework/data_type.h"
#include "paddle/fluid/framework/ir/graph.h"
#include "paddle/fluid/framework/ir/graph_helper.h"

DEFINE_bool(enable_subgraph_optimize, false,
            "SubGraph also reuse global graph variables, it will reduce the "
            "memory occupation"
            "but a higher risk of memory reuse error. default disabled.");
DEFINE_string(memory_optimize_debug, "",
              "debug the operator output variable when do the variable reuse."
              "memory reuse pass."
              "only for debug, default disabled.");

namespace paddle {
namespace framework {
namespace details {

std::unique_ptr<ir::Graph> MemoryOptimizePass::ApplyImpl(
    std::unique_ptr<ir::Graph> graph) const {
  auto nodes = graph->Nodes();
  CollectSkipVarsSet(nodes);

  cfg_.reset(new details::ControlFlowGraph(*graph));
  cfg_->LiveVariableAnalysis();
  InitSSAGraphNodes();

  int reuse_id = 0;
  for (size_t idx = 0; idx < cfg_->Ops().size(); ++idx) {
    auto& op = cfg_->Ops()[idx];
    auto* op_desc = op->Op();
    // some op in graph has no op desc
    if (op_desc == nullptr) continue;
    if (OpHasSubBlock(op_desc)) {
      if (FLAGS_enable_subgraph_optimize) {
        SubGraphOptimize(op_desc);
      } else {
        VLOG(3) << op->Name()
                << " has subblock, but disable subgraph optimize. skipped.";
        continue;
      }
    }

    for (auto& var : op->outputs) {
      if (var->IsVar() && !var->IsCtrlVar() && skip_set_.count(var->Name())) {
        VLOG(3) << "Skip set contains variable of " << var->Name()
                << "disable reuse on it. skipped";
        continue;
      }
      if (NodeCanReused(var) && cfg_->Use(op).count(var->Name()) == 0) {
        ir::Node* cache = pool_.FindBestFitNode(var);
        while (cache != nullptr && var->Name() == cache->Name()) {
          VLOG(3) << "The same cache variable is cascade reused. "
                  << cache->Name() << " is re-filled to the pool after "
                  << "the reused op is finished. Current op can not "
                  << "replace it again. Skip this candidate.";
          cache = pool_.FindNextBestFitNode(var, cache);
        }
        if (var->Name() == FLAGS_memory_optimize_debug) {
          VLOG(3) << "start match var " << DebugString(var) << " of op "
                  << op->Name();
          VLOG(3) << pool_.ToString();
          VLOG(3) << "matched in pool : "
                  << ((cache == nullptr) ? "False" : "True");
        }

        if (cache != nullptr) {
          int node_idx_in_pool = pool_.GetNodeIndexInPool(cache);
          VLOG(3) << string::Sprintf(
              "!!! %s,  %s => %s, cache idx %d, pool size %d",
              std::to_string(reuse_id++), DebugString(var), DebugString(cache),
              node_idx_in_pool, static_cast<int>(pool_.size()));
          // NOTE(dzhwinter): update the ProgramDesc/IR Graph
          // and the CFG Graph on the fly.
          //
          // IR Graph define the dependence relationship between nodes.
          //
          // ProgramDesc defines the input/output vars. Its used in
          // CreateOp, CreateVar when running happens.
          //
          // CFG Graph store the liveness information, when reuse happens
          // we also need to update the variable liveness.
          const std::string var_name = var->Name();
          const std::string cache_name = cache->Name();

          cfg_->RenameVarInCFGGraph(var_name, cache_name, idx);
          RenameVarInGraphDesc(var_name, cache_name, idx);
          RenameVarInGraphNode(var_name, cache_name, idx, graph.get());
          pool_.Erase(cache_name);
        }
      }
    }
    // fill the pool
    for (auto var : cfg_->LiveIn(op)) {
      if (cfg_->LiveOut(op).count(var) == 0) {
        ir::Node* var_node = cfg_->GetNodeByName(var, op);
        if (var_node == nullptr || var_node->IsCtrlVar()) continue;
        if (NodeCanReused(var_node) && !pool_.Has(var_node)) {
          pool_.Insert(var_node);
        }
      }
    }
  }
  graph->ResolveHazard(var_nodes_);

  return graph;
}

void MemoryOptimizePass::SubGraphOptimize(OpDesc* op_desc) const {
  // conditional block, while op and their grad op
  auto* sub_block_desc =
      AttrReader(op_desc->GetAttrMap()).Get<BlockDesc*>("sub_block");

  // create a mirror block to construct an IR Graph.
  ProgramDesc prog;
  auto* copy_block = prog.MutableBlock(0);
  for (auto* op : sub_block_desc->AllOps()) {
    auto* copy_op = copy_block->AppendOp();
    copy_op->CopyFrom(*op);
    copy_op->Flush();
  }

  for (auto* var : sub_block_desc->AllVars()) {
    auto* copy_var = copy_block->Var(var->Name());
    copy_var->SetDataType(var->GetDataType());
    // only lod tensor can be reused. So ignore the multiple dims case.
    copy_var->SetType(var->GetType());
    copy_var->SetShape(var->GetShape());
    copy_var->SetPersistable(var->Persistable());
  }

  ir::Graph sub_graph(prog);
  std::unordered_set<ir::Node*> sub_graph_all_ops;
  FilterVariables(sub_graph.Nodes(), [&](ir::Node* var) {
    // sub_graph_all_ops.emplace(var);
    if (var->IsVar() && !var->IsCtrlVar()) {
      sub_graph_all_ops.emplace(var);
    }
  });
  int sub_reuse_id = 0;
  // subgraph nodes is unordered, reuse need to follow the desc order.
  // find the right op node through the descs
  for (auto* sub_op_desc : sub_block_desc->AllOps()) {
    ir::Node* sub_op = nullptr;
    for (auto* node : sub_graph_all_ops) {
      if (node->Op() == sub_op_desc) {
        sub_op = node;
        break;
      }
    }
    PADDLE_ENFORCE(sub_op != nullptr);
    for (auto* var : sub_op->outputs) {
      if (NodeCanReused(var)) {
        ir::Node* cache = pool_.FindBestFitNode(var);
        if (cache != nullptr) {
          if (var->Var()->GetDataType() != cache->Var()->GetDataType()) {
            continue;
          }
          int node_idx_in_pool = pool_.GetNodeIndexInPool(cache);
          VLOG(3) << string::Sprintf(
              "!!! %s,  %s => %s, cache idx %d, pool size %d",
              std::to_string(sub_reuse_id++), DebugString(var),
              DebugString(cache), node_idx_in_pool,
              static_cast<int>(pool_.size()));
          // NOTE(dzh): subblock is not in IR graph. Modify the block_desc
          // immediately to make the subblock variable reuse strategy take
          // effect. Because it is a single op in graph. No need to
          // update the ir nodes.
          sub_op_desc->Rename(var->Name(), cache->Name());
          if (sub_op_desc->Block()->HasVar(var->Name())) {
            sub_op_desc->Block()->RemoveVar(var->Name());
          }
        }
      }
    }
  }
}

void MemoryOptimizePass::CollectSkipVarsSet(
    const std::unordered_set<ir::Node*>& nodes) const {
  auto update_skip_set = [&](OpDesc* op_desc) {
    auto inputs = op_desc->InputArgumentNames();
    auto outputs = op_desc->OutputArgumentNames();
    skip_set_.insert(inputs.begin(), inputs.end());
    skip_set_.insert(outputs.begin(), outputs.end());
  };
  for (auto& op : nodes) {
    if (!op->IsOp() || op->Op() == nullptr) continue;
    auto* op_desc = op->Op();
    // NOTE(dzhwinter):
    // current block can not reuse next level block vars.
    if (OpHasSubBlock(op_desc)) update_skip_set(op_desc);
    // NOTE(dzhwinter):
    // distributed ops input/output name need to
    // keep same bettwen trainer/pserver
    if (op_desc->Type() == "send") update_skip_set(op_desc);
    if (op_desc->Type() == "recv") update_skip_set(op_desc);
    if (op_desc->Type() == "prefetch") update_skip_set(op_desc);
  }
}

void MemoryOptimizePass::RenameVarInGraphDesc(const std::string& var,
                                              const std::string& cache_var,
                                              size_t idx) const {
  for (size_t i = idx; i < cfg_->Ops().size(); ++i) {
    auto* op = cfg_->Ops()[i];
    PADDLE_ENFORCE(op->IsOp() && op->Op());
    auto* op_desc = op->Op();
    op_desc->RenameInput(var, cache_var);
    op_desc->RenameOutput(var, cache_var);
    if (op_desc->Block() != nullptr && op_desc->Block()->HasVar(var)) {
      op_desc->Block()->RemoveVar(var);
    }
    op_desc->Flush();
  }
}

void MemoryOptimizePass::InitSSAGraphNodes() const {
  std::unordered_map<std::string, std::unordered_set<ir::Node*>> all_vars;
  if (var_nodes_.empty()) {
    for (auto* op : cfg_->Ops()) {
      for (auto* node : op->inputs) {
        if (all_vars[node->Name()].count(node) == 0) {
          all_vars[node->Name()].emplace(node);
          var_nodes_[node->Name()].emplace_back(node);
        }
      }
      for (auto* node : op->outputs) {
        if (all_vars[node->Name()].count(node) == 0) {
          all_vars[node->Name()].emplace(node);
          var_nodes_[node->Name()].emplace_back(node);
        }
      }
    }
  }
}

void MemoryOptimizePass::RenameVarInGraphNode(const std::string& var,
                                              const std::string& cache_var,
                                              size_t idx,
                                              ir::Graph* graph) const {
  // if replace happens, we need to create a newer version cache_var
  // but use the same dims/data_type with var.
  PADDLE_ENFORCE(var_nodes_[var].size() >= 1 &&
                 var_nodes_[var].at(0)->Var() != nullptr);
  std::unique_ptr<VarDesc> var_desc(new VarDesc(*var_nodes_[var].at(0)->Var()));
  var_desc->SetName(cache_var);

  for (size_t i = idx; i < cfg_->Ops().size(); ++i) {
    auto* op = cfg_->Ops()[i];

    // redirect the input to the latest version of cache_var
    for (auto* node : op->inputs) {
      if (node->Name() == var) {
        ir::Node* cache_node = var_nodes_[cache_var].back();

        // swap node to cache_node
        cache_node->outputs.insert(cache_node->outputs.end(),
                                   node->outputs.begin(), node->outputs.end());
        PADDLE_ENFORCE(node->inputs.size() == 1 && node->inputs[0]->IsOp());
        auto* prev_op = node->inputs[0];
        std::replace(prev_op->outputs.begin(), prev_op->outputs.end(), node,
                     cache_node);
        for (auto* next_op : node->outputs) {
          std::replace(next_op->inputs.begin(), next_op->inputs.end(), node,
                       cache_node);
        }

        // erase unused node
        auto& nodes = var_nodes_.at(var);
        nodes.erase(std::remove(nodes.begin(), nodes.end(), node), nodes.end());
        graph->RemoveNode(node);
      }
    }

    // if we need to rename the output,
    // always create a newer version of cache_var
    for (auto* node : op->outputs) {
      if (node->Name() == var) {
        ir::Node* cache_node = graph->CreateVarNode(var_desc.get());
        var_nodes_[cache_var].emplace_back(cache_node);

        // swap node to cache node
        cache_node->outputs.insert(cache_node->outputs.end(),
                                   node->outputs.begin(), node->outputs.end());
        cache_node->inputs.emplace_back(op);
        std::replace(op->outputs.begin(), op->outputs.end(), node, cache_node);
        for (auto* next_op : node->outputs) {
          std::replace(next_op->inputs.begin(), next_op->inputs.end(), node,
                       cache_node);
        }

        // erase unused node
        auto& nodes = var_nodes_.at(var);
        nodes.erase(std::remove(nodes.begin(), nodes.end(), node), nodes.end());
        graph->RemoveNode(node);
      }
    }
  }
}

}  // namespace details
}  // namespace framework
}  // namespace paddle

REGISTER_PASS(memory_optimize_pass,
              paddle::framework::details::MemoryOptimizePass)
    .RequireGraphAttr(paddle::framework::details::kAllOpDescs);
<|endoftext|>


<commit_before>#include <cstring>
#include <errno.h>
#include <iostream>
#include <ncurses.h>
#include <sstream>
#include <sys/utsname.h>

#include "cache.h"
#include "cliargsparser.h"
#include "config.h"
#include "configpaths.h"
#include "controller.h"
#include "dbexception.h"
#include "exception.h"
#include "matcherexception.h"
#include "rss/parser.h"
#include "utils.h"
#include "view.h"
#include "xlicense.h"

extern "C" {
	void rs_setup_human_panic(void);
}

using namespace newsboat;

void print_usage(const std::string& argv0, const std::string& config_path,
	const std::string& urls_path, const std::string& cache_path)
{
	auto msg = strprintf::fmt(
			_("%s %s\nusage: %s [-i <file>|-e] [-u <urlfile>] "
				"[-c <cachefile>] [-x <command> ...] [-h]\n"),
			PROGRAM_NAME,
			utils::program_version(),
			argv0);
	std::cout << msg;

	struct arg {
		const char name;
		const std::string longname;
		const std::string params;
		const std::string desc;
	};

	static const std::vector<arg> args = {
		{'e', "export-to-opml", "", _s("export OPML feed to stdout")},
		{'r', "refresh-on-start", "", _s("refresh feeds on start")},
		{'i', "import-from-opml", _s("<file>"), _s("import OPML file")},
		{
			'u',
			"url-file",
			_s("<urlfile>"),
			_s("read RSS feed URLs from <urlfile>")
		},
		{
			'c',
			"cache-file",
			_s("<cachefile>"),
			_s("use <cachefile> as cache file")
		},
		{
			'C',
			"config-file",
			_s("<configfile>"),
			_s("read configuration from <configfile>")
		},
		{'X', "vacuum", "", _s("compact the cache")},
		{
			'x',
			"execute",
			_s("<command>..."),
			_s("execute list of commands")
		},
		{'q', "quiet", "", _s("quiet startup")},
		{'v', "version", "", _s("get version information")},
		{
			'l',
			"log-level",
			_s("<loglevel>"),
			_s("write a log with a certain loglevel (valid values: "
				"1 to "
				"6)")
		},
		{
			'd',
			"log-file",
			_s("<logfile>"),
			_s("use <logfile> as output log file")
		},
		{
			'E',
			"export-to-file",
			_s("<file>"),
			_s("export list of read articles to <file>")
		},
		{
			'I',
			"import-from-file",
			_s("<file>"),
			_s("import list of read articles from <file>")
		},
		{'h', "help", "", _s("this help")}
	};

	std::stringstream ss;
	for (const auto& a : args) {
		std::string longcolumn("-");
		longcolumn += a.name;
		longcolumn += ", --" + a.longname;
		longcolumn += a.params.size() > 0 ? "=" + a.params : "";
		ss << "\t" << longcolumn;
		for (unsigned int j = 0; j < utils::gentabs(longcolumn); j++) {
			ss << "\t";
		}
		ss << a.desc << std::endl;
	}
	std::cout << ss.str();

	std::cout << '\n';

	std::cout << _("Files:") << '\n';
	/// This is printed out by --help before the path to the config file
	const std::string tr_config = _("configuration");
	/// This is printed out by --help before the path to the urls file
	const std::string tr_urls = _("feed URLs");
	/// This is printed out by --help before the path to the cache file
	const std::string tr_cache = _("cache");
	const auto widest = std::max({tr_config.length(), tr_urls.length(), tr_cache.length()});

	const auto print_filepath = [widest](const std::string& name,
	const std::string& value) {
		std::cout << "\t- " << name << ":  " << std::string(
				widest - name.length(), ' ') << value << '\n';
	};

	print_filepath(tr_config, config_path);
	print_filepath(tr_urls, urls_path);
	print_filepath(tr_cache, cache_path);
}

void print_version(const std::string& argv0, unsigned int level)
{
	if (level <= 1) {
		std::stringstream ss;
		ss << PROGRAM_NAME << " " << utils::program_version() << " - "
			<< PROGRAM_URL << std::endl;
		ss << "Copyright (C) 2006-2015 Andreas Krennmair"
			<< std::endl;
		ss << "Copyright (C) 2015-2020 Alexander Batischev"
			<< std::endl;
		ss << "Copyright (C) 2006-2017 Newsbeuter contributors"
			<< std::endl;
		ss << "Copyright (C) 2017-2020 Newsboat contributors"
			<< std::endl;
		ss << std::endl;

		ss << strprintf::fmt(
				_("Newsboat is free software licensed "
					"under the MIT License. (Type `%s -vv' "
					"to see the full text.)"),
				argv0)
			<< std::endl;
		ss << _("It bundles:") << std::endl;
		ss << _("- JSON for Modern C++ library, licensed under the MIT License: "
				"https://github.com/nlohmann/json")
			<< std::endl;
		ss << _("- optional-lite library, licensed under the Boost Software "
				"License: https://github.com/martinmoene/optional-lite")
			<< std::endl;
		ss << std::endl;

		struct utsname xuts;
		uname(&xuts);
		ss << PROGRAM_NAME << " " << utils::program_version()
			<< std::endl;
		ss << "System: " << xuts.sysname << " " << xuts.release
			<< " (" << xuts.machine << ")" << std::endl;
#if defined(__GNUC__) && defined(__VERSION__)
		ss << "Compiler: g++ " << __VERSION__ << std::endl;
#endif
		ss << "ncurses: " << curses_version()
			<< " (compiled with " << NCURSES_VERSION << ")"
			<< std::endl;
		ss << "libcurl: " << curl_version() << " (compiled with "
			<< LIBCURL_VERSION << ")" << std::endl;
		ss << "SQLite: " << sqlite3_libversion()
			<< " (compiled with " << SQLITE_VERSION << ")"
			<< std::endl;
		ss << "libxml2: compiled with " << LIBXML_DOTTED_VERSION
			<< std::endl
			<< std::endl;
		std::cout << ss.str();
	} else {
		std::cout << LICENSE_str << std::endl;
	}
}

int main(int argc, char* argv[])
{
	rs_setup_human_panic();
	utils::initialize_ssl_implementation();

	setlocale(LC_CTYPE, "");
	setlocale(LC_MESSAGES, "");

	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	rsspp::Parser::global_init();

	ConfigPaths configpaths;
	if (!configpaths.initialized()) {
		std::cerr << configpaths.error_message() << std::endl;
		return EXIT_FAILURE;
	}

	Controller c(configpaths);
	newsboat::View v(&c);
	c.set_view(&v);
	CliArgsParser args(argc, argv);

	configpaths.process_args(args);

	if (args.should_print_usage()) {
		print_usage(args.program_name(), configpaths.config_file(),
			configpaths.url_file(), configpaths.cache_file());
		if (args.return_code().has_value()) {
			return args.return_code().value();
		}
	} else if (args.show_version()) {
		print_version(args.program_name(), args.show_version());
		return EXIT_SUCCESS;
	}

	int ret;
	try {
		ret = c.run(args);
	} catch (const newsboat::DbException& e) {
		std::cerr << strprintf::fmt(
				_("Caught newsboat::DbException with "
					"message: %s"),
				e.what())
			<< std::endl;
		::exit(EXIT_FAILURE);
	} catch (const newsboat::MatcherException& e) {
		std::cerr << strprintf::fmt(
				_("Caught newsboat::MatcherException with "
					"message: %s"),
				e.what())
			<< std::endl;
		::exit(EXIT_FAILURE);
	} catch (const newsboat::Exception& e) {
		std::cerr << strprintf::fmt(_("Caught newsboat::Exception with "
					"message: %s"),
				e.what())
			<< std::endl;
		::exit(EXIT_FAILURE);
	}

	rsspp::Parser::global_cleanup();

	return ret;
}
<commit_msg>Mention expected-lite in --help<commit_after>#include <cstring>
#include <errno.h>
#include <iostream>
#include <ncurses.h>
#include <sstream>
#include <sys/utsname.h>

#include "cache.h"
#include "cliargsparser.h"
#include "config.h"
#include "configpaths.h"
#include "controller.h"
#include "dbexception.h"
#include "exception.h"
#include "matcherexception.h"
#include "rss/parser.h"
#include "utils.h"
#include "view.h"
#include "xlicense.h"

extern "C" {
	void rs_setup_human_panic(void);
}

using namespace newsboat;

void print_usage(const std::string& argv0, const std::string& config_path,
	const std::string& urls_path, const std::string& cache_path)
{
	auto msg = strprintf::fmt(
			_("%s %s\nusage: %s [-i <file>|-e] [-u <urlfile>] "
				"[-c <cachefile>] [-x <command> ...] [-h]\n"),
			PROGRAM_NAME,
			utils::program_version(),
			argv0);
	std::cout << msg;

	struct arg {
		const char name;
		const std::string longname;
		const std::string params;
		const std::string desc;
	};

	static const std::vector<arg> args = {
		{'e', "export-to-opml", "", _s("export OPML feed to stdout")},
		{'r', "refresh-on-start", "", _s("refresh feeds on start")},
		{'i', "import-from-opml", _s("<file>"), _s("import OPML file")},
		{
			'u',
			"url-file",
			_s("<urlfile>"),
			_s("read RSS feed URLs from <urlfile>")
		},
		{
			'c',
			"cache-file",
			_s("<cachefile>"),
			_s("use <cachefile> as cache file")
		},
		{
			'C',
			"config-file",
			_s("<configfile>"),
			_s("read configuration from <configfile>")
		},
		{'X', "vacuum", "", _s("compact the cache")},
		{
			'x',
			"execute",
			_s("<command>..."),
			_s("execute list of commands")
		},
		{'q', "quiet", "", _s("quiet startup")},
		{'v', "version", "", _s("get version information")},
		{
			'l',
			"log-level",
			_s("<loglevel>"),
			_s("write a log with a certain loglevel (valid values: "
				"1 to "
				"6)")
		},
		{
			'd',
			"log-file",
			_s("<logfile>"),
			_s("use <logfile> as output log file")
		},
		{
			'E',
			"export-to-file",
			_s("<file>"),
			_s("export list of read articles to <file>")
		},
		{
			'I',
			"import-from-file",
			_s("<file>"),
			_s("import list of read articles from <file>")
		},
		{'h', "help", "", _s("this help")}
	};

	std::stringstream ss;
	for (const auto& a : args) {
		std::string longcolumn("-");
		longcolumn += a.name;
		longcolumn += ", --" + a.longname;
		longcolumn += a.params.size() > 0 ? "=" + a.params : "";
		ss << "\t" << longcolumn;
		for (unsigned int j = 0; j < utils::gentabs(longcolumn); j++) {
			ss << "\t";
		}
		ss << a.desc << std::endl;
	}
	std::cout << ss.str();

	std::cout << '\n';

	std::cout << _("Files:") << '\n';
	/// This is printed out by --help before the path to the config file
	const std::string tr_config = _("configuration");
	/// This is printed out by --help before the path to the urls file
	const std::string tr_urls = _("feed URLs");
	/// This is printed out by --help before the path to the cache file
	const std::string tr_cache = _("cache");
	const auto widest = std::max({tr_config.length(), tr_urls.length(), tr_cache.length()});

	const auto print_filepath = [widest](const std::string& name,
	const std::string& value) {
		std::cout << "\t- " << name << ":  " << std::string(
				widest - name.length(), ' ') << value << '\n';
	};

	print_filepath(tr_config, config_path);
	print_filepath(tr_urls, urls_path);
	print_filepath(tr_cache, cache_path);
}

void print_version(const std::string& argv0, unsigned int level)
{
	if (level <= 1) {
		std::stringstream ss;
		ss << PROGRAM_NAME << " " << utils::program_version() << " - "
			<< PROGRAM_URL << std::endl;
		ss << "Copyright (C) 2006-2015 Andreas Krennmair"
			<< std::endl;
		ss << "Copyright (C) 2015-2020 Alexander Batischev"
			<< std::endl;
		ss << "Copyright (C) 2006-2017 Newsbeuter contributors"
			<< std::endl;
		ss << "Copyright (C) 2017-2020 Newsboat contributors"
			<< std::endl;
		ss << std::endl;

		ss << strprintf::fmt(
				_("Newsboat is free software licensed "
					"under the MIT License. (Type `%s -vv' "
					"to see the full text.)"),
				argv0)
			<< std::endl;
		ss << _("It bundles:") << std::endl;
		ss << _("- JSON for Modern C++ library, licensed under the MIT License: "
				"https://github.com/nlohmann/json")
			<< std::endl;
		ss << _("- optional-lite library, licensed under the Boost Software "
				"License: https://github.com/martinmoene/optional-lite")
			<< std::endl;
		ss << _("- expected-lite library, licensed under the Boost Software "
				"License: https://github.com/martinmoene/expected-lite")
			<< std::endl;
		ss << std::endl;

		struct utsname xuts;
		uname(&xuts);
		ss << PROGRAM_NAME << " " << utils::program_version()
			<< std::endl;
		ss << "System: " << xuts.sysname << " " << xuts.release
			<< " (" << xuts.machine << ")" << std::endl;
#if defined(__GNUC__) && defined(__VERSION__)
		ss << "Compiler: g++ " << __VERSION__ << std::endl;
#endif
		ss << "ncurses: " << curses_version()
			<< " (compiled with " << NCURSES_VERSION << ")"
			<< std::endl;
		ss << "libcurl: " << curl_version() << " (compiled with "
			<< LIBCURL_VERSION << ")" << std::endl;
		ss << "SQLite: " << sqlite3_libversion()
			<< " (compiled with " << SQLITE_VERSION << ")"
			<< std::endl;
		ss << "libxml2: compiled with " << LIBXML_DOTTED_VERSION
			<< std::endl
			<< std::endl;
		std::cout << ss.str();
	} else {
		std::cout << LICENSE_str << std::endl;
	}
}

int main(int argc, char* argv[])
{
	rs_setup_human_panic();
	utils::initialize_ssl_implementation();

	setlocale(LC_CTYPE, "");
	setlocale(LC_MESSAGES, "");

	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	rsspp::Parser::global_init();

	ConfigPaths configpaths;
	if (!configpaths.initialized()) {
		std::cerr << configpaths.error_message() << std::endl;
		return EXIT_FAILURE;
	}

	Controller c(configpaths);
	newsboat::View v(&c);
	c.set_view(&v);
	CliArgsParser args(argc, argv);

	configpaths.process_args(args);

	if (args.should_print_usage()) {
		print_usage(args.program_name(), configpaths.config_file(),
			configpaths.url_file(), configpaths.cache_file());
		if (args.return_code().has_value()) {
			return args.return_code().value();
		}
	} else if (args.show_version()) {
		print_version(args.program_name(), args.show_version());
		return EXIT_SUCCESS;
	}

	int ret;
	try {
		ret = c.run(args);
	} catch (const newsboat::DbException& e) {
		std::cerr << strprintf::fmt(
				_("Caught newsboat::DbException with "
					"message: %s"),
				e.what())
			<< std::endl;
		::exit(EXIT_FAILURE);
	} catch (const newsboat::MatcherException& e) {
		std::cerr << strprintf::fmt(
				_("Caught newsboat::MatcherException with "
					"message: %s"),
				e.what())
			<< std::endl;
		::exit(EXIT_FAILURE);
	} catch (const newsboat::Exception& e) {
		std::cerr << strprintf::fmt(_("Caught newsboat::Exception with "
					"message: %s"),
				e.what())
			<< std::endl;
		::exit(EXIT_FAILURE);
	}

	rsspp::Parser::global_cleanup();

	return ret;
}
<|endoftext|>