<commit_before>/*
*
* Copyright 2013 Telefonica Investigacion y Desarrollo, S.A.U
*
* This file is part of Orion Context Broker.
*
* Orion Context Broker is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Orion Context Broker 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 Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Orion Context Broker. If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by this license please contact with
* fermin at tid dot es
*
* Author: Ken Zangelin
*/
#include <stdio.h>

#include "logMsg/logMsg.h"
#include "logMsg/traceLevels.h"

#include "common/globals.h"
#include "common/tag.h"
#include "ngsi/ContextAttribute.h"

/* ****************************************************************************
*
* ContextAttribute::ContextAttribute -
*/
ContextAttribute::ContextAttribute()
{
   name  = "";
   type  = "";
   value = "";
}

/* ****************************************************************************
*
* ContextAttribute::ContextAttribute -
*/
ContextAttribute::ContextAttribute(ContextAttribute* caP)
{
   LM_T(LmtClone, ("'cloning' a ContextAttribute"));
   name  = caP->name;
   type  = caP->type;
   value = caP->value;

   metadataVector.vec.clear();

   for (unsigned int mIx = 0; mIx < caP->metadataVector.size(); ++mIx)
   {
      LM_T(LmtClone, ("Copying metadata %d", mIx));
      Metadata* mP = new Metadata(caP->metadataVector.get(mIx));
      metadataVector.push_back(mP);
   }
}

/* ****************************************************************************
*
* ContextAttribute::ContextAttribute -
*/
ContextAttribute::ContextAttribute(std::string _name, std::string _type, std::string _value)
{
   name  = _name;
   type  = _type;
   value = _value;
}

/* ****************************************************************************
*
* ContextAttribute::getId() -
*/
std::string ContextAttribute::getId()
{
  for (unsigned int ix = 0; ix < metadataVector.size(); ++ix) {
      if (metadataVector.get(ix)->name == NGSI_MD_ID) {
          return metadataVector.get(ix)->value;
      }
  }
  return "";
}

/* ****************************************************************************
*
* render -
*/
std::string ContextAttribute::render(Format format, std::string indent, bool comma)
{
  std::string  out                    = "";
  std::string  xmlTag                 = "contextAttribute";
  std::string  jsonTag                = "attribute";
  bool         commaAfterContextValue = metadataVector.size() != 0;

  metadataVector.tagSet("metadata");

  //
  // About JSON commas:
  // contextValue is MANDATORY, so up to that field, all will wear the JSON comma
  // contextValue itself has a comma if metadataVector is rendered
  //
  out += startTag(indent, xmlTag, jsonTag, format, false, false);
  out += valueTag(indent + "  ", "name",         name,  format, true);
  out += valueTag(indent + "  ", "type",         type,  format, true);
  out += valueTag(indent + "  ", (format == XML ? "contextValue" : "value"), value, format, commaAfterContextValue);
  out += metadataVector.render(format, indent + "  ", false);
  out += endTag(indent, xmlTag, format, comma);

  return out;
}

/* ****************************************************************************
*
* ContextAttribute::check -
*/
std::string ContextAttribute::check(RequestType requestType, Format format, std::string indent, std::string predetectedError, int counter)
{
  if ((name == "") || (name == "not in use"))
    return "missing attribute name";

  if (requestType != UpdateContext) // FIXME: this is just to make harness test work
  {
    if ((value == "") || (value == "not in use"))
      return "missing attribute value";
  }

  return "OK";
}

/* ****************************************************************************
*
* ContextAttribute::present -
*/
void ContextAttribute::present(std::string indent, int ix)
{
  PRINTF("%sAttribute %d:\n",    indent.c_str(), ix);
  PRINTF("%s  Name:       %s\n", indent.c_str(), name.c_str());
  PRINTF("%s  Type:       %s\n", indent.c_str(), type.c_str());
  PRINTF("%s  Value:      %s\n", indent.c_str(), value.c_str());

  metadataVector.present("Attribute", indent + "  ");
}

/* ****************************************************************************
*
* ContextAttribute::release -
*/
void ContextAttribute::release(void)
{
  metadataVector.release();
}

/* ****************************************************************************
*
* toString -
*/
std::string ContextAttribute::toString(void)
{
  return name;
}
<commit_msg>Small code style update<commit_after>/*
*
* Copyright 2013 Telefonica Investigacion y Desarrollo, S.A.U
*
* This file is part of Orion Context Broker.
*
* Orion Context Broker is free software: you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Orion Context Broker 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 Affero
* General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Orion Context Broker. If not, see http://www.gnu.org/licenses/.
*
* For those usages not covered by this license please contact with
* fermin at tid dot es
*
* Author: Ken Zangelin
*/
#include <stdio.h>

#include "logMsg/logMsg.h"
#include "logMsg/traceLevels.h"

#include "common/globals.h"
#include "common/tag.h"
#include "ngsi/ContextAttribute.h"

/* ****************************************************************************
*
* ContextAttribute::ContextAttribute -
*/
ContextAttribute::ContextAttribute()
{
   name  = "";
   type  = "";
   value = "";
}

/* ****************************************************************************
*
* ContextAttribute::ContextAttribute -
*/
ContextAttribute::ContextAttribute(ContextAttribute* caP)
{
   LM_T(LmtClone, ("'cloning' a ContextAttribute"));
   name  = caP->name;
   type  = caP->type;
   value = caP->value;

   metadataVector.vec.clear();

   for (unsigned int mIx = 0; mIx < caP->metadataVector.size(); ++mIx)
   {
      LM_T(LmtClone, ("Copying metadata %d", mIx));
      Metadata* mP = new Metadata(caP->metadataVector.get(mIx));
      metadataVector.push_back(mP);
   }
}

/* ****************************************************************************
*
* ContextAttribute::ContextAttribute -
*/
ContextAttribute::ContextAttribute(std::string _name, std::string _type, std::string _value)
{
   name  = _name;
   type  = _type;
   value = _value;
}

/* ****************************************************************************
*
* ContextAttribute::getId() -
*/
std::string ContextAttribute::getId()
{
  for (unsigned int ix = 0; ix < metadataVector.size(); ++ix) {
      if (metadataVector.get(ix)->name == NGSI_MD_ID) {
          return metadataVector.get(ix)->value;
      }
  }
  return "";
}

/* ****************************************************************************
*
* render -
*/
std::string ContextAttribute::render(Format format, std::string indent, bool comma)
{
  std::string  out                    = "";
  std::string  xmlTag                 = "contextAttribute";
  std::string  jsonTag                = "attribute";
  bool         commaAfterContextValue = metadataVector.size() != 0;

  metadataVector.tagSet("metadata");

  //
  // About JSON commas:
  // contextValue is MANDATORY, so up to that field, all will wear the JSON comma
  // contextValue itself has a comma if metadataVector is rendered
  //
  out += startTag(indent, xmlTag, jsonTag, format, false, false);
  out += valueTag(indent + "  ", "name",         name,  format, true);
  out += valueTag(indent + "  ", "type",         type,  format, true);
  out += valueTag(indent + "  ", ((format == XML)? "contextValue" : "value"), value, format, commaAfterContextValue);
  out += metadataVector.render(format, indent + "  ", false);
  out += endTag(indent, xmlTag, format, comma);

  return out;
}

/* ****************************************************************************
*
* ContextAttribute::check -
*/
std::string ContextAttribute::check(RequestType requestType, Format format, std::string indent, std::string predetectedError, int counter)
{
  if ((name == "") || (name == "not in use"))
    return "missing attribute name";

  if (requestType != UpdateContext) // FIXME: this is just to make harness test work
  {
    if ((value == "") || (value == "not in use"))
      return "missing attribute value";
  }

  return "OK";
}

/* ****************************************************************************
*
* ContextAttribute::present -
*/
void ContextAttribute::present(std::string indent, int ix)
{
  PRINTF("%sAttribute %d:\n",    indent.c_str(), ix);
  PRINTF("%s  Name:       %s\n", indent.c_str(), name.c_str());
  PRINTF("%s  Type:       %s\n", indent.c_str(), type.c_str());
  PRINTF("%s  Value:      %s\n", indent.c_str(), value.c_str());

  metadataVector.present("Attribute", indent + "  ");
}

/* ****************************************************************************
*
* ContextAttribute::release -
*/
void ContextAttribute::release(void)
{
  metadataVector.release();
}

/* ****************************************************************************
*
* toString -
*/
std::string ContextAttribute::toString(void)
{
  return name;
}
<|endoftext|>


<commit_before>// l1_fused_dot.cpp: example program showing a fused-dot product for error free linear algebra
//
// Copyright (C) 2017-2018 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
#include "common.hpp"
// enable the following define to show the intermediate steps in the fused-dot product
// #define POSIT_VERBOSE_OUTPUT
#define POSIT_TRACE_MUL
#define QUIRE_TRACE_ADD
// enable posit arithmetic exceptions
#define POSIT_THROW_ARITHMETIC_EXCEPTION 1
#include <posit>
#include "blas_operators.hpp"

template<typename Ty>
Ty minValue(const std::vector<Ty>& samples) {
	typename std::vector<Ty>::const_iterator it = min_element(samples.begin(), samples.end());
	return *it;
}
template<typename Ty>
Ty maxValue(const std::vector<Ty>& samples) {
	typename std::vector<Ty>::const_iterator it = max_element(samples.begin(), samples.end());
	return *it;
}

