<commit_before>#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>

#include <string>

#include "globals.h"
#include "profiler.h"
#include "stacktraces.h"

static Profiler *prof;
FILE *Globals::OutFile;

void JNICALL OnThreadStart(jvmtiEnv *jvmti_env, JNIEnv *jni_env,
                           jthread thread) {
  IMPLICITLY_USE(jvmti_env);
  IMPLICITLY_USE(thread);
  Accessors::SetCurrentJniEnv(jni_env);
}

void JNICALL OnThreadEnd(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread) {
  IMPLICITLY_USE(jvmti_env);
  IMPLICITLY_USE(jni_env);
  IMPLICITLY_USE(thread);
}

// This has to be here, or the VM turns off class loading events.
// And AsyncGetCallTrace needs class loading events to be turned on!
void JNICALL OnClassLoad(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread,
                         jclass klass) {
  IMPLICITLY_USE(jvmti_env);
  IMPLICITLY_USE(jni_env);
  IMPLICITLY_USE(thread);
  IMPLICITLY_USE(klass);
}

// Calls GetClassMethods on a given class to force the creation of
// jmethodIDs of it.
void CreateJMethodIDsForClass(jvmtiEnv *jvmti, jclass klass) {
  jint method_count;
  JvmtiScopedPtr<jmethodID> methods(jvmti);
  jvmtiError e = jvmti->GetClassMethods(klass, &method_count, methods.GetRef());
  if (e != JVMTI_ERROR_NONE && e != JVMTI_ERROR_CLASS_NOT_PREPARED) {
    // JVMTI_ERROR_CLASS_NOT_PREPARED is okay because some classes may
    // be loaded but not prepared at this point.
    JvmtiScopedPtr<char> ksig(jvmti);
    JVMTI_ERROR((jvmti->GetClassSignature(klass, ksig.GetRef(), NULL)));
    fprintf(
        stderr,
        "Failed to create method IDs for methods in class %s with error %d ",
        ksig.Get(), e);
  }
}

void JNICALL OnVMInit(jvmtiEnv *jvmti, JNIEnv *jni_env, jthread thread) {
  IMPLICITLY_USE(thread);
  IMPLICITLY_USE(jni_env);
  // Forces the creation of jmethodIDs of the classes that had already
  // been loaded (eg java.lang.Object, java.lang.ClassLoader) and
  // OnClassPrepare() misses.
  jint class_count;
  JvmtiScopedPtr<jclass> classes(jvmti);
  JVMTI_ERROR((jvmti->GetLoadedClasses(&class_count, classes.GetRef())));
  jclass *classList = classes.Get();
  for (int i = 0; i < class_count; ++i) {
    jclass klass = classList[i];
    CreateJMethodIDsForClass(jvmti, klass);
  }
  prof->Start();
}

void JNICALL OnClassPrepare(jvmtiEnv *jvmti_env, JNIEnv *jni_env,
                            jthread thread, jclass klass) {
  IMPLICITLY_USE(jni_env);
  IMPLICITLY_USE(thread);
  // We need to do this to "prime the pump", as it were -- make sure
  // that all of the methodIDs have been initialized internally, for
  // AsyncGetCallTrace.  I imagine it slows down class loading a mite,
  // but honestly, how fast does class loading have to be?
  CreateJMethodIDsForClass(jvmti_env, klass);
}

void JNICALL OnVMDeath(jvmtiEnv *jvmti_env, JNIEnv *jni_env) {
  IMPLICITLY_USE(jvmti_env);
  IMPLICITLY_USE(jni_env);

  prof->Stop();
  prof->DumpToFile(Globals::OutFile);
}

static bool PrepareJvmti(jvmtiEnv *jvmti) {
  // Set the list of permissions to do the various internal VM things
  // we want to do.
  jvmtiCapabilities caps;

  memset(&caps, 0, sizeof(caps));
  caps.can_generate_all_class_hook_events = 1;

  caps.can_get_source_file_name = 1;
  caps.can_get_line_numbers = 1;
  caps.can_get_bytecodes = 1;
  caps.can_get_constant_pool = 1;

  jvmtiCapabilities all_caps;
  int error;

  if (JVMTI_ERROR_NONE ==
      (error = jvmti->GetPotentialCapabilities(&all_caps))) {
    // This makes sure that if we need a capability, it is one of the
    // potential capabilities.  The technique isn't wonderful, but it
    // is compact and as likely to be compatible between versions as
    // anything else.
    char *has = reinterpret_cast<char *>(&all_caps);
    const char *should_have = reinterpret_cast<const char *>(&caps);
    for (int i = 0; i < sizeof(all_caps); i++) {
      if ((should_have[i] != 0) && (has[i] == 0)) {
        return false;
      }
    }

    // This adds the capabilities.
    if ((error = jvmti->AddCapabilities(&caps)) != JVMTI_ERROR_NONE) {
      fprintf(stderr, "Failed to add capabilities with error %d\n", error);
      return false;
    }
  }
  return true;
}

static bool RegisterJvmti(jvmtiEnv *jvmti) {
  // Create the list of callbacks to be called on given events.
  jvmtiEventCallbacks *callbacks = new jvmtiEventCallbacks();
  memset(callbacks, 0, sizeof(jvmtiEventCallbacks));

  callbacks->ThreadStart = &OnThreadStart;
  callbacks->ThreadEnd = &OnThreadEnd;
  callbacks->VMInit = &OnVMInit;
  callbacks->VMDeath = &OnVMDeath;

  callbacks->ClassLoad = &OnClassLoad;
  callbacks->ClassPrepare = &OnClassPrepare;

  JVMTI_ERROR_1(
      (jvmti->SetEventCallbacks(callbacks, sizeof(jvmtiEventCallbacks))),
      false);

  jvmtiEvent events[] = {JVMTI_EVENT_CLASS_LOAD, JVMTI_EVENT_CLASS_PREPARE,
                         JVMTI_EVENT_THREAD_END, JVMTI_EVENT_THREAD_START,
                         JVMTI_EVENT_VM_DEATH, JVMTI_EVENT_VM_INIT};

  size_t num_events = sizeof(events) / sizeof(jvmtiEvent);

  // Enable the callbacks to be triggered when the events occur.
  // Events are enumerated in jvmstatagent.h
  for (int i = 0; i < num_events; i++) {
    JVMTI_ERROR_1(
        (jvmti->SetEventNotificationMode(JVMTI_ENABLE, events[i], NULL)),
        false);
  }

  return true;
}

#define POSITIVE(x) (static_cast<size_t>(x > 0 ? x : 0))

static void SetFileFromOption(char *equals) {
  char *name_begin = equals + 1;
  char *name_end;
  if ((name_end = strchr(equals, ',')) == NULL) {
    name_end = equals + strlen(equals);
  }
  size_t len = POSITIVE(name_end - name_begin);
  char *file_name = new char[len];
  strncpy(file_name, name_begin, len);
  if (strcmp(file_name, "stderr") == 0) {
    Globals::OutFile = stderr;
  } else if (strcmp(file_name, "stdout") == 0) {
    Globals::OutFile = stdout;
  } else {
    Globals::OutFile = fopen(file_name, "w+");
    if (Globals::OutFile == NULL) {
      fprintf(stderr, "Could not open file %s: ", file_name);
      perror(NULL);
      exit(1);
    }
  }

  delete[] file_name;
}

static void ParseArguments(char *options) {
  char *key = options;
  for (char *next = options; next != NULL;
       next = strchr((key = next + 1), ',')) {
    char *equals = strchr(key, '=');
    if (equals == NULL) {
      fprintf(stderr, "No value for key %s\n", key);
      continue;
    }
    if (strncmp(key, "file", POSITIVE(equals - key)) == 0) {
      SetFileFromOption(equals);
    }
  }

  if (Globals::OutFile == NULL) {
    char path[PATH_MAX];
    if (getcwd(path, PATH_MAX) == NULL) {
      fprintf(stderr, "cwd too long?\n");
      exit(0);
    }
    size_t pathlen = strlen(path);
    strncat(path, "/", PATH_MAX - (pathlen++));
    strncat(path, kDefaultOutFile, PATH_MAX - pathlen);
    Globals::OutFile = fopen(path, "w+");
  }
}

AGENTEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options,
                                      void *reserved) {
  IMPLICITLY_USE(reserved);
  int err;
  jvmtiEnv *jvmti;
  ParseArguments(options);

  Accessors::Init();

  if ((err = (vm->GetEnv(reinterpret_cast<void **>(&jvmti), JVMTI_VERSION))) !=
      JNI_OK) {
    fprintf(stderr, "JNI Error %d\n", err);
    return 1;
  }

  if (!PrepareJvmti(jvmti)) {
    fprintf(stderr, "Failed to initialize JVMTI.  Continuing...\n");
    return 0;
  }

  if (!RegisterJvmti(jvmti)) {
    fprintf(stderr, "Failed to enable JVMTI events.  Continuing...\n");
    // We fail hard here because we may have failed in the middle of
    // registering callbacks, which will leave the system in an
    // inconsistent state.
    return 1;
  }

  Asgct::SetAsgct(Accessors::GetJvmFunction<ASGCTType>("AsyncGetCallTrace"));

  prof = new Profiler(jvmti);

  return 0;
}

AGENTEXPORT void JNICALL Agent_OnUnload(JavaVM *vm) {
  IMPLICITLY_USE(vm);
  Accessors::Destroy();
}
<commit_msg>fix bug: when using with hadoop profile, filename get garbled<commit_after>#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>

#include <string>

#include "globals.h"
#include "profiler.h"
#include "stacktraces.h"

static Profiler *prof;
FILE *Globals::OutFile;

void JNICALL OnThreadStart(jvmtiEnv *jvmti_env, JNIEnv *jni_env,
                           jthread thread) {
  IMPLICITLY_USE(jvmti_env);
  IMPLICITLY_USE(thread);
  Accessors::SetCurrentJniEnv(jni_env);
}

void JNICALL OnThreadEnd(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread) {
  IMPLICITLY_USE(jvmti_env);
  IMPLICITLY_USE(jni_env);
  IMPLICITLY_USE(thread);
}

// This has to be here, or the VM turns off class loading events.
// And AsyncGetCallTrace needs class loading events to be turned on!
void JNICALL OnClassLoad(jvmtiEnv *jvmti_env, JNIEnv *jni_env, jthread thread,
                         jclass klass) {
  IMPLICITLY_USE(jvmti_env);
  IMPLICITLY_USE(jni_env);
  IMPLICITLY_USE(thread);
  IMPLICITLY_USE(klass);
}

// Calls GetClassMethods on a given class to force the creation of
// jmethodIDs of it.
void CreateJMethodIDsForClass(jvmtiEnv *jvmti, jclass klass) {
  jint method_count;
  JvmtiScopedPtr<jmethodID> methods(jvmti);
  jvmtiError e = jvmti->GetClassMethods(klass, &method_count, methods.GetRef());
  if (e != JVMTI_ERROR_NONE && e != JVMTI_ERROR_CLASS_NOT_PREPARED) {
    // JVMTI_ERROR_CLASS_NOT_PREPARED is okay because some classes may
    // be loaded but not prepared at this point.
    JvmtiScopedPtr<char> ksig(jvmti);
    JVMTI_ERROR((jvmti->GetClassSignature(klass, ksig.GetRef(), NULL)));
    fprintf(
        stderr,
        "Failed to create method IDs for methods in class %s with error %d ",
        ksig.Get(), e);
  }
}

void JNICALL OnVMInit(jvmtiEnv *jvmti, JNIEnv *jni_env, jthread thread) {
  IMPLICITLY_USE(thread);
  IMPLICITLY_USE(jni_env);
  // Forces the creation of jmethodIDs of the classes that had already
  // been loaded (eg java.lang.Object, java.lang.ClassLoader) and
  // OnClassPrepare() misses.
  jint class_count;
  JvmtiScopedPtr<jclass> classes(jvmti);
  JVMTI_ERROR((jvmti->GetLoadedClasses(&class_count, classes.GetRef())));
  jclass *classList = classes.Get();
  for (int i = 0; i < class_count; ++i) {
    jclass klass = classList[i];
    CreateJMethodIDsForClass(jvmti, klass);
  }
  prof->Start();
}

void JNICALL OnClassPrepare(jvmtiEnv *jvmti_env, JNIEnv *jni_env,
                            jthread thread, jclass klass) {
  IMPLICITLY_USE(jni_env);
  IMPLICITLY_USE(thread);
  // We need to do this to "prime the pump", as it were -- make sure
  // that all of the methodIDs have been initialized internally, for
  // AsyncGetCallTrace.  I imagine it slows down class loading a mite,
  // but honestly, how fast does class loading have to be?
  CreateJMethodIDsForClass(jvmti_env, klass);
}

void JNICALL OnVMDeath(jvmtiEnv *jvmti_env, JNIEnv *jni_env) {
  IMPLICITLY_USE(jvmti_env);
  IMPLICITLY_USE(jni_env);

  prof->Stop();
  prof->DumpToFile(Globals::OutFile);
}

