<commit_before>// Copyright (c) Facebook, Inc. and its affiliates.

// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.

#include "ReadableNativeMap.h"

using namespace facebook::jni;

namespace facebook {
namespace react {

void ReadableNativeMap::mapException(const std::exception &ex) {
  if (dynamic_cast<const folly::TypeError *>(&ex) != nullptr) {
    throwNewJavaException(
        exceptions::gUnexpectedNativeTypeExceptionClass, ex.what());
  }
}

void addDynamicToJArray(
    local_ref<JArrayClass<jobject>> jarray,
    jint index,
    const folly::dynamic &dyn) {
  switch (dyn.type()) {
    case folly::dynamic::Type::NULLT: {
      jarray->setElement(index, nullptr);
      break;
    }
    case folly::dynamic::Type::BOOL: {
      (*jarray)[index] = JBoolean::valueOf(dyn.getBool());
      break;
    }
    case folly::dynamic::Type::INT64: {
      (*jarray)[index] = JDouble::valueOf(dyn.getInt());
      break;
    }
    case folly::dynamic::Type::DOUBLE: {
      (*jarray)[index] = JDouble::valueOf(dyn.getDouble());
      break;
    }
    case folly::dynamic::Type::STRING: {
      (*jarray)[index] = make_jstring(dyn.getString());
      break;
    }
    case folly::dynamic::Type::OBJECT: {
      (*jarray)[index] = ReadableNativeMap::newObjectCxxArgs(dyn);
      break;
    }
    case folly::dynamic::Type::ARRAY: {
      (*jarray)[index] = ReadableNativeArray::newObjectCxxArgs(dyn);
      break;
    }
    default:
      jarray->setElement(index, nullptr);
      break;
  }
}

local_ref<JArrayClass<jstring>> ReadableNativeMap::importKeys() {
  auto pairs = map_.items();
  keys_ = folly::dynamic::array();
  for (auto &pair : pairs) {
    keys_.value().push_back(pair.first.asString());
  }
  jint size = keys_.value().size();
  auto jarray = JArrayClass<jstring>::newArray(size);
  for (jint ii = 0; ii < size; ii++) {
    (*jarray)[ii] = make_jstring(keys_.value()[ii].getString());
  }
  return jarray;
}

local_ref<JArrayClass<jobject>> ReadableNativeMap::importValues() {
  jint size = keys_.value().size();
  auto jarray = JArrayClass<jobject>::newArray(size);
  for (jint ii = 0; ii < size; ii++) {
    const std::string &key = keys_.value()[ii].getString();
    addDynamicToJArray(jarray, ii, map_.at(key));
  }
  return jarray;
}

local_ref<JArrayClass<jobject>> ReadableNativeMap::importTypes() {
  jint size = keys_.value().size();
  auto jarray = JArrayClass<jobject>::newArray(size);
  for (jint ii = 0; ii < size; ii++) {
    const std::string &key = keys_.value()[ii].getString();
    (*jarray)[ii] = ReadableType::getType(map_.at(key).type());
  }
  return jarray;
}

local_ref<ReadableNativeMap::jhybridobject>
ReadableNativeMap::createWithContents(folly::dynamic &&map) {
  if (map.isNull()) {
    return local_ref<jhybridobject>(nullptr);
  }

  if (!map.isObject()) {
    throwNewJavaException(
        exceptions::gUnexpectedNativeTypeExceptionClass,
        "expected Map, got a %s",
        map.typeName());
  }

  return newObjectCxxArgs(std::move(map));
}

void ReadableNativeMap::registerNatives() {
  registerHybrid({
      makeNativeMethod("importKeys", ReadableNativeMap::importKeys),
      makeNativeMethod("importValues", ReadableNativeMap::importValues),
      makeNativeMethod("importTypes", ReadableNativeMap::importTypes),
  });
}

} // namespace react
} // namespace facebook
<commit_msg>ReadableNativeMap: `importKeys` shouldn't choke on null `map_`<commit_after>// Copyright (c) Facebook, Inc. and its affiliates.

// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.

#include "ReadableNativeMap.h"

using namespace facebook::jni;

namespace facebook {
namespace react {

void ReadableNativeMap::mapException(const std::exception &ex) {
  if (dynamic_cast<const folly::TypeError *>(&ex) != nullptr) {
    throwNewJavaException(
        exceptions::gUnexpectedNativeTypeExceptionClass, ex.what());
  }
}

void addDynamicToJArray(
    local_ref<JArrayClass<jobject>> jarray,
    jint index,
    const folly::dynamic &dyn) {
  switch (dyn.type()) {
    case folly::dynamic::Type::NULLT: {
      jarray->setElement(index, nullptr);
      break;
    }
    case folly::dynamic::Type::BOOL: {
      (*jarray)[index] = JBoolean::valueOf(dyn.getBool());
      break;
    }
    case folly::dynamic::Type::INT64: {
      (*jarray)[index] = JDouble::valueOf(dyn.getInt());
      break;
    }
    case folly::dynamic::Type::DOUBLE: {
      (*jarray)[index] = JDouble::valueOf(dyn.getDouble());
      break;
    }
    case folly::dynamic::Type::STRING: {
      (*jarray)[index] = make_jstring(dyn.getString());
      break;
    }
    case folly::dynamic::Type::OBJECT: {
      (*jarray)[index] = ReadableNativeMap::newObjectCxxArgs(dyn);
      break;
    }
    case folly::dynamic::Type::ARRAY: {
      (*jarray)[index] = ReadableNativeArray::newObjectCxxArgs(dyn);
      break;
    }
    default:
      jarray->setElement(index, nullptr);
      break;
  }
}

local_ref<JArrayClass<jstring>> ReadableNativeMap::importKeys() {
  keys_ = folly::dynamic::array();
  if (map_ == nullptr) {
    return JArrayClass<jstring>::newArray(0);
  }
  auto pairs = map_.items();
  for (auto &pair : pairs) {
    keys_.value().push_back(pair.first.asString());
  }
  jint size = keys_.value().size();
  auto jarray = JArrayClass<jstring>::newArray(size);
  for (jint ii = 0; ii < size; ii++) {
    (*jarray)[ii] = make_jstring(keys_.value()[ii].getString());
  }
  return jarray;
}

local_ref<JArrayClass<jobject>> ReadableNativeMap::importValues() {
  jint size = keys_.value().size();
  auto jarray = JArrayClass<jobject>::newArray(size);
  for (jint ii = 0; ii < size; ii++) {
    const std::string &key = keys_.value()[ii].getString();
    addDynamicToJArray(jarray, ii, map_.at(key));
  }
  return jarray;
}

local_ref<JArrayClass<jobject>> ReadableNativeMap::importTypes() {
  jint size = keys_.value().size();
  auto jarray = JArrayClass<jobject>::newArray(size);
  for (jint ii = 0; ii < size; ii++) {
    const std::string &key = keys_.value()[ii].getString();
    (*jarray)[ii] = ReadableType::getType(map_.at(key).type());
  }
  return jarray;
}

local_ref<ReadableNativeMap::jhybridobject>
ReadableNativeMap::createWithContents(folly::dynamic &&map) {
  if (map.isNull()) {
    return local_ref<jhybridobject>(nullptr);
  }

  if (!map.isObject()) {
    throwNewJavaException(
        exceptions::gUnexpectedNativeTypeExceptionClass,
        "expected Map, got a %s",
        map.typeName());
  }

  return newObjectCxxArgs(std::move(map));
}

void ReadableNativeMap::registerNatives() {
  registerHybrid({
      makeNativeMethod("importKeys", ReadableNativeMap::importKeys),
      makeNativeMethod("importValues", ReadableNativeMap::importValues),
      makeNativeMethod("importTypes", ReadableNativeMap::importTypes),
  });
}

} // namespace react
} // namespace facebook
<|endoftext|>


<commit_before><commit_msg>Only load resources for renderer, extension, and zygote processes (and plugins processes on Windows).<commit_after><|endoftext|>


<commit_before><commit_msg>Ignore SIGPIPE in the browser process.<commit_after><|endoftext|>


<commit_before>#include "value.h"
#include "vm.h"

#include <cassert>

extern "C" void *builtin_sub();
extern "C" void *builtin_add();
extern "C" void *builtin_lt();

namespace Verve {

