<commit_before>//===-- CPPLanguageRuntime.cpp
//-------------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"

#include <string.h>

#include <memory>

#include "llvm/ADT/StringRef.h"

#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"

#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Target/ThreadPlanStepInRange.h"

using namespace lldb;
using namespace lldb_private;

static ConstString g_this = ConstString("this");

// Destructor
CPPLanguageRuntime::~CPPLanguageRuntime() {}

CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
    : LanguageRuntime(process) {}

bool CPPLanguageRuntime::IsRuntimeSupportValue(ValueObject &valobj) {
  // All runtime support values have to be marked as artificial by the
  // compiler. But not all artificial variables should be hidden from
  // the user.
  if (!valobj.GetVariable())
    return false;
  if (!valobj.GetVariable()->IsArtificial())
    return false;

  // Whitelist "this" and since there is no ObjC++ runtime, any ObjC names.
  ConstString name = valobj.GetName();
  if (name == g_this)
    return false;
  return !ObjCLanguageRuntime::IsWhitelistedRuntimeValue(name);
}

bool CPPLanguageRuntime::GetObjectDescription(Stream &str,
                                              ValueObject &object) {
  // C++ has no generic way to do this.
  return false;
}

bool CPPLanguageRuntime::GetObjectDescription(
    Stream &str, Value &value, ExecutionContextScope *exe_scope) {
  // C++ has no generic way to do this.
  return false;
}

CPPLanguageRuntime::LibCppStdFunctionCallableInfo
CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
    lldb::ValueObjectSP &valobj_sp) {
  LibCppStdFunctionCallableInfo optional_info;

  if (!valobj_sp)
    return optional_info;

  // Member __f_ has type __base*, the contents of which will hold:
  // 1) a vtable entry which may hold type information needed to discover the
  //    lambda being called
  // 2) possibly hold a pointer to the callable object
  // e.g.
  //
  // (lldb) frame var -R  f_display
  // (std::__1::function<void (int)>) f_display = {
  //  __buf_ = {
  //  …
  // }
  //  __f_ = 0x00007ffeefbffa00
  // }
  // (lldb) memory read -fA 0x00007ffeefbffa00
  // 0x7ffeefbffa00: ... `vtable for std::__1::__function::__func<void (*) ...
  // 0x7ffeefbffa08: ... `print_num(int) at std_function_cppreference_exam ...
  //
  // We will be handling five cases below, std::function is wrapping:
  //
  // 1) a lambda we know at compile time. We will obtain the name of the lambda
  //    from the first template pameter from __func's vtable. We will look up
  //    the lambda's operator()() and obtain the line table entry.
  // 2) a lambda we know at runtime. A pointer to the lambdas __invoke method
  //    will be stored after the vtable. We will obtain the lambdas name from
  //    this entry and lookup operator()() and obtain the line table entry.
  // 3) a callable object via operator()(). We will obtain the name of the
  //    object from the first template parameter from __func's vtable. We will
  //    look up the objectc operator()() and obtain the line table entry.
  // 4) a member function. A pointer to the function will stored after the
  //    we will obtain the name from this pointer.
  // 5) a free function. A pointer to the function will stored after the vtable
  //    we will obtain the name from this pointer.
  ValueObjectSP member__f_(
      valobj_sp->GetChildMemberWithName(ConstString("__f_"), true));

  if (member__f_) {
    ValueObjectSP sub_member__f_(
       member__f_->GetChildMemberWithName(ConstString("__f_"), true));

    if (sub_member__f_)
        member__f_ = sub_member__f_;
  }

  lldb::addr_t member__f_pointer_value = member__f_->GetValueAsUnsigned(0);

  optional_info.member__f_pointer_value = member__f_pointer_value;

  ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
  Process *process = exe_ctx.GetProcessPtr();

  if (process == nullptr)
    return optional_info;

  uint32_t address_size = process->GetAddressByteSize();
  Status status;

  // First item pointed to by __f_ should be the pointer to the vtable for
  // a __base object.
  lldb::addr_t vtable_address =
      process->ReadPointerFromMemory(member__f_pointer_value, status);

  if (status.Fail())
    return optional_info;

  lldb::addr_t address_after_vtable = member__f_pointer_value + address_size;
  // As commened above we may not have a function pointer but if we do we will
  // need it.
  lldb::addr_t possible_function_address =
      process->ReadPointerFromMemory(address_after_vtable, status);

  if (status.Fail())
    return optional_info;

  Target &target = process->GetTarget();

  if (target.GetSectionLoadList().IsEmpty())
    return optional_info;

  Address vtable_addr_resolved;
  SymbolContext sc;
  Symbol *symbol;

  if (!target.GetSectionLoadList().ResolveLoadAddress(vtable_address,
                                                      vtable_addr_resolved))
    return optional_info;

  target.GetImages().ResolveSymbolContextForAddress(
      vtable_addr_resolved, eSymbolContextEverything, sc);
  symbol = sc.symbol;

  if (symbol == nullptr)
    return optional_info;

  llvm::StringRef vtable_name(symbol->GetName().GetCString());
  bool found_expected_start_string =
      vtable_name.startswith("vtable for std::__1::__function::__func<");

  if (!found_expected_start_string)
    return optional_info;

  // Given case 1 or 3 we have a vtable name, we are want to extract the first
  // template parameter
  //
  //  ... __func<main::$_0, std::__1::allocator<main::$_0> ...
  //             ^^^^^^^^^
  //
  // We do this by find the first < and , and extracting in between.
  //
  // This covers the case of the lambda known at compile time.
  size_t first_open_angle_bracket = vtable_name.find('<') + 1;
  size_t first_comma = vtable_name.find(',');

  llvm::StringRef first_template_parameter =
      vtable_name.slice(first_open_angle_bracket, first_comma);

  Address function_address_resolved;

  // Setup for cases 2, 4 and 5 we have a pointer to a function after the
  // vtable. We will use a process of elimination to drop through each case
  // and obtain the data we need.
  if (target.GetSectionLoadList().ResolveLoadAddress(
          possible_function_address, function_address_resolved)) {
    target.GetImages().ResolveSymbolContextForAddress(
        function_address_resolved, eSymbolContextEverything, sc);
    symbol = sc.symbol;
  }

  auto get_name = [&first_template_parameter, &symbol]() {
    // Given case 1:
    //
    //    main::$_0
    //
    // we want to append ::operator()()
    if (first_template_parameter.contains("$_"))
      return llvm::Regex::escape(first_template_parameter.str()) +
             R"(::operator\(\)\(.*\))";

    if (symbol != NULL &&
        symbol->GetName().GetStringRef().contains("__invoke")) {

      llvm::StringRef symbol_name = symbol->GetName().GetStringRef();
      size_t pos2 = symbol_name.find_last_of(':');

      // Given case 2:
      //
      //    main::$_1::__invoke(...)
      //
      // We want to slice off __invoke(...) and append operator()()
      std::string lambda_operator =
          llvm::Regex::escape(symbol_name.slice(0, pos2 + 1).str()) +
          R"(operator\(\)\(.*\))";

      return lambda_operator;
    }

    // Case 3
    return first_template_parameter.str() + R"(::operator\(\)\(.*\))";
    ;
  };

  std::string func_to_match = get_name();

  SymbolContextList scl;

  target.GetImages().FindFunctions(RegularExpression{func_to_match}, true, true,
                                   true, scl);

  // Case 1,2 or 3
  if (scl.GetSize() >= 1) {
    SymbolContext sc2 = scl[0];

    AddressRange range;
    sc2.GetAddressRange(eSymbolContextEverything, 0, false, range);

    Address address = range.GetBaseAddress();

    Address addr;
    if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
                                  addr)) {
      LineEntry line_entry;
      addr.CalculateSymbolContextLineEntry(line_entry);

      if (first_template_parameter.contains("$_") ||
          (symbol != nullptr &&
           symbol->GetName().GetStringRef().contains("__invoke"))) {
        // Case 1 and 2
        optional_info.callable_case = LibCppStdFunctionCallableCase::Lambda;
      } else {
        // Case 3
        optional_info.callable_case =
            LibCppStdFunctionCallableCase::CallableObject;
      }

      optional_info.callable_symbol = *symbol;
      optional_info.callable_line_entry = line_entry;
      optional_info.callable_address = addr;
      return optional_info;
    }
  }

  // Case 4 or 5
  if (!symbol->GetName().GetStringRef().startswith("vtable for")) {
    optional_info.callable_case =
        LibCppStdFunctionCallableCase::FreeOrMemberFunction;
    optional_info.callable_address = function_address_resolved;
    optional_info.callable_symbol = *symbol;

    return optional_info;
  }

  return optional_info;
}

lldb::ThreadPlanSP
CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
                                                 bool stop_others) {
  ThreadPlanSP ret_plan_sp;

  lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();

  TargetSP target_sp(thread.CalculateTarget());

  if (target_sp->GetSectionLoadList().IsEmpty())
    return ret_plan_sp;

  Address pc_addr_resolved;
  SymbolContext sc;
  Symbol *symbol;

  if (!target_sp->GetSectionLoadList().ResolveLoadAddress(curr_pc,
                                                          pc_addr_resolved))
    return ret_plan_sp;

  target_sp->GetImages().ResolveSymbolContextForAddress(
      pc_addr_resolved, eSymbolContextEverything, sc);
  symbol = sc.symbol;

  if (symbol == nullptr)
    return ret_plan_sp;

  llvm::StringRef function_name(symbol->GetName().GetCString());

  // Handling the case where we are attempting to step into std::function.
  // The behavior will be that we will attempt to obtain the wrapped
  // callable via FindLibCppStdFunctionCallableInfo() and if we find it we
  // will return a ThreadPlanRunToAddress to the callable. Therefore we will
  // step into the wrapped callable.
  //
  bool found_expected_start_string =
      function_name.startswith("std::__1::function<");

  if (!found_expected_start_string)
    return ret_plan_sp;

  AddressRange range_of_curr_func;
  sc.GetAddressRange(eSymbolContextEverything, 0, false, range_of_curr_func);

  StackFrameSP frame = thread.GetStackFrameAtIndex(0);

  if (frame) {
    ValueObjectSP value_sp = frame->FindVariable(g_this);

    CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
        FindLibCppStdFunctionCallableInfo(value_sp);

    if (callable_info.callable_case != LibCppStdFunctionCallableCase::Invalid &&
        value_sp->GetValueIsValid()) {
      // We found the std::function wrapped callable and we have its address.
      // We now create a ThreadPlan to run to the callable.
      ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>(
          thread, callable_info.callable_address, stop_others);
      return ret_plan_sp;
    } else {
      // We are in std::function but we could not obtain the callable.
      // We create a ThreadPlan to keep stepping through using the address range
      // of the current function.
      ret_plan_sp = std::make_shared<ThreadPlanStepInRange>(
          thread, range_of_curr_func, sc, eOnlyThisThread, eLazyBoolYes,
          eLazyBoolYes);
      return ret_plan_sp;
    }
  }

  return ret_plan_sp;
}
<commit_msg>[DataFormatters] FindLibCppStdFunctionCallableInfo() currently uses FindFunctions() in order to find a lambdas operator()() but using FindSymbolsMatchingRegExAndType() is cheaper and if we also anchor the regex using ^ this adds some additional performance gains.<commit_after>//===-- CPPLanguageRuntime.cpp
//-------------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"

#include <string.h>

#include <memory>

#include "llvm/ADT/StringRef.h"

#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Variable.h"
#include "lldb/Symbol/VariableList.h"

#include "lldb/Core/PluginManager.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
#include "lldb/Target/ThreadPlanStepInRange.h"

using namespace lldb;
using namespace lldb_private;

static ConstString g_this = ConstString("this");

// Destructor
CPPLanguageRuntime::~CPPLanguageRuntime() {}

CPPLanguageRuntime::CPPLanguageRuntime(Process *process)
    : LanguageRuntime(process) {}

bool CPPLanguageRuntime::IsRuntimeSupportValue(ValueObject &valobj) {
  // All runtime support values have to be marked as artificial by the
  // compiler. But not all artificial variables should be hidden from
  // the user.
  if (!valobj.GetVariable())
    return false;
  if (!valobj.GetVariable()->IsArtificial())
    return false;

  // Whitelist "this" and since there is no ObjC++ runtime, any ObjC names.
  ConstString name = valobj.GetName();
  if (name == g_this)
    return false;
  return !ObjCLanguageRuntime::IsWhitelistedRuntimeValue(name);
}

bool CPPLanguageRuntime::GetObjectDescription(Stream &str,
                                              ValueObject &object) {
  // C++ has no generic way to do this.
  return false;
}

bool CPPLanguageRuntime::GetObjectDescription(
    Stream &str, Value &value, ExecutionContextScope *exe_scope) {
  // C++ has no generic way to do this.
  return false;
}