static bool PrepareJvmti(jvmtiEnv *jvmti) {
  // Set the list of permissions to do the various internal VM things
  // we want to do.
  jvmtiCapabilities caps;

  memset(&caps, 0, sizeof(caps));
  caps.can_generate_all_class_hook_events = 1;

  caps.can_get_source_file_name = 1;
  caps.can_get_line_numbers = 1;
  caps.can_get_bytecodes = 1;
  caps.can_get_constant_pool = 1;

  jvmtiCapabilities all_caps;
  int error;

  if (JVMTI_ERROR_NONE ==
      (error = jvmti->GetPotentialCapabilities(&all_caps))) {
    // This makes sure that if we need a capability, it is one of the
    // potential capabilities.  The technique isn't wonderful, but it
    // is compact and as likely to be compatible between versions as
    // anything else.
    char *has = reinterpret_cast<char *>(&all_caps);
    const char *should_have = reinterpret_cast<const char *>(&caps);
    for (int i = 0; i < sizeof(all_caps); i++) {
      if ((should_have[i] != 0) && (has[i] == 0)) {
        return false;
      }
    }

    // This adds the capabilities.
    if ((error = jvmti->AddCapabilities(&caps)) != JVMTI_ERROR_NONE) {
      fprintf(stderr, "Failed to add capabilities with error %d\n", error);
      return false;
    }
  }
  return true;
}

static bool RegisterJvmti(jvmtiEnv *jvmti) {
  // Create the list of callbacks to be called on given events.
  jvmtiEventCallbacks *callbacks = new jvmtiEventCallbacks();
  memset(callbacks, 0, sizeof(jvmtiEventCallbacks));

  callbacks->ThreadStart = &OnThreadStart;
  callbacks->ThreadEnd = &OnThreadEnd;
  callbacks->VMInit = &OnVMInit;
  callbacks->VMDeath = &OnVMDeath;

  callbacks->ClassLoad = &OnClassLoad;
  callbacks->ClassPrepare = &OnClassPrepare;

  JVMTI_ERROR_1(
      (jvmti->SetEventCallbacks(callbacks, sizeof(jvmtiEventCallbacks))),
      false);

  jvmtiEvent events[] = {JVMTI_EVENT_CLASS_LOAD, JVMTI_EVENT_CLASS_PREPARE,
                         JVMTI_EVENT_THREAD_END, JVMTI_EVENT_THREAD_START,
                         JVMTI_EVENT_VM_DEATH, JVMTI_EVENT_VM_INIT};

  size_t num_events = sizeof(events) / sizeof(jvmtiEvent);

  // Enable the callbacks to be triggered when the events occur.
  // Events are enumerated in jvmstatagent.h
  for (int i = 0; i < num_events; i++) {
    JVMTI_ERROR_1(
        (jvmti->SetEventNotificationMode(JVMTI_ENABLE, events[i], NULL)),
        false);
  }

  return true;
}

#define POSITIVE(x) (static_cast<size_t>(x > 0 ? x : 0))

static void SetFileFromOption(char *equals) {
  char *name_begin = equals + 1;
  char *name_end;
  if ((name_end = strchr(equals, ',')) == NULL) {
    name_end = equals + strlen(equals);
  }
  size_t len = POSITIVE(name_end - name_begin);
  char *file_name = new char[len];
  for(int i = 0; i < len; ++i){
    file_name[i] = '\0';
  }
  strcpy(file_name, name_begin);
  if (strcmp(file_name, "stderr") == 0) {
    Globals::OutFile = stderr;
  } else if (strcmp(file_name, "stdout") == 0) {
    Globals::OutFile = stdout;
  } else {
    Globals::OutFile = fopen(file_name, "w+");
    if (Globals::OutFile == NULL) {
      fprintf(stderr, "Could not open file %s: ", file_name);
      perror(NULL);
      exit(1);
    }
  }

  delete[] file_name;
}

static void ParseArguments(char *options) {
  char *key = options;
  for (char *next = options; next != NULL;
       next = strchr((key = next + 1), ',')) {
    char *equals = strchr(key, '=');
    if (equals == NULL) {
      fprintf(stderr, "No value for key %s\n", key);
      continue;
    }
    if (strncmp(key, "file", POSITIVE(equals - key)) == 0) {
      SetFileFromOption(equals);
    }
  }

  if (Globals::OutFile == NULL) {
    char path[PATH_MAX];
    if (getcwd(path, PATH_MAX) == NULL) {
      fprintf(stderr, "cwd too long?\n");
      exit(0);
    }
    size_t pathlen = strlen(path);
    strncat(path, "/", PATH_MAX - (pathlen++));
    strncat(path, kDefaultOutFile, PATH_MAX - pathlen);
    Globals::OutFile = fopen(path, "w+");
  }
}

AGENTEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options,
                                      void *reserved) {
  IMPLICITLY_USE(reserved);
  int err;
  jvmtiEnv *jvmti;
  ParseArguments(options);

  Accessors::Init();

  if ((err = (vm->GetEnv(reinterpret_cast<void **>(&jvmti), JVMTI_VERSION))) !=
      JNI_OK) {
    fprintf(stderr, "JNI Error %d\n", err);
    return 1;
  }

  if (!PrepareJvmti(jvmti)) {
    fprintf(stderr, "Failed to initialize JVMTI.  Continuing...\n");
    return 0;
  }

  if (!RegisterJvmti(jvmti)) {
    fprintf(stderr, "Failed to enable JVMTI events.  Continuing...\n");
    // We fail hard here because we may have failed in the middle of
    // registering callbacks, which will leave the system in an
    // inconsistent state.
    return 1;
  }

  Asgct::SetAsgct(Accessors::GetJvmFunction<ASGCTType>("AsyncGetCallTrace"));

  prof = new Profiler(jvmti);

  return 0;
}

AGENTEXPORT void JNICALL Agent_OnUnload(JavaVM *vm) {
  IMPLICITLY_USE(vm);
  Accessors::Destroy();
}
<|endoftext|>


<commit_before>#include "eval.h"

#include <cmath>
#include <vector>

uint64_t primitive_polynomial(unsigned degree) {
  static const std::vector<uint64_t> primitive_polynomials(
      { 0, 0x3, 0x7, 0xb, 0x13, 0x25, 0x43 });
  return primitive_polynomials.at(degree);
}

static double sigma(const double eb_n0, const double R) {
  return 1.0f / sqrt((2 * R * pow(10, eb_n0 / 10.0)));
}

std::tuple<std::vector<int>, std::vector<float>, unsigned>
pzg_wrapper(const bch &code, const std::vector<float> &b) {
  std::vector<int> hard;
  hard.reserve(b.size());
  std::transform(std::cbegin(b), std::cend(b), std::back_inserter(hard),
                 [](const auto &bit) { return bit < 0; });
  auto b_corr = code.correct_peterson(hard);
  return std::make_tuple(b_corr, std::vector<float>(), 0);
}

std::tuple<std::vector<int>, std::vector<float>, unsigned>
bm_wrapper(const bch &code, const std::vector<float> &b) {
  std::vector<int> hard;
  hard.reserve(b.size());
  std::transform(std::cbegin(b), std::cend(b), std::back_inserter(hard),
                 [](const auto &bit) { return bit < 0; });
  auto b_corr = code.correct_bm(hard);
  return std::make_tuple(b_corr, std::vector<float>(), 0);
}

std::tuple<std::vector<int>, std::vector<float>, unsigned>
uncoded(const std::vector<float> &b) {
  std::vector<int> hard;
  hard.reserve(b.size());
  std::transform(std::cbegin(b), std::cend(b), std::back_inserter(hard),
                 [](const auto &bit) { return bit < 0; });
  return std::make_tuple(hard, std::vector<float>(), 0);
}

std::string eval_object::header() {
  return "reconstruction_failures "
         "reconstruction_errors "
         "wer "
         "fk_rate "
         "ber "
         "wer ";
}

std::ostream &operator<<(std::ostream &os, const eval_object &e) {
  os << std::scientific;
  const double samples_ = e.samples;
  os << std::setprecision(12) << e.reconstruction_failures / samples_ << " ";
  os << std::setprecision(12) << e.reconstruction_errors / samples_ << " ";
  const auto wrong_words = e.reconstruction_failures + e.reconstruction_errors;
  os << std::setprecision(12) << wrong_words / samples_ << " ";
  os << std::setprecision(12) << e.fk_corr / samples_ << " ";
  os << std::setprecision(12) << e.bit_errors / (samples_ * e.n);
  return os;
}

double eval_object::ber() const { return bit_errors / (double)(samples * n); }
double eval_object::wer() const { return word_errors / (double)(samples); }

eval_object evaluate(std::mt19937_64 &generator, const decoder_t &decoder,
                     const size_t samples, const float eb_n0, const unsigned n,
                     const unsigned l, const unsigned fk) {
  const float R = (float)l / n;

  unsigned reconstruction_failures = 0;
  unsigned reconstruction_errors = 0;
  unsigned fk_corr = 0;
  unsigned bit_errors = 0;
  unsigned word_errors = 0;

  std::vector<float> b(n);
  std::normal_distribution<float> random(1.0, sigma(eb_n0, R));
  auto noise_gen = std::bind(std::ref(random), std::ref(generator));

  for (size_t sample = 0; sample < samples; sample++) {
    std::generate(std::begin(b), std::end(b), noise_gen);
    try {
      auto result = decoder(b);
      const auto &b_corr = std::get<0>(result);
      auto wrong_bits = std::count_if(std::cbegin(b_corr), std::cend(b_corr),
                                      [](const auto &bit) { return bit != 0; });
      if (wrong_bits) {
        reconstruction_errors++;
        bit_errors += wrong_bits;
        word_errors++;
      } else {
        auto d = std::count_if(std::cbegin(b), std::cend(b),
                               [](const auto &bit) { return bit < 0; });
        if (d > fk)
          fk_corr++;
      }
    }
    catch (const decoding_failure &) {
      reconstruction_failures++;
      bit_errors += n;
      word_errors++;
    }
  }

  return { eb_n0,      reconstruction_failures, reconstruction_errors, fk_corr,
           bit_errors, word_errors,             samples,               n };
}

<commit_msg>use ber and wer function in operator<<<commit_after>#include "eval.h"

#include <cmath>
#include <vector>

uint64_t primitive_polynomial(unsigned degree) {
  static const std::vector<uint64_t> primitive_polynomials(
      { 0, 0x3, 0x7, 0xb, 0x13, 0x25, 0x43 });
  return primitive_polynomials.at(degree);
}

static double sigma(const double eb_n0, const double R) {
  return 1.0f / sqrt((2 * R * pow(10, eb_n0 / 10.0)));
}

std::tuple<std::vector<int>, std::vector<float>, unsigned>
pzg_wrapper(const bch &code, const std::vector<float> &b) {
  std::vector<int> hard;
  hard.reserve(b.size());
  std::transform(std::cbegin(b), std::cend(b), std::back_inserter(hard),
                 [](const auto &bit) { return bit < 0; });
  auto b_corr = code.correct_peterson(hard);
  return std::make_tuple(b_corr, std::vector<float>(), 0);
}

std::tuple<std::vector<int>, std::vector<float>, unsigned>
bm_wrapper(const bch &code, const std::vector<float> &b) {
  std::vector<int> hard;
  hard.reserve(b.size());
  std::transform(std::cbegin(b), std::cend(b), std::back_inserter(hard),
                 [](const auto &bit) { return bit < 0; });
  auto b_corr = code.correct_bm(hard);
  return std::make_tuple(b_corr, std::vector<float>(), 0);
}

std::tuple<std::vector<int>, std::vector<float>, unsigned>
uncoded(const std::vector<float> &b) {
  std::vector<int> hard;
  hard.reserve(b.size());
  std::transform(std::cbegin(b), std::cend(b), std::back_inserter(hard),
                 [](const auto &bit) { return bit < 0; });
  return std::make_tuple(hard, std::vector<float>(), 0);
}

std::string eval_object::header() {
  return "reconstruction_failures "
         "reconstruction_errors "
         "wer "
         "fk_rate "
         "ber "
         "wer ";
}

std::ostream &operator<<(std::ostream &os, const eval_object &e) {
  os << std::scientific;
  const double samples_ = e.samples;
  os << std::setprecision(12) << e.reconstruction_failures / samples_ << " ";
  os << std::setprecision(12) << e.reconstruction_errors / samples_ << " ";
  const auto wrong_words = e.reconstruction_failures + e.reconstruction_errors;
  os << std::setprecision(12) << wrong_words / samples_ << " ";
  os << std::setprecision(12) << e.fk_corr / samples_ << " ";
  os << std::setprecision(12) << e.ber() << " ";
  os << std::setprecision(12) << e.wer();
  return os;
}

double eval_object::ber() const { return bit_errors / (double)(samples * n); }
double eval_object::wer() const { return word_errors / (double)(samples); }

