<commit_before>#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <set>
#include <string>
#include <sstream>
#include <iterator>
#include <regex>
#include <chrono>

#include <unistd.h>
#include <sched.h>

#include "interference.h"
#include "interference_mpi.h"
#include "counter.hpp"
#include "perf.hpp"

#include "nlohmann/json.hpp"

using json = nlohmann::json;

std::string PREFIX;
std::string sched;
std::vector<int> affinity;
bool mvapich_hack = false;

/**
 * Parse integer value from an environment variable, which
 * environment variable ~reference~ references.
 * @param reference environment variable with environment variable name
 * @return value of the indirectly referenced variable
 */
static int get_indirect_param(const std::string &reference)
{
  int res = 0;
  auto ref_ptr = std::getenv(reference.c_str());
  if (ref_ptr) {
    auto param_ptr = std::getenv(ref_ptr);
    if (!param_ptr)
      throw std::runtime_error(reference +
                               " points to nonexistent variable");
    res = std::stol(param_ptr);
  }

  return res;
}

std::vector<int> parse_affinity(std::string cpu_string)
{
  std::vector<int> cpus;
  // static boost::regex r("(\\d+|\\d+-\\d+)?");
  std::regex r("^(\\d+-\\d+|\\d+)(,\\d+-\\d+|,\\d+)?(,\\d+-\\d+|,\\d+)*$");

  // Do regex match and convert the interesting part to
  // int.
  std::smatch what;
  if (!std::regex_match(cpu_string, what, r)) {
    throw std::runtime_error("Can't parse CPU string");
  }

  std::string::const_iterator start = cpu_string.begin();
  std::string::const_iterator end = cpu_string.end();

  while (std::regex_search(start, end, what, r)) {
    // what[1] single or a range of cpus
    if (!what[1].matched)
      throw std::runtime_error("Can't parse CPU string");

    std::string stest(what[1].first, what[1].second);
    auto minus = stest.find('-');
    if (minus == std::string::npos) {
      int value;
      try {
        value = std::stoi(stest);
      } catch (std::exception &e) {
        throw std::runtime_error("Can't parse CPU string");
      }
      cpus.push_back(value);
    } else {
      auto s = std::stoi(stest.substr(0, minus));
      auto e = std::stoi(stest.substr(minus+1));

      if (s > e)
        throw std::runtime_error("Can't parse CPU string");

      for (int cpu = s; cpu<=e; cpu++)
        cpus.push_back(cpu);
    }
    start = what[2].first;
    if (*start == ',')
      start++;
  }

  std::sort(cpus.begin(), cpus.end());
  cpus.erase(std::unique(cpus.begin(), cpus.end()), cpus.end());

  return cpus;
}

void parse_env()
{
  // Here we should set scheduler
  auto env = std::getenv("INTERFERENCE_PREFIX");
  if (!env)
    throw std::runtime_error("INTERFERENCE_PREFIX should be set");
  PREFIX = env;

  auto sched_ptr = std::getenv("INTERFERENCE_SCHED");
  if (!sched_ptr)
    throw std::runtime_error("INTERFERENCE_SCHED should be set");
  sched = std::string(sched_ptr);

  auto affinity_ptr = std::getenv("INTERFERENCE_AFFINITY");
  if (!affinity_ptr)
    throw std::runtime_error("INTERFERENCE_AFFINITY should be set");
  affinity = parse_affinity(affinity_ptr);

  if (std::getenv("INTERFERENCE_HACK"))
    mvapich_hack = true;
}

/**
 *  Set affinity to a particular cpu
 */
static void set_own_affinity(const cpu_set_t &cpu_set)
{
  int ret = sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
  if (ret)
    throw std::runtime_error("Failed to set affinity");
}

static void set_own_affinity(int cpu)
{
  cpu_set_t cpu_set;

  CPU_ZERO(&cpu_set);
  CPU_SET(cpu, &cpu_set);
  set_own_affinity(cpu_set);
}

static void set_own_affinity(const std::vector<int> &cpus)
{
  cpu_set_t cpu_set;

  CPU_ZERO(&cpu_set);
  for (auto c : cpus)
    CPU_SET(c, &cpu_set);
  set_own_affinity(cpu_set);
}

class WallClock : public IntervalCounter<wall_time_t> {
public:
  using IntervalCounter<wall_time_t>::IntervalCounter;

  void get_value(wall_time_t &val) {
    val = std::chrono::system_clock::now();
  }

  void exchange() {
    auto diff = end - start;
    long diff_long = std::chrono::duration_cast<std::chrono::milliseconds>(diff).count();

    _values.resize(_ranks);
    gather(&diff_long, sizeof(diff_long), _values.data());
  }
};

class ProcReader : public IntervalCounter<milli_time_t> {
  std::vector<std::string> get_stat_strings()
  {
    std::ifstream proc("/proc/self/stat");

    std::string line;
    std::getline(proc, line);
    std::istringstream iss(line);

    std::vector<std::string> tokens;
    std::copy(std::istream_iterator<std::string>(iss),
              std::istream_iterator<std::string>(),
              std::back_inserter(tokens));

    return tokens;
  }

  int _column;
public:
  using IntervalCounter<milli_time_t>::IntervalCounter;

  enum StatColumn
  {
    utime = 13,
    stime = 14,
  };

  ProcReader(StatColumn column, int ranks, const std::string &name) :
    IntervalCounter(ranks, name),
    _column(column)
  {}

  void get_value(milli_time_t &val) {
    std::vector<std::string> tokens = get_stat_strings();

    val = milli_time_t((std::stol(tokens[_column]) * 1000
                        / sysconf(_SC_CLK_TCK)));
  }

  void exchange() {
    auto diff = end - start;
    long diff_long = diff.count();
    _values.resize(_ranks);
    gather(&diff_long, sizeof(diff_long), _values.data());
  }
};

class CPUaccounter : public SingleCounter<long> {
  int localid;
  int block_size;
public:
  CPUaccounter(int ranks, const std::string &name)
    : SingleCounter(ranks, name),
      localid(get_indirect_param("INTERFERENCE_LOCALID")),
      block_size(get_indirect_param("INTERFERENCE_LOCAL_SIZE"))
  {
    if ((block_size == 0) && (sched == "pinned_blocked")) {
      throw std::runtime_error("Scheduler pinned_blocked requires variable"
                               " INTERFERENCE_LOCAL_SIZE to be set");
    }
  }

  void start_accounting() {
    if (sched == "pinned_blocked") {
      _value = affinity[localid * affinity.size() / block_size];
      std::cout << localid << " " << block_size << std::endl;
      set_own_affinity(_value);
    } else if (sched == "pinned_cyclic") {
      _value = affinity[localid % affinity.size()];
      set_own_affinity(_value);
    } else if (sched == "cfs") {
      _value = -1;
      set_own_affinity(affinity);
    } else {
      throw std::runtime_error("Unknown scheduler requested: " + sched);
    }
  }
};

class LocalId : public SingleCounter<long> {
  int localid;
public:

  LocalId(int ranks, const std::string &name) :
    SingleCounter(ranks, name),
    localid(get_indirect_param("INTERFERENCE_LOCALID"))
  {}

  void start_accounting() {
    _value = localid;
  }
};

class HostNameAccounter : public Counter {
protected:
  std::vector<char> _value;

  int _ranks;
  std::vector<char> _values;
  const unsigned name_len;
public:
  HostNameAccounter(int ranks, std::string name, unsigned name_len = 20) :
    Counter(name),
    _ranks(ranks),
    name_len(name_len)
  {
  }

  CounterMap emit() {
    CounterMap map;
    std::vector<std::string> str_values;

    for (int i = 0; i < _ranks; i ++) {
      auto name = std::string(_values.data() + i * name_len);
      str_values.push_back(name);
    }

    map[_name] = str_values;
    return map;
  }

  void end_accounting() {
    exchange();
  }

  void start_accounting() {
    // Assume no overflow happens
    _value.resize(name_len);
    gethostname(_value.data(), name_len);
    _value[name_len - 1] = '\0';
  }

private:
  void exchange() {
    _values.resize(name_len * _ranks);
    gather_names(_value.data(), _values.data(), name_len);
  }

};

class IterAccounter : public SingleCounter<long> {
public:
  using SingleCounter<long>::SingleCounter;

  void start_accounting() {
    _value = 1;
  }
};

class InterferenceAccounter : public Accounter {
  const std::string output_format;

private:
  typedef std::unique_ptr<Counter> counter_ptr;

  std::vector<std::string> parse_perf_counters(const std::string &str) {
    std::vector<std::string> result;
    std::stringstream ss(str);
    std::string token;

    while(std::getline(ss, token, ',')) {
      result.push_back(token);
    }

    return result;
  }

  void parse_and_add_perf_counters(const std::string &str) {
    std::vector<std::string> counter_list;
    counter_list = parse_perf_counters(str);

    if (counter_list.size() == 0)
      return;

    for (const auto &cnt : counter_list) {
      _counters.push_back(counter_ptr(new PerfCounter(_ranks, cnt)));
    }
  }

public:
  InterferenceAccounter(int ranks, const std::string &output_format) :
    Accounter(ranks), output_format(output_format)
  {
    _counters.push_back(counter_ptr(new IterAccounter(ranks, "ITER")));
    _counters.push_back(counter_ptr(new HostNameAccounter(ranks, "NODE")));
    _counters.push_back(counter_ptr(new LocalId(ranks, "LOCALID")));
    _counters.push_back(counter_ptr(new CPUaccounter(ranks, "CPU")));
    _counters.push_back(counter_ptr(new WallClock(ranks, "WTIME")));

    auto utime = ProcReader::StatColumn::utime;
    _counters.push_back(counter_ptr(new ProcReader(utime, ranks, "UTIME")));
    auto stime = ProcReader::StatColumn::stime;
    _counters.push_back(counter_ptr(new ProcReader(stime, ranks, "STIME")));

    if (output_format != "csv" && output_format != "json") {
      throw std::runtime_error("Unknown output format: " + output_format);
    }

    // Allow additional perf counters for json
    if (output_format == "json") {
      auto counters = std::getenv("INTERFERENCE_PERF");
      if (counters) {
        parse_and_add_perf_counters(counters);
      }
    }
  }

  void dump_csv(const CounterMap &map) {
    for (int i = 0; i < _ranks; i++) {
      std::cout << PREFIX
                << " ,RANK: " << i;
      for (const auto &cnt : map) {
        std::cout << " ," << cnt.first << ": "
                  << cnt.second[i];
      }
      std::cout << std::endl;
    }
  }

  void dump_json(const CounterMap &map) {
    json j;

    for (int i = 0; i < _ranks; i++) {
      json row;
      for (const auto &cnt : map) {
        row[cnt.first] = cnt.second[i];
      }
      j[PREFIX].push_back(row);
    }

    std::cout << j.dump() << std::endl;
  }

  void dump(const std::set<std::string> &filter = std::set<std::string>()) {
    int my_rank = get_my_rank();
    if (my_rank != 0)
      return;

    auto map = generate_map(filter);

    if (output_format == "csv") {
      dump_csv(map);
    } else if (output_format == "json") {
      dump_json(map);
    }
  }
};

std::unique_ptr<InterferenceAccounter> accounter;

void interference_start()
{
  parse_env();

  int ranks = get_ranks();

  accounter = std::unique_ptr<InterferenceAccounter>(
    new InterferenceAccounter(ranks, std::getenv("INTERFERENCE_OUTPUT")));
  accounter->start_accounting();
}

void interference_end()
{
  // Here we should read stat
  accounter->end_accounting();

  accounter->dump();

  if (mvapich_hack) {
    barrier();
    std::flush(std::cout);
    exit(0);
  }
}
<commit_msg>Remove global variable sched<commit_after>#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <set>
#include <string>
#include <sstream>
#include <iterator>
#include <regex>
#include <chrono>