  void registerBuiltins(VM &vm) {

#define REGISTER(NAME, FN) \
    do { \
      Builtin FN##_ = (Builtin)FN;  \
      vm.m_scope->set(#NAME, Value(FN##_)); \
    } while(0)

    REGISTER(print_string, print_string);
    REGISTER(concat_string, concat_string);

    REGISTER(head, head);
    REGISTER(tail, tail);
    REGISTER(length, length);

    // type conversion
    REGISTER(int_to_string, int_to_string);
    REGISTER(float_to_string, float_to_string);

    REGISTER(+, builtin_add);
    REGISTER(-, builtin_sub);
    REGISTER(*, mul);
    REGISTER(/, div);
    REGISTER(%, mod);
    REGISTER(<, builtin_lt);
    REGISTER(>, gt);
    REGISTER(<=, lte);
    REGISTER(>=, gte);
    REGISTER(==, equals);
    REGISTER(!=, not_equal);
    REGISTER(&&, _and);
    REGISTER(||, _or);

    REGISTER(unary_!, _not);
    REGISTER(unary_-, minus);

    REGISTER(at, at);
    REGISTER(substr, substr);
    REGISTER(count, count);
    REGISTER(__heap-size__, heapSize);
  }

#define EACH_ARG(IT) \
  Value IT; for (unsigned I = 0; (I < argc ? (IT = argv[I]) : 0), I < argc; I++)

#define BASIC_MATH(NAME, OP) \
  VERVE_FUNCTION(NAME) { \
    assert(argc == 2); \
 \
    return Value(argv[0].asInt() OP argv[1].asInt()); \
  }

  BASIC_MATH(add, +)
  BASIC_MATH(sub, -)
  BASIC_MATH(mul, *)
  BASIC_MATH(div, /)
  BASIC_MATH(mod, %)
  BASIC_MATH(lt, <)
  BASIC_MATH(gt, >)
  BASIC_MATH(lte, <=)
  BASIC_MATH(gte, >=)
  BASIC_MATH(equals, ==)
  BASIC_MATH(not_equal, !=)
  BASIC_MATH(_and, &&)
  BASIC_MATH(_or, ||)

  VERVE_FUNCTION(_not) {
    assert(argc == 1);
    return Value(!argv[0].asInt());
  }

  VERVE_FUNCTION(minus) {
    assert(argc == 1);
    return Value(-argv[0].asInt());
  }

  static void printValue(Value value) {
    if (value.isString()) {
      printf("%s", value.asString().str());
    } else if (value.isList()) {
      for (unsigned i = 0; i < value.asList()->length; i++) {
        if (i) putchar(' ');
        printValue(value.asList()->at(i));
      }
    } else if (value.isInt()){
      printf("%d", value.asInt());
    } else {
      auto v = value.encode();
      printf("%lg", *(double *)&v);
      //throw std::runtime_error("Trying to print unsupported type");
    }
  }

  VERVE_FUNCTION(print_string) {
    assert(argc == 1);

    printf("%s", argv[0].asString().str());
    putchar('\n');

    return 0;
  }

  VERVE_FUNCTION(head) {
    assert(argc == 1);

    auto lst = argv[0].asList();
    if (lst->length  == 0)
      return Value{};
    else
      return lst->at(0);
  }

  VERVE_FUNCTION(tail) {
    assert(argc == 1);

    auto lst = argv[0].asList();
    auto size = lst->length > 0 ? lst->length - 1 : 0;
    auto ret = (uint64_t *)calloc(size + 1, 8);
    ret[0] = size;
    for (unsigned i = 1; i < lst->length; i++) {
      ret[i] = lst->at(i).encode();
    }
    vm->trackAllocation(ret, (size + 1) * 8);
    return (List *)ret;
  }

  VERVE_FUNCTION(length) {
    assert(argc == 1);

    return argv[0].asList()->length;
  }

  VERVE_FUNCTION(int_to_string) {
    assert(argc == 1);

    auto number = argv[0].asInt();
    auto size = snprintf(NULL, 0, "%d", number);
    auto buffer = (char *)malloc(size + 1);
    snprintf(buffer, size + 1, "%d", number);
    vm->trackAllocation(buffer, size + 1);

    return Value(buffer);
  }

  VERVE_FUNCTION(float_to_string) {
    assert(argc == 1);

    auto v = argv[0].encode();
    auto number = *(double *)&v;
    auto size = snprintf(NULL, 0, "%lg", number);
    auto buffer = (char *)malloc(size + 1);
    snprintf(buffer, size + 1, "%lg", number);
    vm->trackAllocation(buffer, size + 1);

    return Value(buffer);
  }

  VERVE_FUNCTION(concat_string) {
    assert(argc == 2);

    auto s1 = argv[0].asString().str();
    auto s2 = argv[1].asString().str();
    auto size = strlen(s1) + strlen(s2);
    auto buffer = (char *)malloc(size + 1);
    snprintf(buffer, size + 1, "%s%s", s1, s2);
    vm->trackAllocation(buffer, size + 1);

    return Value(buffer);
  }

  VERVE_FUNCTION(at) {
    assert(argc == 2);

    Value arg = argv[0];
    if (arg.isString()) {
      return arg.asString()[argv[1].asInt()];
    } else if (arg.isList()) {
      return arg.asList()->at(argv[1].asInt());
    }

    return Value(0);
  }

  VERVE_FUNCTION(substr) {
    assert(argc == 2 || argc == 3);

    Value arg = argv[0];
    if (arg.isString()) {
      const char *str = arg.asString().str();
      const char *substring;
      if (argc == 2) {
        substring = str + argv[1].asInt();
      } else {
        size_t start = argv[0].asInt();
        size_t length = argv[1].asInt() - start;
        char *substr = (char *)malloc(length + 1);
        memcpy(substr, str, length);
        substr[length] = 0;
        vm->trackAllocation(substr, length);
        substring = substr;
      }

      return Value(substring);
    } else {
      throw;
    }

    return 0;
  }

  VERVE_FUNCTION(count) {
    assert(argc == 1);

    Value arg = argv[0];
    if (arg.isString()) {
      return strlen(arg.asString());
    } else {
      throw;
    }

    return 0;
  }

  VERVE_FUNCTION(heapSize) {
    assert(argc == 0);

    return Value((int)vm->heapSize);
  }

}
<commit_msg>Remove unused function printValue<commit_after>#include "value.h"
#include "vm.h"

#include <cassert>

extern "C" void *builtin_sub();
extern "C" void *builtin_add();
extern "C" void *builtin_lt();

namespace Verve {

  void registerBuiltins(VM &vm) {

#define REGISTER(NAME, FN) \
    do { \
      Builtin FN##_ = (Builtin)FN;  \
      vm.m_scope->set(#NAME, Value(FN##_)); \
    } while(0)

    REGISTER(print_string, print_string);
    REGISTER(concat_string, concat_string);

    REGISTER(head, head);
    REGISTER(tail, tail);
    REGISTER(length, length);

    // type conversion
    REGISTER(int_to_string, int_to_string);
    REGISTER(float_to_string, float_to_string);

    REGISTER(+, builtin_add);
    REGISTER(-, builtin_sub);
    REGISTER(*, mul);
    REGISTER(/, div);
    REGISTER(%, mod);
    REGISTER(<, builtin_lt);
    REGISTER(>, gt);
    REGISTER(<=, lte);
    REGISTER(>=, gte);
    REGISTER(==, equals);
    REGISTER(!=, not_equal);
    REGISTER(&&, _and);
    REGISTER(||, _or);

    REGISTER(unary_!, _not);
    REGISTER(unary_-, minus);

    REGISTER(at, at);
    REGISTER(substr, substr);
    REGISTER(count, count);
    REGISTER(__heap-size__, heapSize);
  }

#define EACH_ARG(IT) \
  Value IT; for (unsigned I = 0; (I < argc ? (IT = argv[I]) : 0), I < argc; I++)

#define BASIC_MATH(NAME, OP) \
  VERVE_FUNCTION(NAME) { \
    assert(argc == 2); \
 \
    return Value(argv[0].asInt() OP argv[1].asInt()); \
  }

  BASIC_MATH(add, +)
  BASIC_MATH(sub, -)
  BASIC_MATH(mul, *)
  BASIC_MATH(div, /)
  BASIC_MATH(mod, %)
  BASIC_MATH(lt, <)
  BASIC_MATH(gt, >)
  BASIC_MATH(lte, <=)
  BASIC_MATH(gte, >=)
  BASIC_MATH(equals, ==)
  BASIC_MATH(not_equal, !=)
  BASIC_MATH(_and, &&)
  BASIC_MATH(_or, ||)

  VERVE_FUNCTION(_not) {
    assert(argc == 1);
    return Value(!argv[0].asInt());
  }

  VERVE_FUNCTION(minus) {
    assert(argc == 1);
    return Value(-argv[0].asInt());
  }

  VERVE_FUNCTION(print_string) {
    assert(argc == 1);

    printf("%s", argv[0].asString().str());
    putchar('\n');

    return 0;
  }

  VERVE_FUNCTION(head) {
    assert(argc == 1);

    auto lst = argv[0].asList();
    if (lst->length  == 0)
      return Value{};
    else
      return lst->at(0);
  }

  VERVE_FUNCTION(tail) {
    assert(argc == 1);

    auto lst = argv[0].asList();
    auto size = lst->length > 0 ? lst->length - 1 : 0;
    auto ret = (uint64_t *)calloc(size + 1, 8);
    ret[0] = size;
    for (unsigned i = 1; i < lst->length; i++) {
      ret[i] = lst->at(i).encode();
    }
    vm->trackAllocation(ret, (size + 1) * 8);
    return (List *)ret;
  }

  VERVE_FUNCTION(length) {
    assert(argc == 1);

    return argv[0].asList()->length;
  }

  VERVE_FUNCTION(int_to_string) {
    assert(argc == 1);

    auto number = argv[0].asInt();
    auto size = snprintf(NULL, 0, "%d", number);
    auto buffer = (char *)malloc(size + 1);
    snprintf(buffer, size + 1, "%d", number);
    vm->trackAllocation(buffer, size + 1);

    return Value(buffer);
  }

  VERVE_FUNCTION(float_to_string) {
    assert(argc == 1);

    auto v = argv[0].encode();
    auto number = *(double *)&v;
    auto size = snprintf(NULL, 0, "%lg", number);
    auto buffer = (char *)malloc(size + 1);
    snprintf(buffer, size + 1, "%lg", number);
    vm->trackAllocation(buffer, size + 1);

    return Value(buffer);
  }

  VERVE_FUNCTION(concat_string) {
    assert(argc == 2);

    auto s1 = argv[0].asString().str();
    auto s2 = argv[1].asString().str();
    auto size = strlen(s1) + strlen(s2);
    auto buffer = (char *)malloc(size + 1);
    snprintf(buffer, size + 1, "%s%s", s1, s2);
    vm->trackAllocation(buffer, size + 1);

    return Value(buffer);
  }

  VERVE_FUNCTION(at) {
    assert(argc == 2);

    Value arg = argv[0];
    if (arg.isString()) {
      return arg.asString()[argv[1].asInt()];
    } else if (arg.isList()) {
      return arg.asList()->at(argv[1].asInt());
    }

    return Value(0);
  }

  VERVE_FUNCTION(substr) {
    assert(argc == 2 || argc == 3);

    Value arg = argv[0];
    if (arg.isString()) {
      const char *str = arg.asString().str();
      const char *substring;
      if (argc == 2) {
        substring = str + argv[1].asInt();
      } else {
        size_t start = argv[0].asInt();
        size_t length = argv[1].asInt() - start;
        char *substr = (char *)malloc(length + 1);
        memcpy(substr, str, length);
        substr[length] = 0;
        vm->trackAllocation(substr, length);
        substring = substr;
      }

      return Value(substring);
    } else {
      throw;
    }

    return 0;
  }

  VERVE_FUNCTION(count) {
    assert(argc == 1);

    Value arg = argv[0];
    if (arg.isString()) {
      return strlen(arg.asString());
    } else {
      throw;
    }

    return 0;
  }

  VERVE_FUNCTION(heapSize) {
    assert(argc == 0);

    return Value((int)vm->heapSize);
  }

}
<|endoftext|>


<commit_before>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * usbpro-rdm.cpp
 * A very simple RDM sniffer for USB Pro like devices
 * Copyright (C) 2010 Simon Newton
 */

#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <string.h>
#include <sysexits.h>
#include <termios.h>
#include <ola/Logging.h>
#include <ola/Callback.h>
#include <ola/network/SelectServer.h>
#include <ola/rdm/RDMCommand.h>

#include <iostream>
#include <fstream>
#include <string>

#include "plugins/usbpro/UsbWidget.h"

using std::cout;
using std::endl;
using std::string;
using ola::network::SelectServerInterface;
using ola::plugin::usbpro::UsbWidget;
using ola::rdm::RDMCommand;
using ola::rdm::RDMRequest;
using ola::rdm::RDMResponse;

static const char DEFAULT_DEVICE[] = "/dev/ttyUSB0";

typedef struct {
  bool help;
  bool dump_all;
  bool verbose;
  ola::log_level log_level;
  string device;
} options;

class RDMSniffer {
  public:
    RDMSniffer(UsbWidget *widget,
               SelectServerInterface *ss,
               bool dump_all,
               bool verbose);

    void HandleMessage(uint8_t label,
                       const uint8_t *data,
                       unsigned int length);

  private:
    UsbWidget *m_widget;
    SelectServerInterface *m_ss;
    bool m_dump_all;
    bool m_verbose;

