<commit_before>/*
    knaccountmanager.cpp

    KNode, the KDE newsreader
    Copyright (c) 1999-2001 the KNode authors.
    See file AUTHORS for details

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, US
*/

#include <stdlib.h>

#include <qdir.h>

#include <kdebug.h>
#include <ksimpleconfig.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>

#include "kngroupmanager.h"
#include "knnntpaccount.h"
#include "kncollectionviewitem.h"
#include "knglobals.h"
#include "knconfigmanager.h"
#include "utilities.h"
#include "knaccountmanager.h"
#include "knfoldermanager.h"

KNAccountManager::KNAccountManager(KNGroupManager *gm, KNListView *v, QObject * parent, const char * name)
  : QObject(parent, name), gManager(gm), c_urrentAccount(0), view(v)
{
  accList=new QPtrList<KNNntpAccount>;
  accList->setAutoDelete(true);
  s_mtp=new KNServerInfo();
  s_mtp->setType(KNServerInfo::STsmtp);
  s_mtp->setId(0);
  KConfig *conf=knGlobals.config();
  conf->setGroup("MAILSERVER");
  s_mtp->readConf(conf);

  loadAccounts();
}

KNAccountManager::~KNAccountManager()
{
  delete accList;
  delete s_mtp;
}

void KNAccountManager::prepareShutdown()
{
  for(KNNntpAccount *a=accList->first(); a; a=accList->next())
    a->saveInfo();
}

void KNAccountManager::loadAccounts()
{
  QString dir(locateLocal("data","knode/"));
  if (dir.isNull()) {
    KNHelper::displayInternalFileError();
    return;
  }
  QDir d(dir);
  KNNntpAccount *a;
  QPixmap pm=knGlobals.cfgManager->appearance()->icon(KNConfig::Appearance::nntp);
  QStringList entries(d.entryList("nntp.*", QDir::Dirs));

  QStringList::Iterator it;
  for(it = entries.begin(); it != entries.end(); it++) {
    a=new KNNntpAccount();
    if (a->readInfo(dir+(*it)+"/info")) {
      accList->append(a);
      KNCollectionViewItem* cvit=new KNCollectionViewItem(view);
      a->setListItem(cvit);
      cvit->setPixmap(0, pm);
      gManager->loadGroups(a);
      cvit->setOpen(a->wasOpen());
    } else {
      delete a;
      kdError(5003) << "Unable to load account " << (*it) << "!" << endl;
    }
  }
}

KNNntpAccount* KNAccountManager::account(int i)
{
  KNNntpAccount *ret=0;
  if(i>0)
  {
    for(KNNntpAccount *a=accList->first(); a; a=accList->next()) {
      if(a->id()==i) {
        ret=a;
        break;
      }
    }
  }
  return ret;
}

void KNAccountManager::setCurrentAccount(KNNntpAccount *a)
{
  c_urrentAccount=a;
}

// a is new account allocated and configured by the caller
bool KNAccountManager::newAccount(KNNntpAccount *a)
{
  // find a unused id for the new account...
  QString dir(locateLocal("data","knode/"));
  if (dir.isNull()) {
    delete a;
    KNHelper::displayInternalFileError();
    return false;
  }
  QDir d(dir);
  QStringList entries(d.entryList("nntp.*", QDir::Dirs));

  int id = 1;
  while (entries.findIndex(QString("nntp.%1").arg(id))!=-1)
    ++id;

  a->setId(id);

  dir = locateLocal("data","knode/") + QString("nntp.%1/").arg(a->id());
  if (!dir.isNull()) {
    accList->append(a);
    KNCollectionViewItem *it = new KNCollectionViewItem(view);
    it->setPixmap(0, knGlobals.cfgManager->appearance()->icon(KNConfig::Appearance::nntp));
    a->setListItem(it);
    emit(accountAdded(a));
    return true;
  } else {
    delete a;
    KMessageBox::error(knGlobals.topWidget, i18n("Cannot create a folder for this account!"));
    return false;
  }
}

// a==0: remove current account
bool KNAccountManager::removeAccount(KNNntpAccount *a)
{
  if(!a) a=c_urrentAccount;
  if(!a) return false;

  QPtrList<KNGroup> *lst;
  if(knGlobals.folManager->unsentForAccount(a->id()) > 0) {
    KMessageBox::sorry(knGlobals.topWidget, i18n("This account cannot be deleted since there are some unsent messages for it."));
  }
  else if(KMessageBox::questionYesNo(knGlobals.topWidget, i18n("Do you really want to delete this account?"))==KMessageBox::Yes) {
    lst=new QPtrList<KNGroup>;
    lst->setAutoDelete(false);
    gManager->getGroupsOfAccount(a, lst);
    for(KNGroup *g=lst->first(); g; g=lst->next()) {
      if(g->isLocked()) {
        KMessageBox::sorry(knGlobals.topWidget, i18n("At least one group of this account is currently in use.\nThe account cannot be deleted at the moment."));
        return false;
      }
    }
    for(KNGroup *g=lst->first(); g; g=lst->next())
      gManager->unsubscribeGroup(g);
    delete lst;

    QDir dir(a->path());
    if (dir.exists()) {
      const QFileInfoList *list = dir.entryInfoList();  // get list of matching files and delete all
      if (list) {
        QFileInfoListIterator it( *list );
        while (it.current()) {
          dir.remove(it.current()->fileName());
          ++it;
        }
      }
      dir.cdUp();                                       // directory should now be empty, deleting it
      dir.rmdir(QString("nntp.%1/").arg(a->id()));
    }

    if(c_urrentAccount==a) setCurrentAccount(0);

    emit(accountRemoved(a));
    accList->removeRef(a);      // finally delete a
    return true;
  }

  return false;
}

void KNAccountManager::editProperties(KNNntpAccount *a)
{
  if(!a) a=c_urrentAccount;
  if(!a) return;

  a->editProperties(knGlobals.topWidget);
  emit(accountModified(a));
}

void KNAccountManager::accountRenamed(KNNntpAccount *a)
{
  if(!a) a=c_urrentAccount;
  if(!a) return;

  emit(accountModified(a));
}

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

#include "knaccountmanager.moc"
<commit_msg>One more wrong locateLocal... I thought I had fixed all of them. Oh well :-/<commit_after>/*
    knaccountmanager.cpp

    KNode, the KDE newsreader
    Copyright (c) 1999-2001 the KNode authors.
    See file AUTHORS for details

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software Foundation,
    Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, US
*/

#include <stdlib.h>

#include <qdir.h>

#include <kdebug.h>
#include <ksimpleconfig.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>

#include "kngroupmanager.h"
#include "knnntpaccount.h"
#include "kncollectionviewitem.h"
#include "knglobals.h"
#include "knconfigmanager.h"
#include "utilities.h"
#include "knaccountmanager.h"
#include "knfoldermanager.h"

KNAccountManager::KNAccountManager(KNGroupManager *gm, KNListView *v, QObject * parent, const char * name)
  : QObject(parent, name), gManager(gm), c_urrentAccount(0), view(v)
{
  accList=new QPtrList<KNNntpAccount>;
  accList->setAutoDelete(true);
  s_mtp=new KNServerInfo();
  s_mtp->setType(KNServerInfo::STsmtp);
  s_mtp->setId(0);
  KConfig *conf=knGlobals.config();
  conf->setGroup("MAILSERVER");
  s_mtp->readConf(conf);

  loadAccounts();
}

KNAccountManager::~KNAccountManager()
{
  delete accList;
  delete s_mtp;
}

void KNAccountManager::prepareShutdown()
{
  for(KNNntpAccount *a=accList->first(); a; a=accList->next())
    a->saveInfo();
}

void KNAccountManager::loadAccounts()
{
  QString dir(locateLocal("data","knode/"));
  if (dir.isNull()) {
    KNHelper::displayInternalFileError();
    return;
  }
  QDir d(dir);
  KNNntpAccount *a;
  QPixmap pm=knGlobals.cfgManager->appearance()->icon(KNConfig::Appearance::nntp);
  QStringList entries(d.entryList("nntp.*", QDir::Dirs));

  QStringList::Iterator it;
  for(it = entries.begin(); it != entries.end(); it++) {
    a=new KNNntpAccount();
    if (a->readInfo(dir+(*it)+"/info")) {
      accList->append(a);
      KNCollectionViewItem* cvit=new KNCollectionViewItem(view);
      a->setListItem(cvit);
      cvit->setPixmap(0, pm);
      gManager->loadGroups(a);
      cvit->setOpen(a->wasOpen());
    } else {
      delete a;
      kdError(5003) << "Unable to load account " << (*it) << "!" << endl;
    }
  }
}

KNNntpAccount* KNAccountManager::account(int i)
{
  KNNntpAccount *ret=0;
  if(i>0)
  {
    for(KNNntpAccount *a=accList->first(); a; a=accList->next()) {
      if(a->id()==i) {
        ret=a;
        break;
      }
    }
  }
  return ret;
}

void KNAccountManager::setCurrentAccount(KNNntpAccount *a)
{
  c_urrentAccount=a;
}

// a is new account allocated and configured by the caller
bool KNAccountManager::newAccount(KNNntpAccount *a)
{
  // find a unused id for the new account...
  QString dir(locateLocal("data","knode/"));
  if (dir.isNull()) {
    delete a;
    KNHelper::displayInternalFileError();
    return false;
  }
  QDir d(dir);
  QStringList entries(d.entryList("nntp.*", QDir::Dirs));

  int id = 1;
  while (entries.findIndex(QString("nntp.%1").arg(id))!=-1)
    ++id;

  a->setId(id);

  dir = locateLocal("data",QString("knode/nntp.%1/").arg(a->id()));
  if (!dir.isNull()) {
    accList->append(a);
    KNCollectionViewItem *it = new KNCollectionViewItem(view);
    it->setPixmap(0, knGlobals.cfgManager->appearance()->icon(KNConfig::Appearance::nntp));
    a->setListItem(it);
    emit(accountAdded(a));
    return true;
  } else {
    delete a;
    KMessageBox::error(knGlobals.topWidget, i18n("Cannot create a folder for this account!"));
    return false;
  }
}

// a==0: remove current account
bool KNAccountManager::removeAccount(KNNntpAccount *a)
{
  if(!a) a=c_urrentAccount;
  if(!a) return false;

  QPtrList<KNGroup> *lst;
  if(knGlobals.folManager->unsentForAccount(a->id()) > 0) {
    KMessageBox::sorry(knGlobals.topWidget, i18n("This account cannot be deleted since there are some unsent messages for it."));
  }
  else if(KMessageBox::questionYesNo(knGlobals.topWidget, i18n("Do you really want to delete this account?"))==KMessageBox::Yes) {
    lst=new QPtrList<KNGroup>;
    lst->setAutoDelete(false);
    gManager->getGroupsOfAccount(a, lst);
    for(KNGroup *g=lst->first(); g; g=lst->next()) {
      if(g->isLocked()) {
        KMessageBox::sorry(knGlobals.topWidget, i18n("At least one group of this account is currently in use.\nThe account cannot be deleted at the moment."));
        return false;
      }
    }
    for(KNGroup *g=lst->first(); g; g=lst->next())
      gManager->unsubscribeGroup(g);
    delete lst;

    QDir dir(a->path());
    if (dir.exists()) {
      const QFileInfoList *list = dir.entryInfoList();  // get list of matching files and delete all
      if (list) {
        QFileInfoListIterator it( *list );
        while (it.current()) {
          dir.remove(it.current()->fileName());
          ++it;
        }
      }
      dir.cdUp();                                       // directory should now be empty, deleting it
      dir.rmdir(QString("nntp.%1/").arg(a->id()));
    }

    if(c_urrentAccount==a) setCurrentAccount(0);

    emit(accountRemoved(a));
    accList->removeRef(a);      // finally delete a
    return true;
  }

  return false;
}