#include <unistd.h>
#include <sched.h>

#include "interference.h"
#include "interference_mpi.h"
#include "counter.hpp"
#include "perf.hpp"

#include "nlohmann/json.hpp"

using json = nlohmann::json;

std::string PREFIX;
std::vector<int> affinity;
bool mvapich_hack = false;

/**
 * Parse integer value from an environment variable, which
 * environment variable ~reference~ references.
 * @param reference environment variable with environment variable name
 * @return value of the indirectly referenced variable
 */
static int get_indirect_param(const std::string &reference)
{
  int res = 0;
  auto ref_ptr = std::getenv(reference.c_str());
  if (ref_ptr) {
    auto param_ptr = std::getenv(ref_ptr);
    if (!param_ptr)
      throw std::runtime_error(reference +
                               " points to nonexistent variable");
    res = std::stol(param_ptr);
  }

  return res;
}

std::vector<int> parse_affinity(std::string cpu_string)
{
  std::vector<int> cpus;
  // static boost::regex r("(\\d+|\\d+-\\d+)?");
  std::regex r("^(\\d+-\\d+|\\d+)(,\\d+-\\d+|,\\d+)?(,\\d+-\\d+|,\\d+)*$");

  // Do regex match and convert the interesting part to
  // int.
  std::smatch what;
  if (!std::regex_match(cpu_string, what, r)) {
    throw std::runtime_error("Can't parse CPU string");
  }

  std::string::const_iterator start = cpu_string.begin();
  std::string::const_iterator end = cpu_string.end();

  while (std::regex_search(start, end, what, r)) {
    // what[1] single or a range of cpus
    if (!what[1].matched)
      throw std::runtime_error("Can't parse CPU string");

    std::string stest(what[1].first, what[1].second);
    auto minus = stest.find('-');
    if (minus == std::string::npos) {
      int value;
      try {
        value = std::stoi(stest);
      } catch (std::exception &e) {
        throw std::runtime_error("Can't parse CPU string");
      }
      cpus.push_back(value);
    } else {
      auto s = std::stoi(stest.substr(0, minus));
      auto e = std::stoi(stest.substr(minus+1));

      if (s > e)
        throw std::runtime_error("Can't parse CPU string");

      for (int cpu = s; cpu<=e; cpu++)
        cpus.push_back(cpu);
    }
    start = what[2].first;
    if (*start == ',')
      start++;
  }

  std::sort(cpus.begin(), cpus.end());
  cpus.erase(std::unique(cpus.begin(), cpus.end()), cpus.end());

  return cpus;
}

void parse_env()
{
  // Here we should set scheduler
  auto env = std::getenv("INTERFERENCE_PREFIX");
  if (!env)
    throw std::runtime_error("INTERFERENCE_PREFIX should be set");
  PREFIX = env;

  auto affinity_ptr = std::getenv("INTERFERENCE_AFFINITY");
  if (!affinity_ptr)
    throw std::runtime_error("INTERFERENCE_AFFINITY should be set");
  affinity = parse_affinity(affinity_ptr);

  if (std::getenv("INTERFERENCE_HACK"))
    mvapich_hack = true;
}

/**
 *  Set affinity to a particular cpu
 */
static void set_own_affinity(const cpu_set_t &cpu_set)
{
  int ret = sched_setaffinity(getpid(), sizeof(cpu_set), &cpu_set);
  if (ret)
    throw std::runtime_error("Failed to set affinity");
}

static void set_own_affinity(int cpu)
{
  cpu_set_t cpu_set;

  CPU_ZERO(&cpu_set);
  CPU_SET(cpu, &cpu_set);
  set_own_affinity(cpu_set);
}

static void set_own_affinity(const std::vector<int> &cpus)
{
  cpu_set_t cpu_set;

  CPU_ZERO(&cpu_set);
  for (auto c : cpus)
    CPU_SET(c, &cpu_set);
  set_own_affinity(cpu_set);
}

class WallClock : public IntervalCounter<wall_time_t> {
public:
  using IntervalCounter<wall_time_t>::IntervalCounter;

  void get_value(wall_time_t &val) {
    val = std::chrono::system_clock::now();
  }

  void exchange() {
    auto diff = end - start;
    long diff_long = std::chrono::duration_cast<std::chrono::milliseconds>(diff).count();

    _values.resize(_ranks);
    gather(&diff_long, sizeof(diff_long), _values.data());
  }
};

class ProcReader : public IntervalCounter<milli_time_t> {
  std::vector<std::string> get_stat_strings()
  {
    std::ifstream proc("/proc/self/stat");

    std::string line;
    std::getline(proc, line);
    std::istringstream iss(line);

    std::vector<std::string> tokens;
    std::copy(std::istream_iterator<std::string>(iss),
              std::istream_iterator<std::string>(),
              std::back_inserter(tokens));

    return tokens;
  }

  int _column;
public:
  using IntervalCounter<milli_time_t>::IntervalCounter;

  enum StatColumn
  {
    utime = 13,
    stime = 14,
  };

  ProcReader(StatColumn column, int ranks, const std::string &name) :
    IntervalCounter(ranks, name),
    _column(column)
  {}

  void get_value(milli_time_t &val) {
    std::vector<std::string> tokens = get_stat_strings();

    val = milli_time_t((std::stol(tokens[_column]) * 1000
                        / sysconf(_SC_CLK_TCK)));
  }

  void exchange() {
    auto diff = end - start;
    long diff_long = diff.count();
    _values.resize(_ranks);
    gather(&diff_long, sizeof(diff_long), _values.data());
  }
};

class CPUaccounter : public SingleCounter<long> {
  int _localid;
  int _block_size;
  std::string _sched;
public:
  CPUaccounter(int ranks, const std::string &name)
    : SingleCounter(ranks, name),
      _localid(get_indirect_param("INTERFERENCE_LOCALID")),
      _block_size(get_indirect_param("INTERFERENCE_LOCAL_SIZE"))
  {
    auto sched_ptr = std::getenv("INTERFERENCE_SCHED");
    if (!sched_ptr)
      throw std::runtime_error("INTERFERENCE_SCHED should be set");
    _sched = std::string(sched_ptr);

    if ((_block_size == 0) && (_sched == "pinned_blocked")) {
      throw std::runtime_error("Scheduler pinned_blocked requires variable"
                               " INTERFERENCE_LOCAL_SIZE to be set");
    }
  }

  void start_accounting() {
    if (_sched == "pinned_blocked") {
      _value = affinity[_localid * affinity.size() / _block_size];
      set_own_affinity(_value);
    } else if (_sched == "pinned_cyclic") {
      _value = affinity[_localid % affinity.size()];
      set_own_affinity(_value);
    } else if (_sched == "cfs") {
      _value = -1;
      set_own_affinity(affinity);
    } else {
      throw std::runtime_error("Unknown scheduler requested: " + _sched);
    }
  }
};

class LocalId : public SingleCounter<long> {
  int localid;
public:

  LocalId(int ranks, const std::string &name) :
    SingleCounter(ranks, name),
    localid(get_indirect_param("INTERFERENCE_LOCALID"))
  {}

  void start_accounting() {
    _value = localid;
  }
};

class HostNameAccounter : public Counter {
protected:
  std::vector<char> _value;

  int _ranks;
  std::vector<char> _values;
  const unsigned name_len;
public:
  HostNameAccounter(int ranks, std::string name, unsigned name_len = 20) :
    Counter(name),
    _ranks(ranks),
    name_len(name_len)
  {
  }

  CounterMap emit() {
    CounterMap map;
    std::vector<std::string> str_values;

    for (int i = 0; i < _ranks; i ++) {
      auto name = std::string(_values.data() + i * name_len);
      str_values.push_back(name);
    }

    map[_name] = str_values;
    return map;
  }

  void end_accounting() {
    exchange();
  }

  void start_accounting() {
    // Assume no overflow happens
    _value.resize(name_len);
    gethostname(_value.data(), name_len);
    _value[name_len - 1] = '\0';
  }

private:
  void exchange() {
    _values.resize(name_len * _ranks);
    gather_names(_value.data(), _values.data(), name_len);
  }

};

class IterAccounter : public SingleCounter<long> {
public:
  using SingleCounter<long>::SingleCounter;

  void start_accounting() {
    _value = 1;
  }
};

class InterferenceAccounter : public Accounter {
  const std::string output_format;

private:
  typedef std::unique_ptr<Counter> counter_ptr;

  std::vector<std::string> parse_perf_counters(const std::string &str) {
    std::vector<std::string> result;
    std::stringstream ss(str);
    std::string token;

    while(std::getline(ss, token, ',')) {
      result.push_back(token);
    }

    return result;
  }

  void parse_and_add_perf_counters(const std::string &str) {
    std::vector<std::string> counter_list;
    counter_list = parse_perf_counters(str);

    if (counter_list.size() == 0)
      return;

    for (const auto &cnt : counter_list) {
      _counters.push_back(counter_ptr(new PerfCounter(_ranks, cnt)));
    }
  }

public:
  InterferenceAccounter(int ranks, const std::string &output_format) :
    Accounter(ranks), output_format(output_format)
  {
    _counters.push_back(counter_ptr(new IterAccounter(ranks, "ITER")));
    _counters.push_back(counter_ptr(new HostNameAccounter(ranks, "NODE")));
    _counters.push_back(counter_ptr(new LocalId(ranks, "LOCALID")));
    _counters.push_back(counter_ptr(new CPUaccounter(ranks, "CPU")));
    _counters.push_back(counter_ptr(new WallClock(ranks, "WTIME")));

    auto utime = ProcReader::StatColumn::utime;
    _counters.push_back(counter_ptr(new ProcReader(utime, ranks, "UTIME")));
    auto stime = ProcReader::StatColumn::stime;
    _counters.push_back(counter_ptr(new ProcReader(stime, ranks, "STIME")));

    if (output_format != "csv" && output_format != "json") {
      throw std::runtime_error("Unknown output format: " + output_format);
    }

    // Allow additional perf counters for json
    if (output_format == "json") {
      auto counters = std::getenv("INTERFERENCE_PERF");
      if (counters) {
        parse_and_add_perf_counters(counters);
      }
    }
  }

  void dump_csv(const CounterMap &map) {
    for (int i = 0; i < _ranks; i++) {
      std::cout << PREFIX
                << " ,RANK: " << i;
      for (const auto &cnt : map) {
        std::cout << " ," << cnt.first << ": "
                  << cnt.second[i];
      }
      std::cout << std::endl;
    }
  }

  void dump_json(const CounterMap &map) {
    json j;

    for (int i = 0; i < _ranks; i++) {
      json row;
      for (const auto &cnt : map) {
        row[cnt.first] = cnt.second[i];
      }
      j[PREFIX].push_back(row);
    }

    std::cout << j.dump() << std::endl;
  }

  void dump(const std::set<std::string> &filter = std::set<std::string>()) {
    int my_rank = get_my_rank();
    if (my_rank != 0)
      return;

    auto map = generate_map(filter);

    if (output_format == "csv") {
      dump_csv(map);
    } else if (output_format == "json") {
      dump_json(map);
    }
  }
};

std::unique_ptr<InterferenceAccounter> accounter;

void interference_start()
{
  parse_env();

  int ranks = get_ranks();

  accounter = std::unique_ptr<InterferenceAccounter>(
    new InterferenceAccounter(ranks, std::getenv("INTERFERENCE_OUTPUT")));
  accounter->start_accounting();
}