CPPLanguageRuntime::LibCppStdFunctionCallableInfo
CPPLanguageRuntime::FindLibCppStdFunctionCallableInfo(
    lldb::ValueObjectSP &valobj_sp) {
  LibCppStdFunctionCallableInfo optional_info;

  if (!valobj_sp)
    return optional_info;

  // Member __f_ has type __base*, the contents of which will hold:
  // 1) a vtable entry which may hold type information needed to discover the
  //    lambda being called
  // 2) possibly hold a pointer to the callable object
  // e.g.
  //
  // (lldb) frame var -R  f_display
  // (std::__1::function<void (int)>) f_display = {
  //  __buf_ = {
  //  …
  // }
  //  __f_ = 0x00007ffeefbffa00
  // }
  // (lldb) memory read -fA 0x00007ffeefbffa00
  // 0x7ffeefbffa00: ... `vtable for std::__1::__function::__func<void (*) ...
  // 0x7ffeefbffa08: ... `print_num(int) at std_function_cppreference_exam ...
  //
  // We will be handling five cases below, std::function is wrapping:
  //
  // 1) a lambda we know at compile time. We will obtain the name of the lambda
  //    from the first template pameter from __func's vtable. We will look up
  //    the lambda's operator()() and obtain the line table entry.
  // 2) a lambda we know at runtime. A pointer to the lambdas __invoke method
  //    will be stored after the vtable. We will obtain the lambdas name from
  //    this entry and lookup operator()() and obtain the line table entry.
  // 3) a callable object via operator()(). We will obtain the name of the
  //    object from the first template parameter from __func's vtable. We will
  //    look up the objectc operator()() and obtain the line table entry.
  // 4) a member function. A pointer to the function will stored after the
  //    we will obtain the name from this pointer.
  // 5) a free function. A pointer to the function will stored after the vtable
  //    we will obtain the name from this pointer.
  ValueObjectSP member__f_(
      valobj_sp->GetChildMemberWithName(ConstString("__f_"), true));

  if (member__f_) {
    ValueObjectSP sub_member__f_(
       member__f_->GetChildMemberWithName(ConstString("__f_"), true));

    if (sub_member__f_)
        member__f_ = sub_member__f_;
  }

  lldb::addr_t member__f_pointer_value = member__f_->GetValueAsUnsigned(0);

  optional_info.member__f_pointer_value = member__f_pointer_value;

  ExecutionContext exe_ctx(valobj_sp->GetExecutionContextRef());
  Process *process = exe_ctx.GetProcessPtr();

  if (process == nullptr)
    return optional_info;

  uint32_t address_size = process->GetAddressByteSize();
  Status status;

  // First item pointed to by __f_ should be the pointer to the vtable for
  // a __base object.
  lldb::addr_t vtable_address =
      process->ReadPointerFromMemory(member__f_pointer_value, status);

  if (status.Fail())
    return optional_info;

  lldb::addr_t address_after_vtable = member__f_pointer_value + address_size;
  // As commened above we may not have a function pointer but if we do we will
  // need it.
  lldb::addr_t possible_function_address =
      process->ReadPointerFromMemory(address_after_vtable, status);

  if (status.Fail())
    return optional_info;

  Target &target = process->GetTarget();

  if (target.GetSectionLoadList().IsEmpty())
    return optional_info;

  Address vtable_addr_resolved;
  SymbolContext sc;
  Symbol *symbol;

  if (!target.GetSectionLoadList().ResolveLoadAddress(vtable_address,
                                                      vtable_addr_resolved))
    return optional_info;

  target.GetImages().ResolveSymbolContextForAddress(
      vtable_addr_resolved, eSymbolContextEverything, sc);
  symbol = sc.symbol;

  if (symbol == nullptr)
    return optional_info;

  llvm::StringRef vtable_name(symbol->GetName().GetCString());
  bool found_expected_start_string =
      vtable_name.startswith("vtable for std::__1::__function::__func<");

  if (!found_expected_start_string)
    return optional_info;

  // Given case 1 or 3 we have a vtable name, we are want to extract the first
  // template parameter
  //
  //  ... __func<main::$_0, std::__1::allocator<main::$_0> ...
  //             ^^^^^^^^^
  //
  // We do this by find the first < and , and extracting in between.
  //
  // This covers the case of the lambda known at compile time.
  size_t first_open_angle_bracket = vtable_name.find('<') + 1;
  size_t first_comma = vtable_name.find(',');

  llvm::StringRef first_template_parameter =
      vtable_name.slice(first_open_angle_bracket, first_comma);

  Address function_address_resolved;

  // Setup for cases 2, 4 and 5 we have a pointer to a function after the
  // vtable. We will use a process of elimination to drop through each case
  // and obtain the data we need.
  if (target.GetSectionLoadList().ResolveLoadAddress(
          possible_function_address, function_address_resolved)) {
    target.GetImages().ResolveSymbolContextForAddress(
        function_address_resolved, eSymbolContextEverything, sc);
    symbol = sc.symbol;
  }

  auto get_name = [&first_template_parameter, &symbol]() {
    // Given case 1:
    //
    //    main::$_0
    //
    // we want to append ::operator()()
    if (first_template_parameter.contains("$_"))
      return llvm::Regex::escape(first_template_parameter.str()) +
             R"(::operator\(\)\(.*\))";

    if (symbol != NULL &&
        symbol->GetName().GetStringRef().contains("__invoke")) {

      llvm::StringRef symbol_name = symbol->GetName().GetStringRef();
      size_t pos2 = symbol_name.find_last_of(':');

      // Given case 2:
      //
      //    main::$_1::__invoke(...)
      //
      // We want to slice off __invoke(...) and append operator()()
      std::string lambda_operator =
          llvm::Regex::escape(symbol_name.slice(0, pos2 + 1).str()) +
          R"(operator\(\)\(.*\))";

      return lambda_operator;
    }

    // Case 3
    return first_template_parameter.str() + R"(::operator\(\)\(.*\))";
    ;
  };

  std::string func_to_match = get_name();

  SymbolContextList scl;

  target.GetImages().FindSymbolsMatchingRegExAndType(
      RegularExpression{R"(^)" + func_to_match}, eSymbolTypeAny, scl, true);

  // Case 1,2 or 3
  if (scl.GetSize() >= 1) {
    SymbolContext sc2 = scl[0];

    AddressRange range;
    sc2.GetAddressRange(eSymbolContextEverything, 0, false, range);

    Address address = range.GetBaseAddress();

    Address addr;
    if (target.ResolveLoadAddress(address.GetCallableLoadAddress(&target),
                                  addr)) {
      LineEntry line_entry;
      addr.CalculateSymbolContextLineEntry(line_entry);

      if (first_template_parameter.contains("$_") ||
          (symbol != nullptr &&
           symbol->GetName().GetStringRef().contains("__invoke"))) {
        // Case 1 and 2
        optional_info.callable_case = LibCppStdFunctionCallableCase::Lambda;
      } else {
        // Case 3
        optional_info.callable_case =
            LibCppStdFunctionCallableCase::CallableObject;
      }

      optional_info.callable_symbol = *symbol;
      optional_info.callable_line_entry = line_entry;
      optional_info.callable_address = addr;
      return optional_info;
    }
  }

  // Case 4 or 5
  if (!symbol->GetName().GetStringRef().startswith("vtable for")) {
    optional_info.callable_case =
        LibCppStdFunctionCallableCase::FreeOrMemberFunction;
    optional_info.callable_address = function_address_resolved;
    optional_info.callable_symbol = *symbol;

    return optional_info;
  }

  return optional_info;
}

lldb::ThreadPlanSP
CPPLanguageRuntime::GetStepThroughTrampolinePlan(Thread &thread,
                                                 bool stop_others) {
  ThreadPlanSP ret_plan_sp;

  lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();

  TargetSP target_sp(thread.CalculateTarget());

  if (target_sp->GetSectionLoadList().IsEmpty())
    return ret_plan_sp;

  Address pc_addr_resolved;
  SymbolContext sc;
  Symbol *symbol;

  if (!target_sp->GetSectionLoadList().ResolveLoadAddress(curr_pc,
                                                          pc_addr_resolved))
    return ret_plan_sp;

  target_sp->GetImages().ResolveSymbolContextForAddress(
      pc_addr_resolved, eSymbolContextEverything, sc);
  symbol = sc.symbol;

  if (symbol == nullptr)
    return ret_plan_sp;

  llvm::StringRef function_name(symbol->GetName().GetCString());

  // Handling the case where we are attempting to step into std::function.
  // The behavior will be that we will attempt to obtain the wrapped
  // callable via FindLibCppStdFunctionCallableInfo() and if we find it we
  // will return a ThreadPlanRunToAddress to the callable. Therefore we will
  // step into the wrapped callable.
  //
  bool found_expected_start_string =
      function_name.startswith("std::__1::function<");

  if (!found_expected_start_string)
    return ret_plan_sp;

  AddressRange range_of_curr_func;
  sc.GetAddressRange(eSymbolContextEverything, 0, false, range_of_curr_func);

  StackFrameSP frame = thread.GetStackFrameAtIndex(0);

  if (frame) {
    ValueObjectSP value_sp = frame->FindVariable(g_this);

    CPPLanguageRuntime::LibCppStdFunctionCallableInfo callable_info =
        FindLibCppStdFunctionCallableInfo(value_sp);

    if (callable_info.callable_case != LibCppStdFunctionCallableCase::Invalid &&
        value_sp->GetValueIsValid()) {
      // We found the std::function wrapped callable and we have its address.
      // We now create a ThreadPlan to run to the callable.
      ret_plan_sp = std::make_shared<ThreadPlanRunToAddress>(
          thread, callable_info.callable_address, stop_others);
      return ret_plan_sp;
    } else {
      // We are in std::function but we could not obtain the callable.
      // We create a ThreadPlan to keep stepping through using the address range
      // of the current function.
      ret_plan_sp = std::make_shared<ThreadPlanStepInRange>(
          thread, range_of_curr_func, sc, eOnlyThisThread, eLazyBoolYes,
          eLazyBoolYes);
      return ret_plan_sp;
    }
  }

  return ret_plan_sp;
}
<|endoftext|>


<commit_before>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: datasetControl.C,v 1.46.16.1 2007/03/25 21:56:44 oliver Exp $
//

#include <BALL/VIEW/WIDGETS/datasetControl.h>
#include <BALL/VIEW/DATATYPE/dataset.h>
#include <BALL/VIEW/KERNEL/message.h>

namespace BALL
{
	namespace VIEW
	{

DatasetControl::DatasetControl(QWidget* parent, const char* name)
	throw()
	:	GenericControl(parent, name)
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "new DatasetControl " << this << std::endl;
#endif
	listview->setColumnCount(3);
	listview->headerItem()->setText(0, "Name");
	listview->headerItem()->setText(1, "from");
	listview->headerItem()->setText(2, "Type");
	listview->setSortingEnabled(true);
	default_visible_ = false;
	resize(50,50);
	registerWidget(this);
}

DatasetControl::~DatasetControl()
	throw()
{
	#ifdef BALL_VIEW_DEBUG
		Log.error() << "Destructing object " << this << " of class DatasetControl" << std::endl;
	#endif

	listview->clear();

	for (Position p = 0; p < controllers_.size(); p++)
	{
		delete controllers_[p];
	}
}

void DatasetControl::initializeWidget(MainControl& main_control)
	throw()
{
	GenericControl::initializeWidget(main_control);
	registerForHelpSystem(this, "datasetControl.html");
	for (Position p = 0; p < controllers_.size(); p++)
	{
		controllers_[p]->createMenuEntries();
	}
}

void DatasetControl::checkMenu(MainControl& main_control)
	throw()
{
	for (Position p = 0; p < controllers_.size(); p++)
	{
		controllers_[p]->checkMenu(main_control);
	}
}

void DatasetControl::onNotify(Message *message)
	throw()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "DatasetControl "<<this<<  " onNotify " << message << std::endl;
#endif

	GenericControl::onNotify(message);
	if (!RTTI::isKindOf<DatasetMessage>(*message)) return;

	DatasetMessage* msg = (DatasetMessage*) message;
	if (!msg->isValid())
	{
		BALLVIEW_DEBUG
		return;
	}

	String type = msg->getDataset()->getType();
	for (Position p = 0; p < controllers_.size(); p++)
	{
		if (controllers_[p]->getType() == type)
		{
			if (!controllers_[p]->handle(msg)) BALLVIEW_DEBUG;

			return;
		}
	}

	BALLVIEW_DEBUG
	Log.error() << "Unknown dataset type:"<< type << std::endl;

}

void DatasetControl::updateSelection()
	throw()
{
	GenericControl::updateSelection();

	ItemList list = getSelectedItems();
	ItemList::iterator it = list.begin();
	for (; it != list.end(); it++)
	{
		QTreeWidgetItem* item = *it;
		DatasetController* cont = getController(item);
		if (cont == 0) continue;

		Dataset* set = cont->getDataset(item);
		DatasetMessage* msg = new DatasetMessage(set, DatasetMessage::SELECTED);
		notify_(msg);
	}
}

DatasetControl::DatasetControl(const DatasetControl& control)
	throw()
	: GenericControl(control)
{
}

void DatasetControl::showGuestContextMenu(const QPoint& pos)
{
	getSelectedItems();
	if (context_item_ == 0) return;

	for (Position p = 0; p < controllers_.size(); p++)
	{
		// find the corresponding controller
		QMenu* menu = controllers_[p]->buildContextMenu(context_item_);
		if (menu != 0)
		{
			BALL_ASSIGN_NAME(menu)
			menu->exec(mapToGlobal(pos));
			delete menu;
			return;
		}
	}
}

bool DatasetControl::canHandle(const String& fileformat) const
{
	for (Position p = 0; p < controllers_.size(); p++)
	{
		vector<String> file_types = controllers_[p]->getSupportedFileFormats();
		for (Position t = 0; t < file_types.size(); t++)
		{
			if (file_types[t] == fileformat)
			{
				return true;
			}
		}
	}

	return false;
}