int main(int argc, char** argv)
try {
	using namespace std;
	using namespace sw::unum;

	//constexpr size_t nbits = 16;
	//constexpr size_t es = 1;
	//constexpr size_t capacity = 6;   // 2^3 accumulations of maxpos^2
	//constexpr size_t vecSizePwr = 5;
	//constexpr size_t vecSize = (size_t(1) << vecSizePwr);

	// generate an interesting vector x with 0.5 ULP round-off errors in each product
	// that the fused-dot product will be able to resolve
	// by progressively adding smaller values, a regular dot product loses these bits due to canceleation.
	// but a fused dot product leveraging a quire will be able to resolve these.
	//float eps      = std::numeric_limits<float>::epsilon();
	//float epsminus = 1.0f - eps;
	//float epsplus  = 1.0f + eps;

	{
		using IEEEType = float;
		IEEEType a1 = 3.2e8, a2 = 1, a3 = -1, a4 = 8e7;
		IEEEType b1 = 4.0e7, b2 = 1, b3 = -1, b4 = -1.6e8;
		vector<IEEEType> xieee = { a1, a2, a3, a4 };
		vector<IEEEType> yieee = { b1, b2, b3, b4 };

		printVector(cout, "a: ", xieee);
		printVector(cout, "b: ", yieee);

		cout << endl << endl;

		cout << setprecision(17);
		cout << "IEEE float   BLAS dot(x,y)  : " << dot(xieee.size(), xieee, 1, yieee, 1) << endl;
		cout << setprecision(5);
	}

	{
		using IEEEType = double;
		IEEEType a1 = 3.2e8, a2 = 1, a3 = -1, a4 = 8e7;
		IEEEType b1 = 4.0e7, b2 = 1, b3 = -1, b4 = -1.6e8;
		vector<IEEEType> xieee = { a1, a2, a3, a4 };
		vector<IEEEType> yieee = { b1, b2, b3, b4 };

		cout << setprecision(17);
		cout << "IEEE double  BLAS dot(x,y)  : " << dot(xieee.size(), xieee, 1, yieee, 1) << endl;
		cout << setprecision(5);
	}

	{
		// a little verbose but enabling different precisions to be injected
		// float, double, long double
		// so that you can convince yourself that this is a property of posits and quires
		// and not some input precision shenanigans. The magic is all in the quire
		// accumulating UNROUNDED multiplies: that gives you in affect double the
		// fraction bits.
		using IEEEType = float;
		IEEEType a1 = 3.2e8, a2 = 1, a3 = -1, a4 = 8e7;
		IEEEType b1 = 4.0e7, b2 = 1, b3 = -1, b4 = -1.6e8;

		using PositType = posit<32, 2>;
		vector<PositType> xposit = { a1, a2, a3, a4 };
		vector<PositType> yposit = { b1, b2, b3, b4 };

		cout << "posit<32,2> fused dot(x,y)  : " << fused_dot(xposit.size(), xposit, 1, yposit, 1) << "           <----- correct answer is 2" << endl;
		cout << setprecision(5);
	}

	return EXIT_SUCCESS;
}
catch (char const* msg) {
	std::cerr << msg << std::endl;
	return EXIT_FAILURE;
}
catch (const posit_arithmetic_exception& err) {
	std::cerr << "Uncaught posit arithmetic exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const quire_exception& err) {
	std::cerr << "Uncaught quire exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const posit_internal_exception& err) {
	std::cerr << "Uncaught posit internal exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const std::runtime_error& err) {
	std::cerr << "Uncaught runtime exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "Caught unknown exception" << std::endl;
	return EXIT_FAILURE;
}
<commit_msg>Embellishing the fused dot produce example<commit_after>// l1_fused_dot.cpp: example program showing a fused-dot product for error free linear algebra
//
// Copyright (C) 2017-2018 Stillwater Supercomputing, Inc.
//
// This file is part of the universal numbers project, which is released under an MIT Open Source license.
#include "common.hpp"
// enable the following define to show the intermediate steps in the fused-dot product
// #define POSIT_VERBOSE_OUTPUT
#define POSIT_TRACE_MUL
#define QUIRE_TRACE_ADD
// enable posit arithmetic exceptions
#define POSIT_THROW_ARITHMETIC_EXCEPTION 1
#include <posit>
#include "blas_operators.hpp"

template<typename Ty>
Ty minValue(const std::vector<Ty>& samples) {
	typename std::vector<Ty>::const_iterator it = min_element(samples.begin(), samples.end());
	return *it;
}
template<typename Ty>
Ty maxValue(const std::vector<Ty>& samples) {
	typename std::vector<Ty>::const_iterator it = max_element(samples.begin(), samples.end());
	return *it;
}