void KNAccountManager::editProperties(KNNntpAccount *a)
{
  if(!a) a=c_urrentAccount;
  if(!a) return;

  a->editProperties(knGlobals.topWidget);
  emit(accountModified(a));
}

void KNAccountManager::accountRenamed(KNNntpAccount *a)
{
  if(!a) a=c_urrentAccount;
  if(!a) return;

  emit(accountModified(a));
}

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

#include "knaccountmanager.moc"
<|endoftext|>


<commit_before>#include "runtime.h"

// The class of the global object.
static JSClass globalClass = {
    "global",
    JSCLASS_GLOBAL_FLAGS,
    JS_PropertyStub,
    JS_DeletePropertyStub,
    JS_PropertyStub,
    JS_StrictPropertyStub,
    JS_EnumerateStub,
    JS_ResolveStub,
    JS_ConvertStub,
    nullptr, nullptr, nullptr, nullptr,
    JS_GlobalObjectTraceHook
};

std::atomic<int> rs::jsapi::Runtime::Instance::count_;
std::mutex rs::jsapi::Runtime::Instance::m_;

rs::jsapi::Runtime::Instance::Instance() {
    if (count_ == 0) {
        std::lock_guard<std::mutex> lk(m_);
        if (count_ == 0) {
            JS_Init();
            count_ += 1;
        }
    }

}

rs::jsapi::Runtime::Instance::~Instance() {
    count_ -= 1;

    if (count_ == 0) {
        JS_ShutDown();
    }
}

rs::jsapi::Runtime::Runtime() :
    rt_(JS_NewRuntime(8L * 1024L * 1024L, JSUseHelperThreads::JS_USE_HELPER_THREADS)),
    cx_(JS_NewContext(rt_, 8192)),
    global_(cx_, JS_NewGlobalObject(cx_, &globalClass, nullptr, JS::DontFireOnNewGlobalHook)),
    ac_(cx_, global_) {
    JS_InitStandardClasses(cx_, global_);

    JS_SetContextPrivate(cx_, this);
    JS_SetErrorReporter(cx_, &ReportError);
}

rs::jsapi::Runtime::~Runtime() {
    JS_DestroyContext(cx_);
    JS_DestroyRuntime(rt_);
}

void rs::jsapi::Runtime::ReportError(JSContext* cx, const char* message, JSErrorReport* report) {
    auto rt = static_cast<Runtime*>(JS_GetContextPrivate(cx));
    if (rt != nullptr) {
        rt->error_ = message;
    }
}

bool rs::jsapi::Runtime::HasError() {
    return error_.length() > 0;
}

const std::string& rs::jsapi::Runtime::getError() {
    return error_;
}

bool rs::jsapi::Runtime::ClearError() {
    error_.clear();
}<commit_msg>Correct the JS_Init startup count<commit_after>#include "runtime.h"

// The class of the global object.
static JSClass globalClass = {
    "global",
    JSCLASS_GLOBAL_FLAGS,
    JS_PropertyStub,
    JS_DeletePropertyStub,
    JS_PropertyStub,
    JS_StrictPropertyStub,
    JS_EnumerateStub,
    JS_ResolveStub,
    JS_ConvertStub,
    nullptr, nullptr, nullptr, nullptr,
    JS_GlobalObjectTraceHook
};

std::atomic<int> rs::jsapi::Runtime::Instance::count_;
std::mutex rs::jsapi::Runtime::Instance::m_;

rs::jsapi::Runtime::Instance::Instance() {
    if (count_ == 0) {
        std::lock_guard<std::mutex> lk(m_);
        if (count_ == 0) {
            JS_Init();
            count_ += 1;
        }
    } else {
        count_ += 1;
    }

}

rs::jsapi::Runtime::Instance::~Instance() {
    count_ -= 1;

    if (count_ == 0) {
        JS_ShutDown();
    }
}

rs::jsapi::Runtime::Runtime() :
    rt_(JS_NewRuntime(8L * 1024L * 1024L, JSUseHelperThreads::JS_USE_HELPER_THREADS)),
    cx_(JS_NewContext(rt_, 8192)),
    global_(cx_, JS_NewGlobalObject(cx_, &globalClass, nullptr, JS::DontFireOnNewGlobalHook)),
    ac_(cx_, global_) {
    JS_InitStandardClasses(cx_, global_);

    JS_SetContextPrivate(cx_, this);
    JS_SetErrorReporter(cx_, &ReportError);
}

rs::jsapi::Runtime::~Runtime() {
    JS_DestroyContext(cx_);
    JS_DestroyRuntime(rt_);
}

void rs::jsapi::Runtime::ReportError(JSContext* cx, const char* message, JSErrorReport* report) {
    auto rt = static_cast<Runtime*>(JS_GetContextPrivate(cx));
    if (rt != nullptr) {
        rt->error_ = message;
    }
}

bool rs::jsapi::Runtime::HasError() {
    return error_.length() > 0;
}

const std::string& rs::jsapi::Runtime::getError() {
    return error_;
}

bool rs::jsapi::Runtime::ClearError() {
    error_.clear();
}<|endoftext|>


<commit_before>#include <node.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#include <pwd.h>

using namespace node;
using namespace v8;

static Handle<Value> GetGroups(const Arguments& args) {
  HandleScope scope;
  gid_t *groupList;
  int ngroups = 0, i = 0;

  ngroups = sysconf(_SC_NGROUPS_MAX);

  groupList = (gid_t *)calloc(ngroups, sizeof(gid_t));
  assert(groupList != NULL);

  ngroups = getgroups(ngroups, groupList);
  assert(ngroups != -1);

  Local<Array> groupsArray = Array::New(ngroups);

  for (i = 0; i < ngroups; i++) {
    groupsArray->Set(i, Integer::New(groupList[i]));
  }

  return scope.Close(groupsArray);
}

static Handle<Value> InitGroups(const Arguments& args) {
  HandleScope scope;

  if (args.Length() < 1) {
    return ThrowException(Exception::Error(
          String::New("initgroups requires 1 argument")));
  }

  int err = 0, bufsize = 0;
  gid_t gid = 0;
  String::Utf8Value pwnam(args[0]);
  struct passwd pwd, *pwdp = NULL;
  bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
  char buffer[bufsize];

  if ((err = getpwnam_r(*pwnam, &pwd, buffer, bufsize, &pwdp)) ||
      pwdp == NULL) {
    if (errno == 0)
      return ThrowException(Exception::Error(
        String::New("initgroups user does not exist")));
    else
      return ThrowException(ErrnoException(errno, "getpwnam_r"));
  }

  gid = pwd.pw_gid;

  if ((err = initgroups(*pwnam, gid)) == -1)
    return ThrowException(ErrnoException(errno, "initgroups"));

  return Undefined();
}

extern "C" void init (Handle<Object> target) {
  target->Set(String::NewSymbol("initgroups"), FunctionTemplate::New(InitGroups)->GetFunction());
  target->Set(String::NewSymbol("getgroups"), FunctionTemplate::New(GetGroups)->GetFunction());
}

NODE_MODULE(unixgroups, init);
<commit_msg>initgroups can optionally call setgid as well<commit_after>#include <node.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#include <pwd.h>

using namespace node;
using namespace v8;

static Handle<Value> GetGroups(const Arguments& args) {
  HandleScope scope;
  gid_t *groupList;
  int ngroups = 0, i = 0;

  ngroups = sysconf(_SC_NGROUPS_MAX);

  groupList = (gid_t *)calloc(ngroups, sizeof(gid_t));
  assert(groupList != NULL);

  ngroups = getgroups(ngroups, groupList);
  assert(ngroups != -1);

  Local<Array> groupsArray = Array::New(ngroups);

  for (i = 0; i < ngroups; i++) {
    groupsArray->Set(i, Integer::New(groupList[i]));
  }

  return scope.Close(groupsArray);
}

static Handle<Value> InitGroups(const Arguments& args) {
  HandleScope scope;

  if (args.Length() < 1) {
    return ThrowException(Exception::Error(
          String::New("initgroups requires 1 argument")));
  }

  int err = 0, bufsize = 0;
  gid_t gid = 0;
  String::Utf8Value pwnam(args[0]);
  struct passwd pwd, *pwdp = NULL;
  bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
  char buffer[bufsize];

  errno = 0;
  if ((err = getpwnam_r(*pwnam, &pwd, buffer, bufsize, &pwdp)) ||
      pwdp == NULL) {
    if (errno == 0)
      return ThrowException(Exception::Error(
        String::New("initgroups user does not exist")));
    else
      return ThrowException(ErrnoException(errno, "getpwnam_r"));
  }

  gid = pwd.pw_gid;
  if (args.Length() > 1 && args[1]->IsTrue()) {
    if ((err = setgid(gid)) == -1)
      return ThrowException(ErrnoException(errno, "setgid"));
  }

  if ((err = initgroups(*pwnam, gid)) == -1)
    return ThrowException(ErrnoException(errno, "initgroups"));

  return Undefined();
}

extern "C" void init (Handle<Object> target) {
  target->Set(String::NewSymbol("initgroups"), FunctionTemplate::New(InitGroups)->GetFunction());
  target->Set(String::NewSymbol("getgroups"), FunctionTemplate::New(GetGroups)->GetFunction());
}

NODE_MODULE(unixgroups, init);
<|endoftext|>


<commit_before>/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <utility>
#include "kernel/builtin.h"
#include "library/fo_unify.h"
#include "library/expr_pair.h"
#include "library/kernel_bindings.h"

namespace lean {
static void assign(substitution & s, expr const & mvar, expr const & e) {
    lean_assert(is_metavar(mvar));
    s.insert(metavar_name(mvar), e);
}

static bool is_metavar_wo_local_context(expr const & e) {
    return is_metavar(e) && !metavar_lctx(e);
}

static bool is_eq_heq(expr const & e, expr & lhs, expr & rhs) {
    return is_eq(e, lhs, rhs) || is_homo_eq(e, lhs, rhs);
}

optional<substitution> fo_unify(expr e1, expr e2) {
    lean_assert(e1);
    lean_assert(e2);
    substitution s;
    unsigned i;
    expr lhs1, rhs1, lhs2, rhs2;
    buffer<expr_pair> todo;
    todo.emplace_back(e1, e2);
    while (!todo.empty()) {
        auto p = todo.back();
        todo.pop_back();
        e1 = find(s, p.first);
        e2 = find(s, p.second);
        if (e1 != e2) {
            if (is_metavar_wo_local_context(e1)) {
                assign(s, e1, e2);
            } else if (is_metavar_wo_local_context(e2)) {
                assign(s, e2, e1);
            } else if (is_eq_heq(e1, lhs1, rhs1) && is_eq_heq(e2, lhs2, rhs2)) {
                todo.emplace_back(lhs1, lhs2);
                todo.emplace_back(rhs1, rhs2);
            } else {
                if (e1.kind() != e2.kind())
                    return optional<substitution>();
                switch (e1.kind()) {
                case expr_kind::Var: case expr_kind::Constant: case expr_kind::Type: case expr_kind::Value: case expr_kind::MetaVar:
                    return optional<substitution>();
                case expr_kind::App:
                    if (num_args(e1) != num_args(e2))
                        return optional<substitution>();
                    i = num_args(e1);
                    while (i > 0) {
                        --i;
                        todo.emplace_back(arg(e1, i), arg(e2, i));
                    }
                    break;
                case expr_kind::Eq:
                    lean_unreachable(); break; // LCOV_EXCL_LINE
                case expr_kind::Lambda: case expr_kind::Pi:
                    todo.emplace_back(abst_body(e1), abst_body(e2));
                    todo.emplace_back(abst_domain(e1), abst_domain(e2));
                    break;
                case expr_kind::Let:
                    todo.emplace_back(let_body(e1), let_body(e2));
                    todo.emplace_back(let_value(e1), let_value(e2));
                    if (static_cast<bool>(let_type(e1)) != static_cast<bool>(let_type(e2)))
                        return optional<substitution>();
                    if (let_type(e1)) {
                        lean_assert(let_type(e2));
                        todo.emplace_back(let_type(e1), let_type(e2));
                    }
                    break;
                }
            }
        }
    }
    return optional<substitution>(s);
}

static int fo_unify(lua_State * L) {
    optional<substitution> r = fo_unify(to_nonnull_expr(L, 1), to_nonnull_expr(L, 2));
    if (!r) {
        lua_pushnil(L);
        return 1;
    } else {
        return push_substitution(L, *r);
    }
}

void open_fo_unify(lua_State * L) {
    SET_GLOBAL_FUN(fo_unify, "fo_unify");
}
}
<commit_msg>fix(library/fo_unify): unify (?f ?x) with (g a b)<commit_after>/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.