void interference_end()
{
  // Here we should read stat
  accounter->end_accounting();

  accounter->dump();

  if (mvapich_hack) {
    barrier();
    std::flush(std::cout);
    exit(0);
  }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2008-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <iostream>

#include <libport/cassert>
#include <libport/containers.hh>
#include <libport/cstdio>
#include <libport/debug.hh>
#include <libport/escape.hh>
#include <libport/foreach.hh>
#include <libport/format.hh>
#include <libport/ip-semaphore.hh>
#include <libport/lockable.hh>
#include <libport/pthread.h>
#include <libport/windows.hh>
#include <libport/unistd.h>

#ifndef WIN32
# include <syslog.h>
#endif

#ifndef LIBPORT_DEBUG_DISABLE

GD_CATEGORY(libport::Debug);

namespace libport
{

  namespace debug
  {
    categories_type& get_categories()
    {
      static categories_type categories;
      return categories;
    }

    size_t&
    categories_largest()
    {
      static size_t res = 0;
      return res;
    }

    Symbol
    add_category(Symbol name)
    {
      get_categories()[name] = true;
      size_t size = name.name_get().size();
      if (categories_largest() < size)
        categories_largest() = size;
      return name;
    }

    int enable_category(Symbol name)
    {
      get_categories()[name] = true;
      return 42;
    }

    int disable_category(Symbol name)
    {
      get_categories()[name] = false;
      return 42;
    }

    bool test_category(Symbol name)
    {
      return get_categories()[name];
    }
  }

  Debug::Debug()
    : locations_(getenv("GD_LOC"))
    , timestamps_(getenv("GD_TIME"))
    , filter_(levels::log)
  {
    if (const char* lvl_c = getenv("GD_LEVEL"))
      filter(lvl_c);
  }

  Debug::~Debug()
  {}

  void
  Debug::filter(levels::Level lvl)
  {
    filter_ = lvl;
  }

  void
  Debug::filter(const std::string& lvl)
  {
    if (lvl == "NONE" || lvl == "0")
      filter(Debug::levels::none);
    else if (lvl == "LOG" || lvl == "1")
      filter(Debug::levels::log);
    else if (lvl == "TRACE" || lvl == "2")
      filter(Debug::levels::trace);
    else if (lvl == "DEBUG" || lvl == "3")
      filter(Debug::levels::debug);
    else if (lvl == "DUMP" || lvl == "4")
      filter(Debug::levels::dump);
    else
      // Don't use GD_ABORT here, we can be in the debugger constructor!
      pabort("invalid debug level (NONE, LOG, TRACE, DEBUG, DUMP or [0-4])");
  }

  Debug::levels::Level
  Debug::level() const
  {
    return filter_;
  }

# ifdef LIBPORT_HAVE_IP_SEMAPHORE
  static IPSemaphore& sem()
  {
    static IPSemaphore res(1);
    return res;
  }
# endif

  void
  Debug::debug(const std::string& msg,
               types::Type type,
               debug::category_type category,
               const std::string& fun,
               const std::string& file,
               unsigned line)
  {
# ifdef LIBPORT_HAVE_IP_SEMAPHORE
    static bool useLock = getenv("GD_USE_LOCK") || getenv("GD_PID");
    libport::Finally f;
    if (useLock)
    {
      --sem();
      f << boost::bind(&IPSemaphore::operator++, boost::ref(sem()));
    }
# endif
    message(category, msg, type, fun, file, line);
  }

  Debug*
  Debug::push(debug::category_type category,
              const std::string& msg,
              const std::string& fun,
              const std::string& file,
              unsigned line)
  {
    message_push(category, msg, fun, file, line);
    return this;
  }

  std::string
  Debug::category_format(debug::category_type cat) const
  {
    std::string res = cat;
    size_t size = res.size();
    size_t largest = debug::categories_largest();
    if (size < largest)
    {
      size_t diff = largest - size;
      res = std::string(diff / 2, ' ')
        + res
        + std::string(diff / 2 + diff % 2, ' ');
    }

    return res;
  }

  void Debug::abort()
  {
    libport::abort();
  }

  namespace opts
  {

    void cb_debug_fun(const std::string& lvl)
    {
      GD_DEBUGGER->filter(lvl);
    }

    OptionValued::callback_type cb_debug(&cb_debug_fun);

    OptionValue
    debug("set the debug level in NONE, LOG (default), TRACE, DEBUG, DUMP",
          "debug", 'd', "LEVEL", &cb_debug);

  }

  ConsoleDebug::ConsoleDebug()
    : indent_(0)
  {}

  namespace
  {
    inline
    std::string
    time()
    {
      time_t now = std::time(0);
      struct tm* ts = std::localtime(&now);
      char buf[80];
      strftime(buf, sizeof buf, "%a %Y-%m-%d %H:%M:%S %Z", ts);
      return buf;
    }

    inline
    std::string
    color(int color, bool bold = true)
    {
      static bool tty = isatty(STDERR_FILENO);
      static bool force = getenv("GD_COLOR");
      static bool force_disable = getenv("GD_NO_COLOR");
      return (((tty || force) && !force_disable)
              ? format("[33;0%s;%sm", bold ? 1 : 0, color)
              : "");
    }

    inline
    std::string
    reset()
    {
      return color(0);
    }
  }

  static Debug::colors::Color
  msg_color(Debug::types::Type type)
  {
    switch (type)
    {
      case Debug::types::info:
        return Debug::colors::white;
      case Debug::types::warn:
        return Debug::colors::yellow;
      case Debug::types::error:
        return Debug::colors::red;
    };
    GD_UNREACHABLE();
  }

  void
  ConsoleDebug::message(debug::category_type category,
                        const std::string& msg,
                        types::Type type,
                        const std::string& fun,
                        const std::string& file,
                        unsigned line)
  {
    std::ostringstream ostr;
    Debug::colors::Color c = msg_color(type);
    if (timestamps())
      ostr << color(c) << time() << "    ";
    ostr << color(colors::purple)
         << "[" << category_format(category) << "] ";
    {
      static bool pid = getenv("GD_PID");
      if (pid)
        ostr << "[" << getpid() << "] ";
    }
#ifndef WIN32
    {
      static bool thread = getenv("GD_THREAD");
      if (thread)
        ostr << "[" << pthread_self() << "] ";
    }
#endif
    ostr << color(c);
    for (unsigned i = 0; i < indent_; ++i)
      ostr << " ";
    // As syslog would do, don't issue the users' \n.
    if (!msg.empty() && msg[msg.size() - 1] == '\n')
      ostr.write(msg.c_str(), msg.size() - 1);
    else
      ostr << msg;
    if (locations())
      ostr << color(colors::blue)
           << "    (" << fun << ", " << file << ":" << line << ")";
    ostr << color(colors::white);
    std::cerr << ostr.str() << std::endl;
  }

  void
  ConsoleDebug::message_push(debug::category_type category,
                             const std::string& msg,
                             const std::string& fun,
                             const std::string& file,
                             unsigned line)
  {
    debug(msg, types::info, category, fun, file, line);
    indent_ += 2;
  }

  void
  ConsoleDebug::pop()
  {
    assert_gt(indent_, 0u);
    indent_ -= 2;
  }

  std::string gd_ihexdump(const unsigned char* data, unsigned size)
  {
    std::string res =
      format("\"%s\"",
             libport::escape(std::string((const char*)data, (size_t)(size))));

    bool first = true;
    for (unsigned i = 0; i < size; ++i)
    {
      if (first)
        first = false;
      else
        res += " ";
      // Cast to int, or boost::format will print the character.
      res += format("0x%x", static_cast<unsigned int>(data[i]));
    }
    return res;
  }

#ifndef WIN32
  /*-------------.
  | Syslog debug |
  `-------------*/

  SyslogDebug::SyslogDebug(const std::string& program)
  {
    openlog(strdup(program.c_str()), LOG_PID, LOG_DAEMON);
    syslog(LOG_INFO | LOG_DAEMON, "%s",
           format("Opening syslog session for '%s'", program).c_str());
  }

  SyslogDebug::~SyslogDebug()
  {
    syslog(LOG_INFO | LOG_DAEMON, "Closing syslog session.");
    closelog();
  }

  static
  int type_to_prio(Debug::types::Type t)
  {
    switch (t)
    {
#define CASE(In, Out)                           \
      case Debug::types::In: return Out; break
      CASE(info,  LOG_INFO);
      CASE(warn,  LOG_WARNING);
      CASE(error, LOG_ERR);
      // Pacify Gcc.
    }
    libport::abort();
#undef CASE
  }

  void
  SyslogDebug::message(debug::category_type category,
                       const std::string& msg,
                       types::Type type,
                       const std::string& fun,
                       const std::string& file,
                       unsigned line)
  {
    std::stringstream s;
    s << "[" << category_format(category) << "] ";
    for (unsigned i = 0; i < indent_; ++i)
      s << " ";
    // As syslog would do, don't issue the users' \n.
    if (!msg.empty() && msg[msg.size() - 1] == '\n')
      s.write(msg.c_str(), msg.size() - 1);
    else
      s << msg;
    if (locations())
      s << "    (" << fun << ", " << file << ":" << line << ")";
    int prio = type_to_prio(type) | LOG_DAEMON;
    syslog(prio, "%s", s.str().c_str());
  }

  void
  SyslogDebug::message_push(debug::category_type category,
                            const std::string& msg,
                            const std::string& fun,
                            const std::string& file,
                            unsigned line)
  {
    debug(msg, types::info, category, fun, file, line);
    indent_ += 2;
  }

  void
  SyslogDebug::pop()
  {
    assert_gt(indent_, 0u);
    indent_ -= 2;
  }
#endif

  boost::function0<Debug*> make_debugger;
  AbstractLocalData<Debug>* debugger_data;

  typedef std::map<pthread_t, Debug*> map_type;
  // Do not make it an actual object, as it is sometimes used on
  // dtors, and the order to destruction is not specified.  Using a
  // dynamically allocated object protects us from this.
  static map_type* pdebuggers = new map_type;
  libport::Lockable debugger_mutex_;

  namespace debug
  {
    void clear()
    {
#if FIXME
      typedef std::pair<pthread_t, Debug*> entry;
      foreach (entry p, *pdebuggers)
      {
        delete p.second;
        p.second = 0;
      }
#endif
      delete pdebuggers;
      pdebuggers = 0;
    }
  }

  Debug* debugger()
  {
    libport::BlockLock lock(debugger_mutex_);
    bool no_gd_init = false;

    if (!debugger_data)
    {
      debugger_data =
        new LocalData<Debug, ::libport::localdata::Thread>;
      no_gd_init = true;
    }

    Debug *d = debugger_data->get();
    if (!d)
    {
      if (make_debugger.empty())
      {
        d = new ConsoleDebug;
        no_gd_init = true;
      }
      else
        d = make_debugger();
      debugger_data->set(d);
    }

    if (no_gd_init)
    {
# define _GD_WARN(Message)                                              \
      d->debug(Message, ::libport::Debug::types::warn,                  \
               GD_CATEGORY_GET(), GD_FUNCTION, __FILE__, __LINE__)      \

      _GD_WARN("GD_INIT was not invoked, defaulting to console logs");
# undef _GD_WARN
    }

    return d;
  }

}

#endif
<commit_msg>debug: Support for displaying time as a microsecond timestamp.<commit_after>/*
 * Copyright (C) 2008-2010, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#include <iostream>

#include <libport/cassert>
#include <libport/containers.hh>
#include <libport/cstdio>
#include <libport/debug.hh>
#include <libport/escape.hh>
#include <libport/foreach.hh>
#include <libport/format.hh>
#include <libport/ip-semaphore.hh>
#include <libport/lockable.hh>
#include <libport/pthread.h>
#include <libport/tokenizer.hh>
#include <libport/windows.hh>
#include <libport/unistd.h>
#include <libport/utime.hh>

#ifndef WIN32
# include <syslog.h>
#endif

#ifndef LIBPORT_DEBUG_DISABLE

GD_CATEGORY(libport::Debug);

namespace libport
{

  namespace debug
  {
    categories_type& get_categories()
    {
      static categories_type categories;
      return categories;
    }

    size_t&
    categories_largest()
    {
      static size_t res = 0;
      return res;
    }

    Symbol
    add_category(Symbol name)
    {
      get_categories()[name] = true;
      size_t size = name.name_get().size();
      if (categories_largest() < size)
        categories_largest() = size;
      return name;
    }

    int enable_category(Symbol name)
    {
      get_categories()[name] = true;
      return 42;
    }

    int disable_category(Symbol name)
    {
      get_categories()[name] = false;
      return 42;
    }

    bool test_category(Symbol name)
    {
      return get_categories()[name];
    }
  }

  Debug::Debug()
    : locations_(getenv("GD_LOC"))
    , timestamps_(getenv("GD_TIME"))
    , filter_(levels::log)
  {
    if (const char* lvl_c = getenv("GD_LEVEL"))
      filter(lvl_c);
  }

  Debug::~Debug()
  {}

  void
  Debug::filter(levels::Level lvl)
  {
    filter_ = lvl;
  }

  void
  Debug::filter(const std::string& lvl)
  {
    if (lvl == "NONE" || lvl == "0")
      filter(Debug::levels::none);
    else if (lvl == "LOG" || lvl == "1")
      filter(Debug::levels::log);
    else if (lvl == "TRACE" || lvl == "2")
      filter(Debug::levels::trace);
    else if (lvl == "DEBUG" || lvl == "3")
      filter(Debug::levels::debug);
    else if (lvl == "DUMP" || lvl == "4")
      filter(Debug::levels::dump);
    else
      // Don't use GD_ABORT here, we can be in the debugger constructor!
      pabort("invalid debug level (NONE, LOG, TRACE, DEBUG, DUMP or [0-4])");
  }

  Debug::levels::Level
  Debug::level() const
  {
    return filter_;
  }

# ifdef LIBPORT_HAVE_IP_SEMAPHORE
  static IPSemaphore& sem()
  {
    static IPSemaphore res(1);
    return res;
  }
# endif

  void
  Debug::debug(const std::string& msg,
               types::Type type,
               debug::category_type category,
               const std::string& fun,
               const std::string& file,
               unsigned line)
  {
# ifdef LIBPORT_HAVE_IP_SEMAPHORE
    static bool useLock = getenv("GD_USE_LOCK") || getenv("GD_PID");
    libport::Finally f;
    if (useLock)
    {
      --sem();
      f << boost::bind(&IPSemaphore::operator++, boost::ref(sem()));
    }
# endif
    message(category, msg, type, fun, file, line);
  }

  Debug*
  Debug::push(debug::category_type category,
              const std::string& msg,
              const std::string& fun,
              const std::string& file,
              unsigned line)
  {
    message_push(category, msg, fun, file, line);
    return this;
  }

  std::string
  Debug::category_format(debug::category_type cat) const
  {
    std::string res = cat;
    size_t size = res.size();
    size_t largest = debug::categories_largest();
    if (size < largest)
    {
      size_t diff = largest - size;
      res = std::string(diff / 2, ' ')
        + res
        + std::string(diff / 2 + diff % 2, ' ');
    }

    return res;
  }

  void Debug::abort()
  {
    libport::abort();
  }

  namespace opts
  {

    void cb_debug_fun(const std::string& lvl)
    {
      GD_DEBUGGER->filter(lvl);
    }

    OptionValued::callback_type cb_debug(&cb_debug_fun);

    OptionValue
    debug("set the debug level in NONE, LOG (default), TRACE, DEBUG, DUMP",
          "debug", 'd', "LEVEL", &cb_debug);

  }

  ConsoleDebug::ConsoleDebug()
    : indent_(0)
  {}

  namespace
  {
    inline
    std::string
    time()
    {
      static bool us = getenv("GD_TIMESTAMP_US");
      if (us)
        return string_cast(utime());
      time_t now = std::time(0);
      struct tm* ts = std::localtime(&now);
      char buf[80];
      strftime(buf, sizeof buf, "%a %Y-%m-%d %H:%M:%S %Z", ts);
      return buf;
    }

    inline
    std::string
    color(int color, bool bold = true)
    {
      static bool tty = isatty(STDERR_FILENO);
      static bool force = getenv("GD_COLOR");
      static bool force_disable = getenv("GD_NO_COLOR");
      return (((tty || force) && !force_disable)
              ? format("[33;0%s;%sm", bold ? 1 : 0, color)
              : "");
    }

    inline
    std::string
    reset()
    {
      return color(0);
    }
  }

  static Debug::colors::Color
  msg_color(Debug::types::Type type)
  {
    switch (type)
    {
      case Debug::types::info:
        return Debug::colors::white;
      case Debug::types::warn:
        return Debug::colors::yellow;
      case Debug::types::error:
        return Debug::colors::red;
    };
    GD_UNREACHABLE();
  }

  void
  ConsoleDebug::message(debug::category_type category,
                        const std::string& msg,
                        types::Type type,
                        const std::string& fun,
                        const std::string& file,
                        unsigned line)
  {
    std::ostringstream ostr;
    Debug::colors::Color c = msg_color(type);
    if (timestamps())
      ostr << color(c) << time() << "    ";
    ostr << color(colors::purple)
         << "[" << category_format(category) << "] ";
    {
      static bool pid = getenv("GD_PID");
      if (pid)
        ostr << "[" << getpid() << "] ";
    }
#ifndef WIN32
    {
      static bool thread = getenv("GD_THREAD");
      if (thread)
        ostr << "[" << pthread_self() << "] ";
    }
#endif
    ostr << color(c);
    for (unsigned i = 0; i < indent_; ++i)
      ostr << " ";
    // As syslog would do, don't issue the users' \n.
    if (!msg.empty() && msg[msg.size() - 1] == '\n')
      ostr.write(msg.c_str(), msg.size() - 1);
    else
      ostr << msg;
    if (locations())
      ostr << color(colors::blue)
           << "    (" << fun << ", " << file << ":" << line << ")";
    ostr << color(colors::white);
    std::cerr << ostr.str() << std::endl;
  }

  void
  ConsoleDebug::message_push(debug::category_type category,
                             const std::string& msg,
                             const std::string& fun,
                             const std::string& file,
                             unsigned line)
  {
    debug(msg, types::info, category, fun, file, line);
    indent_ += 2;
  }

  void
  ConsoleDebug::pop()
  {
    assert_gt(indent_, 0u);
    indent_ -= 2;
  }

  std::string gd_ihexdump(const unsigned char* data, unsigned size)
  {
    std::string res =
      format("\"%s\"",
             libport::escape(std::string((const char*)data, (size_t)(size))));

    bool first = true;
    for (unsigned i = 0; i < size; ++i)
    {
      if (first)
        first = false;
      else
        res += " ";
      // Cast to int, or boost::format will print the character.
      res += format("0x%x", static_cast<unsigned int>(data[i]));
    }
    return res;
  }

#ifndef WIN32
  /*-------------.
  | Syslog debug |
  `-------------*/

  SyslogDebug::SyslogDebug(const std::string& program)
  {
    openlog(strdup(program.c_str()), LOG_PID, LOG_DAEMON);
    syslog(LOG_INFO | LOG_DAEMON, "%s",
           format("Opening syslog session for '%s'", program).c_str());
  }

  SyslogDebug::~SyslogDebug()
  {
    syslog(LOG_INFO | LOG_DAEMON, "Closing syslog session.");
    closelog();
  }

  static
  int type_to_prio(Debug::types::Type t)
  {
    switch (t)
    {
#define CASE(In, Out)                           \
      case Debug::types::In: return Out; break
      CASE(info,  LOG_INFO);
      CASE(warn,  LOG_WARNING);
      CASE(error, LOG_ERR);
      // Pacify Gcc.
    }
    libport::abort();
#undef CASE
  }

  void
  SyslogDebug::message(debug::category_type category,
                       const std::string& msg,
                       types::Type type,
                       const std::string& fun,
                       const std::string& file,
                       unsigned line)
  {
    std::stringstream s;
    s << "[" << category_format(category) << "] ";
    for (unsigned i = 0; i < indent_; ++i)
      s << " ";
    // As syslog would do, don't issue the users' \n.
    if (!msg.empty() && msg[msg.size() - 1] == '\n')
      s.write(msg.c_str(), msg.size() - 1);
    else
      s << msg;
    if (locations())
      s << "    (" << fun << ", " << file << ":" << line << ")";
    int prio = type_to_prio(type) | LOG_DAEMON;
    syslog(prio, "%s", s.str().c_str());
  }

  void
  SyslogDebug::message_push(debug::category_type category,
                            const std::string& msg,
                            const std::string& fun,
                            const std::string& file,
                            unsigned line)
  {
    debug(msg, types::info, category, fun, file, line);
    indent_ += 2;
  }

  void
  SyslogDebug::pop()
  {
    assert_gt(indent_, 0u);
    indent_ -= 2;
  }
#endif

  boost::function0<Debug*> make_debugger;
  AbstractLocalData<Debug>* debugger_data;

  typedef std::map<pthread_t, Debug*> map_type;
  // Do not make it an actual object, as it is sometimes used on
  // dtors, and the order to destruction is not specified.  Using a
  // dynamically allocated object protects us from this.
  static map_type* pdebuggers = new map_type;
  libport::Lockable debugger_mutex_;

  namespace debug
  {
    void clear()
    {
#if FIXME
      typedef std::pair<pthread_t, Debug*> entry;
      foreach (entry p, *pdebuggers)
      {
        delete p.second;
        p.second = 0;
      }
#endif
      delete pdebuggers;
      pdebuggers = 0;
    }
  }

  Debug* debugger()
  {
    libport::BlockLock lock(debugger_mutex_);
    bool no_gd_init = false;

    if (!debugger_data)
    {
      debugger_data =
        new LocalData<Debug, ::libport::localdata::Thread>;
      no_gd_init = true;
    }

    Debug *d = debugger_data->get();
    if (!d)
    {
      if (make_debugger.empty())
      {
        d = new ConsoleDebug;
        no_gd_init = true;
      }
      else
        d = make_debugger();
      debugger_data->set(d);
    }

    if (no_gd_init)
    {
# define _GD_WARN(Message)                                              \
      d->debug(Message, ::libport::Debug::types::warn,                  \
               GD_CATEGORY_GET(), GD_FUNCTION, __FILE__, __LINE__)      \

      _GD_WARN("GD_INIT was not invoked, defaulting to console logs");
# undef _GD_WARN
    }

    return d;
  }

}