    void DumpRawPacket(unsigned int length, const uint8_t *data);
    void DumpRequest(unsigned int length, const uint8_t *data);
    void DumpResponse(unsigned int length, const uint8_t *data);
    void DumpDiscover(unsigned int length, const uint8_t *data);

    static const uint8_t RECEIVED_DMX_LABEL = 5;
    static const uint8_t DRAFT_START_CODE = 0xf0;
};

RDMSniffer::RDMSniffer(UsbWidget *widget,
                       SelectServerInterface *ss,
                       bool dump_all,
                       bool verbose):
    m_widget(widget),
    m_ss(ss),
    m_dump_all(dump_all),
    m_verbose(verbose) {
  widget->SetMessageHandler(
      ola::NewCallback(this, &RDMSniffer::HandleMessage));
}

/*
 * Handle the widget replies
 */
void RDMSniffer::HandleMessage(uint8_t label,
                               const uint8_t *data,
                               unsigned int length) {
  if (label != RECEIVED_DMX_LABEL) {
    OLA_INFO << "Not a RECEIVED_DMX_LABEL, was " << static_cast<int>(label);
    return;
  }

  if (!length) {
    if (m_dump_all)
      OLA_INFO << "Zero sized packet";
    return;
  }

  if (data[0]) {
    OLA_INFO << "Error: " << static_cast<int>(data[0]);
    return;
  }

  length--;
  data++;

  if (!length) {
    if (m_dump_all)
      OLA_INFO << "Zero sized packet";
    return;
  }

  switch (data[0]) {
    case 0:
      if (m_dump_all)
        OLA_INFO << "DMX packet";
      return;
    case DRAFT_START_CODE:
      if (m_dump_all) {
        cout << "Draft RDM packet: ";
        DumpRawPacket(length, data);
      }
      return;
    case RDMCommand::START_CODE:
      break;
    default:
      if (m_dump_all)
        OLA_INFO << "Packet with start code " << static_cast<int>(data[0]);
      return;
  }

  if (length < 21) {
    cout << "Short packet: ";
    DumpRawPacket(length, data);
    return;
  }

  uint8_t command_class = data[20];
  cout << static_cast<int>(command_class) << endl;

  switch (command_class) {
    case RDMCommand::GET_COMMAND:
    case RDMCommand::SET_COMMAND:
      DumpRequest(length - 1, data + 1);
      return;
    case RDMCommand::GET_COMMAND_RESPONSE:
    case RDMCommand::SET_COMMAND_RESPONSE:
      DumpResponse(length - 1, data + 1);
      return;
    case RDMCommand::DISCOVER_COMMAND:
      DumpDiscover(length - 1, data + 1);
      return;
    default:
      DumpRawPacket(length -1, data + 1);
  }
}

void RDMSniffer::DumpRawPacket(unsigned int length, const uint8_t *data) {
  for (unsigned int i = 0; i < length; ++i)
    cout << std::hex << static_cast<int>(data[i]) << " ";
  cout << endl;
}

void RDMSniffer::DumpRequest(unsigned int length, const uint8_t *data) {
  RDMRequest *request = RDMRequest::InflateFromData(data, length);
  if (request) {
    cout << (request->CommandClass() == RDMCommand::GET_COMMAND ? "GET" :
             "SET");
    if (m_verbose)
      cout << " src: " << request->SourceUID() << ", dst: " <<
        request->DestinationUID() << ", transaction: " <<
        request->TransactionNumber() << ", port: " << request->PortId() <<
        ", PID " << std::hex << request->ParamId() << endl;
    else
      cout << " src: " << request->SourceUID() << ", dst: " <<
        request->DestinationUID() << ", PID " << std::hex <<
        request->ParamId() << endl;
  } else {
    DumpRawPacket(length, data);
  }
}

void RDMSniffer::DumpResponse(unsigned int length, const uint8_t *data) {
  RDMResponse *response = RDMResponse::InflateFromData(data, length);
  if (response) {
    cout << (response->CommandClass() == RDMCommand::GET_COMMAND_RESPONSE ?
        "GET_RESPONSE" : "SET_RESPONSE");
    if (m_verbose)
      cout << " src: " << response->SourceUID() << ", dst: " <<
        response->DestinationUID() << ", transaction: " <<
        response->TransactionNumber() << ", response type: " <<
        response->ResponseType() << ", PID " << std::hex << response->ParamId()
        << endl;
    else
      cout << " src: " << response->SourceUID() << ", dst: " <<
        response->DestinationUID() << ", PID " << std::hex <<
        response->ParamId() << endl;
  }
  DumpRawPacket(length, data);
}

void RDMSniffer::DumpDiscover(unsigned int length, const uint8_t *data) {
  DumpRawPacket(length, data);
}

/*
 * Parse our command line options
 */
void ParseOptions(int argc, char *argv[], options *opts) {
  static struct option long_options[] = {
      {"dump-all", no_argument, 0, 'a'},
      {"device", required_argument, 0, 'd'},
      {"help", no_argument, 0, 'h'},
      {"log-level", required_argument, 0, 'l'},
      {"verbose", no_argument, 0, 'v'},
      {0, 0, 0, 0}
    };

  int option_index = 0;

  while (1) {
    int c = getopt_long(argc, argv, "ad:hl:v", long_options, &option_index);

    if (c == -1)
      break;

    switch (c) {
      case 0:
        break;
      case 'a':
        opts->dump_all = true;
        break;
      case 'd':
        opts->device = optarg;
        break;
      case 'h':
        opts->help = true;
        break;
      case 'l':
        switch (atoi(optarg)) {
          case 0:
            // nothing is written at this level
            // so this turns logging off
            opts->log_level = ola::OLA_LOG_NONE;
            break;
          case 1:
            opts->log_level = ola::OLA_LOG_FATAL;
            break;
          case 2:
            opts->log_level = ola::OLA_LOG_WARN;
            break;
          case 3:
            opts->log_level = ola::OLA_LOG_INFO;
            break;
          case 4:
            opts->log_level = ola::OLA_LOG_DEBUG;
            break;
          default :
            break;
        }
        break;
      case 'v':
        opts->verbose = true;
        break;
      case '?':
        break;
      default:
       break;
    }
  }
  return;
}

/*
 * Display the help message
 */
void DisplayHelpAndExit(char *argv[]) {
  cout << "Usage: " << argv[0] <<
  " -d <device>\n"
  "\n"
  "Dump RDM traffic from a Enttec USB Pro device.\n"
  "\n"
  "  -a, --dump-all     Dump all packets (default is just RDM)\n"
  "  -d <device_path>   The path to the device.\n"
  "  -h, --help         Display this help message and exit.\n"
  "  -l, --log-level <level>  Set the loggging level 0 .. 4.\n"
  "  -v, --verbose      Show more packet details\n"
  << endl;
  exit(0);
}

void Stop(ola::network::SelectServer *ss) {
  ss->Terminate();
}

/*
 * Dump RDM data
 */
int main(int argc, char *argv[]) {
  options opts;
  opts.dump_all = false;
  opts.verbose = false;
  opts.log_level = ola::OLA_LOG_INFO;
  opts.help = false;
  opts.device = DEFAULT_DEVICE;
  ParseOptions(argc, argv, &opts);

  if (opts.help)
    DisplayHelpAndExit(argv);
  ola::InitLogging(opts.log_level, ola::OLA_LOG_STDERR);

  ola::network::ConnectedSocket *socket = UsbWidget::OpenDevice(opts.device);
  if (!socket)
    exit(EX_UNAVAILABLE);

  ola::network::SelectServer ss;
  ss.AddSocket(socket);
  UsbWidget widget(socket);
  RDMSniffer sniffer(&widget, &ss, opts.dump_all, opts.verbose);

  widget.SetOnRemove(ola::NewSingleCallback(&Stop, &ss));
  ss.Run();

  return EX_OK;
}
<commit_msg> * improve the sniffer a bit<commit_after>/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program 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 Library General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * usbpro-rdm.cpp
 * A very simple RDM sniffer for USB Pro like devices
 * Copyright (C) 2010 Simon Newton
 */

#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <string.h>
#include <sysexits.h>
#include <termios.h>
#include <ola/Logging.h>
#include <ola/Callback.h>
#include <ola/network/NetworkUtils.h>
#include <ola/network/SelectServer.h>
#include <ola/rdm/RDMCommand.h>
#include <ola/rdm/RDMEnums.h>
#include <ola/rdm/RDMHelper.h>
#include <ola/rdm/RDMResponseCodes.h>

#include <iostream>
#include <fstream>
#include <string>

#include "plugins/usbpro/UsbWidget.h"

using std::cout;
using std::endl;
using std::string;
using ola::network::SelectServerInterface;
using ola::plugin::usbpro::UsbWidget;
using ola::rdm::RDMCommand;
using ola::rdm::RDMRequest;
using ola::rdm::RDMResponse;

static const char DEFAULT_DEVICE[] = "/dev/ttyUSB0";

typedef struct {
  bool help;
  bool dump_all;
  bool verbose;
  ola::log_level log_level;
  string device;
} options;

class RDMSniffer {
  public:
    RDMSniffer(UsbWidget *widget,
               SelectServerInterface *ss,
               bool dump_all,
               bool verbose);

    void HandleMessage(uint8_t label,
                       const uint8_t *data,
                       unsigned int length);

  private:
    UsbWidget *m_widget;
    SelectServerInterface *m_ss;
    bool m_dump_all;
    bool m_verbose;

    void DumpRawPacket(unsigned int length, const uint8_t *data);
    void DumpRequest(unsigned int length, const uint8_t *data);
    void DumpResponse(unsigned int length, const uint8_t *data);
    void DumpDiscover(unsigned int length, const uint8_t *data);