Author: Leonardo de Moura
*/
#include <utility>
#include "kernel/builtin.h"
#include "library/fo_unify.h"
#include "library/expr_pair.h"
#include "library/kernel_bindings.h"

namespace lean {
static void assign(substitution & s, expr const & mvar, expr const & e) {
    lean_assert(is_metavar(mvar));
    s.insert(metavar_name(mvar), e);
}

static bool is_metavar_wo_local_context(expr const & e) {
    return is_metavar(e) && !metavar_lctx(e);
}

static bool is_eq_heq(expr const & e, expr & lhs, expr & rhs) {
    return is_eq(e, lhs, rhs) || is_homo_eq(e, lhs, rhs);
}

optional<substitution> fo_unify(expr e1, expr e2) {
    lean_assert(e1);
    lean_assert(e2);
    substitution s;
    unsigned i1, i2;
    expr lhs1, rhs1, lhs2, rhs2;
    buffer<expr_pair> todo;
    todo.emplace_back(e1, e2);
    while (!todo.empty()) {
        auto p = todo.back();
        todo.pop_back();
        e1 = find(s, p.first);
        e2 = find(s, p.second);
        if (e1 != e2) {
            if (is_metavar_wo_local_context(e1)) {
                assign(s, e1, e2);
            } else if (is_metavar_wo_local_context(e2)) {
                assign(s, e2, e1);
            } else if (is_eq_heq(e1, lhs1, rhs1) && is_eq_heq(e2, lhs2, rhs2)) {
                todo.emplace_back(lhs1, lhs2);
                todo.emplace_back(rhs1, rhs2);
            } else {
                if (e1.kind() != e2.kind())
                    return optional<substitution>();
                switch (e1.kind()) {
                case expr_kind::Var: case expr_kind::Constant: case expr_kind::Type: case expr_kind::Value: case expr_kind::MetaVar:
                    return optional<substitution>();
                case expr_kind::App:
                    i1 = num_args(e1);
                    i2 = num_args(e2);
                    while (i1 > 0 && i2 > 0) {
                        --i1;
                        --i2;
                        if (i1 == 0 && i2 > 0) {
                            todo.emplace_back(arg(e1, i1), mk_app(i2+1, begin_args(e2)));
                        } else if (i2 == 0 && i1 > 0) {
                            todo.emplace_back(mk_app(i1+1, begin_args(e1)), arg(e2, i2));
                        } else {
                            todo.emplace_back(arg(e1, i1), arg(e2, i2));
                        }
                    }
                    break;
                case expr_kind::Eq:
                    lean_unreachable(); break; // LCOV_EXCL_LINE
                case expr_kind::Lambda: case expr_kind::Pi:
                    todo.emplace_back(abst_body(e1), abst_body(e2));
                    todo.emplace_back(abst_domain(e1), abst_domain(e2));
                    break;
                case expr_kind::Let:
                    todo.emplace_back(let_body(e1), let_body(e2));
                    todo.emplace_back(let_value(e1), let_value(e2));
                    if (static_cast<bool>(let_type(e1)) != static_cast<bool>(let_type(e2)))
                        return optional<substitution>();
                    if (let_type(e1)) {
                        lean_assert(let_type(e2));
                        todo.emplace_back(let_type(e1), let_type(e2));
                    }
                    break;
                }
            }
        }
    }
    return optional<substitution>(s);
}

static int fo_unify(lua_State * L) {
    optional<substitution> r = fo_unify(to_nonnull_expr(L, 1), to_nonnull_expr(L, 2));
    if (!r) {
        lua_pushnil(L);
        return 1;
    } else {
        return push_substitution(L, *r);
    }
}

void open_fo_unify(lua_State * L) {
    SET_GLOBAL_FUN(fo_unify, "fo_unify");
}
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef SOL_PROTECTED_FUNCTION_HPP
#define SOL_PROTECTED_FUNCTION_HPP

#include "reference.hpp"
#include "stack.hpp"
#include "protected_function_result.hpp"
#include <cstdint>

namespace sol {
class protected_function : public reference {
private:
    static reference& handler_storage() {
        static sol::reference h;
        return h;
    }

public:
    static const reference& get_default_handler () {
        return handler_storage();
    }

    static void set_default_handler( reference& ref ) {
        handler_storage() = ref;
    }

private:
    struct handler {
        const reference& target;
        int stackindex;
        handler(const reference& target) : target(target), stackindex(0) {
            if (target.valid()) {
                stackindex = lua_gettop(target.lua_state()) + 1;
                target.push();
            }
        }
        ~handler() {
            if (stackindex > 0) {
                lua_remove(target.lua_state(), stackindex);
            }
        }
    };

    int luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, handler& h) const {
        return lua_pcallk(lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), h.stackindex, 0, nullptr);
    }

    template<std::size_t... I, typename... Ret>
    auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n, handler& h) const {
        luacall(n, sizeof...(Ret), h);
        int stacksize = lua_gettop(lua_state());
        int firstreturn = std::max(0, stacksize - static_cast<int>(sizeof...(Ret)) + 1);
        auto r = stack::get<std::tuple<Ret...>>(lua_state(), firstreturn);
        lua_pop(lua_state(), static_cast<int>(sizeof...(Ret)));
        return r;
    }

    template<std::size_t I, typename Ret>
    Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n, handler& h) const {
        luacall(n, 1, h);
        return stack::pop<Ret>(lua_state());
    }

    template <std::size_t I>
    void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n, handler& h) const {
        luacall(n, 0, h);
    }

    protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, handler& h) const {
        bool handlerpushed = error_handler.valid();
        int stacksize = lua_gettop(lua_state());
        int firstreturn = std::max(1, stacksize - static_cast<int>(n) - 1);
        int returncount = 0;
        call_status code = call_status::ok;
#ifndef SOL_NO_EXCEPTIONS
	   auto onexcept = [&](const char* error) {
            h.stackindex = 0;
            if (h.target.valid()) {
                h.target.push();
                stack::push(lua_state(), error);
                lua_call(lua_state(), 1, 1);
            }
		  else {
                stack::push(lua_state(), error);
		  }
	   };
        try {
#endif // No Exceptions
            code = static_cast<call_status>(luacall(n, LUA_MULTRET, h));
            int poststacksize = lua_gettop(lua_state());
            returncount = poststacksize - firstreturn;
#ifndef SOL_NO_EXCEPTIONS
        }
        // Handle C++ errors thrown from C++ functions bound inside of lua
        catch (const char* error) {
            onexcept(error);
            firstreturn = lua_gettop(lua_state());
            return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
        }
        catch (const std::exception& error) {
            onexcept(error.what());
            firstreturn = lua_gettop(lua_state());
            return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
        }
        catch (...) {
            throw;
        }
#endif // No Exceptions
        return protected_function_result(lua_state(), firstreturn + ( handlerpushed ? 0 : 1 ), returncount, returncount, code);
    }

public:
    sol::reference error_handler;

    protected_function() = default;
    protected_function(lua_State* L, int index = -1): reference(L, index), error_handler(get_default_handler()) {
        type_assert(L, index, type::function);
    }
    protected_function(const protected_function&) = default;
    protected_function& operator=(const protected_function&) = default;
    protected_function( protected_function&& ) = default;
    protected_function& operator=( protected_function&& ) = default;

    template<typename... Args>
    protected_function_result operator()(Args&&... args) const {
        return call<>(std::forward<Args>(args)...);
    }

    template<typename... Ret, typename... Args>
    decltype(auto) operator()(types<Ret...>, Args&&... args) const {
        return call<Ret...>(std::forward<Args>(args)...);
    }

    template<typename... Ret, typename... Args>
    decltype(auto) call(Args&&... args) const {
        handler h(error_handler);
        push();
        int pushcount = stack::push_args(lua_state(), std::forward<Args>(args)...);
        return invoke(types<Ret...>(), std::index_sequence_for<Ret...>(), pushcount, h);
    }
};
} // sol

#endif // SOL_FUNCTION_HPP
<commit_msg>Catch EVERYTHING, even the shit we don't know about.<commit_after>// The MIT License (MIT)

// Copyright (c) 2013-2016 Rapptz, ThePhD and contributors

// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:

// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#ifndef SOL_PROTECTED_FUNCTION_HPP
#define SOL_PROTECTED_FUNCTION_HPP

#include "reference.hpp"
#include "stack.hpp"
#include "protected_function_result.hpp"
#include <cstdint>

namespace sol {
class protected_function : public reference {
private:
    static reference& handler_storage() {
        static sol::reference h;
        return h;
    }

public:
    static const reference& get_default_handler () {
        return handler_storage();
    }

    static void set_default_handler( reference& ref ) {
        handler_storage() = ref;
    }

private:
    struct handler {
        const reference& target;
        int stackindex;
        handler(const reference& target) : target(target), stackindex(0) {
            if (target.valid()) {
                stackindex = lua_gettop(target.lua_state()) + 1;
                target.push();
            }
        }
        ~handler() {
            if (stackindex > 0) {
                lua_remove(target.lua_state(), stackindex);
            }
        }
    };

    int luacall(std::ptrdiff_t argcount, std::ptrdiff_t resultcount, handler& h) const {
        return lua_pcallk(lua_state(), static_cast<int>(argcount), static_cast<int>(resultcount), h.stackindex, 0, nullptr);
    }

    template<std::size_t... I, typename... Ret>
    auto invoke(types<Ret...>, std::index_sequence<I...>, std::ptrdiff_t n, handler& h) const {
        luacall(n, sizeof...(Ret), h);
        int stacksize = lua_gettop(lua_state());
        int firstreturn = std::max(0, stacksize - static_cast<int>(sizeof...(Ret)) + 1);
        auto r = stack::get<std::tuple<Ret...>>(lua_state(), firstreturn);
        lua_pop(lua_state(), static_cast<int>(sizeof...(Ret)));
        return r;
    }