int main(int argc, char** argv)
try {
	using namespace std;
	using namespace sw::unum;

	//constexpr size_t nbits = 16;
	//constexpr size_t es = 1;
	//constexpr size_t capacity = 6;   // 2^3 accumulations of maxpos^2
	//constexpr size_t vecSizePwr = 5;
	//constexpr size_t vecSize = (size_t(1) << vecSizePwr);

	// generate an interesting vector x with 0.5 ULP round-off errors in each product
	// that the fused-dot product will be able to resolve
	// by progressively adding smaller values, a regular dot product loses these bits due to canceleation.
	// but a fused dot product leveraging a quire will be able to resolve these.
	//float eps      = std::numeric_limits<float>::epsilon();
	//float epsminus = 1.0f - eps;
	//float epsplus  = 1.0f + eps;

	std::streamsize prec = cout.precision();
	cout << setprecision(17);

	{
		using IEEEType = float;
		IEEEType a1 = 3.2e8, a2 = 1, a3 = -1, a4 = 8e7;
		IEEEType b1 = 4.0e7, b2 = 1, b3 = -1, b4 = -1.6e8;
		vector<IEEEType> xieee = { a1, a2, a3, a4 };
		vector<IEEEType> yieee = { b1, b2, b3, b4 };

		printVector(cout, "a: ", xieee);
		printVector(cout, "b: ", yieee);

		cout << endl << endl;
		cout << "IEEE float   BLAS dot(x,y)  : " << dot(xieee.size(), xieee, 1, yieee, 1) << "           <----- correct answer is 2" << endl;
	}

	{
		using IEEEType = double;
		IEEEType a1 = 3.2e8, a2 = 1, a3 = -1, a4 = 8e7;
		IEEEType b1 = 4.0e7, b2 = 1, b3 = -1, b4 = -1.6e8;
		vector<IEEEType> xieee = { a1, a2, a3, a4 };
		vector<IEEEType> yieee = { b1, b2, b3, b4 };

		cout << "IEEE double  BLAS dot(x,y)  : " << dot(xieee.size(), xieee, 1, yieee, 1) << "           <----- correct answer is 2" << endl;
	}

	{
		// a little verbose but enabling different precisions to be injected
		// float, double, long double
		// so that you can convince yourself that this is a property of posits and quires
		// and not some input precision shenanigans. The magic is all in the quire
		// accumulating UNROUNDED multiplies: that gives you in affect double the
		// fraction bits.
		using IEEEType = float;
		IEEEType a1 = 3.2e8, a2 = 1, a3 = -1, a4 = 8e7;
		IEEEType b1 = 4.0e7, b2 = 1, b3 = -1, b4 = -1.6e8;

		{
			using PositType = posit<8, 3>;
			vector<PositType> xposit = { a1, a2, a3, a4 };
			vector<PositType> yposit = { b1, b2, b3, b4 };

			cout << "posit< 8,3> fused dot(x,y)  : " << fused_dot(xposit.size(), xposit, 1, yposit, 1) << "           <----- correct answer is 2" << endl;
		}
		{
			using PositType = posit<16, 2>;
			vector<PositType> xposit = { a1, a2, a3, a4 };
			vector<PositType> yposit = { b1, b2, b3, b4 };

			cout << "posit<16,2> fused dot(x,y)  : " << fused_dot(xposit.size(), xposit, 1, yposit, 1) << "           <----- correct answer is 2" << endl;
		}
		{
			using PositType = posit<32, 2>;
			vector<PositType> xposit = { a1, a2, a3, a4 };
			vector<PositType> yposit = { b1, b2, b3, b4 };

			cout << "posit<32,2> fused dot(x,y)  : " << fused_dot(xposit.size(), xposit, 1, yposit, 1) << "           <----- correct answer is 2" << endl;
		}
		{
			using PositType = posit<64, 1>;
			vector<PositType> xposit = { a1, a2, a3, a4 };
			vector<PositType> yposit = { b1, b2, b3, b4 };

			cout << "posit<64,1> fused dot(x,y)  : " << fused_dot(xposit.size(), xposit, 1, yposit, 1) << "           <----- correct answer is 2" << endl;
		}
		{
			using PositType = posit<64, 0>;
			vector<PositType> xposit = { a1, a2, a3, a4 };
			vector<PositType> yposit = { b1, b2, b3, b4 };

			cout << "posit<64,0> fused dot(x,y)  : " << fused_dot(xposit.size(), xposit, 1, yposit, 1) << "           <----- correct answer is 2" << endl;
		}

		{
			using PositType = posit<16, 1>;
			vector<PositType> xposit = { a1, a2, a3, a4 };
			vector<PositType> yposit = { b1, b2, b3, b4 };

			cout << "posit<16,1> fused dot(x,y)  : " << fused_dot(xposit.size(), xposit, 1, yposit, 1) << "           <----- correct answer is 2" << endl;
		}
		{
			using PositType = posit<32, 1>;
			vector<PositType> xposit = { a1, a2, a3, a4 };
			vector<PositType> yposit = { b1, b2, b3, b4 };

			cout << "posit<32,1> fused dot(x,y)  : " << fused_dot(xposit.size(), xposit, 1, yposit, 1) << "           <----- correct answer is 2" << endl;
		}

		cout << setprecision(prec);
	}

	return EXIT_SUCCESS;
}
catch (char const* msg) {
	std::cerr << msg << std::endl;
	return EXIT_FAILURE;
}
catch (const posit_arithmetic_exception& err) {
	std::cerr << "Uncaught posit arithmetic exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const quire_exception& err) {
	std::cerr << "Uncaught quire exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const posit_internal_exception& err) {
	std::cerr << "Uncaught posit internal exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (const std::runtime_error& err) {
	std::cerr << "Uncaught runtime exception: " << err.what() << std::endl;
	return EXIT_FAILURE;
}
catch (...) {
	std::cerr << "Caught unknown exception" << std::endl;
	return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>#include "default_verbs.hpp"
#include "continuation.hpp"
#include "executor.hpp"
#include "restart_exception.hpp"
#include "suspend_exception.hpp"
#include "sleep_record.hpp"
#include "utility/enum_hash.hpp"
#include <unordered_map>
#include <random>

using namespace gorc;
using namespace gorc::cog;

namespace {

    std::default_random_engine rng((std::random_device())());

    std::unordered_map<gorc::cog::value_type,
                       int,
                       gorc::enum_hash<gorc::cog::value_type>> value_type_message_type_map {
        { gorc::cog::value_type::nothing, 0 },
        { gorc::cog::value_type::sector, 5 },
        { gorc::cog::value_type::surface, 6 },
        { gorc::cog::value_type::thing, 3 },
        { gorc::cog::value_type::cog, 9 }
    };

    int value_type_to_message_thing_type(gorc::cog::value_type vt)
    {
        auto it = value_type_message_type_map.find(vt);
        if(it == value_type_message_type_map.end()) {
            LOG_WARNING(gorc::format("extracted type number from unmapped type %s") %
                        gorc::cog::as_string(vt));
            return 1;
        }

        return it->second;
    }

    void add_system_verbs(verb_table &verbs)
    {
        class returnex_verb : public cog::verb {
        public:
            returnex_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { value_type::dynamic })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &stk, service_registry &sr, bool) const override
            {
                auto &cc = sr.get<continuation>();
                cc.frame().return_register = stk.back();
                stk.pop_back();

                return value();
            }
        };

        verbs.emplace_verb<returnex_verb>("returnex");

        class getparam_verb : public cog::verb {
        public:
            getparam_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { value_type::integer })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &stk, service_registry &sr, bool) const override
            {
                auto &cc = sr.get<continuation>();
                int param_num = stk.back();
                stk.pop_back();

                switch(param_num) {
                case 0:
                    return cc.frame().param0;
                case 1:
                    return cc.frame().param1;
                case 2:
                    return cc.frame().param2;
                case 3:
                    return cc.frame().param3;
                default:
                    LOG_ERROR(format("getparam number %d is out of bounds") % param_num);
                    return value();
                }
            }
        };

        verbs.emplace_verb<getparam_verb>("getparam");

        class getsenderid_verb : public cog::verb {
        public:
            getsenderid_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &, service_registry &sr, bool) const override
            {
                return sr.get<continuation>().frame().sender_id;
            }
        };

        verbs.emplace_verb<getsenderid_verb>("getsenderid");

        class getsenderref_verb : public cog::verb {
        public:
            getsenderref_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &, service_registry &sr, bool) const override
            {
                return sr.get<continuation>().frame().sender;
            }
        };

        verbs.emplace_verb<getsenderref_verb>("getsenderref");

        class getsendertype_verb : public cog::verb {
        public:
            getsendertype_verb(std::string const &name)
                : verb(name,
                       value_type::integer,
                       std::vector<value_type> { })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &, service_registry &sr, bool) const override
            {
                return value_type_to_message_thing_type(
                    sr.get<continuation>().frame().sender.get_type());
            }
        };

        verbs.emplace_verb<getsendertype_verb>("getsendertype");

        class getsourceref_verb : public cog::verb {
        public:
            getsourceref_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &, service_registry &sr, bool) const override
            {
                return sr.get<continuation>().frame().source;
            }
        };

        verbs.emplace_verb<getsourceref_verb>("getsourceref");

        class getsourcetype_verb : public cog::verb {
        public:
            getsourcetype_verb(std::string const &name)
                : verb(name,
                       value_type::integer,
                       std::vector<value_type> { })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &, service_registry &sr, bool) const override
            {
                return value_type_to_message_thing_type(
                    sr.get<continuation>().frame().source.get_type());
            }
        };

        verbs.emplace_verb<getsourcetype_verb>("getsourcetype");

        verbs.add_service_verb("sleep", [](bool expects_value,
                                           service_registry const &sr,
                                           float time) {
                auto &cc = sr.get<continuation>();
                auto &exec = sr.get<executor>();

                if(expects_value) {
                    // The void return value from this verb is used.
                    // Poorly written script, but the missing value will cause problems.
                    cc.data_stack.push_back(value());
                }

                exec.add_sleep_record(std::make_unique<sleep_record>(continuation(cc),
                                                                     time_delta(time)));
                throw suspend_exception();
            });

        class sendmessageex_verb : public cog::verb {
        public:
            sendmessageex_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { value_type::cog,
                                                 value_type::message,
                                                 value_type::dynamic,
                                                 value_type::dynamic,
                                                 value_type::dynamic,
                                                 value_type::dynamic })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &stk, service_registry &sr, bool ev) const override
            {
                value param3 = stk.back();
                stk.pop_back();

                value param2 = stk.back();
                stk.pop_back();

                value param1 = stk.back();
                stk.pop_back();

                value param0 = stk.back();
                stk.pop_back();

                message_id mid = stk.back();
                message_type msg = static_cast<message_type>(static_cast<int>(mid));
                stk.pop_back();

                cog_id cog = stk.back();
                stk.pop_back();

                auto &cc = sr.get<continuation>();
                auto &exec = sr.get<executor>();

                auto frame = exec.create_message_frame(cog,
                                                       msg,
                                                       /* sender */ cc.frame().instance_id,
                                                       /* TODO: senderid */ value(),
                                                       /* TODO: source */ value(),
                                                       param0,
                                                       param1,
                                                       param2,
                                                       param3);
                if(!frame.has_value()) {
                    // Warning has already been logged
                    return value();
                }

                auto &real_frame = frame.get_value();
                real_frame.save_return_register = false;
                real_frame.push_return_register = ev;

                cc.call_stack.push_back(real_frame);

                throw restart_exception();
            }
        };

        verbs.emplace_verb<sendmessageex_verb>("sendmessageex");

        class sendmessage_verb : public cog::verb {
        public:
            sendmessage_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { value_type::cog,
                                                 value_type::message })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &stk, service_registry &sr, bool ev) const override
            {
                message_id mid = stk.back();
                message_type msg = static_cast<message_type>(static_cast<int>(mid));
                stk.pop_back();

                cog_id cog = stk.back();
                stk.pop_back();

                auto &cc = sr.get<continuation>();
                auto &exec = sr.get<executor>();

                auto frame = exec.create_message_frame(cog,
                                                       msg,
                                                       /* sender */ cc.frame().instance_id,
                                                       /* TODO: senderid */ value(),
                                                       /* TODO: source */ value(),
                                                       value(),
                                                       value(),
                                                       value(),
                                                       value());
                if(!frame.has_value()) {
                    // Warning has already been logged
                    return value();
                }

                auto &real_frame = frame.get_value();
                real_frame.save_return_register = false;
                real_frame.push_return_register = ev;

                cc.call_stack.push_back(real_frame);

                throw restart_exception();
            }
        };

        verbs.emplace_verb<sendmessage_verb>("sendmessage");

        return;
    }

    void add_math_verbs(verb_table &verbs)
    {
        verbs.add_verb("bitclear", [](int flag, int clear_flags) {
                return flag & ~clear_flags;
            });

        verbs.add_verb("bitset", [](int flag, int set_flags) {
                return flag | set_flags;
            });

        verbs.add_verb("bittest", [](int a, int b) {
                return a & b;
            });

        verbs.add_verb("rand", []() {
                return std::generate_canonical<float, 10>(rng);
            });

        verbs.add_verb("randvec", []() {
                auto vec = make_vector(std::generate_canonical<float, 10>(rng),
                                       std::generate_canonical<float, 10>(rng),
                                       std::generate_canonical<float, 10>(rng));
                vec *= 2.0f;
                vec -= make_vector(1.0f, 1.0f, 1.0f);
                return vec;
            });

        verbs.add_verb("vectorx", [](vector<3> a) {
                return get<0>(a);
            });

        verbs.add_verb("vectory", [](vector<3> a) {
                return get<1>(a);
            });

        verbs.add_verb("vectorz", [](vector<3> a) {
                return get<2>(a);
            });

        verbs.add_verb("vectorset", [](float x, float y, float z) {
                return make_vector(x, y, z);
            });

        verbs.add_verb("vectoradd", [](vector<3> a, vector<3> b) {
                return a + b;
            });

        verbs.add_verb("vectorsub", [](vector<3> a, vector<3> b) {
                return a - b;
            });

        verbs.add_verb("vectorscale", [](vector<3> a, float c) {
                return a * c;
            });

        verbs.add_verb("vectorlen", [](vector<3> a) {
                return length(a);
            });

        verbs.add_verb("vectordist", [](vector<3> a, vector<3> b) {
                return length(a - b);
            });

        verbs.add_verb("vectornorm", [](vector<3> a) {
                return normalize(a);
            });

        verbs.add_verb("vectordot", [](vector<3> a, vector<3> b) {
                return dot(a, b);
            });

        verbs.add_verb("vectorcross", [](vector<3> a, vector<3> b) {
                return cross(a, b);
            });
    }
}

void gorc::cog::default_populate_verb_table(verb_table &verbs)
{
    add_system_verbs(verbs);
    add_math_verbs(verbs);
}
<commit_msg>Added getselfcog verb<commit_after>#include "default_verbs.hpp"
#include "continuation.hpp"
#include "executor.hpp"
#include "restart_exception.hpp"
#include "suspend_exception.hpp"
#include "sleep_record.hpp"
#include "utility/enum_hash.hpp"
#include <unordered_map>
#include <random>

using namespace gorc;
using namespace gorc::cog;

namespace {

    std::default_random_engine rng((std::random_device())());

    std::unordered_map<gorc::cog::value_type,
                       int,
                       gorc::enum_hash<gorc::cog::value_type>> value_type_message_type_map {
        { gorc::cog::value_type::nothing, 0 },
        { gorc::cog::value_type::sector, 5 },
        { gorc::cog::value_type::surface, 6 },
        { gorc::cog::value_type::thing, 3 },
        { gorc::cog::value_type::cog, 9 }
    };

    int value_type_to_message_thing_type(gorc::cog::value_type vt)
    {
        auto it = value_type_message_type_map.find(vt);
        if(it == value_type_message_type_map.end()) {
            LOG_WARNING(gorc::format("extracted type number from unmapped type %s") %
                        gorc::cog::as_string(vt));
            return 1;
        }

        return it->second;
    }

