<commit_before>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2013, Willow Garage, Inc.
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Willow Garage nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: A. Huaman */

#include "urdf_world_parser.h"

#include <fstream>
#include <sstream>
#include <algorithm>

#include <tinyxml.h>

#include <urdf_parser/urdf_parser.h>
#include <urdf_model/model.h>
#include <urdf_world/world.h>
#include <urdf_model/pose.h>

#include "dart/common/Console.h"

const bool debug = false;

namespace dart {
namespace utils {
namespace urdf_parsing {

Entity::Entity(const urdf::Entity& urdfEntity)
  : model(urdfEntity.model),
    origin(urdfEntity.origin),
    twist(urdfEntity.twist)
{
  // Do nothing
}

/**
 * @function parseWorldURDF
 */
std::shared_ptr<World> parseWorldURDF(
    const std::string& _xml_string,
    const dart::common::Uri& _baseUri)
{
  TiXmlDocument xml_doc;
  xml_doc.Parse( _xml_string.c_str() );
  TiXmlElement *world_xml = xml_doc.FirstChildElement("world");
  if( !world_xml )
  {
    dtwarn << "[parseWorldURDF] ERROR: Could not find a <world> element in XML, exiting and not loading! \n";
    return nullptr;
  }

  // Get world name
  const char *name = world_xml->Attribute("name");
  if(!name)
  {
    dtwarn << "[parseWorldURDF] ERROR: World does not have a name tag specified. Exiting and not loading! \n";
    return nullptr;
  }

  std::shared_ptr<World> world(new World);
  world->name = std::string(name);
  if(debug) std::cout<< "World name: "<< world->name << std::endl;

  // Get all include filenames
  int count = 0;
  std::map<std::string, std::string> includedFiles;

  for( TiXmlElement* include_xml = world_xml->FirstChildElement("include");
       include_xml != nullptr;
       include_xml = include_xml->NextSiblingElement("include") )
  {
    ++count;
    const char *filename = include_xml->Attribute("filename");
    const char *model_name = include_xml->Attribute("model_name");
    std::string string_filename( filename );
    std::string string_model_name( model_name );
    includedFiles[string_model_name] = string_filename;
    if(debug) std::cout<< "Include: Model name: " <<  model_name << " filename: " << filename <<std::endl;
  }
  if(debug) std::cout<<"Found "<< count <<" include filenames "<<std::endl;

  // Get all entities
  count = 0;
  for( TiXmlElement* entity_xml = world_xml->FirstChildElement("entity");
       entity_xml != nullptr;
       entity_xml = entity_xml->NextSiblingElement("entity") )
  {
    count++;
    dart::utils::urdf_parsing::Entity entity;
    try
    {
      const char* entity_model = entity_xml->Attribute("model");
      std::string string_entity_model( entity_model );

      // Find the model
      if( includedFiles.find( string_entity_model ) == includedFiles.end() )
      {
        dtwarn << "[parseWorldURDF] Cannot find the model ["
               << string_entity_model << "], did you provide the correct name? "
               << "We will return a nullptr.\n"<<std::endl;
        return nullptr;
      }
      else
      {
        std::string fileName = includedFiles.find( string_entity_model )->second;

        dart::common::Uri absoluteUri;
        if(!absoluteUri.fromRelativeUri(_baseUri, fileName))
        {
          dtwarn << "[parseWorldURDF] Failed resolving mesh URI '"
                 << fileName << "' relative to '" << _baseUri.toString()
                 << "'. We will return a nullptr.\n";
          return nullptr;
        }

        const std::string fileFullName = *(absoluteUri.mPath);
        entity.uri = absoluteUri;
        // Parse model
        std::string xml_model_string;
        std::fstream xml_file( fileFullName.c_str(), std::fstream::in );

        if(!xml_file.is_open())
        {
          dtwarn << "[parseWorldURDF] Could not open the file [" << fileFullName
                 << "]. Returning a nullptr.\n";
          return nullptr;
        }

        while( xml_file.good() )
        {
          std::string line;
          std::getline( xml_file, line );
          xml_model_string += (line + "\n");
        }
        xml_file.close();
        entity.model = urdf::parseURDF( xml_model_string );

        if( !entity.model )
        {
          dtwarn << "[parseWorldURDF] Could not find a model named ["
                 << xml_model_string << "] in file [" <<  fileFullName
                 << "]. We will return a nullptr.\n";
          return nullptr;
        }
        else
        {
          // Parse location
          TiXmlElement* origin = entity_xml->FirstChildElement("origin");
          if( origin )
          {
            if( !urdf::parsePose( entity.origin, origin ) )
            {
              dtwarn << "[ERROR] Missing origin tag for '" << entity.model->getName() << "'\n";
              return world;
            }
          }

          // If name is defined
          const char* entity_name = entity_xml->Attribute("name");
          if( entity_name )
          {
            std::string string_entity_name( entity_name );
            entity.model->name_ = string_entity_name;
          }

          // Store in world
          world->models.push_back( entity );
        }
      } // end of include read

    }
    catch( urdf::ParseError& e )
    {
      if(debug) std::cout << "Entity xml not initialized correctly \n";
      //entity->reset();
      //world->reset();
      return world;
    }

  } // end for
  if(debug) std::cout << "Found " << count << " entities \n";

  return world;
}

} // namesapce urdf_parsing
} // namespace utils
} // namespace dart
<commit_msg>Use Uri::getFilesystemPath() to get file path in urdf_world_parser.cpp<commit_after>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2013, Willow Garage, Inc.
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Willow Garage nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: A. Huaman */

#include "urdf_world_parser.h"

#include <fstream>
#include <sstream>
#include <algorithm>

#include <tinyxml.h>

#include <urdf_parser/urdf_parser.h>
#include <urdf_model/model.h>
#include <urdf_world/world.h>
#include <urdf_model/pose.h>

#include "dart/common/Console.h"

const bool debug = false;

namespace dart {
namespace utils {
namespace urdf_parsing {

Entity::Entity(const urdf::Entity& urdfEntity)
  : model(urdfEntity.model),
    origin(urdfEntity.origin),
    twist(urdfEntity.twist)
{
  // Do nothing
}

/**
 * @function parseWorldURDF
 */
std::shared_ptr<World> parseWorldURDF(
    const std::string& _xml_string,
    const dart::common::Uri& _baseUri)
{
  TiXmlDocument xml_doc;
  xml_doc.Parse( _xml_string.c_str() );
  TiXmlElement *world_xml = xml_doc.FirstChildElement("world");
  if( !world_xml )
  {
    dtwarn << "[parseWorldURDF] ERROR: Could not find a <world> element in XML, exiting and not loading! \n";
    return nullptr;
  }

  // Get world name
  const char *name = world_xml->Attribute("name");
  if(!name)
  {
    dtwarn << "[parseWorldURDF] ERROR: World does not have a name tag specified. Exiting and not loading! \n";
    return nullptr;
  }

  std::shared_ptr<World> world(new World);
  world->name = std::string(name);
  if(debug) std::cout<< "World name: "<< world->name << std::endl;

  // Get all include filenames
  int count = 0;
  std::map<std::string, std::string> includedFiles;

  for( TiXmlElement* include_xml = world_xml->FirstChildElement("include");
       include_xml != nullptr;
       include_xml = include_xml->NextSiblingElement("include") )
  {
    ++count;
    const char *filename = include_xml->Attribute("filename");
    const char *model_name = include_xml->Attribute("model_name");
    std::string string_filename( filename );
    std::string string_model_name( model_name );
    includedFiles[string_model_name] = string_filename;
    if(debug) std::cout<< "Include: Model name: " <<  model_name << " filename: " << filename <<std::endl;
  }
  if(debug) std::cout<<"Found "<< count <<" include filenames "<<std::endl;

  // Get all entities
  count = 0;
  for( TiXmlElement* entity_xml = world_xml->FirstChildElement("entity");
       entity_xml != nullptr;
       entity_xml = entity_xml->NextSiblingElement("entity") )
  {
    count++;
    dart::utils::urdf_parsing::Entity entity;
    try
    {
      const char* entity_model = entity_xml->Attribute("model");
      std::string string_entity_model( entity_model );

      // Find the model
      if( includedFiles.find( string_entity_model ) == includedFiles.end() )
      {
        dtwarn << "[parseWorldURDF] Cannot find the model ["
               << string_entity_model << "], did you provide the correct name? "
               << "We will return a nullptr.\n"<<std::endl;
        return nullptr;
      }
      else
      {
        std::string fileName = includedFiles.find( string_entity_model )->second;

        dart::common::Uri absoluteUri;
        if(!absoluteUri.fromRelativeUri(_baseUri, fileName))
        {
          dtwarn << "[parseWorldURDF] Failed resolving mesh URI '"
                 << fileName << "' relative to '" << _baseUri.toString()
                 << "'. We will return a nullptr.\n";
          return nullptr;
        }

        const std::string fileFullName = absoluteUri.getFilesystemPath();
        entity.uri = absoluteUri;
        // Parse model
        std::string xml_model_string;
        std::fstream xml_file( fileFullName.c_str(), std::fstream::in );

        if(!xml_file.is_open())
        {
          dtwarn << "[parseWorldURDF] Could not open the file [" << fileFullName
                 << "]. Returning a nullptr.\n";
          return nullptr;
        }

        while( xml_file.good() )
        {
          std::string line;
          std::getline( xml_file, line );
          xml_model_string += (line + "\n");
        }
        xml_file.close();
        entity.model = urdf::parseURDF( xml_model_string );

        if( !entity.model )
        {
          dtwarn << "[parseWorldURDF] Could not find a model named ["
                 << xml_model_string << "] in file [" <<  fileFullName
                 << "]. We will return a nullptr.\n";
          return nullptr;
        }
        else
        {
          // Parse location
          TiXmlElement* origin = entity_xml->FirstChildElement("origin");
          if( origin )
          {
            if( !urdf::parsePose( entity.origin, origin ) )
            {
              dtwarn << "[ERROR] Missing origin tag for '" << entity.model->getName() << "'\n";
              return world;
            }
          }

          // If name is defined
          const char* entity_name = entity_xml->Attribute("name");
          if( entity_name )
          {
            std::string string_entity_name( entity_name );
            entity.model->name_ = string_entity_name;
          }

          // Store in world
          world->models.push_back( entity );
        }
      } // end of include read

    }
    catch( urdf::ParseError& e )
    {
      if(debug) std::cout << "Entity xml not initialized correctly \n";
      //entity->reset();
      //world->reset();
      return world;
    }

  } // end for
  if(debug) std::cout << "Found " << count << " entities \n";

  return world;
}

} // namesapce urdf_parsing
} // namespace utils
} // namespace dart
<|endoftext|>


<commit_before>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <gtest/gtest.h>
#include <qitype/signal.hpp>
#include <qi/future.hpp>
#include <qi/application.hpp>
#include <qitype/functiontypefactory.hpp>

qiLogCategory("test");

class Foo
{
public:
  void func(int)               { }
  void func1(int *r, int)
  {
    // hackish sleep so that asynchronous trigger detection is safer
    qi::os::msleep(1); *r += 1;
  }
  void func2(int *r, int, int) { *r += 1; }
};
void foo(int *r, int, int)     { *r += 1; }
void foo2(int *r, char, char)  { *r += 1; }
void foo3(int *r, Foo *)       { *r += 1; }
void foolast(int, qi::Promise<void> prom, int* r) { prom.setValue(0); *r += 1;}

TEST(TestSignal, TestCompilation)
{
  int                    res = 0;
  qi::Signal<void (int)> s;
  Foo*                   f = (Foo*)1;
  qi::Promise<void>      prom;

  //do not count
  s.connect(qi::makeGenericFunction(&Foo::func, f));
  s.connect(boost::bind<void>(&Foo::func, f, _1));

  s.connect(boost::bind(&foo, &res, 12, _1));
  s.connect(boost::bind(&foo2, &res, 12, _1));
  s.connect(boost::bind<void>(&Foo::func1, f, &res, _1));
  s.connect(boost::bind<void>(&Foo::func2, f, &res, 5, _1));
  s.connect(boost::bind(&foo3, &res, f));
  s.connect(boost::bind(&foolast, _1, prom, &res));

  s(42);
  int timeout = 100;
  while (timeout > 0) {
    qi::os::msleep(10);
    if (res == 6)
      break;
    timeout -= 1;
  }
  ASSERT_EQ(6, res);
  ASSERT_TRUE(prom.future().isFinished());
  ASSERT_FALSE(prom.future().hasError());
}

