<commit_before>#include "libtorrent/session.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/extensions/ut_pex.hpp"
#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/operations.hpp>

#include "test.hpp"
#include "setup_transfer.hpp"

using boost::filesystem::remove_all;

void test_pex()
{
	using namespace libtorrent;

	session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48200, 49000));
	session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49200, 50000));
	session ses3(fingerprint("LT", 0, 1, 0, 0), std::make_pair(50200, 51000));

	// this is to avoid everything finish from a single peer
	// immediately. To make the swarm actually connect all
	// three peers before finishing.
	float rate_limit = 500000;
	ses1.set_upload_rate_limit(int(rate_limit));
	ses2.set_download_rate_limit(int(rate_limit));
	ses3.set_download_rate_limit(int(rate_limit));
	// make the peer connecting the two worthless to transfer
	// data, to force peer 3 to connect directly to peer 1 through pex
	ses2.set_upload_rate_limit(200);
	ses3.set_upload_rate_limit(int(rate_limit / 2));

	ses1.add_extension(&create_ut_pex_plugin);
	ses2.add_extension(&create_ut_pex_plugin);

	session_settings settings;
	settings.allow_multiple_connections_per_ip = true;
	settings.ignore_limits_on_local_network = false;
	ses1.set_settings(settings);
	ses2.set_settings(settings);
	ses3.set_settings(settings);

#ifndef TORRENT_DISABLE_ENCRYPTION
	pe_settings pes;
	pes.out_enc_policy = pe_settings::forced;
	pes.in_enc_policy = pe_settings::forced;
	ses1.set_pe_settings(pes);
	ses2.set_pe_settings(pes);
	ses3.set_pe_settings(pes);
#endif

	torrent_handle tor1;
	torrent_handle tor2;
	torrent_handle tor3;

	boost::tie(tor1, tor2, tor3) = setup_transfer(&ses1, &ses2, &ses3, true, false, false, "_pex");

	test_sleep(1000);

	tor2.connect_peer(tcp::endpoint(address::from_string("127.0.0.1"), ses1.listen_port()));
	tor2.connect_peer(tcp::endpoint(address::from_string("127.0.0.1"), ses3.listen_port()));

	for (int i = 0; i < 40; ++i)
	{
		print_alerts(ses1, "ses1");
		print_alerts(ses2, "ses2");
		print_alerts(ses3, "ses3");

		torrent_status st1 = tor1.status();
		torrent_status st2 = tor2.status();
		torrent_status st3 = tor3.status();

		std::cerr
			<< "\033[33m" << int(st1.upload_payload_rate / 1000.f) << "kB/s "
			<< st1.num_peers << ": "
			<< "\033[32m" << int(st2.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st2.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st2.progress * 100) << "% "
			<< st2.num_peers << " - "
			<< "\033[32m" << int(st3.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st3.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st3.progress * 100) << "% "
			<< st3.num_peers
			<< std::endl;

		test_sleep(1000);
	}

	TEST_CHECK(tor2.is_seed());
	TEST_CHECK(tor3.is_seed());

	if (!tor2.is_seed() && tor3.is_seed()) std::cerr << "done\n";
}

int test_main()
{
	using namespace libtorrent;
	using namespace boost::filesystem;

	// in case the previous run was terminated
	try { remove_all("./tmp1_pex"); } catch (std::exception&) {}
	try { remove_all("./tmp2_pex"); } catch (std::exception&) {}
	try { remove_all("./tmp3_pex"); } catch (std::exception&) {}

	test_pex();

	remove_all("./tmp1_pex");
	remove_all("./tmp2_pex");
	remove_all("./tmp3_pex");

	return 0;
}

<commit_msg>fixed pex test<commit_after>#include "libtorrent/session.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/hasher.hpp"
#include "libtorrent/extensions/ut_pex.hpp"
#include <boost/thread.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/operations.hpp>

#include "test.hpp"
#include "setup_transfer.hpp"

using boost::filesystem::remove_all;

void test_pex()
{
	using namespace libtorrent;

	session ses1(fingerprint("LT", 0, 1, 0, 0), std::make_pair(48200, 49000));
	session ses2(fingerprint("LT", 0, 1, 0, 0), std::make_pair(49200, 50000));
	session ses3(fingerprint("LT", 0, 1, 0, 0), std::make_pair(50200, 51000));

	// this is to avoid everything finish from a single peer
	// immediately. To make the swarm actually connect all
	// three peers before finishing.
	float rate_limit = 500000;
	ses1.set_upload_rate_limit(int(rate_limit));
	ses2.set_download_rate_limit(int(rate_limit));
	ses3.set_download_rate_limit(int(rate_limit));
	// make the peer connecting the two worthless to transfer
	// data, to force peer 3 to connect directly to peer 1 through pex
	ses2.set_upload_rate_limit(200);
	ses3.set_upload_rate_limit(int(rate_limit / 2));

	ses1.add_extension(&create_ut_pex_plugin);
	ses2.add_extension(&create_ut_pex_plugin);

	session_settings settings;
	settings.allow_multiple_connections_per_ip = true;
	settings.ignore_limits_on_local_network = false;
	ses1.set_settings(settings);
	ses2.set_settings(settings);
	ses3.set_settings(settings);

#ifndef TORRENT_DISABLE_ENCRYPTION
	pe_settings pes;
	pes.out_enc_policy = pe_settings::forced;
	pes.in_enc_policy = pe_settings::forced;
	ses1.set_pe_settings(pes);
	ses2.set_pe_settings(pes);
	ses3.set_pe_settings(pes);
#endif

	torrent_handle tor1;
	torrent_handle tor2;
	torrent_handle tor3;

	boost::tie(tor1, tor2, tor3) = setup_transfer(&ses1, &ses2, &ses3, true, false, false, "_pex");

	test_sleep(1000);

	tor2.connect_peer(tcp::endpoint(address::from_string("127.0.0.1"), ses1.listen_port()));
	tor2.connect_peer(tcp::endpoint(address::from_string("127.0.0.1"), ses3.listen_port()));

	for (int i = 0; i < 40; ++i)
	{
		print_alerts(ses1, "ses1");
		print_alerts(ses2, "ses2");
		print_alerts(ses3, "ses3");

		torrent_status st1 = tor1.status();
		torrent_status st2 = tor2.status();
		torrent_status st3 = tor3.status();

		std::cerr
			<< "\033[33m" << int(st1.upload_payload_rate / 1000.f) << "kB/s "
			<< st1.num_peers << ": "
			<< "\033[32m" << int(st2.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st2.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st2.progress * 100) << "% "
			<< st2.num_peers << " - "
			<< "\033[32m" << int(st3.download_payload_rate / 1000.f) << "kB/s "
			<< "\033[31m" << int(st3.upload_payload_rate / 1000.f) << "kB/s "
			<< "\033[0m" << int(st3.progress * 100) << "% "
			<< st3.num_peers
			<< std::endl;

		if (st3.state == torrent_status::seeding) break;
		test_sleep(1000);
	}

	TEST_CHECK(tor3.is_seed());

	if (!tor2.is_seed() && tor3.is_seed()) std::cerr << "done\n";
}

int test_main()
{
	using namespace libtorrent;
	using namespace boost::filesystem;

	// in case the previous run was terminated
	try { remove_all("./tmp1_pex"); } catch (std::exception&) {}
	try { remove_all("./tmp2_pex"); } catch (std::exception&) {}
	try { remove_all("./tmp3_pex"); } catch (std::exception&) {}

	test_pex();

	remove_all("./tmp1_pex");
	remove_all("./tmp2_pex");
	remove_all("./tmp3_pex");

	return 0;
}

<|endoftext|>


<commit_before>
#include "evpp/exp.h"
#include "./test_common.h"
#include "evpp/duration.h"
#include "evpp/timestamp.h"

TEST_UNIT(testDuration) {
    evpp::Duration d0(0);
    evpp::Duration d1(1);
    evpp::Duration d2(2);
    evpp::Duration d3(2);
    H_TEST_ASSERT(d0 < d1);
    H_TEST_ASSERT(d1 < d2);
    H_TEST_ASSERT(d2 == d3);
    H_TEST_ASSERT(d0.IsZero());
    H_TEST_ASSERT(d0 <= d1);
    H_TEST_ASSERT(d1 <= d2);
    H_TEST_ASSERT(d2 <= d3);
    H_TEST_ASSERT(d2 >= d3);
    H_TEST_ASSERT(d1 > d0);
    H_TEST_ASSERT(d2 > d1);
    H_TEST_ASSERT(d1 >= d0);
    H_TEST_ASSERT(d2 >= d1);
}

TEST_UNIT(testTimestamp) {
}

<commit_msg>Add Timestamp test code<commit_after>
#include "evpp/exp.h"
#include "./test_common.h"
#include "evpp/duration.h"
#include "evpp/timestamp.h"

TEST_UNIT(testDuration) {
    evpp::Duration d0(0);
    evpp::Duration d1(1);
    evpp::Duration d2(2);
    evpp::Duration d3(2);
    H_TEST_ASSERT(d0 < d1);
    H_TEST_ASSERT(d1 < d2);
    H_TEST_ASSERT(d2 == d3);
    H_TEST_ASSERT(d0.IsZero());
    H_TEST_ASSERT(d0 <= d1);
    H_TEST_ASSERT(d1 <= d2);
    H_TEST_ASSERT(d2 <= d3);
    H_TEST_ASSERT(d2 >= d3);
    H_TEST_ASSERT(d1 > d0);
    H_TEST_ASSERT(d2 > d1);
    H_TEST_ASSERT(d1 >= d0);
    H_TEST_ASSERT(d2 >= d1);
}

TEST_UNIT(testTimestamp) {
    int64_t c_s = time(NULL);
    int64_t c_us = evpp::utcmicrosecond();
    int64_t ts_ns = evpp::Timestamp::Now().UnixNano();
    int64_t c11_us = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
    H_TEST_ASSERT(c_us/1000000 == c11_us/1000000);
    H_TEST_ASSERT(c_s == c11_us/1000000);
    H_TEST_ASSERT(c_s == ts_ns/evpp::Duration::kSecond);
}

<|endoftext|>


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

#ifndef _SLIDESHOW_ANIMATIONSETNODE_HXX
#define _SLIDESHOW_ANIMATIONSETNODE_HXX

#include <activityanimationbasenode.hxx>

namespace presentation
{
    namespace internal
    {
        class AnimationSetNode : public ActivityAnimationBaseNode
        {
        public:
            AnimationSetNode( const ::com::sun::star::uno::Reference<
                                      ::com::sun::star::animations::XAnimationNode >&   xNode,
                              const BaseContainerNodeSharedPtr&                     rParent,
                              const NodeContext&                                    rContext );

            virtual bool init();

#if defined(VERBOSE) && defined(DBG_UTIL)
            virtual const char* getDescription() const;
#endif

        private:
            void implScheduleDeactivationEvent() const;
            AnimationActivitySharedPtr createSetActivity();
        };

        typedef ::boost::shared_ptr< AnimationSetNode > AnimationSetNodeSharedPtr;
    }
}

#endif /* _SLIDESHOW_ANIMATIONSETNODE_HXX */
<commit_msg>INTEGRATION: CWS presfixes10 (1.4.8); FILE MERGED 2005/11/07 15:26:50 dbo 1.4.8.1: #i45197# revised code Issue number: Submitted by: Reviewed by:<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: animationsetnode.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2006-07-26 07:32:46 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef INCLUDED_SLIDESHOW_ANIMATIONSETNODE_HXX
#define INCLUDED_SLIDESHOW_ANIMATIONSETNODE_HXX

#include "animationbasenode.hxx"