bool DatasetControl::openFile(const String& filename)
{
	vector<String> fields;
	String suffix(filename);
	suffix.split(fields, ".");
	if (fields.size() > 1)
	{
		suffix = fields[fields.size() - 1];

		for (Position p = 0; p < controllers_.size(); p++)
		{
			vector<String> file_types = controllers_[p]->getSupportedFileFormats();
			for (Position t = 0; t < file_types.size(); t++)
			{
				if (file_types[t] == suffix)
				{
					return controllers_[p]->open(suffix, filename) != 0;
				}
			}
		}
	}

	setStatusbarText(String("Can not open unknown file type: ") + suffix, true);

	return false;
}

vector<Dataset*> DatasetControl::getDatasets(const String& type)
{
	DatasetController* con = getController(type);
	if (con != 0) return con->getDatasets();

	return vector<Dataset*>();
}

DatasetController* DatasetControl::getController(const String& type)
{
	for (Position p = 0; p < controllers_.size(); p++)
	{
		if (controllers_[p]->getType() == type)
		{
			return controllers_[p];
		}
	}

	return 0;
}

DatasetController* DatasetControl::getController(QTreeWidgetItem* item)
{
	for (Position p = 0; p < controllers_.size(); p++)
	{
		if (controllers_[p]->hasItem(item))
		{
			return controllers_[p];
		}
	}

	BALLVIEW_DEBUG
	return 0;
}

String DatasetControl::getType(QTreeWidgetItem* item)
{
	for (Position p = 0; p < controllers_.size(); p++)
	{
		if (controllers_[p]->hasItem(item))
		{
			return controllers_[p]->getType();
		}
	}

	BALLVIEW_DEBUG
	return "";
}

bool DatasetControl::registerController(DatasetController* con)
{
	String type = con->getType();
	if (type == "" || type == "none")
	{
		Log.error() << "Can not register Controller with type " << type << std::endl;
		return false;
	}

	if (getController(type) != 0)
	{
		Log.error() << "Can not register Controller with type " << type << ": "
								<< "Such a controller was already registered!" << std::endl;
		return false;
	}

	controllers_.push_back(con);
	con->setDatasetControl(this);
	return true;
}

Size DatasetControl::getSelectionSize()
{
	return getSelectedItems().size();
}

	} // namespace VIEW
} // namespace BALL
<commit_msg>no message<commit_after>// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//
// $Id: datasetControl.C,v 1.46.16.2 2007/05/17 21:10:06 amoll Exp $
//

#include <BALL/VIEW/WIDGETS/datasetControl.h>
#include <BALL/VIEW/DATATYPE/dataset.h>
#include <BALL/VIEW/KERNEL/message.h>

namespace BALL
{
	namespace VIEW
	{

DatasetControl::DatasetControl(QWidget* parent, const char* name)
	throw()
	:	GenericControl(parent, name)
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "new DatasetControl " << this << std::endl;
#endif
	listview->setColumnCount(3);
	listview->headerItem()->setText(0, "Name");
	listview->headerItem()->setText(1, "from");
	listview->headerItem()->setText(2, "Type");
	listview->setSortingEnabled(true);
	default_visible_ = false;
	resize(50,50);
	registerWidget(this);
}

DatasetControl::~DatasetControl()
	throw()
{
	#ifdef BALL_VIEW_DEBUG
		Log.error() << "Destructing object " << this << " of class DatasetControl" << std::endl;
	#endif

	listview->clear();

	for (Position p = 0; p < controllers_.size(); p++)
	{
		delete controllers_[p];
	}
}

void DatasetControl::initializeWidget(MainControl& main_control)
	throw()
{
	GenericControl::initializeWidget(main_control);
	registerForHelpSystem(this, "datasetControl.html");
	for (Position p = 0; p < controllers_.size(); p++)
	{
		controllers_[p]->createMenuEntries();
	}
}

void DatasetControl::checkMenu(MainControl& main_control)
	throw()
{
	for (Position p = 0; p < controllers_.size(); p++)
	{
		controllers_[p]->checkMenu(main_control);
	}
}

void DatasetControl::onNotify(Message *message)
	throw()
{
#ifdef BALL_VIEW_DEBUG
	Log.error() << "DatasetControl "<<this<<  " onNotify " << message << std::endl;
#endif

	GenericControl::onNotify(message);
	if (!RTTI::isKindOf<DatasetMessage>(*message)) return;

	DatasetMessage* msg = (DatasetMessage*) message;
	if (!msg->isValid())
	{
		BALLVIEW_DEBUG
		return;
	}

	String type = msg->getDataset()->getType();
	for (Position p = 0; p < controllers_.size(); p++)
	{
		if (controllers_[p]->getType() == type)
		{
			controllers_[p]->handle(msg);

			return;
		}
	}

	BALLVIEW_DEBUG
	Log.error() << "Unknown dataset type:"<< type << std::endl;

}

void DatasetControl::updateSelection()
	throw()
{
	GenericControl::updateSelection();

	ItemList list = getSelectedItems();
	ItemList::iterator it = list.begin();
	for (; it != list.end(); it++)
	{
		QTreeWidgetItem* item = *it;
		DatasetController* cont = getController(item);
		if (cont == 0) continue;

		Dataset* set = cont->getDataset(item);
		DatasetMessage* msg = new DatasetMessage(set, DatasetMessage::SELECTED);
		notify_(msg);
	}
}

DatasetControl::DatasetControl(const DatasetControl& control)
	throw()
	: GenericControl(control)
{
}

void DatasetControl::showGuestContextMenu(const QPoint& pos)
{
	getSelectedItems();
	if (context_item_ == 0) return;

	for (Position p = 0; p < controllers_.size(); p++)
	{
		// find the corresponding controller
		QMenu* menu = controllers_[p]->buildContextMenu(context_item_);
		if (menu != 0)
		{
			BALL_ASSIGN_NAME(menu)
			menu->exec(mapToGlobal(pos));
			delete menu;
			return;
		}
	}
}

bool DatasetControl::canHandle(const String& fileformat) const
{
	for (Position p = 0; p < controllers_.size(); p++)
	{
		vector<String> file_types = controllers_[p]->getSupportedFileFormats();
		for (Position t = 0; t < file_types.size(); t++)
		{
			if (file_types[t] == fileformat)
			{
				return true;
			}
		}
	}

	return false;
}

bool DatasetControl::openFile(const String& filename)
{
	vector<String> fields;
	String suffix(filename);
	suffix.split(fields, ".");
	if (fields.size() > 1)
	{
		suffix = fields[fields.size() - 1];

		for (Position p = 0; p < controllers_.size(); p++)
		{
			vector<String> file_types = controllers_[p]->getSupportedFileFormats();
			for (Position t = 0; t < file_types.size(); t++)
			{
				if (file_types[t] == suffix)
				{
					return controllers_[p]->open(suffix, filename) != 0;
				}
			}
		}
	}

	setStatusbarText(String("Can not open unknown file type: ") + suffix, true);

	return false;
}

vector<Dataset*> DatasetControl::getDatasets(const String& type)
{
	DatasetController* con = getController(type);
	if (con != 0) return con->getDatasets();

	return vector<Dataset*>();
}

DatasetController* DatasetControl::getController(const String& type)
{
	for (Position p = 0; p < controllers_.size(); p++)
	{
		if (controllers_[p]->getType() == type)
		{
			return controllers_[p];
		}
	}

	return 0;
}

DatasetController* DatasetControl::getController(QTreeWidgetItem* item)
{
	for (Position p = 0; p < controllers_.size(); p++)
	{
		if (controllers_[p]->hasItem(item))
		{
			return controllers_[p];
		}
	}

	BALLVIEW_DEBUG
	return 0;
}

String DatasetControl::getType(QTreeWidgetItem* item)
{
	for (Position p = 0; p < controllers_.size(); p++)
	{
		if (controllers_[p]->hasItem(item))
		{
			return controllers_[p]->getType();
		}
	}

	BALLVIEW_DEBUG
	return "";
}

bool DatasetControl::registerController(DatasetController* con)
{
	String type = con->getType();
	if (type == "" || type == "none")
	{
		Log.error() << "Can not register Controller with type " << type << std::endl;
		return false;
	}

	if (getController(type) != 0)
	{
		Log.error() << "Can not register Controller with type " << type << ": "
								<< "Such a controller was already registered!" << std::endl;
		return false;
	}

	controllers_.push_back(con);
	con->setDatasetControl(this);
	return true;
}

Size DatasetControl::getSelectionSize()
{
	return getSelectedItems().size();
}

	} // namespace VIEW
} // namespace BALL
<|endoftext|>


<commit_before>#include "consoleUtil.h"
#include "Deck.h"
#include "TexasHoldem.h"
#include "poker.h"
#include <windows.h>
#include <conio.h>

using namespace std;

#define		TABLE_X		10
#define		TABLE_Y		(COM_Y+PLAYER_HT+1)
#define		TABLE_HT		3
#define		TABLE_WD		(2+2*5+1*4+2)
#define		PLAYER_HT	4
#define		PLAYER_WD	(1+8+1)		//	" COMPUTER ", "  HUMAN   "
#define		COM_X			(TABLE_X + (TABLE_WD - PLAYER_WD) / 2)
#define		COM_Y			2
#define		COM_BET_X	(COM_X + PLAYER_WD + 1)
#define		COM_BET_Y	(COM_Y + 1)
#define		MAN_X			COM_X
#define		MAN_Y			(TABLE_Y+TABLE_HT+1)
#define		MAN_BET_X	(MAN_X + PLAYER_WD + 1)
#define		MAN_BET_Y	(MAN_Y + 1)
#define		POT_X			(TABLE_X + TABLE_WD + 1)
#define		POT_Y			(TABLE_Y + 1)
#define		MENU_X		2
#define		MENU_Y		(MAN_Y+PLAYER_HT+1)
#define		N_MENU		3		//	j[I
#define		MENU_FOLD	0
#define		MENU_CC		1		//	Check/Call
#define		MENU_RAISE	2
#define		KEY_SPECIAL	0xe0
#define		KEY_LEFT		0x4b
#define		KEY_RIGHT	0x4d
#define		ACT_FOLD		1
#define		ACT_CC			2		//	Check/Call
#define		ACT_RAISE	3

TexasHoldem g_table;
int	g_comIX;
int	g_manIX;

int	g_menuIX;			//	IĂ郁j[IX
const char *g_menu[] = {
	"Fold", "Check/Call", "Raise"
};

void draw_card(int x, int y, Card c)
{
	if( c.m_suit == Card::SPADES || c.m_suit == Card::CLUBS )
		setColor(COL_BLACK, COL_WHITE);
	else
		setColor(COL_RED, COL_WHITE);
	setCursorPos(x, y);
	coutW(c.toStringW());
}