#endif
<|endoftext|>


<commit_before>#include "Memory.h"

#include <vector>
#include <iostream>
#include <iomanip>
#include <cstdint>
#include <cassert>

#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Function.h>

#include <libdevcore/Common.h>

#include "Type.h"
#include "Runtime.h"
#include "GasMeter.h"
#include "Endianness.h"
#include "Runtime.h"

namespace dev
{
namespace eth
{
namespace jit
{

Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter):
	RuntimeHelper(_runtimeManager)
{
	auto module = getModule();
	llvm::Type* argTypes[] = {Type::i256, Type::i256};
	auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef<llvm::Type*>(argTypes), false);
	m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
									   "evmccrt_memory_dump", module);

	m_data = new llvm::GlobalVariable(*module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data");
	m_data->setUnnamedAddr(true); // Address is not important

	m_size = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size");
	m_size->setUnnamedAddr(true); // Address is not important

	llvm::Type* resizeArgs[] = {Type::RuntimePtr, Type::WordPtr};
	m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, resizeArgs, false), llvm::Function::ExternalLinkage, "mem_resize", module);
	llvm::AttrBuilder attrBuilder;
	attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly);
	m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder));

	m_require = createRequireFunc(_gasMeter, _runtimeManager);
	m_loadWord = createFunc(false, Type::i256, _gasMeter);
	m_storeWord = createFunc(true, Type::i256, _gasMeter);
	m_storeByte = createFunc(true, Type::Byte,  _gasMeter);
}

llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager)
{
	llvm::Type* argTypes[] = {Type::i256, Type::i256};
	auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "mem.require", getModule());
	auto offset = func->arg_begin();
	offset->setName("offset");
	auto size = offset->getNextNode();
	size->setName("size");

	auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func);
	auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "Resize", func);
	auto returnBB = llvm::BasicBlock::Create(func->getContext(), "Return", func);

	InsertPointGuard guard(m_builder); // Restores insert point at function exit

	// BB "check"
	m_builder.SetInsertPoint(checkBB);
	auto sizeRequired = m_builder.CreateNUWAdd(offset, size, "sizeRequired");
	auto currSize = m_builder.CreateLoad(m_size, "currSize");
	auto resizeNeeded = m_builder.CreateICmpULE(size, sizeRequired, "resizeNeeded");
	m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights?

	// BB "resize"
	m_builder.SetInsertPoint(resizeBB);
	// Check gas first
	auto wordsRequired = m_builder.CreateUDiv(m_builder.CreateAdd(sizeRequired, Constant::get(31)), Constant::get(32), "wordsRequired");
	sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeRequired");
	auto words = m_builder.CreateUDiv(size, Constant::get(32), "words");	// size is always 32*k
	auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords");
	_gasMeter.checkMemory(newWords, m_builder);
	// Resize
	m_builder.CreateStore(sizeRequired, m_size);
	auto newData = m_builder.CreateCall2(m_resize, _runtimeManager.getRuntimePtr(), m_size, "newData");
	m_builder.CreateStore(newData, m_data);
	m_builder.CreateBr(returnBB);

	// BB "return"
	m_builder.SetInsertPoint(returnBB);
	m_builder.CreateRetVoid();
	return func;
}

llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMeter&)
{
	auto isWord = _valueType == Type::i256;

	llvm::Type* storeArgs[] = {Type::i256, _valueType};
	auto name = _isStore ? isWord ? "mstore" : "mstore8" : "mload";
	auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::i256, Type::i256, false);
	auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, getModule());

	InsertPointGuard guard(m_builder); // Restores insert point at function exit

	m_builder.SetInsertPoint(llvm::BasicBlock::Create(func->getContext(), {}, func));
	llvm::Value* index = func->arg_begin();
	index->setName("index");

	auto valueSize = _valueType->getPrimitiveSizeInBits() / 8;
	this->require(index, Constant::get(valueSize));
	auto data = m_builder.CreateLoad(m_data, "data");
	auto ptr = m_builder.CreateGEP(data, index, "ptr");
	if (isWord)
		ptr = m_builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr");
	if (_isStore)
	{
		llvm::Value* value = ++func->arg_begin();
		value->setName("value");
		if (isWord)
			value = Endianness::toBE(m_builder, value);
		m_builder.CreateStore(value, ptr);
		m_builder.CreateRetVoid();
	}
	else
	{
		llvm::Value* ret = m_builder.CreateLoad(ptr);
		ret = Endianness::toNative(m_builder, ret);
		m_builder.CreateRet(ret);
	}

	return func;
}

llvm::Value* Memory::loadWord(llvm::Value* _addr)
{
	auto value = m_builder.CreateCall(m_loadWord, _addr);

	dump(0);
	return value;
}

void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word)
{
	m_builder.CreateCall2(m_storeWord, _addr, _word);

	dump(0);
}

void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word)
{
	auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte");
	m_builder.CreateCall2(m_storeByte, _addr, byte);

	dump(0);
}

llvm::Value* Memory::getData()
{
	return m_builder.CreateLoad(m_data);
}

llvm::Value* Memory::getSize()
{
	return m_builder.CreateLoad(m_size);
}

void Memory::require(llvm::Value* _offset, llvm::Value* _size)
{
	m_builder.CreateCall2(m_require, _offset, _size);
}

void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx,
					   llvm::Value* _destMemIdx, llvm::Value* _reqBytes)
{
	auto zero256 = llvm::ConstantInt::get(Type::i256, 0);

	require(_destMemIdx, _reqBytes);

	auto srcPtr = m_builder.CreateGEP(_srcPtr, _srcIdx, "src_idx");

	auto memPtr = getData();
	auto destPtr = m_builder.CreateGEP(memPtr, _destMemIdx, "dest_mem_ptr");

	// remaining source bytes:
	auto remSrcSize = m_builder.CreateSub(_srcSize, _srcIdx);
	auto remSizeNegative = m_builder.CreateICmpSLT(remSrcSize, zero256);
	auto remSrcBytes = m_builder.CreateSelect(remSizeNegative, zero256, remSrcSize, "rem_src_bytes");

	auto tooFewSrcBytes = m_builder.CreateICmpULT(remSrcBytes, _reqBytes);
	auto bytesToCopy = m_builder.CreateSelect(tooFewSrcBytes, remSrcBytes, _reqBytes, "bytes_to_copy");

	m_builder.CreateMemCpy(destPtr, srcPtr, bytesToCopy, 0);
}

void Memory::dump(uint64_t _begin, uint64_t _end)
{
	if (getenv("EVMCC_DEBUG_MEMORY") == nullptr)
		return;

	auto beginVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _begin);
	auto endVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _end);

	std::vector<llvm::Value*> args = {beginVal, endVal};
	m_builder.CreateCall(m_memDump, llvm::ArrayRef<llvm::Value*>(args));
}

}
}
}

extern "C"
{

	using namespace dev::eth::jit;

	EXPORT uint8_t* mem_resize(Runtime* _rt, i256* _size)
	{
		auto size = _size->a; // Trunc to 64-bit
		auto& memory = _rt->getMemory();
		memory.resize(size);
		return memory.data();
	}

}   // extern "C"
<commit_msg>Handle unsigned integer overflow in Memory::require() [Delivers #81773288]<commit_after>#include "Memory.h"

#include <vector>
#include <iostream>
#include <iomanip>
#include <cstdint>
#include <cassert>

#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/IntrinsicInst.h>

#include <libdevcore/Common.h>

#include "Type.h"
#include "Runtime.h"
#include "GasMeter.h"
#include "Endianness.h"
#include "Runtime.h"

namespace dev
{
namespace eth
{
namespace jit
{

Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter):
	RuntimeHelper(_runtimeManager)
{
	auto module = getModule();
	llvm::Type* argTypes[] = {Type::i256, Type::i256};
	auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef<llvm::Type*>(argTypes), false);
	m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
									   "evmccrt_memory_dump", module);

	m_data = new llvm::GlobalVariable(*module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data");
	m_data->setUnnamedAddr(true); // Address is not important

	m_size = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size");
	m_size->setUnnamedAddr(true); // Address is not important

	llvm::Type* resizeArgs[] = {Type::RuntimePtr, Type::WordPtr};
	m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, resizeArgs, false), llvm::Function::ExternalLinkage, "mem_resize", module);
	llvm::AttrBuilder attrBuilder;
	attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly);
	m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder));

	m_require = createRequireFunc(_gasMeter, _runtimeManager);
	m_loadWord = createFunc(false, Type::i256, _gasMeter);
	m_storeWord = createFunc(true, Type::i256, _gasMeter);
	m_storeByte = createFunc(true, Type::Byte,  _gasMeter);
}

llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager)
{
	llvm::Type* argTypes[] = {Type::i256, Type::i256};
	auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "mem.require", getModule());
	auto offset = func->arg_begin();
	offset->setName("offset");
	auto size = offset->getNextNode();
	size->setName("size");

	auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func);
	auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "Resize", func);
	auto returnBB = llvm::BasicBlock::Create(func->getContext(), "Return", func);

	InsertPointGuard guard(m_builder); // Restores insert point at function exit

	// BB "check"
	m_builder.SetInsertPoint(checkBB);
	auto uaddWO = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::uadd_with_overflow, Type::i256);
	auto uaddRes = m_builder.CreateCall2(uaddWO, offset, size, "res");
	auto sizeRequired = m_builder.CreateExtractValue(uaddRes, 0, "sizeReq");
	auto overflow1 = m_builder.CreateExtractValue(uaddRes, 1, "overflow1");
	auto currSize = m_builder.CreateLoad(m_size, "currSize");
	auto tooSmall = m_builder.CreateICmpULE(size, sizeRequired, "tooSmall");
	auto resizeNeeded = m_builder.CreateOr(tooSmall, overflow1, "resizeNeeded");
	m_builder.CreateCondBr(resizeNeeded, resizeBB, returnBB); // OPT branch weights?

	// BB "resize"
	m_builder.SetInsertPoint(resizeBB);
	// Check gas first
	uaddRes = m_builder.CreateCall2(uaddWO, sizeRequired, Constant::get(31), "res");
	auto wordsRequired = m_builder.CreateExtractValue(uaddRes, 0);
	auto overflow2 = m_builder.CreateExtractValue(uaddRes, 1, "overflow2");
	auto overflow = m_builder.CreateOr(overflow1, overflow2, "overflow");
	wordsRequired = m_builder.CreateSelect(overflow, Constant::get(-1), wordsRequired);
	wordsRequired = m_builder.CreateUDiv(wordsRequired, Constant::get(32), "wordsReq");
	sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeReq");
	auto words = m_builder.CreateUDiv(currSize, Constant::get(32), "words");	// size is always 32*k
	auto newWords = m_builder.CreateSub(wordsRequired, words, "addtionalWords");
	_gasMeter.checkMemory(newWords, m_builder);
	// Resize
	m_builder.CreateStore(sizeRequired, m_size);
	auto newData = m_builder.CreateCall2(m_resize, _runtimeManager.getRuntimePtr(), m_size, "newData");
	m_builder.CreateStore(newData, m_data);
	m_builder.CreateBr(returnBB);

	// BB "return"
	m_builder.SetInsertPoint(returnBB);
	m_builder.CreateRetVoid();
	return func;
}

llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMeter&)
{
	auto isWord = _valueType == Type::i256;

	llvm::Type* storeArgs[] = {Type::i256, _valueType};
	auto name = _isStore ? isWord ? "mstore" : "mstore8" : "mload";
	auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::i256, Type::i256, false);
	auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, getModule());

	InsertPointGuard guard(m_builder); // Restores insert point at function exit

	m_builder.SetInsertPoint(llvm::BasicBlock::Create(func->getContext(), {}, func));
	llvm::Value* index = func->arg_begin();
	index->setName("index");

	auto valueSize = _valueType->getPrimitiveSizeInBits() / 8;
	this->require(index, Constant::get(valueSize));
	auto data = m_builder.CreateLoad(m_data, "data");
	auto ptr = m_builder.CreateGEP(data, index, "ptr");
	if (isWord)
		ptr = m_builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr");
	if (_isStore)
	{
		llvm::Value* value = ++func->arg_begin();
		value->setName("value");
		if (isWord)
			value = Endianness::toBE(m_builder, value);
		m_builder.CreateStore(value, ptr);
		m_builder.CreateRetVoid();
	}
	else
	{
		llvm::Value* ret = m_builder.CreateLoad(ptr);
		ret = Endianness::toNative(m_builder, ret);
		m_builder.CreateRet(ret);
	}

	return func;
}

llvm::Value* Memory::loadWord(llvm::Value* _addr)
{
	auto value = m_builder.CreateCall(m_loadWord, _addr);

	dump(0);
	return value;
}

void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word)
{
	m_builder.CreateCall2(m_storeWord, _addr, _word);

	dump(0);
}

void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word)
{
	auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte");
	m_builder.CreateCall2(m_storeByte, _addr, byte);

	dump(0);
}

llvm::Value* Memory::getData()
{
	return m_builder.CreateLoad(m_data);
}