    void add_system_verbs(verb_table &verbs)
    {
        class returnex_verb : public cog::verb {
        public:
            returnex_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { value_type::dynamic })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &stk, service_registry &sr, bool) const override
            {
                auto &cc = sr.get<continuation>();
                cc.frame().return_register = stk.back();
                stk.pop_back();

                return value();
            }
        };

        verbs.emplace_verb<returnex_verb>("returnex");

        class getparam_verb : public cog::verb {
        public:
            getparam_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { value_type::integer })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &stk, service_registry &sr, bool) const override
            {
                auto &cc = sr.get<continuation>();
                int param_num = stk.back();
                stk.pop_back();

                switch(param_num) {
                case 0:
                    return cc.frame().param0;
                case 1:
                    return cc.frame().param1;
                case 2:
                    return cc.frame().param2;
                case 3:
                    return cc.frame().param3;
                default:
                    LOG_ERROR(format("getparam number %d is out of bounds") % param_num);
                    return value();
                }
            }
        };

        verbs.emplace_verb<getparam_verb>("getparam");

        class getsenderid_verb : public cog::verb {
        public:
            getsenderid_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &, service_registry &sr, bool) const override
            {
                return sr.get<continuation>().frame().sender_id;
            }
        };

        verbs.emplace_verb<getsenderid_verb>("getsenderid");

        class getsenderref_verb : public cog::verb {
        public:
            getsenderref_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &, service_registry &sr, bool) const override
            {
                return sr.get<continuation>().frame().sender;
            }
        };

        verbs.emplace_verb<getsenderref_verb>("getsenderref");

        class getsendertype_verb : public cog::verb {
        public:
            getsendertype_verb(std::string const &name)
                : verb(name,
                       value_type::integer,
                       std::vector<value_type> { })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &, service_registry &sr, bool) const override
            {
                return value_type_to_message_thing_type(
                    sr.get<continuation>().frame().sender.get_type());
            }
        };

        verbs.emplace_verb<getsendertype_verb>("getsendertype");

        class getsourceref_verb : public cog::verb {
        public:
            getsourceref_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &, service_registry &sr, bool) const override
            {
                return sr.get<continuation>().frame().source;
            }
        };

        verbs.emplace_verb<getsourceref_verb>("getsourceref");

        class getsourcetype_verb : public cog::verb {
        public:
            getsourcetype_verb(std::string const &name)
                : verb(name,
                       value_type::integer,
                       std::vector<value_type> { })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &, service_registry &sr, bool) const override
            {
                return value_type_to_message_thing_type(
                    sr.get<continuation>().frame().source.get_type());
            }
        };

        verbs.emplace_verb<getsourcetype_verb>("getsourcetype");

        verbs.add_service_verb("sleep", [](bool expects_value,
                                           service_registry const &sr,
                                           float time) {
                auto &cc = sr.get<continuation>();
                auto &exec = sr.get<executor>();

                if(expects_value) {
                    // The void return value from this verb is used.
                    // Poorly written script, but the missing value will cause problems.
                    cc.data_stack.push_back(value());
                }

                exec.add_sleep_record(std::make_unique<sleep_record>(continuation(cc),
                                                                     time_delta(time)));
                throw suspend_exception();
            });

        class sendmessageex_verb : public cog::verb {
        public:
            sendmessageex_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { value_type::cog,
                                                 value_type::message,
                                                 value_type::dynamic,
                                                 value_type::dynamic,
                                                 value_type::dynamic,
                                                 value_type::dynamic })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &stk, service_registry &sr, bool ev) const override
            {
                value param3 = stk.back();
                stk.pop_back();

                value param2 = stk.back();
                stk.pop_back();

                value param1 = stk.back();
                stk.pop_back();

                value param0 = stk.back();
                stk.pop_back();

                message_id mid = stk.back();
                message_type msg = static_cast<message_type>(static_cast<int>(mid));
                stk.pop_back();

                cog_id cog = stk.back();
                stk.pop_back();

                auto &cc = sr.get<continuation>();
                auto &exec = sr.get<executor>();

                auto frame = exec.create_message_frame(cog,
                                                       msg,
                                                       /* sender */ cc.frame().instance_id,
                                                       /* TODO: senderid */ value(),
                                                       /* TODO: source */ value(),
                                                       param0,
                                                       param1,
                                                       param2,
                                                       param3);
                if(!frame.has_value()) {
                    // Warning has already been logged
                    return value();
                }

                auto &real_frame = frame.get_value();
                real_frame.save_return_register = false;
                real_frame.push_return_register = ev;

                cc.call_stack.push_back(real_frame);

                throw restart_exception();
            }
        };

        verbs.emplace_verb<sendmessageex_verb>("sendmessageex");

        class sendmessage_verb : public cog::verb {
        public:
            sendmessage_verb(std::string const &name)
                : verb(name,
                       value_type::dynamic,
                       std::vector<value_type> { value_type::cog,
                                                 value_type::message })
            {
                return;
            }

            virtual cog::value invoke(cog::stack &stk, service_registry &sr, bool ev) const override
            {
                message_id mid = stk.back();
                message_type msg = static_cast<message_type>(static_cast<int>(mid));
                stk.pop_back();

                cog_id cog = stk.back();
                stk.pop_back();

                auto &cc = sr.get<continuation>();
                auto &exec = sr.get<executor>();

                auto frame = exec.create_message_frame(cog,
                                                       msg,
                                                       /* sender */ cc.frame().instance_id,
                                                       /* TODO: senderid */ value(),
                                                       /* TODO: source */ value(),
                                                       value(),
                                                       value(),
                                                       value(),
                                                       value());
                if(!frame.has_value()) {
                    // Warning has already been logged
                    return value();
                }

                auto &real_frame = frame.get_value();
                real_frame.save_return_register = false;
                real_frame.push_return_register = ev;

                cc.call_stack.push_back(real_frame);

                throw restart_exception();
            }
        };

        verbs.emplace_verb<sendmessage_verb>("sendmessage");

        verbs.add_service_verb("getselfcog", [](bool,
                                                service_registry const &sr) {
                auto &cc = sr.get<continuation>();
                return cc.frame().instance_id;
            });

        return;
    }

    void add_math_verbs(verb_table &verbs)
    {
        verbs.add_verb("bitclear", [](int flag, int clear_flags) {
                return flag & ~clear_flags;
            });

        verbs.add_verb("bitset", [](int flag, int set_flags) {
                return flag | set_flags;
            });

        verbs.add_verb("bittest", [](int a, int b) {
                return a & b;
            });

        verbs.add_verb("rand", []() {
                return std::generate_canonical<float, 10>(rng);
            });

        verbs.add_verb("randvec", []() {
                auto vec = make_vector(std::generate_canonical<float, 10>(rng),
                                       std::generate_canonical<float, 10>(rng),
                                       std::generate_canonical<float, 10>(rng));
                vec *= 2.0f;
                vec -= make_vector(1.0f, 1.0f, 1.0f);
                return vec;
            });

        verbs.add_verb("vectorx", [](vector<3> a) {
                return get<0>(a);
            });

        verbs.add_verb("vectory", [](vector<3> a) {
                return get<1>(a);
            });

        verbs.add_verb("vectorz", [](vector<3> a) {
                return get<2>(a);
            });

        verbs.add_verb("vectorset", [](float x, float y, float z) {
                return make_vector(x, y, z);
            });

        verbs.add_verb("vectoradd", [](vector<3> a, vector<3> b) {
                return a + b;
            });

        verbs.add_verb("vectorsub", [](vector<3> a, vector<3> b) {
                return a - b;
            });

        verbs.add_verb("vectorscale", [](vector<3> a, float c) {
                return a * c;
            });

        verbs.add_verb("vectorlen", [](vector<3> a) {
                return length(a);
            });

        verbs.add_verb("vectordist", [](vector<3> a, vector<3> b) {
                return length(a - b);
            });

        verbs.add_verb("vectornorm", [](vector<3> a) {
                return normalize(a);
            });

        verbs.add_verb("vectordot", [](vector<3> a, vector<3> b) {
                return dot(a, b);
            });

        verbs.add_verb("vectorcross", [](vector<3> a, vector<3> b) {
                return cross(a, b);
            });
    }
}

void gorc::cog::default_populate_verb_table(verb_table &verbs)
{
    add_system_verbs(verbs);
    add_math_verbs(verbs);
}
<|endoftext|>


<commit_before>#include <specreader.hpp>

#include <backendbuilder.hpp>

#include <helper/keyhelper.hpp>

#include "../../../tools/kdb/command.hpp"
#include <unordered_set>

namespace kdb
{

namespace tools
{

SpecBackendBuilder::SpecBackendBuilder (BackendBuilderInit const & bbi) : MountBackendBuilder (bbi), nodes (0)
{
}

SpecReader::SpecReader (BackendBuilderInit const & abbi) : bbi (abbi)
{
}

SpecReader::~SpecReader ()
{
}

class SpecMountpointReader
{
private:
	KeySet ks;
	Key mp;
	KeySet backendConfig;
	KeySet mountConf;
	typedef std::unordered_map<Key, SpecBackendBuilder> Backends;
	Backends & backends;
	BackendBuilderInit const & bbi;
	SpecBackendBuilder bb;

public:
	SpecMountpointReader (Backends & b, BackendBuilderInit const & bbi_) : backends (b), bbi (bbi_), bb (bbi)
	{
	}