void write42(boost::shared_ptr<int> ptr)
{
  *ptr = 42;
}

TEST(TestSignal, SharedPtr)
{
  // Redundant with Copy test, but just to be sure, check that shared_ptr
  // is correctly transmited.
  qi::Signal<void (boost::shared_ptr<int>)> sig;
  sig.connect(qi::makeGenericFunction(&write42), qi::MetaCallType_Queued);
  {
    boost::shared_ptr<int> ptr(new int(12));
    sig(ptr);
  };
}

void byRef(int& i, bool* done)
{
  qiLogDebug() <<"byRef " << &i << ' ' << done;
  i = 12;
  *done = true;
}

TEST(TestSignal, Copy)
{
  // Check that reference argument type are copied when an async call is made
  qi::Signal<void (int&, bool*)> sig;
  qiLogDebug() << "sync";
  sig.connect(qi::makeGenericFunction(byRef), qi::MetaCallType_Direct);
  bool done = false;
  int i = 0;
  qiLogDebug() << "iref is " << &i;
  sig(i, &done);
  ASSERT_TRUE(done); //synchronous
  //ASSERT_EQ(0, i); // byref, but still copies for small types
  qiLogDebug() << "async";
  sig =  qi::Signal<void (int&, bool*)>();
  sig.connect(qi::makeGenericFunction(byRef), qi::MetaCallType_Queued);
  i = 0;
  done = false;
  qiLogDebug() << "done is " << &done;
  sig(i, &done);
  for (unsigned c=0; !done && c<100;++c) qi::os::msleep(10);
  ASSERT_TRUE(done);
  ASSERT_EQ(0, i); // async: was copied
}

TEST(TestSignal, AutoDisconnect)
{
  // Test automatic disconnection when passing shared_ptrs
  int r = 0;
  boost::shared_ptr<Foo> foo(new Foo());
  qi::Signal<void (int*, int)> sig;
  sig.connect(foo, &Foo::func1, qi::MetaCallType_Direct);
  sig(&r, 0);
  ASSERT_EQ(1, r);
  foo.reset();
  sig(&r, 0);
  ASSERT_EQ(1, r);
}

TEST(TestSignal, AutoDisconnectTrack)
{
  // Test auto-disconnect using external tracker
  int r = 0;
  boost::shared_ptr<int> s(new int(2));
  Foo* ptr = new Foo();
  qi::Signal<void (int*, int)> sig;
  sig.connect(ptr, &Foo::func1, qi::MetaCallType_Direct).track(boost::weak_ptr<int>(s));
  sig(&r, 0);
  ASSERT_EQ(1, r);
  sig(&r, 1);
  ASSERT_EQ(2, r);
  s.reset();
  sig(&r, 1);
  ASSERT_EQ(2, r);
}

TEST(TestSignal, BadArity)
{
  qi::Signal<void()> s;
  // caught at compile-time by signal<T>
  ASSERT_EQ(qi::SignalBase::invalidLink, ((qi::SignalBase&)s).connect(&foo));
  //idem
  ASSERT_EQ(qi::SignalBase::invalidLink, ((qi::SignalBase&)s).connect(&foo2));
  ASSERT_EQ(qi::SignalBase::invalidLink, s.connect((Foo*)0, &Foo::func1));
}

void lol(int v, int& target)
{
  target = v;
}
TEST(TestSignal, SignalSignal)
{
  qi::Signal<void (int)> sig1;
  qi::Signal<void (int)> sig2;
  int res = 0;
  sig1.connect(sig2);
  sig2.connect(boost::bind<void>(&lol, _1, boost::ref(res)));
  sig1(10);
  qi::os::msleep(300);
  ASSERT_EQ(10, res);
}

int main(int argc, char **argv) {
  qi::Application app(argc, argv);
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Add throwing callback signal test<commit_after>/*
** Author(s):
**  - Cedric GESTES <gestes@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#include <gtest/gtest.h>
#include <qitype/signal.hpp>
#include <qi/future.hpp>
#include <qi/application.hpp>
#include <qitype/functiontypefactory.hpp>

qiLogCategory("test");

class Foo
{
public:
  void func(int)               { }
  void func1(int *r, int)
  {
    // hackish sleep so that asynchronous trigger detection is safer
    qi::os::msleep(1); *r += 1;
  }
  void func2(int *r, int, int) { *r += 1; }
};
void foo(int *r, int, int)     { *r += 1; }
void foo2(int *r, char, char)  { *r += 1; }
void foo3(int *r, Foo *)       { *r += 1; }
void foolast(int, qi::Promise<void> prom, int* r) { prom.setValue(0); *r += 1;}

TEST(TestSignal, TestCompilation)
{
  int                    res = 0;
  qi::Signal<void (int)> s;
  Foo*                   f = (Foo*)1;
  qi::Promise<void>      prom;

  //do not count
  s.connect(qi::makeGenericFunction(&Foo::func, f));
  s.connect(boost::bind<void>(&Foo::func, f, _1));

  s.connect(boost::bind(&foo, &res, 12, _1));
  s.connect(boost::bind(&foo2, &res, 12, _1));
  s.connect(boost::bind<void>(&Foo::func1, f, &res, _1));
  s.connect(boost::bind<void>(&Foo::func2, f, &res, 5, _1));
  s.connect(boost::bind(&foo3, &res, f));
  s.connect(boost::bind(&foolast, _1, prom, &res));

  s(42);
  int timeout = 100;
  while (timeout > 0) {
    qi::os::msleep(10);
    if (res == 6)
      break;
    timeout -= 1;
  }
  ASSERT_EQ(6, res);
  ASSERT_TRUE(prom.future().isFinished());
  ASSERT_FALSE(prom.future().hasError());
}

void write42(boost::shared_ptr<int> ptr)
{
  *ptr = 42;
}

TEST(TestSignal, SharedPtr)
{
  // Redundant with Copy test, but just to be sure, check that shared_ptr
  // is correctly transmited.
  qi::Signal<void (boost::shared_ptr<int>)> sig;
  sig.connect(qi::makeGenericFunction(&write42), qi::MetaCallType_Queued);
  {
    boost::shared_ptr<int> ptr(new int(12));
    sig(ptr);
  };
}

void byRef(int& i, bool* done)
{
  qiLogDebug() <<"byRef " << &i << ' ' << done;
  i = 12;
  *done = true;
}

TEST(TestSignal, Copy)
{
  // Check that reference argument type are copied when an async call is made
  qi::Signal<void (int&, bool*)> sig;
  qiLogDebug() << "sync";
  sig.connect(qi::makeGenericFunction(byRef), qi::MetaCallType_Direct);
  bool done = false;
  int i = 0;
  qiLogDebug() << "iref is " << &i;
  sig(i, &done);
  ASSERT_TRUE(done); //synchronous
  //ASSERT_EQ(0, i); // byref, but still copies for small types
  qiLogDebug() << "async";
  sig =  qi::Signal<void (int&, bool*)>();
  sig.connect(qi::makeGenericFunction(byRef), qi::MetaCallType_Queued);
  i = 0;
  done = false;
  qiLogDebug() << "done is " << &done;
  sig(i, &done);
  for (unsigned c=0; !done && c<100;++c) qi::os::msleep(10);
  ASSERT_TRUE(done);
  ASSERT_EQ(0, i); // async: was copied
}

TEST(TestSignal, AutoDisconnect)
{
  // Test automatic disconnection when passing shared_ptrs
  int r = 0;
  boost::shared_ptr<Foo> foo(new Foo());
  qi::Signal<void (int*, int)> sig;
  sig.connect(foo, &Foo::func1, qi::MetaCallType_Direct);
  sig(&r, 0);
  ASSERT_EQ(1, r);
  foo.reset();
  sig(&r, 0);
  ASSERT_EQ(1, r);
}

TEST(TestSignal, AutoDisconnectTrack)
{
  // Test auto-disconnect using external tracker
  int r = 0;
  boost::shared_ptr<int> s(new int(2));
  Foo* ptr = new Foo();
  qi::Signal<void (int*, int)> sig;
  sig.connect(ptr, &Foo::func1, qi::MetaCallType_Direct).track(boost::weak_ptr<int>(s));
  sig(&r, 0);
  ASSERT_EQ(1, r);
  sig(&r, 1);
  ASSERT_EQ(2, r);
  s.reset();
  sig(&r, 1);
  ASSERT_EQ(2, r);
}

TEST(TestSignal, BadArity)
{
  qi::Signal<void()> s;
  // caught at compile-time by signal<T>
  ASSERT_EQ(qi::SignalBase::invalidLink, ((qi::SignalBase&)s).connect(&foo));
  //idem
  ASSERT_EQ(qi::SignalBase::invalidLink, ((qi::SignalBase&)s).connect(&foo2));
  ASSERT_EQ(qi::SignalBase::invalidLink, s.connect((Foo*)0, &Foo::func1));
}

void lol(int v, int& target)
{
  target = v;
}
TEST(TestSignal, SignalSignal)
{
  qi::Signal<void (int)> sig1;
  qi::Signal<void (int)> sig2;
  int res = 0;
  sig1.connect(sig2);
  sig2.connect(boost::bind<void>(&lol, _1, boost::ref(res)));
  sig1(10);
  qi::os::msleep(300);
  ASSERT_EQ(10, res);
}

void foothrow() {
  throw 42;
}

TEST(TestSignal, SignalThrow)
{
  qi::Signal<void()> sig;
  sig.connect(boost::bind<void>(&foothrow));
  ASSERT_NO_THROW(sig());
  qi::os::msleep(50);
}

int main(int argc, char **argv) {
  qi::Application app(argc, argv);
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#include "util/file_piece.hh"

#include "util/file.hh"
#include "util/scoped.hh"
#include "util/string_piece.hh"
#include "util/tokenize_piece.hh"
#include "util/murmur_hash.hh"
#include "util/probing_hash_table.hh"

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <fstream>
#include <iostream>

#include <boost/scoped_array.hpp>
#include <boost/functional/hash.hpp>

//Struct for holding processed line
struct line_text {
	int value;
	StringPiece text;
};

//Hash table entry
struct Entry {
	uint64_t key;
	typedef unsigned char Key;

	uint64_t GetKey() const {
		return key;
	}

	void SetKey(uint64_t to) {
		key = to;
	}

	unsigned int GetValue() const {
		return value;
	}

	unsigned int value;
};

//Define table
typedef util::ProbingHashTable<Entry, boost::hash<uint64_t> > Table;

void serialize_table(char *mem, size_t size, char * filename);

void readTable(char * filename, char *mem, size_t size);

//Ask if it's better to have it receive a pointer to a line_text struct
line_text splitLine(StringPiece textin);

//Gets the MurmurmurHash for give string
uint64_t getHash(StringPiece text);

uint64_t getHash(StringPiece text) {
	std::size_t len = text.size();
	uint64_t key = util::MurmurHashNative(text.data(), len);
	return key;
}

void readTable(char * filename, char *mem, size_t size) {
	//Initial position of the file is the end of the file, thus we know the size
	std::ifstream file (filename, std::ios::in|std::ios::binary);
	file.read ((char *)mem, size); // read
	file.close();
}

void serialize_table(char *mem, size_t size, char * filename){
	std::ofstream os (filename, std::ios::binary);
	os.write((const char*)&mem[0], size);
	os.close();

}

line_text splitLine(StringPiece textin) {
	const char delim[] = " ||| ";
	StringPiece str; //Temp string container
	std::string temp; //Temp string for conversion
	int num;
	line_text output;

	//Tokenize
	util::TokenIter<util::MultiCharacter> it(textin, util::MultiCharacter(delim));
	//Get string
	str = *it;
	output.text = str;
	it++;

	//Get num
	str = *it;

	//Convert to int
	temp = str.as_string();
	num = atoi(temp.c_str());
	output.value = num;

	return output;
}

int main(int argc, char* argv[]){

	//Input file and table size
	/*if (argc != 2) {
		std::cout << "Provide input file and number of lines!" << std::endl;
		return 1;
	}*/
	std::fstream fileread("source.uniq.rand", std::ios::in);
	util::FilePiece filein(fileread);
	int tablesize = 23339836;

	//Init the table
	size_t size = Table::Size(tablesize, 1.2);
	char * mem = new char[size];
	memset(mem, 0, size);
	Table table(mem, size);

	//Output binary
	std::ofstream os ("data.dat", std::ios::binary);

	//Vector with 1000 elements, after the 1000nd we swap to disk
	std::vector<int> ram_container(1000);
	short counter = 0; //Counts how many entires are in the vector
	unsigned int offset = 0; //Keeps track of the offset

	//debuging variables
	Entry kiro;
	line_text temp;

	while(true){
		try {
			//Process line read
			line_text line;
			line = splitLine(filein.ReadLine());

			ram_container[counter] = line.value; //Put into the array

			//Create an entry to keep track of the offset
			Entry pesho;
			pesho.value = offset;
			pesho.key = getHash(line.text);

			//Put into table
			table.Insert(pesho);
			counter++;
			offset++;

			//debugging
			kiro = pesho;
			temp.value = line.value;
			temp.text = line.text;

			//Write to memory
			if (counter == 1000) {
				//write to memory
				os.write((const char*)&ram_container[0], counter * sizeof(int));
				counter = 0;
			}
		} catch (util::EndOfFileException e){
			std::cout << "End of file" << std::endl;
			os.write((const char*)&ram_container[0], counter * sizeof(int));
			break;
		}
	}
	//Close write stream:
	os.close();
	std::cout << "Last offset was " << offset << std::endl;
	std::cout << "Last entry key " << kiro.key << " Value " << kiro.value << std::endl;
	std::cout << "Last line text " << temp.text << " Num " << temp.value << std::endl;
	std::cout << "Expected hash is " << getHash(temp.text) << std::endl;

	const Entry * tocheck;
	table.Find(kiro.key, tocheck);
	std::cout << "Tocheck key " << tocheck -> GetKey() << " Tocheck value " << tocheck -> GetValue() << std::endl;

	serialize_table(mem, size, "hashtable.dat");
	return 0;

}<commit_msg>Speed up by removing debugging<commit_after>#include "util/file_piece.hh"