llvm::Value* Memory::getSize()
{
	return m_builder.CreateLoad(m_size);
}

void Memory::require(llvm::Value* _offset, llvm::Value* _size)
{
	m_builder.CreateCall2(m_require, _offset, _size);
}

void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx,
					   llvm::Value* _destMemIdx, llvm::Value* _reqBytes)
{
	auto zero256 = llvm::ConstantInt::get(Type::i256, 0);

	require(_destMemIdx, _reqBytes);

	auto srcPtr = m_builder.CreateGEP(_srcPtr, _srcIdx, "src_idx");

	auto memPtr = getData();
	auto destPtr = m_builder.CreateGEP(memPtr, _destMemIdx, "dest_mem_ptr");

	// remaining source bytes:
	auto remSrcSize = m_builder.CreateSub(_srcSize, _srcIdx);
	auto remSizeNegative = m_builder.CreateICmpSLT(remSrcSize, zero256);
	auto remSrcBytes = m_builder.CreateSelect(remSizeNegative, zero256, remSrcSize, "rem_src_bytes");

	auto tooFewSrcBytes = m_builder.CreateICmpULT(remSrcBytes, _reqBytes);
	auto bytesToCopy = m_builder.CreateSelect(tooFewSrcBytes, remSrcBytes, _reqBytes, "bytes_to_copy");

	m_builder.CreateMemCpy(destPtr, srcPtr, bytesToCopy, 0);
}

void Memory::dump(uint64_t _begin, uint64_t _end)
{
	if (getenv("EVMCC_DEBUG_MEMORY") == nullptr)
		return;

	auto beginVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _begin);
	auto endVal = llvm::ConstantInt::get(m_builder.getInt64Ty(), _end);

	std::vector<llvm::Value*> args = {beginVal, endVal};
	m_builder.CreateCall(m_memDump, llvm::ArrayRef<llvm::Value*>(args));
}

}
}
}

extern "C"
{

	using namespace dev::eth::jit;

	EXPORT uint8_t* mem_resize(Runtime* _rt, i256* _size)
	{
		auto size = _size->a; // Trunc to 64-bit
		auto& memory = _rt->getMemory();
		memory.resize(size);
		return memory.data();
	}

}   // extern "C"
<|endoftext|>


<commit_before>// Significant changes to C++14

#if !defined(__cpp_binary_literals)
// Binary Literals in the C++ Core Language
// \see N3472 section 2.14 Header predefined
#define __cpp_binary_literals 201304
#endif

#if !defined(none)
// A Proposal to Tweak Certain C++ Contextual Conversions
// \see N3323 section 4 Header
#define none
#endif

#if !defined(__cpp_init_captures)
// Wording Changes for Generalized Lambda-capture
// \see N3648 section 5.1 Header predefined
#define __cpp_init_captures 201304
#endif

#if !defined(__cpp_generic_lambdas)
// Generic (Polymorphic) Lambda Expressions
// \see N3649 section 5.1 Header predefined
#define __cpp_generic_lambdas 201304
#endif

#if !defined(none)
// Clarifying Memory Allocation
// \see N3664 section 5.3 Header
#define none
#endif

#if !defined(none)
// Core Issue 1512: Pointer comparison vs qualification conversions
// \see N3624 section "5.9; 5.10" Header
#define none
#endif

#if !defined(__cpp_constexpr)
// Relaxing constraints on constexpr functions / constexpr member functions and implicit const
// \see N3652 section "5.19; 7.1" Header predefined
#define __cpp_constexpr 201304
#endif

#if !defined(__cpp_decltype_auto)
// Return type deduction for normal functions
// \see N3638 section 7.1 Header predefined
#define __cpp_decltype_auto 201304
#endif

#if !defined(__cpp_return_type_deduction)
//
// \see  section  Header predefined
#define __cpp_return_type_deduction 201304
#endif

#if !defined(__cpp_runtime_arrays)
// Runtime-sized arrays with automatic storage duration
// \see N3639 section 8.3 Header predefined
#define __cpp_runtime_arrays 201304
#endif

#if !defined(__cpp_aggregate_nsdmi)
// Member initializers and aggregates
// \see N3653 section 8.5 Header predefined
#define __cpp_aggregate_nsdmi 201304
#endif

#if !defined(none)
// Drafting for Core 1402
// \see N3667 section 12.8 Header
#define none
#endif

#if !defined(__cpp_variable_templates)
// Variable Templates
// \see N3651 section "14; 14.7" Header predefined
#define __cpp_variable_templates 201304
#endif

// N3669,Fixing constexpr member functions without const,various,none,,
// N3673,C++ Library Working Group Ready Issues Bristol 2013,various,none,,

#if !defined(__cpp_lib_constexpr_functions)
// Constexpr Library Additions: utilities
// \see N3471 section 20.2-20.4 Header <utility>
#define __cpp_lib_constexpr_functions 201210
#endif

//#if !defined()
//// Constexpr Library Additions: chrono
//// \see N3469 section 20.11 Header <chrono>
//#define
//#endif

//#if !defined()
//// Constexpr Library Additions: containers
//// \see N3470 section 23.3 Header <array>
//#define
//#endif

#if !defined(__cpp_lib_integer_sequence)
// Compile-time integer sequences
// \see N3658 section 20 Header <utility>
#define __cpp_lib_integer_sequence 201304
#endif

#if !defined(__cpp_lib_exchange_function)
// exchange() utility function
// \see N3668 section 20 Header <utility>
#define __cpp_lib_exchange_function 201304
#endif

#if !defined(__cpp_lib_tuples_by_type)
// Wording for Addressing Tuples by Type
// \see N3670 section 20.2-20.4 Header <utility>
#define __cpp_lib_tuples_by_type 201304
#endif

//N3672,A proposal to add a utility class to represent optional objects,20.5,__has_include(<optional>),1,predefined

#if !defined(__cpp_lib_make_unique)
// make_unique
// \see N3656 section 20.7 Header <memory>
#define __cpp_lib_make_unique 201304
#endif

#if !defined(__cpp_lib_transparent_operators)
// Making Operator Functors greater<>
// \see N3421 section 20.8 Header <functional>
#define __cpp_lib_transparent_operators 201210
#endif

#if !defined(__cpp_lib_result_of_sfinae)
// std::result_of and SFINAE
// \see N3462 section 20.9 Header <functional>
#define __cpp_lib_result_of_sfinae 201210
#endif

#if !defined(__cpp_lib_integral_constant_callable)
// An Incremental Improvement to integral_constant
// \see N3545 section 20.9 Header <type_traits>
#define __cpp_lib_integral_constant_callable 201304
#endif

#if !defined(__cpp_lib_transformation_trait_aliases)
// TransformationTraits Redux
// \see N3655 section 20.9 Header <type_traits>
#define __cpp_lib_transformation_trait_aliases 201304
#endif

#if !defined(__cpp_lib_chrono_udls)
// User-defined Literals for Standard Library Types
// \see N3642 section 20.11 Header <chrono>
#define __cpp_lib_chrono_udls 201304
#endif

#if !defined(__cpp_lib_string_udls)
//
// \see  section 21.7 Header <string>
#define __cpp_lib_string_udls 201304
#endif

//N3662,C++ Dynamic Arrays,"23.2; 23.3",__has_include(<dynarray>),1,predefined

#if !defined(__cpp_lib_generic_associative_lookup)
// Adding heterogeneous comparison lookup to associative containers
// \see N3657 section 23.4 Header <map>
#define __cpp_lib_generic_associative_lookup 201304
#endif

//#if !defined()
////
//// \see  section  Header <set>
//#define
//#endif

#if !defined(__cpp_lib_null_iterators)
// Null Forward Iterators
// \see N3644 section 24.2 Header <iterator>
#define __cpp_lib_null_iterators 201304
#endif

#if !defined(__cpp_lib_robust_nonmodifying_seq_ops)
// Making non-modifying sequence operations more robust
// \see N3671 section 25.2 Header <algorithm>
#define __cpp_lib_robust_nonmodifying_seq_ops 201304
#endif

#if !defined(__cpp_lib_quoted_string_io)
// Quoted Strings Library Proposal
// \see N3654 section 27.7 Header <iomanip>
#define __cpp_lib_quoted_string_io 201304
#endif

#if !defined(__cpp_lib_shared_mutex)
// Shared locking in C++
// \see N3659 section 30.4 Header <mutex>
#define __cpp_lib_shared_mutex 201304
#endif

//#if !defined()
////
//// \see  section  Header
//#define
//#endif
//Significant features of C++11,,,,,
//Doc. No.,Title,Primary Section,Macro name,Value,Header

#if !defined(__cpp_unicode_characters)
// New Character Types in C++
// \see N2249 section 2.13 Header predefined
#define __cpp_unicode_characters 200704
#endif

#if !defined(__cpp_raw_strings)
// Raw and Unicode String Literals Unified Proposal
// \see N2442 section 2.13 Header predefined
#define __cpp_raw_strings 200710
#endif

#if !defined(__cpp_unicode_literals)
//
// \see  section  Header predefined
#define __cpp_unicode_literals 200710
#endif

#if !defined(__cpp_user_defined_literals)
// User-defined Literals
// \see N2765 section "2.13; 13.5" Header predefined
#define __cpp_user_defined_literals 200809
#endif

#if !defined(__cpp_constexpr)
// Generalized Constant Expressions
// \see N2235 section "5.19; 7.1" Header predefined
#define __cpp_constexpr 200704
#endif

#if !defined(__cpp_decltype)
// Decltype
// \see N2343 section 7.1 Header predefined
#define __cpp_decltype 200707
#endif

#if !defined(__cpp_attributes)
// Towards support for attributes in C++
// \see N2761 section 7.6 Header predefined
#define __cpp_attributes 200809
#endif

#if !defined(__cpp_rvalue_reference)
// A Proposal to Add an Rvalue Reference to the C++ Language
// \see N2118 section 8.3 Header predefined
#define __cpp_rvalue_reference 200610
#endif

#if !defined(__cpp_variadic_templates)
// Proposed Wording for Variadic Templates
// \see N2242 section "8.3; 14" Header predefined
#define __cpp_variadic_templates 200704
#endif
<commit_msg>Added default feature test names based on document number for those that didn't have one<commit_after>// Significant changes to C++14

#if !defined(__cpp_binary_literals)
// Binary Literals in the C++ Core Language
// \see N3472 section 2.14
// Header: predefined
#define __cpp_binary_literals 201304
#endif

#if !defined(__cpp_noname_N3323)
// A Proposal to Tweak Certain C++ Contextual Conversions
// \see N3323 section 4#define __cpp_noname_N3323 1
#endif

#if !defined(__cpp_init_captures)
// Wording Changes for Generalized Lambda - capture
// \see N3648 section 5.1
// Header: predefined
#define __cpp_init_captures 201304
#endif

#if !defined(__cpp_generic_lambdas)
// Generic(Polymorphic) Lambda Expressions
// \see N3649 section 5.1
// Header: predefined
#define __cpp_generic_lambdas 201304
#endif

#if !defined(__cpp_noname_N3664)
// Clarifying Memory Allocation
// \see N3664 section 5.3#define __cpp_noname_N3664 1
#endif

#if !defined(__cpp_noname_N3624)
// Core Issue 1512: Pointer comparison vs qualification conversions
// \see N3624 section "5.9; 5.10"#define __cpp_noname_N3624 1
#endif

#if !defined(__cpp_constexpr)
// Relaxing constraints on constexpr functions / constexpr member functions and implicit const
// \see N3652 section "5.19; 7.1"
// Header: predefined
#define __cpp_constexpr 201304
#endif

#if !defined(__cpp_decltype_auto)
// Return type deduction for normal functions
// \see N3638 section 7.1
// Header: predefined
#define __cpp_decltype_auto 201304
#endif