void draw_com(bool open = false);
void draw_com(bool open)
{
	setCursorPos(COM_X, COM_Y);
	setColor(COL_BLACK, COL_YELLOW);
	cout << " COMPUTER ";
	setColor(COL_GRAY, COL_BLACK);
	setCursorPos(COM_X, COM_Y+1);
	cout << "chip:" << g_table.chip(g_comIX);
	if( g_comIX == g_table.dealerIX() ) {
		setCursorPos(COM_X - 2, COM_Y);
		cout << "D";
	}
	if( g_comIX == g_table.BBIX() ) {
		setCursorPos(COM_X - 3, COM_Y + 1);
		cout << "BB";
	}
	if( g_comIX == g_table.SBIX() ) {
		setCursorPos(COM_X - 3, COM_Y + 1);
		cout << "SB";
	}
	setCursorPos(COM_BET_X, COM_BET_Y);
	cout << "bet:" << g_table.bet(g_comIX) << "      ";
	if( open ) {
		Card c1, c2;
		g_table.getHoleCards(g_comIX, c1, c2);
		draw_card(COM_X, COM_Y+2, c1);
		draw_card(COM_X+3, COM_Y+2, c2);
	} else {
		setColor(COL_BLACK, COL_CYAN);
		setCursorPos(COM_X, COM_Y+2);
		cout << "  ";
		setCursorPos(COM_X+3, COM_Y+2);
		cout << "  ";
	}
}
void draw_human()
{
	setCursorPos(MAN_X, MAN_Y);
	setColor(COL_BLACK, COL_YELLOW);
	cout << "  HUMAN   ";
	setColor(COL_GRAY, COL_BLACK);
	setCursorPos(MAN_X, MAN_Y+1);
	cout << "chip:" << g_table.chip(g_manIX);
	setCursorPos(MAN_BET_X, MAN_BET_Y);
	cout << "bet:" << g_table.bet(g_manIX) << "      ";
	if( g_manIX == g_table.dealerIX() ) {
		setCursorPos(MAN_X - 2, MAN_Y);
		cout << "D";
	}
	if( g_manIX == g_table.BBIX() ) {
		setCursorPos(MAN_X - 3, MAN_Y + 1);
		cout << "BB";
	}
	if( g_manIX == g_table.SBIX() ) {
		setCursorPos(MAN_X - 3, MAN_Y + 1);
		cout << "SB";
	}
	Card c1, c2;
	g_table.getHoleCards(g_manIX, c1, c2);
	if( c1.m_suit == Card::SPADES || c1.m_suit == Card::CLUBS )
		setColor(COL_BLACK, COL_WHITE);
	else
		setColor(COL_RED, COL_WHITE);
	setCursorPos(MAN_X, MAN_Y+2);
	coutW(c1.toStringW());
	//cout << " ";
	if( c2.m_suit == Card::SPADES || c2.m_suit == Card::CLUBS )
		setColor(COL_BLACK, COL_WHITE);
	else
		setColor(COL_RED, COL_WHITE);
	setCursorPos(MAN_X+3, MAN_Y+2);
	coutW(c2.toStringW());
	//cout << "?? ??";
}
void draw_table()
{
	setColor(COL_WHITE, COL_DARK_GREEN);
	for(int k = 0; k < TABLE_HT; ++k) {
		setCursorPos(TABLE_X, k + TABLE_Y);
		for(int i = 0; i < TABLE_WD; ++i)
			cout << " ";
	}
	const std::vector<Card> &cc = g_table.communityCards();
	for (int i = 0; i < (int)cc.size(); ++i) {
		//setCursorPos(TABLE_X + 2 + i * 3, TABLE_Y + 1);
		draw_card(TABLE_X + 2 + i * 3, TABLE_Y + 1, cc[i]);
	}

	setColor(COL_GRAY, COL_BLACK);
	setCursorPos(POT_X, POT_Y);
	cout << "Pot:" << g_table.pot() << "        ";
}
void draw_menu()
{
	setCursorPos(MENU_X, MENU_Y);
	for (int i = 0; i < N_MENU; ++i) {
		if( i == g_menuIX )
			setColor(COL_BLACK, COL_WHITE);
		else
			setColor(COL_GRAY, COL_BLACK);
		cout << "[" << g_menu[i] << "]";
		setColor(COL_GRAY, COL_BLACK);
		cout << " ";
	}
	//setColor(COL_GRAY, COL_BLACK);
	//cout << "[Fold] [Check] [Call] [Raise] 0";
}
//	vtbvAtbvA^[Ao[̏
//	SR[Freturn true;
//	lȊOS~肽Freturn false;
bool turn()
{
	int pix = g_table.dealerIX() + 1;		//	݂̎
	if( g_table.turn() == TexasHoldem::PRE_FLOP )
		pix += 2;
	for (;;) {
		draw_com();
		draw_human();
		draw_table();
		int act = 0;
		while( pix >= g_table.nPlayer() )
			pix -= g_table.nPlayer();
		if( pix == g_manIX ) {
			g_menuIX = MENU_CC;		//	Check/Call
			for (;;) {
				draw_menu();
				int ch = _getch();
				if( ch == 'Q' || ch == 'q' )
					return 0;
				if( ch == KEY_SPECIAL ) {		//	L[Ȃǂ̏ꍇ
					ch = _getch();
					if( ch == KEY_LEFT && g_menuIX != 0 )
						--g_menuIX;
					else if( ch == KEY_RIGHT && g_menuIX < N_MENU - 1)
						++g_menuIX;
				}
				if( ch == '\r' || ch == '\n' ) {	//	j[m
					break;
				}
			}
			switch( g_menuIX ) {
				case MENU_FOLD:
					act = ACT_FOLD;
					break;
				case MENU_CC: {
					act = ACT_CC;
					break;
				}
				case MENU_RAISE:
					act = ACT_RAISE;
					break;
			}
		} else {
			Sleep(500);
			act = ACT_CC;
		}
		switch( act ) {
			case ACT_CC: {
				int b = g_table.call() - g_table.bet(pix);
				if( b != 0 ) {
					g_table.addBet(pix, b);
				}
				break;
			}
		}
		if( g_table.allCalled() )
			return true;
		++pix;
	}
}
int main()
{
	g_table.addPlayer(Player("YOU", 200));
	g_manIX = 0;
	g_table.addPlayer(Player("COM", 200, /*comp:*/true));
	g_comIX = 1;
	g_table.setDealer();
	g_table.dealHoleCards();
	setColor(COL_BLACK, COL_WHITE);
	setCursorPos(5, 0);
	cout << "*** Texas Hold'em Poker ***";
	for (;;) {
		if( turn() ) {
			//	܂QlȏcĂꍇ
			g_table.dealFlop();
			if( turn() ) {
				//	܂QlȏcĂꍇ
				g_table.dealTurn();
				if( turn() ) {
					//	܂QlȏcĂꍇ
					g_table.dealTurn();
					turn();
				}
			}
		}
		draw_com(/*open:*/true);
		//	Z
		uint odr0, odr1;
		std::vector<Card> v;
		g_table.playersCard(0, v);
		checkHand(v, odr0);
		g_table.playersCard(1, v);
		checkHand(v, odr1);
	}
	//getchar();
	return 0;
}
/*
 e[uőR~jeBJ[hɍ킹
 fB[}[N\
 BB, SB }[N\
 `bv𐳂\
 pot \
 evC[̃xbgz\
  mt19937 ɕύX
 J[h\Fwiɍ or Ԃŕ`
 ĂJ[h̓VAŕ\
 j[f[^
 EL[Ńj[I\
 Ƃ肠 Check/Call Őɐi߂悤ɂ
 R[Ã^[ɐi
 R~jeBJ[h𐳂\
 FR[Ɏ`bvĂȂ
 FZɃRs[^̎DI[vȂ
 PQ[I̐Z
 tH[h
 ㉺L[ŃCYzݒ\
 [AllIn] j[ǉ
*/
<commit_msg>精算時：役種別表示<commit_after>#include "consoleUtil.h"
#include "Deck.h"
#include "TexasHoldem.h"
#include "poker.h"
#include <windows.h>
#include <conio.h>

using namespace std;

#define		TABLE_X		10
#define		TABLE_Y		(COM_Y+PLAYER_HT+1)
#define		TABLE_HT		3
#define		TABLE_WD		(2+2*5+1*4+2)
#define		PLAYER_HT	4
#define		PLAYER_WD	(1+8+1)		//	" COMPUTER ", "  HUMAN   "
#define		COM_X			(TABLE_X + (TABLE_WD - PLAYER_WD) / 2)
#define		COM_Y			2
#define		COM_BET_X	(COM_X + PLAYER_WD + 1)
#define		COM_BET_Y	(COM_Y + 1)
#define		MAN_X			COM_X
#define		MAN_Y			(TABLE_Y+TABLE_HT+1)
#define		MAN_BET_X	(MAN_X + PLAYER_WD + 1)
#define		MAN_BET_Y	(MAN_Y + 1)
#define		POT_X			(TABLE_X + TABLE_WD + 1)
#define		POT_Y			(TABLE_Y + 1)
#define		MENU_X		2
#define		MENU_Y		(MAN_Y+PLAYER_HT+1)
#define		N_MENU		3		//	j[I
#define		MENU_FOLD	0
#define		MENU_CC		1		//	Check/Call
#define		MENU_RAISE	2
#define		KEY_SPECIAL	0xe0
#define		KEY_LEFT		0x4b
#define		KEY_RIGHT	0x4d
#define		ACT_FOLD		1
#define		ACT_CC			2		//	Check/Call
#define		ACT_RAISE	3

TexasHoldem g_table;
int	g_comIX;
int	g_manIX;

int	g_menuIX;			//	IĂ郁j[IX
const char *g_menu[] = {
	"Fold", "Check/Call", "Raise"
};

void draw_card(int x, int y, Card c)
{
	if( c.m_suit == Card::SPADES || c.m_suit == Card::CLUBS )
		setColor(COL_BLACK, COL_WHITE);
	else
		setColor(COL_RED, COL_WHITE);
	setCursorPos(x, y);
	coutW(c.toStringW());
}

void draw_com(bool open = false);
void draw_com(bool open)
{
	setCursorPos(COM_X, COM_Y);
	setColor(COL_BLACK, COL_YELLOW);
	cout << " COMPUTER ";
	setColor(COL_GRAY, COL_BLACK);
	setCursorPos(COM_X, COM_Y+1);
	cout << "chip:" << g_table.chip(g_comIX);
	if( g_comIX == g_table.dealerIX() ) {
		setCursorPos(COM_X - 2, COM_Y);
		cout << "D";
	}
	if( g_comIX == g_table.BBIX() ) {
		setCursorPos(COM_X - 3, COM_Y + 1);
		cout << "BB";
	}
	if( g_comIX == g_table.SBIX() ) {
		setCursorPos(COM_X - 3, COM_Y + 1);
		cout << "SB";
	}
	setCursorPos(COM_BET_X, COM_BET_Y);
	cout << "bet:" << g_table.bet(g_comIX) << "      ";
	if( open ) {
		Card c1, c2;
		g_table.getHoleCards(g_comIX, c1, c2);
		draw_card(COM_X, COM_Y+2, c1);
		draw_card(COM_X+3, COM_Y+2, c2);
	} else {
		setColor(COL_BLACK, COL_CYAN);
		setCursorPos(COM_X, COM_Y+2);
		cout << "  ";
		setCursorPos(COM_X+3, COM_Y+2);
		cout << "  ";
	}
}
void draw_human()
{
	setCursorPos(MAN_X, MAN_Y);
	setColor(COL_BLACK, COL_YELLOW);
	cout << "  HUMAN   ";
	setColor(COL_GRAY, COL_BLACK);
	setCursorPos(MAN_X, MAN_Y+1);
	cout << "chip:" << g_table.chip(g_manIX);
	setCursorPos(MAN_BET_X, MAN_BET_Y);
	cout << "bet:" << g_table.bet(g_manIX) << "      ";
	if( g_manIX == g_table.dealerIX() ) {
		setCursorPos(MAN_X - 2, MAN_Y);
		cout << "D";
	}
	if( g_manIX == g_table.BBIX() ) {
		setCursorPos(MAN_X - 3, MAN_Y + 1);
		cout << "BB";
	}
	if( g_manIX == g_table.SBIX() ) {
		setCursorPos(MAN_X - 3, MAN_Y + 1);
		cout << "SB";
	}
	Card c1, c2;
	g_table.getHoleCards(g_manIX, c1, c2);
	if( c1.m_suit == Card::SPADES || c1.m_suit == Card::CLUBS )
		setColor(COL_BLACK, COL_WHITE);
	else
		setColor(COL_RED, COL_WHITE);
	setCursorPos(MAN_X, MAN_Y+2);
	coutW(c1.toStringW());
	//cout << " ";
	if( c2.m_suit == Card::SPADES || c2.m_suit == Card::CLUBS )
		setColor(COL_BLACK, COL_WHITE);
	else
		setColor(COL_RED, COL_WHITE);
	setCursorPos(MAN_X+3, MAN_Y+2);
	coutW(c2.toStringW());
	//cout << "?? ??";
}
void draw_table()
{
	setColor(COL_WHITE, COL_DARK_GREEN);
	for(int k = 0; k < TABLE_HT; ++k) {
		setCursorPos(TABLE_X, k + TABLE_Y);
		for(int i = 0; i < TABLE_WD; ++i)
			cout << " ";
	}
	const std::vector<Card> &cc = g_table.communityCards();
	for (int i = 0; i < (int)cc.size(); ++i) {
		//setCursorPos(TABLE_X + 2 + i * 3, TABLE_Y + 1);
		draw_card(TABLE_X + 2 + i * 3, TABLE_Y + 1, cc[i]);
	}

	setColor(COL_GRAY, COL_BLACK);
	setCursorPos(POT_X, POT_Y);
	cout << "Pot:" << g_table.pot() << "        ";
}
void draw_menu()
{
	setCursorPos(MENU_X, MENU_Y);
	for (int i = 0; i < N_MENU; ++i) {
		if( i == g_menuIX )
			setColor(COL_BLACK, COL_WHITE);
		else
			setColor(COL_GRAY, COL_BLACK);
		cout << "[" << g_menu[i] << "]";
		setColor(COL_GRAY, COL_BLACK);
		cout << " ";
	}
	//setColor(COL_GRAY, COL_BLACK);
	//cout << "[Fold] [Check] [Call] [Raise] 0";
}
//	vtbvAtbvA^[Ao[̏
//	SR[Freturn true;
//	lȊOS~肽Freturn false;
bool turn()
{
	int pix = g_table.dealerIX() + 1;		//	݂̎
	if( g_table.turn() == TexasHoldem::PRE_FLOP )
		pix += 2;
	for (;;) {
		draw_com();
		draw_human();
		draw_table();
		int act = 0;
		while( pix >= g_table.nPlayer() )
			pix -= g_table.nPlayer();
		if( pix == g_manIX ) {
			g_menuIX = MENU_CC;		//	Check/Call
			for (;;) {
				draw_menu();
				int ch = _getch();
				if( ch == 'Q' || ch == 'q' )
					return 0;
				if( ch == KEY_SPECIAL ) {		//	L[Ȃǂ̏ꍇ
					ch = _getch();
					if( ch == KEY_LEFT && g_menuIX != 0 )
						--g_menuIX;
					else if( ch == KEY_RIGHT && g_menuIX < N_MENU - 1)
						++g_menuIX;
				}
				if( ch == '\r' || ch == '\n' ) {	//	j[m
					break;
				}
			}
			switch( g_menuIX ) {
				case MENU_FOLD:
					act = ACT_FOLD;
					break;
				case MENU_CC: {
					act = ACT_CC;
					break;
				}
				case MENU_RAISE:
					act = ACT_RAISE;
					break;
			}
		} else {
			Sleep(500);
			act = ACT_CC;
		}
		switch( act ) {
			case ACT_CC: {
				int b = g_table.call() - g_table.bet(pix);
				if( b != 0 ) {
					g_table.addBet(pix, b);
				}
				break;
			}
		}
		if( g_table.allCalled() )
			return true;
		++pix;
	}
}
int main()
{
	g_table.addPlayer(Player("YOU", 200));
	g_manIX = 0;
	g_table.addPlayer(Player("COM", 200, /*comp:*/true));
	g_comIX = 1;
	g_table.setDealer();
	g_table.dealHoleCards();
	setColor(COL_BLACK, COL_WHITE);
	setCursorPos(5, 0);
	cout << "*** Texas Hold'em Poker ***";
	for (;;) {
		if( turn() ) {
			//	܂QlȏcĂꍇ
			g_table.dealFlop();
			if( turn() ) {
				//	܂QlȏcĂꍇ
				g_table.dealTurn();
				if( turn() ) {
					//	܂QlȏcĂꍇ
					g_table.dealTurn();
					turn();
				}
			}
		}
		draw_com(/*open:*/true);
		//	Z
		uint odr[2];		//	undone: RlȏΉ
		uint hand[2];
		std::vector<Card> v;
		for (int i = 0; i < g_table.nPlayer(); ++i) {
			g_table.playersCard(i, v);
			hand[i] = checkHand(v, odr[i]);
		}
		setColor(COL_GRAY, COL_BLACK);
		setCursorPos(COM_X, COM_Y + 3);
		cout << handName[hand[g_comIX]];
		setCursorPos(MAN_X, MAN_Y + 3);
		cout << handName[hand[g_manIX]];
	}
	//getchar();
	return 0;
}
/*
 e[uőR~jeBJ[hɍ킹
 fB[}[N\
 BB, SB }[N\
 `bv𐳂\
 pot \
 evC[̃xbgz\
  mt19937 ɕύX
 J[h\Fwiɍ or Ԃŕ`
 ĂJ[h̓VAŕ\
 j[f[^
 EL[Ńj[I\
 Ƃ肠 Check/Call Őɐi߂悤ɂ
 R[Ã^[ɐi
 R~jeBJ[h𐳂\
 FR[Ɏ`bvĂȂ
 FZɃRs[^̎DI[vȂ
 ZFʕ\
 PQ[I̐Z
 tH[h
 ㉺L[ŃCYzݒ\
 [AllIn] j[ǉ
*/
<|endoftext|>