    template<std::size_t I, typename Ret>
    Ret invoke(types<Ret>, std::index_sequence<I>, std::ptrdiff_t n, handler& h) const {
        luacall(n, 1, h);
        return stack::pop<Ret>(lua_state());
    }

    template <std::size_t I>
    void invoke(types<void>, std::index_sequence<I>, std::ptrdiff_t n, handler& h) const {
        luacall(n, 0, h);
    }

    protected_function_result invoke(types<>, std::index_sequence<>, std::ptrdiff_t n, handler& h) const {
        bool handlerpushed = error_handler.valid();
        int stacksize = lua_gettop(lua_state());
        int firstreturn = std::max(1, stacksize - static_cast<int>(n) - 1);
        int returncount = 0;
        call_status code = call_status::ok;
#ifndef SOL_NO_EXCEPTIONS
	   auto onexcept = [&](const char* error) {
            h.stackindex = 0;
            if (h.target.valid()) {
                h.target.push();
                stack::push(lua_state(), error);
                lua_call(lua_state(), 1, 1);
            }
		  else {
                stack::push(lua_state(), error);
		  }
	   };
        try {
#endif // No Exceptions
            code = static_cast<call_status>(luacall(n, LUA_MULTRET, h));
            int poststacksize = lua_gettop(lua_state());
            returncount = poststacksize - firstreturn;
#ifndef SOL_NO_EXCEPTIONS
        }
        // Handle C++ errors thrown from C++ functions bound inside of lua
        catch (const char* error) {
            onexcept(error);
            firstreturn = lua_gettop(lua_state());
            return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
        }
        catch (const std::exception& error) {
            onexcept(error.what());
            firstreturn = lua_gettop(lua_state());
            return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
        }
        catch (...) {
            onexcept("caught (...) unknown error during protected_function call");
            firstreturn = lua_gettop(lua_state());
            return protected_function_result(lua_state(), firstreturn, 0, 1, call_status::runtime);
        }
#endif // No Exceptions
        return protected_function_result(lua_state(), firstreturn + ( handlerpushed ? 0 : 1 ), returncount, returncount, code);
    }

public:
    sol::reference error_handler;

    protected_function() = default;
    protected_function(lua_State* L, int index = -1): reference(L, index), error_handler(get_default_handler()) {
        type_assert(L, index, type::function);
    }
    protected_function(const protected_function&) = default;
    protected_function& operator=(const protected_function&) = default;
    protected_function( protected_function&& ) = default;
    protected_function& operator=( protected_function&& ) = default;

    template<typename... Args>
    protected_function_result operator()(Args&&... args) const {
        return call<>(std::forward<Args>(args)...);
    }

    template<typename... Ret, typename... Args>
    decltype(auto) operator()(types<Ret...>, Args&&... args) const {
        return call<Ret...>(std::forward<Args>(args)...);
    }

    template<typename... Ret, typename... Args>
    decltype(auto) call(Args&&... args) const {
        handler h(error_handler);
        push();
        int pushcount = stack::push_args(lua_state(), std::forward<Args>(args)...);
        return invoke(types<Ret...>(), std::index_sequence_for<Ret...>(), pushcount, h);
    }
};
} // sol

#endif // SOL_FUNCTION_HPP
<|endoftext|>


<commit_before>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * 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 <iostream>
#include <stdexcept>
#include <stdio.h>
#include <expat.h>
#include <string.h>
#include <fstream>
#include <string>
#include <stack>
#include <iomanip>

#include <votca/tools/property.h>
#include <votca/tools/tokenizer.h>

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

namespace votca { namespace tools {

PropertyFormat XML(formatXML);
PropertyFormat TXT(formatTXT);
PropertyFormat T2T(formatT2T);
PropertyFormat LOG(formatLOG);
PropertyFormat TEX(formatTEX);
PropertyFormat HLP(formatHLP);

// ostream modifier defines the output format
const int Property::_format = std::ios_base::xalloc();
// ostream modifier defines the output level
const int Property::_output_level = std::ios_base::xalloc();

Property &Property::get(const string &key)
{
    Tokenizer tok(key, ".");
    Tokenizer::iterator n;

    n = tok.begin();
    if(n==tok.end()) return *this;

    Property *p;
    map<string, Property*>::iterator iter;
    if(*n=="") {
        p = this;
    }
    else {
        iter = _map.find(*n);

        if(iter == _map.end())
            throw runtime_error("property not found: " + key);

        p = (((*iter).second));
    }
    ++n;
    try {
        for(; n!=tok.end(); ++n) {
            p = &p->get(*n);
        }
    }
    catch(string err) { // catch here to get full key in exception
        throw runtime_error("property not found: " + key);
    }

    return *p;
}

std::list<Property *> Property::Select(const string &filter)
{
    Tokenizer tok(filter, ".");

    std::list<Property *> selection;

    if(tok.begin()==tok.end()) return selection;

    selection.push_back(this);

    for (Tokenizer::iterator n = tok.begin();
            n != tok.end(); ++n) {
        std::list<Property *> childs;
        for (std::list<Property *>::iterator p = selection.begin();
                p != selection.end(); ++p) {
                for (list<Property>::iterator iter = (*p)->_properties.begin();
                    iter != (*p)->_properties.end(); ++iter) {
                    if (wildcmp((*n).c_str(), (*iter).name().c_str())) {
                        childs.push_back(&(*iter));
                    }
                }
        }
        selection = childs;
    }

    return selection;
}

void PrintNodeTXT(std::ostream &out, Property &p, const int start_level, int level, string prefix, string offset)
{

    list<Property>::iterator iter;

    //cout << "LEVEL: " << level << " " << start_level << endl;
    if((p.value() != "") || p.HasChilds() ) {

        if ( level >= start_level ) {
                if((p.value()).find_first_not_of("\t\n ") != std::string::npos)
                        out << prefix << " = " << p.value() << endl;
        } else {
            prefix="";
        }
    }

    for(iter = p.begin(); iter!=p.end(); ++iter) {
        if(prefix=="") {
            level++;
            PrintNodeTXT(out, (*iter), start_level, level, prefix + (*iter).name() );
            level--;
        } else {
            level++;
            PrintNodeTXT(out, (*iter), start_level, level, prefix + "." + (*iter).name() );
            level--;
        }
    }
}

void PrintNodeXML(std::ostream &out, Property &p, const int start_level, int level, string prefix,  string offset)
{

    list<Property>::iterator iter;
    map<string,string>::iterator ia;
    bool _endl = true;

    //cout << p._name << " Attributes: " << p._attributes.size() << endl;

    //if( p.HasChilds() || p.value() != "" ) {

        // print starting only from the start_level (the first node (level 0) can be <> </>)
        if ( level >= start_level )  {
            // print the node name
            out << offset << "<" << p._name ;
            // print the node attributes
            for(ia = p._attributes.begin(); ia!=p._attributes.end(); ++ia)
                out << " " << ia->first << "=\"" << ia->second << "\"" ;
            out << ">";

            // print node value if it is not empty
            bool has_value = ( (p._value).find_first_not_of("\t\n ") != std::string::npos );
            if( has_value ) { out << p._value; _endl = false; }

            // check if we need the end of the line or not
            if( !has_value &&  p.HasChilds() ) out << endl;
            if( !has_value &&  !p.HasChilds() ) _endl = false;
        }

        // continue iteratively through the rest of the nodes
        for(iter = p._properties.begin(); iter!=p._properties.end(); ++iter) {
            level++;
            if (  level > start_level ) offset += "\t";
            PrintNodeXML(out, (*iter), start_level, level, (*iter)._name, offset);
            if (  level > start_level ) offset.resize(offset.size()-1);
            level--;
        }

        if ( level >= start_level ) {
            if ( _endl ) {
                out << offset << "</" << p._name << ">"  << endl;
            } else {
                out << "</" << p._name << ">"  << endl;
            }
        }

    //}
}

void PrintNodeT2T(std::ostream &out, const string &prefix, Property &p) {
    out << "T2T format is not implemented";
}

void PrintNodeLOG(std::ostream &out, const string &prefix, Property &p) {
    out << "LOG format is not implemented";
}

void PrintNodeTEX(std::ostream &out, Property &p, const int start_level, int level, string prefix,  string offset) {

    list<Property>::iterator iter;
    string head_name;
    string label; // reference of the xml file in the manual
    string section; // reference of the description section in the manual
    string help;
    string header_format("\\subsection{%1%}\n"
                         "\\label{%2%}\n%3%\n"
                         "\\rowcolors{1}{invisiblegray}{white}\n"
                         "{\\small\n "
                         "\\begin{longtable}{m{3cm}|m{2cm}|m{1cm}|m{8cm}}\n"
                         " option & default & unit & description\\\\\n\\hline\n");

    string footer_format("\\end{longtable}\n}\n"
                         "\\noindent Return to the description of \\slink{%1%}{\\texttt{%2%}}.\n");

    string body_format(" \\hspace{%1%pt}\\hypertarget{%2%}{%3%} & %4% & %5% & %6% \\\\\n");

    // if this is the head node, print the header
    if ( level == start_level )  {
            head_name = p._name;
            label = p.getAttribute<string>("label");
            section = p.getAttribute<string>("section");
            help = p.getAttribute<string>("help");
            out << boost::format(header_format) % head_name % label % help;
            prefix = p._name;
     }

    if ( level > start_level ) {

        // if this node has children or a value or is not the first, start recursive printing
        if( ( p.value() != "" || p.HasChilds() ) && level > -1) {
            string _tex_name = boost::replace_all_copy( p.name(), "_", "\\_" );

            out << boost::format(body_format) % int((level-start_level-1)*10)
                    % prefix
                    % _tex_name
                    % p.getAttribute<string>("default")
                    % p.getAttribute<string>("unit")
                    % p.getAttribute<string>("help");
            /*out << " \\hspace{" << (level-1)*10 << "pt} "
                << "\\hypertarget{" << prefix << "}"
                <<  "{" << _tex_name << "}"
                << " & " <<  p.getAttribute<string>("help") << "\\\\" << endl; */
        }
    }

    // continue iteratively through the rest of the nodes
    for(iter = p.begin(); iter != p.end(); ++iter) {
        if(prefix=="") {
            level++;
            PrintNodeTEX(out, (*iter), start_level, level, (*iter)._name, offset);
            level--;
        } else {
            level++;
            PrintNodeTEX(out, (*iter), start_level, level, prefix + "." + (*iter)._name, offset);
            level--;
        }
    }

    // if this is the head node, print the footer
    if ( level == start_level )  out << boost::format(footer_format) % section % head_name;

}

void PrintNodeHLP(std::ostream &out, Property &p, const int start_level, int level=0, string prefix="",  int offset=0) {

    list<Property>::iterator iter;
    string head_name;
    string help;
    string fmt("t|%1%%|15t|%2%%|40t|%3%%|55t|%4%\n");

    // if this is the head node, print the header
    if ( level == start_level ) {
            head_name = p.name();
            if ( p.hasAttribute("help") ) {
                help = p.getAttribute<string>("help");
                out << boost::format(" %1%: %|18t| %2%\n") % head_name % help;
            }
            offset=0;
            //out << boost::format(fmt) % "option" % "def" % "[un]" % "description";
    }

    if ( level > start_level ) {
        // if this node has children or a value or is not the first, start recursive printing
        //if( ( p.value() != "" || p.HasChilds() ) ) {

            string ofmt;
            ofmt = "%|" + boost::lexical_cast<string>(offset) + fmt;
            //cout << ofmt << " " << fmt << endl;
            string _unit("");
            string _default("");

            if  ( p.hasAttribute("unit") ) _unit = p.getAttribute<string>("unit");
            if  ( p.hasAttribute("default") ) _default = p.getAttribute<string>("default") ;
            if ( !_unit.empty() ) _unit = "[" + _unit + "]";
            if ( !_default.empty() ) _default = "(" + _default + ")";

            out << boost::format(ofmt)
                    % p.name()
                    % _default
                    % _unit
                    % p.getAttribute<string>("help");
        //}
    }

    for(iter = p.begin(); iter != p.end(); ++iter) {
        if(prefix=="") {
            offset += 2; level++;
            PrintNodeHLP(out, (*iter), start_level, level, prefix + (*iter).name(), offset);
            offset -= 2; level--;
        } else {
            offset += 2; level++;
            PrintNodeHLP(out, (*iter), start_level, level, prefix + "." + (*iter).name(), offset);
            offset -= 2; level--;
        }
    }

    // if this is the head node, print the footer
    if ( level == start_level ) {
     }
}

std::ostream &operator<<(std::ostream &out, Property& p)
{
    if (!out.good())
        return out;

    std::ostream::sentry sentry(out);

    if(sentry)
    {
        // level from which to start node output
        int _level = out.iword(p.GetOutputLevel());

        switch(out.iword(p.GetFormat()))
        {
        default:
            PrintNodeTXT(out, p, _level);
        case formatXML:
            PrintNodeXML(out, p, _level);
            break;
        case formatTXT:
            PrintNodeTXT(out, p, _level);
            break;
        case formatT2T:
            PrintNodeT2T(out, "", p);
            break;
        case formatLOG:
            PrintNodeLOG(out, "", p);
            break;
        case formatTEX:
            PrintNodeTEX(out, p, _level);
            break;
        case formatHLP:
            PrintNodeHLP(out, p, _level);
            break;
        }
        out << endl;
    }

    return out;
};

//{
//      Property::PrintNode(out, "", p);
      //Property::PrintNodeXML(out, "", p, "");
//      return out;
//}

static void start_hndl(void *data, const char *el, const char **attr)
{
    stack<Property *> *property_stack =
        (stack<Property *> *)XML_GetUserData((XML_Parser*)data);

    Property *cur = property_stack->top();
    Property &np = cur->add(el, "");

    for (int i = 0; attr[i]; i += 2)
        np.setAttribute(attr[i], attr[i + 1]);

    property_stack->push(&np);
}

static void end_hndl(void *data, const char *el)
{
    stack<Property *> *property_stack =
        (stack<Property *> *)XML_GetUserData((XML_Parser*)data);
    property_stack->pop();
}

void char_hndl(void *data, const char *txt, int txtlen)
{
    stack<Property *> *property_stack =
        (stack<Property *> *)XML_GetUserData((XML_Parser*)data);

    Property *cur = property_stack->top();
    cur->value().append(txt, txtlen);
}

bool load_property_from_xml(Property &p, string filename)
{
  XML_Parser parser = XML_ParserCreate(NULL);
  if (! parser)
    throw std::runtime_error("Couldn't allocate memory for xml parser");

  XML_UseParserAsHandlerArg(parser);
  XML_SetElementHandler(parser, start_hndl, end_hndl);
  XML_SetCharacterDataHandler(parser, char_hndl);

  ifstream fl;
  fl.open(filename.c_str());
  if(!fl.is_open())
    throw std::ios_base::failure("Error on open xml file: " + filename);

  stack<Property *> pstack;
  pstack.push(&p);

  XML_SetUserData(parser, (void*)&pstack);
  while(!fl.eof()) {
    string line;
    getline(fl, line);
    line=line + "\n";
    if (! XML_Parse(parser, line.c_str(), line.length(), fl.eof()))
      throw  std::ios_base::failure(filename + ": Parse error at line " +
          boost::lexical_cast<string>(XML_GetCurrentLineNumber(parser)) + "\n" +
          XML_ErrorString(XML_GetErrorCode(parser)));
  }
  fl.close();
  return true;
}

}}
<commit_msg>checks in the property class<commit_after>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * 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 <iostream>
#include <stdexcept>
#include <stdio.h>
#include <expat.h>
#include <string.h>
#include <fstream>
#include <string>
#include <stack>
#include <iomanip>