eval_object evaluate(std::mt19937_64 &generator, const decoder_t &decoder,
                     const size_t samples, const float eb_n0, const unsigned n,
                     const unsigned l, const unsigned fk) {
  const float R = (float)l / n;

  unsigned reconstruction_failures = 0;
  unsigned reconstruction_errors = 0;
  unsigned fk_corr = 0;
  unsigned bit_errors = 0;
  unsigned word_errors = 0;

  std::vector<float> b(n);
  std::normal_distribution<float> random(1.0, sigma(eb_n0, R));
  auto noise_gen = std::bind(std::ref(random), std::ref(generator));

  for (size_t sample = 0; sample < samples; sample++) {
    std::generate(std::begin(b), std::end(b), noise_gen);
    try {
      auto result = decoder(b);
      const auto &b_corr = std::get<0>(result);
      auto wrong_bits = std::count_if(std::cbegin(b_corr), std::cend(b_corr),
                                      [](const auto &bit) { return bit != 0; });
      if (wrong_bits) {
        reconstruction_errors++;
        bit_errors += wrong_bits;
        word_errors++;
      } else {
        auto d = std::count_if(std::cbegin(b), std::cend(b),
                               [](const auto &bit) { return bit < 0; });
        if (d > fk)
          fk_corr++;
      }
    }
    catch (const decoding_failure &) {
      reconstruction_failures++;
      bit_errors += n;
      word_errors++;
    }
  }

  return { eb_n0,      reconstruction_failures, reconstruction_errors, fk_corr,
           bit_errors, word_errors,             samples,               n };
}

<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <boost/filesystem/operations.hpp>
#include "libtorrent/file.hpp"
#include <sstream>

#ifdef WIN32

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
typedef int mode_t;

#else

#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#endif

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

namespace fs = boost::filesystem;

namespace
{
	enum { mode_in = 1, mode_out = 2 };

	mode_t map_open_mode(int m)
	{
//		if (m == (mode_in | mode_out)) return O_RDWR | O_BINARY;
		if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM;
		assert(false);
		return 0;
	}
}

namespace libtorrent
{

	const file::open_mode file::in(mode_in);
	const file::open_mode file::out(mode_out);

	const file::seek_mode file::begin(1);
	const file::seek_mode file::end(2);

	struct file::impl
	{
		impl()
			: m_fd(-1)
			, m_open_mode(0)
		{}

		impl(fs::path const& path, int mode)
			: m_fd(-1)
			, m_open_mode(0)
		{
			open(path, mode);
		}

		~impl()
		{
			close();
		}

		void open(fs::path const& path, int mode)
		{
			close();
			m_fd = ::open(
				path.native_file_string().c_str()
				, map_open_mode(mode)
				, S_IREAD | S_IWRITE);
			if (m_fd == -1)
			{
				std::stringstream msg;
				msg << "open failed: '" << path.native_file_string() << "'. "
					<< strerror(errno);
				throw file_error(msg.str());
			}
			m_open_mode = mode;
		}

		void close()
		{
			if (m_fd == -1) return;

			std::stringstream str;
			str << "fd: " << m_fd << "\n";

			::close(m_fd);
			m_fd = -1;
			m_open_mode = 0;
		}

		size_type read(char* buf, size_type num_bytes)
		{
			assert(m_open_mode == mode_in);
			assert(m_fd != -1);

			size_type ret = ::read(m_fd, buf, num_bytes);
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "read failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type write(const char* buf, size_type num_bytes)
		{
			assert(m_open_mode == mode_out);
			assert(m_fd != -1);

			size_type ret = ::write(m_fd, buf, num_bytes);
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "write failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		void seek(size_type offset, int m)
		{
			assert(m_open_mode);
			assert(m_fd != -1);

			int seekdir = (m == 1)?SEEK_SET:SEEK_END;
#ifdef WIN32
			size_type ret = _lseeki64(m_fd, offset, seekdir);
#else
			size_type ret = lseek(m_fd, offset, seekdir);
#endif

			// For some strange reason this fails
			// on win32. Use windows specific file
			// wrapper instead.
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "seek failed: '" << strerror(errno)
					<< "' fd: " << m_fd
					<< " offset: " << offset
					<< " seekdir: " << seekdir;
				throw file_error(msg.str());
			}

		}

		size_type tell()
		{
			assert(m_open_mode);
			assert(m_fd != -1);

#ifdef WIN32
			return _telli64(m_fd);
#else
			return lseek(m_fd, 0, SEEK_CUR);
#endif
		}

		int m_fd;
		int m_open_mode;
	};

	// pimpl forwardings

	file::file() : m_impl(new impl()) {}

	file::file(boost::filesystem::path const& p, file::open_mode m)
		: m_impl(new impl(p, m.m_mask))
	{}

	file::~file() {}

	void file::open(boost::filesystem::path const& p, file::open_mode m)
	{
		m_impl->open(p, m.m_mask);
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buf, size_type num_bytes)
	{
		return m_impl->write(buf, num_bytes);
	}

	size_type file::read(char* buf, size_type num_bytes)
	{
		return m_impl->read(buf, num_bytes);
	}

	void file::seek(size_type pos, file::seek_mode m)
	{
		m_impl->seek(pos, m.m_val);
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}

}
<commit_msg>*** empty log message ***<commit_after>/*

Copyright (c) 2003, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include <boost/filesystem/operations.hpp>
#include "libtorrent/file.hpp"
#include <sstream>

#ifdef WIN32

#include <io.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#ifndef _MODE_T_
typedef int mode_t;
#endif

#else

#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>

#endif

#ifndef O_BINARY
#define O_BINARY 0
#endif

#ifndef O_RANDOM
#define O_RANDOM 0
#endif

namespace fs = boost::filesystem;

namespace
{
	enum { mode_in = 1, mode_out = 2 };

	mode_t map_open_mode(int m)
	{
//		if (m == (mode_in | mode_out)) return O_RDWR | O_BINARY;
		if (m == mode_out) return O_WRONLY | O_CREAT | O_BINARY | O_RANDOM;
		if (m == mode_in) return O_RDONLY | O_BINARY | O_RANDOM;
		assert(false);
		return 0;
	}
}

namespace libtorrent
{

	const file::open_mode file::in(mode_in);
	const file::open_mode file::out(mode_out);

	const file::seek_mode file::begin(1);
	const file::seek_mode file::end(2);

	struct file::impl
	{
		impl()
			: m_fd(-1)
			, m_open_mode(0)
		{}

		impl(fs::path const& path, int mode)
			: m_fd(-1)
			, m_open_mode(0)
		{
			open(path, mode);
		}

		~impl()
		{
			close();
		}

		void open(fs::path const& path, int mode)
		{
			close();
			m_fd = ::open(
				path.native_file_string().c_str()
				, map_open_mode(mode)
				, S_IREAD | S_IWRITE);
			if (m_fd == -1)
			{
				std::stringstream msg;
				msg << "open failed: '" << path.native_file_string() << "'. "
					<< strerror(errno);
				throw file_error(msg.str());
			}
			m_open_mode = mode;
		}

		void close()
		{
			if (m_fd == -1) return;

			std::stringstream str;
			str << "fd: " << m_fd << "\n";

			::close(m_fd);
			m_fd = -1;
			m_open_mode = 0;
		}

		size_type read(char* buf, size_type num_bytes)
		{
			assert(m_open_mode == mode_in);
			assert(m_fd != -1);

			size_type ret = ::read(m_fd, buf, num_bytes);
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "read failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		size_type write(const char* buf, size_type num_bytes)
		{
			assert(m_open_mode == mode_out);
			assert(m_fd != -1);

			size_type ret = ::write(m_fd, buf, num_bytes);
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "write failed: " << strerror(errno);
				throw file_error(msg.str());
			}
			return ret;
		}

		void seek(size_type offset, int m)
		{
			assert(m_open_mode);
			assert(m_fd != -1);

			int seekdir = (m == 1)?SEEK_SET:SEEK_END;
#ifdef WIN32
			size_type ret = _lseeki64(m_fd, offset, seekdir);
#else
			size_type ret = lseek(m_fd, offset, seekdir);
#endif

			// For some strange reason this fails
			// on win32. Use windows specific file
			// wrapper instead.
			if (ret == -1)
			{
				std::stringstream msg;
				msg << "seek failed: '" << strerror(errno)
					<< "' fd: " << m_fd
					<< " offset: " << offset
					<< " seekdir: " << seekdir;
				throw file_error(msg.str());
			}

		}

		size_type tell()
		{
			assert(m_open_mode);
			assert(m_fd != -1);

#ifdef WIN32
			return _telli64(m_fd);
#else
			return lseek(m_fd, 0, SEEK_CUR);
#endif
		}

		int m_fd;
		int m_open_mode;
	};

	// pimpl forwardings

	file::file() : m_impl(new impl()) {}

	file::file(boost::filesystem::path const& p, file::open_mode m)
		: m_impl(new impl(p, m.m_mask))
	{}

	file::~file() {}

	void file::open(boost::filesystem::path const& p, file::open_mode m)
	{
		m_impl->open(p, m.m_mask);
	}

	void file::close()
	{
		m_impl->close();
	}

	size_type file::write(const char* buf, size_type num_bytes)
	{
		return m_impl->write(buf, num_bytes);
	}

	size_type file::read(char* buf, size_type num_bytes)
	{
		return m_impl->read(buf, num_bytes);
	}

	void file::seek(size_type pos, file::seek_mode m)
	{
		m_impl->seek(pos, m.m_val);
	}

	size_type file::tell()
	{
		return m_impl->tell();
	}

}
<|endoftext|>


<commit_before>/*!
 *  @file File game.cpp
 *  @brief Implementation of the class of game actions
 *
 *  The class implemented provides the flow of the game
 *
 *  @sa game.hpp
 *
 *  @warning All variables are initialized
 */

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL_ttf.h>

#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <functional>
#include <map>
#include <vector>

#include <game.hpp>
#include <gameException.hpp>
#include <inputManager.hpp>
#include <resources.hpp>
#include <state.hpp>

Game* Game::instance = NULL;

/*!
	@fn Game::Game(string title,int width,int height):frameStart{0},dt{0},winSize{(float)width,(float)height}
	@brief This is a constructor
	@param title
	@param width
	@param height
	@warning Method that requires review of comment
*/

Game::Game(string title, int width, int height):frameStart{0},deltatime{0},windowSize{
																												(float)width,(float)height} {

	srand(time(NULL));

	if (instance) {

		cerr << "Erro, mais de uma instancia de 'Game' instanciada, o programa ira encerrar agora" << endl;

		exit(EXIT_FAILURE);
	}
	else {
		//Nothing to do
	}

	instance = this;

	// Check all SDL outputs and if can't be initialize display a error messege
	bool success = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) == 0;

	if (!success) {

		string error_msg(error_messege = SDL_GetError());
		error_messege = "Could not initialize SDL:\n" + error_messege;

		throw GameException(error_messege);
	}

	// Initialize image module and check if process went OK

	map<int, string> code_name_map = {{IMAGE_INIT_TIF, "tif"},
									  {IMAGE_INIT_JPG, "jpg"},
									  {IMAGE_INIT_PNG, "png"}};

	vector<int> image_formats{IMAGE_INIT_TIF, IMAGE_INIT_JPG, IMAGE_INIT_PNG};

	// Initialize image module or between all desired formats

	int image_settings = accumulate(image_formats.begin(),
									image_formats.end(),
									0,
									[](const int &a, const int &b) {
										return a | b;
									}
	);

	int res = IMAGE_Init(image_settings);

	/* Check the possibility initialize image library and return the error messege
	   for ever type
	 */

	if (image_settings != res) {

		string error_messege_main = SDL_GetError();
		string error_messege = "Could not initiazlie image libary for type:";

		for (auto format : image_formats)
			if ((format & res) == 0) {
				error_messege += code_name_map[format];
			}

		error_messege += "\n";
		error_messege = error_messege_main + error_messege;

		throw GameException(error_messege);
	}

	int audio_modules = MIX_INIT_OGG;
	res = Mix_Init(audio_modules);

	/* Check the possibility initiation of SDL audio and return a error messege
		 if its necessary
	 */

	if (res != audio_modules) {

		if ((MIX_INIT_OGG & res ) == 0 ){
			cerr << "OGG flag not in res!" << endl;
		}

		if ((MIX_INIT_MP3 & res ) == 0 ){
			cerr << "MP3 flag not in res!" << endl;
		}

		throw GameException("Problem when initiating SDL audio!");

	}

	res = Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 1024);

	if (res != 0){
		throw GameException("Problem when initiating SDL audio!");
	}

	res = TTF_Init();

	if (res != 0){
		cerr << "Could not initialize TTF module!" << endl;
	}

	// Creating the window that will contain the game interface

	window = SDL_CreateWindow(title.c_str(),
														SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
														width, height, SDL_WINDOW_FULLSCREEN);

	if (!window){
		throw GameException("Window nao foi carregada)!");
	}

	renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);

	if (!renderer){
		throw GameException("Erro ao instanciar renderizador da SDL!");
	}

	storedState = nullptr;

	SDL_SetRenderDrawBlendMode(GAMERENDER, SDL_BLENDMODE_BLEND);

};

/*!
	@fn Game::~Game()
	@brief This is a destructor
	@warning Method that requires review of comment
*/

Game::~Game() {

	while (stateStack.size()) {
		delete stateStack.top().get();
		stateStack.pop();
	}

	if (storedState) {
		delete storedState;
	}

	Resources::ClearImages();
	Resources::ClearMusics();
	Resources::ClearFonts();

	TTF_Quit();

	Mix_CloseAudio();
	Mix_Quit();

	IMAGE_Quit();

	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
	SDL_Quit();

}

