<commit_before>/**
 * Copyright © 2019 IBM Corporation
 *
 * 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 "data_interface.hpp"
#include "elog_entry.hpp"
#include "event_logger.hpp"
#include "extensions.hpp"
#include "manager.hpp"
#include "pldm_interface.hpp"

#include <phosphor-logging/log.hpp>

#ifdef SBE_FFDC_SUPPORTED
#include <libekb.H>
#include <libpdbg.h>
#endif

namespace openpower
{
namespace pels
{

using namespace phosphor::logging;

std::unique_ptr<Manager> manager;

DISABLE_LOG_ENTRY_CAPS()

void pelStartup(internal::Manager& logManager)
{
    EventLogger::LogFunction logger = std::bind(
        std::mem_fn(&internal::Manager::create), &logManager,
        std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);

    std::unique_ptr<DataInterfaceBase> dataIface =
        std::make_unique<DataInterface>(logManager.getBus());

#ifndef DONT_SEND_PELS_TO_HOST
    std::unique_ptr<HostInterface> hostIface = std::make_unique<PLDMInterface>(
        logManager.getBus().get_event(), *(dataIface.get()));

    manager =
        std::make_unique<Manager>(logManager, std::move(dataIface),
                                  std::move(logger), std::move(hostIface));
#else
    manager = std::make_unique<Manager>(logManager, std::move(dataIface),
                                        std::move(logger));
#endif

#ifdef SBE_FFDC_SUPPORTED
    if (!pdbg_targets_init(NULL))
    {
        log<level::ERR>("pdbg_targets_init failed");
        throw std::runtime_error("pdbg target initialization failed");
    }

    if (libekb_init())
    {
        log<level::ERR>("libekb_init failed");
        throw std::runtime_error("libekb initialization failed");
    }
#endif
}

REGISTER_EXTENSION_FUNCTION(pelStartup)

void pelCreate(const std::string& message, uint32_t id, uint64_t timestamp,
               Entry::Level severity, const AdditionalDataArg& additionalData,
               const AssociationEndpointsArg& assocs, const FFDCArg& ffdc)
{
    manager->create(message, id, timestamp, severity, additionalData, assocs,
                    ffdc);
}

REGISTER_EXTENSION_FUNCTION(pelCreate)

void pelDelete(uint32_t id)
{
    return manager->erase(id);
}

REGISTER_EXTENSION_FUNCTION(pelDelete)

void pelDeleteProhibited(uint32_t id, bool& prohibited)
{
    prohibited = manager->isDeleteProhibited(id);
}

REGISTER_EXTENSION_FUNCTION(pelDeleteProhibited)

} // namespace pels
} // namespace openpower
<commit_msg>PEL: set pdbg environment variable<commit_after>/**
 * Copyright © 2019 IBM Corporation
 *
 * 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 "data_interface.hpp"
#include "elog_entry.hpp"
#include "event_logger.hpp"
#include "extensions.hpp"
#include "manager.hpp"
#include "pldm_interface.hpp"

#include <fmt/format.h>

#include <phosphor-logging/log.hpp>

#ifdef SBE_FFDC_SUPPORTED
#include <libekb.H>
#include <libpdbg.h>
#endif

namespace openpower
{
namespace pels
{

using namespace phosphor::logging;

std::unique_ptr<Manager> manager;

DISABLE_LOG_ENTRY_CAPS()

void pelStartup(internal::Manager& logManager)
{
    EventLogger::LogFunction logger = std::bind(
        std::mem_fn(&internal::Manager::create), &logManager,
        std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);

    std::unique_ptr<DataInterfaceBase> dataIface =
        std::make_unique<DataInterface>(logManager.getBus());

#ifndef DONT_SEND_PELS_TO_HOST
    std::unique_ptr<HostInterface> hostIface = std::make_unique<PLDMInterface>(
        logManager.getBus().get_event(), *(dataIface.get()));

    manager =
        std::make_unique<Manager>(logManager, std::move(dataIface),
                                  std::move(logger), std::move(hostIface));
#else
    manager = std::make_unique<Manager>(logManager, std::move(dataIface),
                                        std::move(logger));
#endif

#ifdef SBE_FFDC_SUPPORTED
    // PDBG_DTB environment variable set to CEC device tree path
    static constexpr auto PDBG_DTB_PATH =
        "/var/lib/phosphor-software-manager/pnor/rw/DEVTREE";

    if (setenv("PDBG_DTB", PDBG_DTB_PATH, 1))
    {
        // Log message and continue,
        // This is to help continue creating PEL in raw format.
        log<level::ERR>(
            fmt::format("Failed to set PDBG_DTB: ({})", strerror(errno))
                .c_str());
    }

    if (!pdbg_targets_init(NULL))
    {
        log<level::ERR>("pdbg_targets_init failed");
        throw std::runtime_error("pdbg target initialization failed");
    }

    if (libekb_init())
    {
        log<level::ERR>("libekb_init failed");
        throw std::runtime_error("libekb initialization failed");
    }
#endif
}

REGISTER_EXTENSION_FUNCTION(pelStartup)

void pelCreate(const std::string& message, uint32_t id, uint64_t timestamp,
               Entry::Level severity, const AdditionalDataArg& additionalData,
               const AssociationEndpointsArg& assocs, const FFDCArg& ffdc)
{
    manager->create(message, id, timestamp, severity, additionalData, assocs,
                    ffdc);
}

REGISTER_EXTENSION_FUNCTION(pelCreate)

void pelDelete(uint32_t id)
{
    return manager->erase(id);
}

REGISTER_EXTENSION_FUNCTION(pelDelete)

void pelDeleteProhibited(uint32_t id, bool& prohibited)
{
    prohibited = manager->isDeleteProhibited(id);
}

REGISTER_EXTENSION_FUNCTION(pelDeleteProhibited)

} // namespace pels
} // namespace openpower
<|endoftext|>


<commit_before>/*
 *  Vehicle.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Tue May 25 2004.
 *  Copyright (c) 2004 Alyssa Milburn. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 */

#include "Vehicle.h"
#include "Engine.h"
#include "World.h"
#include "MetaRoom.h"

Vehicle::Vehicle(unsigned int family, unsigned int genus, unsigned int species, unsigned int plane,
		std::string spritefile, unsigned int firstimage, unsigned int imagecount) :
		CompoundAgent(family, genus, species, plane, spritefile, firstimage, imagecount) {
	capacity = 0;
	bump = 0;

	cabinleft = (int)x;
	cabinright = (int)x + getWidth();
	cabintop = (int)y;
	cabinbottom = (int)y + getHeight();
}

Vehicle::Vehicle(std::string spritefile, unsigned int firstimage, unsigned int imagecount) : CompoundAgent(spritefile, firstimage, imagecount) {
	capacity = 0;
	bump = 0;

	// TODO: set cabin bounds?
}

void Vehicle::tick() {
	CompoundAgent::tick();
	if (paused) return;

	if (xvec.getInt() != 0 && engine.version == 1) {
		// handle magical C1 vehicle world wrapping, if necessary

		MetaRoom *m = world.map.metaRoomAt(x, y);
		if (!m) {
			std::cout << "BUG: moving c1 vehicle " << identify() << " is out of room system at " << x << ", " << y << ", so killing it" << std::endl;
			kill();
			return;
		}

		if (x + (xvec.getInt() / 256.0) < m->x()) {
			assert(xvec.getInt() < 0);
			x += m->width();
		} else if (x + (xvec.getInt() / 256.0) > m->x() + m->width()) {
			assert(xvec.getInt() > 0);
			x -= m->width();
		}
	}

	// move by xvec/yvec!
	x += xvec.getInt() / 256.0;
	y += yvec.getInt() / 256.0;
}

/* vim: set noet: */
<commit_msg>oops: set the right default cabin rect for Vehicle<commit_after>/*
 *  Vehicle.cpp
 *  openc2e
 *
 *  Created by Alyssa Milburn on Tue May 25 2004.
 *  Copyright (c) 2004 Alyssa Milburn. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 */

#include "Vehicle.h"
#include "Engine.h"
#include "World.h"
#include "MetaRoom.h"

Vehicle::Vehicle(unsigned int family, unsigned int genus, unsigned int species, unsigned int plane,
		std::string spritefile, unsigned int firstimage, unsigned int imagecount) :
		CompoundAgent(family, genus, species, plane, spritefile, firstimage, imagecount) {
	capacity = 0;
	bump = 0;

	cabinleft = 0; cabintop = 0; cabinright = getWidth(); cabinbottom = getHeight();
}

Vehicle::Vehicle(std::string spritefile, unsigned int firstimage, unsigned int imagecount) : CompoundAgent(spritefile, firstimage, imagecount) {
	capacity = 0;
	bump = 0;

	// TODO: set cabin bounds? we don't know width/height at this point..
}

void Vehicle::tick() {
	CompoundAgent::tick();
	if (paused) return;

	if (xvec.getInt() != 0 && engine.version == 1) {
		// handle magical C1 vehicle world wrapping, if necessary

		MetaRoom *m = world.map.metaRoomAt(x, y);
		if (!m) {
			std::cout << "BUG: moving c1 vehicle " << identify() << " is out of room system at " << x << ", " << y << ", so killing it" << std::endl;
			kill();
			return;
		}

		if (x + (xvec.getInt() / 256.0) < m->x()) {
			assert(xvec.getInt() < 0);
			x += m->width();
		} else if (x + (xvec.getInt() / 256.0) > m->x() + m->width()) {
			assert(xvec.getInt() > 0);
			x -= m->width();
		}
	}

	// move by xvec/yvec!
	x += xvec.getInt() / 256.0;
	y += yvec.getInt() / 256.0;
}

/* vim: set noet: */
<|endoftext|>


<commit_before>#include "stdsneezy.h"
#include "database.h"

#include <map>
#include "sstring.h"

#include "cgicc/Cgicc.h"
#include "cgicc/HTTPHTMLHeader.h"
#include "cgicc/HTMLClasses.h"
#include <cgicc/HTTPCookie.h>
#include <cgicc/CgiEnvironment.h>
#include <cgicc/HTTPRedirectHeader.h>

#include <sys/types.h>
#include <md5.h>

using namespace cgicc;

Cgicc cgi;

sstring getSessionID();
void sendLogin();
void sendLoginCheck();
sstring generateSessionID();
int validateSessionID(sstring);
void sendPickPlayer(int);
void sendJavaScript();

int main(int argc, char **argv)
{
  // trick the db code into using the prod database
  gamePort = PROD_GAMEPORT;
  toggleInfo.loadToggles();
  form_iterator state_form=cgi.getElement("state");

  sstring session_id=getSessionID();
  int account_id=validateSessionID(session_id);

  // this if statement sucks
  if(session_id.empty()){
    if(state_form == cgi.getElements().end() ||
       **state_form != "logincheck"){
      sendLogin();
      return 0;
    } else {
      sendLoginCheck();
      return 0;
    }
  } else if(account_id < 0){
    sendLogin();
    return 0;
  } else {
    if(state_form == cgi.getElements().end() || **state_form == "main"){
      sendPickPlayer(account_id);
      return 0;
    }

    cout << HTTPHTMLHeader() << endl;
    cout << html() << head() << title("Mudmail") << endl;
    cout << head() << body() << endl;
    cout << "Fell through state switch.

" << endl;
    cout << body() << endl;
    cout << html() << endl;

    return 0;
  }

  // shouldn't get here
  cout << HTTPHTMLHeader() << endl;
  cout << html() << head() << title("Mudmail") << endl;
  cout << head() << body() << endl;
  cout << "This is bad.

" << endl;
  cout << body() << endl;
  cout << html() << endl;

}

int validateSessionID(sstring session_id)
{
  TDatabase db(DB_SNEEZY);

  db.query("select account_id from cgisession where session_id='%s'",
	   session_id.c_str());

  if(!db.fetchRow())
    return -1;

  return convertTo<int>(db["account_id"]);
}

// gets the value of the "mudmail" cookie and returns it
sstring getSessionID()
{
  CgiEnvironment env = cgi.getEnvironment();
  vector<HTTPCookie> cookies = env.getCookieList();

  if(!cookies.size())
    return "";

  for(unsigned int i=0;i<cookies.size();++i){
    if(cookies[i].getName() == "mudmail")
      return cookies[i].getValue();
  }
  return "";
}