namespace presentation {
namespace internal {

class AnimationSetNode : public AnimationBaseNode
{
public:
    AnimationSetNode(
        ::com::sun::star::uno::Reference<
        ::com::sun::star::animations::XAnimationNode> const& xNode,
        ::boost::shared_ptr<BaseContainerNode> const& pParent,
        NodeContext const& rContext )
        : AnimationBaseNode( xNode, pParent, rContext ) {}

#if defined(VERBOSE) && defined(DBG_UTIL)
    virtual const char* getDescription() const { return "AnimationSetNode"; }
#endif

private:
    virtual AnimationActivitySharedPtr createActivity() const;
    void implScheduleDeactivationEvent();
};

} // namespace internal
} // namespace presentation

#endif /* INCLUDED_SLIDESHOW_ANIMATIONSETNODE_HXX */

<|endoftext|>


<commit_before>

#include "miopen.hpp"
#include "tensor.hpp"
#include "utils.hpp"
#include "layers.hpp"
#include "multi_layers.hpp"

void benchmark_convlayers() {
    // batch_size, w, h, channels_in, channels_out, kernel_size, padding, stride
    // Layerwise benchmark L1-L5: https://github.com/soumith/convnet-benchmarks
    std::vector<ConvLayerDesc> runs = {{128, 13, 13, 384, 384, 3, 0, 1},
                                   {128, 16, 16, 128, 128, 7, 0, 1},
                                   {128, 32, 32, 128, 128, 9, 0, 1},
                                   {128, 64, 64, 64, 128, 9, 0, 1},
                                   {128, 128, 128, 3, 96, 11, 0, 1}};

    /*
    std::vector<ConvLayerDesc> runs = {{128, 64, 64, 64, 128, 3, 1, 1}};
                                       {128, 64, 64, 64, 128, 3, 0, 1},
                                       {128, 28, 28, 64, 64, 5, 1, 2}};
                                       */

    int layer = 5;
    int reps = 50;
    BenchmarkLogger::new_session("conv_layers");
    for (ConvLayerDesc& l : runs) {
        std::stringstream ss;
        ss << "Layer L" << layer;
        TensorDesc input_dim(l.batch_size, l.channels_in, l.height, l.width);
        Model m(input_dim, ss.str());
        m.emplace<ConvLayer>(l.channels_out, l.kernel_size, l.padding, l.stride);

        BenchmarkLogger::benchmark(m, reps);

        --layer;
    }
}

int main(int argc, char *argv[])
{
    device_init();
    CHECK_MIO(miopenEnableProfiling(mio::handle(), true));

    benchmark_convlayers();
}
<commit_msg>randomly init layerwise benchmark<commit_after>

#include "miopen.hpp"
#include "tensor.hpp"
#include "utils.hpp"
#include "layers.hpp"
#include "multi_layers.hpp"

void benchmark_convlayers() {
    // batch_size, w, h, channels_in, channels_out, kernel_size, padding, stride
    // Layerwise benchmark L1-L5: https://github.com/soumith/convnet-benchmarks
    std::vector<ConvLayerDesc> runs = {{128, 13, 13, 384, 384, 3, 0, 1},
                                   {128, 16, 16, 128, 128, 7, 0, 1},
                                   {128, 32, 32, 128, 128, 9, 0, 1},
                                   {128, 64, 64, 64, 128, 9, 0, 1},
                                   {128, 128, 128, 3, 96, 11, 0, 1}};

    /*
    std::vector<ConvLayerDesc> runs = {{128, 64, 64, 64, 128, 3, 1, 1}};
                                       {128, 64, 64, 64, 128, 3, 0, 1},
                                       {128, 28, 28, 64, 64, 5, 1, 2}};
                                       */

    int layer = 5;
    int reps = 50;
    BenchmarkLogger::new_session("conv_layers");
    for (ConvLayerDesc& l : runs) {
        std::stringstream ss;
        ss << "Layer L" << layer;
        TensorDesc input_dim(l.batch_size, l.channels_in, l.height, l.width);
        Model m(input_dim, ss.str());
        m.emplace<ConvLayer>(l.channels_out, l.kernel_size, l.padding, l.stride);

        m.input.uniform(); // randomly initialize input
        BenchmarkLogger::benchmark(m, reps);

        --layer;
    }
}

int main(int argc, char *argv[])
{
    device_init();
    CHECK_MIO(miopenEnableProfiling(mio::handle(), true));

    benchmark_convlayers();
}
<|endoftext|>


<commit_before>/*
 * SpawnAreaMap.cpp
 *
 *  Created on: 12/08/2011
 *      Author: TheAnswer
 */

#include "SpawnAreaMap.h"
#include "server/zone/Zone.h"
#include "server/zone/managers/creature/CreatureManager.h"
#include "server/zone/objects/creature/AiAgent.h"
#include "server/conf/ConfigManager.h"
#include "server/zone/objects/area/areashapes/CircularAreaShape.h"

void SpawnAreaMap::loadMap(Zone* z) {
	zone = z;
	String planetName = zone->getZoneName();

	setLoggingName("SpawnAreaMap " + planetName);

	lua->init();

	try {
		lua->runFile("scripts/managers/spawn_manager/" + planetName + ".lua");

		LuaObject obj = lua->getGlobalObject(planetName + "_regions");

		if (obj.isValidTable()) {
			lua_State* s = obj.getLuaState();

			for (int i = 1; i <= obj.getTableSize(); ++i) {
				lua_rawgeti(s, -1, i);
				LuaObject areaObj(s);

				if (areaObj.isValidTable()) {
					readAreaObject(areaObj);
				}

				areaObj.pop();
			}
		}

		obj.pop();

		for (int i = 0; i < size(); ++i) {
			SpawnArea* area = get(i);

			for (int j = 0; j < noSpawnAreas.size(); ++j) {
				SpawnArea* notHere = noSpawnAreas.get(j);

				if (area->intersectsWith(notHere)) {
					area->addNoSpawnArea(notHere);
				}
			}
		}

		loadStaticSpawns();
	} catch (Exception& e) {
		error(e.getMessage());
	}

	lua->deinit();

	delete lua;
	lua = NULL;
}

void SpawnAreaMap::loadStaticSpawns() {
	String planetName = zone->getZoneName();

	LuaObject obj = lua->getGlobalObject(planetName + "_static_spawns");

	if (!obj.isValidTable()) {
		obj.pop();
		return;
	}

	int count = 0;
	int max = obj.getTableSize();

	for (int i = 1; i <= obj.getTableSize(); ++i) {
		lua_rawgeti(obj.getLuaState(), -1, i);
		LuaObject spawn(obj.getLuaState());

		if (spawn.isValidTable()) {
			CreatureManager* creatureManager = zone->getCreatureManager();

			String name = obj.getStringAt(1);
			uint32 respawn = obj.getIntAt(2);
			float x = obj.getFloatAt(3);
			float z = obj.getFloatAt(4);
			float y = obj.getFloatAt(5);
			float heading = obj.getFloatAt(6);
			uint64 parentID = obj.getLongAt(7);
			String moodString;
			UnicodeString customName;

			if (obj.getTableSize() > 7)
				moodString = obj.getStringAt(8);

			if (obj.getTableSize() > 8)
				customName = obj.getStringAt(9);

			if (parentID == 0)
				z = zone->getHeight(x, y);

			ManagedReference<CreatureObject*> creatureObject = creatureManager->spawnCreature(name.hashCode(), 0, x, z, y, parentID);

			if (creatureObject != NULL) {
				creatureObject->setDirection(Math::deg2rad(heading));

				if (!moodString.isEmpty()) {
					creatureObject->setMoodString(moodString);

					//TODO: remove after fixing commoners
					if (moodString == "conversation" || moodString == "calm") {
						creatureObject->setPvpStatusBitmask(0);
						creatureObject->setCloseObjects(NULL);
					}
				}

				if (!customName.isEmpty())
					creatureObject->setCustomObjectName(customName, true);

				if (creatureObject->isAiAgent()) {
					AiAgent* ai = cast<AiAgent*>( creatureObject.get());
					ai->setRespawnTimer(respawn);
				}

				if (name.contains("trainer_")) {
					Vector3 coords(creatureObject.get()->getWorldPositionX(), creatureObject.get()->getWorldPositionY(), 0);
					trainerObjects.add(coords);
				}
			} else {
				StringBuffer msg;
				msg << "could not spawn mobile: " + name;
				error(msg.toString());
			}
		}

		spawn.pop();

		if (ConfigManager::instance()->isProgressMonitorActivated())
			printf("\r\tLoading static spawns: [%d] / [%d]\t", ++count, max);
	}

	obj.pop();

	//--{"mobile", x, z, y, degrees heading, parentID}

	//spawnCreature(uint32 templateCRC, uint32 objectCRC, float x, float z, float y, uint64 parentID)
}

void SpawnAreaMap::readAreaObject(LuaObject& areaObj) {
	String name = areaObj.getStringAt(1);
	float x = areaObj.getFloatAt(2);
	float y = areaObj.getFloatAt(3);
	float radius = areaObj.getFloatAt(4);
	int tier = areaObj.getIntAt(5);
	int constant = areaObj.getIntAt(6);

	if (radius == 0)
		return;

	uint32 crc = 0;
	switch (tier) {
	case 0:
	case 1:
		crc = String("object/static_spawn_area.iff").hashCode();
		break;
	case 2:
		crc = String("object/dynamic_spawn_area.iff").hashCode();
		break;
	case 3:
	case 4:
	case 5:
	case 6:
		crc = String("object/lair_spawn_area.iff").hashCode();
		break;
	default:
		error("unknown tier " + String::valueOf(tier));
		crc = String("object/dynamic_spawn_area.iff").hashCode();
		break;
	}

	ManagedReference<SpawnArea*> area = dynamic_cast<SpawnArea*>(ObjectManager::instance()->createObject(crc, 0, "spawnareas"));
	if (area == NULL)
		return;

	StringId nameID(zone->getZoneName() + "_region_names", name);

	area->setObjectName(nameID);

	ManagedReference<CircularAreaShape*> circularAreaShape = new CircularAreaShape();
	circularAreaShape->setAreaCenter(x, y);
	circularAreaShape->setRadius(radius);
	area->setAreaShape(circularAreaShape);

	area->setTier(tier);

	area->setSpawnConstant(constant);

	for (int j = 7; j <= areaObj.getTableSize(); ++j)
		area->addTemplate(areaObj.getStringAt(j).hashCode());

	if (radius != -1)
		zone->transferObject(area, -1, true);
	else {
		circularAreaShape->setRadius(zone->getBoundingRadius());

		switch (tier) {
		case 4:
			factionalNeutralMissionSpawnAreas.add(area);
			break;
		case 5:
			factionalRebelMissionSpawnAreas.add(area);
			break;
		case 6:
			factionalImperialMissionSpawnAreas.add(area);
			break;
		default:
			worldSpawnAreas.add(area);
			break;
		}

		area->setZone(zone);
	}

	area->updateToDatabase();

	put(nameID.getStringID().hashCode(), area);

	if (area->isStaticArea()) {
		noSpawnAreas.add(area);
		if (tier == 1) {
			StaticSpawnArea* staticArea = cast<StaticSpawnArea*>(area.get());
			staticArea->spawnCreatures();
		}
	}
}

Vector3 SpawnAreaMap::getRandomJediTrainer() {
	uint32 size = trainerObjects.size();
	return trainerObjects.get(System::random(size - 1));
}
<commit_msg>(unstable) [updated] Spawn area map to support reading in both circular and rectangular area shapes from lua files.<commit_after>/*
 * SpawnAreaMap.cpp
 *
 *  Created on: 12/08/2011
 *      Author: TheAnswer
 */