<commit_before>#include <QtCore/QCoreApplication>
#include <QNetworkAccessManager>
#include <QTimer>
#include <QJSonDocument>
#include <QJsonObject>
#include <QDebug>

#include "../QPubNub.h"

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

    QNetworkAccessManager networkAccessManager;

    QPubNub pubnub(&networkAccessManager);
    pubnub.connect(&pubnub, &QPubNub::trace, [](QString message) {
      qDebug() << "Trace:" << qPrintable(message);
    });
    pubnub.time();
    pubnub.setPublishKey("demo");
    pubnub.setSubscribeKey("demo");
    pubnub.connect(&pubnub, &QPubNub::error, [](QString message, int code) {
      qDebug() << "error:" << qPrintable(message);
    });
    pubnub.setCipherKey("enigma");
    pubnub.publish("qwertz", QJsonValue(QString("test")));
    pubnub.subscribe("qwertz");
    pubnub.connect(&pubnub, &QPubNub::message, [](QJsonValue value, QString timeToken, QString channel) {
      qDebug().nospace() << "[" << qPrintable(channel) << "]:" << value;
    });

    return a.exec();
}
<commit_msg>Fix warning for unreferenced parameter<commit_after>#include <QtCore/QCoreApplication>
#include <QNetworkAccessManager>
#include <QTimer>
#include <QJSonDocument>
#include <QJsonObject>
#include <QDebug>

#include "../QPubNub.h"

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

    QNetworkAccessManager networkAccessManager;

    QPubNub pubnub(&networkAccessManager);
    pubnub.connect(&pubnub, &QPubNub::trace, [](QString message) {
      qDebug() << "Trace:" << qPrintable(message);
    });
    pubnub.time();
    pubnub.setPublishKey("demo");
    pubnub.setSubscribeKey("demo");
    pubnub.connect(&pubnub, &QPubNub::error, [](QString message, int /* code */) {
      qDebug() << "error:" << qPrintable(message);
    });
    pubnub.setCipherKey("enigma");
    pubnub.publish("qwertz", QJsonValue(QString("test")));
    pubnub.subscribe("qwertz");
    pubnub.connect(&pubnub, &QPubNub::message, [](QJsonValue value, QString timeToken, QString channel) {
      qDebug().nospace() << "[" << qPrintable(channel) << "]:" << value;
    });

    return a.exec();
}
<|endoftext|>


<commit_before>/**
  MQTT433gateway - MQTT 433.92 MHz radio gateway utilizing ESPiLight
  Project home: https://github.com/puuu/MQTT433gateway/

  The MIT License (MIT)

  Copyright (c) 2016 Puuu

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation files
  (the "Software"), to deal in the Software without restriction,
  including without limitation the rights to use, copy, modify, merge,
  publish, distribute, sublicense, and/or sell copies of the Software,
  and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
*/

#include "config.h"

#include <ESP8266httpUpdate.h>
#include <ESP8266mDNS.h>
#include <FS.h>

#include <ArduinoSimpleLogging.h>
#include <ConfigWebServer.h>
#include <Heartbeat.h>
#include <MqttClient.h>
#include <RfHandler.h>
#include <SHAauth.h>
#include <Settings.h>
#include <SyslogLogTarget.h>
#include <WifiConnection.h>

#ifndef myMQTT_USERNAME
#define myMQTT_USERNAME nullptr
#define myMQTT_PASSWORD nullptr
#endif

#ifndef mySSID
#define mySSID nullptr
#define myWIFIPASSWD nullptr
#endif

const int HEARTBEAD_LED_PIN = 0;

WiFiClient wifi;

Settings settings(myMQTT_BROCKER, myMQTT_USERNAME, myMQTT_PASSWORD);
RfHandler *rf = nullptr;
ConfigWebServer *webServer;
MqttClient *mqttClient = nullptr;

Heartbeat beatLED(HEARTBEAD_LED_PIN);

SHAauth *otaAuth = nullptr;

SyslogLogTarget *syslogLog = nullptr;

bool logMode = false;
bool rawMode = false;

void handleOta(const String &topic, const String &payload) {
  if (topic == F("url")) {
    settings.updateOtaUrl(payload);
    mqttClient->publishOta(F("nonce"), otaAuth->nonce());
    return;
  }

  if ((topic == F("passwd")) && (settings.otaUrl.length() > 7)) {
    if (otaAuth->verify(payload)) {
      beatLED.on();
      Logger.info.print(F("Start OTA update from: "));
      Logger.info.println(settings.otaUrl);
      rf->disableReceiver();
      t_httpUpdate_return ret = ESPhttpUpdate.update(settings.otaUrl);
      switch (ret) {
        case HTTP_UPDATE_FAILED:
          Logger.error.print(F("HTTP_UPDATE_FAILD Error ("));
          Logger.error.print(ESPhttpUpdate.getLastError());
          Logger.error.print(F("): "));
          Logger.error.println(ESPhttpUpdate.getLastErrorString());
          break;
        case HTTP_UPDATE_NO_UPDATES:
          Logger.info.println(F("HTTP_UPDATE_NO_UPDATES"));
          break;
        case HTTP_UPDATE_OK:
          Logger.info.println(
              F("HTTP_UPDATE_OK"));  // may not called ESPhttpUpdate
          // reboot the ESP?
          ESP.restart();
          break;
      }
      rf->enableReceiver();
    } else {
      Logger.warning.println(F("OTA authentication failed!"));
    }
  }
}

void reconnectMqtt(const Settings &) {
  if (mqttClient != nullptr) {
    delete mqttClient;
    mqttClient = nullptr;
  }

  mqttClient = new MqttClient(settings, wifi);
  mqttClient->begin();

  mqttClient->registerSetHandler(F("log"), [](const String &payload) {
    if (rf) rf->setLogMode(payload[0] == '1');
  });
  mqttClient->registerSetHandler(F("raw"), [](const String &payload) {
    if (rf) rf->setRawMode(payload[0] == '1');
  });
  mqttClient->registerSetHandler(F("protocols"), [](const String &payload) {
    settings.updateProtocols(payload);
  });

  mqttClient->registerRfDataHandler(
      [](const String &protocol, const String &data) {
        if (rf) rf->transmitCode(protocol, data);
      });
  mqttClient->registerOtaHandler(handleOta);
}

void setupRf(const Settings &) {
  // Init only on first load. We need to reboot else.
  if (rf) {
    return;
  }
  rf =
      new RfHandler(settings,
                    [](const String &protocol, const String &data) {
                      if (mqttClient) {
                        mqttClient->publishCode(protocol, data);
                      }
                    },
                    [](int statuc, const String &protocol, const String &data) {
                      if (mqttClient) {
                        mqttClient->publishLog(statuc, protocol, data);
                      }
                    },
                    [](const String &data) {
                      if (mqttClient) {
                        mqttClient->publishRaw(data);
                      }
                    });
  rf->begin();
}

void setupWebLog() {
  if (webServer) {
    if (settings.webLogLevel.length() > 0) {
      Logger.addHandler(Logger.stringToLevel(settings.webLogLevel),
                        webServer->logTarget());
    } else {
      Logger.removeHandler(webServer->logTarget());
    }
  }
}

void setupWebServer(const Settings &s) {
  webServer = new ConfigWebServer();

  webServer->registerSystemCommandHandler(F("restart"), []() {
    delay(100);
    ESP.restart();
  });
  webServer->registerSystemCommandHandler(F("reset_wifi"), resetWifiConfig);
  webServer->registerSystemCommandHandler(F("reset_config"),
                                          []() { settings.reset(); });

  webServer->registerProtocolProvider([]() {
    if (rf) {
      return rf->availableProtocols();
    }
    return String(F("[]"));
  });
  webServer->begin(settings);

  setupWebLog();
}

void setupMdns() {
  if (0 == settings.mdnsName.length()) {
    return;
  }
  if (!MDNS.begin(settings.mdnsName.c_str())) {
    Logger.error.println(F("Error setting up MDNS responder"));
  }

  MDNS.addService("http", "tcp", 80);
}

void setup() {
  Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
  Logger.addHandler(Logger.DEBUG, Serial);
  SPIFFS.begin();

  if (!connectWifi(mySSID, myWIFIPASSWD, []() { beatLED.loop(); })) {
    Logger.warning.println(F("Try connecting again after reboot"));
    ESP.restart();
  }

  settings.registerChangeHandler(MQTT, reconnectMqtt);

  settings.registerChangeHandler(RF_ECHO, [](const Settings &s) {
    if (rf) rf->setEchoEnabled(s.rfEchoMessages);
  });

  settings.registerChangeHandler(RF_PROTOCOL, [](const Settings &s) {
    if (rf) rf->filterProtocols(s.rfProtocols);
  });

  settings.registerChangeHandler(OTA, [](const Settings &s) {
    if (otaAuth) {
      delete (otaAuth);
    }
    otaAuth = new SHAauth(s.otaPassword);
  });

  settings.registerChangeHandler(WEB_CONFIG, [](const Settings &s) {
    if (!webServer) {
      setupWebServer(s);
    } else {
      webServer->updateSettings(s);
    }
  });

  settings.registerChangeHandler(SYSLOG, [](const Settings &s) {
    if (syslogLog) {
      Logger.removeHandler(*syslogLog);
      delete syslogLog;
    }
    if (s.syslogLevel.length() != 0 && s.syslogHost.length() != 0 &&
        s.syslogPort != 0) {
      syslogLog = new SyslogLogTarget();
      Logger.addHandler(Logger.stringToLevel(s.syslogLevel), *syslogLog);
      syslogLog->begin(s.deviceName, s.syslogHost, s.syslogPort);
    }
  });

  settings.registerChangeHandler(RF_CONFIG, setupRf);

  settings.registerChangeHandler(LOGGING, [](const Settings &s) {
    Logger.addHandler(Logger.stringToLevel(settings.serialLogLevel), Serial);
    setupWebLog();
  });

  Logger.info.println(F("Load Settings..."));
  settings.load();

  Logger.debug.println(F("Current configuration:"));
  settings.serialize(Logger.debug, true, false);

  setupMdns();

  Logger.info.println("\n");
  Logger.info.print(F("Name: "));
  Logger.info.println(String(ESP.getChipId(), HEX));
}

void loop() {
  webServer->handleClient();

  mqttClient->loop();

  rf->loop();
  beatLED.loop();
}
<commit_msg>src/MQTT433gateway.cpp: Print error, if SPIFFS init failed.<commit_after>/**
  MQTT433gateway - MQTT 433.92 MHz radio gateway utilizing ESPiLight
  Project home: https://github.com/puuu/MQTT433gateway/

  The MIT License (MIT)

  Copyright (c) 2016 Puuu

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation files
  (the "Software"), to deal in the Software without restriction,
  including without limitation the rights to use, copy, modify, merge,
  publish, distribute, sublicense, and/or sell copies of the Software,
  and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
*/

#include "config.h"

#include <ESP8266httpUpdate.h>
#include <ESP8266mDNS.h>
#include <FS.h>

#include <ArduinoSimpleLogging.h>
#include <ConfigWebServer.h>
#include <Heartbeat.h>
#include <MqttClient.h>
#include <RfHandler.h>
#include <SHAauth.h>
#include <Settings.h>
#include <SyslogLogTarget.h>
#include <WifiConnection.h>

#ifndef myMQTT_USERNAME
#define myMQTT_USERNAME nullptr
#define myMQTT_PASSWORD nullptr
#endif

#ifndef mySSID
#define mySSID nullptr
#define myWIFIPASSWD nullptr
#endif

const int HEARTBEAD_LED_PIN = 0;

WiFiClient wifi;

Settings settings(myMQTT_BROCKER, myMQTT_USERNAME, myMQTT_PASSWORD);
RfHandler *rf = nullptr;
ConfigWebServer *webServer;
MqttClient *mqttClient = nullptr;

Heartbeat beatLED(HEARTBEAD_LED_PIN);

SHAauth *otaAuth = nullptr;