void sendLoginCheck()
{
  // validate, create session cookie + db entry, redirect to main
  TDatabase db(DB_SNEEZY);
  sstring name=**(cgi.getElement("account"));
  sstring passwd=**(cgi.getElement("passwd"));

  //// make sure the account exists, and pull out the encrypted password
  db.query("select account_id, passwd from account where name='%s'",
	   name.c_str());

  if(!db.fetchRow()){
    cout << HTTPHTMLHeader() << endl;
    cout << html() << head() << title("Mudmail") << endl;
    cout << head() << body() << endl;
    cout << "Account not found.

" << endl;
    cout << body() << endl;
    cout << html() << endl;
    return;
  }

  //// validate password
  sstring crypted=crypt(passwd.c_str(), name.c_str());

  // for some retarded reason the mud truncates the crypted portion to 10 chars
  if(crypted.substr(0,10) != db["passwd"]){
    cout << HTTPHTMLHeader() << endl;
    cout << html() << head() << title("Mudmail") << endl;
    cout << head() << body() << endl;
    cout << "Password incorrect.

" << endl;
    cout << body() << endl;
    cout << html() << endl;
    return;
  }

  // ok, login is good, create session db entry and cookie
  sstring session_id=generateSessionID();
  int account_id=convertTo<int>(db["account_id"]);

  db.query("delete from cgisession where account_id=%i", account_id);
  db.query("insert into cgisession values ('%s', %i)",
	   session_id.c_str(), account_id);

  cout << HTTPRedirectHeader("mudmail.cgi").setCookie(HTTPCookie("mudmail",session_id.c_str()));
  cout << endl;
  cout << html() << head() << title("Mudmail") << endl;
  cout << head() << body() << endl;
  cout << "Good job, you logged in.

" << endl;
  cout << body() << endl;
  cout << html() << endl;
}

sstring generateSessionID()
{
  unsigned char data[16];
  int length=16;
  int seed[4];

  srandomdev();

  seed[0]=time(NULL);
  seed[1]=random();
  seed[2]=getpid();
  seed[3]=(int)&seed;

  int c=0;
  for(int i=0;i<4;++i){
    for(int j=0;j<4;++j){
      data[c++]=(&seed[i])[j];
    }
  }

  return MD5Data(data, length, NULL);
}

void sendLogin()
{
  cout << HTTPHTMLHeader() << endl;
  cout << html() << head() << title("Mudmail") << endl;
  cout << head() << body() << endl;

  cout << "<form action=\"mudmail.cgi\" method=post>" << endl;
  cout << "
" << endl;
  cout << "
Account	" << endl;
  cout << "<input type=text name=account>
" << endl;
  cout << "
Password	" << endl;
  cout << "<input type=password name=passwd>
" << endl;
  cout << "
<input type=submit value=Login>
" <<endl;
  cout << "
" << endl;
  cout << "<input type=hidden name=state value=logincheck>" << endl;
  cout << "</form>" << endl;

  cout << body() << endl;
  cout << html() << endl;
}

void sendPickPlayer(int account_id)
{
  TDatabase db(DB_SNEEZY);

  cout << HTTPHTMLHeader() << endl;
  cout << html() << head() << title("Mudmail") << endl;
  sendJavaScript();
  cout << head() << body() << endl;

  // get a list of players in this account
  db.query("select p.id, p.name, count(m.*) as count from player p left outer join mail m on (p.name=m.mailto) where account_id=%i group by p.id, p.name order by p.name",
	   account_id);

  if(!db.fetchRow()){
    cout << "No players were found in this account." << endl;
    return;
  }

  cout << "<form action=\"mudmail.cgi\" method=post name=pickplayer>" << endl;
  cout << "<input type=hidden name=player>" << endl;
  cout << "<input type=hidden name=state value=listmessages>" << endl;
  cout << "
" << endl;
  cout << "
Player	# of Letters
";

  do {
    cout << "
" << endl;
    cout << "<a href=javascript:pickplayer('" << db["id"] << "')>";
    cout << db["name"] << "	" << endl;
    cout << db["count"] << "
";
  } while(db.fetchRow());

  cout << "</form>" << endl;

  cout << body() << endl;
  cout << html() << endl;
}

void sendJavaScript()
{
  cout << "" << endl;
}

<commit_msg>added message list and logout<commit_after>#include "stdsneezy.h"
#include "database.h"

#include <map>
#include "sstring.h"

#include "cgicc/Cgicc.h"
#include "cgicc/HTTPHTMLHeader.h"
#include "cgicc/HTMLClasses.h"
#include <cgicc/HTTPCookie.h>
#include <cgicc/CgiEnvironment.h>
#include <cgicc/HTTPRedirectHeader.h>

#include <sys/types.h>
#include <md5.h>

using namespace cgicc;

Cgicc cgi;

sstring getSessionID();
sstring generateSessionID();
int validateSessionID(sstring);

void sendJavaScript();

void sendLogin();
void sendLoginCheck();
void sendPickPlayer(int);
void sendMessageList(int);

int main(int argc, char **argv)
{
  // trick the db code into using the prod database
  gamePort = PROD_GAMEPORT;
  toggleInfo.loadToggles();
  form_iterator state_form=cgi.getElement("state");

  sstring session_id=getSessionID();
  int account_id=validateSessionID(session_id);

  // this if statement sucks
  if(session_id.empty() || account_id < 0){
    if(state_form == cgi.getElements().end() ||
       **state_form != "logincheck"){
      sendLogin();
      return 0;
    } else {
      sendLoginCheck();
      return 0;
    }
  } else {
    if(state_form == cgi.getElements().end() || **state_form == "main"){
      sendPickPlayer(account_id);
      return 0;
    } else if(**state_form == "listmessages"){
      sendMessageList(account_id);
      return 0;
    } else if(**state_form == "logout"){
      TDatabase db(DB_SNEEZY);
      db.query("delete from cgisession where session_id='%s'",
	       session_id.c_str());
      sendLogin();
      return 0;
    }

    cout << HTTPHTMLHeader() << endl;
    cout << html() << head() << title("Mudmail") << endl;
    cout << head() << body() << endl;
    cout << "Fell through state switch.

" << endl;
    cout << body() << endl;
    cout << html() << endl;

    return 0;
  }

  // shouldn't get here
  cout << HTTPHTMLHeader() << endl;
  cout << html() << head() << title("Mudmail") << endl;
  cout << head() << body() << endl;
  cout << "This is bad.

" << endl;
  cout << body() << endl;
  cout << html() << endl;

}

void sendMessageList(int account_id)
{
  int player_id=convertTo<int>(**(cgi.getElement("player")));
  TDatabase db(DB_SNEEZY);

  cout << HTTPHTMLHeader() << endl;
  cout << html() << head() << title("Mudmail") << endl;
  cout << head() << body() << endl;

  db.query("select m.mailfrom, m.timesent, m.content from mail m, player p where m.mailto=p.name and p.id=%i", player_id);

  cout << "
" << endl;

  while(db.fetchRow()){
    cout << "
" << db["mailfrom"] << endl;
    cout << "	" << db["timesent"] << endl;
    cout << "

" << db["content"] << endl;
    cout << "
" << endl;
  }

  cout << "
" << endl;

  cout << body() << endl;
  cout << html() << endl;
}

int validateSessionID(sstring session_id)
{
  TDatabase db(DB_SNEEZY);

  db.query("select account_id from cgisession where session_id='%s'",
	   session_id.c_str());

  if(!db.fetchRow())
    return -1;

  return convertTo<int>(db["account_id"]);
}

// gets the value of the "mudmail" cookie and returns it
sstring getSessionID()
{
  CgiEnvironment env = cgi.getEnvironment();
  vector<HTTPCookie> cookies = env.getCookieList();

  if(!cookies.size())
    return "";

  for(unsigned int i=0;i<cookies.size();++i){
    if(cookies[i].getName() == "mudmail")
      return cookies[i].getValue();
  }
  return "";
}

void sendLoginCheck()
{
  // validate, create session cookie + db entry, redirect to main
  TDatabase db(DB_SNEEZY);
  sstring name=**(cgi.getElement("account"));
  sstring passwd=**(cgi.getElement("passwd"));

  //// make sure the account exists, and pull out the encrypted password
  db.query("select account_id, passwd from account where name='%s'",
	   name.c_str());

  if(!db.fetchRow()){
    cout << HTTPHTMLHeader() << endl;
    cout << html() << head() << title("Mudmail") << endl;
    cout << head() << body() << endl;
    cout << "Account not found.

" << endl;
    cout << body() << endl;
    cout << html() << endl;
    return;
  }

  //// validate password
  sstring crypted=crypt(passwd.c_str(), name.c_str());

  // for some retarded reason the mud truncates the crypted portion to 10 chars
  if(crypted.substr(0,10) != db["passwd"]){
    cout << HTTPHTMLHeader() << endl;
    cout << html() << head() << title("Mudmail") << endl;
    cout << head() << body() << endl;
    cout << "Password incorrect.

" << endl;
    cout << body() << endl;
    cout << html() << endl;
    return;
  }

  // ok, login is good, create session db entry and cookie
  sstring session_id=generateSessionID();
  int account_id=convertTo<int>(db["account_id"]);

  db.query("delete from cgisession where account_id=%i", account_id);
  db.query("insert into cgisession values ('%s', %i)",
	   session_id.c_str(), account_id);

  cout << HTTPRedirectHeader("mudmail.cgi").setCookie(HTTPCookie("mudmail",session_id.c_str()));
  cout << endl;
  cout << html() << head() << title("Mudmail") << endl;
  cout << head() << body() << endl;
  cout << "Good job, you logged in.

" << endl;
  cout << body() << endl;
  cout << html() << endl;
}

sstring generateSessionID()
{
  unsigned char data[16];
  int length=16;
  int seed[4];

  srandomdev();

  seed[0]=time(NULL);
  seed[1]=random();
  seed[2]=getpid();
  seed[3]=(int)&seed;

  int c=0;
  for(int i=0;i<4;++i){
    for(int j=0;j<4;++j){
      data[c++]=(&seed[i])[j];
    }
  }

  return MD5Data(data, length, NULL);
}

void sendLogin()
{
  cout << HTTPHTMLHeader() << endl;
  cout << html() << head() << title("Mudmail") << endl;
  cout << head() << body() << endl;

  cout << "<form action=\"mudmail.cgi\" method=post>" << endl;
  cout << "
" << endl;
  cout << "
Account	" << endl;
  cout << "<input type=text name=account>
" << endl;
  cout << "
Password	" << endl;
  cout << "<input type=password name=passwd>
" << endl;
  cout << "
<input type=submit value=Login>
" <<endl;
  cout << "
" << endl;
  cout << "<input type=hidden name=state value=logincheck>" << endl;
  cout << "</form>" << endl;

  cout << body() << endl;
  cout << html() << endl;
}

void sendPickPlayer(int account_id)
{
  TDatabase db(DB_SNEEZY);

  cout << HTTPHTMLHeader() << endl;
  cout << html() << head() << title("Mudmail") << endl;
  sendJavaScript();
  cout << head() << body() << endl;
  cout << "Logout
" << endl;

  // get a list of players in this account
  db.query("select p.id, p.name, count(m.*) as count from player p left outer join mail m on (p.name=m.mailto) where account_id=%i group by p.id, p.name order by p.name",
	   account_id);

  if(!db.fetchRow()){
    cout << "No players were found in this account." << endl;
    return;
  }

  cout << "<form action=\"mudmail.cgi\" method=post name=pickplayer>" << endl;
  cout << "<input type=hidden name=player>" << endl;
  cout << "<input type=hidden name=state value=listmessages>" << endl;
  cout << "
" << endl;
  cout << "
Player	# of Letters
";

  do {
    cout << "
" << endl;
    cout << "<a href=javascript:pickplayer('" << db["id"] << "')>";
    cout << db["name"] << "	" << endl;
    cout << db["count"] << "
";
  } while(db.fetchRow());

  cout << "</form>" << endl;

  cout << body() << endl;
  cout << html() << endl;
}

void sendJavaScript()
{
  cout << "" << endl;
}

<|endoftext|>


<commit_before>#include "monolingual.hpp"
#include "bilingual.hpp"

/**
 * @brief Compute cosine similarity between word1 and word2.
 * For the score to be in [0,1], the weights need to be normalized beforehand.
 * Return 0 if word1 or word2 is unknown.
 */