#include "SpawnAreaMap.h"
#include "server/zone/Zone.h"
#include "server/zone/managers/creature/CreatureManager.h"
#include "server/zone/objects/creature/AiAgent.h"
#include "server/conf/ConfigManager.h"
#include "server/zone/objects/area/areashapes/CircularAreaShape.h"
#include "server/zone/objects/area/areashapes/RectangularAreaShape.h"

void SpawnAreaMap::loadMap(Zone* z) {
	zone = z;
	String planetName = zone->getZoneName();

	setLoggingName("SpawnAreaMap " + planetName);

	lua->init();

	try {
		lua->runFile("scripts/managers/spawn_manager/" + planetName + ".lua");

		LuaObject obj = lua->getGlobalObject(planetName + "_regions");

		if (obj.isValidTable()) {
			lua_State* s = obj.getLuaState();

			for (int i = 1; i <= obj.getTableSize(); ++i) {
				lua_rawgeti(s, -1, i);
				LuaObject areaObj(s);

				if (areaObj.isValidTable()) {
					readAreaObject(areaObj);
				}

				areaObj.pop();
			}
		}

		obj.pop();

		for (int i = 0; i < size(); ++i) {
			SpawnArea* area = get(i);

			for (int j = 0; j < noSpawnAreas.size(); ++j) {
				SpawnArea* notHere = noSpawnAreas.get(j);

				if (area->intersectsWith(notHere)) {
					area->addNoSpawnArea(notHere);
				}
			}
		}

		loadStaticSpawns();
	} catch (Exception& e) {
		error(e.getMessage());
	}

	lua->deinit();

	delete lua;
	lua = NULL;
}

void SpawnAreaMap::loadStaticSpawns() {
	String planetName = zone->getZoneName();

	LuaObject obj = lua->getGlobalObject(planetName + "_static_spawns");

	if (!obj.isValidTable()) {
		obj.pop();
		return;
	}

	int count = 0;
	int max = obj.getTableSize();

	for (int i = 1; i <= obj.getTableSize(); ++i) {
		lua_rawgeti(obj.getLuaState(), -1, i);
		LuaObject spawn(obj.getLuaState());

		if (spawn.isValidTable()) {
			CreatureManager* creatureManager = zone->getCreatureManager();

			String name = obj.getStringAt(1);
			uint32 respawn = obj.getIntAt(2);
			float x = obj.getFloatAt(3);
			float z = obj.getFloatAt(4);
			float y = obj.getFloatAt(5);
			float heading = obj.getFloatAt(6);
			uint64 parentID = obj.getLongAt(7);
			String moodString;
			UnicodeString customName;

			if (obj.getTableSize() > 7)
				moodString = obj.getStringAt(8);

			if (obj.getTableSize() > 8)
				customName = obj.getStringAt(9);

			if (parentID == 0)
				z = zone->getHeight(x, y);

			ManagedReference<CreatureObject*> creatureObject = creatureManager->spawnCreature(name.hashCode(), 0, x, z, y, parentID);

			if (creatureObject != NULL) {
				creatureObject->setDirection(Math::deg2rad(heading));

				if (!moodString.isEmpty()) {
					creatureObject->setMoodString(moodString);

					//TODO: remove after fixing commoners
					if (moodString == "conversation" || moodString == "calm") {
						creatureObject->setPvpStatusBitmask(0);
						creatureObject->setCloseObjects(NULL);
					}
				}

				if (!customName.isEmpty())
					creatureObject->setCustomObjectName(customName, true);

				if (creatureObject->isAiAgent()) {
					AiAgent* ai = cast<AiAgent*>( creatureObject.get());
					ai->setRespawnTimer(respawn);
				}

				if (name.contains("trainer_")) {
					Vector3 coords(creatureObject.get()->getWorldPositionX(), creatureObject.get()->getWorldPositionY(), 0);
					trainerObjects.add(coords);
				}
			} else {
				StringBuffer msg;
				msg << "could not spawn mobile: " + name;
				error(msg.toString());
			}
		}

		spawn.pop();

		if (ConfigManager::instance()->isProgressMonitorActivated())
			printf("\r\tLoading static spawns: [%d] / [%d]\t", ++count, max);
	}

	obj.pop();

	//--{"mobile", x, z, y, degrees heading, parentID}

	//spawnCreature(uint32 templateCRC, uint32 objectCRC, float x, float z, float y, uint64 parentID)
}

void SpawnAreaMap::readAreaObject(LuaObject& areaObj) {
	String name = areaObj.getStringAt(1);
	float x = areaObj.getFloatAt(2);
	float y = areaObj.getFloatAt(3);
	int tier = areaObj.getIntAt(5);
	int constant = areaObj.getIntAt(6);

	float radius = 0;
	float width = 0;
	float height = 0;

    LuaObject areaShapeObject = areaObj.getObjectAt(4);
    if (areaShapeObject.isValidTable()) {
        if (areaShapeObject.getIntAt(1) == 1) {
            radius = areaShapeObject.getFloatAt(2);
        } else if (areaShapeObject.getIntAt(1) == 2) {
            width = areaShapeObject.getFloatAt(2);
            height = areaShapeObject.getFloatAt(3);
        }
        areaShapeObject.pop();
    } else {
    	areaShapeObject.pop();
        radius = areaObj.getFloatAt(4);
        width = 0;
        height = 0;
    }

	if (radius == 0 && width == 0 && height == 0)
		return;

	uint32 crc = 0;
	switch (tier) {
	case 0:
	case 1:
		crc = String("object/static_spawn_area.iff").hashCode();
		break;
	case 2:
		crc = String("object/dynamic_spawn_area.iff").hashCode();
		break;
	case 3:
	case 4:
	case 5:
	case 6:
		crc = String("object/lair_spawn_area.iff").hashCode();
		break;
	default:
		error("unknown tier " + String::valueOf(tier));
		crc = String("object/dynamic_spawn_area.iff").hashCode();
		break;
	}

	ManagedReference<SpawnArea*> area = dynamic_cast<SpawnArea*>(ObjectManager::instance()->createObject(crc, 0, "spawnareas"));
	if (area == NULL)
		return;

	StringId nameID(zone->getZoneName() + "_region_names", name);

	area->setObjectName(nameID);

	if (height > 0 && width > 0) {
		ManagedReference<RectangularAreaShape*> rectangularAreaShape = new RectangularAreaShape();
		rectangularAreaShape->setAreaCenter(x, y);
		rectangularAreaShape->setDimensions(height, width);
		area->setAreaShape(rectangularAreaShape);
	} else if (radius > 0) {
		ManagedReference<CircularAreaShape*> circularAreaShape = new CircularAreaShape();
		circularAreaShape->setAreaCenter(x, y);
		circularAreaShape->setRadius(radius);
		area->setAreaShape(circularAreaShape);
	} else {
		return;
	}

	area->setTier(tier);

	area->setSpawnConstant(constant);

	for (int j = 7; j <= areaObj.getTableSize(); ++j)
		area->addTemplate(areaObj.getStringAt(j).hashCode());

	if (radius != -1)
		zone->transferObject(area, -1, true);
	else {
		switch (tier) {
		case 4:
			factionalNeutralMissionSpawnAreas.add(area);
			break;
		case 5:
			factionalRebelMissionSpawnAreas.add(area);
			break;
		case 6:
			factionalImperialMissionSpawnAreas.add(area);
			break;
		default:
			worldSpawnAreas.add(area);
			break;
		}

		area->setZone(zone);
	}

	area->updateToDatabase();

	put(nameID.getStringID().hashCode(), area);

	if (area->isStaticArea()) {
		noSpawnAreas.add(area);
		if (tier == 1) {
			StaticSpawnArea* staticArea = cast<StaticSpawnArea*>(area.get());
			staticArea->spawnCreatures();
		}
	}
}

Vector3 SpawnAreaMap::getRandomJediTrainer() {
	uint32 size = trainerObjects.size();
	return trainerObjects.get(System::random(size - 1));
}
<|endoftext|>


<commit_before>#include <allegro.h>
#ifdef WINDOWS
#include <winalleg.h>
#endif

#include "init.h"
#include <pthread.h>

#include <iostream>
#include <dumb.h>
#include <aldumb.h>
#include <loadpng.h>
#include "util/bitmap.h"

using namespace std;

volatile double Global::speed_counter = 0;
volatile int Global::second_counter = 0;

static const int TICS_PER_SECOND = 90;

pthread_mutex_t Global::loading_screen_mutex;
bool Global::done_loading = false;

const int Global::WINDOWED = GFX_AUTODETECT_WINDOWED;
const int Global::FULLSCREEN = GFX_AUTODETECT_FULLSCREEN;

// DATAFILE * Global::all_fonts;

void inc_speed_counter() {
	Global::speed_counter += 1.0;
}
END_OF_FUNCTION( inc_speed_counter );

void inc_second_counter() {
	Global::second_counter++;
}
END_OF_FUNCTION( inc_second_counter );

bool init( int gfx ){

	cout << "Allegro version: " << ALLEGRO_VERSION_STR << endl;
	cout<<"Allegro init: "<<allegro_init()<<endl;
	cout<<"Loadpng init: "<<loadpng_init()<<endl;
	cout<<"Install timer: "<<install_timer()<<endl;

	set_volume_per_voice( 0 );
	cout<<"Install sound: "<<install_sound( DIGI_AUTODETECT, MIDI_NONE, "" )<<endl;

	cout<<"Install keyboard: "<<install_keyboard()<<endl;
	cout<<"Install mouse: "<<install_mouse()<<endl;
	loadpng_init();
	set_color_depth( 16 );
	cout<<"Set gfx mode: "<<set_gfx_mode( gfx, GFX_X, GFX_Y, 0, 0 )<<endl;

	LOCK_VARIABLE( speed_counter );
	LOCK_VARIABLE( second_counter );
	LOCK_FUNCTION( (void *)inc_speed_counter );
	LOCK_FUNCTION( (void *)inc_second_counter );
	cout<<"Install game timer: "<<install_int_ex( inc_speed_counter, BPS_TO_TIMER( TICS_PER_SECOND ) )<<endl;
	cout<<"Install second timer: "<<install_int_ex( inc_second_counter, BPS_TO_TIMER( 1 ) )<<endl;
	srand( time( NULL ) );
	// Global::all_fonts = load_datafile( "data/fonts.dat" );
	/*
	if ( ! Global::all_fonts ){
		if ( ! exists( "data/fonts.dat" ) ){
			cout << "data/fonts.dat is missing!" << endl;
		} else {
			cout << "data/fonts.dat is corrupted!" << endl;
		}
		return false;
	}
	cout<<"Loaded fonts " << endl;
	*/

	atexit( &dumb_exit );
	dumb_register_packfiles();

	cout<<"-- END init --"<<endl;

	Bitmap::Screen = new Bitmap( screen );
	if ( ! Bitmap::Screen ){
		return false;
	}
	return true;
}
<commit_msg>set the display mode to background<commit_after>#include <allegro.h>
#ifdef WINDOWS
#include <winalleg.h>
#endif

#include "init.h"
#include <pthread.h>

#include <iostream>
#include <dumb.h>
#include <aldumb.h>
#include <loadpng.h>
#include "util/bitmap.h"

using namespace std;

volatile double Global::speed_counter = 0;
volatile int Global::second_counter = 0;

static const int TICS_PER_SECOND = 90;

pthread_mutex_t Global::loading_screen_mutex;
bool Global::done_loading = false;

const int Global::WINDOWED = GFX_AUTODETECT_WINDOWED;
const int Global::FULLSCREEN = GFX_AUTODETECT_FULLSCREEN;

// DATAFILE * Global::all_fonts;