/*!
	@fn Game& Game::GetInstance()
	@brief Create a instance of class Game
	@return Returns a instance of Game
	@warning Method that requires review of comment
*/

Game& Game::GetInstance() {
	return (*instance);
}

/*!
	@fn State& Game::GetCurrentState()
	@brief Verify the current object state
	@return state
	@warning Method that requires review of comment
*/

State& Game::GetCurrentState() {
	return (*stateStack.top());
}

/*!
	@fn void Game::Run()
	@brief
	@param
	@return
	@warning Method that requires review of comment
*/

SDL_Renderer* Game::GetRenderer() {
	return renderer;
}

/*!
	@fn void Game::Push(State* state)
	@brief Swapping the object state
	@param state
	@return The execution of this method returns no value
	@warning Method that requires review of comment
*/

void Game::Push(State* state) {

	if (storedState){
		delete storedState;
	}

	storedState=state;
}

/*!
	@fn void Game::Run()
	@brief
	@param
	@return The execution of this method returns no value
	@warning Method that requires review of comment
*/

void Game::Run() {

	if (storedState) {

		stateStack.push(unique_ptr<State>(storedState));
		storedState=nullptr;

		GetCurrentState().Begin();
	}

	while (!stateStack.empty()) {
		CalculateDeltaTime();

		// Update the state of the game elements and set it

		INPUT.input_event_handler(deltatime);
		//if (INPUT.KeyPress(KEY_F(11))) SwitchWindowMode();

		GetCurrentState().update(deltatime);
		GetCurrentState().render();

		SDL_RenderPresent(renderer);

		if (GetCurrentState().get_quit_requested()) {
				break;
		}

		/* If the user press Pause button the system change the status to paused
			or press End button stop the game and reset
			*/
		if (GetCurrentState().PopRequested()) {
			GetCurrentState().Pause();
			GetCurrentState().End();
			stateStack.pop();

			Resources::game_clear_images();
			Resources::game_clear_musics();
			Resources::game_clear_fonts();

			if (stateStack.size()) {
				GetCurrentState().Resume();
			}

		}

		if (storedState) {
			GetCurrentState().Pause();
			stateStack.push(unique_ptr<State>(storedState));
			storedState=nullptr;
			GetCurrentState().Begin();
		}

		SDL_Delay(17);
	}

	while (stateStack.size()) {
		GetCurrentState().End();
		stateStack.pop();
	}
}

float Game::GetDeltaTime() {
	return deltatime;
}

/*!
	@fn void Game::CalculateDeltaTime()
	@brief
	@return The execution of this method returns no value
	@warning Method that requires review of comment
*/

void Game::CalculateDeltaTime() {

	unsigned int tmp = frameStart;

	//Define the response time of a frame
	frameStart = SDL_GetTicks();
	deltatime = max((frameStart - tmp) / 1000.0, 0.001);
}

/*!
	@fn void Game::SwitchWindowMode()
	@brief
	@return The execution of this method returns no value
	@warning Method that requires review of comment
*/

void Game::SwitchWindowMode() {
	// Method body its empty
}
<commit_msg>Inserting elses in game.cpp<commit_after>/*!
 *  @file File game.cpp
 *  @brief Implementation of the class of game actions
 *
 *  The class implemented provides the flow of the game
 *
 *  @sa game.hpp
 *
 *  @warning All variables are initialized
 */

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL_ttf.h>

#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <functional>
#include <map>
#include <vector>

#include <game.hpp>
#include <gameException.hpp>
#include <inputManager.hpp>
#include <resources.hpp>
#include <state.hpp>

Game* Game::instance = NULL;

/*!
	@fn Game::Game(string title,int width,int height):frameStart{0},dt{0},winSize{(float)width,(float)height}
	@brief This is a constructor
	@param title
	@param width
	@param height
	@warning Method that requires review of comment
*/

Game::Game(string title, int width, int height):frameStart{0},deltatime{0},windowSize{
																												(float)width,(float)height} {

	srand(time(NULL));

	if (instance) {

		cerr << "Erro, mais de uma instancia de 'Game' instanciada, o programa ira encerrar agora" << endl;

		exit(EXIT_FAILURE);
	}
	else {
		//Nothing to do
	}

	instance = this;

	// Check all SDL outputs and if can't be initialize display a error messege
	bool success = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) == 0;

	if (!success) {

		string error_msg(error_messege = SDL_GetError());
		error_messege = "Could not initialize SDL:\n" + error_messege;

		throw GameException(error_messege);
	}
	else {
		//Nothing to do
	}

	// Initialize image module and check if process went OK

	map<int, string> code_name_map = {{IMAGE_INIT_TIF, "tif"},
									  {IMAGE_INIT_JPG, "jpg"},
									  {IMAGE_INIT_PNG, "png"}};

	vector<int> image_formats{IMAGE_INIT_TIF, IMAGE_INIT_JPG, IMAGE_INIT_PNG};

	// Initialize image module or between all desired formats

	int image_settings = accumulate(image_formats.begin(),
									image_formats.end(),
									0,
									[](const int &a, const int &b) {
										return a | b;
									}
	);

	int res = IMAGE_Init(image_settings);

	/* Check the possibility initialize image library and return the error messege
	   for ever type
	 */

	if (image_settings != res) {

		string error_messege_main = SDL_GetError();
		string error_messege = "Could not initiazlie image libary for type:";

		for (auto format : image_formats) {
			if ((format & res) == 0) {
				error_messege += code_name_map[format];
			}
			else {
				//Nothing to do
			}
		}

		error_messege += "\n";
		error_messege = error_messege_main + error_messege;

		throw GameException(error_messege);
	}
	else {
		//Nothing to do
	}

	int audio_modules = MIX_INIT_OGG;

	res = Mix_Init(audio_modules);

	/* Check the possibility initiation of SDL audio and return a error messege
		 if its necessary
	 */

	if (res != audio_modules) {

		throw GameException("Problem when initiating SDL audio!");

		if ((MIX_INIT_OGG & res ) == 0 ){
			cerr << "OGG flag not in res!" << endl;
		}
		else {
			//Nothing to do
		}

		if ((MIX_INIT_MP3 & res ) == 0 ){
			cerr << "MP3 flag not in res!" << endl;
		}

	}

	res = Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 1024);

	if (res != 0){
		throw GameException("Problem when initiating SDL audio!");
	}

	res = TTF_Init();

	if (res != 0){
		cerr << "Could not initialize TTF module!" << endl;
	}

	// Creating the window that will contain the game interface

	window = SDL_CreateWindow(title.c_str(),
														SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
														width, height, SDL_WINDOW_FULLSCREEN);

	if (!window){
		throw GameException("Window nao foi carregada)!");
	}

	renderer = SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED);

	if (!renderer){
		throw GameException("Erro ao instanciar renderizador da SDL!");
	}

	storedState = nullptr;

	SDL_SetRenderDrawBlendMode(GAMERENDER, SDL_BLENDMODE_BLEND);

};

/*!
	@fn Game::~Game()
	@brief This is a destructor
	@warning Method that requires review of comment
*/

Game::~Game() {

	while (stateStack.size()) {
		delete stateStack.top().get();
		stateStack.pop();
	}

	if (storedState) {
		delete storedState;
	}

	Resources::ClearImages();
	Resources::ClearMusics();
	Resources::ClearFonts();

	TTF_Quit();

	Mix_CloseAudio();
	Mix_Quit();

	IMAGE_Quit();

	SDL_DestroyRenderer(renderer);
	SDL_DestroyWindow(window);
	SDL_Quit();

}

/*!
	@fn Game& Game::GetInstance()
	@brief Create a instance of class Game
	@return Returns a instance of Game
	@warning Method that requires review of comment
*/

Game& Game::GetInstance() {
	return (*instance);
}

/*!
	@fn State& Game::GetCurrentState()
	@brief Verify the current object state
	@return state
	@warning Method that requires review of comment
*/

State& Game::GetCurrentState() {
	return (*stateStack.top());
}

/*!
	@fn void Game::Run()
	@brief
	@param
	@return
	@warning Method that requires review of comment
*/

SDL_Renderer* Game::GetRenderer() {
	return renderer;
}

/*!
	@fn void Game::Push(State* state)
	@brief Swapping the object state
	@param state
	@return The execution of this method returns no value
	@warning Method that requires review of comment
*/

void Game::Push(State* state) {

	if (storedState){
		delete storedState;
	}

	storedState=state;
}

/*!
	@fn void Game::Run()
	@brief
	@param
	@return The execution of this method returns no value
	@warning Method that requires review of comment
*/

void Game::Run() {

	if (storedState) {

		stateStack.push(unique_ptr<State>(storedState));
		storedState=nullptr;

		GetCurrentState().Begin();
	}

	while (!stateStack.empty()) {
		CalculateDeltaTime();

		// Update the state of the game elements and set it

		INPUT.input_event_handler(deltatime);
		//if (INPUT.KeyPress(KEY_F(11))) SwitchWindowMode();

		GetCurrentState().update(deltatime);
		GetCurrentState().render();

		SDL_RenderPresent(renderer);

		if (GetCurrentState().get_quit_requested()) {
				break;
		}

		/* If the user press Pause button the system change the status to paused
			or press End button stop the game and reset
			*/
		if (GetCurrentState().PopRequested()) {
			GetCurrentState().Pause();
			GetCurrentState().End();
			stateStack.pop();

			Resources::game_clear_images();
			Resources::game_clear_musics();
			Resources::game_clear_fonts();

			if (stateStack.size()) {
				GetCurrentState().Resume();
			}

		}

		if (storedState) {
			GetCurrentState().Pause();
			stateStack.push(unique_ptr<State>(storedState));
			storedState=nullptr;
			GetCurrentState().Begin();
		}

		SDL_Delay(17);
	}

	while (stateStack.size()) {
		GetCurrentState().End();
		stateStack.pop();
	}
}

float Game::GetDeltaTime() {
	return deltatime;
}

/*!
	@fn void Game::CalculateDeltaTime()
	@brief
	@return The execution of this method returns no value
	@warning Method that requires review of comment
*/

void Game::CalculateDeltaTime() {

	unsigned int tmp = frameStart;

	//Define the response time of a frame
	frameStart = SDL_GetTicks();
	deltatime = max((frameStart - tmp) / 1000.0, 0.001);
}

/*!
	@fn void Game::SwitchWindowMode()
	@brief
	@return The execution of this method returns no value
	@warning Method that requires review of comment
*/

void Game::SwitchWindowMode() {
	// Method body its empty
}
<|endoftext|>


<commit_before>//
// Created by Artur Troian on 1/21/17.
//

#include <jwtpp/crypto.hpp>

#include <openssl/hmac.h>

#include <jwtpp/b64.hpp>

namespace jwt {

hmac::hmac(jwt::alg alg, const std::string &secret) :
	  crypto(alg)
	, secret_(secret)
{
	if (alg != jwt::alg::HS256 && alg != jwt::alg::HS384 && alg != jwt::alg::HS512) {
		throw std::invalid_argument("Invalid algorithm");
	}

	if (secret.empty()) {
		throw std::invalid_argument("Invalid secret");
	}
}

hmac::~hmac()
{
	// clear out secret
	std::memset((void *)secret_.data(), 0 , secret_.length());
}

std::string hmac::sign(const std::string &data)
{
	if (data.empty()) {
		throw std::invalid_argument("Data is empty");
	}

	std::string sig;

	const EVP_MD *alg;

	switch (alg_) {
	case jwt::alg::HS256:
		alg = EVP_sha256();
		break;
	case jwt::alg::HS384:
		alg = EVP_sha384();
		break;
	case jwt::alg::HS512:
		alg = EVP_sha512();
		break;
	default:
		// Should never happen
		throw std::runtime_error("Invalid alg");
	}

	uint32_t size;

	HMAC(alg, secret_.data(), secret_.length(), (const uint8_t *) data.c_str(), data.size(), nullptr, &size);

	std::shared_ptr<uint8_t> res = std::shared_ptr<uint8_t>(new uint8_t[size], std::default_delete<uint8_t[]>());

	HMAC(alg, secret_.data(), secret_.length(), (const uint8_t *) data.c_str(), data.size(), res.get(), &size);

	b64::encode(sig, res.get(), size);

	return sig;
}

bool hmac::verify(const std::string &data, const std::string &sig)
{
	return sig == sign(data);
}

} // namespace jwt
<commit_msg>Fix memset for linux gcc<commit_after>//
// Created by Artur Troian on 1/21/17.
//

#include <cstring>

#include <jwtpp/crypto.hpp>

#include <openssl/hmac.h>

#include <jwtpp/b64.hpp>