float MonolingualModel::similarity(const string& word1, const string& word2, int policy) const {
    auto it1 = vocabulary.find(word1);
    auto it2 = vocabulary.find(word2);

    if (it1 == vocabulary.end() || it2 == vocabulary.end()) {
        return 0.0;
    } else if (it1->second.index == it2->second.index) {
        return 1.0;
    } else {
        vec v1 = wordVec(it1->second.index, policy);
        vec v2 = wordVec(it2->second.index, policy);
        return cosineSimilarity(v1, v2);
    }
}

float MonolingualModel::distance(const string& word1, const string& word2, int policy) const {
    return 1 - similarity(word1, word2, policy);
}

static bool comp(const pair<string, float>& p1, const pair<string, float>& p2) {
    return p1.second > p2.second;
}

/**
 * @brief Return an ordered list of the `n` closest words to `word` according to cosine similarity.
 */
vector<pair<string, float>> MonolingualModel::closest(const string& word, int n, int policy) const {
    vector<pair<string, float>> res;
    auto it = vocabulary.find(word);

    if (it == vocabulary.end()) {
        throw runtime_error("OOV word");
    }

    int index = it->second.index;
    vec v1 = wordVec(index, policy);

    for (auto it = vocabulary.begin(); it != vocabulary.end(); ++it) {
        if (it->second.index != index) {
            vec v2 = wordVec(it->second.index, policy);
            res.push_back({it->second.word, cosineSimilarity(v1, v2)});
        }
    }

    std::partial_sort(res.begin(), res.begin() + n, res.end(), comp);
    if (res.size() > n) res.resize(n);
    return res;
}

vector<pair<string, float>> MonolingualModel::closest(const vec& v, int n, int policy) const {
    vector<pair<string, float>> res;

    for (auto it = vocabulary.begin(); it != vocabulary.end(); ++it) {
        vec v2 = wordVec(it->second.index, policy);
        res.push_back({it->second.word, cosineSimilarity(v, v2)});
    }

    std::partial_sort(res.begin(), res.begin() + n, res.end(), comp);
    if (res.size() > n) res.resize(n);
    return res;
}

/**
 * @brief Return sorted list of `words` according to their similarity to `word`.
 */
vector<pair<string, float>> MonolingualModel::closest(const string& word, const vector<string>& words, int policy) const {
    vector<pair<string, float>> res;
    auto it = vocabulary.find(word);

    if (it == vocabulary.end()) {
        throw runtime_error("OOV word");
    }

    int index = it->second.index;
    vec v1 = wordVec(index, policy);

    for (auto it = words.begin(); it != words.end(); ++it) {
        auto node_it = vocabulary.find(*it);
        if (node_it != vocabulary.end()) {
            vec v2 = wordVec(node_it->second.index, policy);
            res.push_back({node_it->second.word, cosineSimilarity(v1, v2)});
        }
    }

    std::sort(res.begin(), res.end(), comp);
    return res;
}

float MonolingualModel::similarityNgrams(const string& seq1, const string& seq2, int policy) const {
    auto words1 = split(seq1);
    auto words2 = split(seq2);

    if (words2.size() != words2.size()) {
        throw runtime_error("input sequences don't have the same size");
    }

    float res = 0;
    int n = 0;
    for (size_t i = 0; i < words1.size(); ++i) {
        try {
            res += similarity(words1[i], words2[i], policy);
            n += 1;
        }
        catch (runtime_error) {}
    }

    if (n == 0) {
        throw runtime_error("all word pairs are unknown (OOV)");
    } else {
        return res / n;
    }
}

void normalizeWeights(mat& weights) {
    if (weights.empty()) {
        return;
    }

    int dim = weights[0].size();

    vec min_values = weights[0];
    vec max_values = weights[0];
    for (size_t i = 1; i < weights.size(); ++i) {
        for (size_t j = 0; j < dim; ++j) {
            min_values[j] = min(min_values[j], weights[i][j]);
            max_values[j] = max(max_values[j], weights[i][j]);
        }
    }

    for (size_t i = 0; i < weights.size(); ++i) {
        for (size_t j = 0; j < dim; ++j) {
            if (max_values[j] != min_values[j]) {
                weights[i][j] = (weights[i][j] - min_values[j]) / (max_values[j] - min_values[j]);
            }
        }
    }
}

void MonolingualModel::normalizeWeights() {
    ::normalizeWeights(input_weights);
    ::normalizeWeights(output_weights);
    ::normalizeWeights(output_weights_hs);
    ::normalizeWeights(sent_weights);
}

float MonolingualModel::similaritySentence(const string& seq1, const string& seq2, int policy) const {
    auto words1 = split(seq1);
    auto words2 = split(seq2);

    vec vec1(config->dimension);
    vec vec2(config->dimension);

    for (auto it = words1.begin(); it != words1.end(); ++it) {
        try {
            vec1 += wordVec(*it, policy);
        }
        catch (runtime_error) {}
    }

    for (auto it = words2.begin(); it != words2.end(); ++it) {
        try {
            vec2 += wordVec(*it, policy);
        }
        catch (runtime_error) {}
    }

    float length = vec1.norm() * vec2.norm();

    if (length == 0) {
        return 0.0;
    } else {
        return vec1.dot(vec2) / length;
    }
}

float MonolingualModel::softWER(const string& hyp, const string& ref, int policy) const {
    auto s1 = split(hyp);
    auto s2 = split(ref);
	const size_t len1 = s1.size(), len2 = s2.size();
	vector<vector<float>> d(len1 + 1, vector<float>(len2 + 1));

	d[0][0] = 0;
	for (size_t i = 1; i <= len1; ++i) d[i][0] = i;
	for (size_t i = 1; i <= len2; ++i) d[0][i] = i;

	for (size_t i = 1; i <= len1; ++i) {
		for (size_t j = 1; j <= len2; ++j) {
		    // uses distance between word embeddings as a substitution cost
		    // FIXME: distances tend to be well below 1, even for very different words.
		    // This is rather unbalanced with deletion and insertion costs, which remain at 1.
		    // Also, distance can (but will rarely) be greater than 1.
            float sub_cost = distance(s1[i - 1], s2[j - 1], policy);

            d[i][j] = min({ d[i - 1][j] + 1,  // deletion
                            d[i][j - 1] + 1,  // insertion
                            d[i - 1][j - 1] + sub_cost });  // substitution
        }
    }

	return d[len1][len2] / len2;
}

/**
 *
 * Bilingual Methods
 *
 */

/**
 * @brief Compute cosine similarity between word1 in the source model and word2 in the target model.
 * For the score to be in [0,1], the weights need to be normalized beforehand.
 * Return 0 if word1 or word2 is unknown.
 */
float BilingualModel::similarity(const string& src_word, const string& trg_word, int policy) const {
    auto it1 = src_model.vocabulary.find(src_word);
    auto it2 = trg_model.vocabulary.find(trg_word);

    if (it1 == src_model.vocabulary.end() || it2 == trg_model.vocabulary.end()) {
        return 0.0;
    } else {
        vec v1 = src_model.wordVec(it1->second.index, policy);
        vec v2 = trg_model.wordVec(it2->second.index, policy);
        return cosineSimilarity(v1, v2);
    }
}

float BilingualModel::distance(const string& src_word, const string& trg_word, int policy) const {
    return 1 - similarity(src_word, trg_word, policy);
}

vector<pair<string, float>> BilingualModel::trg_closest(const string& src_word, int n, int policy) const {
    vector<pair<string, float>> res;
    auto it = src_model.vocabulary.find(src_word);

    if (it == src_model.vocabulary.end()) {
        throw runtime_error("OOV word");
    }

    vec v = src_model.wordVec(it->second.index, policy);
    return trg_model.closest(v, n, policy);
}

vector<pair<string, float>> BilingualModel::src_closest(const string& trg_word, int n, int policy) const {
    vector<pair<string, float>> res;
    auto it = trg_model.vocabulary.find(trg_word);

    if (it == trg_model.vocabulary.end()) {
        throw runtime_error("OOV word");
    }

    vec v = trg_model.wordVec(it->second.index, policy);
    return src_model.closest(v, n, policy);
}

float BilingualModel::similarityNgrams(const string& src_seq, const string& trg_seq, int policy) const {
    auto src_words = split(src_seq);
    auto trg_words = split(trg_seq);

    if (trg_words.size() != trg_words.size()) {
        throw runtime_error("input sequences don't have the same size");
    }

    float res = 0;
    int n = 0;
    for (size_t i = 0; i < src_words.size(); ++i) {
        try {
            res += similarity(src_words[i], trg_words[i], policy);
            n += 1;
        }
        catch (runtime_error) {}
    }

    if (n == 0) {
        throw runtime_error("all word pairs are unknown (OOV)");
    } else {
        return res / n;
    }
}

float BilingualModel::similaritySentence(const string& src_seq, const string& trg_seq, int policy) const {
    auto src_words = split(src_seq);
    auto trg_words = split(trg_seq);

    vec src_vec(config->dimension);
    vec trg_vec(config->dimension);

    for (auto it = src_words.begin(); it != src_words.end(); ++it) {
        try {
            src_vec += src_model.wordVec(*it, policy);
        }
        catch (runtime_error) {}
    }

    for (auto it = trg_words.begin(); it != trg_words.end(); ++it) {
        try {
            trg_vec += trg_model.wordVec(*it, policy);
        }
        catch (runtime_error) {}
    }

    float length = src_vec.norm() * trg_vec.norm();

    if (length == 0) {
        return 0.0;
    } else {
        return src_vec.dot(trg_vec) / length;
    }
}

const static std::map<std::string, float> syntax_weights = {
    { "VERB", 0.75 },
    { "NOUN", 1.00 },
    { "PRON", 0.10 },
    { "ADJ",  0.75 },
    { "ADV",  0.50 },
    { "ADP",  0.10 },
    { "CONJ", 0.10 },
    { "DET",  0.10 },
    { "NUM",  0.50 },
    { "PRT",  0.10 },
    { "X",    0.50 },
    { ".",    0.05 }
};

float MonolingualModel::similaritySentenceSyntax(const string& seq1, const string& seq2, const string& tags1, const string& tags2, int policy) const {
    auto words1 = split(seq1);
    auto words2 = split(seq2);

  	auto pos_tags1 = split(tags1);
    auto pos_tags2 = split(tags2);

    vec vec1(config->dimension);
    vec vec2(config->dimension);

    for (size_t i = 0; i < words1.size() && i < pos_tags1.size(); ++i) {
        try {
            vec1 += wordVec(words1[i], policy) * syntax_weights.at(pos_tags1[i]);
        }
        catch (runtime_error) {}
    }

    for (size_t i = 0; i < words2.size() && i < pos_tags2.size(); ++i) {
        try {
            vec2 += wordVec(words2[i], policy) * syntax_weights.at(pos_tags2[i]);
        }
        catch (runtime_error) {}
    }

    float length = vec1.norm() * vec2.norm();

    if (length == 0) {
        return 0.0;
    } else {
        return vec1.dot(vec2) / length;
    }
}

float BilingualModel::similaritySentenceSyntax(const string& src_seq, const string& trg_seq, const string& src_tags, const string& trg_tags, int policy) const {
    auto src_words = split(src_seq);
    auto trg_words = split(trg_seq);

	auto src_pos_tags = split(src_tags);
    auto trg_pos_tags = split(trg_tags);

    vec src_vec(config->dimension);
    vec trg_vec(config->dimension);

    for (size_t i = 0; i < src_words.size() && i < src_pos_tags.size(); ++i) {
        try {
            src_vec += src_model.wordVec(src_words[i], policy) * syntax_weights.at(src_pos_tags[i]);
        }
        catch (runtime_error) {}
    }
    for (size_t i = 0; i < trg_words.size() && i < trg_pos_tags.size(); ++i) {
        try {
            trg_vec += trg_model.wordVec(trg_words[i], policy) * syntax_weights.at(trg_pos_tags[i]);
        }
        catch (runtime_error) {}
    }

    float length = src_vec.norm() * trg_vec.norm();

    if (length == 0) {
        return 0.0;
    } else {
        return src_vec.dot(trg_vec) / length;
    }
}
<commit_msg>POS weights docstring<commit_after>#include "monolingual.hpp"
#include "bilingual.hpp"

/**
 * @brief Compute cosine similarity between word1 and word2.
 * For the score to be in [0,1], the weights need to be normalized beforehand.
 * Return 0 if word1 or word2 is unknown.
 */