    static const uint8_t RECEIVED_DMX_LABEL = 5;
    static const uint8_t DRAFT_START_CODE = 0xf0;
};

RDMSniffer::RDMSniffer(UsbWidget *widget,
                       SelectServerInterface *ss,
                       bool dump_all,
                       bool verbose):
    m_widget(widget),
    m_ss(ss),
    m_dump_all(dump_all),
    m_verbose(verbose) {
  widget->SetMessageHandler(
      ola::NewCallback(this, &RDMSniffer::HandleMessage));
}

/*
 * Handle the widget replies
 */
void RDMSniffer::HandleMessage(uint8_t label,
                               const uint8_t *data,
                               unsigned int length) {
  if (label != RECEIVED_DMX_LABEL) {
    OLA_INFO << "Not a RECEIVED_DMX_LABEL, was " << static_cast<int>(label);
    return;
  }

  if (!length) {
    if (m_dump_all)
      OLA_INFO << "Zero sized packet";
    return;
  }

  if (data[0]) {
    OLA_INFO << "Error: " << static_cast<int>(data[0]);
    return;
  }

  length--;
  data++;

  if (!length) {
    if (m_dump_all)
      OLA_INFO << "Zero sized packet";
    return;
  }

  switch (data[0]) {
    case 0:
      if (m_dump_all)
        OLA_INFO << "DMX packet";
      return;
    case DRAFT_START_CODE:
      if (m_dump_all) {
        cout << "Draft RDM packet: ";
        DumpRawPacket(length, data);
      }
      return;
    case RDMCommand::START_CODE:
      break;
    default:
      if (m_dump_all)
        OLA_INFO << "Packet with start code " << static_cast<int>(data[0]);
      return;
  }

  if (length < 21) {
    cout << "Short packet: ";
    DumpRawPacket(length, data);
    return;
  }

  uint8_t command_class = data[20];

  switch (command_class) {
    case RDMCommand::GET_COMMAND:
    case RDMCommand::SET_COMMAND:
      DumpRequest(length - 1, data + 1);
      return;
    case RDMCommand::GET_COMMAND_RESPONSE:
    case RDMCommand::SET_COMMAND_RESPONSE:
      DumpResponse(length - 1, data + 1);
      return;
    case RDMCommand::DISCOVER_COMMAND:
    case RDMCommand::DISCOVER_COMMAND_RESPONSE:
      DumpDiscover(length - 1, data + 1);
      return;
    default:
      DumpRawPacket(length -1, data + 1);
  }
}

void RDMSniffer::DumpRawPacket(unsigned int length, const uint8_t *data) {
  for (unsigned int i = 0; i < length; ++i)
    cout << std::hex << static_cast<int>(data[i]) << " ";
  cout << endl;
}

void RDMSniffer::DumpRequest(unsigned int length, const uint8_t *data) {
  RDMRequest *request = RDMRequest::InflateFromData(data, length);
  if (request) {
    cout << (request->CommandClass() == RDMCommand::GET_COMMAND ? "GET" :
             "SET");
    cout << " src: " << request->SourceUID() << ", dst: " <<
      request->DestinationUID() << ", sub-device: " << std::dec <<
      request->SubDevice() << ", transaction: " <<
      (int) request->TransactionNumber() << ", port: " << std::dec <<
      (int) request->PortId() << ", PID 0x" << std::hex << std::setfill('0')
      << std::setw(4) << request->ParamId();
    if (m_verbose) {
      cout << ", pdl: " << request->ParamDataSize() << ", param data: ";
      const uint8_t *param_data = request->ParamData();
      for (unsigned int i = 0; i < request->ParamDataSize(); ++i)
        cout << std::hex << static_cast<int>(param_data[i]) << " ";
    }
    cout << endl;
  } else {
    DumpRawPacket(length, data);
  }
}

void RDMSniffer::DumpResponse(unsigned int length, const uint8_t *data) {
  RDMResponse *response = RDMResponse::InflateFromData(data, length);
  if (response) {
    cout << (response->CommandClass() == RDMCommand::GET_COMMAND_RESPONSE ?
        "GET_RESPONSE" : "SET_RESPONSE");
    cout << " src: " << response->SourceUID() << ", dst: " <<
      response->DestinationUID() << ", sub-device: " << std::dec <<
      response->SubDevice() << ", transaction: " <<
      (int) response->TransactionNumber() << ", response type: ";

    switch (response->ResponseType()) {
      case ola::rdm::RDM_ACK:
        cout << "ACK";
        break;
      case ola::rdm::RDM_ACK_TIMER:
        cout << "ACK TIMER";
        break;
      case ola::rdm::RDM_NACK_REASON:
        uint16_t reason;
        if (length >= 26)
          memcpy(reinterpret_cast<uint8_t*>(&reason),
                 reinterpret_cast<const void*>(data + 23),
                 sizeof(reason));
        reason = ola::network::NetworkToHost(reason);
        cout << "NACK (" << ola::rdm::NackReasonToString(reason) << ")";
        break;
      case ola::rdm::ACK_OVERFLOW:
        cout << "ACK OVERFLOW";
        break;
      default:
        cout << "Unknown (" << response->ResponseType() << ")";
    }
    cout << ", PID 0x" << std::hex <<
      std::setfill('0') << std::setw(4) << response->ParamId();
    if (m_verbose) {
      cout << ", pdl: " << response->ParamDataSize() << ", param data: ";
      const uint8_t *param_data = response->ParamData();
      for (unsigned int i = 0; i < response->ParamDataSize(); ++i)
        cout << std::hex << static_cast<int>(param_data[i]) << " ";
    }
    cout << endl;
  }
}

void RDMSniffer::DumpDiscover(unsigned int length, const uint8_t *data) {
  DumpRawPacket(length, data);
}

/*
 * Parse our command line options
 */
void ParseOptions(int argc, char *argv[], options *opts) {
  static struct option long_options[] = {
      {"dump-all", no_argument, 0, 'a'},
      {"device", required_argument, 0, 'd'},
      {"help", no_argument, 0, 'h'},
      {"log-level", required_argument, 0, 'l'},
      {"verbose", no_argument, 0, 'v'},
      {0, 0, 0, 0}
    };

  int option_index = 0;

  while (1) {
    int c = getopt_long(argc, argv, "ad:hl:v", long_options, &option_index);

    if (c == -1)
      break;

    switch (c) {
      case 0:
        break;
      case 'a':
        opts->dump_all = true;
        break;
      case 'd':
        opts->device = optarg;
        break;
      case 'h':
        opts->help = true;
        break;
      case 'l':
        switch (atoi(optarg)) {
          case 0:
            // nothing is written at this level
            // so this turns logging off
            opts->log_level = ola::OLA_LOG_NONE;
            break;
          case 1:
            opts->log_level = ola::OLA_LOG_FATAL;
            break;
          case 2:
            opts->log_level = ola::OLA_LOG_WARN;
            break;
          case 3:
            opts->log_level = ola::OLA_LOG_INFO;
            break;
          case 4:
            opts->log_level = ola::OLA_LOG_DEBUG;
            break;
          default :
            break;
        }
        break;
      case 'v':
        opts->verbose = true;
        break;
      case '?':
        break;
      default:
       break;
    }
  }
  return;
}

/*
 * Display the help message
 */
void DisplayHelpAndExit(char *argv[]) {
  cout << "Usage: " << argv[0] <<
  " -d <device>\n"
  "\n"
  "Dump RDM traffic from a Enttec USB Pro device.\n"
  "\n"
  "  -a, --dump-all     Dump all packets (default is just RDM)\n"
  "  -d <device_path>   The path to the device.\n"
  "  -h, --help         Display this help message and exit.\n"
  "  -l, --log-level <level>  Set the loggging level 0 .. 4.\n"
  "  -v, --verbose      Show more packet details\n"
  << endl;
  exit(0);
}

void Stop(ola::network::SelectServer *ss) {
  ss->Terminate();
}

/*
 * Dump RDM data
 */
int main(int argc, char *argv[]) {
  options opts;
  opts.dump_all = false;
  opts.verbose = false;
  opts.log_level = ola::OLA_LOG_INFO;
  opts.help = false;
  opts.device = DEFAULT_DEVICE;
  ParseOptions(argc, argv, &opts);

  if (opts.help)
    DisplayHelpAndExit(argv);
  ola::InitLogging(opts.log_level, ola::OLA_LOG_STDERR);

  ola::network::ConnectedSocket *socket = UsbWidget::OpenDevice(opts.device);
  if (!socket)
    exit(EX_UNAVAILABLE);

  ola::network::SelectServer ss;
  ss.AddSocket(socket);
  UsbWidget widget(socket);
  RDMSniffer sniffer(&widget, &ss, opts.dump_all, opts.verbose);

  widget.SetOnRemove(ola::NewSingleCallback(&Stop, &ss));
  ss.Run();

  return EX_OK;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cmath>
#include <list>
#include <fstream>
#include <vector>
#include "gnuplot_i.hpp"

#define GNUPLOT_PATH "C:/gnuplot/bin"
#define M_PI 3.1415926

using namespace std;

double start, stop;
double dokladnosc=0.1;
double h;
double (*funk)(double);
double (*funkN)(double);
bool metodaNewt = true;

double wezel(int k, int n){
    return cos((2*k-1)/(2.0*n)*M_PI);
}

double polynomial(double x, int n){
    int dwojka = 1;
    for(int i=0; i<=n-1;i++) dwojka*=2;

    double mnoznik = 1;
    for (int i = 1; i<=n; i++)
        mnoznik *= (x-wezel(i,n));
    //cout << "poly " << mnoznik << endl;
    return mnoznik*dwojka;
}

double calka(int n){
    double sum = 0;
    for(int k=1; k<=n;k++){
        sum += funk(wezel(k,n));
    }
    sum *= M_PI/n;

    return sum;
}

double cj(int j, int N){ //co jest zle?
    double sum = 0;
    for(int i=1; i<=N; i++){
        sum+=(funk(wezel(i,N))*polynomial(wezel(i,N), N));
        //sum+=(funk(wezel(i,N))*cos(M_PI*j*(i-0.5)/N));
    }
    sum*= (2/N);
    return sum;
}

double approx(double x, int N){
    double result = 0;
    for(int i = 0;i<=N-1;i++){
        //cout << "app " << cj(i,N)<< " " << polynomial(x,i) << endl;
        result+= (cj(i,N)*polynomial(x,i));
    }
    result -= (0.5*cj(0,N));
    return result;
}

void wypiszWektor(vector<double> w){
    for(int i=0; i< w.size(); i++){
        cout << w[i] << " ";
    }

    cout << endl;
}

void wypiszWektor(vector<double> w, string opis){
    cout << "\n" << opis << ": ";
    wypiszWektor(w);
}

double sinus(double x){
    return sin(x);
}

double specialSinus(double x){
    return sin((x+1)*M_PI/2);
}

double power(double base, double exp){
    return pow(base, exp);
}

double horner(double wsp[],int st, double x)
{
  if(st==0){
    return wsp[0];}
  return x*horner(wsp,st-1,x)+wsp[st];
}

double *wspolczynniki;
int stopien;

double waga(double x){
    return sqrt(1-x*x);
}

void wybierzFunk(){
    cout << "Wybierz funkcje: \n1. Sinus\n2. Wykladnicza\n3. Wielomian \n4. sin((x-1)*pi/2) \n> ";
    int wybor;

    cin >> wybor;

    switch(wybor){
    case 1:
        funk=sinus;
        break;
    case 2:
        funk=[](double x) -> double {return power(2,x);};
        break;
    case 3:
        cout<<"Podaj stopien wielomianu: ";
        cin>>stopien;
        wspolczynniki = new double [stopien+1];
        //wczytanie wspolczynnikow
        for(int i=0;i<=stopien;i++)
        {
          cout<<"Podaj wspolczynnik stojacy przy potedze "<<stopien-i<<": ";
          cin>>wspolczynniki[i];
        }
        funk=[](double x) -> double {return horner(wspolczynniki,stopien,x);};
        break;
    case 4:
        funk=[](double x) -> double {return specialSinus(x);};
        break;
    default:
        throw string("Function not found");
    }
}

int main()
{
    Gnuplot::set_GNUPlotPath( GNUPLOT_PATH );

    try{
        wybierzFunk();
    } catch (string s){
        cout << s << endl;
        return 0;
    }

    for(int i=2; i<=10; i++)
        cout << "Liczba wezlow: " << i <<"; WYNIK: " << calka(i) << endl;

    start = -0.99999999;
    stop = 0.999999999;

    Gnuplot main_plot;

    main_plot.set_title( "Wykres" );
    main_plot.set_xlabel( "X" );
    main_plot.set_ylabel( "Y" );

    main_plot.set_grid();
    main_plot.set_xrange( start , stop ) ;
    main_plot.set_yrange(-2,2);
    main_plot.set_style( "lines" );
    int precyzja = 10000;
    double skok = (stop-start)/precyzja;
    vector<double> x;
    vector<double> y;
    vector<double> y_approx;
    for(double d=start; d<=stop;d+=skok){
        x.push_back(d);
        y.push_back(funk(d));
        y_approx.push_back(approx(d,5));
        cout << funk(d) << " " << approx(d,5) << endl;
    }

    main_plot.plot_xy( x, y, "Wykres funkcji." );

    main_plot.plot_xy( x, y_approx, "Wykres funkcji." );

    getchar();
    getchar();
    return 0;
}

<commit_msg>W pełni działająca aproksymacja z wieloma dokładnościami na jednym wykresie - ZAD5.<commit_after>#include <iostream>
#include <cmath>
#include <list>
#include <fstream>
#include <vector>
#include "gnuplot_i.hpp"

#define GNUPLOT_PATH "C:/gnuplot/bin"
#define M_PI 3.1415926

using namespace std;

double start, stop;
double dokladnosc=0.1;
double h;
double (*funk)(double);
double (*funkN)(double);
bool metodaNewt = true;

double wezel(int k, int n){
    return cos((2*k-1)/(2.0*n)*M_PI);
}

double polynomial(double x, int n){
    /*int dwojka = 1;
    for(int i=0; i<=n-1;i++) dwojka*=2;

    double mnoznik = 1;
    for (int i = 1; i<=n; i++)
        mnoznik *= (x-wezel(i,n))!= 0 ? x-wezel(i,n) : 1;
    //cout << "poly " << mnoznik << endl;
    return mnoznik*dwojka;*/
    //return cos(n/cos(x));
    return cos(n*acos((x)));
}

double calka(int n){
    double sum = 0;
    for(int k=1; k<=n;k++){
        sum += funk(wezel(k,n));
    }
    sum *= M_PI/n;

    return sum;
}

double cj(int j, int N){ //co jest zle?
    double sum = 0;
    for(int i=1; i<=N; i++){
        //sum+=(funk(wezel(i,N))*polynomial(wezel(i,N), N)); //polynomial mnoy si raz przez zero.
        sum+=(funk(wezel(i,N))*cos(M_PI*j*(i-0.5)/N));
        //cout << "cj " << funk(wezel(i,N)) << " " << polynomial(wezel(i,N), N) << endl;
    }
    sum*= (2.0/N);
    return sum;
}

double approx(double x, int N){
    double result = 0;
    for(int i = 0;i<=N-1;i++){
        //cout << "app " << cj(i,N)<< " " << polynomial(x,i) << endl;
        result+= (cj(i,N)*polynomial(x,i));
    }
    result -= (0.5*cj(0,N));
    return result;
}

void wypiszWektor(vector<double> w){
    for(int i=0; i< w.size(); i++){
        cout << w[i] << " ";
    }

    cout << endl;
}

void wypiszWektor(vector<double> w, string opis){
    cout << "\n" << opis << ": ";
    wypiszWektor(w);
}

double sinus(double x){
    return sin(x*5);
}

double power(double base, double exp){
    return pow(base, exp);
}

double horner(double wsp[],int st, double x)
{
  if(st==0){
    return wsp[0];}
  return x*horner(wsp,st-1,x)+wsp[st];
}

double *wspolczynniki;
int stopien;

double waga(double x){
    return sqrt(1-x*x);
}

void wybierzFunk(){
    cout << "Wybierz funkcje: \n1. f(x) = sinus(5x)\n2. f(x) = 2^(5x)\n3. Wielomian \n4. f(x) = |2x| \n> ";
    int wybor;

    cin >> wybor;

    switch(wybor){
    case 1:
        funk=sinus;
        break;
    case 2:
        funk=[](double x) -> double {return power(2,x*5);};
        break;
    case 3:
        cout<<"Podaj stopien wielomianu: ";
        cin>>stopien;
        wspolczynniki = new double [stopien+1];
        //wczytanie wspolczynnikow
        for(int i=0;i<=stopien;i++)
        {
          cout<<"Podaj wspolczynnik stojacy przy potedze "<<stopien-i<<": ";
          cin>>wspolczynniki[i];
        }
        funk=[](double x) -> double {return horner(wspolczynniki,stopien,x);};
        break;
    case 4:
        funk=[](double x) -> double {return abs(2*x);};
        break;
    default:
        throw string("Function not found");
    }
}

int main()
{
    Gnuplot::set_GNUPlotPath( GNUPLOT_PATH );

    try{
        wybierzFunk();
    } catch (string s){
        cout << s << endl;
        return 0;
    }

    start = -1;
    stop = 1;

    Gnuplot main_plot;

    main_plot.set_title( "Wykres" );
    main_plot.set_xlabel( "X" );
    main_plot.set_ylabel( "Y" );

    main_plot.set_grid();
    main_plot.set_xrange( start , stop ) ;
    main_plot.set_yrange(-2,2);
    main_plot.set_style( "lines" );
    int precyzja = 100;
    double skok = (stop-start)/precyzja;
    vector<double> x;
    vector<double> y;
    vector<double> y_approx2;
    vector<double> y_approx4;
    vector<double> y_approx5;
    vector<double> y_approx7;
    vector<double> y_approx10;
    for(double d=start; d<=stop;d+=skok){
        x.push_back(d);
        y.push_back(funk(d));
        y_approx2.push_back(approx(d,2));
        y_approx4.push_back(approx(d,4));
        y_approx5.push_back(approx(d,5));
        y_approx7.push_back(approx(d,7));
        y_approx10.push_back(approx(d,10));
        //cout << funk(d) << " " << approx(d,12) << endl;
    }

    main_plot.plot_xy( x, y, "Wykres funkcji." );

    main_plot.plot_xy( x, y_approx2, "2 wezly" );
    main_plot.plot_xy( x, y_approx4, "4 wezly" );
    main_plot.plot_xy( x, y_approx5, "5 wezlow" );
    main_plot.plot_xy( x, y_approx7, "7 wezlow" );
    main_plot.plot_xy( x, y_approx10, "10 wezlow" );

    getchar();
    getchar();
    return 0;
}

<|endoftext|>


<commit_before>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2010-2012 The PECOS Development Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Version 2 GNU General
// Public License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA
// 02110-1301 USA
//
//-----------------------------------------------------------------------el-
//
// $Id$
//
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

// GRINS
#include "chemical_mixture.h"

int test_species( const std::map<std::string,GRINS::Species>& species_name_map,
		  const std::vector<GRINS::ChemicalSpecies*>& chemical_species,
		  const std::string& species_name,
		  Real molar_mass, Real gas_constant, Real formation_enthalpy,
		  Real n_tr_dofs, int charge );

int main()
{
  std::vector<std::string> species_str_list;
  const unsigned int n_species = 5;
  species_str_list.reserve(n_species);
  species_str_list.push_back( "N2" );
  species_str_list.push_back( "O2" );
  species_str_list.push_back( "N" );
  species_str_list.push_back( "O" );
  species_str_list.push_back( "NO" );

  GRINS::ChemicalMixture chem_mixture( species_str_list );

  const std::map<std::string,GRINS::Species>& species_name_map = chem_mixture.species_name_map();
  const std::vector<GRINS::ChemicalSpecies*>& chemical_species = chem_mixture.chemical_species();
  const std::vector<GRINS::Species> species_list = chem_mixture.species_list();

  int return_flag = 0;

  for( unsigned int i = 0; i < n_species; i++ )
    {
      if( species_name_map.find( species_str_list[i] )->second != species_list[i] )
	{
	  std::cerr << "Error: species name map and species list ordering mismatch" << std::endl
		    << "species_name_map = " << species_name_map.find( species_str_list[i] )->second
		    << ", species_list = " << species_list[i] << std::endl;
	  return_flag = 1;
	}
    }

  // Check N2 properties
  {
    Real molar_mass = 28.01600;
    if( molar_mass != chem_mixture.M(0) )
      {
	std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
		  << "molar mass = " << chem_mixture.M(0) << std::endl;
	return_flag = 1;
      }
    return_flag = test_species( species_name_map, chemical_species, "N2",
				molar_mass, GRINS::Constants::R_universal/molar_mass, 0.0, 2.5, 0);
  }

  // Check O2 properties
  {
    Real molar_mass = 32.00000;
    if( molar_mass != chem_mixture.M(1) )
      {
	std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
		  << "molar mass = " << chem_mixture.M(1) << std::endl;
	return_flag = 1;
      }
    return_flag = test_species( species_name_map, chemical_species, "O2",
				molar_mass, GRINS::Constants::R_universal/molar_mass, 0.0, 2.5, 0);
  }

  // Check N properties
  {
    Real molar_mass = 14.00800;
    if( molar_mass != chem_mixture.M(2) )
      {
	std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
		  << "molar mass = " << chem_mixture.M(2) << std::endl;
	return_flag = 1;
      }
    return_flag = test_species( species_name_map, chemical_species, "N",
				molar_mass, GRINS::Constants::R_universal/molar_mass, 3.3621610000e7, 1.5, 0);
  }

  // Check O properties
  {
    Real molar_mass = 16.00000;
    if( molar_mass != chem_mixture.M(3) )
      {
	std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
		  << "molar mass = " << chem_mixture.M(3) << std::endl;
	return_flag = 1;
      }
    return_flag = test_species( species_name_map, chemical_species, "O",
				molar_mass, GRINS::Constants::R_universal/molar_mass, 1.5420000000e7, 1.5, 0);
  }

  // Check NO properties
  {
    Real molar_mass = 30.00800;
    if( molar_mass != chem_mixture.M(4) )
      {
	std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
		  << "molar mass = " << chem_mixture.M(4) << std::endl;
	return_flag = 1;
      }
    return_flag = test_species( species_name_map, chemical_species, "NO",
				molar_mass, GRINS::Constants::R_universal/molar_mass, 2.9961230000e6, 2.5, 0);
  }

  return return_flag;
}

int test_species( const std::map<std::string,GRINS::Species>& species_name_map,
		  const std::vector<GRINS::ChemicalSpecies*>& chemical_species,
		  const std::string& species_name,
		  Real molar_mass, Real gas_constant, Real formation_enthalpy,
		  Real n_tr_dofs, int charge )
{

  int return_flag = 0;

  GRINS::Species species = species_name_map.find( species_name )->second;
  const GRINS::ChemicalSpecies& chem_species = *(chemical_species[species]);

  if( chem_species.species() != species_name )
    {
      std::cerr << "Error: Name mismatch for "<< species_name << std::endl
		<< "name = " << chem_species.species() << std::endl;
      return_flag = 1;
    }

  if( chem_species.molar_mass() != molar_mass )
    {
      std::cerr << "Error: Molar mass mismatch for "<< species_name << std::endl
		<< "molar mass = " << chem_species.molar_mass() << std::endl;
      return_flag = 1;
    }

  if( chem_species.gas_constant() != gas_constant )
    {
      std::cerr << "Error: Gas constant mismatch for "<< species_name << std::endl
		<< "gas constant = " << chem_species.gas_constant() << std::endl;
      return_flag = 1;
    }

  if( chem_species.formation_enthalpy() != formation_enthalpy )
    {
      std::cerr << "Error: Formation enthalpy mismatch for "<< species_name << std::endl
		<< "formation enthalpy = " << chem_species.formation_enthalpy() << std::endl;
      return_flag = 1;
    }

  if( chem_species.n_tr_dofs() != n_tr_dofs )
    {
      std::cerr << "Error: Number translational DoFs mismatch for "<< species_name << std::endl
		<< "n_tr_dofs = " << chem_species.n_tr_dofs() << std::endl;
      return_flag = 1;
    }

  if( chem_species.charge() != charge )
    {
      std::cerr << "Error: Charge mismatch for "<< species_name << std::endl
		<< "charge = " << chem_species.charge() << std::endl;
      return_flag = 1;
    }

  return return_flag;
}
<commit_msg>[GRINS]: ChemicalMixture test fixed for API update (#2600).<commit_after>//-----------------------------------------------------------------------bl-
//--------------------------------------------------------------------------
//
// GRINS - General Reacting Incompressible Navier-Stokes
//
// Copyright (C) 2010-2012 The PECOS Development Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Version 2 GNU General
// Public License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this library; if not, write to the Free Software
// Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA
// 02110-1301 USA
//
//-----------------------------------------------------------------------el-
//
// $Id$
//
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------

// GRINS
#include "chemical_mixture.h"

int test_species( const unsigned int species,
		  const std::vector<GRINS::ChemicalSpecies*>& chemical_species,
		  const std::string& species_name,
		  Real molar_mass, Real gas_constant, Real formation_enthalpy,
		  Real n_tr_dofs, int charge );

int main()
{
  std::vector<std::string> species_str_list;
  const unsigned int n_species = 5;
  species_str_list.reserve(n_species);
  species_str_list.push_back( "N2" );
  species_str_list.push_back( "O2" );
  species_str_list.push_back( "N" );
  species_str_list.push_back( "O" );
  species_str_list.push_back( "NO" );

  GRINS::ChemicalMixture chem_mixture( species_str_list );

  const std::map<std::string,GRINS::Species>& species_name_map = chem_mixture.species_name_map();
  const std::vector<GRINS::ChemicalSpecies*>& chemical_species = chem_mixture.chemical_species();
  const std::vector<GRINS::Species> species_list = chem_mixture.species_list();

  int return_flag = 0;

  for( unsigned int i = 0; i < n_species; i++ )
    {
      if( species_name_map.find( species_str_list[i] )->second != species_list[i] )
	{
	  std::cerr << "Error: species name map and species list ordering mismatch" << std::endl
		    << "species_name_map = " << species_name_map.find( species_str_list[i] )->second
		    << ", species_list = " << species_list[i] << std::endl;
	  return_flag = 1;
	}
    }

  // Check N2 properties
  {
    unsigned int index = 0;
    Real molar_mass = 28.01600;
    if( molar_mass != chem_mixture.M(index) )
      {
	std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
		  << "molar mass = " << chem_mixture.M(index) << std::endl;
	return_flag = 1;
      }
    return_flag = test_species( index, chemical_species, "N2",
				molar_mass, GRINS::Constants::R_universal/molar_mass, 0.0, 2.5, 0);
  }

  // Check O2 properties
  {
    unsigned int index = 1;
    Real molar_mass = 32.00000;
    if( molar_mass != chem_mixture.M(index) )
      {
	std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
		  << "molar mass = " << chem_mixture.M(index) << std::endl;
	return_flag = 1;
      }
    return_flag = test_species( index, chemical_species, "O2",
				molar_mass, GRINS::Constants::R_universal/molar_mass, 0.0, 2.5, 0);
  }

  // Check N properties
  {
    unsigned int index = 2;
    Real molar_mass = 14.00800;
    if( molar_mass != chem_mixture.M(index) )
      {
	std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
		  << "molar mass = " << chem_mixture.M(index) << std::endl;
	return_flag = 1;
      }
    return_flag = test_species( index, chemical_species, "N",
				molar_mass, GRINS::Constants::R_universal/molar_mass, 3.3621610000e7, 1.5, 0);
  }

  // Check O properties
  {
    unsigned int index = 3;
    Real molar_mass = 16.00000;
    if( molar_mass != chem_mixture.M(index) )
      {
	std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
		  << "molar mass = " << chem_mixture.M(index) << std::endl;
	return_flag = 1;
      }
    return_flag = test_species( index, chemical_species, "O",
				molar_mass, GRINS::Constants::R_universal/molar_mass, 1.5420000000e7, 1.5, 0);
  }

  // Check NO properties
  {
    unsigned int index = 4;
    Real molar_mass = 30.00800;
    if( molar_mass != chem_mixture.M(index) )
      {
	std::cerr << "Error: Molar mass inconsistency in mixture" << std::endl
		  << "molar mass = " << chem_mixture.M(index) << std::endl;
	return_flag = 1;
      }
    return_flag = test_species( index, chemical_species, "NO",
				molar_mass, GRINS::Constants::R_universal/molar_mass, 2.9961230000e6, 2.5, 0);
  }

  return return_flag;
}

int test_species( const unsigned int species,
		  const std::vector<GRINS::ChemicalSpecies*>& chemical_species,
		  const std::string& species_name,
		  Real molar_mass, Real gas_constant, Real formation_enthalpy,
		  Real n_tr_dofs, int charge )
{

  int return_flag = 0;

  const GRINS::ChemicalSpecies& chem_species = *(chemical_species[species]);

  if( chem_species.species() != species_name )
    {
      std::cerr << "Error: Name mismatch for "<< species_name << std::endl
		<< "name = " << chem_species.species() << std::endl;
      return_flag = 1;
    }

  if( chem_species.molar_mass() != molar_mass )
    {
      std::cerr << "Error: Molar mass mismatch for "<< species_name << std::endl
		<< "molar mass = " << chem_species.molar_mass() << std::endl;
      return_flag = 1;
    }

  if( chem_species.gas_constant() != gas_constant )
    {
      std::cerr << "Error: Gas constant mismatch for "<< species_name << std::endl
		<< "gas constant = " << chem_species.gas_constant() << std::endl;
      return_flag = 1;
    }

  if( chem_species.formation_enthalpy() != formation_enthalpy )
    {
      std::cerr << "Error: Formation enthalpy mismatch for "<< species_name << std::endl
		<< "formation enthalpy = " << chem_species.formation_enthalpy() << std::endl;
      return_flag = 1;
    }

  if( chem_species.n_tr_dofs() != n_tr_dofs )
    {
      std::cerr << "Error: Number translational DoFs mismatch for "<< species_name << std::endl
		<< "n_tr_dofs = " << chem_species.n_tr_dofs() << std::endl;
      return_flag = 1;
    }

  if( chem_species.charge() != charge )
    {
      std::cerr << "Error: Charge mismatch for "<< species_name << std::endl
		<< "charge = " << chem_species.charge() << std::endl;
      return_flag = 1;
    }

  return return_flag;
}
<|endoftext|>


<commit_before>//===-- PrologEpilogInserter.cpp - Insert Prolog/Epilog code in function --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass is responsible for finalizing the functions frame layout, saving
// callee saved registers, and for emitting prolog & epilog code for the
// function.
//
// This pass must be run after register allocation.  After this pass is
// executed, it is illegal to construct MO_FrameIndex operands.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
using namespace llvm;

namespace {
  struct PEI : public MachineFunctionPass {
    const char *getPassName() const {
      return "Prolog/Epilog Insertion & Frame Finalization";
    }

    /// runOnMachineFunction - Insert prolog/epilog code and replace abstract
    /// frame indexes with appropriate references.
    ///
    bool runOnMachineFunction(MachineFunction &Fn) {
      // Scan the function for modified caller saved registers and insert spill
      // code for any caller saved registers that are modified.  Also calculate
      // the MaxCallFrameSize and HasCalls variables for the function's frame
      // information and eliminates call frame pseudo instructions.
      calculateCallerSavedRegisters(Fn);

      // Add the code to save and restore the caller saved registers
      saveCallerSavedRegisters(Fn);

      // Allow the target machine to make final modifications to the function
      // before the frame layout is finalized.
      Fn.getTarget().getRegisterInfo()->processFunctionBeforeFrameFinalized(Fn);

      // Calculate actual frame offsets for all of the abstract stack objects...
      calculateFrameObjectOffsets(Fn);

      // Add prolog and epilog code to the function.  This function is required
      // to align the stack frame as necessary for any stack variables or
      // called functions.  Because of this, calculateCallerSavedRegisters
      // must be called before this function in order to set the HasCalls
      // and MaxCallFrameSize variables.
      insertPrologEpilogCode(Fn);

      // Replace all MO_FrameIndex operands with physical register references
      // and actual offsets.
      //
      replaceFrameIndices(Fn);

      RegsToSave.clear();
      StackSlots.clear();
      return true;
    }

  private:
    std::vector<unsigned> RegsToSave;
    std::vector<int> StackSlots;

    void calculateCallerSavedRegisters(MachineFunction &Fn);
    void saveCallerSavedRegisters(MachineFunction &Fn);
    void calculateFrameObjectOffsets(MachineFunction &Fn);
    void replaceFrameIndices(MachineFunction &Fn);
    void insertPrologEpilogCode(MachineFunction &Fn);
  };
}

/// createPrologEpilogCodeInserter - This function returns a pass that inserts
/// prolog and epilog code, and eliminates abstract frame references.
///
FunctionPass *llvm::createPrologEpilogCodeInserter() { return new PEI(); }

/// calculateCallerSavedRegisters - Scan the function for modified caller saved
/// registers.  Also calculate the MaxCallFrameSize and HasCalls variables for
/// the function's frame information and eliminates call frame pseudo
/// instructions.
///
void PEI::calculateCallerSavedRegisters(MachineFunction &Fn) {
  const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();
  const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo();
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();

  // Get the callee saved register list...
  const unsigned *CSRegs = RegInfo->getCalleeSaveRegs();

  // Get the function call frame set-up and tear-down instruction opcode
  int FrameSetupOpcode   = RegInfo->getCallFrameSetupOpcode();
  int FrameDestroyOpcode = RegInfo->getCallFrameDestroyOpcode();

  // Early exit for targets which have no callee saved registers and no call
  // frame setup/destroy pseudo instructions.
  if ((CSRegs == 0 || CSRegs[0] == 0) &&
      FrameSetupOpcode == -1 && FrameDestroyOpcode == -1)
    return;

  // This bitset contains an entry for each physical register for the target...
  std::vector<bool> ModifiedRegs(RegInfo->getNumRegs());
  unsigned MaxCallFrameSize = 0;
  bool HasCalls = false;

  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); )
      if (I->getOpcode() == FrameSetupOpcode ||
          I->getOpcode() == FrameDestroyOpcode) {
        assert(I->getNumOperands() == 1 && "Call Frame Setup/Destroy Pseudo"
               " instructions should have a single immediate argument!");
        unsigned Size = I->getOperand(0).getImmedValue();
        if (Size > MaxCallFrameSize) MaxCallFrameSize = Size;
        HasCalls = true;
        RegInfo->eliminateCallFramePseudoInstr(Fn, *BB, I++);
      } else {
        for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
          MachineOperand &MO = I->getOperand(i);
          if (MO.isRegister() && MO.isDef()) {
            assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) &&
                   "Register allocation must be performed!");
            ModifiedRegs[MO.getReg()] = true;         // Register is modified
          }