namespace jwt {

hmac::hmac(jwt::alg alg, const std::string &secret) :
	  crypto(alg)
	, secret_(secret)
{
	if (alg != jwt::alg::HS256 && alg != jwt::alg::HS384 && alg != jwt::alg::HS512) {
		throw std::invalid_argument("Invalid algorithm");
	}

	if (secret.empty()) {
		throw std::invalid_argument("Invalid secret");
	}
}

hmac::~hmac()
{
	// clear out secret
	std::memset((void *)secret_.data(), 0 , secret_.length());
}

std::string hmac::sign(const std::string &data)
{
	if (data.empty()) {
		throw std::invalid_argument("Data is empty");
	}

	std::string sig;

	const EVP_MD *alg;

	switch (alg_) {
	case jwt::alg::HS256:
		alg = EVP_sha256();
		break;
	case jwt::alg::HS384:
		alg = EVP_sha384();
		break;
	case jwt::alg::HS512:
		alg = EVP_sha512();
		break;
	default:
		// Should never happen
		throw std::runtime_error("Invalid alg");
	}

	uint32_t size;

	HMAC(alg, secret_.data(), secret_.length(), (const uint8_t *) data.c_str(), data.size(), nullptr, &size);

	std::shared_ptr<uint8_t> res = std::shared_ptr<uint8_t>(new uint8_t[size], std::default_delete<uint8_t[]>());

	HMAC(alg, secret_.data(), secret_.length(), (const uint8_t *) data.c_str(), data.size(), res.get(), &size);

	b64::encode(sig, res.get(), size);

	return sig;
}

bool hmac::verify(const std::string &data, const std::string &sig)
{
	return sig == sign(data);
}

} // namespace jwt
<|endoftext|>


<commit_before>#include "html.h"
#include "types.h"
#include "html_tag.h"

void litehtml::trim(tstring &s)
{
	tstring::size_type pos = s.find_first_not_of(_t(" \n\r\t"));
	if(pos != tstring::npos)
	{
		s.erase(s.begin(), s.begin() + pos);
	}
	pos = s.find_last_not_of(_t(" \n\r\t"));
	if(pos != tstring::npos)
	{
		s.erase(s.begin() + pos + 1, s.end());
	}
}

void litehtml::lcase(tstring &s)
{
	for(tstring::iterator i = s.begin(); i != s.end(); i++)
	{
		(*i) = t_tolower(*i);
	}
}

litehtml::tstring::size_type litehtml::find_close_bracket(const tstring &s, tstring::size_type off, tchar_t open_b, tchar_t close_b)
{
	int cnt = 0;
	for(tstring::size_type i = off; i < s.length(); i++)
	{
		if(s[i] == open_b)
		{
			cnt++;
		} else if(s[i] == close_b)
		{
			cnt--;
			if(!cnt)
			{
				return i;
			}
		}
	}
	return tstring::npos;
}

int litehtml::value_index( const tstring& val, const tstring& strings, int defValue, tchar_t delim )
{
	if(val.empty() || strings.empty() || !delim)
	{
		return defValue;
	}

	int idx = 0;
	tstring::size_type delim_start	= 0;
	tstring::size_type delim_end	= strings.find(delim, delim_start);
	tstring::size_type item_len		= 0;
	while(true)
	{
		if(delim_end == tstring::npos)
		{
			item_len = strings.length() - delim_start;
		} else
		{
			item_len = delim_end - delim_start;
		}
		if(item_len == val.length())
		{
			if(val == strings.substr(delim_start, item_len))
			{
				return idx;
			}
		}
		idx++;
		delim_start = delim_end;
		if(delim_start == tstring::npos) break;
		delim_start++;
		if(delim_start == strings.length()) break;
		delim_end = strings.find(delim, delim_start);
	}
	return defValue;
}

bool litehtml::value_in_list( const tstring& val, const tstring& strings, tchar_t delim )
{
	int idx = value_index(val, strings, -1, delim);
	if(idx >= 0)
	{
		return true;
	}
	return false;
}

void litehtml::split_string(const tstring& str, string_vector& tokens, const tstring& delims, const tstring& delims_preserve, const tstring& quote)
{
	if(str.empty() || (delims.empty() && delims_preserve.empty()))
	{
		return;
	}

	tstring all_delims = delims + delims_preserve + quote;

	tstring::size_type token_start	= 0;
	tstring::size_type token_end	= str.find_first_of(all_delims, token_start);
	tstring::size_type token_len	= 0;
	tstring token;
	while(true)
	{
		while( token_end != tstring::npos && quote.find_first_of(str[token_end]) != tstring::npos )
		{
			if(str[token_end] == _t('('))
			{
				token_end = find_close_bracket(str, token_end, _t('('), _t(')'));
			} else if(str[token_end] == _t('['))
			{
				token_end = find_close_bracket(str, token_end, _t('['), _t(']'));
			} else if(str[token_end] == _t('{'))
			{
				token_end = find_close_bracket(str, token_end, _t('{'), _t('}'));
			} else
			{
				token_end = str.find_first_of(str[token_end], token_end + 1);
			}
			if(token_end != tstring::npos)
			{
				token_end = str.find_first_of(all_delims, token_end + 1);
			}
		}

		if(token_end == tstring::npos)
		{
			token_len = tstring::npos;
		} else
		{
			token_len = token_end - token_start;
		}

		token = str.substr(token_start, token_len);
		if(!token.empty())
		{
			tokens.push_back( token );
		}
		if(token_end != tstring::npos && !delims_preserve.empty() && delims_preserve.find_first_of(str[token_end]) != tstring::npos)
		{
			tokens.push_back( str.substr(token_end, 1) );
		}

		token_start = token_end;
		if(token_start == tstring::npos) break;
		token_start++;
		if(token_start == str.length()) break;
		token_end = str.find_first_of(all_delims, token_start);
	}
}

void litehtml::join_string(tstring& str, const string_vector& tokens, const tstring& delims)
{
	tstringstream ss;
	for(size_t i=0; i<tokens.size(); ++i)
	{
		if(i != 0)
		{
			ss << delims;
		}
		ss << tokens[i];
	}

	str = ss.str();
}
<commit_msg>Custom 'strtod' implementation.<commit_after>#include "html.h"
#include "types.h"
#include "html_tag.h"

void litehtml::trim(tstring &s)
{
	tstring::size_type pos = s.find_first_not_of(_t(" \n\r\t"));
	if(pos != tstring::npos)
	{
		s.erase(s.begin(), s.begin() + pos);
	}
	pos = s.find_last_not_of(_t(" \n\r\t"));
	if(pos != tstring::npos)
	{
		s.erase(s.begin() + pos + 1, s.end());
	}
}

void litehtml::lcase(tstring &s)
{
	for(tstring::iterator i = s.begin(); i != s.end(); i++)
	{
		(*i) = t_tolower(*i);
	}
}

litehtml::tstring::size_type litehtml::find_close_bracket(const tstring &s, tstring::size_type off, tchar_t open_b, tchar_t close_b)
{
	int cnt = 0;
	for(tstring::size_type i = off; i < s.length(); i++)
	{
		if(s[i] == open_b)
		{
			cnt++;
		} else if(s[i] == close_b)
		{
			cnt--;
			if(!cnt)
			{
				return i;
			}
		}
	}
	return tstring::npos;
}

int litehtml::value_index( const tstring& val, const tstring& strings, int defValue, tchar_t delim )
{
	if(val.empty() || strings.empty() || !delim)
	{
		return defValue;
	}

	int idx = 0;
	tstring::size_type delim_start	= 0;
	tstring::size_type delim_end	= strings.find(delim, delim_start);
	tstring::size_type item_len		= 0;
	while(true)
	{
		if(delim_end == tstring::npos)
		{
			item_len = strings.length() - delim_start;
		} else
		{
			item_len = delim_end - delim_start;
		}
		if(item_len == val.length())
		{
			if(val == strings.substr(delim_start, item_len))
			{
				return idx;
			}
		}
		idx++;
		delim_start = delim_end;
		if(delim_start == tstring::npos) break;
		delim_start++;
		if(delim_start == strings.length()) break;
		delim_end = strings.find(delim, delim_start);
	}
	return defValue;
}

bool litehtml::value_in_list( const tstring& val, const tstring& strings, tchar_t delim )
{
	int idx = value_index(val, strings, -1, delim);
	if(idx >= 0)
	{
		return true;
	}
	return false;
}

void litehtml::split_string(const tstring& str, string_vector& tokens, const tstring& delims, const tstring& delims_preserve, const tstring& quote)
{
	if(str.empty() || (delims.empty() && delims_preserve.empty()))
	{
		return;
	}

	tstring all_delims = delims + delims_preserve + quote;

	tstring::size_type token_start	= 0;
	tstring::size_type token_end	= str.find_first_of(all_delims, token_start);
	tstring::size_type token_len	= 0;
	tstring token;
	while(true)
	{
		while( token_end != tstring::npos && quote.find_first_of(str[token_end]) != tstring::npos )
		{
			if(str[token_end] == _t('('))
			{
				token_end = find_close_bracket(str, token_end, _t('('), _t(')'));
			} else if(str[token_end] == _t('['))
			{
				token_end = find_close_bracket(str, token_end, _t('['), _t(']'));
			} else if(str[token_end] == _t('{'))
			{
				token_end = find_close_bracket(str, token_end, _t('{'), _t('}'));
			} else
			{
				token_end = str.find_first_of(str[token_end], token_end + 1);
			}
			if(token_end != tstring::npos)
			{
				token_end = str.find_first_of(all_delims, token_end + 1);
			}
		}

		if(token_end == tstring::npos)
		{
			token_len = tstring::npos;
		} else
		{
			token_len = token_end - token_start;
		}

		token = str.substr(token_start, token_len);
		if(!token.empty())
		{
			tokens.push_back( token );
		}
		if(token_end != tstring::npos && !delims_preserve.empty() && delims_preserve.find_first_of(str[token_end]) != tstring::npos)
		{
			tokens.push_back( str.substr(token_end, 1) );
		}

		token_start = token_end;
		if(token_start == tstring::npos) break;
		token_start++;
		if(token_start == str.length()) break;
		token_end = str.find_first_of(all_delims, token_start);
	}
}

void litehtml::join_string(tstring& str, const string_vector& tokens, const tstring& delims)
{
	tstringstream ss;
	for(size_t i=0; i<tokens.size(); ++i)
	{
		if(i != 0)
		{
			ss << delims;
		}
		ss << tokens[i];
	}

	str = ss.str();
}

double litehtml::strtod(const char *nptr, char **endptr)
{
	tstring num;
	tstring dec;
	const char *p;
	double val = 0;
	bool neg;
	double f;
	int i;

	p = nptr;

	if (*p == '+')
	{
		neg = false;
		p++;
	}
	else if (*p == '-')
	{
		neg = true;
		p++;
	}

	while (*p)
	{
		if (*p == '.' || !t_isdigit(*p))
			break;
		num += *p++;
	}

	f = 1.0;
	for (i = num.length() - 1; i >= 0; i--)
	{
		val += (num[i] - '0') * f;
		f *= 10.0;
	}

	if (*p == '.')
	{
		p++;
		while(*p)
		{
			if (!t_isdigit(*p))
				break;
			dec += *p++;
		}

		f = 1.0;
		for (i = 0; i < dec.length(); i++)
		{
			f /= 10.0;
			val += (dec[i] - '0') * f;
		}
	}

	if (endptr)
		*endptr = (char *)p;

	return neg ? (-val) : val;
}
<|endoftext|>


<commit_before>#include"ics3/ics3.hpp"

#include"core.hpp"
#include"ics3/eeprom.hpp"
#include"ics3/parameter.hpp"
#include"ics3/id.hpp"

static inline ics::Angle::rawType getReceiveAngle(const ics::Core::Container& rx) noexcept {
  return static_cast<ics::Angle::rawType>((rx[4] << 7) | rx[5]);
}

ics::ICS3::ICS3(const std::string& path, const Baudrate& baudrate)
: core {Core::getCore(path, baudrate.getSpeed())}
{}

ics::Angle ics::ICS3::move(const ID& id, Angle angle) {
  static Core::Container tx(3), rx(6); // cache for runtime speed
  const uint16_t send {angle.getRaw()};
  tx[0] = 0x80 | id.get();
  tx[1] = 0x7F & (send >> 7);
  tx[2] = 0x7F & send;
  core->communicate(tx, rx); // throw std::runtime_error
  angle.rawData = getReceiveAngle(rx); // avoid invalid check. need friend
  return angle;
}

ics::Angle ics::ICS3::free(const ID& id, Angle unit) {
  static Core::Container tx(3), rx(6); // cache for runtime speed
  tx[0] = 0x80 | id.get(); // tx[1] == tx[2] == 0
  core->communicate(tx, rx); // throw std::runtime_error
  unit.rawData = getReceiveAngle(rx); // avoid invalid check. need friend
  return unit;
}

ics::Parameter ics::ICS3::get(const ID& id, const Parameter& type) {
  Core::Container tx(2), rx(5);
  tx[0] = 0xA0 | id.get();
  tx[1] = type.getSubcommand();
  core->communicate(tx, rx); // throw std::runtime_error
  return Parameter::newParameter(type, rx[4]);
}

void ics::ICS3::set(const ID& id, const Parameter& param) {
  Core::Container tx(3), rx(6);
  tx[0] = 0xC0 | id.get();
  tx[1] = param.getSubcommand();
  tx[2] = param.get();
  core->communicate(tx, rx); // throw std::runtime_error
}