#if !defined(__cpp_return_type_deduction)
//
// \see  section
// Header: predefined
#define __cpp_return_type_deduction 201304
#endif

#if !defined(__cpp_runtime_arrays)
// Runtime - sized arrays with automatic storage duration
// \see N3639 section 8.3
// Header: predefined
#define __cpp_runtime_arrays 201304
#endif

#if !defined(__cpp_aggregate_nsdmi)
// Member initializers and aggregates
// \see N3653 section 8.5
// Header: predefined
#define __cpp_aggregate_nsdmi 201304
#endif

#if !defined(__cpp_noname_N3667)
// Drafting for Core 1402
// \see N3667 section 12.8#define __cpp_noname_N3667 1
#endif

#if !defined(__cpp_variable_templates)
// Variable Templates
// \see N3651 section "14; 14.7"
// Header: predefined
#define __cpp_variable_templates 201304
#endif

#if !defined(__cpp_noname_N3669)
// Fixing constexpr member functions without const
// \see N3669 section various#define __cpp_noname_N3669 1
#endif

#if !defined(__cpp_noname_N3673)
// C++ Library Working Group Ready Issues Bristol 2013
// \see N3673 section various#define __cpp_noname_N3673 1
#endif

#if !defined(__cpp_lib_constexpr_functions)
// Constexpr Library Additions : utilities
// \see N3471 section 20.2 - 20.4
// Header: <utility>
#define __cpp_lib_constexpr_functions 201210
#endif

#if !defined(__cpp_noname_N3469)
// Constexpr Library Additions : chrono
// \see N3469 section 20.11
// Header: <chrono>
#define __cpp_noname_N3469 1
#endif

#if !defined(__cpp_noname_N3470)
// Constexpr Library Additions : containers
// \see N3470 section 23.3
// Header: <array>
#define __cpp_noname_N3470 1
#endif

#if !defined(__cpp_lib_integer_sequence)
// Compile - time integer sequences
// \see N3658 section 20
// Header: <utility>
#define __cpp_lib_integer_sequence 201304
#endif

#if !defined(__cpp_lib_exchange_function)
// exchange() utility function
// \see N3668 section 20
// Header: <utility>
#define __cpp_lib_exchange_function 201304
#endif

#if !defined(__cpp_lib_tuples_by_type)
// Wording for Addressing Tuples by Type
// \see N3670 section 20.2 - 20.4
// Header: <utility>
#define __cpp_lib_tuples_by_type 201304
#endif

#if !defined(__has_include_optional)
// A proposal to add a utility class to represent optional objects
// \see N3672 section 20.5
// Header: predefined
#define __has_include_optional 1
#endif

#if !defined(__cpp_lib_make_unique)
// make_unique
// \see N3656 section 20.7
// Header: <memory>
#define __cpp_lib_make_unique 201304
#endif

#if !defined(__cpp_lib_transparent_operators)
// Making Operator Functors greater<>
// \see N3421 section 20.8
// Header: <functional>
#define __cpp_lib_transparent_operators 201210
#endif

#if !defined(__cpp_lib_result_of_sfinae)
// std::result_of and SFINAE
// \see N3462 section 20.9
// Header: <functional>
#define __cpp_lib_result_of_sfinae 201210
#endif

#if !defined(__cpp_lib_integral_constant_callable)
// An Incremental Improvement to integral_constant
// \see N3545 section 20.9
// Header: <type_traits>
#define __cpp_lib_integral_constant_callable 201304
#endif

#if !defined(__cpp_lib_transformation_trait_aliases)
// TransformationTraits Redux
// \see N3655 section 20.9
// Header: <type_traits>
#define __cpp_lib_transformation_trait_aliases 201304
#endif

#if !defined(__cpp_lib_chrono_udls)
// User - defined Literals for Standard Library Types
// \see N3642 section 20.11
// Header: <chrono>
#define __cpp_lib_chrono_udls 201304
#endif

#if !defined(__cpp_lib_string_udls)
//
// \see  section 21.7
// Header: <string>
#define __cpp_lib_string_udls 201304
#endif

#if !defined(__has_include_dynarray)
// C++ Dynamic Arrays
// \see N3662 section "23.2; 23.3"
// Header: predefined
#define __has_include_dynarray 1
#endif

#if !defined(__cpp_lib_generic_associative_lookup)
// Adding heterogeneous comparison lookup to associative containers
// \see N3657 section 23.4
// Header: <map>
#define __cpp_lib_generic_associative_lookup 201304
#endif

#if !defined(__cpp_lib_null_iterators)
// Null Forward Iterators
// \see N3644 section 24.2
// Header: <iterator>
#define __cpp_lib_null_iterators 201304
#endif

#if !defined(__cpp_lib_robust_nonmodifying_seq_ops)
// Making non - modifying sequence operations more robust
// \see N3671 section 25.2
// Header: <algorithm>
#define __cpp_lib_robust_nonmodifying_seq_ops 201304
#endif

#if !defined(__cpp_lib_quoted_string_io)
// Quoted Strings Library Proposal
// \see N3654 section 27.7
// Header: <iomanip>
#define __cpp_lib_quoted_string_io 201304
#endif

#if !defined(__cpp_lib_shared_mutex)
// Shared locking in C++
// \see N3659 section 30.4
// Header: <mutex>
#define __cpp_lib_shared_mutex 201304
#endif

// Significant features of C++11

#if !defined(__cpp_unicode_characters)
// New Character Types in C++
// \see N2249 section 2.13
// Header: predefined
#define __cpp_unicode_characters 200704
#endif

#if !defined(__cpp_raw_strings)
// Raw and Unicode String Literals Unified Proposal
// \see N2442 section 2.13
// Header: predefined
#define __cpp_raw_strings 200710
#endif

#if !defined(__cpp_unicode_literals)
//
// \see  section
// Header: predefined
#define __cpp_unicode_literals 200710
#endif

#if !defined(__cpp_user_defined_literals)
// User - defined Literals
// \see N2765 section "2.13; 13.5"
// Header: predefined
#define __cpp_user_defined_literals 200809
#endif

#if !defined(__cpp_constexpr)
// Generalized Constant Expressions
// \see N2235 section "5.19; 7.1"
// Header: predefined
#define __cpp_constexpr 200704
#endif

#if !defined(__cpp_decltype)
// Decltype
// \see N2343 section 7.1
// Header: predefined
#define __cpp_decltype 200707
#endif

#if !defined(__cpp_attributes)
// Towards support for attributes in C++
// \see N2761 section 7.6
// Header: predefined
#define __cpp_attributes 200809
#endif

#if !defined(__cpp_rvalue_reference)
// A Proposal to Add an Rvalue Reference to the C++ Language
// \see N2118 section 8.3
// Header: predefined
#define __cpp_rvalue_reference 200610
#endif

#if !defined(__cpp_variadic_templates)
// Proposed Wording for Variadic Templates
// \see N2242 section "8.3; 14"
// Header: predefined
#define __cpp_variadic_templates 200704
#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: tbxcolor.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2004-10-12 10:17:34 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "tbxcolor.hxx"

#ifndef _SFXVIEWFRM_HXX
#include <sfx2/viewfrm.hxx>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

//........................................................................
namespace svx
{
//........................................................................

    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::frame;
    using namespace ::com::sun::star::beans;
    using namespace ::drafts::com::sun::star::frame;

    #define DECLARE_ASCII(s)        ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(s) )
    #define TOOLBAR_RESNAME         DECLARE_ASCII("private:resource/toolbar/colorbar")
    #define PROPNAME_LAYOUTMANAGER  DECLARE_ASCII("LayoutManager")

    //====================================================================
    //= ColorToolboxAccess
    //====================================================================
    ColorToolboxAccess::ColorToolboxAccess()
    {
        // the layout manager
        if ( SfxViewFrame::Current() )
        {
            try
            {
                Reference< XFrame > xFrame = SfxViewFrame::Current()->GetFrame()->GetFrameInterface();
                Reference< XPropertySet > xFrameProps( xFrame, UNO_QUERY );
                if ( xFrameProps.is() )
                    xFrameProps->getPropertyValue( PROPNAME_LAYOUTMANAGER ) >>= m_xLayouter;
            }
            catch ( Exception& )
            {
                DBG_ERRORFILE( "ColorToolboxAccess::Ctor(): exception" );
            }
        }
    }

    //--------------------------------------------------------------------
    void ColorToolboxAccess::toggleToolbox() const
    {
        try
        {
            Reference< XLayoutManager > xManager( m_xLayouter );
            OSL_ENSURE( xManager. is(), "ColorToolboxAccess::toggleToolbox: couldn't obtain the layout manager!" );
            if ( xManager. is() )
            {
                ::rtl::OUString sToolboxResource( TOOLBAR_RESNAME );
                if ( xManager->isElementVisible( sToolboxResource ) )
                {
                    xManager->hideElement( sToolboxResource );
                    xManager->destroyElement( sToolboxResource );
                }
                else
                {
                    xManager->createElement( sToolboxResource );
                    xManager->showElement( sToolboxResource );
                }
            }
        }
        catch( const Exception& )
        {
            OSL_ENSURE( sal_False, "ColorToolboxAccess::toggleToolbox: caught an exception!" );
        }
    }

    //--------------------------------------------------------------------
    bool ColorToolboxAccess::isToolboxVisible() const
    {
        return ( m_xLayouter.is() && m_xLayouter->isElementVisible( TOOLBAR_RESNAME ) );
    }

//........................................................................
} // namespace svx
//........................................................................

<commit_msg>INTEGRATION: CWS toolbars3 (1.2.70); FILE MERGED 2004/11/01 12:22:24 pb 1.2.70.1: fix: #i36113# ColorToolboxAccess -> ToolboxAccess<commit_after>/*************************************************************************
 *
 *  $RCSfile: tbxcolor.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2004-11-26 20:14:07 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include "tbxcolor.hxx"

#ifndef _SFXVIEWFRM_HXX
#include <sfx2/viewfrm.hxx>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

//........................................................................
namespace svx
{
//........................................................................

    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::frame;
    using namespace ::com::sun::star::beans;
    using namespace ::drafts::com::sun::star::frame;

    #define DECLARE_ASCII(s)        ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(s) )
    #define TOOLBAR_RESNAME         DECLARE_ASCII("private:resource/toolbar/")
    #define PROPNAME_LAYOUTMANAGER  DECLARE_ASCII("LayoutManager")

    //====================================================================
    //= ToolboxAccess
    //====================================================================
    ToolboxAccess::ToolboxAccess( const ::rtl::OUString& rToolboxName ) :

        m_bDocking          ( false ),
        m_sToolboxResName   ( TOOLBAR_RESNAME )

    {
        m_sToolboxResName += rToolboxName;

        // the layout manager
        if ( SfxViewFrame::Current() )
        {
            try
            {
                Reference< XFrame > xFrame = SfxViewFrame::Current()->GetFrame()->GetFrameInterface();
                Reference< XPropertySet > xFrameProps( xFrame, UNO_QUERY );
                if ( xFrameProps.is() )
                    xFrameProps->getPropertyValue( PROPNAME_LAYOUTMANAGER ) >>= m_xLayouter;
            }
            catch ( Exception& )
            {
                DBG_ERRORFILE( "ToolboxAccess::Ctor(): exception" );
            }
        }
    }