SyslogLogTarget *syslogLog = nullptr;

bool logMode = false;
bool rawMode = false;

void handleOta(const String &topic, const String &payload) {
  if (topic == F("url")) {
    settings.updateOtaUrl(payload);
    mqttClient->publishOta(F("nonce"), otaAuth->nonce());
    return;
  }

  if ((topic == F("passwd")) && (settings.otaUrl.length() > 7)) {
    if (otaAuth->verify(payload)) {
      beatLED.on();
      Logger.info.print(F("Start OTA update from: "));
      Logger.info.println(settings.otaUrl);
      rf->disableReceiver();
      t_httpUpdate_return ret = ESPhttpUpdate.update(settings.otaUrl);
      switch (ret) {
        case HTTP_UPDATE_FAILED:
          Logger.error.print(F("HTTP_UPDATE_FAILD Error ("));
          Logger.error.print(ESPhttpUpdate.getLastError());
          Logger.error.print(F("): "));
          Logger.error.println(ESPhttpUpdate.getLastErrorString());
          break;
        case HTTP_UPDATE_NO_UPDATES:
          Logger.info.println(F("HTTP_UPDATE_NO_UPDATES"));
          break;
        case HTTP_UPDATE_OK:
          Logger.info.println(
              F("HTTP_UPDATE_OK"));  // may not called ESPhttpUpdate
          // reboot the ESP?
          ESP.restart();
          break;
      }
      rf->enableReceiver();
    } else {
      Logger.warning.println(F("OTA authentication failed!"));
    }
  }
}

void reconnectMqtt(const Settings &) {
  if (mqttClient != nullptr) {
    delete mqttClient;
    mqttClient = nullptr;
  }

  mqttClient = new MqttClient(settings, wifi);
  mqttClient->begin();

  mqttClient->registerSetHandler(F("log"), [](const String &payload) {
    if (rf) rf->setLogMode(payload[0] == '1');
  });
  mqttClient->registerSetHandler(F("raw"), [](const String &payload) {
    if (rf) rf->setRawMode(payload[0] == '1');
  });
  mqttClient->registerSetHandler(F("protocols"), [](const String &payload) {
    settings.updateProtocols(payload);
  });

  mqttClient->registerRfDataHandler(
      [](const String &protocol, const String &data) {
        if (rf) rf->transmitCode(protocol, data);
      });
  mqttClient->registerOtaHandler(handleOta);
}

void setupRf(const Settings &) {
  // Init only on first load. We need to reboot else.
  if (rf) {
    return;
  }
  rf =
      new RfHandler(settings,
                    [](const String &protocol, const String &data) {
                      if (mqttClient) {
                        mqttClient->publishCode(protocol, data);
                      }
                    },
                    [](int statuc, const String &protocol, const String &data) {
                      if (mqttClient) {
                        mqttClient->publishLog(statuc, protocol, data);
                      }
                    },
                    [](const String &data) {
                      if (mqttClient) {
                        mqttClient->publishRaw(data);
                      }
                    });
  rf->begin();
}

void setupWebLog() {
  if (webServer) {
    if (settings.webLogLevel.length() > 0) {
      Logger.addHandler(Logger.stringToLevel(settings.webLogLevel),
                        webServer->logTarget());
    } else {
      Logger.removeHandler(webServer->logTarget());
    }
  }
}

void setupWebServer(const Settings &s) {
  webServer = new ConfigWebServer();

  webServer->registerSystemCommandHandler(F("restart"), []() {
    delay(100);
    ESP.restart();
  });
  webServer->registerSystemCommandHandler(F("reset_wifi"), resetWifiConfig);
  webServer->registerSystemCommandHandler(F("reset_config"),
                                          []() { settings.reset(); });

  webServer->registerProtocolProvider([]() {
    if (rf) {
      return rf->availableProtocols();
    }
    return String(F("[]"));
  });
  webServer->begin(settings);

  setupWebLog();
}

void setupMdns() {
  if (0 == settings.mdnsName.length()) {
    return;
  }
  if (!MDNS.begin(settings.mdnsName.c_str())) {
    Logger.error.println(F("Error setting up MDNS responder"));
  }

  MDNS.addService("http", "tcp", 80);
}

void setup() {
  Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
  Logger.addHandler(Logger.DEBUG, Serial);
  if (!SPIFFS.begin()) {
    Logger.error.println(F("Initializing of SPIFFS failed!"));
  }

  if (!connectWifi(mySSID, myWIFIPASSWD, []() { beatLED.loop(); })) {
    Logger.warning.println(F("Try connecting again after reboot"));
    ESP.restart();
  }

  settings.registerChangeHandler(MQTT, reconnectMqtt);

  settings.registerChangeHandler(RF_ECHO, [](const Settings &s) {
    if (rf) rf->setEchoEnabled(s.rfEchoMessages);
  });

  settings.registerChangeHandler(RF_PROTOCOL, [](const Settings &s) {
    if (rf) rf->filterProtocols(s.rfProtocols);
  });

  settings.registerChangeHandler(OTA, [](const Settings &s) {
    if (otaAuth) {
      delete (otaAuth);
    }
    otaAuth = new SHAauth(s.otaPassword);
  });

  settings.registerChangeHandler(WEB_CONFIG, [](const Settings &s) {
    if (!webServer) {
      setupWebServer(s);
    } else {
      webServer->updateSettings(s);
    }
  });

  settings.registerChangeHandler(SYSLOG, [](const Settings &s) {
    if (syslogLog) {
      Logger.removeHandler(*syslogLog);
      delete syslogLog;
    }
    if (s.syslogLevel.length() != 0 && s.syslogHost.length() != 0 &&
        s.syslogPort != 0) {
      syslogLog = new SyslogLogTarget();
      Logger.addHandler(Logger.stringToLevel(s.syslogLevel), *syslogLog);
      syslogLog->begin(s.deviceName, s.syslogHost, s.syslogPort);
    }
  });

  settings.registerChangeHandler(RF_CONFIG, setupRf);

  settings.registerChangeHandler(LOGGING, [](const Settings &s) {
    Logger.addHandler(Logger.stringToLevel(settings.serialLogLevel), Serial);
    setupWebLog();
  });

  Logger.info.println(F("Load Settings..."));
  settings.load();

  Logger.debug.println(F("Current configuration:"));
  settings.serialize(Logger.debug, true, false);

  setupMdns();

  Logger.info.println("\n");
  Logger.info.print(F("Name: "));
  Logger.info.println(String(ESP.getChipId(), HEX));
}