ics::EepRom ics::ICS3::getRom(const ID& id) {
  Core::Container tx(2), rx(68);
  tx[0] = 0xA0 | id.get(); // tx[1] == 0
  core->communicate(tx, rx); // throw std::runtime_error
  std::array<uint8_t, 64> romData;
  std::copy(rx.cbegin() + 4, rx.cend(), romData.begin());
  return EepRom {romData}; // need friend
}

void ics::ICS3::setRom(const ID& id, const EepRom& rom) {
  Core::Container tx(66), rx(68);
  tx[0] = 0xC0 | id.get(); // tx[1] == 0
  rom.write(tx.begin() + 2);
  core->communicate(tx, rx); // throw std::runtime_error
}

ics::ID ics::ICS3::getID() {
  const Core::IDContainerTx tx {0xFF, 0x00, 0x00, 0x00};
  Core::IDContainerRx rx;
  core->communicateID(tx, rx);
  return ID {static_cast<uint8_t>(0x1F & rx[4])};
}

void ics::ICS3::setID(const ID& id) {
  auto cmd = static_cast<Core::value>(0xE0 | id.get());
  const Core::IDContainerTx tx {cmd, 1, 1, 1};
  Core::IDContainerRx rx;
  core->communicateID(tx, rx);
}
<commit_msg>Use constexpr on array<commit_after>#include"ics3/ics3.hpp"

#include"core.hpp"
#include"ics3/eeprom.hpp"
#include"ics3/parameter.hpp"
#include"ics3/id.hpp"

static inline ics::Angle::rawType getReceiveAngle(const ics::Core::Container& rx) noexcept {
  return static_cast<ics::Angle::rawType>((rx[4] << 7) | rx[5]);
}

ics::ICS3::ICS3(const std::string& path, const Baudrate& baudrate)
: core {Core::getCore(path, baudrate.getSpeed())}
{}

ics::Angle ics::ICS3::move(const ID& id, Angle angle) {
  static Core::Container tx(3), rx(6); // cache for runtime speed
  const uint16_t send {angle.getRaw()};
  tx[0] = 0x80 | id.get();
  tx[1] = 0x7F & (send >> 7);
  tx[2] = 0x7F & send;
  core->communicate(tx, rx); // throw std::runtime_error
  angle.rawData = getReceiveAngle(rx); // avoid invalid check. need friend
  return angle;
}

ics::Angle ics::ICS3::free(const ID& id, Angle unit) {
  static Core::Container tx(3), rx(6); // cache for runtime speed
  tx[0] = 0x80 | id.get(); // tx[1] == tx[2] == 0
  core->communicate(tx, rx); // throw std::runtime_error
  unit.rawData = getReceiveAngle(rx); // avoid invalid check. need friend
  return unit;
}

ics::Parameter ics::ICS3::get(const ID& id, const Parameter& type) {
  Core::Container tx(2), rx(5);
  tx[0] = 0xA0 | id.get();
  tx[1] = type.getSubcommand();
  core->communicate(tx, rx); // throw std::runtime_error
  return Parameter::newParameter(type, rx[4]);
}

void ics::ICS3::set(const ID& id, const Parameter& param) {
  Core::Container tx(3), rx(6);
  tx[0] = 0xC0 | id.get();
  tx[1] = param.getSubcommand();
  tx[2] = param.get();
  core->communicate(tx, rx); // throw std::runtime_error
}

ics::EepRom ics::ICS3::getRom(const ID& id) {
  Core::Container tx(2), rx(68);
  tx[0] = 0xA0 | id.get(); // tx[1] == 0
  core->communicate(tx, rx); // throw std::runtime_error
  std::array<uint8_t, 64> romData;
  std::copy(rx.cbegin() + 4, rx.cend(), romData.begin());
  return EepRom {romData}; // need friend
}

void ics::ICS3::setRom(const ID& id, const EepRom& rom) {
  Core::Container tx(66), rx(68);
  tx[0] = 0xC0 | id.get(); // tx[1] == 0
  rom.write(tx.begin() + 2);
  core->communicate(tx, rx); // throw std::runtime_error
}

ics::ID ics::ICS3::getID() {
  constexpr Core::IDContainerTx tx {0xFF, 0x00, 0x00, 0x00};
  Core::IDContainerRx rx;
  core->communicateID(tx, rx);
  return ID {static_cast<uint8_t>(0x1F & rx[4])};
}

void ics::ICS3::setID(const ID& id) {
  auto cmd = static_cast<Core::value>(0xE0 | id.get());
  const Core::IDContainerTx tx {cmd, 1, 1, 1};
  Core::IDContainerRx rx;
  core->communicateID(tx, rx);
}
<|endoftext|>


<commit_before>//===- ICF.cpp ------------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Identical Code Folding is a feature to merge sections not by name (which
// is regular comdat handling) but by contents. If two non-writable sections
// have the same data, relocations, attributes, etc., then the two
// are considered identical and merged by the linker. This optimization
// makes outputs smaller.
//
// ICF is theoretically a problem of reducing graphs by merging as many
// identical subgraphs as possible if we consider sections as vertices and
// relocations as edges. It may sound simple, but it is a bit more
// complicated than you might think. The order of processing sections
// matters because merging two sections can make other sections, whose
// relocations now point to the same section, mergeable. Graphs may contain
// cycles. We need a sophisticated algorithm to do this properly and
// efficiently.
//
// What we do in this file is this. We split sections into groups. Sections
// in the same group are considered identical.
//
// We begin by optimistically putting all sections into a single equivalence
// class. Then we apply a series of checks that split this initial
// equivalence class into more and more refined equivalence classes based on
// the properties by which a section can be distinguished.
//
// We begin by checking that the section contents and flags are the
// same. This only needs to be done once since these properties don't depend
// on the current equivalence class assignment.
//
// Then we split the equivalence classes based on checking that their
// relocations are the same, where relocation targets are compared by their
// equivalence class, not the concrete section. This may need to be done
// multiple times because as the equivalence classes are refined, two
// sections that had a relocation target in the same equivalence class may
// now target different equivalence classes, and hence these two sections
// must be put in different equivalence classes (whereas in the previous
// iteration they were not since the relocation target was the same.)
//
// Our algorithm is smart enough to merge the following mutually-recursive
// functions.
//
//   void foo() { bar(); }
//   void bar() { foo(); }
//
// This algorithm is so-called "optimistic" algorithm described in
// http://research.google.com/pubs/pub36912.html. (Note that what GNU
// gold implemented is different from the optimistic algorithm.)
//
//===----------------------------------------------------------------------===//

#include "ICF.h"
#include "Config.h"
#include "OutputSections.h"
#include "SymbolTable.h"

#include "llvm/ADT/Hashing.h"
#include "llvm/Object/ELF.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>

using namespace lld;
using namespace lld::elf;
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;

namespace lld {
namespace elf {
template <class ELFT> class ICF {
  typedef typename ELFT::Shdr Elf_Shdr;
  typedef typename ELFT::Sym Elf_Sym;
  typedef typename ELFT::uint uintX_t;
  typedef Elf_Rel_Impl<ELFT, false> Elf_Rel;

  using Comparator = std::function<bool(const InputSection<ELFT> *,
                                        const InputSection<ELFT> *)>;

public:
  void run();

private:
  uint64_t NextId = 1;

  static void setLive(SymbolTable<ELFT> *S);
  static uint64_t relSize(InputSection<ELFT> *S);
  static uint64_t getHash(InputSection<ELFT> *S);
  static bool isEligible(InputSectionBase<ELFT> *Sec);
  static std::vector<InputSection<ELFT> *> getSections();

  void segregate(InputSection<ELFT> **Begin, InputSection<ELFT> **End,
                 Comparator Eq);

  void forEachGroup(std::vector<InputSection<ELFT> *> &V, Comparator Eq);

  template <class RelTy>
  static bool relocationEq(ArrayRef<RelTy> RA, ArrayRef<RelTy> RB);

  template <class RelTy>
  static bool variableEq(const InputSection<ELFT> *A, ArrayRef<RelTy> RA,
                         const InputSection<ELFT> *B, ArrayRef<RelTy> RB);

  static bool equalsConstant(const InputSection<ELFT> *A,
                             const InputSection<ELFT> *B);

  static bool equalsVariable(const InputSection<ELFT> *A,
                             const InputSection<ELFT> *B);
};
}
}

// Returns a hash value for S. Note that the information about
// relocation targets is not included in the hash value.
template <class ELFT> uint64_t ICF<ELFT>::getHash(InputSection<ELFT> *S) {
  return hash_combine(S->Flags, S->getSize(), S->NumRelocations);
}

// Returns true if Sec is subject of ICF.
template <class ELFT> bool ICF<ELFT>::isEligible(InputSectionBase<ELFT> *Sec) {
  if (!Sec->Live)
    return false;
  auto *S = dyn_cast<InputSection<ELFT>>(Sec);
  if (!S)
    return false;

  // .init and .fini contains instructions that must be executed to
  // initialize and finalize the process. They cannot and should not
  // be merged.
  StringRef Name = S->Name;
  if (Name == ".init" || Name == ".fini")
    return false;

  return (S->Flags & SHF_ALLOC) && !(S->Flags & SHF_WRITE);
}

template <class ELFT>
std::vector<InputSection<ELFT> *> ICF<ELFT>::getSections() {
  std::vector<InputSection<ELFT> *> V;
  for (InputSectionBase<ELFT> *S : Symtab<ELFT>::X->Sections)
    if (isEligible(S))
      V.push_back(cast<InputSection<ELFT>>(S));
  return V;
}

// All sections between Begin and End must have the same group ID before
// you call this function. This function compare sections between Begin
// and End using Eq and assign new group IDs for new groups.
template <class ELFT>
void ICF<ELFT>::segregate(InputSection<ELFT> **Begin, InputSection<ELFT> **End,
                          Comparator Eq) {
  // This loop rearranges [Begin, End) so that all sections that are
  // equal in terms of Eq are contiguous. The algorithm is quadratic in
  // the worst case, but that is not an issue in practice because the
  // number of distinct sections in [Begin, End) is usually very small.
  InputSection<ELFT> **I = Begin;
  for (;;) {
    InputSection<ELFT> *Head = *I;
    auto Bound = std::stable_partition(
        I + 1, End, [&](InputSection<ELFT> *S) { return Eq(Head, S); });
    if (Bound == End)
      return;
    uint64_t Id = NextId++;
    for (; I != Bound; ++I)
      (*I)->GroupId = Id;
  }
}

template <class ELFT>
void ICF<ELFT>::forEachGroup(std::vector<InputSection<ELFT> *> &V,
                             Comparator Eq) {
  for (InputSection<ELFT> **I = V.data(), **E = I + V.size(); I != E;) {
    InputSection<ELFT> *Head = *I;
    auto Bound = std::find_if(I + 1, E, [&](InputSection<ELFT> *S) {
      return S->GroupId != Head->GroupId;
    });
    segregate(I, Bound, Eq);
    I = Bound;
  }
}

// Compare two lists of relocations.
template <class ELFT>
template <class RelTy>
bool ICF<ELFT>::relocationEq(ArrayRef<RelTy> RelsA, ArrayRef<RelTy> RelsB) {
  auto Eq = [](const RelTy &A, const RelTy &B) {
    return A.r_offset == B.r_offset &&
           A.getType(Config->Mips64EL) == B.getType(Config->Mips64EL) &&
           getAddend<ELFT>(A) == getAddend<ELFT>(B);
  };

  return RelsA.size() == RelsB.size() &&
         std::equal(RelsA.begin(), RelsA.end(), RelsB.begin(), Eq);
}

// Compare "non-moving" part of two InputSections, namely everything
// except relocation targets.
template <class ELFT>
bool ICF<ELFT>::equalsConstant(const InputSection<ELFT> *A,
                               const InputSection<ELFT> *B) {
  if (A->NumRelocations != B->NumRelocations)
    return false;

  if (A->AreRelocsRela) {
    if (!relocationEq(A->relas(), B->relas()))
      return false;
  } else {
    if (!relocationEq(A->rels(), B->rels()))
      return false;
  }

  return A->Flags == B->Flags && A->getSize() == B->getSize() &&
         A->Data == B->Data;
}

template <class ELFT>
template <class RelTy>
bool ICF<ELFT>::variableEq(const InputSection<ELFT> *A, ArrayRef<RelTy> RelsA,
                           const InputSection<ELFT> *B, ArrayRef<RelTy> RelsB) {
  auto Eq = [&](const RelTy &RA, const RelTy &RB) {
    SymbolBody &SA = A->File->getRelocTargetSym(RA);
    SymbolBody &SB = B->File->getRelocTargetSym(RB);
    if (&SA == &SB)
      return true;

    // Or, the symbols should be pointing to the same section
    // in terms of the group ID.
    auto *DA = dyn_cast<DefinedRegular<ELFT>>(&SA);
    auto *DB = dyn_cast<DefinedRegular<ELFT>>(&SB);
    if (!DA || !DB)
      return false;
    if (DA->Value != DB->Value)
      return false;
    InputSection<ELFT> *X = dyn_cast<InputSection<ELFT>>(DA->Section);
    InputSection<ELFT> *Y = dyn_cast<InputSection<ELFT>>(DB->Section);
    return X && Y && X->GroupId && X->GroupId == Y->GroupId;
  };

  return std::equal(RelsA.begin(), RelsA.end(), RelsB.begin(), Eq);
}