          // Mark any implicitly defined registers as being modified.
          for (const unsigned *ImpDefs = TII.getImplicitDefs(I->getOpcode());
               *ImpDefs; ++ImpDefs)
            ModifiedRegs[*ImpDefs] = true;
        }
        ++I;
      }

  MachineFrameInfo *FFI = Fn.getFrameInfo();
  FFI->setHasCalls(HasCalls);
  FFI->setMaxCallFrameSize(MaxCallFrameSize);

  // Now figure out which *callee saved* registers are modified by the current
  // function, thus needing to be saved and restored in the prolog/epilog.
  //
  for (unsigned i = 0; CSRegs[i]; ++i) {
    unsigned Reg = CSRegs[i];
    if (ModifiedRegs[Reg]) {
      RegsToSave.push_back(Reg);  // If modified register...
    } else {
      for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg);
           *AliasSet; ++AliasSet) {  // Check alias registers too...
        if (ModifiedRegs[*AliasSet]) {
          RegsToSave.push_back(Reg);
          break;
        }
      }
    }
  }

  if (RegsToSave.empty())
    return;   // Early exit if no caller saved registers are modified!

  unsigned NumFixedSpillSlots;
  const std::pair<unsigned,int> *FixedSpillSlots =
    TFI->getCalleeSaveSpillSlots(NumFixedSpillSlots);

  // Now that we know which registers need to be saved and restored, allocate
  // stack slots for them.
  for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
    unsigned Reg = RegsToSave[i];

    // Check to see if this physreg must be spilled to a particular stack slot
    // on this target.
    const std::pair<unsigned,int> *FixedSlot = FixedSpillSlots;
    while (FixedSlot != FixedSpillSlots+NumFixedSpillSlots &&
           FixedSlot->first != Reg)
      ++FixedSlot;

    int FrameIdx;
    if (FixedSlot == FixedSpillSlots+NumFixedSpillSlots) {
      // Nope, just spill it anywhere convenient.
      FrameIdx = FFI->CreateStackObject(RegInfo->getSpillSize(Reg)/8,
                                        RegInfo->getSpillAlignment(Reg)/8);
    } else {
      // Spill it to the stack where we must.
      FrameIdx = FFI->CreateFixedObject(RegInfo->getSpillSize(Reg)/8,
                                        FixedSlot->second);
    }
    StackSlots.push_back(FrameIdx);
  }
}