void loop() {
  webServer->handleClient();

  mqttClient->loop();

  rf->loop();
  beatLED.loop();
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <cassert>
#include <vector>

#include "TFile.h"
#include "TTree.h"
#include "TChain.h"
#include "TBranch.h"
#include "TBasket.h"

void readandtest (const std::string & fname)
{
  TFile* inputFile = new TFile(fname.c_str(),"READ");

  std::cout << "Print file info: " << std::endl;
  inputFile->Print();
  std::cout << std::endl;

  std::cout << "List file TTree: " << std::endl;
  inputFile->ls();
  std::cout << std::endl;

  std::cout << "Print TkStubs info: " << std::endl;
  TTree* t1 = (TTree*) inputFile->Get("TkStubs");
  TChain* TT = (TChain*) inputFile->Get("TkStubs");
  t1->Print();
  std::cout << std::endl;

  std::vector<int> layerid, * p_layerid, moduleid, * p_moduleid,
    ladderid, * p_ladderid, tp, * p_tp;
  p_layerid = &layerid;
  p_ladderid = &ladderid;
  p_moduleid = &moduleid;
  p_tp = &tp;

  TT->SetBranchAddress("L1TkSTUB_layer", &p_layerid);
  TT->SetBranchAddress("L1TkSTUB_ladder", &p_ladderid);
  TT->SetBranchAddress("L1TkSTUB_module", &p_moduleid);
  TT->SetBranchAddress("L1TkSTUB_tp", &p_tp);

  std::vector<float> stubx, * p_stubx, stuby, * p_stuby, stubz, * p_stubz,
    px, * p_px, py, * p_py, x0, * p_x0, y0, * p_y0, z0, * p_z0, eta, * p_eta,
    phi, * p_phi;
  p_stubx = &stubx;
  p_stuby = &stuby;
  p_stubz = &stubz;
  p_px = &px;
  p_py = &py;
  p_x0 = &x0;
  p_y0 = &y0;
  p_z0 = &z0;
  p_eta = η
  p_phi = φ

  TT->SetBranchAddress("L1TkSTUB_x", &p_stubx);
  TT->SetBranchAddress("L1TkSTUB_y", &p_stuby);
  TT->SetBranchAddress("L1TkSTUB_z", &p_stubz);

  TT->SetBranchAddress("L1TkSTUB_pxGEN", &p_px);
  TT->SetBranchAddress("L1TkSTUB_pyGEN", &p_py);
  TT->SetBranchAddress("L1TkSTUB_X0", &p_x0);
  TT->SetBranchAddress("L1TkSTUB_Y0", &p_y0);
  TT->SetBranchAddress("L1TkSTUB_Z0", &p_z0);
  TT->SetBranchAddress("L1TkSTUB_etaGEN", &p_eta);
  TT->SetBranchAddress("L1TkSTUB_PHI0", &p_phi);

  unsigned int countevt = 0;
  Int_t nevent = t1->GetEntries();
  std::cout << "We got " << nevent << " events " << std::endl;
  for (Int_t i=0; i<nevent; ++i)
  {
     //L1TkSTUB_tp tutti gli stub appartenti alla stessa traccia hanno stesso tp
     //  posso avere eventi con molte tracce devo solezionarle usando tp
     //
     //StubExtractor e' utile punto di partenza visto che contiene il codice
     //   che scrive il Tree L1Tk

     t1->GetEvent(i);
     assert (layerid.size() == ladderid.size());
     assert (layerid.size() == moduleid.size());
     assert (layerid.size() == tp.size());

     assert (layerid.size() == stubx.size());
     assert (layerid.size() == stuby.size());
     assert (layerid.size() == stubz.size());
     assert (layerid.size() == px.size());
     assert (layerid.size() == py.size());
     assert (layerid.size() == x0.size());
     assert (layerid.size() == y0.size());
     assert (layerid.size() == z0.size());
     assert (layerid.size() == eta.size());
     assert (layerid.size() == phi.size());

     /*
      *
      * pT = sqrt(pxGEN^2 + pyGEN^2)
      * Phi = PHI0
      * d0 = sqrt(X0^2 + Y0^2)
      * Eta = etaGEN
      * z0 = Z0
      *
      */

     if (layerid.size() == 6)
     {
       std::cout << "Event: " << i+1 << " size " << tp.size() << std::endl;

       for (int j=0; j<(int)layerid.size(); ++j)
       {
         std::cout << stubx[j] << " " << stuby[j] << " " <<
           stubz[j];
         std::cout << layerid[j] << " " << ladderid[j] << " " <<
           moduleid[j] << " "  << tp[j] << std::endl;
       }

       countevt++;
     }

     //t1->Show(i);
  }

  std::cout << "Event with 6 layer " << countevt << std::endl;

  inputFile->Close();
}

# ifndef __CINT__
int main(int argc, char ** argv)
{
  if (argc != 2)
  {
    std::cerr << "usage: " << argv[0] << " rootfilename " << std::endl;
    return 1;
  }

  readandtest(argv[1]);

  return 0;
}
# endif
<commit_msg>printout also track parameter<commit_after>#include <iostream>
#include <cassert>
#include <sstream>
#include <fstream>
#include <vector>
#include <string>
#include <cmath>

#include "TFile.h"
#include "TTree.h"
#include "TChain.h"
#include "TBranch.h"
#include "TBasket.h"

void readandtest (const std::string & fname)
{
  TFile* inputFile = new TFile(fname.c_str(),"READ");

  std::cout << "Print file info: " << std::endl;
  inputFile->Print();
  std::cout << std::endl;

  std::cout << "List file TTree: " << std::endl;
  inputFile->ls();
  std::cout << std::endl;

  std::cout << "Print TkStubs info: " << std::endl;
  TTree* t1 = (TTree*) inputFile->Get("TkStubs");
  TChain* TT = (TChain*) inputFile->Get("TkStubs");
  t1->Print();
  std::cout << std::endl;

  std::vector<int> layerid, * p_layerid, moduleid, * p_moduleid,
    ladderid, * p_ladderid, tp, * p_tp;
  p_layerid = &layerid;
  p_ladderid = &ladderid;
  p_moduleid = &moduleid;
  p_tp = &tp;

  TT->SetBranchAddress("L1TkSTUB_layer", &p_layerid);
  TT->SetBranchAddress("L1TkSTUB_ladder", &p_ladderid);
  TT->SetBranchAddress("L1TkSTUB_module", &p_moduleid);
  TT->SetBranchAddress("L1TkSTUB_tp", &p_tp);

  std::vector<float> stubx, * p_stubx, stuby, * p_stuby, stubz, * p_stubz,
    px, * p_px, py, * p_py, x0, * p_x0, y0, * p_y0, z0, * p_z0, eta, * p_eta,
    phi, * p_phi;
  p_stubx = &stubx;
  p_stuby = &stuby;
  p_stubz = &stubz;
  p_px = &px;
  p_py = &py;
  p_x0 = &x0;
  p_y0 = &y0;
  p_z0 = &z0;
  p_eta = η
  p_phi = φ

  TT->SetBranchAddress("L1TkSTUB_x", &p_stubx);
  TT->SetBranchAddress("L1TkSTUB_y", &p_stuby);
  TT->SetBranchAddress("L1TkSTUB_z", &p_stubz);

  TT->SetBranchAddress("L1TkSTUB_pxGEN", &p_px);
  TT->SetBranchAddress("L1TkSTUB_pyGEN", &p_py);
  TT->SetBranchAddress("L1TkSTUB_X0", &p_x0);
  TT->SetBranchAddress("L1TkSTUB_Y0", &p_y0);
  TT->SetBranchAddress("L1TkSTUB_Z0", &p_z0);
  TT->SetBranchAddress("L1TkSTUB_etaGEN", &p_eta);
  TT->SetBranchAddress("L1TkSTUB_PHI0", &p_phi);

  unsigned int countevt = 0;
  Int_t nevent = t1->GetEntries();
  std::cout << "We got " << nevent << " events " << std::endl;
  std::ofstream ptfile("pt.txt");
  std::ofstream phifile("phi.txt");
  std::ofstream d0file("d0.txt");
  std::ofstream etafile("eta.txt");
  std::ofstream z0file("z0.txt");
  for (Int_t i=0; i<nevent; ++i)
  {
     //L1TkSTUB_tp tutti gli stub appartenti alla stessa traccia hanno stesso tp
     //  posso avere eventi con molte tracce devo solezionarle usando tp
     //
     //StubExtractor e' utile punto di partenza visto che contiene il codice
     //   che scrive il Tree L1Tk

     t1->GetEvent(i);
     assert (layerid.size() == ladderid.size());
     assert (layerid.size() == moduleid.size());
     assert (layerid.size() == tp.size());

     assert (layerid.size() == stubx.size());
     assert (layerid.size() == stuby.size());
     assert (layerid.size() == stubz.size());
     assert (layerid.size() == px.size());
     assert (layerid.size() == py.size());
     assert (layerid.size() == x0.size());
     assert (layerid.size() == y0.size());
     assert (layerid.size() == z0.size());
     assert (layerid.size() == eta.size());
     assert (layerid.size() == phi.size());

     /*
      *
      * pT = sqrt(pxGEN^2 + pyGEN^2)
      * Phi = PHI0
      * d0 = sqrt(X0^2 + Y0^2)
      * Eta = etaGEN
      * z0 = Z0
      *
      */

     if (layerid.size() == 6)
     {
       std::cout << "Event: " << i+1 << " size " << tp.size() << std::endl;

       for (int j=0; j<(int)layerid.size(); ++j)
       {
         std::cout << stubx[j] << " " << stuby[j] << " " <<
           stubz[j] << " ";
         std::cout << sqrt(pow(px[j],2.0) + pow(py[j],2.0)) << " "  <<
           phi[j] << " " << sqrt(pow(x0[j],2.0) + pow(y0[j],2.0)) << " "
           << eta[j] << " " << z0[j] << " ";
         std::cout << layerid[j] << " " << ladderid[j] << " " <<
           moduleid[j] << " "  << tp[j] << std::endl;

         ptfile << i << " " << sqrt(pow(px[j],2.0) + pow(py[j],2.0))
           << std::endl;
         phifile << i << " " << phi[j] << std::endl;
         d0file << i << " " << sqrt(pow(x0[j],2.0) + pow(y0[j],2.0))
           << std::endl;
         etafile << i << " " << eta[j] << std::endl;
         z0file << i << " " << z0[j] << std::endl;
       }

       countevt++;

     }

     //t1->Show(i);
  }
  ptfile.close();
  phifile.close();
  d0file.close();
  etafile.close();
  z0file.close();

  std::cout << "Event with 6 layer " << countevt << std::endl;

  inputFile->Close();
}

# ifndef __CINT__
int main(int argc, char ** argv)
{
  if (argc != 2)
  {
    std::cerr << "usage: " << argv[0] << " rootfilename " << std::endl;
    return 1;
  }

  readandtest(argv[1]);

  return 0;
}
# endif
<|endoftext|>


<commit_before>#include "RuntimeManager.h"

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/IntrinsicInst.h>
#include "preprocessor/llvm_includes_end.h"

#include "Stack.h"
#include "Utils.h"

namespace dev
{
namespace eth
{
namespace jit
{

llvm::StructType* RuntimeManager::getRuntimeDataType()
{
	static llvm::StructType* type = nullptr;
	if (!type)
	{
		llvm::Type* elems[] =
		{
			Type::Size,		// gas
			Type::Size,		// gasPrice
			Type::BytePtr,	// callData
			Type::Size,		// callDataSize
			Type::Word,		// address
			Type::Word,		// caller
			Type::Word,		// origin
			Type::Word,		// callValue
			Type::Word,		// coinBase
			Type::Word,		// difficulty
			Type::Word,		// gasLimit
			Type::Size,		// blockNumber
			Type::Size,		// blockTimestamp
			Type::BytePtr,	// code
			Type::Size,		// codeSize
		};
		type = llvm::StructType::create(elems, "RuntimeData");
	}
	return type;
}

llvm::StructType* RuntimeManager::getRuntimeType()
{
	static llvm::StructType* type = nullptr;
	if (!type)
	{
		llvm::Type* elems[] =
		{
			Type::RuntimeDataPtr,	// data
			Type::EnvPtr,			// Env*
			Array::getType()		// memory
		};
		type = llvm::StructType::create(elems, "Runtime");
	}
	return type;
}

namespace
{
llvm::Twine getName(RuntimeData::Index _index)
{
	switch (_index)
	{
	default:						return "data";
	case RuntimeData::Address:		return "address";
	case RuntimeData::Caller:		return "caller";
	case RuntimeData::Origin:		return "origin";
	case RuntimeData::CallValue:	return "callvalue";
	case RuntimeData::GasPrice:		return "gasprice";
	case RuntimeData::CoinBase:		return "coinbase";
	case RuntimeData::Difficulty:	return "difficulty";
	case RuntimeData::GasLimit:		return "gaslimit";
	case RuntimeData::CallData:		return "callData";
	case RuntimeData::Code:			return "code";
	case RuntimeData::CodeSize:		return "code";
	case RuntimeData::CallDataSize:	return "callDataSize";
	case RuntimeData::Gas:			return "gas";
	case RuntimeData::Number:		return "number";
	case RuntimeData::Timestamp:	return "timestamp";
	}
}
}

RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeBegin, code_iterator _codeEnd):
	CompilerHelper(_builder),
	m_codeBegin(_codeBegin),
	m_codeEnd(_codeEnd)
{
	m_longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::eh_sjlj_longjmp);

	// Unpack data
	auto rtPtr = getRuntimePtr();
	m_dataPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 0), "data");
	assert(m_dataPtr->getType() == Type::RuntimeDataPtr);
	m_gasPtr = m_builder.CreateStructGEP(m_dataPtr, 0, "gas");
	assert(m_gasPtr->getType() == Type::Gas->getPointerTo());
	m_memPtr = m_builder.CreateStructGEP(rtPtr, 2, "mem");
	assert(m_memPtr->getType() == Array::getType()->getPointerTo());
	m_envPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 1), "env");
	assert(m_envPtr->getType() == Type::EnvPtr);

	m_stackSize = m_builder.CreateAlloca(Type::Size, nullptr, "stackSize");
	m_builder.CreateStore(m_builder.getInt64(0), m_stackSize);

	llvm::Type* checkStackLimitArgs[] = {Type::Size->getPointerTo(), Type::Size, Type::Size, Type::BytePtr};
	m_checkStackLimit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, checkStackLimitArgs, false), llvm::Function::PrivateLinkage, "stack.checkSize", getModule());
	m_checkStackLimit->setDoesNotThrow();
	m_checkStackLimit->setDoesNotCapture(1);

	auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_checkStackLimit);
	auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "Update", m_checkStackLimit);
	auto outOfStackBB = llvm::BasicBlock::Create(_builder.getContext(), "OutOfStack", m_checkStackLimit);

	auto currSizePtr = &m_checkStackLimit->getArgumentList().front();
	currSizePtr->setName("currSize");
	auto max = currSizePtr->getNextNode();
	max->setName("max");
	auto diff = max->getNextNode();
	diff->setName("diff");
	auto jmpBuf = diff->getNextNode();
	jmpBuf->setName("jmpBuf");

	InsertPointGuard guard{m_builder};
	m_builder.SetInsertPoint(checkBB);
	auto currSize = m_builder.CreateLoad(currSizePtr, "cur");
	auto maxSize = m_builder.CreateNUWAdd(currSize, max, "maxSize");
	auto ok = m_builder.CreateICmpULT(maxSize, m_builder.getInt64(1024), "ok");
	m_builder.CreateCondBr(ok, updateBB, outOfStackBB, Type::expectTrue);

	m_builder.SetInsertPoint(updateBB);
	auto newSize = m_builder.CreateNSWAdd(currSize, diff);
	m_builder.CreateStore(newSize, currSizePtr);
	m_builder.CreateRetVoid();

	m_builder.SetInsertPoint(outOfStackBB);
	abort(jmpBuf);
	m_builder.CreateUnreachable();
}

void RuntimeManager::checkStackLimit(size_t _max, int _diff)
{
	createCall(m_checkStackLimit, {m_stackSize, m_builder.getInt64(_max), m_builder.getInt64(_diff), getJmpBuf()});
}

llvm::Value* RuntimeManager::getRuntimePtr()
{
	// Expect first argument of a function to be a pointer to Runtime
	auto func = m_builder.GetInsertBlock()->getParent();
	auto rtPtr = &func->getArgumentList().front();
	assert(rtPtr->getType() == Type::RuntimePtr);
	return rtPtr;
}

llvm::Value* RuntimeManager::getDataPtr()
{
	if (getMainFunction())
		return m_dataPtr;

	auto rtPtr = getRuntimePtr();
	auto dataPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 0), "data");
	assert(dataPtr->getType() == getRuntimeDataType()->getPointerTo());
	return dataPtr;
}

llvm::Value* RuntimeManager::getEnvPtr()
{
	assert(getMainFunction());	// Available only in main function
	return m_envPtr;
}

llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index)
{
	auto ptr = getBuilder().CreateStructGEP(getDataPtr(), _index);
	assert(getRuntimeDataType()->getElementType(_index)->getPointerTo() == ptr->getType());
	return ptr;
}

llvm::Value* RuntimeManager::get(RuntimeData::Index _index)
{
	return getBuilder().CreateLoad(getPtr(_index), getName(_index));
}

void RuntimeManager::set(RuntimeData::Index _index, llvm::Value* _value)
{
	auto ptr = getPtr(_index);
	assert(ptr->getType() == _value->getType()->getPointerTo());
	getBuilder().CreateStore(_value, ptr);
}

void RuntimeManager::registerReturnData(llvm::Value* _offset, llvm::Value* _size)
{
	auto memPtr = m_builder.CreateBitCast(getMem(), Type::BytePtr->getPointerTo());
	auto mem = getBuilder().CreateLoad(memPtr, "memory");
	auto idx = m_builder.CreateTrunc(_offset, Type::Size, "idx"); // Never allow memory index be a type bigger than i64 // TODO: Report bug & fix to LLVM
	auto returnDataPtr = getBuilder().CreateGEP(mem, idx);
	set(RuntimeData::ReturnData, returnDataPtr);

	auto size64 = getBuilder().CreateTrunc(_size, Type::Size);
	set(RuntimeData::ReturnDataSize, size64);
}

void RuntimeManager::registerSuicide(llvm::Value* _balanceAddress)
{
	set(RuntimeData::SuicideDestAddress, _balanceAddress);
}

void RuntimeManager::exit(ReturnCode _returnCode)
{
	if (m_stack)
		m_stack->free();

	m_builder.CreateRet(Constant::get(_returnCode));
}

void RuntimeManager::abort(llvm::Value* _jmpBuf)
{
	auto longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::eh_sjlj_longjmp);
	createCall(longjmp, {_jmpBuf});
}

llvm::Value* RuntimeManager::get(Instruction _inst)
{
	switch (_inst)
	{
	default: assert(false); return nullptr;
	case Instruction::ADDRESS:		return get(RuntimeData::Address);
	case Instruction::CALLER:		return get(RuntimeData::Caller);
	case Instruction::ORIGIN:		return get(RuntimeData::Origin);
	case Instruction::CALLVALUE:	return get(RuntimeData::CallValue);
	case Instruction::GASPRICE:		return get(RuntimeData::GasPrice);
	case Instruction::COINBASE:		return get(RuntimeData::CoinBase);
	case Instruction::DIFFICULTY:	return get(RuntimeData::Difficulty);
	case Instruction::GASLIMIT:		return get(RuntimeData::GasLimit);
	case Instruction::NUMBER:		return get(RuntimeData::Number);
	case Instruction::TIMESTAMP:	return get(RuntimeData::Timestamp);
	}
}

llvm::Value* RuntimeManager::getCallData()
{
	return get(RuntimeData::CallData);
}

llvm::Value* RuntimeManager::getCode()
{
	// OPT Check what is faster
	//return get(RuntimeData::Code);
	return m_builder.CreateGlobalStringPtr({reinterpret_cast<char const*>(m_codeBegin), static_cast<size_t>(m_codeEnd - m_codeBegin)}, "code");
}

llvm::Value* RuntimeManager::getCodeSize()
{
	return Constant::get(m_codeEnd - m_codeBegin);
}

llvm::Value* RuntimeManager::getCallDataSize()
{
	auto value = get(RuntimeData::CallDataSize);
	assert(value->getType() == Type::Size);
	return getBuilder().CreateZExt(value, Type::Word);
}

llvm::Value* RuntimeManager::getGas()
{
	auto gas = get(RuntimeData::Gas);
	assert(gas->getType() == Type::Gas);
	return gas;
}