#include "util/file.hh"
#include "util/scoped.hh"
#include "util/string_piece.hh"
#include "util/tokenize_piece.hh"
#include "util/murmur_hash.hh"
#include "util/probing_hash_table.hh"

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#include <fstream>
#include <iostream>

#include <boost/scoped_array.hpp>
#include <boost/functional/hash.hpp>

//Struct for holding processed line
struct line_text {
	int value;
	StringPiece text;
};

//Hash table entry
struct Entry {
	uint64_t key;
	typedef unsigned char Key;

	uint64_t GetKey() const {
		return key;
	}

	void SetKey(uint64_t to) {
		key = to;
	}

	unsigned int GetValue() const {
		return value;
	}

	unsigned int value;
};

//Define table
typedef util::ProbingHashTable<Entry, boost::hash<uint64_t> > Table;

void serialize_table(char *mem, size_t size, char * filename);

void readTable(char * filename, char *mem, size_t size);

//Ask if it's better to have it receive a pointer to a line_text struct
line_text splitLine(StringPiece textin);

//Gets the MurmurmurHash for give string
uint64_t getHash(StringPiece text);

uint64_t getHash(StringPiece text) {
	std::size_t len = text.size();
	uint64_t key = util::MurmurHashNative(text.data(), len);
	return key;
}

void readTable(char * filename, char *mem, size_t size) {
	//Initial position of the file is the end of the file, thus we know the size
	std::ifstream file (filename, std::ios::in|std::ios::binary);
	file.read ((char *)mem, size); // read
	file.close();
}

void serialize_table(char *mem, size_t size, char * filename){
	std::ofstream os (filename, std::ios::binary);
	os.write((const char*)&mem[0], size);
	os.close();

}

line_text splitLine(StringPiece textin) {
	const char delim[] = " ||| ";
	StringPiece str; //Temp string container
	std::string temp; //Temp string for conversion
	int num;
	line_text output;

	//Tokenize
	util::TokenIter<util::MultiCharacter> it(textin, util::MultiCharacter(delim));
	//Get string
	str = *it;
	output.text = str;
	it++;

	//Get num
	str = *it;

	//Convert to int
	temp = str.as_string();
	num = atoi(temp.c_str());
	output.value = num;

	return output;
}

int main(int argc, char* argv[]){

	//Input file and table size
	/*if (argc != 2) {
		std::cout << "Provide input file and number of lines!" << std::endl;
		return 1;
	}*/
	std::fstream fileread("source.uniq.rand", std::ios::in);
	util::FilePiece filein(fileread);
	int tablesize = 23339836;

	//Init the table
	size_t size = Table::Size(tablesize, 1.2);
	char * mem = new char[size];
	memset(mem, 0, size);
	Table table(mem, size);

	//Output binary
	std::ofstream os ("data.dat", std::ios::binary);

	//Vector with 1000 elements, after the 1000nd we swap to disk
	std::vector<int> ram_container(1000);
	short counter = 0; //Counts how many entires are in the vector
	unsigned int offset = 0; //Keeps track of the offset

	while(true){
		try {
			//Process line read
			line_text line;
			line = splitLine(filein.ReadLine());

			ram_container[counter] = line.value; //Put into the array

			//Create an entry to keep track of the offset
			Entry pesho;
			pesho.value = offset;
			pesho.key = getHash(line.text);

			//Put into table
			table.Insert(pesho);
			counter++;
			offset++;

			//Write to memory
			if (counter == 1000) {
				//write to memory
				os.write((const char*)&ram_container[0], counter * sizeof(int));
				counter = 0;
			}
		} catch (util::EndOfFileException e){
			std::cout << "End of file" << std::endl;
			os.write((const char*)&ram_container[0], counter * sizeof(int));
			break;
		}
	}
	//Close write stream:
	os.close();

	serialize_table(mem, size, "hashtable.dat");
	return 0;

}<|endoftext|>


<commit_before>#include "gemvtest.hh"
#include "matrix.hh"
#include "vector.hh"
#include "blas/gemv.hh"

using namespace Linalg;

void
GEMVTest::testSquareRowMajor()
{
  Matrix<double> A(3,3);
  Vector<double> x(3), y(3);

  A(0,0) = 1; A(0, 1) = 2; A(0, 2) = 3;
  A(1,0) = 4; A(1, 1) = 5; A(1, 2) = 6;
  A(2,0) = 7; A(2, 1) = 8; A(2, 2) = 9;
  x(0) = 10; x(1) = 11; x(2) = 12;
  y(0) = 0; y(1) = 0; y(2) = 0;

  Blas::gemv(1, A, x, 0.0, y);

  UT_ASSERT_EQUAL(y(0), 68.);
  UT_ASSERT_EQUAL(y(1), 40.+55.+72.);
  UT_ASSERT_EQUAL(y(2), 70.+88.+108.);
}

void
GEMVTest::testSquareTransposedRowMajor()
{
  Matrix<double> A(3,3);
  Vector<double> x(3), y(3);

  A(0,0) = 1; A(0, 1) = 2; A(0, 2) = 3;
  A(1,0) = 4; A(1, 1) = 5; A(1, 2) = 6;
  A(2,0) = 7; A(2, 1) = 8; A(2, 2) = 9;
  x(0) = 10; x(1) = 11; x(2) = 12;
  y(0) = 0; y(1) = 0; y(2) = 0;

  Blas::gemv(1, A.t(), x, 0.0, y);

  UT_ASSERT_EQUAL(y(0), 10. + 44. + 84.);
  UT_ASSERT_EQUAL(y(1), 20. + 55. + 96.);
  UT_ASSERT_EQUAL(y(2), 30. + 66. + 108.);
}

void
GEMVTest::testSquareColMajor()
{
  Matrix<double> A(3,3, false);
  Vector<double> x(3), y(3);

  A(0,0) = 1; A(0, 1) = 2; A(0, 2) = 3;
  A(1,0) = 4; A(1, 1) = 5; A(1, 2) = 6;
  A(2,0) = 7; A(2, 1) = 8; A(2, 2) = 9;
  x(0) = 10; x(1) = 11; x(2) = 12;
  y(0) = 0; y(1) = 0; y(2) = 0;

  Blas::gemv(1, A, x, 0.0, y);

  UT_ASSERT_EQUAL(y(0), 68.);
  UT_ASSERT_EQUAL(y(1), 40.+55.+72.);
  UT_ASSERT_EQUAL(y(2), 70.+88.+108.);
}

void
GEMVTest::testSquareTransposedColMajor()
{
  Matrix<double> A(3,3, false);
  Vector<double> x(3), y(3);

  A(0,0) = 1; A(0, 1) = 2; A(0, 2) = 3;
  A(1,0) = 4; A(1, 1) = 5; A(1, 2) = 6;
  A(2,0) = 7; A(2, 1) = 8; A(2, 2) = 9;
  x(0) = 10; x(1) = 11; x(2) = 12;
  y(0) = 0; y(1) = 0; y(2) = 0;

  Blas::gemv(1, A.t(), x, 0.0, y);

  UT_ASSERT_EQUAL(y(0), 10. + 44. + 84.);
  UT_ASSERT_EQUAL(y(1), 20. + 55. + 96.);
  UT_ASSERT_EQUAL(y(2), 30. + 66. + 108.);
}

void
GEMVTest::testRectRowMajor()
{
  Matrix<double> A(2,3);
  Vector<double> x(3), y(2);

  A(0,0) = 1; A(0, 1) = 2; A(0, 2) = 3;
  A(1,0) = 4; A(1, 1) = 5; A(1, 2) = 6;
  x(0) = 10; x(1) = 11; x(2) = 12;
  y(0) = 0; y(1) = 0; y(2) = 0;

  Blas::gemv(1, A, x, 0.0, y);

  UT_ASSERT_EQUAL(y(0), 68.);
  UT_ASSERT_EQUAL(y(1), 40.+55.+72.);
}

void
GEMVTest::testRectColMajor()
{
  Matrix<double> A(2,3, false);
  Vector<double> x(3), y(2);

  A(0,0) = 1; A(0, 1) = 2; A(0, 2) = 3;
  A(1,0) = 4; A(1, 1) = 5; A(1, 2) = 6;
  x(0) = 10; x(1) = 11; x(2) = 12;
  y(0) = 0; y(1) = 0; y(2) = 0;

  Blas::gemv(1, A, x, 0.0, y);

  UT_ASSERT_EQUAL(y(0), 68.);
  UT_ASSERT_EQUAL(y(1), 40.+55.+72.);
}

UnitTest::TestSuite *
GEMVTest::suite()
{
  UnitTest::TestSuite *s = new UnitTest::TestSuite("Tests for Blas::gemv()");

  s->addTest(new UnitTest::TestCaller<GEMVTest>(
               "Blas::gemv(double[m,m], double[m], double[m]) (row-major)",
               &GEMVTest::testSquareRowMajor));

  s->addTest(new UnitTest::TestCaller<GEMVTest>(
               "Blas::gemv(double[m,n], double[n], double[m]) (row-major)",
               &GEMVTest::testRectRowMajor));

  s->addTest(new UnitTest::TestCaller<GEMVTest>(
               "Blas::gemv(double[m,m]::t(), double[m], double[m]) (row-major)",
               &GEMVTest::testSquareTransposedRowMajor));

  s->addTest(new UnitTest::TestCaller<GEMVTest>(
               "Blas::gemv(double[m,m], double[m], double[m]) (col-major)",
               &GEMVTest::testSquareColMajor));

  s->addTest(new UnitTest::TestCaller<GEMVTest>(
               "Blas::gemv(double[m,n], double[n], double[m]) (col-major)",
               &GEMVTest::testRectColMajor));

  s->addTest(new UnitTest::TestCaller<GEMVTest>(
               "Blas::gemv(double[m,m]::t(), double[m], double[m]) (col-major)",
               &GEMVTest::testSquareTransposedColMajor));

  return s;

}
<commit_msg>Fixed bug in test.<commit_after>#include "gemvtest.hh"
#include "matrix.hh"
#include "vector.hh"
#include "blas/gemv.hh"