float MonolingualModel::similarity(const string& word1, const string& word2, int policy) const {
    auto it1 = vocabulary.find(word1);
    auto it2 = vocabulary.find(word2);

    if (it1 == vocabulary.end() || it2 == vocabulary.end()) {
        return 0.0;
    } else if (it1->second.index == it2->second.index) {
        return 1.0;
    } else {
        vec v1 = wordVec(it1->second.index, policy);
        vec v2 = wordVec(it2->second.index, policy);
        return cosineSimilarity(v1, v2);
    }
}

float MonolingualModel::distance(const string& word1, const string& word2, int policy) const {
    return 1 - similarity(word1, word2, policy);
}

static bool comp(const pair<string, float>& p1, const pair<string, float>& p2) {
    return p1.second > p2.second;
}

/**
 * @brief Return an ordered list of the `n` closest words to `word` according to cosine similarity.
 */
vector<pair<string, float>> MonolingualModel::closest(const string& word, int n, int policy) const {
    vector<pair<string, float>> res;
    auto it = vocabulary.find(word);

    if (it == vocabulary.end()) {
        throw runtime_error("OOV word");
    }

    int index = it->second.index;
    vec v1 = wordVec(index, policy);

    for (auto it = vocabulary.begin(); it != vocabulary.end(); ++it) {
        if (it->second.index != index) {
            vec v2 = wordVec(it->second.index, policy);
            res.push_back({it->second.word, cosineSimilarity(v1, v2)});
        }
    }

    std::partial_sort(res.begin(), res.begin() + n, res.end(), comp);
    if (res.size() > n) res.resize(n);
    return res;
}

vector<pair<string, float>> MonolingualModel::closest(const vec& v, int n, int policy) const {
    vector<pair<string, float>> res;

    for (auto it = vocabulary.begin(); it != vocabulary.end(); ++it) {
        vec v2 = wordVec(it->second.index, policy);
        res.push_back({it->second.word, cosineSimilarity(v, v2)});
    }

    std::partial_sort(res.begin(), res.begin() + n, res.end(), comp);
    if (res.size() > n) res.resize(n);
    return res;
}

/**
 * @brief Return sorted list of `words` according to their similarity to `word`.
 */
vector<pair<string, float>> MonolingualModel::closest(const string& word, const vector<string>& words, int policy) const {
    vector<pair<string, float>> res;
    auto it = vocabulary.find(word);

    if (it == vocabulary.end()) {
        throw runtime_error("OOV word");
    }

    int index = it->second.index;
    vec v1 = wordVec(index, policy);

    for (auto it = words.begin(); it != words.end(); ++it) {
        auto node_it = vocabulary.find(*it);
        if (node_it != vocabulary.end()) {
            vec v2 = wordVec(node_it->second.index, policy);
            res.push_back({node_it->second.word, cosineSimilarity(v1, v2)});
        }
    }

    std::sort(res.begin(), res.end(), comp);
    return res;
}

float MonolingualModel::similarityNgrams(const string& seq1, const string& seq2, int policy) const {
    auto words1 = split(seq1);
    auto words2 = split(seq2);

    if (words2.size() != words2.size()) {
        throw runtime_error("input sequences don't have the same size");
    }

    float res = 0;
    int n = 0;
    for (size_t i = 0; i < words1.size(); ++i) {
        try {
            res += similarity(words1[i], words2[i], policy);
            n += 1;
        }
        catch (runtime_error) {}
    }

    if (n == 0) {
        throw runtime_error("all word pairs are unknown (OOV)");
    } else {
        return res / n;
    }
}

void normalizeWeights(mat& weights) {
    if (weights.empty()) {
        return;
    }

    int dim = weights[0].size();

    vec min_values = weights[0];
    vec max_values = weights[0];
    for (size_t i = 1; i < weights.size(); ++i) {
        for (size_t j = 0; j < dim; ++j) {
            min_values[j] = min(min_values[j], weights[i][j]);
            max_values[j] = max(max_values[j], weights[i][j]);
        }
    }

    for (size_t i = 0; i < weights.size(); ++i) {
        for (size_t j = 0; j < dim; ++j) {
            if (max_values[j] != min_values[j]) {
                weights[i][j] = (weights[i][j] - min_values[j]) / (max_values[j] - min_values[j]);
            }
        }
    }
}

void MonolingualModel::normalizeWeights() {
    ::normalizeWeights(input_weights);
    ::normalizeWeights(output_weights);
    ::normalizeWeights(output_weights_hs);
    ::normalizeWeights(sent_weights);
}

float MonolingualModel::similaritySentence(const string& seq1, const string& seq2, int policy) const {
    auto words1 = split(seq1);
    auto words2 = split(seq2);

    vec vec1(config->dimension);
    vec vec2(config->dimension);

    for (auto it = words1.begin(); it != words1.end(); ++it) {
        try {
            vec1 += wordVec(*it, policy);
        }
        catch (runtime_error) {}
    }

    for (auto it = words2.begin(); it != words2.end(); ++it) {
        try {
            vec2 += wordVec(*it, policy);
        }
        catch (runtime_error) {}
    }

    float length = vec1.norm() * vec2.norm();

    if (length == 0) {
        return 0.0;
    } else {
        return vec1.dot(vec2) / length;
    }
}

float MonolingualModel::softWER(const string& hyp, const string& ref, int policy) const {
    auto s1 = split(hyp);
    auto s2 = split(ref);
	const size_t len1 = s1.size(), len2 = s2.size();
	vector<vector<float>> d(len1 + 1, vector<float>(len2 + 1));

	d[0][0] = 0;
	for (size_t i = 1; i <= len1; ++i) d[i][0] = i;
	for (size_t i = 1; i <= len2; ++i) d[0][i] = i;

	for (size_t i = 1; i <= len1; ++i) {
		for (size_t j = 1; j <= len2; ++j) {
		    // uses distance between word embeddings as a substitution cost
		    // FIXME: distances tend to be well below 1, even for very different words.
		    // This is rather unbalanced with deletion and insertion costs, which remain at 1.
		    // Also, distance can (but will rarely) be greater than 1.
            float sub_cost = distance(s1[i - 1], s2[j - 1], policy);

            d[i][j] = min({ d[i - 1][j] + 1,  // deletion
                            d[i][j - 1] + 1,  // insertion
                            d[i - 1][j - 1] + sub_cost });  // substitution
        }
    }

	return d[len1][len2] / len2;
}

/**
 *
 * Bilingual Methods
 *
 */

/**
 * @brief Compute cosine similarity between word1 in the source model and word2 in the target model.
 * For the score to be in [0,1], the weights need to be normalized beforehand.
 * Return 0 if word1 or word2 is unknown.
 */
float BilingualModel::similarity(const string& src_word, const string& trg_word, int policy) const {
    auto it1 = src_model.vocabulary.find(src_word);
    auto it2 = trg_model.vocabulary.find(trg_word);

    if (it1 == src_model.vocabulary.end() || it2 == trg_model.vocabulary.end()) {
        return 0.0;
    } else {
        vec v1 = src_model.wordVec(it1->second.index, policy);
        vec v2 = trg_model.wordVec(it2->second.index, policy);
        return cosineSimilarity(v1, v2);
    }
}

float BilingualModel::distance(const string& src_word, const string& trg_word, int policy) const {
    return 1 - similarity(src_word, trg_word, policy);
}

vector<pair<string, float>> BilingualModel::trg_closest(const string& src_word, int n, int policy) const {
    vector<pair<string, float>> res;
    auto it = src_model.vocabulary.find(src_word);

    if (it == src_model.vocabulary.end()) {
        throw runtime_error("OOV word");
    }

    vec v = src_model.wordVec(it->second.index, policy);
    return trg_model.closest(v, n, policy);
}

vector<pair<string, float>> BilingualModel::src_closest(const string& trg_word, int n, int policy) const {
    vector<pair<string, float>> res;
    auto it = trg_model.vocabulary.find(trg_word);

    if (it == trg_model.vocabulary.end()) {
        throw runtime_error("OOV word");
    }

    vec v = trg_model.wordVec(it->second.index, policy);
    return src_model.closest(v, n, policy);
}

float BilingualModel::similarityNgrams(const string& src_seq, const string& trg_seq, int policy) const {
    auto src_words = split(src_seq);
    auto trg_words = split(trg_seq);

    if (trg_words.size() != trg_words.size()) {
        throw runtime_error("input sequences don't have the same size");
    }

    float res = 0;
    int n = 0;
    for (size_t i = 0; i < src_words.size(); ++i) {
        try {
            res += similarity(src_words[i], trg_words[i], policy);
            n += 1;
        }
        catch (runtime_error) {}
    }

    if (n == 0) {
        throw runtime_error("all word pairs are unknown (OOV)");
    } else {
        return res / n;
    }
}

float BilingualModel::similaritySentence(const string& src_seq, const string& trg_seq, int policy) const {
    auto src_words = split(src_seq);
    auto trg_words = split(trg_seq);

    vec src_vec(config->dimension);
    vec trg_vec(config->dimension);

    for (auto it = src_words.begin(); it != src_words.end(); ++it) {
        try {
            src_vec += src_model.wordVec(*it, policy);
        }
        catch (runtime_error) {}
    }

    for (auto it = trg_words.begin(); it != trg_words.end(); ++it) {
        try {
            trg_vec += trg_model.wordVec(*it, policy);
        }
        catch (runtime_error) {}
    }

    float length = src_vec.norm() * trg_vec.norm();

    if (length == 0) {
        return 0.0;
    } else {
        return src_vec.dot(trg_vec) / length;
    }
}

/**
 * POS weights according to Universal Tagset from http://github.com/slavpetrov/universal-pos-tags
 */
const static std::map<std::string, float> syntax_weights = {
    { "VERB", 0.75 },
    { "NOUN", 1.00 },
    { "PRON", 0.10 },
    { "ADJ",  0.75 },
    { "ADV",  0.50 },
    { "ADP",  0.10 },
    { "CONJ", 0.10 },
    { "DET",  0.10 },
    { "NUM",  0.50 },
    { "PRT",  0.10 },
    { "X",    0.50 },
    { ".",    0.05 }
};

float MonolingualModel::similaritySentenceSyntax(const string& seq1, const string& seq2, const string& tags1, const string& tags2, int policy) const {
    auto words1 = split(seq1);
    auto words2 = split(seq2);

  	auto pos_tags1 = split(tags1);
    auto pos_tags2 = split(tags2);

    vec vec1(config->dimension);
    vec vec2(config->dimension);

    for (size_t i = 0; i < words1.size() && i < pos_tags1.size(); ++i) {
        try {
            vec1 += wordVec(words1[i], policy) * syntax_weights.at(pos_tags1[i]);
        }
        catch (runtime_error) {}
    }

    for (size_t i = 0; i < words2.size() && i < pos_tags2.size(); ++i) {
        try {
            vec2 += wordVec(words2[i], policy) * syntax_weights.at(pos_tags2[i]);
        }
        catch (runtime_error) {}
    }

    float length = vec1.norm() * vec2.norm();

    if (length == 0) {
        return 0.0;
    } else {
        return vec1.dot(vec2) / length;
    }
}

float BilingualModel::similaritySentenceSyntax(const string& src_seq, const string& trg_seq, const string& src_tags, const string& trg_tags, int policy) const {
    auto src_words = split(src_seq);
    auto trg_words = split(trg_seq);

	auto src_pos_tags = split(src_tags);
    auto trg_pos_tags = split(trg_tags);

    vec src_vec(config->dimension);
    vec trg_vec(config->dimension);

    for (size_t i = 0; i < src_words.size() && i < src_pos_tags.size(); ++i) {
        try {
            src_vec += src_model.wordVec(src_words[i], policy) * syntax_weights.at(src_pos_tags[i]);
        }
        catch (runtime_error) {}
    }
    for (size_t i = 0; i < trg_words.size() && i < trg_pos_tags.size(); ++i) {
        try {
            trg_vec += trg_model.wordVec(trg_words[i], policy) * syntax_weights.at(trg_pos_tags[i]);
        }
        catch (runtime_error) {}
    }

    float length = src_vec.norm() * trg_vec.norm();

    if (length == 0) {
        return 0.0;
    } else {
        return src_vec.dot(trg_vec) / length;
    }
}
<|endoftext|>


<commit_before>
#include <plugin.h>
#include "strings.h"
#include "dynamiclibrary.h"
#include "logger.h"
#include "pluginmanager.h"