    //--------------------------------------------------------------------
    void ToolboxAccess::toggleToolbox() const
    {
        try
        {
            Reference< XLayoutManager > xManager( m_xLayouter );
            OSL_ENSURE( xManager. is(), "ToolboxAccess::toggleToolbox: couldn't obtain the layout manager!" );
            if ( xManager. is() )
            {
                if ( xManager->isElementVisible( m_sToolboxResName ) )
                {
                    xManager->hideElement( m_sToolboxResName );
                    xManager->destroyElement( m_sToolboxResName );
                }
                else
                {
                    xManager->createElement( m_sToolboxResName );
                    xManager->showElement( m_sToolboxResName );
                    ::com::sun::star::awt::Point aPos;

                    if ( m_bDocking )
                        xManager->dockWindow( m_sToolboxResName,
                            ::drafts::com::sun::star::ui::DockingArea_DOCKINGAREA_BOTTOM, aPos );
                }
            }
        }
        catch( const Exception& )
        {
            OSL_ENSURE( sal_False, "ToolboxAccess::toggleToolbox: caught an exception!" );
        }
    }

    //--------------------------------------------------------------------
    bool ToolboxAccess::isToolboxVisible() const
    {
        return ( m_xLayouter.is() && m_xLayouter->isElementVisible( m_sToolboxResName ) );
    }

//........................................................................
} // namespace svx
//........................................................................

<|endoftext|>


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

#pragma hdrstop

#ifndef _EDITSH_HXX
#include <editsh.hxx>
#endif
#ifndef _DOC_HXX
#include <doc.hxx>      // fuer aNodes
#endif
#ifndef _PAM_HXX
#include <pam.hxx>      // fuer SwPaM
#endif
#ifndef _EDIMP_HXX
#include <edimp.hxx>    // fuer MACROS
#endif
#ifndef _SWUNDO_HXX
#include <swundo.hxx>   // fuer die UndoIds
#endif
#ifndef _NDTXT_HXX
#include <ndtxt.hxx>    // fuer Get-/ChgFmt Set-/GetAttrXXX
#endif

/*************************************
 * harte Formatierung (Attribute)
 *************************************/

void SwEditShell::ResetAttr()
{
    SET_CURR_SHELL( this );
    StartAllAction();
    BOOL bUndoGroup = GetCrsr()->GetNext() != GetCrsr();
    if( bUndoGroup )
        GetDoc()->StartUndo(UNDO_RESETATTR, NULL);

        FOREACHPAM_START(this)
            // if ( PCURCRSR->HasMark() )
                GetDoc()->ResetAttr(*PCURCRSR);
        FOREACHPAM_END()

    if( bUndoGroup )
        GetDoc()->EndUndo(UNDO_RESETATTR, NULL);
    CallChgLnk();
    EndAllAction();
}

void SwEditShell::GCAttr()
{
//JP 04.02.97: wozu eine Action-Klammerung - ein Formatierung sollte nicht
//              ausgeloest werden, so dass es hier ueberfluessig ist.
//              Sonst Probleme im MouseBut.DownHdl - Bug 35562
//  StartAllAction();
    FOREACHPAM_START(this)
        SwTxtNode *pTxtNode;
        if ( !PCURCRSR->HasMark() )
        {
            if( 0 != (pTxtNode = GetDoc()->GetNodes()[
                                PCURCRSR->GetPoint()->nNode]->GetTxtNode()))
                pTxtNode->GCAttr();
        }
        else
        {
            const SwNodeIndex& rEnd = PCURCRSR->End()->nNode;
            SwNodeIndex aIdx( PCURCRSR->Start()->nNode );
            SwNode* pNd = &aIdx.GetNode();
            do {
                if( pNd->IsTxtNode() )
                    ((SwTxtNode*)pNd)->GCAttr();
            }
            while( 0 != ( pNd = GetDoc()->GetNodes().GoNext( &aIdx )) &&
                    aIdx <= rEnd );
        }
    FOREACHPAM_END()
//  EndAllAction();
}

// Setze das Attribut als neues default Attribut im Dokument.

void SwEditShell::SetDefault( const SfxPoolItem& rFmtHint )
{
    // 7502: Action-Klammerung
    StartAllAction();
    GetDoc()->SetDefault( rFmtHint );
    EndAllAction();
}

/*

void SwEditShell::SetDefault( const SfxItemSet& rSet )
{
    // 7502: Action-Klammerung
    StartAllAction();
    GetDoc()->SetDefault( rSet );
    EndAllAction();
}
*/

// Erfrage das Default Attribut in diesem Dokument.

const SfxPoolItem& SwEditShell::GetDefault( USHORT nFmtHint ) const
{
    return GetDoc()->GetDefault( nFmtHint );

}

void SwEditShell::SetAttr( const SfxPoolItem& rHint, USHORT nFlags )
{
    SET_CURR_SHELL( this );
    StartAllAction();
    SwPaM* pCrsr = GetCrsr();
    if( pCrsr->GetNext() != pCrsr )     // Ring von Cursorn
    {
        FASTBOOL bIsTblMode = IsTableMode();
        GetDoc()->StartUndo(UNDO_INSATTR, NULL);

        FOREACHPAM_START(this)
            if( PCURCRSR->HasMark() && ( bIsTblMode ||
                *PCURCRSR->GetPoint() != *PCURCRSR->GetMark() ))
                GetDoc()->Insert(*PCURCRSR, rHint, nFlags );
        FOREACHPAM_END()

        GetDoc()->EndUndo(UNDO_INSATTR, NULL);
    }
    else
    {
        if( !HasSelection() )
            UpdateAttr();
        GetDoc()->Insert( *pCrsr, rHint, nFlags );
    }
    EndAllAction();
}

void SwEditShell::SetAttr( const SfxItemSet& rSet, USHORT nFlags )
{
    SET_CURR_SHELL( this );
    StartAllAction();
    SwPaM* pCrsr = GetCrsr();
    if( pCrsr->GetNext() != pCrsr )     // Ring von Cursorn
    {
        FASTBOOL bIsTblMode = IsTableMode();
        GetDoc()->StartUndo(UNDO_INSATTR, NULL);

        FOREACHPAM_START(this)
            if( PCURCRSR->HasMark() && ( bIsTblMode ||
                *PCURCRSR->GetPoint() != *PCURCRSR->GetMark() ))
                GetDoc()->Insert(*PCURCRSR, rSet, nFlags );
        FOREACHPAM_END()

        GetDoc()->EndUndo(UNDO_INSATTR, NULL);
    }
    else
    {
        if( !HasSelection() )
            UpdateAttr();
        GetDoc()->Insert( *pCrsr, rSet, nFlags );
    }
    EndAllAction();
}

<commit_msg>INTEGRATION: CWS pchfix02 (1.5.2); FILE MERGED 2006/09/01 17:51:36 kaib 1.5.2.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: edatmisc.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 21:04:33 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#ifndef _EDITSH_HXX
#include <editsh.hxx>
#endif
#ifndef _DOC_HXX
#include <doc.hxx>      // fuer aNodes
#endif
#ifndef _PAM_HXX
#include <pam.hxx>      // fuer SwPaM
#endif
#ifndef _EDIMP_HXX
#include <edimp.hxx>    // fuer MACROS
#endif
#ifndef _SWUNDO_HXX
#include <swundo.hxx>   // fuer die UndoIds
#endif
#ifndef _NDTXT_HXX
#include <ndtxt.hxx>    // fuer Get-/ChgFmt Set-/GetAttrXXX
#endif

/*************************************
 * harte Formatierung (Attribute)
 *************************************/

void SwEditShell::ResetAttr()
{
    SET_CURR_SHELL( this );
    StartAllAction();
    BOOL bUndoGroup = GetCrsr()->GetNext() != GetCrsr();
    if( bUndoGroup )
        GetDoc()->StartUndo(UNDO_RESETATTR, NULL);

        FOREACHPAM_START(this)
            // if ( PCURCRSR->HasMark() )
                GetDoc()->ResetAttr(*PCURCRSR);
        FOREACHPAM_END()

    if( bUndoGroup )
        GetDoc()->EndUndo(UNDO_RESETATTR, NULL);
    CallChgLnk();
    EndAllAction();
}

void SwEditShell::GCAttr()
{
//JP 04.02.97: wozu eine Action-Klammerung - ein Formatierung sollte nicht
//              ausgeloest werden, so dass es hier ueberfluessig ist.
//              Sonst Probleme im MouseBut.DownHdl - Bug 35562
//  StartAllAction();
    FOREACHPAM_START(this)
        SwTxtNode *pTxtNode;
        if ( !PCURCRSR->HasMark() )
        {
            if( 0 != (pTxtNode = GetDoc()->GetNodes()[
                                PCURCRSR->GetPoint()->nNode]->GetTxtNode()))
                pTxtNode->GCAttr();
        }
        else
        {
            const SwNodeIndex& rEnd = PCURCRSR->End()->nNode;
            SwNodeIndex aIdx( PCURCRSR->Start()->nNode );
            SwNode* pNd = &aIdx.GetNode();
            do {
                if( pNd->IsTxtNode() )
                    ((SwTxtNode*)pNd)->GCAttr();
            }
            while( 0 != ( pNd = GetDoc()->GetNodes().GoNext( &aIdx )) &&
                    aIdx <= rEnd );
        }
    FOREACHPAM_END()
//  EndAllAction();
}

// Setze das Attribut als neues default Attribut im Dokument.

void SwEditShell::SetDefault( const SfxPoolItem& rFmtHint )
{
    // 7502: Action-Klammerung
    StartAllAction();
    GetDoc()->SetDefault( rFmtHint );
    EndAllAction();
}

/*

void SwEditShell::SetDefault( const SfxItemSet& rSet )
{
    // 7502: Action-Klammerung
    StartAllAction();
    GetDoc()->SetDefault( rSet );
    EndAllAction();
}
*/

// Erfrage das Default Attribut in diesem Dokument.

const SfxPoolItem& SwEditShell::GetDefault( USHORT nFmtHint ) const
{
    return GetDoc()->GetDefault( nFmtHint );

}

void SwEditShell::SetAttr( const SfxPoolItem& rHint, USHORT nFlags )
{
    SET_CURR_SHELL( this );
    StartAllAction();
    SwPaM* pCrsr = GetCrsr();
    if( pCrsr->GetNext() != pCrsr )     // Ring von Cursorn
    {
        FASTBOOL bIsTblMode = IsTableMode();
        GetDoc()->StartUndo(UNDO_INSATTR, NULL);

        FOREACHPAM_START(this)
            if( PCURCRSR->HasMark() && ( bIsTblMode ||
                *PCURCRSR->GetPoint() != *PCURCRSR->GetMark() ))
                GetDoc()->Insert(*PCURCRSR, rHint, nFlags );
        FOREACHPAM_END()

        GetDoc()->EndUndo(UNDO_INSATTR, NULL);
    }
    else
    {
        if( !HasSelection() )
            UpdateAttr();
        GetDoc()->Insert( *pCrsr, rHint, nFlags );
    }
    EndAllAction();
}

void SwEditShell::SetAttr( const SfxItemSet& rSet, USHORT nFlags )
{
    SET_CURR_SHELL( this );
    StartAllAction();
    SwPaM* pCrsr = GetCrsr();
    if( pCrsr->GetNext() != pCrsr )     // Ring von Cursorn
    {
        FASTBOOL bIsTblMode = IsTableMode();
        GetDoc()->StartUndo(UNDO_INSATTR, NULL);

        FOREACHPAM_START(this)
            if( PCURCRSR->HasMark() && ( bIsTblMode ||
                *PCURCRSR->GetPoint() != *PCURCRSR->GetMark() ))
                GetDoc()->Insert(*PCURCRSR, rSet, nFlags );
        FOREACHPAM_END()

        GetDoc()->EndUndo(UNDO_INSATTR, NULL);
    }
    else
    {
        if( !HasSelection() )
            UpdateAttr();
        GetDoc()->Insert( *pCrsr, rSet, nFlags );
    }
    EndAllAction();
}

<|endoftext|>


<commit_before><commit_msg>coverity#1213245 Dereference null return value<commit_after><|endoftext|>


<commit_before><commit_msg>CID#736201 out of bounds<commit_after><|endoftext|>