using namespace Linalg;

void
GEMVTest::testSquareRowMajor()
{
  Matrix<double> A(3,3);
  Vector<double> x(3), y(3);

  A(0,0) = 1; A(0, 1) = 2; A(0, 2) = 3;
  A(1,0) = 4; A(1, 1) = 5; A(1, 2) = 6;
  A(2,0) = 7; A(2, 1) = 8; A(2, 2) = 9;
  x(0) = 10; x(1) = 11; x(2) = 12;
  y(0) = 0; y(1) = 0; y(2) = 0;

  Blas::gemv(1, A, x, 0.0, y);

  UT_ASSERT_EQUAL(y(0), 68.);
  UT_ASSERT_EQUAL(y(1), 40.+55.+72.);
  UT_ASSERT_EQUAL(y(2), 70.+88.+108.);
}

void
GEMVTest::testSquareTransposedRowMajor()
{
  Matrix<double> A(3,3);
  Vector<double> x(3), y(3);

  A(0,0) = 1; A(0, 1) = 2; A(0, 2) = 3;
  A(1,0) = 4; A(1, 1) = 5; A(1, 2) = 6;
  A(2,0) = 7; A(2, 1) = 8; A(2, 2) = 9;
  x(0) = 10; x(1) = 11; x(2) = 12;
  y(0) = 0; y(1) = 0; y(2) = 0;

  Blas::gemv(1, A.t(), x, 0.0, y);

  UT_ASSERT_EQUAL(y(0), 10. + 44. + 84.);
  UT_ASSERT_EQUAL(y(1), 20. + 55. + 96.);
  UT_ASSERT_EQUAL(y(2), 30. + 66. + 108.);
}

void
GEMVTest::testSquareColMajor()
{
  Matrix<double> A(3,3, false);
  Vector<double> x(3), y(3);

  A(0,0) = 1; A(0, 1) = 2; A(0, 2) = 3;
  A(1,0) = 4; A(1, 1) = 5; A(1, 2) = 6;
  A(2,0) = 7; A(2, 1) = 8; A(2, 2) = 9;
  x(0) = 10; x(1) = 11; x(2) = 12;
  y(0) = 0; y(1) = 0; y(2) = 0;

  Blas::gemv(1, A, x, 0.0, y);

  UT_ASSERT_EQUAL(y(0), 68.);
  UT_ASSERT_EQUAL(y(1), 40.+55.+72.);
  UT_ASSERT_EQUAL(y(2), 70.+88.+108.);
}

void
GEMVTest::testSquareTransposedColMajor()
{
  Matrix<double> A(3,3, false);
  Vector<double> x(3), y(3);

  A(0,0) = 1; A(0, 1) = 2; A(0, 2) = 3;
  A(1,0) = 4; A(1, 1) = 5; A(1, 2) = 6;
  A(2,0) = 7; A(2, 1) = 8; A(2, 2) = 9;
  x(0) = 10; x(1) = 11; x(2) = 12;
  y(0) = 0; y(1) = 0; y(2) = 0;

  Blas::gemv(1, A.t(), x, 0.0, y);

  UT_ASSERT_EQUAL(y(0), 10. + 44. + 84.);
  UT_ASSERT_EQUAL(y(1), 20. + 55. + 96.);
  UT_ASSERT_EQUAL(y(2), 30. + 66. + 108.);
}

void
GEMVTest::testRectRowMajor()
{
  Matrix<double> A(2,3);
  Vector<double> x(3), y(2);

  A(0,0) = 1; A(0, 1) = 2; A(0, 2) = 3;
  A(1,0) = 4; A(1, 1) = 5; A(1, 2) = 6;
  x(0) = 10; x(1) = 11; x(2) = 12;
  y(0) = 0; y(1) = 0;

  Blas::gemv(1, A, x, 0.0, y);

  UT_ASSERT_EQUAL(y(0), 68.);
  UT_ASSERT_EQUAL(y(1), 167.);
}

void
GEMVTest::testRectColMajor()
{
  Matrix<double> A(2,3, false);
  Vector<double> x(3), y(2);

  A(0,0) = 1; A(0, 1) = 2; A(0, 2) = 3;
  A(1,0) = 4; A(1, 1) = 5; A(1, 2) = 6;
  x(0) = 10; x(1) = 11; x(2) = 12;
  y(0) = 0; y(1) = 0;

  Blas::gemv(1, A, x, 0.0, y);

  UT_ASSERT_EQUAL(y(0), 68.);
  UT_ASSERT_EQUAL(y(1), 167.);
}

UnitTest::TestSuite *
GEMVTest::suite()
{
  UnitTest::TestSuite *s = new UnitTest::TestSuite("Tests for Blas::gemv()");

  s->addTest(new UnitTest::TestCaller<GEMVTest>(
               "Blas::gemv(double[m,m], double[m], double[m]) (row-major)",
               &GEMVTest::testSquareRowMajor));

  s->addTest(new UnitTest::TestCaller<GEMVTest>(
               "Blas::gemv(double[m,n], double[n], double[m]) (row-major)",
               &GEMVTest::testRectRowMajor));

  s->addTest(new UnitTest::TestCaller<GEMVTest>(
               "Blas::gemv(double[m,m]::t(), double[m], double[m]) (row-major)",
               &GEMVTest::testSquareTransposedRowMajor));

  s->addTest(new UnitTest::TestCaller<GEMVTest>(
               "Blas::gemv(double[m,m], double[m], double[m]) (col-major)",
               &GEMVTest::testSquareColMajor));

  s->addTest(new UnitTest::TestCaller<GEMVTest>(
               "Blas::gemv(double[m,n], double[n], double[m]) (col-major)",
               &GEMVTest::testRectColMajor));

  s->addTest(new UnitTest::TestCaller<GEMVTest>(
               "Blas::gemv(double[m,m]::t(), double[m], double[m]) (col-major)",
               &GEMVTest::testSquareTransposedColMajor));

  return s;

}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file jsonrpc.cpp
 * @author Marek Kotewicz <marek@ethdev.com>
 * @date 2014
 */

#if ETH_JSONRPC

#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
#include <libdevcore/Log.h>
#include <libdevcore/CommonIO.h>
#include <libdevcore/CommonJS.h>
#include <libwebthree/WebThree.h>
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include <libweb3jsonrpc/CorsHttpServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h>
#include <jsonrpccpp/client/connectors/httpclient.h>
#include <set>
#include "JsonSpiritHeaders.h"
#include "TestHelper.h"
#include "webthreestubclient.h"

BOOST_AUTO_TEST_SUITE(jsonrpc)

using namespace std;
using namespace dev;
using namespace dev::eth;
namespace js = json_spirit;

WebThreeDirect *web3;
unique_ptr<WebThreeStubServer> jsonrpcServer;
unique_ptr<WebThreeStubClient> jsonrpcClient;

struct Setup
{
	Setup()
	{
		static bool setup = false;
		if (setup)
			return;
		setup = true;

		dev::p2p::NetworkPreferences nprefs(30303, std::string(), false);
		web3 = new WebThreeDirect("Ethereum(++) tests", "", true, {"eth", "shh"}, nprefs);

		web3->setIdealPeerCount(5);
		web3->ethereum()->setForceMining(true);
		jsonrpcServer = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(jsonrpc::CorsHttpServer(8080), *web3, {}));
		jsonrpcServer->setIdentities({});
		jsonrpcServer->StartListening();

		jsonrpcClient = unique_ptr<WebThreeStubClient>(new WebThreeStubClient(jsonrpc::HttpClient("http://localhost:8080")));
	}
};

BOOST_FIXTURE_TEST_SUITE(environment, Setup)

BOOST_AUTO_TEST_CASE(jsonrpc_defaultBlock)
{
	cnote << "Testing jsonrpc defaultBlock...";
	int defaultBlock = jsonrpcClient->eth_defaultBlock();
	BOOST_CHECK_EQUAL(defaultBlock, web3->ethereum()->getDefault());
}

BOOST_AUTO_TEST_CASE(jsonrpc_gasPrice)
{
	cnote << "Testing jsonrpc gasPrice...";
	string gasPrice = jsonrpcClient->eth_gasPrice();
	BOOST_CHECK_EQUAL(gasPrice, toJS(10 * dev::eth::szabo));
}

BOOST_AUTO_TEST_CASE(jsonrpc_isListening)
{
	cnote << "Testing jsonrpc isListening...";

	web3->startNetwork();
	bool listeningOn = jsonrpcClient->eth_listening();
	BOOST_CHECK_EQUAL(listeningOn, web3->isNetworkStarted());

	web3->stopNetwork();
	bool listeningOff = jsonrpcClient->eth_listening();
	BOOST_CHECK_EQUAL(listeningOff, web3->isNetworkStarted());
}

BOOST_AUTO_TEST_CASE(jsonrpc_isMining)
{
	cnote << "Testing jsonrpc isMining...";

	web3->ethereum()->startMining();
	bool miningOn = jsonrpcClient->eth_mining();
	BOOST_CHECK_EQUAL(miningOn, web3->ethereum()->isMining());

	web3->ethereum()->stopMining();
	bool miningOff = jsonrpcClient->eth_mining();
	BOOST_CHECK_EQUAL(miningOff, web3->ethereum()->isMining());
}

BOOST_AUTO_TEST_CASE(jsonrpc_accounts)
{
	cnote << "Testing jsonrpc accounts...";
	std::vector <dev::KeyPair> keys = {KeyPair::create(), KeyPair::create()};
	jsonrpcServer->setAccounts(keys);
	Json::Value k = jsonrpcClient->eth_accounts();
	jsonrpcServer->setAccounts({});
	BOOST_CHECK_EQUAL(k.isArray(), true);
	BOOST_CHECK_EQUAL(k.size(),  keys.size());
	for (auto &i:k)
	{
		auto it = std::find_if(keys.begin(), keys.end(), [i](dev::KeyPair const& keyPair)
		{
			return jsToAddress(i.asString()) == keyPair.address();
		});
		BOOST_CHECK_EQUAL(it != keys.end(), true);
	}
}

BOOST_AUTO_TEST_CASE(jsonrpc_number)
{
	cnote << "Testing jsonrpc number2...";
	int number = jsonrpcClient->eth_number();
	BOOST_CHECK_EQUAL(number, web3->ethereum()->number() + 1);
	dev::eth::mine(*(web3->ethereum()), 1);
	int numberAfter = jsonrpcClient->eth_number();
	BOOST_CHECK_EQUAL(number + 1, numberAfter);
	BOOST_CHECK_EQUAL(numberAfter, web3->ethereum()->number() + 1);
}

BOOST_AUTO_TEST_CASE(jsonrpc_peerCount)
{
	cnote << "Testing jsonrpc peerCount...";
	int peerCount = jsonrpcClient->eth_peerCount();
	BOOST_CHECK_EQUAL(web3->peerCount(), peerCount);
}

BOOST_AUTO_TEST_CASE(jsonrpc_setListening)
{
	cnote << "Testing jsonrpc setListening...";

	jsonrpcClient->eth_setListening(true);
	BOOST_CHECK_EQUAL(web3->isNetworkStarted(), true);

	jsonrpcClient->eth_setListening(false);
	BOOST_CHECK_EQUAL(web3->isNetworkStarted(), false);
}