#include <votca/tools/property.h>
#include <votca/tools/tokenizer.h>

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

namespace votca { namespace tools {

PropertyFormat XML(formatXML);
PropertyFormat TXT(formatTXT);
PropertyFormat T2T(formatT2T);
PropertyFormat LOG(formatLOG);
PropertyFormat TEX(formatTEX);
PropertyFormat HLP(formatHLP);

// ostream modifier defines the output format
const int Property::_format = std::ios_base::xalloc();
// ostream modifier defines the output level
const int Property::_output_level = std::ios_base::xalloc();

Property &Property::get(const string &key)
{
    Tokenizer tok(key, ".");
    Tokenizer::iterator n;

    n = tok.begin();
    if(n==tok.end()) return *this;

    Property *p;
    map<string, Property*>::iterator iter;
    if(*n=="") {
        p = this;
    }
    else {
        iter = _map.find(*n);

        if(iter == _map.end())
            throw runtime_error("property not found: " + key);

        p = (((*iter).second));
    }
    ++n;
    try {
        for(; n!=tok.end(); ++n) {
            p = &p->get(*n);
        }
    }
    catch(string err) { // catch here to get full key in exception
        throw runtime_error("property not found: " + key);
    }

    return *p;
}

std::list<Property *> Property::Select(const string &filter)
{
    Tokenizer tok(filter, ".");

    std::list<Property *> selection;

    if(tok.begin()==tok.end()) return selection;

    selection.push_back(this);

    for (Tokenizer::iterator n = tok.begin();
            n != tok.end(); ++n) {
        std::list<Property *> childs;
        for (std::list<Property *>::iterator p = selection.begin();
                p != selection.end(); ++p) {
                for (list<Property>::iterator iter = (*p)->_properties.begin();
                    iter != (*p)->_properties.end(); ++iter) {
                    if (wildcmp((*n).c_str(), (*iter).name().c_str())) {
                        childs.push_back(&(*iter));
                    }
                }
        }
        selection = childs;
    }

    return selection;
}

void PrintNodeTXT(std::ostream &out, Property &p, const int start_level, int level, string prefix, string offset)
{

    list<Property>::iterator iter;

    //cout << "LEVEL: " << level << " " << start_level << endl;
    if((p.value() != "") || p.HasChilds() ) {

        if ( level >= start_level ) {
                if((p.value()).find_first_not_of("\t\n ") != std::string::npos)
                        out << prefix << " = " << p.value() << endl;
        } else {
            prefix="";
        }
    }

    for(iter = p.begin(); iter!=p.end(); ++iter) {
        if(prefix=="") {
            level++;
            PrintNodeTXT(out, (*iter), start_level, level, prefix + (*iter).name() );
            level--;
        } else {
            level++;
            PrintNodeTXT(out, (*iter), start_level, level, prefix + "." + (*iter).name() );
            level--;
        }
    }
}

void PrintNodeXML(std::ostream &out, Property &p, const int start_level, int level, string prefix,  string offset)
{

    list<Property>::iterator iter;
    map<string,string>::iterator ia;
    bool _endl = true;

    //cout << p._name << " Attributes: " << p._attributes.size() << endl;

    //if( p.HasChilds() || p.value() != "" ) {

        // print starting only from the start_level (the first node (level 0) can be <> </>)
        if ( level >= start_level )  {
            // print the node name
            out << offset << "<" << p._name ;
            // print the node attributes
            for(ia = p._attributes.begin(); ia!=p._attributes.end(); ++ia)
                out << " " << ia->first << "=\"" << ia->second << "\"" ;
            out << ">";

            // print node value if it is not empty
            bool has_value = ( (p._value).find_first_not_of("\t\n ") != std::string::npos );
            if( has_value ) { out << p._value; _endl = false; }

            // check if we need the end of the line or not
            if( !has_value &&  p.HasChilds() ) out << endl;
            if( !has_value &&  !p.HasChilds() ) _endl = false;
        }

        // continue iteratively through the rest of the nodes
        for(iter = p._properties.begin(); iter!=p._properties.end(); ++iter) {
            level++;
            if (  level > start_level ) offset += "\t";
            PrintNodeXML(out, (*iter), start_level, level, (*iter)._name, offset);
            if (  level > start_level ) offset.resize(offset.size()-1);
            level--;
        }

        if ( level >= start_level ) {
            if ( _endl ) {
                out << offset << "</" << p._name << ">"  << endl;
            } else {
                out << "</" << p._name << ">"  << endl;
            }
        }

    //}
}

void PrintNodeT2T(std::ostream &out, const string &prefix, Property &p) {
    out << "T2T format is not implemented";
}

void PrintNodeLOG(std::ostream &out, const string &prefix, Property &p) {
    out << "LOG format is not implemented";
}

void PrintNodeTEX(std::ostream &out, Property &p, const int start_level, int level, string prefix,  string offset) {

    list<Property>::iterator iter;
    string head_name;
    string _label(""); // reference of the xml file in the manual
    string _section(""); // reference of the description section in the manual
    string _help("");
    string _default(""); // default value if supplied
    string _unit(""); //unit, if supplied

    string header_format("\\subsection{%1%}\n"
                         "\\label{%2%}\n%3%\n"
                         "\\rowcolors{1}{invisiblegray}{white}\n"
                         "{\\small\n "
                         "\\begin{longtable}{m{3cm}|m{2cm}|m{1cm}|m{8cm}}\n"
                         " option & default & unit & description\\\\\n\\hline\n");

    string footer_format("\\end{longtable}\n}\n"
                         "\\noindent Return to the description of \\slink{%1%}{\\texttt{%2%}}.\n");

    string body_format(" \\hspace{%1%pt}\\hypertarget{%2%}{%3%} & %4% & %5% & %6% \\\\\n");

    // if this is the head node, print the header
    if ( level == start_level )  {
            head_name = p._name;
            if ( p.hasAttribute("label") ) _label = p.getAttribute<string>("label");
            if ( p.hasAttribute("section") ) _section = p.getAttribute<string>("section");
            if ( p.hasAttribute("help") ) _help = p.getAttribute<string>("help");
            out << boost::format(header_format) % head_name % _label % _help;
            prefix = p._name;
     }

    if ( level > start_level ) {

        // if this node has children or a value or is not the first, start recursive printing
        if( ( p.value() != "" || p.HasChilds() ) && level > -1) {
            string _tex_name = boost::replace_all_copy( p.name(), "_", "\\_" );

            if ( p.hasAttribute("default") ) _default = p.getAttribute<string>("default");
            if ( p.hasAttribute("unit") ) _unit = p.getAttribute<string>("unit");
            if ( p.hasAttribute("help") ) _help = p.getAttribute<string>("help");

            out << boost::format(body_format) % int((level-start_level-1)*10)
                    % prefix
                    % _tex_name
                    % _default
                    % _unit
                    % _help;
            /*out << " \\hspace{" << (level-1)*10 << "pt} "
                << "\\hypertarget{" << prefix << "}"
                <<  "{" << _tex_name << "}"
                << " & " <<  p.getAttribute<string>("help") << "\\\\" << endl; */
        }
    }

    // continue iteratively through the rest of the nodes
    for(iter = p.begin(); iter != p.end(); ++iter) {
        if(prefix=="") {
            level++;
            PrintNodeTEX(out, (*iter), start_level, level, (*iter)._name, offset);
            level--;
        } else {
            level++;
            PrintNodeTEX(out, (*iter), start_level, level, prefix + "." + (*iter)._name, offset);
            level--;
        }
    }

    // if this is the head node, print the footer
    if ( level == start_level )  out << boost::format(footer_format) % _section % head_name;

}

void PrintNodeHLP(std::ostream &out, Property &p, const int start_level, int level=0, string prefix="",  int offset=0) {

    list<Property>::iterator iter;
    string head_name;
    string help;
    string fmt("t|%1%%|15t|%2%%|40t|%3%%|55t|%4%\n");

    // if this is the head node, print the header
    if ( level == start_level ) {
            head_name = p.name();
            if ( p.hasAttribute("help") ) {
                help = p.getAttribute<string>("help");
                out << boost::format(" %1%: %|18t| %2%\n") % head_name % help;
            }
            offset=0;
            //out << boost::format(fmt) % "option" % "def" % "[un]" % "description";
    }

    if ( level > start_level ) {
        // if this node has children or a value or is not the first, start recursive printing
        //if( ( p.value() != "" || p.HasChilds() ) ) {

            string ofmt;
            ofmt = "%|" + boost::lexical_cast<string>(offset) + fmt;
            //cout << ofmt << " " << fmt << endl;
            string _unit("");
            string _default("");

            if  ( p.hasAttribute("unit") ) _unit = p.getAttribute<string>("unit");
            if  ( p.hasAttribute("default") ) _default = p.getAttribute<string>("default") ;
            if ( !_unit.empty() ) _unit = "[" + _unit + "]";
            if ( !_default.empty() ) _default = "(" + _default + ")";

            out << boost::format(ofmt)
                    % p.name()
                    % _default
                    % _unit
                    % p.getAttribute<string>("help");
        //}
    }

    for(iter = p.begin(); iter != p.end(); ++iter) {
        if(prefix=="") {
            offset += 2; level++;
            PrintNodeHLP(out, (*iter), start_level, level, prefix + (*iter).name(), offset);
            offset -= 2; level--;
        } else {
            offset += 2; level++;
            PrintNodeHLP(out, (*iter), start_level, level, prefix + "." + (*iter).name(), offset);
            offset -= 2; level--;
        }
    }

    // if this is the head node, print the footer
    if ( level == start_level ) {
     }
}

std::ostream &operator<<(std::ostream &out, Property& p)
{
    if (!out.good())
        return out;

    std::ostream::sentry sentry(out);

    if(sentry)
    {
        // level from which to start node output
        int _level = out.iword(p.GetOutputLevel());

        switch(out.iword(p.GetFormat()))
        {
        default:
            PrintNodeTXT(out, p, _level);
        case formatXML:
            PrintNodeXML(out, p, _level);
            break;
        case formatTXT:
            PrintNodeTXT(out, p, _level);
            break;
        case formatT2T:
            PrintNodeT2T(out, "", p);
            break;
        case formatLOG:
            PrintNodeLOG(out, "", p);
            break;
        case formatTEX:
            PrintNodeTEX(out, p, _level);
            break;
        case formatHLP:
            PrintNodeHLP(out, p, _level);
            break;
        }
        out << endl;
    }

    return out;
};

//{
//      Property::PrintNode(out, "", p);
      //Property::PrintNodeXML(out, "", p, "");
//      return out;
//}

static void start_hndl(void *data, const char *el, const char **attr)
{
    stack<Property *> *property_stack =
        (stack<Property *> *)XML_GetUserData((XML_Parser*)data);

    Property *cur = property_stack->top();
    Property &np = cur->add(el, "");

    for (int i = 0; attr[i]; i += 2)
        np.setAttribute(attr[i], attr[i + 1]);

    property_stack->push(&np);
}

static void end_hndl(void *data, const char *el)
{
    stack<Property *> *property_stack =
        (stack<Property *> *)XML_GetUserData((XML_Parser*)data);
    property_stack->pop();
}

void char_hndl(void *data, const char *txt, int txtlen)
{
    stack<Property *> *property_stack =
        (stack<Property *> *)XML_GetUserData((XML_Parser*)data);

    Property *cur = property_stack->top();
    cur->value().append(txt, txtlen);
}

bool load_property_from_xml(Property &p, string filename)
{
  XML_Parser parser = XML_ParserCreate(NULL);
  if (! parser)
    throw std::runtime_error("Couldn't allocate memory for xml parser");

  XML_UseParserAsHandlerArg(parser);
  XML_SetElementHandler(parser, start_hndl, end_hndl);
  XML_SetCharacterDataHandler(parser, char_hndl);

  ifstream fl;
  fl.open(filename.c_str());
  if(!fl.is_open())
    throw std::ios_base::failure("Error on open xml file: " + filename);

  stack<Property *> pstack;
  pstack.push(&p);

  XML_SetUserData(parser, (void*)&pstack);
  while(!fl.eof()) {
    string line;
    getline(fl, line);
    line=line + "\n";
    if (! XML_Parse(parser, line.c_str(), line.length(), fl.eof()))
      throw  std::ios_base::failure(filename + ": Parse error at line " +
          boost::lexical_cast<string>(XML_GetCurrentLineNumber(parser)) + "\n" +
          XML_ErrorString(XML_GetErrorCode(parser)));
  }
  fl.close();
  return true;
}

}}
<|endoftext|>