/// saveCallerSavedRegisters -  Insert spill code for any caller saved registers
/// that are modified in the function.
///
void PEI::saveCallerSavedRegisters(MachineFunction &Fn) {
  // Early exit if no caller saved registers are modified!
  if (RegsToSave.empty())
    return;

  const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();

  // Now that we have a stack slot for each register to be saved, insert spill
  // code into the entry block...
  MachineBasicBlock *MBB = Fn.begin();
  MachineBasicBlock::iterator I = MBB->begin();
  for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
    // Insert the spill to the stack frame.
    RegInfo->storeRegToStackSlot(*MBB, I, RegsToSave[i], StackSlots[i]);
  }

  // Add code to restore the callee-save registers in each exiting block.
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
  for (MachineFunction::iterator FI = Fn.begin(), E = Fn.end(); FI != E; ++FI) {
    // If last instruction is a return instruction, add an epilogue
    if (!FI->empty() && TII.isReturn(FI->back().getOpcode())) {
      MBB = FI;
      I = MBB->end(); --I;

      for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
        RegInfo->loadRegFromStackSlot(*MBB, I, RegsToSave[i], StackSlots[i]);
        assert(I != MBB->begin() &&
               "loadRegFromStackSlot didn't insert any code!");
        --I;  // Insert in reverse order
      }
    }
  }
}

/// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the
/// abstract stack objects...
///
void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
  const TargetFrameInfo &TFI = *Fn.getTarget().getFrameInfo();

  bool StackGrowsDown =
    TFI.getStackGrowthDirection() == TargetFrameInfo::StackGrowsDown;

  // Loop over all of the stack objects, assigning sequential addresses...
  MachineFrameInfo *FFI = Fn.getFrameInfo();

  unsigned StackAlignment = TFI.getStackAlignment();

  // Start at the beginning of the local area.
  // The Offset is the distance from the stack top in the direction
  // of stack growth -- so it's always positive.
  int Offset = TFI.getOffsetOfLocalArea();
  if (StackGrowsDown)
    Offset = -Offset;
  assert(Offset >= 0
         && "Local area offset should be in direction of stack growth");

  // If there are fixed sized objects that are preallocated in the local area,
  // non-fixed objects can't be allocated right at the start of local area.
  // We currently don't support filling in holes in between fixed sized objects,
  // so we adjust 'Offset' to point to the end of last fixed sized
  // preallocated object.
  for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) {
    int FixedOff;
    if (StackGrowsDown) {
      // The maximum distance from the stack pointer is at lower address of
      // the object -- which is given by offset. For down growing stack
      // the offset is negative, so we negate the offset to get the distance.
      FixedOff = -FFI->getObjectOffset(i);
    } else {
      // The maximum distance from the start pointer is at the upper
      // address of the object.
      FixedOff = FFI->getObjectOffset(i) + FFI->getObjectSize(i);
    }
    if (FixedOff > Offset) Offset = FixedOff;
  }

  for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
    // If stack grows down, we need to add size of find the lowest
    // address of the object.
    if (StackGrowsDown)
      Offset += FFI->getObjectSize(i);

    unsigned Align = FFI->getObjectAlignment(i);
    assert(Align <= StackAlignment && "Cannot align stack object to higher "
           "alignment boundary than the stack itself!");
    Offset = (Offset+Align-1)/Align*Align;   // Adjust to Alignment boundary...

    if (StackGrowsDown) {
      FFI->setObjectOffset(i, -Offset);        // Set the computed offset
    } else {
      FFI->setObjectOffset(i, Offset);
      Offset += FFI->getObjectSize(i);
    }
  }

  // Align the final stack pointer offset, but only if there are calls in the
  // function.  This ensures that any calls to subroutines have their stack
  // frames suitable aligned.
  if (FFI->hasCalls())
    Offset = (Offset+StackAlignment-1)/StackAlignment*StackAlignment;

  // Set the final value of the stack pointer...
  FFI->setStackSize(Offset+TFI.getOffsetOfLocalArea());
}

/// insertPrologEpilogCode - Scan the function for modified caller saved
/// registers, insert spill code for these caller saved registers, then add
/// prolog and epilog code to the function.
///
void PEI::insertPrologEpilogCode(MachineFunction &Fn) {
  // Add prologue to the function...
  Fn.getTarget().getRegisterInfo()->emitPrologue(Fn);

  // Add epilogue to restore the callee-save registers in each exiting block
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
  for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
    // If last instruction is a return instruction, add an epilogue
    if (!I->empty() && TII.isReturn(I->back().getOpcode()))
      Fn.getTarget().getRegisterInfo()->emitEpilogue(Fn, *I);
  }
}

/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical
/// register references and actual offsets.
///
void PEI::replaceFrameIndices(MachineFunction &Fn) {
  if (!Fn.getFrameInfo()->hasStackObjects()) return; // Nothing to do?

  const TargetMachine &TM = Fn.getTarget();
  assert(TM.getRegisterInfo() && "TM::getRegisterInfo() must be implemented!");
  const MRegisterInfo &MRI = *TM.getRegisterInfo();

  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
      for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
        if (I->getOperand(i).isFrameIndex()) {
          // If this instruction has a FrameIndex operand, we need to use that
          // target machine register info object to eliminate it.
          MRI.eliminateFrameIndex(I);
          break;
        }
}
<commit_msg>Speed this up a bit by making ModifiedRegs a vector<char> not vector<bool><commit_after>//===-- PrologEpilogInserter.cpp - Insert Prolog/Epilog code in function --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass is responsible for finalizing the functions frame layout, saving
// callee saved registers, and for emitting prolog & epilog code for the
// function.
//
// This pass must be run after register allocation.  After this pass is
// executed, it is illegal to construct MO_FrameIndex operands.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
using namespace llvm;

namespace {
  struct PEI : public MachineFunctionPass {
    const char *getPassName() const {
      return "Prolog/Epilog Insertion & Frame Finalization";
    }

    /// runOnMachineFunction - Insert prolog/epilog code and replace abstract
    /// frame indexes with appropriate references.
    ///
    bool runOnMachineFunction(MachineFunction &Fn) {
      // Scan the function for modified caller saved registers and insert spill
      // code for any caller saved registers that are modified.  Also calculate
      // the MaxCallFrameSize and HasCalls variables for the function's frame
      // information and eliminates call frame pseudo instructions.
      calculateCallerSavedRegisters(Fn);

      // Add the code to save and restore the caller saved registers
      saveCallerSavedRegisters(Fn);

      // Allow the target machine to make final modifications to the function
      // before the frame layout is finalized.
      Fn.getTarget().getRegisterInfo()->processFunctionBeforeFrameFinalized(Fn);

      // Calculate actual frame offsets for all of the abstract stack objects...
      calculateFrameObjectOffsets(Fn);

      // Add prolog and epilog code to the function.  This function is required
      // to align the stack frame as necessary for any stack variables or
      // called functions.  Because of this, calculateCallerSavedRegisters
      // must be called before this function in order to set the HasCalls
      // and MaxCallFrameSize variables.
      insertPrologEpilogCode(Fn);

      // Replace all MO_FrameIndex operands with physical register references
      // and actual offsets.
      //
      replaceFrameIndices(Fn);

      RegsToSave.clear();
      StackSlots.clear();
      return true;
    }