BOOST_AUTO_TEST_CASE(jsonrpc_setMining)
{
	cnote << "Testing jsonrpc setMining...";

	jsonrpcClient->eth_setMining(true);
	BOOST_CHECK_EQUAL(web3->ethereum()->isMining(), true);

	jsonrpcClient->eth_setMining(false);
	BOOST_CHECK_EQUAL(web3->ethereum()->isMining(), false);
}

BOOST_AUTO_TEST_CASE(jsonrpc_stateAt)
{
	cnote << "Testing jsonrpc stateAt...";
	dev::KeyPair key = KeyPair::create();
	auto address = key.address();
	string stateAt = jsonrpcClient->eth_stateAt(toJS(address), "0");
	BOOST_CHECK_EQUAL(toJS(web3->ethereum()->stateAt(address, jsToU256("0"), 0)), stateAt);
}

BOOST_AUTO_TEST_CASE(jsonrpc_transact)
{
	cnote << "Testing jsonrpc transact...";
	string coinbase = jsonrpcClient->eth_coinbase();
	BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3->ethereum()->address());

	dev::KeyPair key = KeyPair::create();
	auto address = key.address();
	auto receiver = KeyPair::create();
	web3->ethereum()->setAddress(address);

	coinbase = jsonrpcClient->eth_coinbase();
	BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3->ethereum()->address());
	BOOST_CHECK_EQUAL(jsToAddress(coinbase), address);

	jsonrpcServer->setAccounts({key});
	auto balance = web3->ethereum()->balanceAt(address, 0);
	string balanceString = jsonrpcClient->eth_balanceAt(toJS(address));
	double countAt = jsonrpcClient->eth_countAt(toJS(address));

	BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3->ethereum()->countAt(address));
	BOOST_CHECK_EQUAL(countAt, 0);
	BOOST_CHECK_EQUAL(toJS(balance), balanceString);
	BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "0");

	dev::eth::mine(*(web3->ethereum()), 1);
	balance = web3->ethereum()->balanceAt(address, 0);
	balanceString = jsonrpcClient->eth_balanceAt(toJS(address));

	BOOST_CHECK_EQUAL(toJS(balance), balanceString);
	BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "1500000000000000000");

	auto txAmount = balance / 2u;
	auto gasPrice = 10 * dev::eth::szabo;
	auto gas = dev::eth::c_txGas;

	Json::Value t;
	t["from"] = toJS(address);
	t["value"] = jsToDecimal(toJS(txAmount));
	t["to"] = toJS(receiver.address());
	t["data"] = toJS(bytes());
	t["gas"] = toJS(gas);
	t["gasPrice"] = toJS(gasPrice);

	jsonrpcClient->eth_transact(t);
	jsonrpcServer->setAccounts({});
	dev::eth::mine(*(web3->ethereum()), 1);

	countAt = jsonrpcClient->eth_countAt(toJS(address));
	auto balance2 = web3->ethereum()->balanceAt(receiver.address());
	string balanceString2 = jsonrpcClient->eth_balanceAt(toJS(receiver.address()));

	BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3->ethereum()->countAt(address));
	BOOST_CHECK_EQUAL(countAt, 1);
	BOOST_CHECK_EQUAL(toJS(balance2), balanceString2);
	BOOST_CHECK_EQUAL(jsToDecimal(balanceString2), "750000000000000000");
	BOOST_CHECK_EQUAL(txAmount, balance2);
}

BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()

#endif
<commit_msg>fixed test<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum 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 General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file jsonrpc.cpp
 * @author Marek Kotewicz <marek@ethdev.com>
 * @date 2014
 */

#if ETH_JSONRPC

#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
#include <libdevcore/Log.h>
#include <libdevcore/CommonIO.h>
#include <libdevcore/CommonJS.h>
#include <libwebthree/WebThree.h>
#include <libweb3jsonrpc/WebThreeStubServer.h>
#include <libweb3jsonrpc/CorsHttpServer.h>
#include <jsonrpccpp/server/connectors/httpserver.h>
#include <jsonrpccpp/client/connectors/httpclient.h>
#include <set>
#include "JsonSpiritHeaders.h"
#include "TestHelper.h"
#include "webthreestubclient.h"

BOOST_AUTO_TEST_SUITE(jsonrpc)

using namespace std;
using namespace dev;
using namespace dev::eth;
namespace js = json_spirit;

WebThreeDirect *web3;
unique_ptr<WebThreeStubServer> jsonrpcServer;
unique_ptr<WebThreeStubClient> jsonrpcClient;

struct Setup
{
	Setup()
	{
		static bool setup = false;
		if (setup)
			return;
		setup = true;

		dev::p2p::NetworkPreferences nprefs(30303, std::string(), false);
		web3 = new WebThreeDirect("Ethereum(++) tests", "", true, {"eth", "shh"}, nprefs);

		web3->setIdealPeerCount(5);
		web3->ethereum()->setForceMining(true);
		auto server = new jsonrpc::CorsHttpServer(8080);
		jsonrpcServer = unique_ptr<WebThreeStubServer>(new WebThreeStubServer(*server, *web3, {}));
		jsonrpcServer->setIdentities({});
		jsonrpcServer->StartListening();
		auto client = new jsonrpc::HttpClient("http://localhost:8080");
		jsonrpcClient = unique_ptr<WebThreeStubClient>(new WebThreeStubClient(*client));
	}
};

BOOST_FIXTURE_TEST_SUITE(environment, Setup)

BOOST_AUTO_TEST_CASE(jsonrpc_defaultBlock)
{
	cnote << "Testing jsonrpc defaultBlock...";
	int defaultBlock = jsonrpcClient->eth_defaultBlock();
	BOOST_CHECK_EQUAL(defaultBlock, web3->ethereum()->getDefault());
}

BOOST_AUTO_TEST_CASE(jsonrpc_gasPrice)
{
	cnote << "Testing jsonrpc gasPrice...";
	string gasPrice = jsonrpcClient->eth_gasPrice();
	BOOST_CHECK_EQUAL(gasPrice, toJS(10 * dev::eth::szabo));
}

BOOST_AUTO_TEST_CASE(jsonrpc_isListening)
{
	cnote << "Testing jsonrpc isListening...";

	web3->startNetwork();
	bool listeningOn = jsonrpcClient->eth_listening();
	BOOST_CHECK_EQUAL(listeningOn, web3->isNetworkStarted());

	web3->stopNetwork();
	bool listeningOff = jsonrpcClient->eth_listening();
	BOOST_CHECK_EQUAL(listeningOff, web3->isNetworkStarted());
}

BOOST_AUTO_TEST_CASE(jsonrpc_isMining)
{
	cnote << "Testing jsonrpc isMining...";

	web3->ethereum()->startMining();
	bool miningOn = jsonrpcClient->eth_mining();
	BOOST_CHECK_EQUAL(miningOn, web3->ethereum()->isMining());

	web3->ethereum()->stopMining();
	bool miningOff = jsonrpcClient->eth_mining();
	BOOST_CHECK_EQUAL(miningOff, web3->ethereum()->isMining());
}

BOOST_AUTO_TEST_CASE(jsonrpc_accounts)
{
	cnote << "Testing jsonrpc accounts...";
	std::vector <dev::KeyPair> keys = {KeyPair::create(), KeyPair::create()};
	jsonrpcServer->setAccounts(keys);
	Json::Value k = jsonrpcClient->eth_accounts();
	jsonrpcServer->setAccounts({});
	BOOST_CHECK_EQUAL(k.isArray(), true);
	BOOST_CHECK_EQUAL(k.size(),  keys.size());
	for (auto &i:k)
	{
		auto it = std::find_if(keys.begin(), keys.end(), [i](dev::KeyPair const& keyPair)
		{
			return jsToAddress(i.asString()) == keyPair.address();
		});
		BOOST_CHECK_EQUAL(it != keys.end(), true);
	}
}

BOOST_AUTO_TEST_CASE(jsonrpc_number)
{
	cnote << "Testing jsonrpc number2...";
	int number = jsonrpcClient->eth_number();
	BOOST_CHECK_EQUAL(number, web3->ethereum()->number() + 1);
	dev::eth::mine(*(web3->ethereum()), 1);
	int numberAfter = jsonrpcClient->eth_number();
	BOOST_CHECK_EQUAL(number + 1, numberAfter);
	BOOST_CHECK_EQUAL(numberAfter, web3->ethereum()->number() + 1);
}

BOOST_AUTO_TEST_CASE(jsonrpc_peerCount)
{
	cnote << "Testing jsonrpc peerCount...";
	int peerCount = jsonrpcClient->eth_peerCount();
	BOOST_CHECK_EQUAL(web3->peerCount(), peerCount);
}

BOOST_AUTO_TEST_CASE(jsonrpc_setListening)
{
	cnote << "Testing jsonrpc setListening...";

	jsonrpcClient->eth_setListening(true);
	BOOST_CHECK_EQUAL(web3->isNetworkStarted(), true);

	jsonrpcClient->eth_setListening(false);
	BOOST_CHECK_EQUAL(web3->isNetworkStarted(), false);
}

BOOST_AUTO_TEST_CASE(jsonrpc_setMining)
{
	cnote << "Testing jsonrpc setMining...";

	jsonrpcClient->eth_setMining(true);
	BOOST_CHECK_EQUAL(web3->ethereum()->isMining(), true);

	jsonrpcClient->eth_setMining(false);
	BOOST_CHECK_EQUAL(web3->ethereum()->isMining(), false);
}

BOOST_AUTO_TEST_CASE(jsonrpc_stateAt)
{
	cnote << "Testing jsonrpc stateAt...";
	dev::KeyPair key = KeyPair::create();
	auto address = key.address();
	string stateAt = jsonrpcClient->eth_stateAt(toJS(address), "0");
	BOOST_CHECK_EQUAL(toJS(web3->ethereum()->stateAt(address, jsToU256("0"), 0)), stateAt);
}

BOOST_AUTO_TEST_CASE(jsonrpc_transact)
{
	cnote << "Testing jsonrpc transact...";
	string coinbase = jsonrpcClient->eth_coinbase();
	BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3->ethereum()->address());

	dev::KeyPair key = KeyPair::create();
	auto address = key.address();
	auto receiver = KeyPair::create();
	web3->ethereum()->setAddress(address);

	coinbase = jsonrpcClient->eth_coinbase();
	BOOST_CHECK_EQUAL(jsToAddress(coinbase), web3->ethereum()->address());
	BOOST_CHECK_EQUAL(jsToAddress(coinbase), address);

	jsonrpcServer->setAccounts({key});
	auto balance = web3->ethereum()->balanceAt(address, 0);
	string balanceString = jsonrpcClient->eth_balanceAt(toJS(address));
	double countAt = jsonrpcClient->eth_countAt(toJS(address));

	BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3->ethereum()->countAt(address));
	BOOST_CHECK_EQUAL(countAt, 0);
	BOOST_CHECK_EQUAL(toJS(balance), balanceString);
	BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "0");

	dev::eth::mine(*(web3->ethereum()), 1);
	balance = web3->ethereum()->balanceAt(address, 0);
	balanceString = jsonrpcClient->eth_balanceAt(toJS(address));

	BOOST_CHECK_EQUAL(toJS(balance), balanceString);
	BOOST_CHECK_EQUAL(jsToDecimal(balanceString), "1500000000000000000");

	auto txAmount = balance / 2u;
	auto gasPrice = 10 * dev::eth::szabo;
	auto gas = dev::eth::c_txGas;

	Json::Value t;
	t["from"] = toJS(address);
	t["value"] = jsToDecimal(toJS(txAmount));
	t["to"] = toJS(receiver.address());
	t["data"] = toJS(bytes());
	t["gas"] = toJS(gas);
	t["gasPrice"] = toJS(gasPrice);

	jsonrpcClient->eth_transact(t);
	jsonrpcServer->setAccounts({});
	dev::eth::mine(*(web3->ethereum()), 1);

	countAt = jsonrpcClient->eth_countAt(toJS(address));
	auto balance2 = web3->ethereum()->balanceAt(receiver.address());
	string balanceString2 = jsonrpcClient->eth_balanceAt(toJS(receiver.address()));

	BOOST_CHECK_EQUAL(countAt, (double)(uint64_t)web3->ethereum()->countAt(address));
	BOOST_CHECK_EQUAL(countAt, 1);
	BOOST_CHECK_EQUAL(toJS(balance2), balanceString2);
	BOOST_CHECK_EQUAL(jsToDecimal(balanceString2), "750000000000000000");
	BOOST_CHECK_EQUAL(txAmount, balance2);
}

BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()

#endif
<|endoftext|>


<commit_before>#ifndef ecmdClientCapi_H
#define ecmdClientCapi_H

/* $Header$ */

/**
 * @file ecmdClientCapi.H
 * @brief eCMD C/C++ Client Interface
*/

//--------------------------------------------------------------------
// Includes
//--------------------------------------------------------------------

//--------------------------------------------------------------------
//  Forward References
//--------------------------------------------------------------------

/** @name Load/Unload Functions */
//@{
/**
 @brief Load the eCMD DLL
 @retval 0 if successful load   1 if unsuccessful
 @post eCMD DLL is loaded into memory
 @see initDll
 @see unloadDll

       - This function loads the DLL based first on CRONUS_DLL env variable, next on CRONUS_EXE env. variable.
       - Name limit of 255 characters.
       - Function also inits a symbol table of DLL functions.
       - Errors in loading are printed to STDOUT.
*/
int loadDll();

/**
 @brief Unload the eCMD DLL
 @retval 0 if successful load  1 if unsuccessful
 @see loadDll

 - Errors in unloading are printed to STDOUT.
*/

int unloadDll();

/**
 @brief Initialize the eCMD DLL
 @retval 0 if successful load  1 if unsuccessful
 @param argc Passed from Command line Arguments
 @param argv Passed from Command line Arguments
 @pre loadDll must have been called
 @post Global options (ex. -debug, -p#, -c#) will be removed from arg list
 @see loadDll

 - initializes Cronus objects in the DLL.
 - argc/argv get passed to the Cronus DLL.
 - Global options such as -debug flags and -p#, -c# will be parsed out.
 - Position flags can be queried later with functions like wasposselected()
*/

int initDll(int argc, char* argv[]);

//@}

#endif /* ecmdClientCapi_H */

// Change Log *********************************************************
//
//  Flag Reason   Vers Date     Coder  Description
//  ---- -------- ---- -------- -----  -------------------------------
//                              cengel Initial Creation
//
// End Change Log *****************************************************
<commit_msg>Added error functions<commit_after>#ifndef ecmdClientCapi_H
#define ecmdClientCapi_H

/* $Header$ */

/**
 * @file ecmdClientCapi.H
 * @brief eCMD C/C++ Client Interface
*/

//--------------------------------------------------------------------
// Includes
//--------------------------------------------------------------------
#include "ecmdReturnCodes.H"

//--------------------------------------------------------------------
//  Forward References
//--------------------------------------------------------------------

/** @name Load/Unload Functions */
//@{
/**
 @brief Load the eCMD DLL
 @retval ECMD_SUCCESS if successful load   nonzero if unsuccessful
 @post eCMD DLL is loaded into memory
 @see initDll
 @see unloadDll

       - This function loads the DLL based first on CRONUS_DLL env variable, next on CRONUS_EXE env. variable.
       - Name limit of 255 characters.
       - Function also inits a symbol table of DLL functions.
       - Errors in loading are printed to STDOUT.
*/
ecmdrc_t ecmdLoadDll();

/**
 @brief Unload the eCMD DLL
 @retval ECMD_SUCCESS if successful load  nonzero if unsuccessful
 @see loadDll

 - Errors in unloading are printed to STDOUT.
*/

ecmdrc_t ecmdUnloadDll();

/**
 @brief Initialize the eCMD DLL
 @retval ECMD_SUCCESS if successful load  nonzero if unsuccessful
 @param argc Passed from Command line Arguments
 @param argv Passed from Command line Arguments
 @pre loadDll must have been called
 @post Global options (ex. -debug, -p#, -c#) will be removed from arg list
 @see loadDll

 - initializes objects in the DLL.
 - argc/argv get passed to the eCMD DLL.
 - Global options such as -debug flags and -p#, -c# will be parsed out.
 - Position flags can be queried later with functions like wasposselected()
*/

ecmdrc_t ecmdInitDll(int argc, char* argv[]);

//@}

/** @name Error Handling Functions */
//@{

/**
 @brief Retrieve
*/
ecmdrc_t ecmdGetErrorMsg(ecmdrc_t errorcode, char* message);

ecmdrc_t ecmdRegisterErrorMsg(ecmdrc_t errorcode, const char* message);

//@}

/** @name Output Functions */
//@{

//@}

#endif /* ecmdClientCapi_H */

// Change Log *********************************************************
//
//  Flag Reason   Vers Date     Coder  Description
//  ---- -------- ---- -------- -----  -------------------------------
//                              cengel Initial Creation
//
// End Change Log *****************************************************
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (C) 2012 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file mixer.cpp
 *
 * Control channel input/output mixer and failsafe.
 */

#include <nuttx/config.h>

#include <sys/types.h>
#include <stdbool.h>
#include <string.h>

#include <drivers/drv_pwm_output.h>
#include <drivers/drv_hrt.h>

#include <systemlib/mixer/mixer.h>

extern "C" {
//#define DEBUG
#include "px4io.h"
}

/*
 * Maximum interval in us before FMU signal is considered lost
 */
#define FMU_INPUT_DROP_LIMIT_US		200000

/* XXX need to move the RC_CHANNEL_FUNCTION out of rc_channels.h and into systemlib */
#define ROLL     0
#define PITCH    1
#define YAW      2
#define THROTTLE 3
#define OVERRIDE 4

/* current servo arm/disarm state */
static bool mixer_servos_armed = false;

/* selected control values and count for mixing */
enum mixer_source {
	MIX_NONE,
	MIX_FMU,
	MIX_OVERRIDE,
	MIX_FAILSAFE
};
static mixer_source source;

static int	mixer_callback(uintptr_t handle,
			       uint8_t control_group,
			       uint8_t control_index,
			       float &control);

static MixerGroup mixer_group(mixer_callback, 0);

void
mixer_tick(void)
{
	/* check that we are receiving fresh data from the FMU */
	if ((hrt_absolute_time() - system_state.fmu_data_received_time) > FMU_INPUT_DROP_LIMIT_US) {

		/* too long without FMU input, time to go to failsafe */
		r_status_flags |= PX4IO_P_STATUS_FLAGS_OVERRIDE;
		r_status_flags &= ~(PX4IO_P_STATUS_FLAGS_FMU_OK | PX4IO_P_STATUS_FLAGS_RAW_PWM);
		r_status_alarms |= PX4IO_P_STATUS_ALARMS_FMU_LOST;
		debug("AP RX timeout");
	}

	source = MIX_FAILSAFE;

	/*
	 * Decide which set of controls we're using.
	 */
	if (r_status_flags & PX4IO_P_STATUS_FLAGS_RAW_PWM) {

		/* don't actually mix anything - we already have raw PWM values */
		source = MIX_NONE;

	} else {

		if (!(r_status_flags & PX4IO_P_STATUS_FLAGS_OVERRIDE) &&
		     (r_status_flags & PX4IO_P_STATUS_FLAGS_MIXER_OK)) {

			/* mix from FMU controls */
			source = MIX_FMU;
		}

		if ( (r_status_flags & PX4IO_P_STATUS_FLAGS_OVERRIDE) &&
		     (r_status_flags & PX4IO_P_STATUS_FLAGS_RC_OK)) {

		 	/* if allowed, mix from RC inputs directly */
			source = MIX_OVERRIDE;
		}
	}

	/*
	 * Run the mixers.
	 */
	if (source == MIX_FAILSAFE) {

		/* copy failsafe values to the servo outputs */
		for (unsigned i = 0; i < IO_SERVO_COUNT; i++)
			r_page_servos[i] = r_page_servo_failsafe[i];

	} else if (source != MIX_NONE) {

		float	outputs[IO_SERVO_COUNT];
		unsigned mixed;

		/* mix */
		mixed = mixer_group.mix(&outputs[0], IO_SERVO_COUNT);

		/* scale to PWM and update the servo outputs as required */
		for (unsigned i = 0; i < mixed; i++) {

			/* save actuator values for FMU readback */
			r_page_actuators[i] = FLOAT_TO_REG(outputs[i]);

			/* scale to servo output */
			r_page_servos[i] = (outputs[i] * 500.0f) + 1500;

		}
		for (unsigned i = mixed; i < IO_SERVO_COUNT; i++)
			r_page_servos[i] = 0;
	}

#if 0
		/* if everything is ok */

		if (!system_state.mixer_manual_override && system_state.mixer_fmu_available) {
			/* we have recent control data from the FMU */
			control_count = PX4IO_CONTROL_CHANNELS;
			control_values = &system_state.fmu_channel_data[0];

		} else if (system_state.rc_channels > 0) {
			/* when override is on or the fmu is not available, but RC is present */
			control_count = system_state.rc_channels;

			sched_lock();

			/* remap roll, pitch, yaw and throttle from RC specific to internal ordering */
			rc_channel_data[ROLL]     = system_state.rc_channel_data[system_state.rc_map[ROLL] - 1];
			rc_channel_data[PITCH]    = system_state.rc_channel_data[system_state.rc_map[PITCH] - 1];
			rc_channel_data[YAW]      = system_state.rc_channel_data[system_state.rc_map[YAW] - 1];
			rc_channel_data[THROTTLE] = system_state.rc_channel_data[system_state.rc_map[THROTTLE] - 1];
			//rc_channel_data[OVERRIDE] = system_state.rc_channel_data[system_state.rc_map[OVERRIDE] - 1];

			/* get the remaining channels, no remapping needed */
			for (unsigned i = 4; i < system_state.rc_channels; i++) {
				rc_channel_data[i] = system_state.rc_channel_data[i];
			}

			/* scale the control inputs */
			rc_channel_data[THROTTLE] = ((float)(rc_channel_data[THROTTLE] - system_state.rc_min[THROTTLE]) /
				(float)(system_state.rc_max[THROTTLE] - system_state.rc_min[THROTTLE])) * 1000.0f + 1000;

			if (rc_channel_data[THROTTLE] > 2000) {
				rc_channel_data[THROTTLE] = 2000;
			}

			if (rc_channel_data[THROTTLE] < 1000) {
				rc_channel_data[THROTTLE] = 1000;
			}

			// lib_lowprintf("Tmin: %d Ttrim: %d Tmax: %d T: %d \n",
			// 	(int)(system_state.rc_min[THROTTLE]), (int)(system_state.rc_trim[THROTTLE]),
			// 	(int)(system_state.rc_max[THROTTLE]), (int)(rc_channel_data[THROTTLE]));

			control_values = &rc_channel_data[0];
			sched_unlock();
		} else {
			/* we have no control input (no FMU, no RC) */

			// XXX builtin failsafe would activate here
			control_count = 0;
		}
		//lib_lowprintf("R: %d P: %d Y: %d T: %d \n", control_values[0], control_values[1], control_values[2], control_values[3]);

	/* this is for multicopters, etc. where manual override does not make sense */
	} else {
		/* if the fmu is available whe are good */
		if (system_state.mixer_fmu_available) {
			control_count = PX4IO_CONTROL_CHANNELS;
			control_values = &system_state.fmu_channel_data[0];
		/* we better shut everything off */
		} else {
			control_count = 0;
		}
	}