void inc_speed_counter() {
	Global::speed_counter += 1.0;
}
END_OF_FUNCTION( inc_speed_counter );

void inc_second_counter() {
	Global::second_counter++;
}
END_OF_FUNCTION( inc_second_counter );

bool init( int gfx ){

	cout << "Allegro version: " << ALLEGRO_VERSION_STR << endl;
	cout<<"Allegro init: "<<allegro_init()<<endl;
	cout<<"Loadpng init: "<<loadpng_init()<<endl;
	cout<<"Install timer: "<<install_timer()<<endl;

	set_volume_per_voice( 0 );
	cout<<"Install sound: "<<install_sound( DIGI_AUTODETECT, MIDI_NONE, "" )<<endl;

	cout<<"Install keyboard: "<<install_keyboard()<<endl;
	cout<<"Install mouse: "<<install_mouse()<<endl;
	loadpng_init();
	set_color_depth( 16 );
	cout<<"Set gfx mode: "<<set_gfx_mode( gfx, GFX_X, GFX_Y, 0, 0 )<<endl;

	LOCK_VARIABLE( speed_counter );
	LOCK_VARIABLE( second_counter );
	LOCK_FUNCTION( (void *)inc_speed_counter );
	LOCK_FUNCTION( (void *)inc_second_counter );
	cout<<"Install game timer: "<<install_int_ex( inc_speed_counter, BPS_TO_TIMER( TICS_PER_SECOND ) )<<endl;
	cout<<"Install second timer: "<<install_int_ex( inc_second_counter, BPS_TO_TIMER( 1 ) )<<endl;
	srand( time( NULL ) );
	set_display_switch_mode( SWITCH_BACKGROUND );
	// Global::all_fonts = load_datafile( "data/fonts.dat" );
	/*
	if ( ! Global::all_fonts ){
		if ( ! exists( "data/fonts.dat" ) ){
			cout << "data/fonts.dat is missing!" << endl;
		} else {
			cout << "data/fonts.dat is corrupted!" << endl;
		}
		return false;
	}
	cout<<"Loaded fonts " << endl;
	*/

	atexit( &dumb_exit );
	dumb_register_packfiles();

	cout<<"-- END init --"<<endl;

	Bitmap::Screen = new Bitmap( screen );
	if ( ! Bitmap::Screen ){
		return false;
	}
	return true;
}
<|endoftext|>


<commit_before>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "ClientAuthentication.h"

/* system implementation headers */
#include <string>
#include <assert.h>
#ifdef HAVE_KRB5
#include <com_err.h>
#define err(x,y,z) if (debugLevel >= 1) com_err(x,y,z)
#endif

#include "DirectoryNames.h"

#ifdef HAVE_KRB5
krb5_context      ClientAuthentication::context      = NULL;
krb5_ccache       ClientAuthentication::cc           = NULL;
krb5_auth_context ClientAuthentication::auth_context = NULL;
krb5_data         ClientAuthentication::packet;
krb5_data         ClientAuthentication::inbuf;
krb5_creds        ClientAuthentication::creds;
krb5_creds       *ClientAuthentication::new_creds;
krb5_principal    ClientAuthentication::client;
krb5_principal    ClientAuthentication::server;
char              ClientAuthentication::principalName[128];
#endif
bool              ClientAuthentication::authentication = false;

#ifdef HAVE_KRB5
void ClientAuthentication::init(const char *username, const char *password)
#else
void ClientAuthentication::init(const char *username, const char *)
#endif // HAVE_KRB5
{
  strncpy(principalName, username, 128);
  principalName[127] = 0;

#ifdef HAVE_KRB5
  assert(context == NULL);
  assert(cc == NULL);

  krb5_error_code retval;
  krb5_creds      my_creds;

  // Initializing kerberos library
  if ((retval = krb5_init_context(&context)))
    err("bzflag:", retval, "while initializing krb5");
  // Getting a default cache specifically for bzflag
  std::string ccfile = "FILE:" + getConfigDirName() + "krb5_cc";
  if (context && (retval
		  = krb5_cc_set_default_name(context, ccfile.c_str())))
    err("bzflag", retval, "setting default cache");
  // Getting credential cache
  if (!retval && (retval = krb5_cc_default(context, &cc)))
    err("bzflag:", retval, "getting credentials cache");

  char clientName[139];
  snprintf(clientName, 139, "%s@BZFLAG.ORG", username);
  if (cc && (retval = krb5_parse_name(context, clientName, &client)))
    err("bzflag", retval, "parsing principal name");

  // Initing credential cache
  if (!retval && (retval = krb5_cc_initialize(context, cc, client)))
    err("bzflag", retval, "initializing credential cache");

  char intPassword[128];
  strncpy(intPassword, password, 128);
  intPassword[127] = 0;
  // Get credentials for server
  if (!retval && (retval = krb5_get_init_creds_password(context, &my_creds,
 							client, intPassword,
 							krb5_prompter_posix,
 							NULL, 0, NULL, NULL)))
    err("bzflag", retval, "getting credential");

  // Store credentials in cache
  if (!retval && (retval = krb5_cc_store_cred(context, cc, &my_creds)))
    err("bzflag", retval, "storing credential in cache");

  if (!retval && (retval = krb5_parse_name(context,
					   "krbtgt/BZFLAG.ORG@BZFLAG.ORG",
					   &server)))
    err("bzflag:", retval, "setting up tgt server name");
  authentication = (retval == 0);
#endif
}