namespace crap
{

PluginManager::PluginManager( void* memory, uint32_t memory_size, const char* resource_path ) :
    _handles( memory, memory_size ), _path(resource_path)
{
    if( _path[ _path.size()-1 ] != '/')
        _path.concat('/');
}

PluginManager::~PluginManager( void )
{
    while( _handles.size() > 0 )
    {
        deinit(0);
    }
}

uint32_t PluginManager::load( const char* filename )
{
	libraryError();
    string256 full_path = _path + filename;
    dlhandle_t handle = loadLibrary( full_path.c_str() );
    if( handle != 0 )
    {
    	createFunction func = (createFunction)librarySymbol( handle, "createPlugin");
    	if( func != 0 )
    	{
    		Plugin* ptr = func(0);
    		return _handles.push_back( handle, ptr );
    	}
    }

    crap::log( LOG_CHANNEL_CORE | LOG_TARGET_CERR | LOG_TYPE_ERROR, "Error: %s", libraryError() );
    return array_map<void*, Plugin*>::INVALID;
}

void PluginManager::init( uint32_t id )
{
	if( id < _handles.size() )
	{
		Plugin* plugin = *(_handles.get_value( id ));
		plugin->init();
	}
}

void PluginManager::deinit( uint32_t id )
{
	if( id < _handles.size() )
	{
		Plugin* plugin = *(_handles.get_value( id ));
		plugin->deinit();
	}
}

void PluginManager::unload( uint32_t id )
{
	if( id < _handles.size() )
	{
    	destroyFunction func = (destroyFunction)librarySymbol( *(_handles.get_key(id)), "destroyPlugin");
    	if( func != 0 )
    	{
    		Plugin* ptr = *(_handles.get_value(id));
    		func(ptr);
    		closeLibrary( *(_handles.get_key(id)) );
    		_handles.erase_at(id);
    		return;
    	}
	}
	crap::log( LOG_CHANNEL_CORE | LOG_TARGET_CERR | LOG_TYPE_ERROR, "Error: %s", libraryError() );
}

}
<commit_msg>Update pluginmanager.cpp<commit_after>
#include <plugin.h>
#include "strings.h"
#include "dynamiclibrary.h"
#include "logger.h"
#include "pluginmanager.h"

namespace crap
{

PluginManager::PluginManager( void* memory, uint32_t memory_size, const char* resource_path ) :
    _handles( memory, memory_size ), _path(resource_path)
{
    if( _path[ _path.size()-1 ] != '/')
        _path.concat('/');
}

PluginManager::~PluginManager( void )
{
    while( _handles.size() > 0 )
    {
        deinit(0);
    }
}

uint32_t PluginManager::load( const char* filename )
{
	libraryError();
    string256 full_path = _path + filename;
    dlhandle_t handle = loadLibrary( full_path.c_str() );
    if( handle != 0 )
    {
		createFunction func = (createFunction)librarySymbol( handle, "createPlugin");
		if( func != 0 )
		{
			Plugin* ptr = func(0);
			return _handles.push_back( handle, ptr );
		}
    }

    crap::log( LOG_CHANNEL_CORE | LOG_TARGET_CERR | LOG_TYPE_ERROR, "Error: %s", libraryError() );
    return array_map<void*, Plugin*>::INVALID;
}

void PluginManager::init( uint32_t id )
{
	if( id < _handles.size() )
	{
		Plugin* plugin = *(_handles.get_value( id ));
		plugin->init();
	}
}

void PluginManager::deinit( uint32_t id )
{
	if( id < _handles.size() )
	{
		Plugin* plugin = *(_handles.get_value( id ));
		plugin->deinit();
	}
}

void PluginManager::unload( uint32_t id )
{
	if( id < _handles.size() )
	{
		destroyFunction func = (destroyFunction)librarySymbol( *(_handles.get_key(id)), "destroyPlugin");
		if( func != 0 )
		{
			Plugin* ptr = *(_handles.get_value(id));
			func(ptr);
			closeLibrary( *(_handles.get_key(id)) );
			_handles.erase_at(id);
			return;
		}
	}
	crap::log( LOG_CHANNEL_CORE | LOG_TARGET_CERR | LOG_TYPE_ERROR, "Error: %s", libraryError() );
}

}
<|endoftext|>


<commit_before>#include "prepostorderstorage.h"

#include "../dfs.h"
#include "../exactannovaluesearch.h"
#include "../exactannokeysearch.h"

#include <set>
#include <stack>

#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/map.hpp>

using namespace annis;

PrePostOrderStorage::PrePostOrderStorage(StringStorage &strings, const Component &component)
{

}

PrePostOrderStorage::~PrePostOrderStorage()
{

}

bool PrePostOrderStorage::load(std::string dirPath)
{
  node2order.clear();
  order2node.clear();

  bool result = edgeAnno.load(dirPath);
  std::ifstream in;

  in.open(dirPath + "/node2order.btree", std::ios::binary);
  result = result && node2order.restore(in);
  in.close();

  in.open(dirPath + "/order2node.btree", std::ios::binary);
  result = result && order2node.restore(in);
  in.close();

  return result;
}

bool PrePostOrderStorage::save(std::string dirPath)
{
  bool result = edgeAnno.save(dirPath);

  std::ofstream out;

  out.open(dirPath + "/node2order.btree", std::ios::binary);
  node2order.dump(out);
  out.close();

  out.open(dirPath + "/order2node.btree", std::ios::binary);
  order2node.dump(out);
  out.close();

  return result;

}

void PrePostOrderStorage::copy(const DB& db, const ReadableGraphStorage& orig)
{
  using ItType = stx::btree_set<Edge>::const_iterator;
  clear();

  // find all roots of the component
  std::set<nodeid_t> roots;
  ExactAnnoKeySearch nodes(db, annis_ns, annis_node_name);
  // first add all nodes that are a source of an edge as possible roots
  while(nodes.hasNext())
  {
    nodeid_t n = nodes.next().node;
    // insert all nodes to the root candidate list which are part of this component
    if(!orig.getOutgoingEdges(n).empty())
    {
      roots.insert(n);
    }
  }

  nodes.reset();
  while(nodes.hasNext())
  {
    nodeid_t source = nodes.next().node;

    std::vector<nodeid_t> outEdges = orig.getOutgoingEdges(source);
    for(auto target : outEdges)
    {
      Edge e = {source, target};

      // remove the nodes that have an incoming edge from the root list
      roots.erase(target);

      std::vector<Annotation> edgeAnnos = orig.getEdgeAnnotations(e);
      for(auto a : edgeAnnos)
      {
        edgeAnno.addEdgeAnnotation(e, a);
      }
    }
  }

  uint32_t currentOrder = 0;

  // traverse the graph for each sub-component
  for(const auto& startNode : roots)
  {
    unsigned int lastDistance = 0;

    NStack nodeStack;

    enterNode(currentOrder, startNode, startNode, 0, nodeStack);

    CycleSafeDFS dfs(orig, startNode, 1, uintmax);
    for(DFSIteratorResult step = dfs.nextDFS(); step.found;
          step = dfs.nextDFS())
    {
      if(step.distance > lastDistance)
      {
        // first visited, set pre-order
        enterNode(currentOrder, step.node, startNode, step.distance, nodeStack);
      }
      else
      {
        // Neighbour node, the last subtree was iterated completly, thus the last node
        // can be assigned a post-order.
        // The parent node must be at the top of the node stack,
        // thus exit every node which comes after the parent node.
        // Distance starts with 0 but the stack size starts with 1.
        while(nodeStack.size() > step.distance)
        {
          exitNode(currentOrder, nodeStack);
        }
        // new node
        enterNode(currentOrder, step.node, startNode, step.distance, nodeStack);
      }
      lastDistance = step.distance;
    } // end for each DFS step

    while(!nodeStack.empty())
    {
      exitNode(currentOrder, nodeStack);
    }

  } // end for each root
}

void PrePostOrderStorage::clear()
{
  node2order.clear();
  order2node.clear();
  edgeAnno.clear();
}

void PrePostOrderStorage::enterNode(uint32_t& currentOrder, nodeid_t nodeID, nodeid_t rootNode,
                                        int level, NStack& nodeStack)
{
  NodeStackEntry newEntry;
  newEntry.id = nodeID;
  newEntry.order.pre = currentOrder++;
  newEntry.order.level = level;

  nodeStack.push(newEntry);
}

void PrePostOrderStorage::exitNode(uint32_t& currentOrder, NStack &nodeStack)
{
  // find the correct pre/post entry and update the post-value
  auto& entry = nodeStack.top();
  entry.order.post = currentOrder++;

  node2order.insert2(entry.id, entry.order);
  order2node[entry.order] = entry.id;

  nodeStack.pop();
}

bool PrePostOrderStorage::isConnected(const Edge &edge, unsigned int minDistance, unsigned int maxDistance) const
{
  const auto itSourceBegin = node2order.lower_bound(edge.source);
  const auto itSourceEnd = node2order.upper_bound(edge.source);

  for(auto itSource=itSourceBegin; itSource != itSourceEnd; itSource++)
  {
    auto itTargetRange = node2order.equal_range(edge.target);
    for(auto itTarget=itTargetRange.first; itTarget != itTargetRange.second; itTarget++)
    {
      if(itSource->second.pre <= itTarget->second.pre
         && itTarget->second.post <= itSource->second.post)
      {
        // check the level
        int diffLevel = (itTarget->second.level - itSource->second.level);
        if(minDistance <= diffLevel && diffLevel <= maxDistance)
        {
          return true;
        }
      }
    }
  }
  return false;
}

int PrePostOrderStorage::distance(const Edge &edge) const
{
  if(edge.source == edge.target)
  {
    return 0;
  }

  const auto itSourceBegin = node2order.lower_bound(edge.source);
  const auto itSourceEnd = node2order.upper_bound(edge.source);

  bool wasFound = false;
  int32_t minLevel = std::numeric_limits<int32_t>::max();

  for(auto itSource=itSourceBegin; itSource != itSourceEnd; itSource++)
  {
    auto itTargetRange = node2order.equal_range(edge.target);
    for(auto itTarget=itTargetRange.first; itTarget != itTargetRange.second; itTarget++)
    {
      if(itSource->second.pre <= itTarget->second.pre
         && itTarget->second.post <= itSource->second.post)
      {
        // check the level
        int32_t diffLevel = (itTarget->second.level - itSource->second.level);
        if(diffLevel >= 0)
        {
          wasFound = true;
          minLevel = std::min(minLevel, diffLevel);
        }
      }
    }
  }
  if(wasFound)
  {
    return minLevel;
  }
  else
  {
    return -1;
  }
}

std::unique_ptr<EdgeIterator> PrePostOrderStorage::findConnected(nodeid_t sourceNode, unsigned int minDistance, unsigned int maxDistance) const
{
  return std::unique_ptr<EdgeIterator>(
        new PrePostIterator(*this, sourceNode, minDistance, maxDistance));
}

std::vector<nodeid_t> PrePostOrderStorage::getOutgoingEdges(nodeid_t node) const
{
  std::vector<nodeid_t> result;
  result.reserve(10);

  auto connectedIt = findConnected(node, 1, 1);
  for(auto c=connectedIt->next(); c.first; c=connectedIt->next())
  {
    result.push_back(c.second);
  }

  return result;
}

std::vector<nodeid_t> PrePostOrderStorage::getIncomingEdges(nodeid_t node) const
{
  std::set<nodeid_t> sources;
  auto itRange = node2order.equal_range(node);
  for(auto itTarget=itRange.first; itTarget != itRange.second; itTarget++)
  {
    const auto& targetOrder = itTarget->second;
    // get all nodes that are potential predecessors
    PrePost minPrePost = {0, 0, 0};
    PrePost maxPrePost = {targetOrder.pre-1, uintmax, std::numeric_limits<int32_t>::max()};
    auto itMin = order2node.lower_bound(minPrePost);
    auto itMax = order2node.upper_bound(maxPrePost);
    for(auto itSource=itMin; itSource != itMax; itSource++)
    {
      const PrePost& sourceOrder = itSource->first;
      if(sourceOrder.level == targetOrder.level-1
         && targetOrder.post < sourceOrder.post
         && sourceOrder.pre < targetOrder.pre)
      {
        sources.insert(itSource->second);
      }
    }
  }

  std::vector<nodeid_t> result;
  result.reserve(sources.size());
  for(auto n : sources)
  {
    result.push_back(n);
  }
  return result;

}

PrePostIterator::PrePostIterator(const PrePostOrderStorage &storage, std::uint32_t startNode, unsigned int minDistance, unsigned int maxDistance)
  : storage(storage), startNode(startNode),
    minDistance(minDistance), maxDistance(maxDistance)
{
  init();
}