	void processKey (Key const & ck);
	SpecBackendBuilder readMountpointSpecification (KeySet const & cks);
};

namespace
{
bool startsWith (std::string const & str, std::string const & start)
{
	if (str.length () < start.length ())
	{
		return false;
	}
	return std::equal (start.begin (), start.end (), str.begin ());
}

bool isToBeIgnored (std::string const & metaName)
{
	const auto & name = metaName.substr (sizeof ("meta:/") - 1);
	// TODO: read from METADATA.ini
	return startsWith (name, "infos") || startsWith (name, "exports") || startsWith (name, "constants") ||
	       startsWith (name, "exports") ||

	       // spec-plugin
	       startsWith (name, "conflict") || startsWith (name, "require") || startsWith (name, "array") ||

	       startsWith (name, "fallback") || startsWith (name, "override") || startsWith (name, "namespace") || name == "default" ||
	       name == "context" ||

	       // always ignore stuff internal to plugins
	       startsWith (name, "internal") ||

	       startsWith (name, "callback") ||

	       startsWith (name, "binary") ||

	       // elektraGetOpts
	       startsWith (name, "opt") || startsWith (name, "args") || startsWith (name, "env") || startsWith (name, "command") ||

	       // code generator
	       startsWith (name, "gen") ||

	       // docu
	       startsWith (name, "comment") || startsWith (name, "description") || startsWith (name, "see") ||
	       startsWith (name, "rationale") || startsWith (name, "example") ||

	       name == "mountpoint" || startsWith (name, "config");
}
} // namespace

void SpecMountpointReader::processKey (Key const & ck)
{
	Key k (ck);
	k.rewindMeta ();
	Key m;
	while ((m = k.nextMeta ()))
	{
		std::string const & cn = "meta:/config/needs";
		if (startsWith (m.getName (), cn))
		{
			Key bKey = m.dup ();
			bKey.setName ("user:" + bKey.getName ().substr (cn.length ()));
			backendConfig.append (bKey);
		}
		else if (m.getName () == "meta:/infos/plugins")
		{
			bb.addPlugins (parseArguments (m.getString ()));
		}
		else if (m.getName () == "meta:/infos/needs")
		{
			bb.needPlugin (m.getString ());
		}
		else if (m.getName () == "meta:/infos/recommends")
		{
			bb.recommendPlugin (m.getString ());
		}
		else if (isToBeIgnored (m.getName ()))
		{
		}
		else
		{
			bb.needMetadata (m.getName ());
		}
	}
}

SpecBackendBuilder SpecMountpointReader::readMountpointSpecification (KeySet const & cks)
{
	ks = cks;
	mp = ks.head ().dup ();

	Key rmp (mp.dup ());
	helper::removeNamespace (rmp);

	bb.setMountpoint (rmp, mountConf);

	processKey (mp);
	bb.nodes++; // count mp

	ks.lookup (mp, KDB_O_POP);

	ks.rewind (); // we need old fashioned loop, because it can handle ks.cut during iteration
	for (Key k = ks.next (); k; k = ks.next ())
	{
		// search for mountpoint
		Key m = k.getMeta<const Key> ("mountpoint");
		if (m)
		{
			SpecMountpointReader smr (backends, bbi);
			backends[k] = smr.readMountpointSpecification (ks.cut (k));
			continue;
		}

		processKey (k);
		bb.nodes++;
	}

	bb.setBackendConfig (backendConfig);
	bb.useConfigFile (mp.getMeta<std::string> ("mountpoint"));
	return bb;
}

void SpecReader::readSpecification (KeySet const & cks)
{
	KeySet ks;
	Key mp;

	// Filter keys and perform sanity checks.
	for (Key k : cks)
	{
		// Only include keys in spec namespace
		if (k.isSpec ())
		{
			ks.append (k);
		}
		checkKey(k);
	}

	ks.rewind (); // we need old fashioned loop, because it can handle ks.cut during iteration
	for (Key k = ks.next (); k; k = ks.next ())
	{
		// search for mountpoint
		Key m = k.getMeta<const Key> ("mountpoint");
		if (m)
		{
			SpecMountpointReader smr (backends, bbi);
			backends[k] = smr.readMountpointSpecification (ks.cut (k));
		}
	}
}

void SpecReader::checkKey(const Key key) {
	std::ostringstream stringStream;
	// Ensure that "check/enum" can only be used with type "enum"
	if (key.getMeta<std::string>("type") != "enum"
	    && key.hasMeta ("check/enum")) {
		stringStream << "Key " << key.getName() << " has \"type\"=\"" << key.getMeta<std::string>("type")														     << "\" and \"check/enum\". \"check/enum\" can only be used with \"type=enum\"!";
	}
	// Ensure that type and check/type are equal
	else if (key.hasMeta ("type") && key.hasMeta ("check/type")
		 && key.getMeta<std::string>("type") != key.getMeta<std::string> ("check/type")) {
			stringStream << "Key " << key.getName() << " has different values for \"type\" and \"check/type\". If both are specified, they must be equal!";
	}
	if (stringStream.str().length() > 0) {
		throw CommandAbortException(stringStream.str());
	}
}

} // namespace tools
} // namespace kdb
<commit_msg>Add check for unsupported type<commit_after>#include <specreader.hpp>

#include <backendbuilder.hpp>

#include <helper/keyhelper.hpp>

#include "../../../tools/kdb/command.hpp"
#include <unordered_set>

namespace kdb
{

namespace tools
{

const std::set<std::string> supportedTypes{
		"enum", "short", "unsigned_short", "long", "unsigned_long", "long_long", "unsigned_long_long", "float", "double",
		"long_double"
		"char",
		"boolean",
		"octet",
		"any", "string"
};

SpecBackendBuilder::SpecBackendBuilder (BackendBuilderInit const & bbi) : MountBackendBuilder (bbi), nodes (0)
{
}

SpecReader::SpecReader (BackendBuilderInit const & abbi) : bbi (abbi)
{
}

SpecReader::~SpecReader ()
{
}

class SpecMountpointReader
{
private:
	KeySet ks;
	Key mp;
	KeySet backendConfig;
	KeySet mountConf;
	typedef std::unordered_map<Key, SpecBackendBuilder> Backends;
	Backends & backends;
	BackendBuilderInit const & bbi;
	SpecBackendBuilder bb;

public:
	SpecMountpointReader (Backends & b, BackendBuilderInit const & bbi_) : backends (b), bbi (bbi_), bb (bbi)
	{
	}

	void processKey (Key const & ck);
	SpecBackendBuilder readMountpointSpecification (KeySet const & cks);
};

namespace
{
bool startsWith (std::string const & str, std::string const & start)
{
	if (str.length () < start.length ())
	{
		return false;
	}
	return std::equal (start.begin (), start.end (), str.begin ());
}

bool isToBeIgnored (std::string const & metaName)
{
	const auto & name = metaName.substr (sizeof ("meta:/") - 1);
	// TODO: read from METADATA.ini
	return startsWith (name, "infos") || startsWith (name, "exports") || startsWith (name, "constants") ||
	       startsWith (name, "exports") ||

	       // spec-plugin
	       startsWith (name, "conflict") || startsWith (name, "require") || startsWith (name, "array") ||

	       startsWith (name, "fallback") || startsWith (name, "override") || startsWith (name, "namespace") || name == "default" ||
	       name == "context" ||

	       // always ignore stuff internal to plugins
	       startsWith (name, "internal") ||

	       startsWith (name, "callback") ||

	       startsWith (name, "binary") ||

	       // elektraGetOpts
	       startsWith (name, "opt") || startsWith (name, "args") || startsWith (name, "env") || startsWith (name, "command") ||

	       // code generator
	       startsWith (name, "gen") ||

	       // docu
	       startsWith (name, "comment") || startsWith (name, "description") || startsWith (name, "see") ||
	       startsWith (name, "rationale") || startsWith (name, "example") ||

	       name == "mountpoint" || startsWith (name, "config");
}
} // namespace

void SpecMountpointReader::processKey (Key const & ck)
{
	Key k (ck);
	k.rewindMeta ();
	Key m;
	while ((m = k.nextMeta ()))
	{
		std::string const & cn = "meta:/config/needs";
		if (startsWith (m.getName (), cn))
		{
			Key bKey = m.dup ();
			bKey.setName ("user:" + bKey.getName ().substr (cn.length ()));
			backendConfig.append (bKey);
		}
		else if (m.getName () == "meta:/infos/plugins")
		{
			bb.addPlugins (parseArguments (m.getString ()));
		}
		else if (m.getName () == "meta:/infos/needs")
		{
			bb.needPlugin (m.getString ());
		}
		else if (m.getName () == "meta:/infos/recommends")
		{
			bb.recommendPlugin (m.getString ());
		}
		else if (isToBeIgnored (m.getName ()))
		{
		}
		else
		{
			bb.needMetadata (m.getName ());
		}
	}
}

SpecBackendBuilder SpecMountpointReader::readMountpointSpecification (KeySet const & cks)
{
	ks = cks;
	mp = ks.head ().dup ();

	Key rmp (mp.dup ());
	helper::removeNamespace (rmp);

	bb.setMountpoint (rmp, mountConf);

	processKey (mp);
	bb.nodes++; // count mp

	ks.lookup (mp, KDB_O_POP);

	ks.rewind (); // we need old fashioned loop, because it can handle ks.cut during iteration
	for (Key k = ks.next (); k; k = ks.next ())
	{
		// search for mountpoint
		Key m = k.getMeta<const Key> ("mountpoint");
		if (m)
		{
			SpecMountpointReader smr (backends, bbi);
			backends[k] = smr.readMountpointSpecification (ks.cut (k));
			continue;
		}

		processKey (k);
		bb.nodes++;
	}

	bb.setBackendConfig (backendConfig);
	bb.useConfigFile (mp.getMeta<std::string> ("mountpoint"));
	return bb;
}

void SpecReader::readSpecification (KeySet const & cks)
{
	KeySet ks;
	Key mp;

	// Filter keys and perform sanity checks.
	for (Key k : cks)
	{
		// Only include keys in spec namespace
		if (k.isSpec ())
		{
			ks.append (k);
		}
		checkKey(k);
	}

	ks.rewind (); // we need old fashioned loop, because it can handle ks.cut during iteration
	for (Key k = ks.next (); k; k = ks.next ())
	{
		// search for mountpoint
		Key m = k.getMeta<const Key> ("mountpoint");
		if (m)
		{
			SpecMountpointReader smr (backends, bbi);
			backends[k] = smr.readMountpointSpecification (ks.cut (k));
		}
	}
}

void SpecReader::checkKey(const Key key) {
	std::ostringstream stringStream;
	// Ensure that "check/enum" can only be used with type "enum"
	if (key.getMeta<std::string>("type") != "enum"
	    && key.hasMeta ("check/enum")) {
		stringStream << "Key " << key.getName() << " has \"type\"=\"" << key.getMeta<std::string>("type")														     << "\" and \"check/enum\". \"check/enum\" can only be used with \"type=enum\"!";
	}
	// Checks for "type" and "check/type" are equal
	else if (key.hasMeta ("type")) {
		std::string keyType = key.getMeta<std::string> ("type");
		// Check if "type" is supported
		if(std::find(supportedTypes.begin(), supportedTypes.end(), key.getMeta<std::string> ("type")) == supportedTypes.end()) {
			stringStream << "Type \"" << key.getMeta<std::string>("type") << "\" of key \"" << key.getName() << "\" is not supported in Elektra!";
		}
		// Check if "type" and "check/type" are equal
		else if (key.hasMeta ("check/type")
			 && key.getMeta<std::string> ("check/type") != keyType)
		{
			stringStream << "Key " << key.getName ()
				     << " has different values for \"type\" and \"check/type\". If both are specified, they must be equal!";
		}
	}
	if (stringStream.str().length() > 0) {
		throw CommandAbortException(stringStream.str());
	}
}

} // namespace tools
} // namespace kdb
<|endoftext|>


<commit_before>//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Defines the Static Analyzer Checker Manager.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/AST/DeclBase.h"

using namespace clang;
using namespace ento;

//===----------------------------------------------------------------------===//
// Functions for running checkers for AST traversing..
//===----------------------------------------------------------------------===//