#ifdef HAVE_KRB5
void ClientAuthentication::sendCredential(ServerLink &serverLink)
#else
void ClientAuthentication::sendCredential(ServerLink&)
#endif // HAVE_KRB5
{
  if (!authentication)
    return;
#ifdef HAVE_KRB5
  assert(context != NULL);
  assert(cc != NULL);

  krb5_error_code retval;
  /* Get credentials for server */
  memset((char*)&creds, 0, sizeof(creds));
  memcpy(&creds.client, &client, sizeof(client));
  memcpy(&creds.server, &server, sizeof(server));
  /* Get credentials for server */
  if ((retval = krb5_get_credentials(context, KRB5_GC_CACHED, cc, &creds,
				     &new_creds)))
    err("bzflag:", retval, "getting TGT");
  if (!retval) {
    serverLink.sendKerberosTicket(principalName, &new_creds->ticket);
  }
#endif
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>make it compile without kerberos<commit_after>/* bzflag
 * Copyright (c) 1993 - 2004 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named LICENSE that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/* interface header */
#include "ClientAuthentication.h"

/* system implementation headers */
#include <string>
#include <assert.h>
#ifdef HAVE_KRB5
#include <com_err.h>
#define err(x,y,z) if (debugLevel >= 1) com_err(x,y,z)
#endif

#include "DirectoryNames.h"

#ifdef HAVE_KRB5
krb5_context      ClientAuthentication::context      = NULL;
krb5_ccache       ClientAuthentication::cc           = NULL;
krb5_auth_context ClientAuthentication::auth_context = NULL;
krb5_data         ClientAuthentication::packet;
krb5_data         ClientAuthentication::inbuf;
krb5_creds        ClientAuthentication::creds;
krb5_creds       *ClientAuthentication::new_creds;
krb5_principal    ClientAuthentication::client;
krb5_principal    ClientAuthentication::server;
#endif
char              ClientAuthentication::principalName[128];
bool              ClientAuthentication::authentication = false;

#ifdef HAVE_KRB5
void ClientAuthentication::init(const char *username, const char *password)
#else
void ClientAuthentication::init(const char *username, const char *)
#endif // HAVE_KRB5
{
  strncpy(principalName, username, 128);
  principalName[127] = 0;

#ifdef HAVE_KRB5
  assert(context == NULL);
  assert(cc == NULL);

  krb5_error_code retval;
  krb5_creds      my_creds;

  // Initializing kerberos library
  if ((retval = krb5_init_context(&context)))
    err("bzflag:", retval, "while initializing krb5");
  // Getting a default cache specifically for bzflag
  std::string ccfile = "FILE:" + getConfigDirName() + "krb5_cc";
  if (context && (retval
		  = krb5_cc_set_default_name(context, ccfile.c_str())))
    err("bzflag", retval, "setting default cache");
  // Getting credential cache
  if (!retval && (retval = krb5_cc_default(context, &cc)))
    err("bzflag:", retval, "getting credentials cache");

  char clientName[139];
  snprintf(clientName, 139, "%s@BZFLAG.ORG", username);
  if (cc && (retval = krb5_parse_name(context, clientName, &client)))
    err("bzflag", retval, "parsing principal name");

  // Initing credential cache
  if (!retval && (retval = krb5_cc_initialize(context, cc, client)))
    err("bzflag", retval, "initializing credential cache");

  char intPassword[128];
  strncpy(intPassword, password, 128);
  intPassword[127] = 0;
  // Get credentials for server
  if (!retval && (retval = krb5_get_init_creds_password(context, &my_creds,
 							client, intPassword,
 							krb5_prompter_posix,
 							NULL, 0, NULL, NULL)))
    err("bzflag", retval, "getting credential");

  // Store credentials in cache
  if (!retval && (retval = krb5_cc_store_cred(context, cc, &my_creds)))
    err("bzflag", retval, "storing credential in cache");

  if (!retval && (retval = krb5_parse_name(context,
					   "krbtgt/BZFLAG.ORG@BZFLAG.ORG",
					   &server)))
    err("bzflag:", retval, "setting up tgt server name");
  authentication = (retval == 0);
#endif
}

#ifdef HAVE_KRB5
void ClientAuthentication::sendCredential(ServerLink &serverLink)
#else
void ClientAuthentication::sendCredential(ServerLink&)
#endif // HAVE_KRB5
{
  if (!authentication)
    return;
#ifdef HAVE_KRB5
  assert(context != NULL);
  assert(cc != NULL);

  krb5_error_code retval;
  /* Get credentials for server */
  memset((char*)&creds, 0, sizeof(creds));
  memcpy(&creds.client, &client, sizeof(client));
  memcpy(&creds.server, &server, sizeof(server));
  /* Get credentials for server */
  if ((retval = krb5_get_credentials(context, KRB5_GC_CACHED, cc, &creds,
				     &new_creds)))
    err("bzflag:", retval, "getting TGT");
  if (!retval) {
    serverLink.sendKerberosTicket(principalName, &new_creds->ticket);
  }
#endif
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>


<commit_before>#include <Ab/Config.hpp>
#include <Ab/Context.hpp>
#include <Ab/Wasm/Loader.hpp>
#include <Pith/Assert.hpp>
#include <istream>

namespace Ab {
namespace Wasm {

auto Loader::operator()(ActiveContext& cx, std::istream& in)
	-> Pith::Result<Om::Ref<Module>, LoaderError> {
	PITH_ASSERT_UNREACHABLE();
	return Pith::err(LoaderError{});
}

}  // namespace Wasm
}  // namespace Ab
<commit_msg>Note temporarily unused args<commit_after>#include <Ab/Config.hpp>
#include <Ab/Context.hpp>
#include <Ab/Wasm/Loader.hpp>
#include <Pith/Assert.hpp>
#include <istream>

namespace Ab {
namespace Wasm {

auto Loader::operator()([[maybe_unused]] ActiveContext& cx, [[maybe_unused]] std::istream& in)
	-> Pith::Result<Om::Ref<Module>, LoaderError> {
	PITH_ASSERT_UNREACHABLE();
	return Pith::err(LoaderError{});
}

}  // namespace Wasm
}  // namespace Ab
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
/**
 * @file        src/service/plugin/PluginManager.cpp
 * @author      Zofia Abramowska <z.abramowska@samsung.com>
 * @version     1.0
 * @brief       Definition of PluginManager class
 */

#define _BSD_SOURCE_

#include <cinttypes>
#include <cstdlib>
#include <dirent.h>
#include <dlfcn.h>
#include <functional>

#include <log/log.h>

#include "PluginManager.h"

namespace {
    int pluginFilter(const struct dirent *ent) {
#ifdef _DIRENT_HAVE_D_TYPE
        if (ent->d_type != DT_REG) {
            return 0;
        }
#endif
        if (ent->d_name[0] == '.') {
            return 0;
        }
        return 1;
    }
}

namespace Cynara {

PluginManager::PluginManager(const std::string &pluginDir) : m_dir(pluginDir) {
    loadPlugins();
}

PluginManager::~PluginManager(void) {
    // We have to be sure, that external objects will be destroyed
    // before handles to libraries are closed.
    for (auto &plugin : m_plugins) {
        plugin.second.reset();
    }
}

ExternalPluginPtr PluginManager::getPlugin(PolicyType pType) {
    return m_plugins[pType];
}

std::vector<PolicyDescription> PluginManager::getPolicyDescriptions(void) const {
    std::vector<PolicyDescription> descriptions;
    descriptions.reserve(m_plugins.size());
    for (auto &plugin : m_plugins) {
        descriptions.push_back(plugin.first);
    }
    return descriptions;
}

void PluginManager::invalidateAll(void) {
    for (auto &plugin : m_plugins) {
        plugin.second->invalidate();
    }
}

void PluginManager::loadPlugins(void) {
    struct dirent **nameList = NULL;
    int fileAmount = scandir(m_dir.c_str(), &nameList, pluginFilter, alphasort);

    if (fileAmount < 0) {
        auto error = strerror(errno);
        LOGE("Couldn't scan for plugins in <%s> : <%s>", m_dir.c_str(), error);
        return;
    }

    std::unique_ptr<dirent*, std::function<void(dirent**)>> direntPtr(nameList,
            [fileAmount](dirent** dirs) {
                for (int i = 0; i < fileAmount; i++) {
                    free(dirs[i]);
                }
                free(dirs);
            });
    for (int i = 0; i < fileAmount; i++) {
        openPlugin(m_dir + nameList[i]->d_name);
    }
}

void PluginManager::openPlugin(const std::string &path) {
    void *handle = dlopen(path.c_str(), RTLD_LAZY);

    if (!handle) {
        LOGW("File could not be dlopened <%s> : <%s>", path.c_str(), dlerror());
        return;
    }
    PluginLibPtr handlePtr(handle, std::ptr_fun(dlclose));

    //Flush any previous errors
    dlerror();
    create_t creator = reinterpret_cast<create_t>(dlsym(handle, "create"));

    char *error;
    if ((error = dlerror()) != NULL) {
        LOGE("Couldn't resolve symbol <create> from lib <%s> : <%s>", path.c_str(), error);
        return;
    }

    destroy_t destroyer = reinterpret_cast<destroy_t>(dlsym(handle, "destroy"));
    if ((error = dlerror()) != NULL) {
        LOGE("Couldn't resolve symbol <destroy> from lib <%s> : <%s>", path.c_str(), error);
        return;
    }

    ExternalPluginPtr pluginPtr(creator(), destroyer);

    if (!pluginPtr) {
        LOGE("Couldn't create plugin for <%s>", path.c_str());
        return;
    }

    auto policies = pluginPtr->getSupportedPolicyDescr();
    if (policies.empty()) {
        LOGE("Plugin <%s> does not support any type!", path.c_str());
        return;
    }
    for (auto &desc : policies) {
        if (!m_plugins.insert(std::make_pair(desc, pluginPtr)).second) {
            LOGW("policy type: [%" PRIu16 "] name: <%s> was already supported.",
                 desc.type, desc.name.c_str());
        }
    }

    m_pluginLibs.push_back(std::move(handlePtr));
}

} // namespace Cynara

<commit_msg>Add debug info in plugins loading mechanism<commit_after>/*
 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
/**
 * @file        src/service/plugin/PluginManager.cpp
 * @author      Zofia Abramowska <z.abramowska@samsung.com>
 * @version     1.0
 * @brief       Definition of PluginManager class
 */

#define _BSD_SOURCE_

#include <cinttypes>
#include <cstdlib>
#include <dirent.h>
#include <dlfcn.h>
#include <functional>

#include <log/log.h>

#include "PluginManager.h"

namespace {
    int pluginFilter(const struct dirent *ent) {
#ifdef _DIRENT_HAVE_D_TYPE
        if (ent->d_type != DT_REG) {
            return 0;
        }
#endif
        if (ent->d_name[0] == '.') {
            return 0;
        }
        return 1;
    }
}

namespace Cynara {

PluginManager::PluginManager(const std::string &pluginDir) : m_dir(pluginDir) {
    loadPlugins();
}

PluginManager::~PluginManager(void) {
    // We have to be sure, that external objects will be destroyed
    // before handles to libraries are closed.
    for (auto &plugin : m_plugins) {
        plugin.second.reset();
    }
}

ExternalPluginPtr PluginManager::getPlugin(PolicyType pType) {
    return m_plugins[pType];
}

std::vector<PolicyDescription> PluginManager::getPolicyDescriptions(void) const {
    std::vector<PolicyDescription> descriptions;
    descriptions.reserve(m_plugins.size());
    for (auto &plugin : m_plugins) {
        descriptions.push_back(plugin.first);
    }
    return descriptions;
}

void PluginManager::invalidateAll(void) {
    for (auto &plugin : m_plugins) {
        plugin.second->invalidate();
    }
}

void PluginManager::loadPlugins(void) {
    struct dirent **nameList = NULL;
    int fileAmount = scandir(m_dir.c_str(), &nameList, pluginFilter, alphasort);

    if (fileAmount < 0) {
        auto error = strerror(errno);
        LOGE("Couldn't scan for plugins in <%s> : <%s>", m_dir.c_str(), error);
        return;
    }

    std::unique_ptr<dirent*, std::function<void(dirent**)>> direntPtr(nameList,
            [fileAmount](dirent** dirs) {
                for (int i = 0; i < fileAmount; i++) {
                    free(dirs[i]);
                }
                free(dirs);
            });
    for (int i = 0; i < fileAmount; i++) {
        openPlugin(m_dir + nameList[i]->d_name);
    }
}

void PluginManager::openPlugin(const std::string &path) {
    LOGD("Loading plugin: <%s>", path.c_str());

    void *handle = dlopen(path.c_str(), RTLD_LAZY);

    if (!handle) {
        LOGW("File could not be dlopened <%s> : <%s>", path.c_str(), dlerror());
        return;
    }
    PluginLibPtr handlePtr(handle, std::ptr_fun(dlclose));

    //Flush any previous errors
    dlerror();
    create_t creator = reinterpret_cast<create_t>(dlsym(handle, "create"));

    char *error;
    if ((error = dlerror()) != NULL) {
        LOGE("Couldn't resolve symbol <create> from lib <%s> : <%s>", path.c_str(), error);
        return;
    }

    destroy_t destroyer = reinterpret_cast<destroy_t>(dlsym(handle, "destroy"));
    if ((error = dlerror()) != NULL) {
        LOGE("Couldn't resolve symbol <destroy> from lib <%s> : <%s>", path.c_str(), error);
        return;
    }

    ExternalPluginPtr pluginPtr(creator(), destroyer);

    if (!pluginPtr) {
        LOGE("Couldn't create plugin for <%s>", path.c_str());
        return;
    }

    auto policies = pluginPtr->getSupportedPolicyDescr();
    if (policies.empty()) {
        LOGE("Plugin <%s> does not support any type!", path.c_str());
        return;
    }
    for (auto &desc : policies) {
        if (!m_plugins.insert(std::make_pair(desc, pluginPtr)).second) {
            LOGW("Policy: type [%" PRIu16 "] name <%s> was already supported.",
                 desc.type, desc.name.c_str());
        } else {
            LOGD("Supported policy: type [%" PRIu16 "] name <%s>", desc.type, desc.name.c_str());
        }
    }

    m_pluginLibs.push_back(std::move(handlePtr));
}

} // namespace Cynara

<|endoftext|>


<commit_before>/**
 * @file binop.cpp
 * @brief  Binary operations are handled in this file, along with the appropriate coercions.
 *
 */

#include "angort.h"
#include "hash.h"
#include "opcodes.h"

namespace angort {

/// append to a list. If the element to add is itself a list,
/// split it apart and and the items individually.

static void addListOrValueToList(ArrayList<Value> *list,Value *a){
    if(a->getType() == Types::tList){
        ArrayListIterator<Value> iter(Types::tList->get(a));

        for(iter.first();!iter.isDone();iter.next()){
            list->append()->copy(iter.current());
        }
    } else
        list->append()->copy(a);
}

static void addHashToHash(Hash *h,Hash *h2){
    HashKeyIterator iter(h2);
    for(iter.first();!iter.isDone();iter.next()){
        Value *k = iter.current();
        Value *v;
        if(h2->find(k))
            v = h2->getval();
        else
            throw WTF;

        h->set(k,v);
    }
}

/**
 * Take a pair of values a,b and perform the binary operation given.
 * The result should be pushed onto the stack. The instruction pointer
 * is incremented by the caller.
 */

void Angort::binop(Value *a,Value *b,int opcode){

    const Type *at = a->getType();
    const Type *bt = b->getType();

    // first look to see if it's a registered binop. If
    // so, run it. Otherwise fall through to a set of if
    // statements.

    if(at->binop(this,opcode,a,b))
        return;

    if(at == Types::tNone ||  bt == Types::tNone){
        /**
         *
         * One of the values is NONE
         *
         */
        switch(opcode){
        case OP_EQUALS: // none is equal to nothing
            pushInt(0);break;
        case OP_NEQUALS:// and not equal to everything
            pushInt(1);break;
        default:
            throw RUNT(EX_TYPE,"invalid operation with a 'none' operand");
        }
    }else if(at == Types::tList || bt == Types::tList) {
        // collection equality checks look for identity
        ListObject *lo;
        switch(opcode){
        case OP_EQUALS:
            pushInt(a->v.list == b->v.list);break;
        case OP_NEQUALS:
            pushInt(a->v.list != b->v.list);break;
        case OP_ADD:
            lo = new ListObject();
            addListOrValueToList(&lo->list,a);
            addListOrValueToList(&lo->list,b);
            Types::tList->set(pushval(),lo);
            break;
        default:
            throw RUNT(EX_TYPE,"invalid operation with a list operand");
        }
    }else if(at == Types::tHash || bt == Types::tHash) {
        HashObject *ho;
        switch(opcode){
        case OP_EQUALS:
            pushInt(a->v.hash == b->v.hash);break;
        case OP_NEQUALS:
            pushInt(a->v.hash != b->v.hash);break;
        case OP_ADD:
            ho = new HashObject();
            addHashToHash(ho->hash,a->v.hash->hash);
            addHashToHash(ho->hash,b->v.hash->hash);
            Types::tHash->set(pushval(),ho);
            break;
        default:
            throw RUNT(EX_TYPE,"invalid operation with a list operand");
        }
    } else if((at == Types::tString || at == Types::tSymbol) &&
              bt == Types::tInteger &&
              opcode == OP_MUL){
        /**
         * Special case for multiplying a string/symbol by a number
         */
        const StringBuffer& p = a->toString();

        int reps = b->toInt();
        int len = strlen(p.get());
        Value t; // temp value
        // allocate a new result
        char *q = Types::tString->allocate(&t,len*reps+1,Types::tString);
        for(int i=0;i<reps;i++){
            memcpy(q+i*len,p.get(),len);
        }
        q[len*reps]=0;
        stack.pushptr()->copy(&t);
    } else if(at == Types::tString || bt == Types::tString){
        /**
         *
         * One of the value is a string; coerce the other to a string and then
         * perform a string operation.
         *
         */
        const StringBuffer& p = a->toString();
        const StringBuffer& q = b->toString();
        switch(opcode){
        case OP_ADD:{
            Value t; // we use a temp, otherwise allocate() will clear the type
            int len = strlen(p.get())+strlen(q.get());
            char *r = Types::tString->allocate(&t,len+1,Types::tString);
            strcpy(r,p.get());
            strcat(r,q.get());
            stack.pushptr()->copy(&t);
            break;
        }
        case OP_EQUALS:
            pushInt(!strcmp(p.get(),q.get()));
            break;
        case OP_NEQUALS:
            pushInt(strcmp(p.get(),q.get()));
            break;
        case OP_GT:
            pushInt(strcmp(p.get(),q.get())>0);
            break;
        case OP_LT:
            pushInt(strcmp(p.get(),q.get())<0);
            break;
        case OP_GE:
            pushInt(strcmp(p.get(),q.get())>=0);
            break;
        case OP_LE:
            pushInt(strcmp(p.get(),q.get())<=0);
            break;
        case OP_CMP:
            pushInt(strcmp(p.get(),q.get()));
            break;
        default:throw RUNT(EX_TYPE,"bad operation for strings");
        }
    }else if(at == Types::tDouble || bt == Types::tDouble){
        /**
         * One of the values is a doublet; coerce the other to a double and perform
         * a float operation
         */
        double r;
        double p = a->toDouble();
        double q = b->toDouble();
        bool cmp=false;
        switch(opcode){
        case OP_ADD:
            r = p+q;break;
        case OP_SUB:
            r = p-q;break;
        case OP_DIV:
            if(q==0.0f)throw DivZeroException();
            r = p/q;break;
        case OP_MUL:
            r = p*q;break;
            // "comparisons" go down here - things which
            // produce integer results even though one operand
            // is float.
        case OP_EQUALS:
            cmp=true;
            pushInt(p==q);break;
        case OP_NEQUALS:
            cmp=true;
            pushInt(p!=q);break;
        case OP_AND:
            cmp=true;
            pushInt(p&&q);break;
        case OP_OR:
            cmp=true;
            pushInt(p&&q);break;
        case OP_GT:
            cmp=true;
            pushInt(p>q);break;
        case OP_LT:
            cmp=true;
            pushInt(p<q);break;
        case OP_GE:
            cmp=true;
            pushInt(p>=q);break;
        case OP_LE:
            cmp=true;
            pushInt(p<=q);break;
        case OP_CMP:
            cmp=true;
            pushInt(((p-q)>0)?1:(((p-q)<0)?-1:0));
            break;
        default:
            throw RUNT(EX_TYPE,"invalid operator for floats");
        }
        if(!cmp)
            pushDouble(r);
    }else if(at == Types::tFloat || bt == Types::tFloat){
        /**
         * One of the values is a float; coerce the other to a float and perform
         * a float operation
         */
        float r;
        float p = a->toFloat();
        float q = b->toFloat();
        bool cmp=false;
        switch(opcode){
        case OP_ADD:
            r = p+q;break;
        case OP_SUB:
            r = p-q;break;
        case OP_DIV:
            if(q==0.0f)throw DivZeroException();
            r = p/q;break;
        case OP_MUL:
            r = p*q;break;
            // "comparisons" go down here - things which
            // produce integer results even though one operand
            // is float.
        case OP_EQUALS:
            cmp=true;
            pushInt(p==q);break;
        case OP_NEQUALS:
            cmp=true;
            pushInt(p!=q);break;
        case OP_AND:
            cmp=true;
            pushInt(p&&q);break;
        case OP_OR:
            cmp=true;
            pushInt(p&&q);break;
        case OP_GT:
            cmp=true;
            pushInt(p>q);break;
        case OP_LT:
            cmp=true;
            pushInt(p<q);break;
        case OP_GE:
            cmp=true;
            pushInt(p>=q);break;
        case OP_LE:
            cmp=true;
            pushInt(p<=q);break;
        case OP_CMP:
            cmp=true;
            pushInt(((p-q)>0)?1:(((p-q)<0)?-1:0));
            break;
        default:
            throw RUNT(EX_TYPE,"invalid operator for floats");
        }
        if(!cmp)
            pushFloat(r);
    }else if(at == Types::tSymbol && bt == Types::tSymbol){
        /*
         * Both are symbols
         */
        switch(opcode){
        case OP_EQUALS:
            pushInt((a->v.i == b->v.i)?1:0);break;
        case OP_NEQUALS:
            pushInt((a->v.i != b->v.i)?1:0);break;
        case OP_GT:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())>0);
            break;
        }
        case OP_LT:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())<0);
            break;
        }
        case OP_GE:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())>=0);
            break;
        }
        case OP_LE:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())<=0);
            break;
        }
        case OP_CMP:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get()));
            break;
        }
        default:
            throw RUNT(EX_TYPE,"bad operation for symbols");
        }
    }else if(at == Types::tSymbol || bt == Types::tSymbol){
        /*
         * One of the values is a symbol; tests are done as with
         * strings
         */
        switch(opcode){
        case OP_EQUALS:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())==0);
            break;}
        case OP_NEQUALS:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())!=0);
            break;}
        case OP_GT:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())>0);
            break;
        }
        case OP_LT:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())<0);
            break;
        }
        case OP_GE:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())>=0);
            break;
        }
        case OP_LE:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())<=0);
            break;
        }
        case OP_CMP:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get()));
            break;
        }
        default:
            throw RUNT(EX_TYPE,"bad operation for symbols");
        }
    }else if(at == Types::tLong || bt == Types::tLong){
        /**
         * One is a long, these are similar to int ops
         */

        long p,q,r;
        switch(opcode){
        case OP_MOD:
            p = a->toLong();
            q = b->toLong();
            r = p%q;break;
        case OP_ADD:
            p = a->toLong();
            q = b->toLong();
            r = p+q;break;
        case OP_SUB:
            p = a->toLong();
            q = b->toLong();
            r = p-q;break;
        case OP_DIV:
            p = a->toLong();
            q = b->toLong();
            if(!q)throw DivZeroException();
            r = p/q;break;
        case OP_MUL:
            p = a->toLong();
            q = b->toLong();
            r = p*q;break;
        case OP_AND:
            p = a->toLong();
            q = b->toLong();
            r = (p&&q);break;
        case OP_OR:
            p = a->toLong();
            q = b->toLong();
            r = (p||q);break;
        case OP_GT:
            p = a->toLong();
            q = b->toLong();
            r = (p>q);break;
        case OP_LT:
            p = a->toLong();
            q = b->toLong();
            r = (p<q);break;
        case OP_GE:
            p = a->toLong();
            q = b->toLong();
            r = (p>=q);break;
        case OP_LE:
            p = a->toLong();
            q = b->toLong();
            r = (p<=q);break;
        case OP_CMP:
            p = a->toLong();
            q = b->toLong();
            r = ((p-q)>0)?1:(((p-q)<0)?-1:0);
            break;
        case OP_EQUALS:
            r = a->toLong() == b->toLong();
            break;
        case OP_NEQUALS:
            r = a->toLong() != b->toLong();
            break;
        default:
            throw WTF;

        }
        Types::tLong->set(pushval(),r);
    } else {
        /**
         * Otherwise assume we're dealing with ints
         */
        int p,q,r;
        switch(opcode){
        case OP_MOD:
            p = a->toInt();
            q = b->toInt();
            r = p%q;break;
        case OP_ADD:
            p = a->toInt();
            q = b->toInt();
            r = p+q;break;
        case OP_SUB:
            p = a->toInt();
            q = b->toInt();
            r = p-q;break;
        case OP_DIV:
            p = a->toInt();
            q = b->toInt();
            if(!q)throw DivZeroException();
            r = p/q;break;
        case OP_MUL:
            p = a->toInt();
            q = b->toInt();
            r = p*q;break;
        case OP_AND:
            p = a->toInt();
            q = b->toInt();
            r = (p&&q);break;
        case OP_OR:
            p = a->toInt();
            q = b->toInt();
            r = (p||q);break;
        case OP_GT:
            p = a->toInt();
            q = b->toInt();
            r = (p>q);break;
        case OP_LT:
            p = a->toInt();
            q = b->toInt();
            r = (p<q);break;
        case OP_GE:
            p = a->toInt();
            q = b->toInt();
            r = (p>=q);break;
        case OP_LE:
            p = a->toInt();
            q = b->toInt();
            r = (p<=q);break;
        case OP_CMP:
            p = a->toInt();
            q = b->toInt();
            r = ((p-q)>0)?1:(((p-q)<0)?-1:0);
            break;
        case OP_EQUALS:
            if(at == Types::tInteger || bt == Types::tInteger)
                r = a->toInt() == b->toInt();
            else
                r = (a->v.s == b->v.s);
            break;
        case OP_NEQUALS:
            if(at == Types::tInteger || bt == Types::tInteger)
                r = a->toInt() != b->toInt();
            else
                r = (a->v.s != b->v.s);
            break;
        default:
            throw WTF;

        }
        pushInt(r);
    }

}
}
<commit_msg>bug: [%] [] + would crash.<commit_after>/**
 * @file binop.cpp
 * @brief  Binary operations are handled in this file, along with the appropriate coercions.
 *
 */