<commit_before>void lb_populate_function_pass_manager(LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level) {
	// NOTE(bill): Treat -opt:3 as if it was -opt:2
	// TODO(bill): Determine which opt definitions should exist in the first place
	optimization_level = gb_clamp(optimization_level, 0, 2);

	if (!ignore_memcpy_pass) {
		LLVMAddMemCpyOptPass(fpm);
	}
	LLVMAddPromoteMemoryToRegisterPass(fpm);
	LLVMAddMergedLoadStoreMotionPass(fpm);
	LLVMAddConstantPropagationPass(fpm);
	LLVMAddEarlyCSEPass(fpm);

	LLVMAddConstantPropagationPass(fpm);
	LLVMAddMergedLoadStoreMotionPass(fpm);
	LLVMAddPromoteMemoryToRegisterPass(fpm);
	LLVMAddCFGSimplificationPass(fpm);

	// LLVMAddSLPVectorizePass(fpm);
	// LLVMAddLoopVectorizePass(fpm);

	// LLVMAddScalarizerPass(fpm);
	// LLVMAddLoopIdiomPass(fpm);
	if (optimization_level == 0) {
		return;
	}

#if 1
	LLVMAddSCCPPass(fpm);

	LLVMAddPromoteMemoryToRegisterPass(fpm);
	LLVMAddUnifyFunctionExitNodesPass(fpm);

	LLVMAddCFGSimplificationPass(fpm);
	LLVMAddEarlyCSEPass(fpm);
	LLVMAddLowerExpectIntrinsicPass(fpm);
#endif
}

void lb_add_function_simplifcation_passes(LLVMPassManagerRef mpm, i32 optimization_level) {
	LLVMAddEarlyCSEMemSSAPass(mpm);

	LLVMAddGVNPass(mpm);
	LLVMAddCFGSimplificationPass(mpm);

	LLVMAddJumpThreadingPass(mpm);

	// if (optimization_level > 2) {
		// LLVMAddAggressiveInstCombinerPass(mpm);
	// }
	LLVMAddInstructionCombiningPass(mpm);
	LLVMAddSimplifyLibCallsPass(mpm);

	LLVMAddTailCallEliminationPass(mpm);
	LLVMAddCFGSimplificationPass(mpm);
	LLVMAddReassociatePass(mpm);

	LLVMAddLoopRotatePass(mpm);
	LLVMAddLICMPass(mpm);
	LLVMAddLoopUnswitchPass(mpm);

	LLVMAddCFGSimplificationPass(mpm);
	LLVMAddInstructionCombiningPass(mpm);
	LLVMAddIndVarSimplifyPass(mpm);
	LLVMAddLoopIdiomPass(mpm);
	LLVMAddLoopDeletionPass(mpm);

	LLVMAddLoopUnrollPass(mpm);

	LLVMAddMergedLoadStoreMotionPass(mpm);

	LLVMAddGVNPass(mpm);

	LLVMAddMemCpyOptPass(mpm);
	LLVMAddSCCPPass(mpm);

	LLVMAddBitTrackingDCEPass(mpm);

	LLVMAddInstructionCombiningPass(mpm);
	LLVMAddJumpThreadingPass(mpm);
	LLVMAddCorrelatedValuePropagationPass(mpm);
	LLVMAddDeadStoreEliminationPass(mpm);
	LLVMAddLICMPass(mpm);

	LLVMAddLoopRerollPass(mpm);
	LLVMAddAggressiveDCEPass(mpm);
	LLVMAddCFGSimplificationPass(mpm);
	LLVMAddInstructionCombiningPass(mpm);
}

void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPassManagerRef mpm, i32 optimization_level) {

	// NOTE(bill): Treat -opt:3 as if it was -opt:2
	// TODO(bill): Determine which opt definitions should exist in the first place
	optimization_level = gb_clamp(optimization_level, 0, 2);

	LLVMAddAlwaysInlinerPass(mpm);
	LLVMAddStripDeadPrototypesPass(mpm);
	LLVMAddAnalysisPasses(target_machine, mpm);
	LLVMAddPruneEHPass(mpm);
	if (optimization_level == 0) {
		return;
	}

	LLVMAddGlobalDCEPass(mpm);

	if (optimization_level >= 2) {
		// NOTE(bill, 2021-03-29: use this causes invalid code generation)
		LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
		LLVMPassManagerBuilderPopulateModulePassManager(pmb, mpm);
		LLVMPassManagerBuilderPopulateLTOPassManager(pmb, mpm, false, true);
		LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
		// LLVMPassManagerBuilderSetSizeLevel(pmb, optimization_level);
	}

	LLVMAddIPSCCPPass(mpm);
	LLVMAddCalledValuePropagationPass(mpm);

	LLVMAddGlobalOptimizerPass(mpm);
	LLVMAddDeadArgEliminationPass(mpm);

	// LLVMAddConstantMergePass(mpm); // ???
	LLVMAddInstructionCombiningPass(mpm);
	LLVMAddCFGSimplificationPass(mpm);

	LLVMAddPruneEHPass(mpm);
	if (optimization_level < 2) {
		return;
	}

	LLVMAddFunctionInliningPass(mpm);
	lb_add_function_simplifcation_passes(mpm, optimization_level);

	LLVMAddGlobalDCEPass(mpm);
	LLVMAddGlobalOptimizerPass(mpm);

	// LLVMAddLowerConstantIntrinsicsPass(mpm);

	LLVMAddLoopRotatePass(mpm);

	LLVMAddLoopVectorizePass(mpm);

	LLVMAddInstructionCombiningPass(mpm);
	if (optimization_level >= 2) {
		LLVMAddEarlyCSEPass(mpm);
		LLVMAddCorrelatedValuePropagationPass(mpm);
		LLVMAddLICMPass(mpm);
		LLVMAddLoopUnswitchPass(mpm);
		LLVMAddCFGSimplificationPass(mpm);
		LLVMAddInstructionCombiningPass(mpm);
	}

	LLVMAddCFGSimplificationPass(mpm);

	LLVMAddSLPVectorizePass(mpm);
	LLVMAddLICMPass(mpm);

	LLVMAddAlignmentFromAssumptionsPass(mpm);

	LLVMAddStripDeadPrototypesPass(mpm);

	if (optimization_level >= 2) {
		LLVMAddGlobalDCEPass(mpm);
		LLVMAddConstantMergePass(mpm);
	}

	LLVMAddCFGSimplificationPass(mpm);
}
<commit_msg>Experiment with different opt passes<commit_after>void lb_populate_function_pass_manager(LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level) {
	// NOTE(bill): Treat -opt:3 as if it was -opt:2
	// TODO(bill): Determine which opt definitions should exist in the first place
	optimization_level = gb_clamp(optimization_level, 0, 2);

	if (!ignore_memcpy_pass) {
		LLVMAddMemCpyOptPass(fpm);
	}
	LLVMAddPromoteMemoryToRegisterPass(fpm);
	LLVMAddMergedLoadStoreMotionPass(fpm);
	LLVMAddConstantPropagationPass(fpm);
	LLVMAddEarlyCSEPass(fpm);

	LLVMAddConstantPropagationPass(fpm);
	LLVMAddMergedLoadStoreMotionPass(fpm);
	LLVMAddPromoteMemoryToRegisterPass(fpm);
	LLVMAddCFGSimplificationPass(fpm);

	// LLVMAddSLPVectorizePass(fpm);
	// LLVMAddLoopVectorizePass(fpm);

	// LLVMAddScalarizerPass(fpm);
	// LLVMAddLoopIdiomPass(fpm);
	if (optimization_level == 0) {
		return;
	}

#if 1
	LLVMAddSCCPPass(fpm);

	LLVMAddPromoteMemoryToRegisterPass(fpm);
	LLVMAddUnifyFunctionExitNodesPass(fpm);

	LLVMAddCFGSimplificationPass(fpm);
	LLVMAddEarlyCSEPass(fpm);
	LLVMAddLowerExpectIntrinsicPass(fpm);
#endif
}