std::pair<bool, nodeid_t> PrePostIterator::next()
{
  std::pair<bool, nodeid_t> result(0, false);

  while(!ranges.empty())
  {
    const auto& upper = ranges.top().upper;
    const auto& maximumPost = ranges.top().maximumPost;
    const auto& startLevel = ranges.top().startLevel;

    while(currentNode != upper)
    {
      const auto& currentPre = currentNode->first.pre;
      const auto& currentPost = currentNode->first.post;
      const auto& currentLevel = currentNode->first.level;

      int diffLevel = currentLevel - startLevel;

      // check post order and level as well
      if(currentPost <= maximumPost && minDistance <= diffLevel && diffLevel <= maxDistance
         && visited.find(currentNode->second) == visited.end())
      {
        // success
        result.first = true;
        result.second = currentNode->second;

        visited.insert(result.second);

        currentNode++;
        return result;
      }
      else if(currentPre < maximumPost)
      {
        // proceed with the next entry in the range
        currentNode++;
      }
      else
      {
        // abort searching in this range
        break;
      }
    } // end while range not finished yet

    // this range is finished, try next one
    ranges.pop();
    if(!ranges.empty())
    {
      currentNode = ranges.top().lower;
    }
  }

  return result;
}

void PrePostIterator::init()
{
  auto subComponentsLower = storage.node2order.lower_bound(startNode);
  auto subComponentsUpper = storage.node2order.upper_bound(startNode);

  for(auto it=subComponentsLower; it != subComponentsUpper; it++)
  {
    auto pre = it->second.pre;
    auto post = it->second.post;
    auto lowerIt = storage.order2node.lower_bound({pre, 0, 0});
    auto upperIt = storage.order2node.upper_bound({post, uintmax, std::numeric_limits<int32_t>::max()});

    ranges.push({lowerIt, upperIt, post, it->second.level});
  }
  if(!ranges.empty())
  {
    currentNode = ranges.top().lower;
  }
}

void PrePostIterator::reset()
{
  while(!ranges.empty())
  {
    ranges.pop();
  }

  visited.clear();

  init();
}

PrePostIterator::~PrePostIterator()
{

}
<commit_msg>reference pre/post order value instead of copying them<commit_after>#include "prepostorderstorage.h"

#include "../dfs.h"
#include "../exactannovaluesearch.h"
#include "../exactannokeysearch.h"

#include <set>
#include <stack>

#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/map.hpp>

using namespace annis;

PrePostOrderStorage::PrePostOrderStorage(StringStorage &strings, const Component &component)
{

}

PrePostOrderStorage::~PrePostOrderStorage()
{

}

bool PrePostOrderStorage::load(std::string dirPath)
{
  node2order.clear();
  order2node.clear();

  bool result = edgeAnno.load(dirPath);
  std::ifstream in;

  in.open(dirPath + "/node2order.btree", std::ios::binary);
  result = result && node2order.restore(in);
  in.close();

  in.open(dirPath + "/order2node.btree", std::ios::binary);
  result = result && order2node.restore(in);
  in.close();

  return result;
}

bool PrePostOrderStorage::save(std::string dirPath)
{
  bool result = edgeAnno.save(dirPath);

  std::ofstream out;

  out.open(dirPath + "/node2order.btree", std::ios::binary);
  node2order.dump(out);
  out.close();

  out.open(dirPath + "/order2node.btree", std::ios::binary);
  order2node.dump(out);
  out.close();

  return result;

}

void PrePostOrderStorage::copy(const DB& db, const ReadableGraphStorage& orig)
{
  using ItType = stx::btree_set<Edge>::const_iterator;
  clear();

  // find all roots of the component
  std::set<nodeid_t> roots;
  ExactAnnoKeySearch nodes(db, annis_ns, annis_node_name);
  // first add all nodes that are a source of an edge as possible roots
  while(nodes.hasNext())
  {
    nodeid_t n = nodes.next().node;
    // insert all nodes to the root candidate list which are part of this component
    if(!orig.getOutgoingEdges(n).empty())
    {
      roots.insert(n);
    }
  }

  nodes.reset();
  while(nodes.hasNext())
  {
    nodeid_t source = nodes.next().node;

    std::vector<nodeid_t> outEdges = orig.getOutgoingEdges(source);
    for(auto target : outEdges)
    {
      Edge e = {source, target};

      // remove the nodes that have an incoming edge from the root list
      roots.erase(target);

      std::vector<Annotation> edgeAnnos = orig.getEdgeAnnotations(e);
      for(auto a : edgeAnnos)
      {
        edgeAnno.addEdgeAnnotation(e, a);
      }
    }
  }

  uint32_t currentOrder = 0;

  // traverse the graph for each sub-component
  for(const auto& startNode : roots)
  {
    unsigned int lastDistance = 0;

    NStack nodeStack;

    enterNode(currentOrder, startNode, startNode, 0, nodeStack);

    CycleSafeDFS dfs(orig, startNode, 1, uintmax);
    for(DFSIteratorResult step = dfs.nextDFS(); step.found;
          step = dfs.nextDFS())
    {
      if(step.distance > lastDistance)
      {
        // first visited, set pre-order
        enterNode(currentOrder, step.node, startNode, step.distance, nodeStack);
      }
      else
      {
        // Neighbour node, the last subtree was iterated completly, thus the last node
        // can be assigned a post-order.
        // The parent node must be at the top of the node stack,
        // thus exit every node which comes after the parent node.
        // Distance starts with 0 but the stack size starts with 1.
        while(nodeStack.size() > step.distance)
        {
          exitNode(currentOrder, nodeStack);
        }
        // new node
        enterNode(currentOrder, step.node, startNode, step.distance, nodeStack);
      }
      lastDistance = step.distance;
    } // end for each DFS step

    while(!nodeStack.empty())
    {
      exitNode(currentOrder, nodeStack);
    }

  } // end for each root
}

void PrePostOrderStorage::clear()
{
  node2order.clear();
  order2node.clear();
  edgeAnno.clear();
}

void PrePostOrderStorage::enterNode(uint32_t& currentOrder, nodeid_t nodeID, nodeid_t rootNode,
                                        int level, NStack& nodeStack)
{
  NodeStackEntry newEntry;
  newEntry.id = nodeID;
  newEntry.order.pre = currentOrder++;
  newEntry.order.level = level;

  nodeStack.push(newEntry);
}

void PrePostOrderStorage::exitNode(uint32_t& currentOrder, NStack &nodeStack)
{
  // find the correct pre/post entry and update the post-value
  auto& entry = nodeStack.top();
  entry.order.post = currentOrder++;

  node2order.insert2(entry.id, entry.order);
  order2node[entry.order] = entry.id;

  nodeStack.pop();
}

bool PrePostOrderStorage::isConnected(const Edge &edge, unsigned int minDistance, unsigned int maxDistance) const
{
  const auto itSourceBegin = node2order.lower_bound(edge.source);
  const auto itSourceEnd = node2order.upper_bound(edge.source);

  for(auto itSource=itSourceBegin; itSource != itSourceEnd; itSource++)
  {
    auto itTargetRange = node2order.equal_range(edge.target);
    for(auto itTarget=itTargetRange.first; itTarget != itTargetRange.second; itTarget++)
    {
      if(itSource->second.pre <= itTarget->second.pre
         && itTarget->second.post <= itSource->second.post)
      {
        // check the level
        int diffLevel = (itTarget->second.level - itSource->second.level);
        if(minDistance <= diffLevel && diffLevel <= maxDistance)
        {
          return true;
        }
      }
    }
  }
  return false;
}

int PrePostOrderStorage::distance(const Edge &edge) const
{
  if(edge.source == edge.target)
  {
    return 0;
  }

  const auto itSourceBegin = node2order.lower_bound(edge.source);
  const auto itSourceEnd = node2order.upper_bound(edge.source);

  bool wasFound = false;
  int32_t minLevel = std::numeric_limits<int32_t>::max();

  for(auto itSource=itSourceBegin; itSource != itSourceEnd; itSource++)
  {
    auto itTargetRange = node2order.equal_range(edge.target);
    for(auto itTarget=itTargetRange.first; itTarget != itTargetRange.second; itTarget++)
    {
      if(itSource->second.pre <= itTarget->second.pre
         && itTarget->second.post <= itSource->second.post)
      {
        // check the level
        int32_t diffLevel = (itTarget->second.level - itSource->second.level);
        if(diffLevel >= 0)
        {
          wasFound = true;
          minLevel = std::min(minLevel, diffLevel);
        }
      }
    }
  }
  if(wasFound)
  {
    return minLevel;
  }
  else
  {
    return -1;
  }
}

std::unique_ptr<EdgeIterator> PrePostOrderStorage::findConnected(nodeid_t sourceNode, unsigned int minDistance, unsigned int maxDistance) const
{
  return std::unique_ptr<EdgeIterator>(
        new PrePostIterator(*this, sourceNode, minDistance, maxDistance));
}

std::vector<nodeid_t> PrePostOrderStorage::getOutgoingEdges(nodeid_t node) const
{
  std::vector<nodeid_t> result;
  result.reserve(10);

  auto connectedIt = findConnected(node, 1, 1);
  for(auto c=connectedIt->next(); c.first; c=connectedIt->next())
  {
    result.push_back(c.second);
  }

  return result;
}

std::vector<nodeid_t> PrePostOrderStorage::getIncomingEdges(nodeid_t node) const
{
  std::set<nodeid_t> sources;
  auto itRange = node2order.equal_range(node);
  for(auto itTarget=itRange.first; itTarget != itRange.second; itTarget++)
  {
    const auto& targetOrder = itTarget->second;
    // get all nodes that are potential predecessors
    PrePost minPrePost = {0, 0, 0};
    PrePost maxPrePost = {targetOrder.pre-1, uintmax, std::numeric_limits<int32_t>::max()};
    auto itMin = order2node.lower_bound(minPrePost);
    auto itMax = order2node.upper_bound(maxPrePost);
    for(auto itSource=itMin; itSource != itMax; itSource++)
    {
      const PrePost& sourceOrder = itSource->first;
      if(sourceOrder.level == targetOrder.level-1
         && targetOrder.post < sourceOrder.post
         && sourceOrder.pre < targetOrder.pre)
      {
        sources.insert(itSource->second);
      }
    }
  }

  std::vector<nodeid_t> result;
  result.reserve(sources.size());
  for(auto n : sources)
  {
    result.push_back(n);
  }
  return result;

}

PrePostIterator::PrePostIterator(const PrePostOrderStorage &storage, std::uint32_t startNode, unsigned int minDistance, unsigned int maxDistance)
  : storage(storage), startNode(startNode),
    minDistance(minDistance), maxDistance(maxDistance)
{
  init();
}

std::pair<bool, nodeid_t> PrePostIterator::next()
{
  std::pair<bool, nodeid_t> result(0, false);

  while(!ranges.empty())
  {
    const auto& upper = ranges.top().upper;
    const auto& maximumPost = ranges.top().maximumPost;
    const auto& startLevel = ranges.top().startLevel;

    while(currentNode != upper)
    {
      const auto& currentPre = currentNode->first.pre;
      const auto& currentPost = currentNode->first.post;
      const auto& currentLevel = currentNode->first.level;

      int diffLevel = currentLevel - startLevel;

      // check post order and level as well
      if(currentPost <= maximumPost && minDistance <= diffLevel && diffLevel <= maxDistance
         && visited.find(currentNode->second) == visited.end())
      {
        // success
        result.first = true;
        result.second = currentNode->second;

        visited.insert(result.second);

        currentNode++;
        return result;
      }
      else if(currentPre < maximumPost)
      {
        // proceed with the next entry in the range
        currentNode++;
      }
      else
      {
        // abort searching in this range
        break;
      }
    } // end while range not finished yet

    // this range is finished, try next one
    ranges.pop();
    if(!ranges.empty())
    {
      currentNode = ranges.top().lower;
    }
  }

  return result;
}

void PrePostIterator::init()
{
  auto subComponentsLower = storage.node2order.lower_bound(startNode);
  auto subComponentsUpper = storage.node2order.upper_bound(startNode);

  for(auto it=subComponentsLower; it != subComponentsUpper; it++)
  {
    const auto& pre = it->second.pre;
    const auto& post = it->second.post;
    auto lowerIt = storage.order2node.lower_bound({pre, 0, 0});
    auto upperIt = storage.order2node.upper_bound({post, uintmax, std::numeric_limits<int32_t>::max()});

    ranges.push({lowerIt, upperIt, post, it->second.level});
  }
  if(!ranges.empty())
  {
    currentNode = ranges.top().lower;
  }
}