#include "angort.h"
#include "hash.h"
#include "opcodes.h"

namespace angort {

/// append to a list. If the element to add is itself a list,
/// split it apart and and the items individually.

static void addListOrValueToList(ArrayList<Value> *list,Value *a){
    if(a->getType() == Types::tList){
        ArrayListIterator<Value> iter(Types::tList->get(a));

        for(iter.first();!iter.isDone();iter.next()){
            list->append()->copy(iter.current());
        }
    } else
        list->append()->copy(a);
}

static void addHashToHash(Hash *h,Hash *h2){
    HashKeyIterator iter(h2);
    for(iter.first();!iter.isDone();iter.next()){
        Value *k = iter.current();
        Value *v;
        if(h2->find(k))
            v = h2->getval();
        else
            throw WTF;

        h->set(k,v);
    }
}

/**
 * Take a pair of values a,b and perform the binary operation given.
 * The result should be pushed onto the stack. The instruction pointer
 * is incremented by the caller.
 */

void Angort::binop(Value *a,Value *b,int opcode){

    const Type *at = a->getType();
    const Type *bt = b->getType();

    // first look to see if it's a registered binop. If
    // so, run it. Otherwise fall through to a set of if
    // statements.

    if(at->binop(this,opcode,a,b))
        return;

    if(at == Types::tNone ||  bt == Types::tNone){
        /**
         *
         * One of the values is NONE
         *
         */
        switch(opcode){
        case OP_EQUALS: // none is equal to nothing
            pushInt(0);break;
        case OP_NEQUALS:// and not equal to everything
            pushInt(1);break;
        default:
            throw RUNT(EX_TYPE,"invalid operation with a 'none' operand");
        }
    }else if(at == Types::tList && bt == Types::tList) {
        // collection equality checks look for identity
        ListObject *lo;
        switch(opcode){
        case OP_EQUALS:
            pushInt(a->v.list == b->v.list);break;
        case OP_NEQUALS:
            pushInt(a->v.list != b->v.list);break;
        case OP_ADD:
            lo = new ListObject();
            addListOrValueToList(&lo->list,a);
            addListOrValueToList(&lo->list,b);
            Types::tList->set(pushval(),lo);
            break;
        default:
            throw RUNT(EX_TYPE,"invalid operation with a list operand");
        }
    }else if(at == Types::tHash && bt == Types::tHash) {
        HashObject *ho;
        switch(opcode){
        case OP_EQUALS:
            pushInt(a->v.hash == b->v.hash);break;
        case OP_NEQUALS:
            pushInt(a->v.hash != b->v.hash);break;
        case OP_ADD:
            ho = new HashObject();
            addHashToHash(ho->hash,a->v.hash->hash);
            addHashToHash(ho->hash,b->v.hash->hash);
            Types::tHash->set(pushval(),ho);
            break;
        default:
            throw RUNT(EX_TYPE,"invalid operation with a list operand");
        }
    } else if((at == Types::tString || at == Types::tSymbol) &&
              bt == Types::tInteger &&
              opcode == OP_MUL){
        /**
         * Special case for multiplying a string/symbol by a number
         */
        const StringBuffer& p = a->toString();

        int reps = b->toInt();
        int len = strlen(p.get());
        Value t; // temp value
        // allocate a new result
        char *q = Types::tString->allocate(&t,len*reps+1,Types::tString);
        for(int i=0;i<reps;i++){
            memcpy(q+i*len,p.get(),len);
        }
        q[len*reps]=0;
        stack.pushptr()->copy(&t);
    } else if(at == Types::tString || bt == Types::tString){
        /**
         *
         * One of the value is a string; coerce the other to a string and then
         * perform a string operation.
         *
         */
        const StringBuffer& p = a->toString();
        const StringBuffer& q = b->toString();
        switch(opcode){
        case OP_ADD:{
            Value t; // we use a temp, otherwise allocate() will clear the type
            int len = strlen(p.get())+strlen(q.get());
            char *r = Types::tString->allocate(&t,len+1,Types::tString);
            strcpy(r,p.get());
            strcat(r,q.get());
            stack.pushptr()->copy(&t);
            break;
        }
        case OP_EQUALS:
            pushInt(!strcmp(p.get(),q.get()));
            break;
        case OP_NEQUALS:
            pushInt(strcmp(p.get(),q.get()));
            break;
        case OP_GT:
            pushInt(strcmp(p.get(),q.get())>0);
            break;
        case OP_LT:
            pushInt(strcmp(p.get(),q.get())<0);
            break;
        case OP_GE:
            pushInt(strcmp(p.get(),q.get())>=0);
            break;
        case OP_LE:
            pushInt(strcmp(p.get(),q.get())<=0);
            break;
        case OP_CMP:
            pushInt(strcmp(p.get(),q.get()));
            break;
        default:throw RUNT(EX_TYPE,"bad operation for strings");
        }
    }else if(at == Types::tDouble || bt == Types::tDouble){
        /**
         * One of the values is a doublet; coerce the other to a double and perform
         * a float operation
         */
        double r;
        double p = a->toDouble();
        double q = b->toDouble();
        bool cmp=false;
        switch(opcode){
        case OP_ADD:
            r = p+q;break;
        case OP_SUB:
            r = p-q;break;
        case OP_DIV:
            if(q==0.0f)throw DivZeroException();
            r = p/q;break;
        case OP_MUL:
            r = p*q;break;
            // "comparisons" go down here - things which
            // produce integer results even though one operand
            // is float.
        case OP_EQUALS:
            cmp=true;
            pushInt(p==q);break;
        case OP_NEQUALS:
            cmp=true;
            pushInt(p!=q);break;
        case OP_AND:
            cmp=true;
            pushInt(p&&q);break;
        case OP_OR:
            cmp=true;
            pushInt(p&&q);break;
        case OP_GT:
            cmp=true;
            pushInt(p>q);break;
        case OP_LT:
            cmp=true;
            pushInt(p<q);break;
        case OP_GE:
            cmp=true;
            pushInt(p>=q);break;
        case OP_LE:
            cmp=true;
            pushInt(p<=q);break;
        case OP_CMP:
            cmp=true;
            pushInt(((p-q)>0)?1:(((p-q)<0)?-1:0));
            break;
        default:
            throw RUNT(EX_TYPE,"invalid operator for floats");
        }
        if(!cmp)
            pushDouble(r);
    }else if(at == Types::tFloat || bt == Types::tFloat){
        /**
         * One of the values is a float; coerce the other to a float and perform
         * a float operation
         */
        float r;
        float p = a->toFloat();
        float q = b->toFloat();
        bool cmp=false;
        switch(opcode){
        case OP_ADD:
            r = p+q;break;
        case OP_SUB:
            r = p-q;break;
        case OP_DIV:
            if(q==0.0f)throw DivZeroException();
            r = p/q;break;
        case OP_MUL:
            r = p*q;break;
            // "comparisons" go down here - things which
            // produce integer results even though one operand
            // is float.
        case OP_EQUALS:
            cmp=true;
            pushInt(p==q);break;
        case OP_NEQUALS:
            cmp=true;
            pushInt(p!=q);break;
        case OP_AND:
            cmp=true;
            pushInt(p&&q);break;
        case OP_OR:
            cmp=true;
            pushInt(p&&q);break;
        case OP_GT:
            cmp=true;
            pushInt(p>q);break;
        case OP_LT:
            cmp=true;
            pushInt(p<q);break;
        case OP_GE:
            cmp=true;
            pushInt(p>=q);break;
        case OP_LE:
            cmp=true;
            pushInt(p<=q);break;
        case OP_CMP:
            cmp=true;
            pushInt(((p-q)>0)?1:(((p-q)<0)?-1:0));
            break;
        default:
            throw RUNT(EX_TYPE,"invalid operator for floats");
        }
        if(!cmp)
            pushFloat(r);
    }else if(at == Types::tSymbol && bt == Types::tSymbol){
        /*
         * Both are symbols
         */
        switch(opcode){
        case OP_EQUALS:
            pushInt((a->v.i == b->v.i)?1:0);break;
        case OP_NEQUALS:
            pushInt((a->v.i != b->v.i)?1:0);break;
        case OP_GT:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())>0);
            break;
        }
        case OP_LT:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())<0);
            break;
        }
        case OP_GE:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())>=0);
            break;
        }
        case OP_LE:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())<=0);
            break;
        }
        case OP_CMP:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get()));
            break;
        }
        default:
            throw RUNT(EX_TYPE,"bad operation for symbols");
        }
    }else if(at == Types::tSymbol || bt == Types::tSymbol){
        /*
         * One of the values is a symbol; tests are done as with
         * strings
         */
        switch(opcode){
        case OP_EQUALS:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())==0);
            break;}
        case OP_NEQUALS:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())!=0);
            break;}
        case OP_GT:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())>0);
            break;
        }
        case OP_LT:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())<0);
            break;
        }
        case OP_GE:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())>=0);
            break;
        }
        case OP_LE:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get())<=0);
            break;
        }
        case OP_CMP:{
            const StringBuffer& p = a->toString();
            const StringBuffer& q = b->toString();
            pushInt(strcmp(p.get(),q.get()));
            break;
        }
        default:
            throw RUNT(EX_TYPE,"bad operation for symbols");
        }
    }else if(at == Types::tLong || bt == Types::tLong){
        /**
         * One is a long, these are similar to int ops
         */

        long p,q,r;
        switch(opcode){
        case OP_MOD:
            p = a->toLong();
            q = b->toLong();
            r = p%q;break;
        case OP_ADD:
            p = a->toLong();
            q = b->toLong();
            r = p+q;break;
        case OP_SUB:
            p = a->toLong();
            q = b->toLong();
            r = p-q;break;
        case OP_DIV:
            p = a->toLong();
            q = b->toLong();
            if(!q)throw DivZeroException();
            r = p/q;break;
        case OP_MUL:
            p = a->toLong();
            q = b->toLong();
            r = p*q;break;
        case OP_AND:
            p = a->toLong();
            q = b->toLong();
            r = (p&&q);break;
        case OP_OR:
            p = a->toLong();
            q = b->toLong();
            r = (p||q);break;
        case OP_GT:
            p = a->toLong();
            q = b->toLong();
            r = (p>q);break;
        case OP_LT:
            p = a->toLong();
            q = b->toLong();
            r = (p<q);break;
        case OP_GE:
            p = a->toLong();
            q = b->toLong();
            r = (p>=q);break;
        case OP_LE:
            p = a->toLong();
            q = b->toLong();
            r = (p<=q);break;
        case OP_CMP:
            p = a->toLong();
            q = b->toLong();
            r = ((p-q)>0)?1:(((p-q)<0)?-1:0);
            break;
        case OP_EQUALS:
            r = a->toLong() == b->toLong();
            break;
        case OP_NEQUALS:
            r = a->toLong() != b->toLong();
            break;
        default:
            throw WTF;

        }
        Types::tLong->set(pushval(),r);
    } else {
        /**
         * Otherwise assume we're dealing with ints
         */
        int p,q,r;
        switch(opcode){
        case OP_MOD:
            p = a->toInt();
            q = b->toInt();
            r = p%q;break;
        case OP_ADD:
            p = a->toInt();
            q = b->toInt();
            r = p+q;break;
        case OP_SUB:
            p = a->toInt();
            q = b->toInt();
            r = p-q;break;
        case OP_DIV:
            p = a->toInt();
            q = b->toInt();
            if(!q)throw DivZeroException();
            r = p/q;break;
        case OP_MUL:
            p = a->toInt();
            q = b->toInt();
            r = p*q;break;
        case OP_AND:
            p = a->toInt();
            q = b->toInt();
            r = (p&&q);break;
        case OP_OR:
            p = a->toInt();
            q = b->toInt();
            r = (p||q);break;
        case OP_GT:
            p = a->toInt();
            q = b->toInt();
            r = (p>q);break;
        case OP_LT:
            p = a->toInt();
            q = b->toInt();
            r = (p<q);break;
        case OP_GE:
            p = a->toInt();
            q = b->toInt();
            r = (p>=q);break;
        case OP_LE:
            p = a->toInt();
            q = b->toInt();
            r = (p<=q);break;
        case OP_CMP:
            p = a->toInt();
            q = b->toInt();
            r = ((p-q)>0)?1:(((p-q)<0)?-1:0);
            break;
        case OP_EQUALS:
            if(at == Types::tInteger || bt == Types::tInteger)
                r = a->toInt() == b->toInt();
            else
                r = (a->v.s == b->v.s);
            break;
        case OP_NEQUALS:
            if(at == Types::tInteger || bt == Types::tInteger)
                r = a->toInt() != b->toInt();
            else
                r = (a->v.s != b->v.s);
            break;
        default:
            throw WTF;

        }
        pushInt(r);
    }

}
}
<|endoftext|>