llvm::Value* RuntimeManager::getGasPtr()
{
	assert(getMainFunction());
	return m_gasPtr;
}

llvm::Value* RuntimeManager::getMem()
{
	assert(getMainFunction());
	return m_memPtr;
}

void RuntimeManager::setGas(llvm::Value* _gas)
{
	assert(_gas->getType() == Type::Gas);
	set(RuntimeData::Gas, _gas);
}

}
}
}
<commit_msg>Fix stack limit check<commit_after>#include "RuntimeManager.h"

#include "preprocessor/llvm_includes_start.h"
#include <llvm/IR/IntrinsicInst.h>
#include "preprocessor/llvm_includes_end.h"

#include "Stack.h"
#include "Utils.h"

namespace dev
{
namespace eth
{
namespace jit
{

llvm::StructType* RuntimeManager::getRuntimeDataType()
{
	static llvm::StructType* type = nullptr;
	if (!type)
	{
		llvm::Type* elems[] =
		{
			Type::Size,		// gas
			Type::Size,		// gasPrice
			Type::BytePtr,	// callData
			Type::Size,		// callDataSize
			Type::Word,		// address
			Type::Word,		// caller
			Type::Word,		// origin
			Type::Word,		// callValue
			Type::Word,		// coinBase
			Type::Word,		// difficulty
			Type::Word,		// gasLimit
			Type::Size,		// blockNumber
			Type::Size,		// blockTimestamp
			Type::BytePtr,	// code
			Type::Size,		// codeSize
		};
		type = llvm::StructType::create(elems, "RuntimeData");
	}
	return type;
}

llvm::StructType* RuntimeManager::getRuntimeType()
{
	static llvm::StructType* type = nullptr;
	if (!type)
	{
		llvm::Type* elems[] =
		{
			Type::RuntimeDataPtr,	// data
			Type::EnvPtr,			// Env*
			Array::getType()		// memory
		};
		type = llvm::StructType::create(elems, "Runtime");
	}
	return type;
}

namespace
{
llvm::Twine getName(RuntimeData::Index _index)
{
	switch (_index)
	{
	default:						return "data";
	case RuntimeData::Address:		return "address";
	case RuntimeData::Caller:		return "caller";
	case RuntimeData::Origin:		return "origin";
	case RuntimeData::CallValue:	return "callvalue";
	case RuntimeData::GasPrice:		return "gasprice";
	case RuntimeData::CoinBase:		return "coinbase";
	case RuntimeData::Difficulty:	return "difficulty";
	case RuntimeData::GasLimit:		return "gaslimit";
	case RuntimeData::CallData:		return "callData";
	case RuntimeData::Code:			return "code";
	case RuntimeData::CodeSize:		return "code";
	case RuntimeData::CallDataSize:	return "callDataSize";
	case RuntimeData::Gas:			return "gas";
	case RuntimeData::Number:		return "number";
	case RuntimeData::Timestamp:	return "timestamp";
	}
}
}

RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, code_iterator _codeBegin, code_iterator _codeEnd):
	CompilerHelper(_builder),
	m_codeBegin(_codeBegin),
	m_codeEnd(_codeEnd)
{
	m_longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::eh_sjlj_longjmp);

	// Unpack data
	auto rtPtr = getRuntimePtr();
	m_dataPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 0), "data");
	assert(m_dataPtr->getType() == Type::RuntimeDataPtr);
	m_gasPtr = m_builder.CreateStructGEP(m_dataPtr, 0, "gas");
	assert(m_gasPtr->getType() == Type::Gas->getPointerTo());
	m_memPtr = m_builder.CreateStructGEP(rtPtr, 2, "mem");
	assert(m_memPtr->getType() == Array::getType()->getPointerTo());
	m_envPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 1), "env");
	assert(m_envPtr->getType() == Type::EnvPtr);

	m_stackSize = m_builder.CreateAlloca(Type::Size, nullptr, "stackSize");
	m_builder.CreateStore(m_builder.getInt64(0), m_stackSize);

	llvm::Type* checkStackLimitArgs[] = {Type::Size->getPointerTo(), Type::Size, Type::Size, Type::BytePtr};
	m_checkStackLimit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, checkStackLimitArgs, false), llvm::Function::PrivateLinkage, "stack.checkSize", getModule());
	m_checkStackLimit->setDoesNotThrow();
	m_checkStackLimit->setDoesNotCapture(1);

	auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_checkStackLimit);
	auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "Update", m_checkStackLimit);
	auto outOfStackBB = llvm::BasicBlock::Create(_builder.getContext(), "OutOfStack", m_checkStackLimit);

	auto currSizePtr = &m_checkStackLimit->getArgumentList().front();
	currSizePtr->setName("currSize");
	auto max = currSizePtr->getNextNode();
	max->setName("max");
	auto diff = max->getNextNode();
	diff->setName("diff");
	auto jmpBuf = diff->getNextNode();
	jmpBuf->setName("jmpBuf");

	InsertPointGuard guard{m_builder};
	m_builder.SetInsertPoint(checkBB);
	auto currSize = m_builder.CreateLoad(currSizePtr, "cur");
	auto maxSize = m_builder.CreateNUWAdd(currSize, max, "maxSize");
	auto ok = m_builder.CreateICmpULE(maxSize, m_builder.getInt64(1024), "ok");
	m_builder.CreateCondBr(ok, updateBB, outOfStackBB, Type::expectTrue);

	m_builder.SetInsertPoint(updateBB);
	auto newSize = m_builder.CreateNSWAdd(currSize, diff);
	m_builder.CreateStore(newSize, currSizePtr);
	m_builder.CreateRetVoid();

	m_builder.SetInsertPoint(outOfStackBB);
	abort(jmpBuf);
	m_builder.CreateUnreachable();
}

void RuntimeManager::checkStackLimit(size_t _max, int _diff)
{
	createCall(m_checkStackLimit, {m_stackSize, m_builder.getInt64(_max), m_builder.getInt64(_diff), getJmpBuf()});
}

llvm::Value* RuntimeManager::getRuntimePtr()
{
	// Expect first argument of a function to be a pointer to Runtime
	auto func = m_builder.GetInsertBlock()->getParent();
	auto rtPtr = &func->getArgumentList().front();
	assert(rtPtr->getType() == Type::RuntimePtr);
	return rtPtr;
}

llvm::Value* RuntimeManager::getDataPtr()
{
	if (getMainFunction())
		return m_dataPtr;

	auto rtPtr = getRuntimePtr();
	auto dataPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 0), "data");
	assert(dataPtr->getType() == getRuntimeDataType()->getPointerTo());
	return dataPtr;
}

llvm::Value* RuntimeManager::getEnvPtr()
{
	assert(getMainFunction());	// Available only in main function
	return m_envPtr;
}

llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index)
{
	auto ptr = getBuilder().CreateStructGEP(getDataPtr(), _index);
	assert(getRuntimeDataType()->getElementType(_index)->getPointerTo() == ptr->getType());
	return ptr;
}

llvm::Value* RuntimeManager::get(RuntimeData::Index _index)
{
	return getBuilder().CreateLoad(getPtr(_index), getName(_index));
}

void RuntimeManager::set(RuntimeData::Index _index, llvm::Value* _value)
{
	auto ptr = getPtr(_index);
	assert(ptr->getType() == _value->getType()->getPointerTo());
	getBuilder().CreateStore(_value, ptr);
}

void RuntimeManager::registerReturnData(llvm::Value* _offset, llvm::Value* _size)
{
	auto memPtr = m_builder.CreateBitCast(getMem(), Type::BytePtr->getPointerTo());
	auto mem = getBuilder().CreateLoad(memPtr, "memory");
	auto idx = m_builder.CreateTrunc(_offset, Type::Size, "idx"); // Never allow memory index be a type bigger than i64 // TODO: Report bug & fix to LLVM
	auto returnDataPtr = getBuilder().CreateGEP(mem, idx);
	set(RuntimeData::ReturnData, returnDataPtr);

	auto size64 = getBuilder().CreateTrunc(_size, Type::Size);
	set(RuntimeData::ReturnDataSize, size64);
}

void RuntimeManager::registerSuicide(llvm::Value* _balanceAddress)
{
	set(RuntimeData::SuicideDestAddress, _balanceAddress);
}

void RuntimeManager::exit(ReturnCode _returnCode)
{
	if (m_stack)
		m_stack->free();

	m_builder.CreateRet(Constant::get(_returnCode));
}

void RuntimeManager::abort(llvm::Value* _jmpBuf)
{
	auto longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::eh_sjlj_longjmp);
	createCall(longjmp, {_jmpBuf});
}

llvm::Value* RuntimeManager::get(Instruction _inst)
{
	switch (_inst)
	{
	default: assert(false); return nullptr;
	case Instruction::ADDRESS:		return get(RuntimeData::Address);
	case Instruction::CALLER:		return get(RuntimeData::Caller);
	case Instruction::ORIGIN:		return get(RuntimeData::Origin);
	case Instruction::CALLVALUE:	return get(RuntimeData::CallValue);
	case Instruction::GASPRICE:		return get(RuntimeData::GasPrice);
	case Instruction::COINBASE:		return get(RuntimeData::CoinBase);
	case Instruction::DIFFICULTY:	return get(RuntimeData::Difficulty);
	case Instruction::GASLIMIT:		return get(RuntimeData::GasLimit);
	case Instruction::NUMBER:		return get(RuntimeData::Number);
	case Instruction::TIMESTAMP:	return get(RuntimeData::Timestamp);
	}
}

llvm::Value* RuntimeManager::getCallData()
{
	return get(RuntimeData::CallData);
}

llvm::Value* RuntimeManager::getCode()
{
	// OPT Check what is faster
	//return get(RuntimeData::Code);
	return m_builder.CreateGlobalStringPtr({reinterpret_cast<char const*>(m_codeBegin), static_cast<size_t>(m_codeEnd - m_codeBegin)}, "code");
}

llvm::Value* RuntimeManager::getCodeSize()
{
	return Constant::get(m_codeEnd - m_codeBegin);
}

llvm::Value* RuntimeManager::getCallDataSize()
{
	auto value = get(RuntimeData::CallDataSize);
	assert(value->getType() == Type::Size);
	return getBuilder().CreateZExt(value, Type::Word);
}

llvm::Value* RuntimeManager::getGas()
{
	auto gas = get(RuntimeData::Gas);
	assert(gas->getType() == Type::Gas);
	return gas;
}

llvm::Value* RuntimeManager::getGasPtr()
{
	assert(getMainFunction());
	return m_gasPtr;
}

llvm::Value* RuntimeManager::getMem()
{
	assert(getMainFunction());
	return m_memPtr;
}

void RuntimeManager::setGas(llvm::Value* _gas)
{
	assert(_gas->getType() == Type::Gas);
	set(RuntimeData::Gas, _gas);
}

}
}
}
<|endoftext|>


<commit_before>// This example is to get the last value of variable from the Ubidots API

// This example is to save multiple variables to the Ubidots API with TCP method

/****************************************
 * Include Libraries
 ****************************************/

#include "Ubidots.h"

/****************************************
 * Define Constants
 ****************************************/

#ifndef TOKEN
#define TOKEN "Your_Token"  // Put here your Ubidots TOKEN
#endif

Ubidots ubidots(TOKEN);

/****************************************
 * Auxiliar Functions
 ****************************************/

//Put here your auxiliar functions

/****************************************
 * Main Functions
 ****************************************/

void setup() {
  Serial.begin(115200);
  //ubidots.setDebug(true);  //Uncomment this line for printing debug messages
}

void loop() {
  float value1 = analogRead(A0);
  float value2 = analogRead(A1);
  float value3 = analogRead(A2);
  ubidots.add("Variable_Name_One", value1);  // Change for your variable name
  ubidots.add("Variable_Name_Two", value2);
  ubidots.add("Variable_Name_Three", value3);
  ubidots.setMethod(TYPE_TCP);  //Set to TCP the way to send data

  bool bufferSent = false;
  if(ubidots.isDirty()){  // There are stored values in buffer
    bufferSent = ubidots.sendAll();
  }

  if(bufferSent){
    // Do something if values were sent properly
    Serial.println("Values sent by the device");
  }

  delay(5000);
}
<commit_msg>Adding example for sending data using TCP<commit_after>// This example is to get the last value of variable from the Ubidots API

// This example is to save multiple variables to the Ubidots API with TCP method

/****************************************
 * Include Libraries
 ****************************************/

#include "Ubidots.h"

/****************************************
 * Define Constants
 ****************************************/

#ifndef TOKEN
#define TOKEN "Your_Token"  // Put here your Ubidots TOKEN
#endif

Ubidots ubidots(TOKEN);

/****************************************
 * Auxiliar Functions
 ****************************************/

//Put here your auxiliar functions

/****************************************
 * Main Functions
 ****************************************/

void setup() {
  Serial.begin(115200);
  //ubidots.setDebug(true);  // Uncomment this line for printing debug messages
}

void loop() {
  float value1 = analogRead(A0);
  float value2 = analogRead(A1);
  float value3 = analogRead(A2);
  ubidots.add("Variable_Name_One", value1);  // Change for your variable name
  ubidots.add("Variable_Name_Two", value2);
  ubidots.add("Variable_Name_Three", value3);

  bool bufferSent = false;
  bufferSent = ubidots.send();  // Will send data to a device label that matches the device Id

  if(bufferSent){
    // Do something if values were sent properly
    Serial.println("Values sent by the device");
  }

  delay(5000);
}
<|endoftext|>