void lb_add_function_simplifcation_passes(LLVMPassManagerRef mpm, i32 optimization_level) {
	LLVMAddEarlyCSEMemSSAPass(mpm);

	LLVMAddGVNPass(mpm);
	LLVMAddCFGSimplificationPass(mpm);

	LLVMAddJumpThreadingPass(mpm);

	// if (optimization_level > 2) {
		// LLVMAddAggressiveInstCombinerPass(mpm);
	// }
	LLVMAddInstructionCombiningPass(mpm);
	LLVMAddSimplifyLibCallsPass(mpm);

	LLVMAddTailCallEliminationPass(mpm);
	LLVMAddCFGSimplificationPass(mpm);
	LLVMAddReassociatePass(mpm);

	LLVMAddLoopRotatePass(mpm);
	LLVMAddLICMPass(mpm);
	LLVMAddLoopUnswitchPass(mpm);

	LLVMAddCFGSimplificationPass(mpm);
	LLVMAddInstructionCombiningPass(mpm);
	LLVMAddIndVarSimplifyPass(mpm);
	LLVMAddLoopIdiomPass(mpm);
	LLVMAddLoopDeletionPass(mpm);

	LLVMAddLoopUnrollPass(mpm);

	LLVMAddMergedLoadStoreMotionPass(mpm);

	LLVMAddGVNPass(mpm);

	LLVMAddMemCpyOptPass(mpm);
	LLVMAddSCCPPass(mpm);

	LLVMAddBitTrackingDCEPass(mpm);

	LLVMAddInstructionCombiningPass(mpm);
	LLVMAddJumpThreadingPass(mpm);
	LLVMAddCorrelatedValuePropagationPass(mpm);
	LLVMAddDeadStoreEliminationPass(mpm);
	LLVMAddLICMPass(mpm);

	LLVMAddLoopRerollPass(mpm);
	LLVMAddAggressiveDCEPass(mpm);
	LLVMAddCFGSimplificationPass(mpm);
	LLVMAddInstructionCombiningPass(mpm);
}

void lb_populate_module_pass_manager(LLVMTargetMachineRef target_machine, LLVMPassManagerRef mpm, i32 optimization_level) {

	// NOTE(bill): Treat -opt:3 as if it was -opt:2
	// TODO(bill): Determine which opt definitions should exist in the first place
	optimization_level = gb_clamp(optimization_level, 0, 2);

	LLVMAddAlwaysInlinerPass(mpm);
	LLVMAddStripDeadPrototypesPass(mpm);
	LLVMAddAnalysisPasses(target_machine, mpm);
	LLVMAddPruneEHPass(mpm);
	if (optimization_level == 0) {
		return;
	}

	LLVMAddGlobalDCEPass(mpm);

	if (optimization_level >= 2) {
		// NOTE(bill, 2021-03-29: use this causes invalid code generation)
		LLVMPassManagerBuilderRef pmb = LLVMPassManagerBuilderCreate();
		LLVMPassManagerBuilderSetOptLevel(pmb, optimization_level);
		LLVMPassManagerBuilderPopulateModulePassManager(pmb, mpm);
		LLVMPassManagerBuilderPopulateLTOPassManager(pmb, mpm, false, true);
		// LLVMPassManagerBuilderSetSizeLevel(pmb, optimization_level);
		return;
	}

	LLVMAddIPSCCPPass(mpm);
	LLVMAddCalledValuePropagationPass(mpm);

	LLVMAddGlobalOptimizerPass(mpm);
	LLVMAddDeadArgEliminationPass(mpm);

	// LLVMAddConstantMergePass(mpm); // ???
	LLVMAddInstructionCombiningPass(mpm);
	LLVMAddCFGSimplificationPass(mpm);

	LLVMAddPruneEHPass(mpm);
	if (optimization_level < 2) {
		return;
	}

	LLVMAddFunctionInliningPass(mpm);
	lb_add_function_simplifcation_passes(mpm, optimization_level);

	LLVMAddGlobalDCEPass(mpm);
	LLVMAddGlobalOptimizerPass(mpm);

	// LLVMAddLowerConstantIntrinsicsPass(mpm);

	LLVMAddLoopRotatePass(mpm);

	LLVMAddLoopVectorizePass(mpm);

	LLVMAddInstructionCombiningPass(mpm);
	if (optimization_level >= 2) {
		LLVMAddEarlyCSEPass(mpm);
		LLVMAddCorrelatedValuePropagationPass(mpm);
		LLVMAddLICMPass(mpm);
		LLVMAddLoopUnswitchPass(mpm);
		LLVMAddCFGSimplificationPass(mpm);
		LLVMAddInstructionCombiningPass(mpm);
	}

	LLVMAddCFGSimplificationPass(mpm);

	LLVMAddSLPVectorizePass(mpm);
	LLVMAddLICMPass(mpm);

	LLVMAddAlignmentFromAssumptionsPass(mpm);

	LLVMAddStripDeadPrototypesPass(mpm);

	if (optimization_level >= 2) {
		LLVMAddGlobalDCEPass(mpm);
		LLVMAddConstantMergePass(mpm);
	}

	LLVMAddCFGSimplificationPass(mpm);
}
<|endoftext|>


<commit_before>/*!
 *  \file File camera.cpp
 *  \brief Implementation of Camera class
 *
 *  The class implemented here defines the game's camera logic
 *
 *  \sa camera.hpp
 */

#include <camera.hpp>

#include <common.hpp>

#include <game.hpp>
#include <gameObject.hpp>
#include <inputManager.hpp>

// Macros declaration
#define CAMERA_SPEED 500	// unit:
#define MAX_ZOOM 1.0f		 	// unit:
#define MIN_ZOOM 0.2f			// unit:

// uint is actually the short for unsigned int
uint Camera::camera_focus = 0; //!<  Global variable defining camera focus value

Vec2 Camera::camera_position = 0;    //!<  Global variable defining camera pos
Vec2 Camera::camera_speed = 0;       //!<  Global variable defining camera speed
Vec2 Camera::camera_size{100, 50}; //!<  Global variable defining camera size

float Camera::camera_zoom = 1.0f; //!< Global variable defining camera zoom

bool Camera::camera_is_locked = false; //!< Global variable defining camera lock
bool Camera::camera_is_following = false; //!< Global variable defining camera
                                       //!< behavior

/*!
  @fn       void Camera::follow(uint new_focus)
  @brief    Method that defines the camera's focus to follow
  @param    uint new_focus
  @return   void
  @warning  none
*/

void Camera::follow(uint new_focus) { // Range: bigger than 0
  camera_is_following = true;
  camera_focus = new_focus;
}

/*!
  @fn       void Camera::unfollow()
  @brief    Method that defines the camera's focus not to follow
  @param    none
  @return   void
  @warning  none
*/

void Camera::unfollow() {
  camera_is_following = false;
}

/*!
  @fn       uint CompTimer::get_camera_focus()
  @brief    Method that returns the camera's focus value
  @param    none
  @return   unsigned int focus value
  @warning  none
*/

uint Camera::get_camera_focus() {
  return camera_focus;
}

/*!
  @fn       void Camera::update_camera(float time)
  @brief    Updates the camera
  @param    float time
  @return   void
  @warning  TODO in decision structure
*/

void Camera::update_camera(float time) {
  Vec2 center = camera_position + (WINSIZE/2/camera_zoom); //!< Newvalue for center

      // Zooms in if z key is pressed
  if (INPUT.IsKeyDown(KEY(z))) {
    camera_zoom += 0.5 * time;
    camera_zoom = min(camera_zoom, MAX_ZOOM);

    //cout<<"camera_zoom: "<<camera_zoom<<endl;
  }

  // Zooms out if x key is pressed
  if (INPUT.IsKeyDown(KEY(x))) {
    camera_zoom -= 0.5 * time;
    camera_zoom = max(camera_zoom, MIN_ZOOM);

    //cout<<"camera_zoom: "<<camera_zoom<<endl;
  }

  // Centers screen
  center_camera_to(center);

  // TODO: add else(do nothing)
  // Defines camera position in either follow or static or do nothing
  if (camera_is_following) {
    center_camera_to(GO(camera_focus)->Box().center());
  }
  else if (!camera_is_locked) {
    camera_speed = Vec2(0,0);

    // defines camera speed according to the arrow key that has been pressed.
    // (left)
    if (INPUT.IsKeyDown(KEY_LEFT)) {
      camera_speed.x -= CAMERA_SPEED;
    }

    // defines camera speed according to the arrow key that has been pressed.
    // (right)
    if (INPUT.IsKeyDown(KEY_RIGHT)){
      camera_speed.x += CAMERA_SPEED;
    }

    // defines camera speed according to the arrow key that has been pressed.
    // (up)
    if (INPUT.IsKeyDown(KEY_UP)) {
      camera_speed.y -= CAMERA_SPEED;
    }

    // defines camera speed according to the arrow key that has been pressed.
    // (down)
    if (INPUT.IsKeyDown(KEY_DOWN)) {
      camera_speed.y += CAMERA_SPEED;
    }

    // TODO: math refactoring
    camera_speed /= camera_zoom;
    camera_speed *= time;
    camera_position += camera_speed;

    // if (camera_speed != Vec2(0,0)) {
    // 	cout << "camera x= " << pos.x << "\t y= " << pos.y << endl;
    // }
  }
}

/*!
  @fn       void Camera::CenterTo(const Vec2& vector)
  @brief    Centers camera to a pre-stablished position
  @param    const Vec2& vector
  @return   void
  @warning  TODO: some math must be simplified
*/