void PrePostIterator::reset()
{
  while(!ranges.empty())
  {
    ranges.pop();
  }

  visited.clear();

  init();
}

PrePostIterator::~PrePostIterator()
{

}
<|endoftext|>


<commit_before>/* /% C++ %/ */
/***********************************************************************
 * cint (C/C++ interpreter)
 ************************************************************************
 * Source file CallFunc.cxx
 ************************************************************************
 * Description:
 *  Extended Run Time Type Identification API
 ************************************************************************
 * Copyright(c) 1995~1999  Masaharu Goto (MXJ02154@niftyserve.or.jp)
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  The author makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 ************************************************************************/

#include "Api.h"
#include "common.h"

/*********************************************************************
* class G__CallFunc
*
* Usage1:
*
*   TCanvas c[10];
*   void *address;
*   long offset;
*   G__CallFunc func;
*   G__ClassInfo canvas("TCanvas");
*   // set pointer to interface method and argument
*   func.SetFunc(&canvas,"Draw","\"ABC\",1234,3.14",&offset);
*   // call function
*   for(int i=0;i<10;i++) {
*     address = (void*)(&c[i]) + offset;
*     func.Exec(address);
*   }
*   // reset everything
*   func.Init();
*
*
* Usage2:
*
*   TCanvas c[10];
*   void *address;
*   long offset;
*   G__CallFunc func;
*   G__ClassInfo canvas("TCanvas");
*   // set pointer to interface method
*   func.SetFunc(canvas.GetMethod("Draw","char*,int,double",&offset).InterfaceMethod());
*   // set arguments
*   char *title="ABC";
*   func.SetArg((long)title);
*   func.SetArg((long)1234);
*   func.SetArg((double)3.14);
*   // call function
*   for(int i=0;i<10;i++) {
*     address = (void*)(&c[i]) + offset;
*     func.Exec(address);
*   }
*   // reset everything
*   func.Init();
*
*********************************************************************/
///////////////////////////////////////////////////////////////////////////
G__CallFunc::G__CallFunc()
{
#ifndef G__OLDIMPLEMENTATION1035
  G__LockCriticalSection();
#endif
  Init();
#ifndef G__OLDIMPLEMENTATION1035
  G__UnlockCriticalSection();
#endif
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::Init()
{
  pfunc = (G__InterfaceMethod)NULL;
  para.paran = 0;
#ifndef G__OLDIMPLEMENTATION1547
  result = G__null;
#ifdef G__ASM_WHOLEFUNC
  bytecode = (struct G__bytecodefunc*)NULL;
#endif
#endif
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetFunc(G__InterfaceMethod f)
{
  pfunc = f; // Set pointer to interface method
}
#ifdef G__ASM_WHOLEFUNC
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetBytecode(struct G__bytecodefunc* bc)
{
  bytecode = bc;
  if(bytecode) pfunc = (G__InterfaceMethod)G__exec_bytecode;
  else {
    pfunc = (G__InterfaceMethod)NULL;
#ifndef G__ROOT
    G__fprinterr(G__serr,"Warning: Bytecode compilation of %s failed. G__CallFunc::Exec may be slow\n",method.Name());
#endif
  }
  para.paran=0;
}
#endif
#ifndef G__OLDIMPLEMENTATION533
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArgArray(long *p)
{
  int i,n;
  if(method.IsValid()) {
    n = method.NArg();
#ifndef G__OLDIMPLEMENTATION1220 /* NEEDEDSINCE_FIX1167 */
    G__MethodArgInfo arginfo;
    arginfo.Init(method);
#endif
    for(i=0;i<n;i++) {
      if (p[i]) {
        para.para[i].obj.i = p[i];
        para.para[i].ref = p[i];
        // Following data shouldn't matter, but set just in case
#ifndef G__OLDIMPLEMENTATION1220 /* NEEDEDSINCE_FIX1167 */
        arginfo.Next();
        para.para[i].type = arginfo.Type()->Type();
#else
        para.para[i].type = 'l';
#endif
        para.para[i].tagnum = -1;
        para.para[i].typenum = -1;
        para.paran=i+1;
        break;
      }
    }
  }
  else {
    G__fprinterr(G__serr,"Error: G__CallFunc::SetArgArray() must be initialized with 'G__CallFunc::SetFunc(G__ClassInfo* cls,char* fname,char* args,long* poffset)' first\n");
  }
}
#endif
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArg(long l)
{
  para.para[para.paran].obj.i = l;
  para.para[para.paran].ref = l;
  // Following data shouldn't matter, but set just in case
  para.para[para.paran].type = 'l';
  para.para[para.paran].tagnum = -1;
  para.para[para.paran].typenum = -1;
  ++para.paran; // Increment number of argument
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArg(double d)
{
  para.para[para.paran].obj.d = d;
  // Following data shouldn't matter, but set just in case
  para.para[para.paran].ref = 0 ;
  para.para[para.paran].type = 'd';
  para.para[para.paran].tagnum = -1;
  para.para[para.paran].typenum = -1;
  ++para.paran; // Increment number of argument
}
#ifndef G__FONS51
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArgs(const char* args)
{
  int isrc=0;
  char *endmark=(char*)",";

  // separate and evaluate argument list
  para.paran=0;
  int c;
  do {
    c=G__getstream((char*)args,&isrc,para.parameter[para.paran],endmark);
    if (para.parameter[para.paran][0]) {
      // evaluate arg
#ifndef G__OLDIMPLEMENTATION899
      para.para[para.paran] = G__calc(para.parameter[para.paran]);
#else
      para.para[para.paran] = G__getexpr(para.parameter[para.paran]);
#endif
      ++para.paran; // increment argument count
    }
  } while (','==c);
}
#endif
#ifndef G__OLDIMPLEMENTATION540
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetFuncProto(G__ClassInfo* cls
			  ,const char* fname  ,const char* argtype
			  ,long* poffset)
{
#ifndef G__OLDIMPLEMENTATION1035
  G__LockCriticalSection();
#endif

  method = cls->GetMethod(fname,argtype,poffset); // get G__MethodInfo object
  pfunc = method.InterfaceMethod(); // get compiled interface method
#ifdef G__OLDIMPLEMENTATION862
  if((G__InterfaceMethod)NULL==pfunc) {
    SetBytecode(method.GetBytecode()); // try to compile bytecode
  }
#endif
  para.paran=0; // reset parameters, not needed actually, done in SetBytecode

#ifndef G__OLDIMPLEMENTATION1035
  G__UnlockCriticalSection();
#endif
}
#endif
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetFunc(G__ClassInfo* cls
			  ,const char* fname  ,const char* args
			  ,long* poffset)
{
  // G__getstream(), G__type2string()
  int isrc=0;
  char *endmark=(char*)",";
  char argtype[G__ONELINE];
  int pos=0;
  G__value *buf;
#ifdef G__OLDIMPLEMENTATION533
#ifdef G__ASM_WHOLEFUNC
  G__MethodInfo method;
#endif
#endif

  // separate and evaluate argument list
  para.paran=0;
  argtype[0]='\0';
  int c;
  do {
    c=G__getstream((char*)args,&isrc,para.parameter[para.paran],endmark);
    if (para.parameter[para.paran][0]) {
      // evaluate arg
#ifndef G__OLDIMPLEMENTATION899
      para.para[para.paran] = G__calc(para.parameter[para.paran]);
#else
      para.para[para.paran] = G__getexpr(para.parameter[para.paran]);
#endif
      buf = &para.para[para.paran];
      // set type string
      if(pos) argtype[pos++]=',';
      strcpy(argtype+pos
	     ,G__type2string(buf->type,buf->tagnum,buf->typenum,(int)buf->ref
			   ,0));
      pos = strlen(argtype);
      ++para.paran; // increment argument count
    }
  } while (','==c);

  method = cls->GetMethod(fname,argtype,poffset); // get G__MethodInfo object
  pfunc = method.InterfaceMethod(); // get compiled interface method
  if((G__InterfaceMethod)NULL==pfunc) {
    int store_paran=para.paran;
    SetBytecode(method.GetBytecode()); // try to compile bytecode
    para.paran=store_paran;
  }
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::Exec(void *pobject)
{
  int ret;
  long store_struct_offset;
#ifndef G__OLDIMPLEMENTATION1035
  G__LockCriticalSection();
#endif
  // Set object address
  store_struct_offset = G__store_struct_offset;
  G__store_struct_offset = (long)pobject;
#ifndef G__OLDIMPLEMENTATION1591
  SetFuncType();
#endif
  // Call function
#ifdef G__ASM_WHOLEFUNC
  if(pfunc) ret = (*pfunc)(&result,(char*)bytecode,&para,0);
#else
  if(pfunc) ret = (*pfunc)(&result,(char*)NULL,&para,0);
#endif
#ifndef G__OLDIMPLEMENTATION823
  else ret = ExecInterpretedFunc(&result);
#endif
  // Restore  object address
  G__store_struct_offset = store_struct_offset;
  if(0==ret) {
    /* error */
  }
#ifndef G__OLDIMPLEMENTATION1035
  G__UnlockCriticalSection();
#endif
}
///////////////////////////////////////////////////////////////////////////
long G__CallFunc::ExecInt(void *pobject)
{
  int ret;
  long store_struct_offset;
  // Set object address
  store_struct_offset = G__store_struct_offset;
  G__store_struct_offset = (long)pobject;
#ifndef G__OLDIMPLEMENTATION1591
  SetFuncType();
#endif
  // Call function
#ifdef G__ASM_WHOLEFUNC
  if(pfunc) ret = (*pfunc)(&result,(char*)bytecode,&para,0);
#else
  if(pfunc) ret = (*pfunc)(&result,(char*)NULL,&para,0);
#endif
#ifndef G__OLDIMPLEMENTATION823
  else ret = ExecInterpretedFunc(&result);
#endif
  // Restore  object address
  G__store_struct_offset = store_struct_offset;
  if(0==ret) {
    /* error */
  }
  return(G__int(result));
}
///////////////////////////////////////////////////////////////////////////
double G__CallFunc::ExecDouble(void *pobject)
{
  int ret;
  long store_struct_offset;
  // Set object address
  store_struct_offset = G__store_struct_offset;
  G__store_struct_offset = (long)pobject;
#ifndef G__OLDIMPLEMENTATION1591
  SetFuncType();
#endif
  // Call function
#ifdef G__ASM_WHOLEFUNC
  if(pfunc) ret = (*pfunc)(&result,(char*)bytecode,&para,0);
#else
  if(pfunc) ret = (*pfunc)(&result,(char*)NULL,&para,0);
#endif
#ifndef G__OLDIMPLEMENTATION823
  else ret = ExecInterpretedFunc(&result);
#endif
  // Restore  object address
  G__store_struct_offset = store_struct_offset;
  if(0==ret) {
    /* error */
  }
  return(G__double(result));
}
///////////////////////////////////////////////////////////////////////////
int G__CallFunc::ExecInterpretedFunc(G__value* presult)
{
  int ret=0;
  if(method.IsValid()) {
    int store_asm_exec=G__asm_exec;
    int store_asm_index=G__asm_index;
    int store_asm_noverflow = G__asm_noverflow;
    G__asm_exec=1;
    G__asm_index = method.Index();
    G__asm_noverflow = 0;
    ret = G__interpret_func(presult,(char*)method.Name()
		            ,&para,method.Hash(),method.ifunc()
			    ,G__EXACT,G__TRYNORMAL);
    G__asm_exec = store_asm_exec;
    G__asm_index= store_asm_index;
    G__asm_noverflow = store_asm_noverflow;
  }
  return(ret);
}
///////////////////////////////////////////////////////////////////////////
#ifndef G__OLDIMPLEMENTATION1591
void G__CallFunc::SetFuncType() {
  if(method.IsValid()) {
    struct G__ifunc_table *ifunc = method.ifunc();
    int ifn = method.Index();
    result.type = ifunc->type[ifn];
    result.tagnum = ifunc->p_tagtable[ifn];
    result.typenum = ifunc->p_typetable[ifn];
    result.isconst = ifunc->isconst[ifn];
    if('d'!=result.type&&'f'!=result.type) {
      result.obj.reftype.reftype = ifunc->reftype[ifn];
    }
  }
}
#endif
///////////////////////////////////////////////////////////////////////////

<commit_msg>break statement was in wrong location, breaking loop to soon.<commit_after>/* /% C++ %/ */
/***********************************************************************
 * cint (C/C++ interpreter)
 ************************************************************************
 * Source file CallFunc.cxx
 ************************************************************************
 * Description:
 *  Extended Run Time Type Identification API
 ************************************************************************
 * Copyright(c) 1995~1999  Masaharu Goto (MXJ02154@niftyserve.or.jp)
 *
 * Permission to use, copy, modify and distribute this software and its
 * documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  The author makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied warranty.
 ************************************************************************/

#include "Api.h"
#include "common.h"

/*********************************************************************
* class G__CallFunc
*
* Usage1:
*
*   TCanvas c[10];
*   void *address;
*   long offset;
*   G__CallFunc func;
*   G__ClassInfo canvas("TCanvas");
*   // set pointer to interface method and argument
*   func.SetFunc(&canvas,"Draw","\"ABC\",1234,3.14",&offset);
*   // call function
*   for(int i=0;i<10;i++) {
*     address = (void*)(&c[i]) + offset;
*     func.Exec(address);
*   }
*   // reset everything
*   func.Init();
*
*
* Usage2:
*
*   TCanvas c[10];
*   void *address;
*   long offset;
*   G__CallFunc func;
*   G__ClassInfo canvas("TCanvas");
*   // set pointer to interface method
*   func.SetFunc(canvas.GetMethod("Draw","char*,int,double",&offset).InterfaceMethod());
*   // set arguments
*   char *title="ABC";
*   func.SetArg((long)title);
*   func.SetArg((long)1234);
*   func.SetArg((double)3.14);
*   // call function
*   for(int i=0;i<10;i++) {
*     address = (void*)(&c[i]) + offset;
*     func.Exec(address);
*   }
*   // reset everything
*   func.Init();
*
*********************************************************************/
///////////////////////////////////////////////////////////////////////////
G__CallFunc::G__CallFunc()
{
#ifndef G__OLDIMPLEMENTATION1035
  G__LockCriticalSection();
#endif
  Init();
#ifndef G__OLDIMPLEMENTATION1035
  G__UnlockCriticalSection();
#endif
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::Init()
{
  pfunc = (G__InterfaceMethod)NULL;
  para.paran = 0;
#ifndef G__OLDIMPLEMENTATION1547
  result = G__null;
#ifdef G__ASM_WHOLEFUNC
  bytecode = (struct G__bytecodefunc*)NULL;
#endif
#endif
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetFunc(G__InterfaceMethod f)
{
  pfunc = f; // Set pointer to interface method
}
#ifdef G__ASM_WHOLEFUNC
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetBytecode(struct G__bytecodefunc* bc)
{
  bytecode = bc;
  if(bytecode) pfunc = (G__InterfaceMethod)G__exec_bytecode;
  else {
    pfunc = (G__InterfaceMethod)NULL;
#ifndef G__ROOT
    G__fprinterr(G__serr,"Warning: Bytecode compilation of %s failed. G__CallFunc::Exec may be slow\n",method.Name());
#endif
  }
  para.paran=0;
}
#endif
#ifndef G__OLDIMPLEMENTATION533
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArgArray(long *p)
{
  int i,n;
  if(method.IsValid()) {
    n = method.NArg();
#ifndef G__OLDIMPLEMENTATION1220 /* NEEDEDSINCE_FIX1167 */
    G__MethodArgInfo arginfo;
    arginfo.Init(method);
#endif
    for(i=0;i<n;i++) {
      if (p[i]) {
        para.para[i].obj.i = p[i];
        para.para[i].ref = p[i];
        // Following data shouldn't matter, but set just in case
#ifndef G__OLDIMPLEMENTATION1220 /* NEEDEDSINCE_FIX1167 */
        arginfo.Next();
        para.para[i].type = arginfo.Type()->Type();
#else
        para.para[i].type = 'l';
#endif
        para.para[i].tagnum = -1;
        para.para[i].typenum = -1;
        para.paran=i+1;
      } else
         break;
    }
  }
  else {
    G__fprinterr(G__serr,"Error: G__CallFunc::SetArgArray() must be initialized with 'G__CallFunc::SetFunc(G__ClassInfo* cls,char* fname,char* args,long* poffset)' first\n");
  }
}
#endif
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArg(long l)
{
  para.para[para.paran].obj.i = l;
  para.para[para.paran].ref = l;
  // Following data shouldn't matter, but set just in case
  para.para[para.paran].type = 'l';
  para.para[para.paran].tagnum = -1;
  para.para[para.paran].typenum = -1;
  ++para.paran; // Increment number of argument
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArg(double d)
{
  para.para[para.paran].obj.d = d;
  // Following data shouldn't matter, but set just in case
  para.para[para.paran].ref = 0 ;
  para.para[para.paran].type = 'd';
  para.para[para.paran].tagnum = -1;
  para.para[para.paran].typenum = -1;
  ++para.paran; // Increment number of argument
}
#ifndef G__FONS51
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetArgs(const char* args)
{
  int isrc=0;
  char *endmark=(char*)",";

  // separate and evaluate argument list
  para.paran=0;
  int c;
  do {
    c=G__getstream((char*)args,&isrc,para.parameter[para.paran],endmark);
    if (para.parameter[para.paran][0]) {
      // evaluate arg
#ifndef G__OLDIMPLEMENTATION899
      para.para[para.paran] = G__calc(para.parameter[para.paran]);
#else
      para.para[para.paran] = G__getexpr(para.parameter[para.paran]);
#endif
      ++para.paran; // increment argument count
    }
  } while (','==c);
}
#endif
#ifndef G__OLDIMPLEMENTATION540
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetFuncProto(G__ClassInfo* cls
			  ,const char* fname  ,const char* argtype
			  ,long* poffset)
{
#ifndef G__OLDIMPLEMENTATION1035
  G__LockCriticalSection();
#endif

  method = cls->GetMethod(fname,argtype,poffset); // get G__MethodInfo object
  pfunc = method.InterfaceMethod(); // get compiled interface method
#ifdef G__OLDIMPLEMENTATION862
  if((G__InterfaceMethod)NULL==pfunc) {
    SetBytecode(method.GetBytecode()); // try to compile bytecode
  }
#endif
  para.paran=0; // reset parameters, not needed actually, done in SetBytecode

#ifndef G__OLDIMPLEMENTATION1035
  G__UnlockCriticalSection();
#endif
}
#endif
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::SetFunc(G__ClassInfo* cls
			  ,const char* fname  ,const char* args
			  ,long* poffset)
{
  // G__getstream(), G__type2string()
  int isrc=0;
  char *endmark=(char*)",";
  char argtype[G__ONELINE];
  int pos=0;
  G__value *buf;
#ifdef G__OLDIMPLEMENTATION533
#ifdef G__ASM_WHOLEFUNC
  G__MethodInfo method;
#endif
#endif

  // separate and evaluate argument list
  para.paran=0;
  argtype[0]='\0';
  int c;
  do {
    c=G__getstream((char*)args,&isrc,para.parameter[para.paran],endmark);
    if (para.parameter[para.paran][0]) {
      // evaluate arg
#ifndef G__OLDIMPLEMENTATION899
      para.para[para.paran] = G__calc(para.parameter[para.paran]);
#else
      para.para[para.paran] = G__getexpr(para.parameter[para.paran]);
#endif
      buf = &para.para[para.paran];
      // set type string
      if(pos) argtype[pos++]=',';
      strcpy(argtype+pos
	     ,G__type2string(buf->type,buf->tagnum,buf->typenum,(int)buf->ref
			   ,0));
      pos = strlen(argtype);
      ++para.paran; // increment argument count
    }
  } while (','==c);

  method = cls->GetMethod(fname,argtype,poffset); // get G__MethodInfo object
  pfunc = method.InterfaceMethod(); // get compiled interface method
  if((G__InterfaceMethod)NULL==pfunc) {
    int store_paran=para.paran;
    SetBytecode(method.GetBytecode()); // try to compile bytecode
    para.paran=store_paran;
  }
}
///////////////////////////////////////////////////////////////////////////
void G__CallFunc::Exec(void *pobject)
{
  int ret;
  long store_struct_offset;
#ifndef G__OLDIMPLEMENTATION1035
  G__LockCriticalSection();
#endif
  // Set object address
  store_struct_offset = G__store_struct_offset;
  G__store_struct_offset = (long)pobject;
#ifndef G__OLDIMPLEMENTATION1591
  SetFuncType();
#endif
  // Call function
#ifdef G__ASM_WHOLEFUNC
  if(pfunc) ret = (*pfunc)(&result,(char*)bytecode,&para,0);
#else
  if(pfunc) ret = (*pfunc)(&result,(char*)NULL,&para,0);
#endif
#ifndef G__OLDIMPLEMENTATION823
  else ret = ExecInterpretedFunc(&result);
#endif
  // Restore  object address
  G__store_struct_offset = store_struct_offset;
  if(0==ret) {
    /* error */
  }
#ifndef G__OLDIMPLEMENTATION1035
  G__UnlockCriticalSection();
#endif
}
///////////////////////////////////////////////////////////////////////////
long G__CallFunc::ExecInt(void *pobject)
{
  int ret;
  long store_struct_offset;
  // Set object address
  store_struct_offset = G__store_struct_offset;
  G__store_struct_offset = (long)pobject;
#ifndef G__OLDIMPLEMENTATION1591
  SetFuncType();
#endif
  // Call function
#ifdef G__ASM_WHOLEFUNC
  if(pfunc) ret = (*pfunc)(&result,(char*)bytecode,&para,0);
#else
  if(pfunc) ret = (*pfunc)(&result,(char*)NULL,&para,0);
#endif
#ifndef G__OLDIMPLEMENTATION823
  else ret = ExecInterpretedFunc(&result);
#endif
  // Restore  object address
  G__store_struct_offset = store_struct_offset;
  if(0==ret) {
    /* error */
  }
  return(G__int(result));
}
///////////////////////////////////////////////////////////////////////////
double G__CallFunc::ExecDouble(void *pobject)
{
  int ret;
  long store_struct_offset;
  // Set object address
  store_struct_offset = G__store_struct_offset;
  G__store_struct_offset = (long)pobject;
#ifndef G__OLDIMPLEMENTATION1591
  SetFuncType();
#endif
  // Call function
#ifdef G__ASM_WHOLEFUNC
  if(pfunc) ret = (*pfunc)(&result,(char*)bytecode,&para,0);
#else
  if(pfunc) ret = (*pfunc)(&result,(char*)NULL,&para,0);
#endif
#ifndef G__OLDIMPLEMENTATION823
  else ret = ExecInterpretedFunc(&result);
#endif
  // Restore  object address
  G__store_struct_offset = store_struct_offset;
  if(0==ret) {
    /* error */
  }
  return(G__double(result));
}
///////////////////////////////////////////////////////////////////////////
int G__CallFunc::ExecInterpretedFunc(G__value* presult)
{
  int ret=0;
  if(method.IsValid()) {
    int store_asm_exec=G__asm_exec;
    int store_asm_index=G__asm_index;
    int store_asm_noverflow = G__asm_noverflow;
    G__asm_exec=1;
    G__asm_index = method.Index();
    G__asm_noverflow = 0;
    ret = G__interpret_func(presult,(char*)method.Name()
		            ,&para,method.Hash(),method.ifunc()
			    ,G__EXACT,G__TRYNORMAL);
    G__asm_exec = store_asm_exec;
    G__asm_index= store_asm_index;
    G__asm_noverflow = store_asm_noverflow;
  }
  return(ret);
}
///////////////////////////////////////////////////////////////////////////
#ifndef G__OLDIMPLEMENTATION1591
void G__CallFunc::SetFuncType() {
  if(method.IsValid()) {
    struct G__ifunc_table *ifunc = method.ifunc();
    int ifn = method.Index();
    result.type = ifunc->type[ifn];
    result.tagnum = ifunc->p_tagtable[ifn];
    result.typenum = ifunc->p_typetable[ifn];
    result.isconst = ifunc->isconst[ifn];
    if('d'!=result.type&&'f'!=result.type) {
      result.obj.reftype.reftype = ifunc->reftype[ifn];
    }
  }
}
#endif
///////////////////////////////////////////////////////////////////////////

<|endoftext|>