// Compare "moving" part of two InputSections, namely relocation targets.
template <class ELFT>
bool ICF<ELFT>::equalsVariable(const InputSection<ELFT> *A,
                               const InputSection<ELFT> *B) {
  if (A->AreRelocsRela)
    return variableEq(A, A->relas(), B, B->relas());
  return variableEq(A, A->rels(), B, B->rels());
}

// The main function of ICF.
template <class ELFT> void ICF<ELFT>::run() {
  // Initially, we use hash values as section group IDs. Therefore,
  // if two sections have the same ID, they are likely (but not
  // guaranteed) to have the same static contents in terms of ICF.
  std::vector<InputSection<ELFT> *> V = getSections();
  for (InputSection<ELFT> *S : V)
    // Set MSB on to avoid collisions with serial group IDs
    S->GroupId = getHash(S) | (uint64_t(1) << 63);

  // From now on, sections in V are ordered so that sections in
  // the same group are consecutive in the vector.
  std::stable_sort(V.begin(), V.end(),
                   [](InputSection<ELFT> *A, InputSection<ELFT> *B) {
                     if (A->GroupId != B->GroupId)
                       return A->GroupId < B->GroupId;
                     // Within a group, put the highest alignment
                     // requirement first, so that's the one we'll keep.
                     return B->Alignment < A->Alignment;
                   });

  // Compare static contents and assign unique IDs for each static content.
  forEachGroup(V, equalsConstant);

  // Split groups by comparing relocations until we get a convergence.
  int Cnt = 1;
  for (;;) {
    ++Cnt;
    uint64_t Id = NextId;
    forEachGroup(V, equalsVariable);
    if (Id == NextId)
      break;
  }
  log("ICF needed " + Twine(Cnt) + " iterations.");

  // Merge sections in the same group.
  for (auto I = V.begin(), E = V.end(); I != E;) {
    InputSection<ELFT> *Head = *I++;
    auto Bound = std::find_if(I, E, [&](InputSection<ELFT> *S) {
      return Head->GroupId != S->GroupId;
    });
    if (I == Bound)
      continue;
    log("selected " + Head->Name);
    while (I != Bound) {
      InputSection<ELFT> *S = *I++;
      log("  removed " + S->Name);
      Head->replace(S);
    }
  }
}

// ICF entry point function.
template <class ELFT> void elf::doIcf() { ICF<ELFT>().run(); }

template void elf::doIcf<ELF32LE>();
template void elf::doIcf<ELF32BE>();
template void elf::doIcf<ELF64LE>();
template void elf::doIcf<ELF64BE>();
<commit_msg>Refactor ICF.<commit_after>//===- ICF.cpp ------------------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Identical Code Folding is a feature to merge sections not by name (which
// is regular comdat handling) but by contents. If two non-writable sections
// have the same data, relocations, attributes, etc., then the two
// are considered identical and merged by the linker. This optimization
// makes outputs smaller.
//
// ICF is theoretically a problem of reducing graphs by merging as many
// identical subgraphs as possible if we consider sections as vertices and
// relocations as edges. It may sound simple, but it is a bit more
// complicated than you might think. The order of processing sections
// matters because merging two sections can make other sections, whose
// relocations now point to the same section, mergeable. Graphs may contain
// cycles. We need a sophisticated algorithm to do this properly and
// efficiently.
//
// What we do in this file is this. We split sections into groups. Sections
// in the same group are considered identical.
//
// We begin by optimistically putting all sections into a single equivalence
// class. Then we apply a series of checks that split this initial
// equivalence class into more and more refined equivalence classes based on
// the properties by which a section can be distinguished.
//
// We begin by checking that the section contents and flags are the
// same. This only needs to be done once since these properties don't depend
// on the current equivalence class assignment.
//
// Then we split the equivalence classes based on checking that their
// relocations are the same, where relocation targets are compared by their
// equivalence class, not the concrete section. This may need to be done
// multiple times because as the equivalence classes are refined, two
// sections that had a relocation target in the same equivalence class may
// now target different equivalence classes, and hence these two sections
// must be put in different equivalence classes (whereas in the previous
// iteration they were not since the relocation target was the same.)
//
// Our algorithm is smart enough to merge the following mutually-recursive
// functions.
//
//   void foo() { bar(); }
//   void bar() { foo(); }
//
// This algorithm is so-called "optimistic" algorithm described in
// http://research.google.com/pubs/pub36912.html. (Note that what GNU
// gold implemented is different from the optimistic algorithm.)
//
//===----------------------------------------------------------------------===//

#include "ICF.h"
#include "Config.h"
#include "OutputSections.h"
#include "SymbolTable.h"

#include "llvm/ADT/Hashing.h"
#include "llvm/Object/ELF.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>

using namespace lld;
using namespace lld::elf;
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;

namespace lld {
namespace elf {
template <class ELFT> class ICF {
  typedef typename ELFT::Shdr Elf_Shdr;
  typedef typename ELFT::Sym Elf_Sym;
  typedef typename ELFT::uint uintX_t;
  typedef Elf_Rel_Impl<ELFT, false> Elf_Rel;

  using Comparator = std::function<bool(const InputSection<ELFT> *,
                                        const InputSection<ELFT> *)>;

public:
  void run();

private:
  uint64_t NextId = 1;

  static void setLive(SymbolTable<ELFT> *S);
  static uint64_t relSize(InputSection<ELFT> *S);
  static uint64_t getHash(InputSection<ELFT> *S);
  static bool isEligible(InputSectionBase<ELFT> *Sec);
  static std::vector<InputSection<ELFT> *> getSections();

  void segregate(MutableArrayRef<InputSection<ELFT> *> Arr, Comparator Eq);

  void
  forEachGroup(std::vector<InputSection<ELFT> *> &V,
               std::function<void(MutableArrayRef<InputSection<ELFT> *>)> Fn);

  template <class RelTy>
  static bool relocationEq(ArrayRef<RelTy> RA, ArrayRef<RelTy> RB);

  template <class RelTy>
  static bool variableEq(const InputSection<ELFT> *A, ArrayRef<RelTy> RA,
                         const InputSection<ELFT> *B, ArrayRef<RelTy> RB);

  static bool equalsConstant(const InputSection<ELFT> *A,
                             const InputSection<ELFT> *B);

  static bool equalsVariable(const InputSection<ELFT> *A,
                             const InputSection<ELFT> *B);
};
}
}

// Returns a hash value for S. Note that the information about
// relocation targets is not included in the hash value.
template <class ELFT> uint64_t ICF<ELFT>::getHash(InputSection<ELFT> *S) {
  return hash_combine(S->Flags, S->getSize(), S->NumRelocations);
}

// Returns true if Sec is subject of ICF.
template <class ELFT> bool ICF<ELFT>::isEligible(InputSectionBase<ELFT> *Sec) {
  if (!Sec->Live)
    return false;
  auto *S = dyn_cast<InputSection<ELFT>>(Sec);
  if (!S)
    return false;

  // .init and .fini contains instructions that must be executed to
  // initialize and finalize the process. They cannot and should not
  // be merged.
  StringRef Name = S->Name;
  if (Name == ".init" || Name == ".fini")
    return false;

  return (S->Flags & SHF_ALLOC) && !(S->Flags & SHF_WRITE);
}

template <class ELFT>
std::vector<InputSection<ELFT> *> ICF<ELFT>::getSections() {
  std::vector<InputSection<ELFT> *> V;
  for (InputSectionBase<ELFT> *S : Symtab<ELFT>::X->Sections)
    if (isEligible(S))
      V.push_back(cast<InputSection<ELFT>>(S));
  return V;
}

// All sections between Begin and End must have the same group ID before
// you call this function. This function compare sections between Begin
// and End using Eq and assign new group IDs for new groups.
template <class ELFT>
void ICF<ELFT>::segregate(MutableArrayRef<InputSection<ELFT> *> Arr,
                          Comparator Eq) {
  // This loop rearranges [Begin, End) so that all sections that are
  // equal in terms of Eq are contiguous. The algorithm is quadratic in
  // the worst case, but that is not an issue in practice because the
  // number of distinct sections in [Begin, End) is usually very small.
  InputSection<ELFT> **I = Arr.begin();
  for (;;) {
    InputSection<ELFT> *Head = *I;
    auto Bound = std::stable_partition(
        I + 1, Arr.end(), [&](InputSection<ELFT> *S) { return Eq(Head, S); });
    if (Bound == Arr.end())
      return;
    uint64_t Id = NextId++;
    for (; I != Bound; ++I)
      (*I)->GroupId = Id;
  }
}

template <class ELFT>
void ICF<ELFT>::forEachGroup(
    std::vector<InputSection<ELFT> *> &V,
    std::function<void(MutableArrayRef<InputSection<ELFT> *>)> Fn) {
  for (InputSection<ELFT> **I = V.data(), **E = I + V.size(); I != E;) {
    InputSection<ELFT> *Head = *I;
    auto Bound = std::find_if(I + 1, E, [&](InputSection<ELFT> *S) {
      return S->GroupId != Head->GroupId;
    });
    Fn({I, Bound});
    I = Bound;
  }
}

// Compare two lists of relocations.
template <class ELFT>
template <class RelTy>
bool ICF<ELFT>::relocationEq(ArrayRef<RelTy> RelsA, ArrayRef<RelTy> RelsB) {
  auto Eq = [](const RelTy &A, const RelTy &B) {
    return A.r_offset == B.r_offset &&
           A.getType(Config->Mips64EL) == B.getType(Config->Mips64EL) &&
           getAddend<ELFT>(A) == getAddend<ELFT>(B);
  };

  return RelsA.size() == RelsB.size() &&
         std::equal(RelsA.begin(), RelsA.end(), RelsB.begin(), Eq);
}

// Compare "non-moving" part of two InputSections, namely everything
// except relocation targets.
template <class ELFT>
bool ICF<ELFT>::equalsConstant(const InputSection<ELFT> *A,
                               const InputSection<ELFT> *B) {
  if (A->NumRelocations != B->NumRelocations)
    return false;

  if (A->AreRelocsRela) {
    if (!relocationEq(A->relas(), B->relas()))
      return false;
  } else {
    if (!relocationEq(A->rels(), B->rels()))
      return false;
  }

  return A->Flags == B->Flags && A->getSize() == B->getSize() &&
         A->Data == B->Data;
}

template <class ELFT>
template <class RelTy>
bool ICF<ELFT>::variableEq(const InputSection<ELFT> *A, ArrayRef<RelTy> RelsA,
                           const InputSection<ELFT> *B, ArrayRef<RelTy> RelsB) {
  auto Eq = [&](const RelTy &RA, const RelTy &RB) {
    SymbolBody &SA = A->File->getRelocTargetSym(RA);
    SymbolBody &SB = B->File->getRelocTargetSym(RB);
    if (&SA == &SB)
      return true;

    // Or, the symbols should be pointing to the same section
    // in terms of the group ID.
    auto *DA = dyn_cast<DefinedRegular<ELFT>>(&SA);
    auto *DB = dyn_cast<DefinedRegular<ELFT>>(&SB);
    if (!DA || !DB)
      return false;
    if (DA->Value != DB->Value)
      return false;
    InputSection<ELFT> *X = dyn_cast<InputSection<ELFT>>(DA->Section);
    InputSection<ELFT> *Y = dyn_cast<InputSection<ELFT>>(DB->Section);
    return X && Y && X->GroupId && X->GroupId == Y->GroupId;
  };

  return std::equal(RelsA.begin(), RelsA.end(), RelsB.begin(), Eq);
}

// Compare "moving" part of two InputSections, namely relocation targets.
template <class ELFT>
bool ICF<ELFT>::equalsVariable(const InputSection<ELFT> *A,
                               const InputSection<ELFT> *B) {
  if (A->AreRelocsRela)
    return variableEq(A, A->relas(), B, B->relas());
  return variableEq(A, A->rels(), B, B->rels());
}

// The main function of ICF.
template <class ELFT> void ICF<ELFT>::run() {
  // Initially, we use hash values as section group IDs. Therefore,
  // if two sections have the same ID, they are likely (but not
  // guaranteed) to have the same static contents in terms of ICF.
  std::vector<InputSection<ELFT> *> Sections = getSections();
  for (InputSection<ELFT> *S : Sections)
    // Set MSB on to avoid collisions with serial group IDs
    S->GroupId = getHash(S) | (uint64_t(1) << 63);

  // From now on, sections in V are ordered so that sections in
  // the same group are consecutive in the vector.
  std::stable_sort(Sections.begin(), Sections.end(),
                   [](InputSection<ELFT> *A, InputSection<ELFT> *B) {
                     if (A->GroupId != B->GroupId)
                       return A->GroupId < B->GroupId;
                     // Within a group, put the highest alignment
                     // requirement first, so that's the one we'll keep.
                     return B->Alignment < A->Alignment;
                   });

  // Compare static contents and assign unique IDs for each static content.
  forEachGroup(Sections, [&](MutableArrayRef<InputSection<ELFT> *> V) {
    segregate(V, equalsConstant);
  });

  // Split groups by comparing relocations until we get a convergence.
  int Cnt = 1;
  for (;;) {
    ++Cnt;
    uint64_t Id = NextId;
    forEachGroup(Sections, [&](MutableArrayRef<InputSection<ELFT> *> V) {
      segregate(V, equalsVariable);
    });
    if (Id == NextId)
      break;
  }
  log("ICF needed " + Twine(Cnt) + " iterations.");

  // Merge sections in the same group.
  forEachGroup(Sections, [&](MutableArrayRef<InputSection<ELFT> *> V) {
    InputSection<ELFT> *Head = V[0];
    log("selected " + Head->Name);
    for (InputSection<ELFT> *S : V.slice(1)) {
      log("  removed " + S->Name);
      Head->replace(S);
    }
  });
}