void Camera::center_camera_to(const Vec2& vec2_vector) {
  // TODO: break down math
  Vec2 target = vec2_vector - (WINSIZE/2/camera_zoom); //!< Updates the camera
                                                       //!< target
  // Minimum values
  camera_position.x = min(camera_position.x, target.x + camera_size.x);
  camera_position.y = min(camera_position.y, target.y + camera_size.y);

  // maximum vaues
  camera_position.x = max(camera_position.x, target.x - camera_size.x);
  camera_position.y = max(camera_position.y, target.y - camera_size.y);
}

/*!
  @fn       Vec2 Camera::render_camera_pos(const Vec2& vec2_vector)
  @brief    Renders camera's position
  @param    const Vec2& vec2_vector
  @return   Rendered camera position
  @warning  TODO: fix return to no longer be an math expression
*/

Vec2 Camera::render_camera_pos(const Vec2& vec2_vector) {
  return (vec2_vector - CAMERA) * CAMERAZOOM;
}

/*!
  @fn       float Camera::render_camera_pos_x(const float& x_axis_pos)
  @brief    Method that renders x axis position
  @param    const float& x_axis_pos
  @return   Rendered position on x axis for camera
  @warning  TODO: fix return to no longer be an math expression
*/

float Camera::render_camera_pos_x(const float& x_axis_pos) {
  return (x_axis_pos - CAMERA.x) * CAMERAZOOM;
}

/*!
  @fn       float Camera::render_camera_pos_y(const float& y_axis_pos)
  @brief    Method that renders y axis position
  @param    const float& y_axis_pos
  @return   Rendered position on y axis for camera
  @warning  TODO: fix return to no longer be an math expression
*/

float Camera::render_camera_pos_y(const float& y_axis_pos) {
  return (y_axis_pos - CAMERA.y) * CAMERAZOOM;
}
<commit_msg>Applies elses technique at file camera.cpp<commit_after>/*!
 *  \file File camera.cpp
 *  \brief Implementation of Camera class
 *
 *  The class implemented here defines the game's camera logic
 *
 *  \sa camera.hpp
 */

#include <camera.hpp>

#include <common.hpp>

#include <game.hpp>
#include <gameObject.hpp>
#include <inputManager.hpp>

// Macros declaration
#define CAMERA_SPEED 500	// unit:
#define MAX_ZOOM 1.0f		 	// unit:
#define MIN_ZOOM 0.2f			// unit:

// uint is actually the short for unsigned int
uint Camera::camera_focus = 0; //!<  Global variable defining camera focus value

Vec2 Camera::camera_position = 0;    //!<  Global variable defining camera pos
Vec2 Camera::camera_speed = 0;       //!<  Global variable defining camera speed
Vec2 Camera::camera_size{100, 50}; //!<  Global variable defining camera size

float Camera::camera_zoom = 1.0f; //!< Global variable defining camera zoom

bool Camera::camera_is_locked = false; //!< Global variable defining camera lock
bool Camera::camera_is_following = false; //!< Global variable defining camera
                                       //!< behavior

/*!
  @fn       void Camera::follow(uint new_focus)
  @brief    Method that defines the camera's focus to follow
  @param    uint new_focus
  @return   void
  @warning  none
*/

void Camera::follow(uint new_focus) { // Range: bigger than 0
  camera_is_following = true;
  camera_focus = new_focus;
}

/*!
  @fn       void Camera::unfollow()
  @brief    Method that defines the camera's focus not to follow
  @param    none
  @return   void
  @warning  none
*/

void Camera::unfollow() {
  camera_is_following = false;
}

/*!
  @fn       uint CompTimer::get_camera_focus()
  @brief    Method that returns the camera's focus value
  @param    none
  @return   unsigned int focus value
  @warning  none
*/

uint Camera::get_camera_focus() {
  return camera_focus;
}

/*!
  @fn       void Camera::update_camera(float time)
  @brief    Updates the camera
  @param    float time
  @return   void
  @warning  TODO in decision structure
*/

void Camera::update_camera(float time) {
  Vec2 center = camera_position + (WINSIZE/2/camera_zoom); //!< Newvalue for center

      // Zooms in if z key is pressed
  if (INPUT.IsKeyDown(KEY(z))) {
    camera_zoom += 0.5 * time;
    camera_zoom = min(camera_zoom, MAX_ZOOM);

    //cout<<"camera_zoom: "<<camera_zoom<<endl;
  }
  else {
    // Do nothing
  }

  // Zooms out if x key is pressed
  if (INPUT.IsKeyDown(KEY(x))) {
    camera_zoom -= 0.5 * time;
    camera_zoom = max(camera_zoom, MIN_ZOOM);

    //cout<<"camera_zoom: "<<camera_zoom<<endl;
  }
  else {
    // Do nothing
  }

  // Centers screen
  center_camera_to(center);

  // TODO: add else(do nothing)
  // Defines camera position in either follow or static or do nothing
  if (camera_is_following) {
    center_camera_to(GO(camera_focus)->Box().center());
  }
  else if (!camera_is_locked) {
    camera_speed = Vec2(0,0);

    // defines camera speed according to the arrow key that has been pressed.
    // (left)
    if (INPUT.IsKeyDown(KEY_LEFT)) {
      camera_speed.x -= CAMERA_SPEED;
    }
    else {
      // Do nothing
    }

    // defines camera speed according to the arrow key that has been pressed.
    // (right)
    if (INPUT.IsKeyDown(KEY_RIGHT)){
      camera_speed.x += CAMERA_SPEED;
    }
    else {
      // Do nothing
    }

    // defines camera speed according to the arrow key that has been pressed.
    // (up)
    if (INPUT.IsKeyDown(KEY_UP)) {
      camera_speed.y -= CAMERA_SPEED;
    }
    else {
      // Do nothing
    }

    // defines camera speed according to the arrow key that has been pressed.
    // (down)
    if (INPUT.IsKeyDown(KEY_DOWN)) {
      camera_speed.y += CAMERA_SPEED;
    }
    else {
      // Do nothing
    }

    // TODO: math refactoring
    camera_speed /= camera_zoom;
    camera_speed *= time;
    camera_position += camera_speed;

    // if (camera_speed != Vec2(0,0)) {
    // 	cout << "camera x= " << pos.x << "\t y= " << pos.y << endl;
    // }
  }
}

/*!
  @fn       void Camera::CenterTo(const Vec2& vector)
  @brief    Centers camera to a pre-stablished position
  @param    const Vec2& vector
  @return   void
  @warning  TODO: some math must be simplified
*/

void Camera::center_camera_to(const Vec2& vec2_vector) {
  // TODO: break down math
  Vec2 target = vec2_vector - (WINSIZE/2/camera_zoom); //!< Updates the camera
                                                       //!< target
  // Minimum values
  camera_position.x = min(camera_position.x, target.x + camera_size.x);
  camera_position.y = min(camera_position.y, target.y + camera_size.y);

  // maximum vaues
  camera_position.x = max(camera_position.x, target.x - camera_size.x);
  camera_position.y = max(camera_position.y, target.y - camera_size.y);
}

/*!
  @fn       Vec2 Camera::render_camera_pos(const Vec2& vec2_vector)
  @brief    Renders camera's position
  @param    const Vec2& vec2_vector
  @return   Rendered camera position
  @warning  TODO: fix return to no longer be an math expression
*/

Vec2 Camera::render_camera_pos(const Vec2& vec2_vector) {
  return (vec2_vector - CAMERA) * CAMERAZOOM;
}

/*!
  @fn       float Camera::render_camera_pos_x(const float& x_axis_pos)
  @brief    Method that renders x axis position
  @param    const float& x_axis_pos
  @return   Rendered position on x axis for camera
  @warning  TODO: fix return to no longer be an math expression
*/

float Camera::render_camera_pos_x(const float& x_axis_pos) {
  return (x_axis_pos - CAMERA.x) * CAMERAZOOM;
}

/*!
  @fn       float Camera::render_camera_pos_y(const float& y_axis_pos)
  @brief    Method that renders y axis position
  @param    const float& y_axis_pos
  @return   Rendered position on y axis for camera
  @warning  TODO: fix return to no longer be an math expression
*/

float Camera::render_camera_pos_y(const float& y_axis_pos) {
  return (y_axis_pos - CAMERA.y) * CAMERAZOOM;
}
<|endoftext|>


<commit_before>// $Id: timeStamp.C,v 1.9 2000/12/09 21:28:28 amoll Exp $

#include <BALL/CONCEPT/timeStamp.h>
#include <BALL/CONCEPT/persistenceManager.h>

#include <sys/time.h>

using namespace std;

namespace BALL
{

	void PreciseTime::write(PersistenceManager& pm) const
		throw()
  {
		pm.writePrimitive(secs_, "secs_");
		pm.writePrimitive(usecs_, "usecs_");
	}

	bool PreciseTime::read(PersistenceManager& pm)
		throw()
	{
		return (pm.readPrimitive(secs_, "secs_") && pm.readPrimitive(usecs_, "usecs_"));
	}

	PreciseTime PreciseTime::now()
		throw()
	{
		// get the current time via the system call
		// gettimeofday()
		struct timeval tv;
		gettimeofday(&tv, 0);

		return PreciseTime(tv.tv_sec, tv.tv_usec);
	}

	const PreciseTime PreciseTime::ZERO;

  ostream& operator << (ostream& os, const PreciseTime& time)
		throw()
	{
		String usecs((double)time.getMicroSeconds() / 1.0e6);
		time_t secs = (time_t)time.getSeconds();
		static char buf[128];
		strftime(buf, 127, "%Y%m%d%H%M%S", localtime(&secs));

		return os << buf << "." << usecs.after(".");
	}

  ostream& operator << (ostream& os, const TimeStamp& stamp)
		throw()
	{
		return os << stamp.getTime();
	}

# ifdef BALL_NO_INLINE_FUNCTIONS
#   include <BALL/CONCEPT/timeStamp.iC>
# endif

}
<commit_msg>moved include to inline file<commit_after>// $Id: timeStamp.C,v 1.10 2000/12/10 21:19:51 amoll Exp $

#include <BALL/CONCEPT/timeStamp.h>

#include <sys/time.h>

using namespace std;

namespace BALL
{

	void PreciseTime::write(PersistenceManager& pm) const
		throw()
  {
		pm.writePrimitive(secs_, "secs_");
		pm.writePrimitive(usecs_, "usecs_");
	}

	bool PreciseTime::read(PersistenceManager& pm)
		throw()
	{
		return (pm.readPrimitive(secs_, "secs_") && pm.readPrimitive(usecs_, "usecs_"));
	}

	PreciseTime PreciseTime::now()
		throw()
	{
		// get the current time via the system call
		// gettimeofday()
		struct timeval tv;
		gettimeofday(&tv, 0);

		return PreciseTime(tv.tv_sec, tv.tv_usec);
	}

	const PreciseTime PreciseTime::ZERO;

  ostream& operator << (ostream& os, const PreciseTime& time)
		throw()
	{
		String usecs((double)time.getMicroSeconds() / 1.0e6);
		time_t secs = (time_t)time.getSeconds();
		static char buf[128];
		strftime(buf, 127, "%Y%m%d%H%M%S", localtime(&secs));

		return os << buf << "." << usecs.after(".");
	}

  ostream& operator << (ostream& os, const TimeStamp& stamp)
		throw()
	{
		return os << stamp.getTime();
	}

# ifdef BALL_NO_INLINE_FUNCTIONS
#   include <BALL/CONCEPT/timeStamp.iC>
# endif

}
<|endoftext|>