#endif

	/*
	 * Decide whether the servos should be armed right now.
	 *
	 * We must be armed, and we must have a PWM source; either raw from
	 * FMU or from the mixer.
	 *
	 * XXX correct behaviour for failsafe may require an additional case
	 * here.
	 */
	bool should_arm = ((r_status_flags & PX4IO_P_STATUS_FLAGS_ARMED) &&
		(r_status_flags & (PX4IO_P_STATUS_FLAGS_RAW_PWM | PX4IO_P_STATUS_FLAGS_MIXER_OK)));

	if (should_arm && !mixer_servos_armed) {
		/* need to arm, but not armed */
		up_pwm_servo_arm(true);
		mixer_servos_armed = true;

		/*
		 * Update the servo outputs.
		 */
		for (unsigned i = 0; i < IO_SERVO_COUNT; i++)
			up_pwm_servo_set(i, r_page_servos[i]);

	} else if (!should_arm && mixer_servos_armed) {
		/* armed but need to disarm */
		up_pwm_servo_arm(false);
		mixer_servos_armed = false;
	}
}

static int
mixer_callback(uintptr_t handle,
	       uint8_t control_group,
	       uint8_t control_index,
	       float &control)
{
	if (control_group != 0)
		return -1;

	switch (source) {
	case MIX_FMU:
		if (control_index < PX4IO_CONTROL_CHANNELS) {
			control = REG_TO_FLOAT(r_page_controls[control_index]);
			break;
		}
		return -1;

	case MIX_OVERRIDE:
		if (r_page_rc_input[PX4IO_P_RC_VALID] & (1 << control_index)) {
			control = REG_TO_FLOAT(r_page_rc_input[PX4IO_P_RC_BASE + control_index]);
			break;
		}
		return -1;

	case MIX_FAILSAFE:
	case MIX_NONE:
		/* XXX we could allow for configuration of per-output failsafe values */
		return -1;
	}

	return 0;
}

/*
 * XXX error handling here should be more aggressive; currently it is
 * possible to get STATUS_FLAGS_MIXER_OK set even though the mixer has
 * not loaded faithfully.
 */

static char mixer_text[256];		/* large enough for one mixer */
static unsigned mixer_text_length = 0;

void
mixer_handle_text(const void *buffer, size_t length)
{

	px4io_mixdata	*msg = (px4io_mixdata *)buffer;

	debug("mixer text %u", length);

	if (length < sizeof(px4io_mixdata))
		return;

	unsigned	text_length = length - sizeof(px4io_mixdata);

	switch (msg->action) {
	case F2I_MIXER_ACTION_RESET:
		debug("reset");
		mixer_group.reset();
		mixer_text_length = 0;
		r_status_flags &= ~PX4IO_P_STATUS_FLAGS_MIXER_OK;

		/* FALLTHROUGH */
	case F2I_MIXER_ACTION_APPEND:
		debug("append %d", length);

		/* check for overflow - this is really fatal */
		/* XXX could add just what will fit & try to parse, then repeat... */
		if ((mixer_text_length + text_length + 1) > sizeof(mixer_text)) {
			r_status_flags &= ~PX4IO_P_STATUS_FLAGS_MIXER_OK;
			return;
		}

		/* append mixer text and nul-terminate */
		memcpy(&mixer_text[mixer_text_length], msg->text, text_length);
		mixer_text_length += text_length;
		mixer_text[mixer_text_length] = '\0';
		debug("buflen %u", mixer_text_length);

		/* process the text buffer, adding new mixers as their descriptions can be parsed */
		unsigned resid = mixer_text_length;
		mixer_group.load_from_buf(&mixer_text[0], resid);

		/* if anything was parsed */
		if (resid != mixer_text_length) {

			/* ideally, this should test resid == 0 ? */
			r_status_flags |= PX4IO_P_STATUS_FLAGS_MIXER_OK;

			debug("used %u", mixer_text_length - resid);

			/* copy any leftover text to the base of the buffer for re-use */
			if (resid > 0)
				memcpy(&mixer_text[0], &mixer_text[mixer_text_length - resid], resid);

			mixer_text_length = resid;
		}

		break;
	}
}
<commit_msg>A couple of logic fixes from Tridge.<commit_after>/****************************************************************************
 *
 *   Copyright (C) 2012 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file mixer.cpp
 *
 * Control channel input/output mixer and failsafe.
 */

#include <nuttx/config.h>

#include <sys/types.h>
#include <stdbool.h>
#include <string.h>

#include <drivers/drv_pwm_output.h>
#include <drivers/drv_hrt.h>

#include <systemlib/mixer/mixer.h>

extern "C" {
//#define DEBUG
#include "px4io.h"
}

/*
 * Maximum interval in us before FMU signal is considered lost
 */
#define FMU_INPUT_DROP_LIMIT_US		200000

/* XXX need to move the RC_CHANNEL_FUNCTION out of rc_channels.h and into systemlib */
#define ROLL     0
#define PITCH    1
#define YAW      2
#define THROTTLE 3
#define OVERRIDE 4

/* current servo arm/disarm state */
static bool mixer_servos_armed = false;

/* selected control values and count for mixing */
enum mixer_source {
	MIX_NONE,
	MIX_FMU,
	MIX_OVERRIDE,
	MIX_FAILSAFE
};
static mixer_source source;

static int	mixer_callback(uintptr_t handle,
			       uint8_t control_group,
			       uint8_t control_index,
			       float &control);

static MixerGroup mixer_group(mixer_callback, 0);

void
mixer_tick(void)
{
	/* check that we are receiving fresh data from the FMU */
	if ((hrt_absolute_time() - system_state.fmu_data_received_time) > FMU_INPUT_DROP_LIMIT_US) {

		/* too long without FMU input, time to go to failsafe */
		if (r_status_flags & PX4IO_P_STATUS_FLAGS_FMU_OK) {
			debug("AP RX timeout");
		}
		r_status_flags |= PX4IO_P_STATUS_FLAGS_OVERRIDE;
		r_status_flags &= ~(PX4IO_P_STATUS_FLAGS_FMU_OK | PX4IO_P_STATUS_FLAGS_RAW_PWM);
		r_status_alarms |= PX4IO_P_STATUS_ALARMS_FMU_LOST;
	}

	source = MIX_FAILSAFE;

	/*
	 * Decide which set of controls we're using.
	 */
	if (r_status_flags & PX4IO_P_STATUS_FLAGS_RAW_PWM) {

		/* don't actually mix anything - we already have raw PWM values */
		source = MIX_NONE;

	} else {

		if (!(r_status_flags & PX4IO_P_STATUS_FLAGS_OVERRIDE) &&
		     (r_status_flags & PX4IO_P_STATUS_FLAGS_MIXER_OK)) {

			/* mix from FMU controls */
			source = MIX_FMU;
		}

		if ( (r_status_flags & PX4IO_P_STATUS_FLAGS_OVERRIDE) &&
		     (r_status_flags & PX4IO_P_STATUS_FLAGS_RC_OK)) {

		 	/* if allowed, mix from RC inputs directly */
			source = MIX_OVERRIDE;
		}
	}

	/*
	 * Run the mixers.
	 */
	if (source == MIX_FAILSAFE) {

		/* copy failsafe values to the servo outputs */
		for (unsigned i = 0; i < IO_SERVO_COUNT; i++)
			r_page_servos[i] = r_page_servo_failsafe[i];

	} else if (source != MIX_NONE) {

		float	outputs[IO_SERVO_COUNT];
		unsigned mixed;

		/* mix */
		mixed = mixer_group.mix(&outputs[0], IO_SERVO_COUNT);

		/* scale to PWM and update the servo outputs as required */
		for (unsigned i = 0; i < mixed; i++) {

			/* save actuator values for FMU readback */
			r_page_actuators[i] = FLOAT_TO_REG(outputs[i]);

			/* scale to servo output */
			r_page_servos[i] = (outputs[i] * 500.0f) + 1500;

		}
		for (unsigned i = mixed; i < IO_SERVO_COUNT; i++)
			r_page_servos[i] = 0;
	}

#if 0
		/* if everything is ok */

		if (!system_state.mixer_manual_override && system_state.mixer_fmu_available) {
			/* we have recent control data from the FMU */
			control_count = PX4IO_CONTROL_CHANNELS;
			control_values = &system_state.fmu_channel_data[0];

		} else if (system_state.rc_channels > 0) {
			/* when override is on or the fmu is not available, but RC is present */
			control_count = system_state.rc_channels;

			sched_lock();

			/* remap roll, pitch, yaw and throttle from RC specific to internal ordering */
			rc_channel_data[ROLL]     = system_state.rc_channel_data[system_state.rc_map[ROLL] - 1];
			rc_channel_data[PITCH]    = system_state.rc_channel_data[system_state.rc_map[PITCH] - 1];
			rc_channel_data[YAW]      = system_state.rc_channel_data[system_state.rc_map[YAW] - 1];
			rc_channel_data[THROTTLE] = system_state.rc_channel_data[system_state.rc_map[THROTTLE] - 1];
			//rc_channel_data[OVERRIDE] = system_state.rc_channel_data[system_state.rc_map[OVERRIDE] - 1];

			/* get the remaining channels, no remapping needed */
			for (unsigned i = 4; i < system_state.rc_channels; i++) {
				rc_channel_data[i] = system_state.rc_channel_data[i];
			}

			/* scale the control inputs */
			rc_channel_data[THROTTLE] = ((float)(rc_channel_data[THROTTLE] - system_state.rc_min[THROTTLE]) /
				(float)(system_state.rc_max[THROTTLE] - system_state.rc_min[THROTTLE])) * 1000.0f + 1000;

			if (rc_channel_data[THROTTLE] > 2000) {
				rc_channel_data[THROTTLE] = 2000;
			}

			if (rc_channel_data[THROTTLE] < 1000) {
				rc_channel_data[THROTTLE] = 1000;
			}

			// lib_lowprintf("Tmin: %d Ttrim: %d Tmax: %d T: %d \n",
			// 	(int)(system_state.rc_min[THROTTLE]), (int)(system_state.rc_trim[THROTTLE]),
			// 	(int)(system_state.rc_max[THROTTLE]), (int)(rc_channel_data[THROTTLE]));

			control_values = &rc_channel_data[0];
			sched_unlock();
		} else {
			/* we have no control input (no FMU, no RC) */

			// XXX builtin failsafe would activate here
			control_count = 0;
		}
		//lib_lowprintf("R: %d P: %d Y: %d T: %d \n", control_values[0], control_values[1], control_values[2], control_values[3]);

	/* this is for multicopters, etc. where manual override does not make sense */
	} else {
		/* if the fmu is available whe are good */
		if (system_state.mixer_fmu_available) {
			control_count = PX4IO_CONTROL_CHANNELS;
			control_values = &system_state.fmu_channel_data[0];
		/* we better shut everything off */
		} else {
			control_count = 0;
		}
	}
#endif

	/*
	 * Decide whether the servos should be armed right now.
	 *
	 * We must be armed, and we must have a PWM source; either raw from
	 * FMU or from the mixer.
	 *
	 * XXX correct behaviour for failsafe may require an additional case
	 * here.
	 */
	bool should_arm = ((r_status_flags & PX4IO_P_STATUS_FLAGS_ARMED) &&
		(r_status_flags & (PX4IO_P_STATUS_FLAGS_RAW_PWM | PX4IO_P_STATUS_FLAGS_MIXER_OK)));

	if (should_arm && !mixer_servos_armed) {
		/* need to arm, but not armed */
		up_pwm_servo_arm(true);
		mixer_servos_armed = true;

	} else if (!should_arm && mixer_servos_armed) {
		/* armed but need to disarm */
		up_pwm_servo_arm(false);
		mixer_servos_armed = false;
	}

	if (mixer_servos_armed) {
		/* update the servo outputs. */
		for (unsigned i = 0; i < IO_SERVO_COUNT; i++)
			up_pwm_servo_set(i, r_page_servos[i]);
	}
}