void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
                                          BugReporter &BR) {
  assert(D);

  unsigned DeclKind = D->getKind();
  CachedDeclCheckers *checkers = 0;
  CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
  if (CCI != CachedDeclCheckersMap.end()) {
    checkers = &(CCI->second);
  } else {
    // Find the checkers that should run for this Decl and cache them.
    checkers = &CachedDeclCheckersMap[DeclKind];
    for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
      DeclCheckerInfo &info = DeclCheckers[i];
      if (info.IsForDeclFn(D))
        checkers->push_back(info.CheckFn);
    }
  }

  assert(checkers);
  for (CachedDeclCheckers::iterator
         I = checkers->begin(), E = checkers->end(); I != E; ++I)
    (*I)(D, mgr, BR);
}

void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
                                          BugReporter &BR) {
  assert(D && D->hasBody());

  for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
    BodyCheckers[i](D, mgr, BR);
}

//===----------------------------------------------------------------------===//
// Functions for running checkers for path-sensitive checking.
//===----------------------------------------------------------------------===//

template <typename CHECK_CTX>
static void runPathSensitiveCheckers(CHECK_CTX checkCtx,
                                     ExplodedNodeSet &Dst,
                                     ExplodedNodeSet &Src) {

  if (checkCtx.Checkers.empty()) {
    Dst.insert(Src);
    return;
  }

  ExplodedNodeSet Tmp;
  ExplodedNodeSet *PrevSet = &Src;

  for (typename CHECK_CTX::CheckersTy::const_iterator
         I= checkCtx.Checkers.begin(), E= checkCtx.Checkers.end(); I!=E; ++I) {
    ExplodedNodeSet *CurrSet = 0;
    if (I+1 == E)
      CurrSet = &Dst;
    else {
      CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
      CurrSet->clear();
    }

    for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
         NI != NE; ++NI)
      checkCtx.runChecker(*I, *CurrSet, *NI);

    // Update which NodeSet is the current one.
    PrevSet = CurrSet;
  }
}

namespace {
  struct CheckStmtContext {
    typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
    bool IsPreVisit;
    const CheckersTy &Checkers;
    const Stmt *S;
    ExprEngine &Eng;

    CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
                     const Stmt *s, ExprEngine &eng)
      : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { }

    void runChecker(CheckerManager::CheckStmtFunc checkFn,
                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
      // FIXME: Remove respondsToCallback from CheckerContext;
      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
                       IsPreVisit ? ProgramPoint::PreStmtKind :
                                    ProgramPoint::PostStmtKind, 0, S);
      checkFn(S, C);
    }
  };
}

/// \brief Run checkers for visiting Stmts.
void CheckerManager::runCheckersForStmt(bool isPreVisit,
                                        ExplodedNodeSet &Dst,
                                        ExplodedNodeSet &Src,
                                        const Stmt *S,
                                        ExprEngine &Eng) {
  CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
                     S, Eng);
  runPathSensitiveCheckers(C, Dst, Src);
}

namespace {
  struct CheckObjCMessageContext {
    typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
    bool IsPreVisit;
    const CheckersTy &Checkers;
    const ObjCMessage &Msg;
    ExprEngine &Eng;

    CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
                            const ObjCMessage &msg, ExprEngine &eng)
      : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }

    void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
                       IsPreVisit ? ProgramPoint::PreStmtKind :
                                    ProgramPoint::PostStmtKind, 0,
                       Msg.getOriginExpr());
      checkFn(Msg, C);
    }
  };
}

/// \brief Run checkers for visiting obj-c messages.
void CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
                                               ExplodedNodeSet &Dst,
                                               ExplodedNodeSet &Src,
                                               const ObjCMessage &msg,
                                               ExprEngine &Eng) {
  CheckObjCMessageContext C(isPreVisit, PostObjCMessageCheckers, msg, Eng);
  runPathSensitiveCheckers(C, Dst, Src);
}

namespace {
  struct CheckLocationContext {
    typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
    const CheckersTy &Checkers;
    SVal Loc;
    bool IsLoad;
    const Stmt *S;
    const GRState *State;
    ExprEngine &Eng;

    CheckLocationContext(const CheckersTy &checkers,
                         SVal loc, bool isLoad, const Stmt *s,
                         const GRState *state, ExprEngine &eng)
      : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s),
        State(state), Eng(eng) { }

    void runChecker(CheckerManager::CheckLocationFunc checkFn,
                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
                       IsLoad ? ProgramPoint::PreLoadKind :
                       ProgramPoint::PreStoreKind, 0, S, State);
      checkFn(Loc, IsLoad, C);
    }
  };
}

/// \brief Run checkers for load/store of a location.
void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
                                            ExplodedNodeSet &Src,
                                            SVal location, bool isLoad,
                                            const Stmt *S,
                                            const GRState *state,
                                            ExprEngine &Eng) {
  CheckLocationContext C(LocationCheckers, location, isLoad, S, state, Eng);
  runPathSensitiveCheckers(C, Dst, Src);
}

void CheckerManager::registerCheckersToEngine(ExprEngine &eng) {
  for (unsigned i = 0, e = Funcs.size(); i != e; ++i)
    Funcs[i](eng);
}

//===----------------------------------------------------------------------===//
// Internal registration functions for AST traversing.
//===----------------------------------------------------------------------===//

void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
                                      HandlesDeclFunc isForDeclFn) {
  DeclCheckerInfo info = { checkfn, isForDeclFn };
  DeclCheckers.push_back(info);
}

void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
  BodyCheckers.push_back(checkfn);
}

//===----------------------------------------------------------------------===//
// Internal registration functions for path-sensitive checking.
//===----------------------------------------------------------------------===//

void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
                                         HandlesStmtFunc isForStmtFn) {
  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
  StmtCheckers.push_back(info);
}
void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
                                          HandlesStmtFunc isForStmtFn) {
  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
  StmtCheckers.push_back(info);
}

void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
  PreObjCMessageCheckers.push_back(checkfn);
}
void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
  PostObjCMessageCheckers.push_back(checkfn);
}

void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
  LocationCheckers.push_back(checkfn);
}

//===----------------------------------------------------------------------===//
// Implementation details.
//===----------------------------------------------------------------------===//

CheckerManager::CachedStmtCheckers *
CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
  assert(S);

  CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit);
  CachedStmtCheckers *checkers = 0;
  CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key);
  if (CCI != CachedStmtCheckersMap.end()) {
    checkers = &(CCI->second);
  } else {
    // Find the checkers that should run for this Stmt and cache them.
    checkers = &CachedStmtCheckersMap[key];
    for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
      StmtCheckerInfo &info = StmtCheckers[i];
      if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S))
        checkers->push_back(info.CheckFn);
    }
  }

  assert(checkers);
  return checkers;
}

CheckerManager::~CheckerManager() {
  for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
    CheckerDtors[i]();
}

// Anchor for the vtable.
CheckerProvider::~CheckerProvider() { }
<commit_msg>[analyzer] Fix CheckerManager::runCheckersForObjCMessage.<commit_after>//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Defines the Static Analyzer Checker Manager.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/Analysis/ProgramPoint.h"
#include "clang/AST/DeclBase.h"

using namespace clang;
using namespace ento;

//===----------------------------------------------------------------------===//
// Functions for running checkers for AST traversing..
//===----------------------------------------------------------------------===//

void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
                                          BugReporter &BR) {
  assert(D);

  unsigned DeclKind = D->getKind();
  CachedDeclCheckers *checkers = 0;
  CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
  if (CCI != CachedDeclCheckersMap.end()) {
    checkers = &(CCI->second);
  } else {
    // Find the checkers that should run for this Decl and cache them.
    checkers = &CachedDeclCheckersMap[DeclKind];
    for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
      DeclCheckerInfo &info = DeclCheckers[i];
      if (info.IsForDeclFn(D))
        checkers->push_back(info.CheckFn);
    }
  }

  assert(checkers);
  for (CachedDeclCheckers::iterator
         I = checkers->begin(), E = checkers->end(); I != E; ++I)
    (*I)(D, mgr, BR);
}

void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
                                          BugReporter &BR) {
  assert(D && D->hasBody());

  for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
    BodyCheckers[i](D, mgr, BR);
}

//===----------------------------------------------------------------------===//
// Functions for running checkers for path-sensitive checking.
//===----------------------------------------------------------------------===//

template <typename CHECK_CTX>
static void runPathSensitiveCheckers(CHECK_CTX checkCtx,
                                     ExplodedNodeSet &Dst,
                                     ExplodedNodeSet &Src) {

  if (checkCtx.Checkers.empty()) {
    Dst.insert(Src);
    return;
  }

  ExplodedNodeSet Tmp;
  ExplodedNodeSet *PrevSet = &Src;

  for (typename CHECK_CTX::CheckersTy::const_iterator
         I= checkCtx.Checkers.begin(), E= checkCtx.Checkers.end(); I!=E; ++I) {
    ExplodedNodeSet *CurrSet = 0;
    if (I+1 == E)
      CurrSet = &Dst;
    else {
      CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
      CurrSet->clear();
    }

    for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
         NI != NE; ++NI)
      checkCtx.runChecker(*I, *CurrSet, *NI);

    // Update which NodeSet is the current one.
    PrevSet = CurrSet;
  }
}

namespace {
  struct CheckStmtContext {
    typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
    bool IsPreVisit;
    const CheckersTy &Checkers;
    const Stmt *S;
    ExprEngine &Eng;

    CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
                     const Stmt *s, ExprEngine &eng)
      : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { }

    void runChecker(CheckerManager::CheckStmtFunc checkFn,
                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
      // FIXME: Remove respondsToCallback from CheckerContext;
      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
                       IsPreVisit ? ProgramPoint::PreStmtKind :
                                    ProgramPoint::PostStmtKind, 0, S);
      checkFn(S, C);
    }
  };
}

/// \brief Run checkers for visiting Stmts.
void CheckerManager::runCheckersForStmt(bool isPreVisit,
                                        ExplodedNodeSet &Dst,
                                        ExplodedNodeSet &Src,
                                        const Stmt *S,
                                        ExprEngine &Eng) {
  CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
                     S, Eng);
  runPathSensitiveCheckers(C, Dst, Src);
}

namespace {
  struct CheckObjCMessageContext {
    typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
    bool IsPreVisit;
    const CheckersTy &Checkers;
    const ObjCMessage &Msg;
    ExprEngine &Eng;

    CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
                            const ObjCMessage &msg, ExprEngine &eng)
      : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }

    void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
                       IsPreVisit ? ProgramPoint::PreStmtKind :
                                    ProgramPoint::PostStmtKind, 0,
                       Msg.getOriginExpr());
      checkFn(Msg, C);
    }
  };
}

/// \brief Run checkers for visiting obj-c messages.
void CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
                                               ExplodedNodeSet &Dst,
                                               ExplodedNodeSet &Src,
                                               const ObjCMessage &msg,
                                               ExprEngine &Eng) {
  CheckObjCMessageContext C(isPreVisit,
                            isPreVisit ? PreObjCMessageCheckers
                                       : PostObjCMessageCheckers,
                            msg, Eng);
  runPathSensitiveCheckers(C, Dst, Src);
}

namespace {
  struct CheckLocationContext {
    typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
    const CheckersTy &Checkers;
    SVal Loc;
    bool IsLoad;
    const Stmt *S;
    const GRState *State;
    ExprEngine &Eng;

    CheckLocationContext(const CheckersTy &checkers,
                         SVal loc, bool isLoad, const Stmt *s,
                         const GRState *state, ExprEngine &eng)
      : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s),
        State(state), Eng(eng) { }

    void runChecker(CheckerManager::CheckLocationFunc checkFn,
                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
                       IsLoad ? ProgramPoint::PreLoadKind :
                       ProgramPoint::PreStoreKind, 0, S, State);
      checkFn(Loc, IsLoad, C);
    }
  };
}

/// \brief Run checkers for load/store of a location.
void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
                                            ExplodedNodeSet &Src,
                                            SVal location, bool isLoad,
                                            const Stmt *S,
                                            const GRState *state,
                                            ExprEngine &Eng) {
  CheckLocationContext C(LocationCheckers, location, isLoad, S, state, Eng);
  runPathSensitiveCheckers(C, Dst, Src);
}

void CheckerManager::registerCheckersToEngine(ExprEngine &eng) {
  for (unsigned i = 0, e = Funcs.size(); i != e; ++i)
    Funcs[i](eng);
}

//===----------------------------------------------------------------------===//
// Internal registration functions for AST traversing.
//===----------------------------------------------------------------------===//

void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
                                      HandlesDeclFunc isForDeclFn) {
  DeclCheckerInfo info = { checkfn, isForDeclFn };
  DeclCheckers.push_back(info);
}

void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
  BodyCheckers.push_back(checkfn);
}

//===----------------------------------------------------------------------===//
// Internal registration functions for path-sensitive checking.
//===----------------------------------------------------------------------===//

void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
                                         HandlesStmtFunc isForStmtFn) {
  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
  StmtCheckers.push_back(info);
}
void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
                                          HandlesStmtFunc isForStmtFn) {
  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
  StmtCheckers.push_back(info);
}

void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
  PreObjCMessageCheckers.push_back(checkfn);
}
void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
  PostObjCMessageCheckers.push_back(checkfn);
}

void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
  LocationCheckers.push_back(checkfn);
}

//===----------------------------------------------------------------------===//
// Implementation details.
//===----------------------------------------------------------------------===//

CheckerManager::CachedStmtCheckers *
CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
  assert(S);

  CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit);
  CachedStmtCheckers *checkers = 0;
  CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key);
  if (CCI != CachedStmtCheckersMap.end()) {
    checkers = &(CCI->second);
  } else {
    // Find the checkers that should run for this Stmt and cache them.
    checkers = &CachedStmtCheckersMap[key];
    for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
      StmtCheckerInfo &info = StmtCheckers[i];
      if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S))
        checkers->push_back(info.CheckFn);
    }
  }

  assert(checkers);
  return checkers;
}

CheckerManager::~CheckerManager() {
  for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
    CheckerDtors[i]();
}

// Anchor for the vtable.
CheckerProvider::~CheckerProvider() { }
<|endoftext|>


<commit_before>// Copyright (c) 2014, ultramailman
// This file is licensed under the MIT License.

#ifndef CHTABLE_H
#define CHTABLE_H
#include <vector>
#include <tuple>
namespace{
	bool isPrime(unsigned x)
	{
		if((x & 1) != 1) {
			return false;
		}
		char easy [] = {0, 1, 1, 1, 0, 1, 0, 1};
		if(x < sizeof easy) {
			return easy[x] != 0;
		}

		unsigned const half = x / 2;
		for(unsigned i = 3; i < half; i+=2){
			if(x % i == 0)
				return false;
		}
		return true;
	}
	unsigned nextPrime(unsigned const x)
	{
		unsigned n = x;
		if(n / 2 * 2 == n) {
			n++;
		}
		while(!isPrime(n)) {
			n += 2;
		}

		if(n >= x) {
			return n;
		} else {
			return -1;
		}
	}
}

namespace chtable{
	template <class K>
	struct Hash;

}
template <class K, class V>
struct Slot{
	unsigned present;
	K key;
	V val;
};

template <class K, class V>
class Chtable{
	unsigned count_;
	unsigned slots_;
	unsigned tables_;
	std::vector< Slot<K, V> > array_;
	chtable::Hash<K> uhash_;

	unsigned index(unsigned table, unsigned hash) const
	{
		return table * slots_ + hash;
	}

	unsigned totalSlots() const
	{
		return tables_ * slots_;
	}
	bool replace(K const & key, V val);
	bool insert(K & key, V & val);
public:
	Chtable( unsigned size , unsigned tableCount)
	:
		count_(0),

		slots_( nextPrime(size / tableCount + 1) ),
		tables_(tableCount),

		array_(totalSlots()),

		uhash_(tables_, slots_)
	{}

	Chtable() : Chtable(13, 2) {}

	std::tuple<V, bool> Get(K const & key) const;
	bool Set(K key, V val);
	bool Delete(K const & key);

};

//.......................... SEARCH ......................................
template<class K, class V>
std::tuple<V, bool> Chtable<K,V>::
Get(K const & key) const
{
	for(unsigned i = 0; i < tables_; i++) {
		unsigned hash = uhash_(i, key) % slots_;
		unsigned j = index(i, hash);
		auto const & slot = array_[j];
		if(slot.present and key == slot.key) {
			return std::make_tuple(slot.val, true);
		}
	}
	return std::make_tuple(V(), false);
}

//............................ INSERTION ..................................
template<class K, class V>
bool Chtable<K, V>::
replace(K const & key, V val)
{
	for(unsigned i = 0; i < tables_; i++) {
		unsigned hash = uhash_(i, key) % slots_;
		unsigned j = index(i, hash);
		auto & slot = array_[j];
		if(slot.present and key == slot.key) {
			slot.val = val;
			return true;
		}
	}
	return false;
}

template<class K, class V>
bool Chtable<K, V>::
insert(K & key, V & val)
{
	for(unsigned i = 0, timeout = tables_ * count_ + 1; timeout != 0; timeout--) {
		unsigned hash = uhash_(i, key) % slots_;
		unsigned j = index(i, hash);
		auto & slot = array_[j];
		std::swap(slot.key, key);
		std::swap(slot.val, val);

		if(slot.present) {
			i++;
			if(i == tables_) {
				i = 0;
			}
		} else {
			slot.present = true;
			count_++;
			return true;
		}
	}
	return false;
}
template<class K, class V>
bool Chtable<K, V>::
Set(K key, V val)
{
	if(replace(key, val)) {
		return true;
	}
	while(not insert(key, val)) {
		Chtable<K, V> bigger( nextPrime(totalSlots() * 2) , tables_);
		for(auto & slot : array_) {
			if(slot.present) {
				bigger.Set(slot.key, slot.val);
			}
		}
		std::swap(*this, bigger);
	}
	return true;
}

//................................... DELETION .......................
template<class K, class V>
bool Chtable<K, V>::
Delete(K const & key)
{
	for(unsigned i = 0; i < tables_; i++) {
		unsigned hash = uhash_(i, key) % slots_;
		unsigned j = index(i, hash);
		auto & slot = array_[j];
		if(slot.present and key == slot.key) {
			slot.present = false;
			slot.val = V();
			count_--;
			return true;
		}
	}
	return false;
}

#endif
<commit_msg>added methods to query status of table<commit_after>// Copyright (c) 2014, ultramailman
// This file is licensed under the MIT License.

#ifndef CHTABLE_H
#define CHTABLE_H
#include <vector>
#include <tuple>
namespace{
	bool isPrime(unsigned x)
	{
		if((x & 1) != 1) {
			return false;
		}
		char easy [] = {0, 1, 1, 1, 0, 1, 0, 1};
		if(x < sizeof easy) {
			return easy[x] != 0;
		}

		unsigned const half = x / 2;
		for(unsigned i = 3; i < half; i+=2){
			if(x % i == 0)
				return false;
		}
		return true;
	}
	unsigned nextPrime(unsigned const x)
	{
		unsigned n = x;
		if(n / 2 * 2 == n) {
			n++;
		}
		while(!isPrime(n)) {
			n += 2;
		}

		if(n >= x) {
			return n;
		} else {
			return -1;
		}
	}
}

namespace chtable{
	template <class K>
	struct Hash;

}
template <class K, class V>
struct Slot{
	unsigned present;
	K key;
	V val;
};

template <class K, class V>
class Chtable{
	unsigned count_;
	unsigned slots_;
	unsigned tables_;
	std::vector< Slot<K, V> > array_;
	chtable::Hash<K> uhash_;

	unsigned index(unsigned table, unsigned hash) const
	{
		return table * slots_ + hash;
	}

	bool replace(K const & key, V val);
	bool insert(K & key, V & val);
public:
	Chtable( unsigned size , unsigned tableCount)
	:
		count_(0),

		slots_( nextPrime(size / tableCount + 1) ),
		tables_(tableCount),

		array_(capacity()),

		uhash_(tables_, slots_)
	{}

	Chtable() : Chtable(13, 2) {}

	unsigned count() const { return count_; }
	unsigned capacity() const { return tables_ * slots_; }
	std::tuple<V, bool> Get(K const & key) const;
	bool Set(K key, V val);
	bool Delete(K const & key);

};

//.......................... SEARCH ......................................
template<class K, class V>
std::tuple<V, bool> Chtable<K,V>::
Get(K const & key) const
{
	for(unsigned i = 0; i < tables_; i++) {
		unsigned hash = uhash_(i, key) % slots_;
		unsigned j = index(i, hash);
		auto const & slot = array_[j];
		if(slot.present and key == slot.key) {
			return std::make_tuple(slot.val, true);
		}
	}
	return std::make_tuple(V(), false);
}