  private:
    std::vector<unsigned> RegsToSave;
    std::vector<int> StackSlots;

    void calculateCallerSavedRegisters(MachineFunction &Fn);
    void saveCallerSavedRegisters(MachineFunction &Fn);
    void calculateFrameObjectOffsets(MachineFunction &Fn);
    void replaceFrameIndices(MachineFunction &Fn);
    void insertPrologEpilogCode(MachineFunction &Fn);
  };
}

/// createPrologEpilogCodeInserter - This function returns a pass that inserts
/// prolog and epilog code, and eliminates abstract frame references.
///
FunctionPass *llvm::createPrologEpilogCodeInserter() { return new PEI(); }

/// calculateCallerSavedRegisters - Scan the function for modified caller saved
/// registers.  Also calculate the MaxCallFrameSize and HasCalls variables for
/// the function's frame information and eliminates call frame pseudo
/// instructions.
///
void PEI::calculateCallerSavedRegisters(MachineFunction &Fn) {
  const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();
  const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo();
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();

  // Get the callee saved register list...
  const unsigned *CSRegs = RegInfo->getCalleeSaveRegs();

  // Get the function call frame set-up and tear-down instruction opcode
  int FrameSetupOpcode   = RegInfo->getCallFrameSetupOpcode();
  int FrameDestroyOpcode = RegInfo->getCallFrameDestroyOpcode();

  // Early exit for targets which have no callee saved registers and no call
  // frame setup/destroy pseudo instructions.
  if ((CSRegs == 0 || CSRegs[0] == 0) &&
      FrameSetupOpcode == -1 && FrameDestroyOpcode == -1)
    return;

  // This bitset contains an entry for each physical register for the target...
  std::vector<char> ModifiedRegs(RegInfo->getNumRegs());
  unsigned MaxCallFrameSize = 0;
  bool HasCalls = false;

  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); )
      if (I->getOpcode() == FrameSetupOpcode ||
          I->getOpcode() == FrameDestroyOpcode) {
        assert(I->getNumOperands() == 1 && "Call Frame Setup/Destroy Pseudo"
               " instructions should have a single immediate argument!");
        unsigned Size = I->getOperand(0).getImmedValue();
        if (Size > MaxCallFrameSize) MaxCallFrameSize = Size;
        HasCalls = true;
        RegInfo->eliminateCallFramePseudoInstr(Fn, *BB, I++);
      } else {
        for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
          MachineOperand &MO = I->getOperand(i);
          if (MO.isRegister() && MO.isDef()) {
            assert(MRegisterInfo::isPhysicalRegister(MO.getReg()) &&
                   "Register allocation must be performed!");
            ModifiedRegs[MO.getReg()] = true;         // Register is modified
          }

          // Mark any implicitly defined registers as being modified.
          for (const unsigned *ImpDefs = TII.getImplicitDefs(I->getOpcode());
               *ImpDefs; ++ImpDefs)
            ModifiedRegs[*ImpDefs] = true;
        }
        ++I;
      }

  MachineFrameInfo *FFI = Fn.getFrameInfo();
  FFI->setHasCalls(HasCalls);
  FFI->setMaxCallFrameSize(MaxCallFrameSize);

  // Now figure out which *callee saved* registers are modified by the current
  // function, thus needing to be saved and restored in the prolog/epilog.
  //
  for (unsigned i = 0; CSRegs[i]; ++i) {
    unsigned Reg = CSRegs[i];
    if (ModifiedRegs[Reg]) {
      RegsToSave.push_back(Reg);  // If modified register...
    } else {
      for (const unsigned *AliasSet = RegInfo->getAliasSet(Reg);
           *AliasSet; ++AliasSet) {  // Check alias registers too...
        if (ModifiedRegs[*AliasSet]) {
          RegsToSave.push_back(Reg);
          break;
        }
      }
    }
  }

  if (RegsToSave.empty())
    return;   // Early exit if no caller saved registers are modified!

  unsigned NumFixedSpillSlots;
  const std::pair<unsigned,int> *FixedSpillSlots =
    TFI->getCalleeSaveSpillSlots(NumFixedSpillSlots);

  // Now that we know which registers need to be saved and restored, allocate
  // stack slots for them.
  for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
    unsigned Reg = RegsToSave[i];

    // Check to see if this physreg must be spilled to a particular stack slot
    // on this target.
    const std::pair<unsigned,int> *FixedSlot = FixedSpillSlots;
    while (FixedSlot != FixedSpillSlots+NumFixedSpillSlots &&
           FixedSlot->first != Reg)
      ++FixedSlot;

    int FrameIdx;
    if (FixedSlot == FixedSpillSlots+NumFixedSpillSlots) {
      // Nope, just spill it anywhere convenient.
      FrameIdx = FFI->CreateStackObject(RegInfo->getSpillSize(Reg)/8,
                                        RegInfo->getSpillAlignment(Reg)/8);
    } else {
      // Spill it to the stack where we must.
      FrameIdx = FFI->CreateFixedObject(RegInfo->getSpillSize(Reg)/8,
                                        FixedSlot->second);
    }
    StackSlots.push_back(FrameIdx);
  }
}

/// saveCallerSavedRegisters -  Insert spill code for any caller saved registers
/// that are modified in the function.
///
void PEI::saveCallerSavedRegisters(MachineFunction &Fn) {
  // Early exit if no caller saved registers are modified!
  if (RegsToSave.empty())
    return;

  const MRegisterInfo *RegInfo = Fn.getTarget().getRegisterInfo();

  // Now that we have a stack slot for each register to be saved, insert spill
  // code into the entry block.
  MachineBasicBlock *MBB = Fn.begin();
  MachineBasicBlock::iterator I = MBB->begin();
  for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
    // Insert the spill to the stack frame.
    RegInfo->storeRegToStackSlot(*MBB, I, RegsToSave[i], StackSlots[i]);
  }

  // Add code to restore the callee-save registers in each exiting block.
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
  for (MachineFunction::iterator FI = Fn.begin(), E = Fn.end(); FI != E; ++FI)
    // If last instruction is a return instruction, add an epilogue.
    if (!FI->empty() && TII.isReturn(FI->back().getOpcode())) {
      MBB = FI;
      I = MBB->end(); --I;

      for (unsigned i = 0, e = RegsToSave.size(); i != e; ++i) {
        RegInfo->loadRegFromStackSlot(*MBB, I, RegsToSave[i], StackSlots[i]);
        assert(I != MBB->begin() &&
               "loadRegFromStackSlot didn't insert any code!");
        --I;  // Insert in reverse order
      }
    }
}

/// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the
/// abstract stack objects.
///
void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) {
  const TargetFrameInfo &TFI = *Fn.getTarget().getFrameInfo();

  bool StackGrowsDown =
    TFI.getStackGrowthDirection() == TargetFrameInfo::StackGrowsDown;

  // Loop over all of the stack objects, assigning sequential addresses...
  MachineFrameInfo *FFI = Fn.getFrameInfo();

  unsigned StackAlignment = TFI.getStackAlignment();

  // Start at the beginning of the local area.
  // The Offset is the distance from the stack top in the direction
  // of stack growth -- so it's always positive.
  int Offset = TFI.getOffsetOfLocalArea();
  if (StackGrowsDown)
    Offset = -Offset;
  assert(Offset >= 0
         && "Local area offset should be in direction of stack growth");

  // If there are fixed sized objects that are preallocated in the local area,
  // non-fixed objects can't be allocated right at the start of local area.
  // We currently don't support filling in holes in between fixed sized objects,
  // so we adjust 'Offset' to point to the end of last fixed sized
  // preallocated object.
  for (int i = FFI->getObjectIndexBegin(); i != 0; ++i) {
    int FixedOff;
    if (StackGrowsDown) {
      // The maximum distance from the stack pointer is at lower address of
      // the object -- which is given by offset. For down growing stack
      // the offset is negative, so we negate the offset to get the distance.
      FixedOff = -FFI->getObjectOffset(i);
    } else {
      // The maximum distance from the start pointer is at the upper
      // address of the object.
      FixedOff = FFI->getObjectOffset(i) + FFI->getObjectSize(i);
    }
    if (FixedOff > Offset) Offset = FixedOff;
  }

  for (unsigned i = 0, e = FFI->getObjectIndexEnd(); i != e; ++i) {
    // If stack grows down, we need to add size of find the lowest
    // address of the object.
    if (StackGrowsDown)
      Offset += FFI->getObjectSize(i);

    unsigned Align = FFI->getObjectAlignment(i);
    assert(Align <= StackAlignment && "Cannot align stack object to higher "
           "alignment boundary than the stack itself!");
    Offset = (Offset+Align-1)/Align*Align;   // Adjust to Alignment boundary...

    if (StackGrowsDown) {
      FFI->setObjectOffset(i, -Offset);        // Set the computed offset
    } else {
      FFI->setObjectOffset(i, Offset);
      Offset += FFI->getObjectSize(i);
    }
  }

  // Align the final stack pointer offset, but only if there are calls in the
  // function.  This ensures that any calls to subroutines have their stack
  // frames suitable aligned.
  if (FFI->hasCalls())
    Offset = (Offset+StackAlignment-1)/StackAlignment*StackAlignment;

  // Set the final value of the stack pointer...
  FFI->setStackSize(Offset+TFI.getOffsetOfLocalArea());
}

/// insertPrologEpilogCode - Scan the function for modified caller saved
/// registers, insert spill code for these caller saved registers, then add
/// prolog and epilog code to the function.
///
void PEI::insertPrologEpilogCode(MachineFunction &Fn) {
  // Add prologue to the function...
  Fn.getTarget().getRegisterInfo()->emitPrologue(Fn);

  // Add epilogue to restore the callee-save registers in each exiting block
  const TargetInstrInfo &TII = *Fn.getTarget().getInstrInfo();
  for (MachineFunction::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) {
    // If last instruction is a return instruction, add an epilogue
    if (!I->empty() && TII.isReturn(I->back().getOpcode()))
      Fn.getTarget().getRegisterInfo()->emitEpilogue(Fn, *I);
  }
}

/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical
/// register references and actual offsets.
///
void PEI::replaceFrameIndices(MachineFunction &Fn) {
  if (!Fn.getFrameInfo()->hasStackObjects()) return; // Nothing to do?

  const TargetMachine &TM = Fn.getTarget();
  assert(TM.getRegisterInfo() && "TM::getRegisterInfo() must be implemented!");
  const MRegisterInfo &MRI = *TM.getRegisterInfo();

  for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB)
    for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
      for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
        if (I->getOperand(i).isFrameIndex()) {
          // If this instruction has a FrameIndex operand, we need to use that
          // target machine register info object to eliminate it.
          MRI.eliminateFrameIndex(I);
          break;
        }
}
<|endoftext|>