static int
mixer_callback(uintptr_t handle,
	       uint8_t control_group,
	       uint8_t control_index,
	       float &control)
{
	if (control_group != 0)
		return -1;

	switch (source) {
	case MIX_FMU:
		if (control_index < PX4IO_CONTROL_CHANNELS) {
			control = REG_TO_FLOAT(r_page_controls[control_index]);
			break;
		}
		return -1;

	case MIX_OVERRIDE:
		if (r_page_rc_input[PX4IO_P_RC_VALID] & (1 << control_index)) {
			control = REG_TO_FLOAT(r_page_rc_input[PX4IO_P_RC_BASE + control_index]);
			break;
		}
		return -1;

	case MIX_FAILSAFE:
	case MIX_NONE:
		/* XXX we could allow for configuration of per-output failsafe values */
		return -1;
	}

	return 0;
}

/*
 * XXX error handling here should be more aggressive; currently it is
 * possible to get STATUS_FLAGS_MIXER_OK set even though the mixer has
 * not loaded faithfully.
 */

static char mixer_text[256];		/* large enough for one mixer */
static unsigned mixer_text_length = 0;

void
mixer_handle_text(const void *buffer, size_t length)
{

	px4io_mixdata	*msg = (px4io_mixdata *)buffer;

	debug("mixer text %u", length);

	if (length < sizeof(px4io_mixdata))
		return;

	unsigned	text_length = length - sizeof(px4io_mixdata);

	switch (msg->action) {
	case F2I_MIXER_ACTION_RESET:
		debug("reset");
		mixer_group.reset();
		mixer_text_length = 0;
		r_status_flags &= ~PX4IO_P_STATUS_FLAGS_MIXER_OK;

		/* FALLTHROUGH */
	case F2I_MIXER_ACTION_APPEND:
		debug("append %d", length);

		/* check for overflow - this is really fatal */
		/* XXX could add just what will fit & try to parse, then repeat... */
		if ((mixer_text_length + text_length + 1) > sizeof(mixer_text)) {
			r_status_flags &= ~PX4IO_P_STATUS_FLAGS_MIXER_OK;
			return;
		}

		/* append mixer text and nul-terminate */
		memcpy(&mixer_text[mixer_text_length], msg->text, text_length);
		mixer_text_length += text_length;
		mixer_text[mixer_text_length] = '\0';
		debug("buflen %u", mixer_text_length);

		/* process the text buffer, adding new mixers as their descriptions can be parsed */
		unsigned resid = mixer_text_length;
		mixer_group.load_from_buf(&mixer_text[0], resid);

		/* if anything was parsed */
		if (resid != mixer_text_length) {

			/* ideally, this should test resid == 0 ? */
			r_status_flags |= PX4IO_P_STATUS_FLAGS_MIXER_OK;

			debug("used %u", mixer_text_length - resid);

			/* copy any leftover text to the base of the buffer for re-use */
			if (resid > 0)
				memcpy(&mixer_text[0], &mixer_text[mixer_text_length - resid], resid);

			mixer_text_length = resid;
		}

		break;
	}
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
// LLVM 'GCCAS' UTILITY
//
//  This utility is designed to be used by the GCC frontend for creating
// bytecode files from it's intermediate llvm assembly.  The requirements for
// this utility are thus slightly different than that of the standard as util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Transforms/CleanupGCCOutput.h"
#include "llvm/Transforms/LevelChange.h"
#include "llvm/Transforms/ConstantMerge.h"
#include "llvm/Transforms/ChangeAllocations.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "Support/CommandLine.h"
#include "Support/Signals.h"
#include <memory>
#include <fstream>
using std::cerr;

static cl::String InputFilename   ("", "Parse <arg> file, compile to bytecode",
                                   cl::Required, "");
static cl::String OutputFilename  ("o", "Override output filename");
static cl::Int    RunNPasses      ("stopAfterNPasses", "Only run the first N "
                                   "passes of gccas", cl::Hidden);
static cl::Flag   StopAtLevelRaise("stopraise", "Stop optimization before "
                                   "level raise", cl::Hidden);
static cl::Flag   Verify          ("verify", "Verify each pass result");

static inline void addPass(PassManager &PM, Pass *P) {
  static int NumPassesCreated = 0;

  // If we haven't already created the number of passes that was requested...
  if (RunNPasses == 0 || RunNPasses > NumPassesCreated) {
    // Add the pass to the pass manager...
    PM.add(P);

    // If we are verifying all of the intermediate steps, add the verifier...
    if (Verify) PM.add(createVerifierPass());

    // Keep track of how many passes we made for -stopAfterNPasses
    ++NumPassesCreated;
  }
}

void AddConfiguredTransformationPasses(PassManager &PM) {
  if (Verify) PM.add(createVerifierPass());

  addPass(PM, createFunctionResolvingPass());     // Resolve (...) functions
  addPass(PM, createConstantMergePass());         // Merge dup global constants
  addPass(PM, createDeadInstEliminationPass());   // Remove Dead code/vars
  addPass(PM, createRaiseAllocationsPass());      // call %malloc -> malloc inst
  addPass(PM, createCleanupGCCOutputPass());      // Fix gccisms
  addPass(PM, createIndVarSimplifyPass());        // Simplify indvars

  // Level raise is eternally buggy/in need of enhancements.  Allow
  // transformation to stop right before it runs.
  if (StopAtLevelRaise) return;

  addPass(PM, createRaisePointerReferencesPass());// Eliminate casts
  addPass(PM, createPromoteMemoryToRegister());   // Promote alloca's to regs
  addPass(PM, createReassociatePass());           // Reassociate expressions
  addPass(PM, createInstructionCombiningPass());  // Combine silly seq's
  addPass(PM, createDeadInstEliminationPass());   // Kill InstCombine remnants
  addPass(PM, createLICMPass());                  // Hoist loop invariants
  addPass(PM, createGCSEPass());                  // Remove common subexprs
  addPass(PM, createSCCPPass());                  // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  addPass(PM, createInstructionCombiningPass());
  addPass(PM, createAggressiveDCEPass());          // SSA based 'Agressive DCE'
  addPass(PM, createCFGSimplificationPass());      // Merge & remove BBs
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    cerr << E.getMessage() << "\n";
    return 1;
  }

  if (M.get() == 0) {
    cerr << "assembly didn't read correctly.\n";
    return 1;
  }

  if (OutputFilename == "") {   // Didn't specify an output filename?
    std::string IFN = InputFilename;
    int Len = IFN.length();
    if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
      OutputFilename = std::string(IFN.begin(), IFN.end()-2);
    } else {
      OutputFilename = IFN;   // Append a .o to it
    }
    OutputFilename += ".o";
  }

  std::ofstream Out(OutputFilename.c_str(), std::ios::out);
  if (!Out.good()) {
    cerr << "Error opening " << OutputFilename << "!\n";
    return 1;
  }

  // Make sure that the Out file gets unlink'd from the disk if we get a SIGINT
  RemoveFileOnSignal(OutputFilename);

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;

  // Add all of the transformation passes to the pass manager to do the cleanup
  // and optimization of the GCC output.
  //
  AddConfiguredTransformationPasses(Passes);

  // Write bytecode to file...
  Passes.add(new WriteBytecodePass(&Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M.get());
  return 0;
}
<commit_msg>Disabling reassociate pass until it is fixed.<commit_after>//===----------------------------------------------------------------------===//
// LLVM 'GCCAS' UTILITY
//
//  This utility is designed to be used by the GCC frontend for creating
// bytecode files from it's intermediate llvm assembly.  The requirements for
// this utility are thus slightly different than that of the standard as util.
//
//===----------------------------------------------------------------------===//

#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/Transforms/CleanupGCCOutput.h"
#include "llvm/Transforms/LevelChange.h"
#include "llvm/Transforms/ConstantMerge.h"
#include "llvm/Transforms/ChangeAllocations.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/WriteBytecodePass.h"
#include "Support/CommandLine.h"
#include "Support/Signals.h"
#include <memory>
#include <fstream>
using std::cerr;

static cl::String InputFilename   ("", "Parse <arg> file, compile to bytecode",
                                   cl::Required, "");
static cl::String OutputFilename  ("o", "Override output filename");
static cl::Int    RunNPasses      ("stopAfterNPasses", "Only run the first N "
                                   "passes of gccas", cl::Hidden);
static cl::Flag   StopAtLevelRaise("stopraise", "Stop optimization before "
                                   "level raise", cl::Hidden);
static cl::Flag   Verify          ("verify", "Verify each pass result");

static inline void addPass(PassManager &PM, Pass *P) {
  static int NumPassesCreated = 0;

  // If we haven't already created the number of passes that was requested...
  if (RunNPasses == 0 || RunNPasses > NumPassesCreated) {
    // Add the pass to the pass manager...
    PM.add(P);

    // If we are verifying all of the intermediate steps, add the verifier...
    if (Verify) PM.add(createVerifierPass());

    // Keep track of how many passes we made for -stopAfterNPasses
    ++NumPassesCreated;
  }
}

void AddConfiguredTransformationPasses(PassManager &PM) {
  if (Verify) PM.add(createVerifierPass());

  addPass(PM, createFunctionResolvingPass());     // Resolve (...) functions
  addPass(PM, createConstantMergePass());         // Merge dup global constants
  addPass(PM, createDeadInstEliminationPass());   // Remove Dead code/vars
  addPass(PM, createRaiseAllocationsPass());      // call %malloc -> malloc inst
  addPass(PM, createCleanupGCCOutputPass());      // Fix gccisms
  addPass(PM, createIndVarSimplifyPass());        // Simplify indvars

  // Level raise is eternally buggy/in need of enhancements.  Allow
  // transformation to stop right before it runs.
  if (StopAtLevelRaise) return;

  addPass(PM, createRaisePointerReferencesPass());// Eliminate casts
  addPass(PM, createPromoteMemoryToRegister());   // Promote alloca's to regs
  // Disabling until this is fixed -- Vikram, 7/7/02.
  // addPass(PM, createReassociatePass());           // Reassociate expressions
  addPass(PM, createInstructionCombiningPass());  // Combine silly seq's
  addPass(PM, createDeadInstEliminationPass());   // Kill InstCombine remnants
  addPass(PM, createLICMPass());                  // Hoist loop invariants
  addPass(PM, createGCSEPass());                  // Remove common subexprs
  addPass(PM, createSCCPPass());                  // Constant prop with SCCP

  // Run instcombine after redundancy elimination to exploit opportunities
  // opened up by them.
  addPass(PM, createInstructionCombiningPass());
  addPass(PM, createAggressiveDCEPass());          // SSA based 'Agressive DCE'
  addPass(PM, createCFGSimplificationPass());      // Merge & remove BBs
}

int main(int argc, char **argv) {
  cl::ParseCommandLineOptions(argc, argv, " llvm .s -> .o assembler for GCC\n");

  std::auto_ptr<Module> M;
  try {
    // Parse the file now...
    M.reset(ParseAssemblyFile(InputFilename));
  } catch (const ParseException &E) {
    cerr << E.getMessage() << "\n";
    return 1;
  }

  if (M.get() == 0) {
    cerr << "assembly didn't read correctly.\n";
    return 1;
  }

  if (OutputFilename == "") {   // Didn't specify an output filename?
    std::string IFN = InputFilename;
    int Len = IFN.length();
    if (IFN[Len-2] == '.' && IFN[Len-1] == 's') {   // Source ends in .s?
      OutputFilename = std::string(IFN.begin(), IFN.end()-2);
    } else {
      OutputFilename = IFN;   // Append a .o to it
    }
    OutputFilename += ".o";
  }

  std::ofstream Out(OutputFilename.c_str(), std::ios::out);
  if (!Out.good()) {
    cerr << "Error opening " << OutputFilename << "!\n";
    return 1;
  }

  // Make sure that the Out file gets unlink'd from the disk if we get a SIGINT
  RemoveFileOnSignal(OutputFilename);

  // In addition to just parsing the input from GCC, we also want to spiff it up
  // a little bit.  Do this now.
  //
  PassManager Passes;

  // Add all of the transformation passes to the pass manager to do the cleanup
  // and optimization of the GCC output.
  //
  AddConfiguredTransformationPasses(Passes);

  // Write bytecode to file...
  Passes.add(new WriteBytecodePass(&Out));

  // Run our queue of passes all at once now, efficiently.
  Passes.run(*M.get());
  return 0;
}
<|endoftext|>