<commit_before>/*
 * nt loader
 *
 * Copyright 2006-2008 Mike McCormack
 *
 * 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.1 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <assert.h>

#include <sys/wait.h>
#include <sched.h>

#include <sys/ptrace.h>
#ifdef HAVE_ASM_PTRACE_H
#include <asm/ptrace.h>
#endif

#include "windef.h"
#include "winnt.h"
#include "mem.h"
#include "thread.h"

#include "ptrace_if.h"
#include "debug.h"
#include "platform.h"

#include "client.h"
#include "ptrace_base.h"

const char stub_name[] = "ring3k-client";
char stub_path[MAX_PATH];

class tt_address_space_impl: public PTRACE_ADRESS_SPACE_IMPL
{
	long stub_regs[FRAME_SIZE];
	pid_t child_pid;
protected:
	int userside_req( int type );
public:
	tt_address_space_impl();
	virtual pid_t GetChildPid();
	virtual ~tt_address_space_impl();
	virtual int Mmap( BYTE *address, size_t length, int prot, int flags, int file, off_t offset );
	virtual int Munmap( BYTE *address, size_t length );
	virtual unsigned short GetUserspaceFs();
};

pid_t tt_address_space_impl::GetChildPid()
{
	return child_pid;
}

tt_address_space_impl::tt_address_space_impl()
{
	int r;
	pid_t pid;

	pid = fork();
	if (pid == -1)
		Die("fork() failed %d\n", errno);

	if (pid == 0)
	{
		::ptrace( PTRACE_TRACEME, 0, 0, 0 );
		r = ::execl( stub_path, stub_name, NULL );
		// the next line should not be reached
		Die("exec failed (%d) - %s missing?\n", r, stub_path);
	}

	// trace through exec after traceme
	WaitForSignal( pid, SIGTRAP );
	r = ::ptrace( PTRACE_CONT, pid, 0, 0 );
	if (r < 0)
		Die("PTRACE_CONT failed (%d)\n", errno);

	// client should hit a breakpoint
	WaitForSignal( pid, SIGTRAP );
	r = PtraceGetRegs( pid, stub_regs );
	if (r < 0)
		Die("constructor: ptrace_get_regs failed (%d)\n", errno);

	child_pid = pid;
}

tt_address_space_impl::~tt_address_space_impl()
{
	assert( SigTarget == 0 );
	//trace(stderr,"~tt_address_space_impl()\n");
	Destroy();
	ptrace( PTRACE_KILL, child_pid, 0, 0 );
	assert( child_pid != -1 );
	kill( child_pid, SIGTERM );
	child_pid = -1;
}

ADDRESS_SPACE_IMPL* create_tt_address_space()
{
	//trace("create_tt_address_space\n");
	// Set up the signal handler and unmask it first.
	// The child's signal handler will be unmasked too.
	return new tt_address_space_impl();
}

int tt_address_space_impl::userside_req( int type )
{
	struct tt_req *ureq = (struct tt_req *) stub_regs[EBX];
	int r;

	ptrace( PTRACE_POKEDATA, child_pid, &ureq->type, type );

	r = PtraceSetRegs( child_pid, stub_regs );
	if (r < 0)
		Die("ptrace_set_regs failed\n");
	r = ::ptrace( PTRACE_CONT, child_pid, 0, 0 );
	if (r < 0)
		Die("ptrace( PTRACE_CONT ) failed\n");

	WaitForSignal( child_pid, SIGTRAP );
	r = PtraceGetRegs( child_pid, stub_regs );
	if (r < 0)
		Die("ptrace_get_regs failed (%d)\n", errno);

	return stub_regs[EAX];
}

int tt_address_space_impl::Mmap( BYTE *address, size_t length, int prot, int flags, int file, off_t offset )
{
	//trace("tt_address_space_impl::mmap()\n");

	// send our pid to the stub
	struct tt_req *ureq = (struct tt_req *) stub_regs[EBX];
	ptrace( PTRACE_POKEDATA, child_pid, &ureq->u.map.pid, getpid() );
	ptrace( PTRACE_POKEDATA, child_pid, &ureq->u.map.fd, file );
	ptrace( PTRACE_POKEDATA, child_pid, &ureq->u.map.addr, (int) address );
	ptrace( PTRACE_POKEDATA, child_pid, &ureq->u.map.len, length );
	ptrace( PTRACE_POKEDATA, child_pid, &ureq->u.map.ofs, offset );
	ptrace( PTRACE_POKEDATA, child_pid, &ureq->u.map.prot, prot );
	return userside_req( tt_req_map );
}

int tt_address_space_impl::Munmap( BYTE *address, size_t length )
{
	//trace("tt_address_space_impl::munmap()\n");
	struct tt_req *ureq = (struct tt_req *) stub_regs[EBX];
	ptrace( PTRACE_POKEDATA, child_pid, &ureq->u.map.addr, (int) address );
	ptrace( PTRACE_POKEDATA, child_pid, &ureq->u.map.len, length );
	return userside_req( tt_req_umap );
}

unsigned short tt_address_space_impl::GetUserspaceFs()
{
	return stub_regs[FS];
}

void get_stub_path( const char *kernel_path )
{
	// FIXME: handle loader in path too
	const char *p = strrchr( kernel_path, '/' );
	int len;
	if (p)
	{
		len = p - kernel_path + 1;
	}
	else
	{
		static const char current_dir[] = "./";
		p = current_dir;
		len = sizeof current_dir - 1;
	}

	memcpy( stub_path, kernel_path, len );
	stub_path[len] = 0;
	if ((len + sizeof stub_name) > sizeof stub_path)
		Die("path too long\n");
	strcat( stub_path, stub_name );
}

// quick check that /proc is mounted
void check_proc()
{
	int fd = open("/proc/self/fd/0", O_RDONLY);
	if (fd < 0)
		Die("/proc not mounted\n");
	close( fd );
}

bool InitTt( const char *kernel_path )
{
	get_stub_path( kernel_path );
	check_proc();
	trace("using thread tracing, kernel %s, client %s\n", kernel_path, stub_path );
	PTRACE_ADRESS_SPACE_IMPL::SetSignals();
	pCreateAddressSpace = &create_tt_address_space;
	return true;
}
<commit_msg>Code refactoring: tt<commit_after>/*
 * nt loader
 *
 * Copyright 2006-2008 Mike McCormack
 *
 * 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.1 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"

#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <assert.h>

#include <sys/wait.h>
#include <sched.h>

#include <sys/ptrace.h>
#ifdef HAVE_ASM_PTRACE_H
#include <asm/ptrace.h>
#endif

#include "windef.h"
#include "winnt.h"
#include "mem.h"
#include "thread.h"

#include "ptrace_if.h"
#include "debug.h"
#include "platform.h"

#include "client.h"
#include "ptrace_base.h"

const char StubName[] = "ring3k-client";
char StubPath[MAX_PATH];

class TT_ADDRESS_SPACE_IMPL: public PTRACE_ADRESS_SPACE_IMPL
{
	long StubRegs[FRAME_SIZE];
	pid_t ChildPid;
protected:
	int UsersideReq( int type );
public:
	TT_ADDRESS_SPACE_IMPL();
	virtual pid_t GetChildPid();
	virtual ~TT_ADDRESS_SPACE_IMPL();
	virtual int Mmap( BYTE *address, size_t length, int prot, int flags, int file, off_t offset );
	virtual int Munmap( BYTE *address, size_t length );
	virtual unsigned short GetUserspaceFs();
};

pid_t TT_ADDRESS_SPACE_IMPL::GetChildPid()
{
	return ChildPid;
}

TT_ADDRESS_SPACE_IMPL::TT_ADDRESS_SPACE_IMPL()
{
	int r;
	pid_t pid;

	pid = fork();
	if (pid == -1)
		Die("fork() failed %d\n", errno);

	if (pid == 0)
	{
		::ptrace( PTRACE_TRACEME, 0, 0, 0 );
		r = ::execl( StubPath, StubName, NULL );
		// the next line should not be reached
		Die("exec failed (%d) - %s missing?\n", r, StubPath);
	}

	// trace through exec after traceme
	WaitForSignal( pid, SIGTRAP );
	r = ::ptrace( PTRACE_CONT, pid, 0, 0 );
	if (r < 0)
		Die("PTRACE_CONT failed (%d)\n", errno);

	// client should hit a breakpoint
	WaitForSignal( pid, SIGTRAP );
	r = PtraceGetRegs( pid, StubRegs );
	if (r < 0)
		Die("constructor: ptrace_get_regs failed (%d)\n", errno);

	ChildPid = pid;
}

TT_ADDRESS_SPACE_IMPL::~TT_ADDRESS_SPACE_IMPL()
{
	assert( SigTarget == 0 );
	//trace(stderr,"~tt_address_space_impl()\n");
	Destroy();
	ptrace( PTRACE_KILL, ChildPid, 0, 0 );
	assert( ChildPid != -1 );
	kill( ChildPid, SIGTERM );
	ChildPid = -1;
}

ADDRESS_SPACE_IMPL* CreateTTAddressSpace()
{
	//trace("create_tt_address_space\n");
	// Set up the signal handler and unmask it first.
	// The child's signal handler will be unmasked too.
	return new TT_ADDRESS_SPACE_IMPL();
}

int TT_ADDRESS_SPACE_IMPL::UsersideReq( int type )
{
	struct tt_req *ureq = (struct tt_req *) StubRegs[EBX];
	int r;

	ptrace( PTRACE_POKEDATA, ChildPid, &ureq->type, type );

	r = PtraceSetRegs( ChildPid, StubRegs );
	if (r < 0)
		Die("ptrace_set_regs failed\n");
	r = ::ptrace( PTRACE_CONT, ChildPid, 0, 0 );
	if (r < 0)
		Die("ptrace( PTRACE_CONT ) failed\n");

	WaitForSignal( ChildPid, SIGTRAP );
	r = PtraceGetRegs( ChildPid, StubRegs );
	if (r < 0)
		Die("ptrace_get_regs failed (%d)\n", errno);

	return StubRegs[EAX];
}

int TT_ADDRESS_SPACE_IMPL::Mmap( BYTE *address, size_t length, int prot, int flags, int file, off_t offset )
{
	//trace("tt_address_space_impl::mmap()\n");

	// send our pid to the stub
	struct tt_req *ureq = (struct tt_req *) StubRegs[EBX];
	ptrace( PTRACE_POKEDATA, ChildPid, &ureq->u.map.pid, getpid() );
	ptrace( PTRACE_POKEDATA, ChildPid, &ureq->u.map.fd, file );
	ptrace( PTRACE_POKEDATA, ChildPid, &ureq->u.map.addr, (int) address );
	ptrace( PTRACE_POKEDATA, ChildPid, &ureq->u.map.len, length );
	ptrace( PTRACE_POKEDATA, ChildPid, &ureq->u.map.ofs, offset );
	ptrace( PTRACE_POKEDATA, ChildPid, &ureq->u.map.prot, prot );
	return UsersideReq( tt_req_map );
}

int TT_ADDRESS_SPACE_IMPL::Munmap( BYTE *address, size_t length )
{
	//trace("tt_address_space_impl::munmap()\n");
	struct tt_req *ureq = (struct tt_req *) StubRegs[EBX];
	ptrace( PTRACE_POKEDATA, ChildPid, &ureq->u.map.addr, (int) address );
	ptrace( PTRACE_POKEDATA, ChildPid, &ureq->u.map.len, length );
	return UsersideReq( tt_req_umap );
}

unsigned short TT_ADDRESS_SPACE_IMPL::GetUserspaceFs()
{
	return StubRegs[FS];
}

void GetStubPath( const char *kernel_path )
{
	// FIXME: handle loader in path too
	const char *p = strrchr( kernel_path, '/' );
	int len;
	if (p)
	{
		len = p - kernel_path + 1;
	}
	else
	{
		static const char current_dir[] = "./";
		p = current_dir;
		len = sizeof current_dir - 1;
	}

	memcpy( StubPath, kernel_path, len );
	StubPath[len] = 0;
	if ((len + sizeof StubName) > sizeof StubPath)
		Die("path too long\n");
	strcat( StubPath, StubName );
}

// quick check that /proc is mounted
void CheckProc()
{
	int fd = open("/proc/self/fd/0", O_RDONLY);
	if (fd < 0)
		Die("/proc not mounted\n");
	close( fd );
}

bool InitTt( const char *kernel_path )
{
	GetStubPath( kernel_path );
	CheckProc();
	trace("using thread tracing, kernel %s, client %s\n", kernel_path, StubPath );
	PTRACE_ADRESS_SPACE_IMPL::SetSignals();
	pCreateAddressSpace = &CreateTTAddressSpace;
	return true;
}
<|endoftext|>