// ICF entry point function.
template <class ELFT> void elf::doIcf() { ICF<ELFT>().run(); }

template void elf::doIcf<ELF32LE>();
template void elf::doIcf<ELF32BE>();
template void elf::doIcf<ELF64LE>();
template void elf::doIcf<ELF64BE>();
<|endoftext|>


<commit_before>#include <allegro.h>
#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>
#endif

#ifndef ALLEGRO_WINDOWS
#include <signal.h>
#include <string.h>
#endif

/* don't be a boring tuna */
#warning you are ugly

#include "globals.h"
#include "init.h"
#include <pthread.h>
#include "network/network.h"

#include <ostream>
#include "dumb/include/dumb.h"
#include "dumb/include/aldumb.h"
#include "loadpng/loadpng.h"
#include "util/bitmap.h"
#include "util/funcs.h"
#include "configuration.h"
#include "script/script.h"
#include "music.h"

using namespace std;

volatile int Global::speed_counter = 0;
volatile int Global::second_counter = 0;

/* the original engine was running at 90 ticks per second, but we dont
 * need to render that fast, so TICS_PER_SECOND is really fps and
 * LOGIC_MULTIPLIER will be used to adjust the speed counter to its
 * original value.
 */
const int Global::TICS_PER_SECOND = 40;
const double Global::LOGIC_MULTIPLIER = (double) 90 / (double) Global::TICS_PER_SECOND;

pthread_mutex_t Global::loading_screen_mutex;
bool Global::done_loading = false;

const int Global::WINDOWED = GFX_AUTODETECT_WINDOWED;
const int Global::FULLSCREEN = GFX_AUTODETECT_FULLSCREEN;

/* game counter, controls FPS */
void inc_speed_counter(){
    /* probably put input polling here, InputManager::poll() */
    Global::speed_counter += 1;
}
END_OF_FUNCTION( inc_speed_counter );

/* if you need to count seconds for some reason.. */
void inc_second_counter() {
    Global::second_counter += 1;
}
END_OF_FUNCTION( inc_second_counter );

#ifndef ALLEGRO_WINDOWS
static void handleSigSegV(int i, siginfo_t * sig, void * data){
    const char * message = "Bug! Caught a memory violation. Shutting down..\n";
    int dont_care = write(1, message, 48);
    dont_care = dont_care;
    // Global::shutdown_message = "Bug! Caught a memory violation. Shutting down..";
    Bitmap::setGfxModeText();
    allegro_exit();
    /* write to a log file or something because sigsegv shouldn't
     * normally happen.
     */
    exit(1);
}
#else
#endif

/* catch a socket being closed prematurely on unix */
#ifndef ALLEGRO_WINDOWS
static void handleSigPipe( int i, siginfo_t * sig, void * data ){
}

/*
static void handleSigUsr1( int i, siginfo_t * sig, void * data ){
	pthread_exit( NULL );
}
*/
#endif

static void registerSignals(){
#ifndef ALLEGRO_WINDOWS
	struct sigaction action;
	memset( &action, 0, sizeof(struct sigaction) );
	action.sa_sigaction = handleSigPipe;
	sigaction( SIGPIPE, &action, NULL );

	memset( &action, 0, sizeof(struct sigaction) );
	action.sa_sigaction = handleSigSegV;
	sigaction( SIGSEGV, &action, NULL );

	/*
	action.sa_sigaction = handleSigUsr1;
	sigaction( SIGUSR1, &action, NULL );
	*/
#endif
}

/* should probably call the janitor here or something */
static void close_paintown(){
    Music::pause();
    Bitmap::setGfxModeText();
    allegro_exit();
    exit(0);
}
END_OF_FUNCTION(close_paintown)

bool Global::init( int gfx ){

	ostream & out = Global::debug( 0 );
	out << "-- BEGIN init --" << endl;
        out << "Data path is " << Util::getDataPath() << endl;
        out << "Paintown version " << Global::getVersionString() << endl;
	out << "Allegro version: " << ALLEGRO_VERSION_STR << endl;
	out <<"Allegro init: "<<allegro_init()<<endl;
	out <<"Install timer: "<<install_timer()<<endl;

	set_volume_per_voice( 0 );
	out<<"Install sound: "<<install_sound( DIGI_AUTODETECT, MIDI_NONE, "" )<<endl;

        /* png */
	loadpng_init();

        Bitmap::SCALE_X = GFX_X;
        Bitmap::SCALE_Y = GFX_Y;

        Configuration::loadConfigurations();

        const int sx = Configuration::getScreenWidth();
        const int sy = Configuration::getScreenHeight();

	out<<"Install keyboard: "<<install_keyboard()<<endl;
	out<<"Install mouse: "<<install_mouse()<<endl;
	out<<"Install joystick: "<<install_joystick(JOY_TYPE_AUTODETECT)<<endl;
        /* 16 bit color depth */
	set_color_depth( 16 );

        /* set up the screen */
	out<<"Set gfx mode: " << Bitmap::setGraphicsMode( gfx, sx, sy ) <<endl;

	LOCK_VARIABLE( speed_counter );
	LOCK_VARIABLE( second_counter );
	LOCK_FUNCTION( (void *)inc_speed_counter );
	LOCK_FUNCTION( (void *)inc_second_counter );
        /* set up the timers */
	out<<"Install game timer: "<<install_int_ex( inc_speed_counter, BPS_TO_TIMER( TICS_PER_SECOND ) )<<endl;
	out<<"Install second timer: "<<install_int_ex( inc_second_counter, BPS_TO_TIMER( 1 ) )<<endl;
	out << "Initialize random number generator" << endl;
        /* initialize random number generator */
	srand( time( NULL ) );

        /* keep running in the background */
	set_display_switch_mode(SWITCH_BACKGROUND);

        /* close window when the X is pressed */
        LOCK_FUNCTION(close_paintown);
        set_close_button_callback(close_paintown);

        /* music */
	atexit( &dumb_exit );
	atexit( Network::closeAll );
	dumb_register_packfiles();

	registerSignals();

	out << "Initialize network" << endl;
	Network::init();

        /* this mutex is used to show the loading screen while the game loads */
	pthread_mutex_init( &Global::loading_screen_mutex, NULL );

	out<<"-- END init --"<<endl;

	return true;
}
<commit_msg>print build time<commit_after>#include <allegro.h>
#ifdef ALLEGRO_WINDOWS
#include <winalleg.h>
#endif

#ifndef ALLEGRO_WINDOWS
#include <signal.h>
#include <string.h>
#endif

/* don't be a boring tuna */
#warning you are ugly

#include "globals.h"
#include "init.h"
#include <pthread.h>
#include "network/network.h"

#include <ostream>
#include "dumb/include/dumb.h"
#include "dumb/include/aldumb.h"
#include "loadpng/loadpng.h"
#include "util/bitmap.h"
#include "util/funcs.h"
#include "configuration.h"
#include "script/script.h"
#include "music.h"

using namespace std;

volatile int Global::speed_counter = 0;
volatile int Global::second_counter = 0;

/* the original engine was running at 90 ticks per second, but we dont
 * need to render that fast, so TICS_PER_SECOND is really fps and
 * LOGIC_MULTIPLIER will be used to adjust the speed counter to its
 * original value.
 */
const int Global::TICS_PER_SECOND = 40;
const double Global::LOGIC_MULTIPLIER = (double) 90 / (double) Global::TICS_PER_SECOND;

pthread_mutex_t Global::loading_screen_mutex;
bool Global::done_loading = false;

const int Global::WINDOWED = GFX_AUTODETECT_WINDOWED;
const int Global::FULLSCREEN = GFX_AUTODETECT_FULLSCREEN;

/* game counter, controls FPS */
void inc_speed_counter(){
    /* probably put input polling here, InputManager::poll() */
    Global::speed_counter += 1;
}
END_OF_FUNCTION( inc_speed_counter );

/* if you need to count seconds for some reason.. */
void inc_second_counter() {
    Global::second_counter += 1;
}
END_OF_FUNCTION( inc_second_counter );

#ifndef ALLEGRO_WINDOWS
static void handleSigSegV(int i, siginfo_t * sig, void * data){
    const char * message = "Bug! Caught a memory violation. Shutting down..\n";
    int dont_care = write(1, message, 48);
    dont_care = dont_care;
    // Global::shutdown_message = "Bug! Caught a memory violation. Shutting down..";
    Bitmap::setGfxModeText();
    allegro_exit();
    /* write to a log file or something because sigsegv shouldn't
     * normally happen.
     */
    exit(1);
}
#else
#endif

/* catch a socket being closed prematurely on unix */
#ifndef ALLEGRO_WINDOWS
static void handleSigPipe( int i, siginfo_t * sig, void * data ){
}

/*
static void handleSigUsr1( int i, siginfo_t * sig, void * data ){
	pthread_exit( NULL );
}
*/
#endif

static void registerSignals(){
#ifndef ALLEGRO_WINDOWS
	struct sigaction action;
	memset( &action, 0, sizeof(struct sigaction) );
	action.sa_sigaction = handleSigPipe;
	sigaction( SIGPIPE, &action, NULL );

	memset( &action, 0, sizeof(struct sigaction) );
	action.sa_sigaction = handleSigSegV;
	sigaction( SIGSEGV, &action, NULL );

	/*
	action.sa_sigaction = handleSigUsr1;
	sigaction( SIGUSR1, &action, NULL );
	*/
#endif
}

/* should probably call the janitor here or something */
static void close_paintown(){
    Music::pause();
    Bitmap::setGfxModeText();
    allegro_exit();
    exit(0);
}
END_OF_FUNCTION(close_paintown)

bool Global::init( int gfx ){

	ostream & out = Global::debug( 0 );
	out << "-- BEGIN init --" << endl;
        out << "Data path is " << Util::getDataPath() << endl;
        out << "Paintown version " << Global::getVersionString() << endl;
        out << "Build date " << __DATE__ << " " << __TIME__ << endl;
	out << "Allegro version: " << ALLEGRO_VERSION_STR << endl;
	out <<"Allegro init: "<<allegro_init()<<endl;
	out <<"Install timer: "<<install_timer()<<endl;

	set_volume_per_voice( 0 );
	out<<"Install sound: "<<install_sound( DIGI_AUTODETECT, MIDI_NONE, "" )<<endl;

        /* png */
	loadpng_init();

        Bitmap::SCALE_X = GFX_X;
        Bitmap::SCALE_Y = GFX_Y;

        Configuration::loadConfigurations();

        const int sx = Configuration::getScreenWidth();
        const int sy = Configuration::getScreenHeight();

	out<<"Install keyboard: "<<install_keyboard()<<endl;
	out<<"Install mouse: "<<install_mouse()<<endl;
	out<<"Install joystick: "<<install_joystick(JOY_TYPE_AUTODETECT)<<endl;
        /* 16 bit color depth */
	set_color_depth( 16 );

        /* set up the screen */
	out<<"Set gfx mode: " << Bitmap::setGraphicsMode( gfx, sx, sy ) <<endl;

	LOCK_VARIABLE( speed_counter );
	LOCK_VARIABLE( second_counter );
	LOCK_FUNCTION( (void *)inc_speed_counter );
	LOCK_FUNCTION( (void *)inc_second_counter );
        /* set up the timers */
	out<<"Install game timer: "<<install_int_ex( inc_speed_counter, BPS_TO_TIMER( TICS_PER_SECOND ) )<<endl;
	out<<"Install second timer: "<<install_int_ex( inc_second_counter, BPS_TO_TIMER( 1 ) )<<endl;
	out << "Initialize random number generator" << endl;
        /* initialize random number generator */
	srand( time( NULL ) );

        /* keep running in the background */
	set_display_switch_mode(SWITCH_BACKGROUND);

        /* close window when the X is pressed */
        LOCK_FUNCTION(close_paintown);
        set_close_button_callback(close_paintown);

        /* music */
	atexit( &dumb_exit );
	atexit( Network::closeAll );
	dumb_register_packfiles();

	registerSignals();

	out << "Initialize network" << endl;
	Network::init();

        /* this mutex is used to show the loading screen while the game loads */
	pthread_mutex_init( &Global::loading_screen_mutex, NULL );

	out<<"-- END init --"<<endl;

	return true;
}
<|endoftext|>