//............................ INSERTION ..................................
template<class K, class V>
bool Chtable<K, V>::
replace(K const & key, V val)
{
	for(unsigned i = 0; i < tables_; i++) {
		unsigned hash = uhash_(i, key) % slots_;
		unsigned j = index(i, hash);
		auto & slot = array_[j];
		if(slot.present and key == slot.key) {
			slot.val = val;
			return true;
		}
	}
	return false;
}

template<class K, class V>
bool Chtable<K, V>::
insert(K & key, V & val)
{
	for(unsigned i = 0, timeout = tables_ * count_ + 1; timeout != 0; timeout--) {
		unsigned hash = uhash_(i, key) % slots_;
		unsigned j = index(i, hash);
		auto & slot = array_[j];
		std::swap(slot.key, key);
		std::swap(slot.val, val);

		if(slot.present) {
			i++;
			if(i == tables_) {
				i = 0;
			}
		} else {
			slot.present = true;
			count_++;
			return true;
		}
	}
	return false;
}
template<class K, class V>
bool Chtable<K, V>::
Set(K key, V val)
{
	if(replace(key, val)) {
		return true;
	}
	while(not insert(key, val)) {
		Chtable<K, V> bigger( nextPrime(capacity() * 2) , tables_);
		for(auto & slot : array_) {
			if(slot.present) {
				bigger.Set(slot.key, slot.val);
			}
		}
		std::swap(*this, bigger);
	}
	return true;
}

//................................... DELETION .......................
template<class K, class V>
bool Chtable<K, V>::
Delete(K const & key)
{
	for(unsigned i = 0; i < tables_; i++) {
		unsigned hash = uhash_(i, key) % slots_;
		unsigned j = index(i, hash);
		auto & slot = array_[j];
		if(slot.present and key == slot.key) {
			slot.present = false;
			slot.val = V();
			count_--;
			return true;
		}
	}
	return false;
}

#endif
<|endoftext|>


<commit_before>#define MAIN
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>

#include <globals.h>
#include "RTcmix.h"

double irand(double low, double high)
{
    double frac = random() / (double) RAND_MAX;
	return low + frac * (high - low);
}

int
main(int argc, char *argv[])
{
	RTcmix *rrr;
	int num;
	unsigned totalcmds = 0;
	int numcommands = 4;
	int minsleep = 1000;	// in microseconds
	int maxsleep = 10000;
	int checkCount, checkInterval;
	int i;
	int verbose = 0;
	int duration = 10000;	// in seconds
	double start, pval, pval2, pval3, spread;
	struct timeval tv;
	struct timezone tz;
	double base_sec, sec, usec;

	for (int arg = 1; arg < argc; ++arg)
	{
		char *a = argv[arg];
		if (a[0] == '-') {
			switch (a[1]) {
			case 's':
				srand(atoi(argv[++arg]));
				break;
			case 'v':
				verbose = 1;
				break;
			case 'd':
				duration = atoi(argv[++arg]);
				printf("Running for %d seconds...\n", duration);
				break;
			default:
				fprintf(stderr, "usage: %s <-s randseed> <-v>\n", argv[0]);
				exit(1);
			}
		}
		else {
			fprintf(stderr, "usage: %s <-s randseed> <-v>\n", argv[0]);
			exit(1);
		}
	}

	rrr = new RTcmix(44100.0, 2, 256);
	if (verbose)
		rrr->printOn();
	else
		rrr->printOff();

	rrr->cmd("load", 1, "../../insts.std/STRUM/libSTRUM.so");
	rrr->cmd("load", 1, "../../insts.std/TRANS/libTRANS.so");
	rrr->cmd("load", 1, "../../insts.std/STEREO/libSTEREO.so");
	rrr->cmd("rtinput", 1, "./sinetone.wav");

	rrr->cmd("setline", 8, 0., 0., 1., 1., 100., 1., 110., 0.);

	checkInterval = 1000000 / maxsleep;	// about once per second
	checkCount = checkInterval;

	gettimeofday(&tv, &tz);
	base_sec = (double)tv.tv_sec;
//	usec = (double)tv.tv_usec;

	while(1) {
		usleep(minsleep + random() % maxsleep);	// random sleep
		num = random() % numcommands;			// random command

		switch (num) {
			case 0:
			case 3:
				pval = irand(5.0, 5.05);
				spread = irand(0.0, 1.0);
				rrr->cmd("bus_config", 2, "START", "out0-1");
				rrr->cmd("START", 9, 0.0, 1.0, pval, 1.0, 0.7, 5000.0, 1.0, spread, 1.0);
				totalcmds += 2;
				break;
			case 1:
				pval = irand(-0.07, 0.07);			// transp
				pval2 = irand(0.0, 1.0);			// pan
				pval3 = irand(0.05, 0.5);			// dur
				rrr->cmd("bus_config", 3, "TRANS3", "in0", "out0-1");
				rrr->cmd("TRANS3", 5, 0.0, 0.0, pval3, 0.04, pval, pval2);
				totalcmds += 2;
				break;
			case 2:
				rrr->cmd("bus_config", 3, "TRANS", "in0", "aox0");
				rrr->cmd("bus_config", 3, "STEREO", "aix0", "out0-1");
				pval = irand(-0.04, 0.04);
				pval3 = irand(0.05, 0.5);			// dur
				rrr->cmd("TRANS", 5, 0.0, 0.0, pval3, 1.0, pval);
				pval2 = irand(0.0, 1.0);
				rrr->cmd("STEREO", 5, 0.0, 0.0, pval3, 0.04, pval2);
				totalcmds += 2;
				break;
			default:
				break;
		}
		// Check time
		if (--checkCount == 0)
		{
		  gettimeofday(&tv, &tz);
		  sec = (double)tv.tv_sec;
		  if ((int) (sec - base_sec) > duration)
		  {
		  	printf("Reached %d seconds.  Shutting down...", duration);
			sleep(2);
			rrr->close();
			sleep(1);
		  	printf("Exiting.\n");
			exit(0);
		  }
		  checkCount = checkInterval;
		}
	}
	return 0;
}
<commit_msg>Added ability to set bufsize from command line.<commit_after>#define MAIN
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>

#include <globals.h>
#include "RTcmix.h"

double irand(double low, double high)
{
    double frac = random() / (double) RAND_MAX;
	return low + frac * (high - low);
}

int
main(int argc, char *argv[])
{
	RTcmix *rrr;
	int num;
	unsigned totalcmds = 0;
	int numcommands = 4;
	int minsleep = 1000;	// in microseconds
	int maxsleep = 10000;
	int checkCount, checkInterval;
	int i;
	int verbose = 0;
	int bufsize = 256;
	int duration = 10000;	// in seconds
	double start, pval, pval2, pval3, spread;
	struct timeval tv;
	struct timezone tz;
	double base_sec, sec, usec;

	for (int arg = 1; arg < argc; ++arg)
	{
		char *a = argv[arg];
		if (a[0] == '-') {
			switch (a[1]) {
			case 's':
				srand(atoi(argv[++arg]));
				break;
			case 'v':
				verbose = 1;
				break;
			case 'd':
				duration = atoi(argv[++arg]);
				printf("Running for %d seconds...\n", duration);
				break;
			case 'b':
				bufsize = atoi(argv[++arg]);
				break;
			default:
				fprintf(stderr, "usage: %s <-b bufsize> <-s randseed> <-v>\n", argv[0]);
				exit(1);
			}
		}
		else {
			fprintf(stderr, "usage: %s <-s randseed> <-v>\n", argv[0]);
			exit(1);
		}
	}

	rrr = new RTcmix(44100.0, 2, bufsize);
	if (verbose)
		rrr->printOn();
	else
		rrr->printOff();

	rrr->cmd("load", 1, "../../insts.std/STRUM/libSTRUM.so");
	rrr->cmd("load", 1, "../../insts.std/TRANS/libTRANS.so");
	rrr->cmd("load", 1, "../../insts.std/STEREO/libSTEREO.so");
	rrr->cmd("rtinput", 1, "./sinetone.wav");

	rrr->cmd("setline", 8, 0., 0., 1., 1., 100., 1., 110., 0.);

	checkInterval = 1000000 / maxsleep;	// about once per second
	checkCount = checkInterval;

	gettimeofday(&tv, &tz);
	base_sec = (double)tv.tv_sec;
//	usec = (double)tv.tv_usec;

	while(1) {
		usleep(minsleep + random() % maxsleep);	// random sleep
		num = random() % numcommands;			// random command

		switch (num) {
			case 0:
			case 3:
				pval = irand(5.0, 5.05);
				spread = irand(0.0, 1.0);
				rrr->cmd("bus_config", 2, "START", "out0-1");
				rrr->cmd("START", 9, 0.0, 1.0, pval, 1.0, 0.7, 5000.0, 1.0, spread, 1.0);
				totalcmds += 2;
				break;
			case 1:
				pval = irand(-0.07, 0.07);			// transp
				pval2 = irand(0.0, 1.0);			// pan
				pval3 = irand(0.05, 0.5);			// dur
				rrr->cmd("bus_config", 3, "TRANS3", "in0", "out0-1");
				rrr->cmd("TRANS3", 5, 0.0, 0.0, pval3, 0.04, pval, pval2);
				totalcmds += 2;
				break;
			case 2:
				rrr->cmd("bus_config", 3, "TRANS", "in0", "aox0");
				rrr->cmd("bus_config", 3, "STEREO", "aix0", "out0-1");
				pval = irand(-0.04, 0.04);
				pval3 = irand(0.05, 0.5);			// dur
				rrr->cmd("TRANS", 5, 0.0, 0.0, pval3, 1.0, pval);
				pval2 = irand(0.0, 1.0);
				rrr->cmd("STEREO", 5, 0.0, 0.0, pval3, 0.04, pval2);
				totalcmds += 2;
				break;
			default:
				break;
		}
		// Check time
		if (--checkCount == 0)
		{
		  gettimeofday(&tv, &tz);
		  sec = (double)tv.tv_sec;
		  if ((int) (sec - base_sec) > duration)
		  {
		  	printf("Reached %d seconds.  Shutting down...", duration);
			sleep(2);
			rrr->close();
			sleep(1);
		  	printf("Exiting.\n");
			exit(0);
		  }
		  checkCount = checkInterval;
		}
	}
	return 0;
}
<|endoftext|>