<commit_before>/* Copyright 2015 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/examples/android/jni/tensorflow_jni.h"

#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <android/bitmap.h>

#include <jni.h>
#include <pthread.h>
#include <unistd.h>
#include <queue>
#include <sstream>
#include <string>

#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/mutex.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/public/session.h"
#include "tensorflow/examples/android/jni/jni_utils.h"

// Global variables that holds the Tensorflow classifier.
static std::unique_ptr<tensorflow::Session> session;

static std::vector<std::string> g_label_strings;
static bool g_compute_graph_initialized = false;
//static mutex g_compute_graph_mutex(base::LINKER_INITIALIZED);

static int g_tensorflow_input_size;  // The image size for the mognet input.
static int g_image_mean;  // The image mean.

// For basic benchmarking.
static int g_num_runs = 0;
static int64 g_timing_total_us = 0;

using namespace tensorflow;

inline static int64 CurrentThreadTimeUs() {
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return tv.tv_sec * 1000000 + tv.tv_usec;
}

JNIEXPORT jint JNICALL
TENSORFLOW_METHOD(initializeTensorflow)(
    JNIEnv* env, jobject thiz, jobject java_asset_manager,
    jstring model, jstring labels,
    jint num_classes, jint mognet_input_size, jint image_mean) {
  g_num_runs = 0;
  g_timing_total_us = 0;

  //MutexLock input_lock(&g_compute_graph_mutex);
  if (g_compute_graph_initialized) {
    LOG(INFO) << "Compute graph already loaded. skipping.";
    return 0;
  }

  const char* const model_cstr = env->GetStringUTFChars(model, NULL);
  const char* const labels_cstr = env->GetStringUTFChars(labels, NULL);

  g_tensorflow_input_size = mognet_input_size;
  g_image_mean = image_mean;

  LOG(INFO) << "Loading Tensorflow.";

  LOG(INFO) << "Making new SessionOptions.";
  tensorflow::SessionOptions options;
  tensorflow::ConfigProto& config = options.config;
  LOG(INFO) << "Got config, " << config.device_count_size() << " devices";

  session.reset(tensorflow::NewSession(options));
  LOG(INFO) << "Session created.";

  tensorflow::GraphDef tensorflow_graph;
  LOG(INFO) << "Graph created.";

  AAssetManager* const asset_manager =
      AAssetManager_fromJava(env, java_asset_manager);
  LOG(INFO) << "Acquired AssetManager.";

  LOG(INFO) << "Reading file to proto: " << model_cstr;
  ReadFileToProto(asset_manager, model_cstr, &tensorflow_graph);

  LOG(INFO) << "Creating session.";
  tensorflow::Status s = session->Create(tensorflow_graph);
  if (!s.ok()) {
    LOG(ERROR) << "Could not create Tensorflow Graph: " << s;
    return -1;
  }

  // Clear the proto to save memory space.
  tensorflow_graph.Clear();
  LOG(INFO) << "Tensorflow graph loaded from: " << model_cstr;

  // Read the label list
  ReadFileToVector(asset_manager, labels_cstr, &g_label_strings);
  LOG(INFO) << g_label_strings.size() << " label strings loaded from: "
            << labels_cstr;
  g_compute_graph_initialized = true;

  return 0;
}

namespace {
typedef struct {
  uint8 red;
  uint8 green;
  uint8 blue;
  uint8 alpha;
} RGBA;
}  // namespace

// Returns the top N confidence values over threshold in the provided vector,
// sorted by confidence in descending order.
static void GetTopN(
    const Eigen::TensorMap<Eigen::Tensor<float, 1, Eigen::RowMajor>,
                           Eigen::Aligned>& prediction,
    const int num_results, const float threshold,
    std::vector<std::pair<float, int> >* top_results) {
  // Will contain top N results in ascending order.
  std::priority_queue<std::pair<float, int>,
      std::vector<std::pair<float, int> >,
      std::greater<std::pair<float, int> > > top_result_pq;

  const int count = prediction.size();
  for (int i = 0; i < count; ++i) {
    const float value = prediction(i);

    // Only add it if it beats the threshold and has a chance at being in
    // the top N.
    if (value < threshold) {
      continue;
    }

    top_result_pq.push(std::pair<float, int>(value, i));

    // If at capacity, kick the smallest value out.
    if (top_result_pq.size() > num_results) {
      top_result_pq.pop();
    }
  }

  // Copy to output vector and reverse into descending order.
  while (!top_result_pq.empty()) {
    top_results->push_back(top_result_pq.top());
    top_result_pq.pop();
  }
  std::reverse(top_results->begin(), top_results->end());
}

static std::string ClassifyImage(const RGBA* const bitmap_src,
                                 const int in_stride,
                                 const int width, const int height) {
  ++g_num_runs;

  // Create input tensor
  tensorflow::Tensor input_tensor(
      tensorflow::DT_FLOAT,
      tensorflow::TensorShape({
          1, g_tensorflow_input_size, g_tensorflow_input_size, 3}));

  auto input_tensor_mapped = input_tensor.tensor<float, 4>();

  LOG(INFO) << "Tensorflow: Copying Data.";
  for (int i = 0; i < g_tensorflow_input_size; ++i) {
    const RGBA* src = bitmap_src + i * g_tensorflow_input_size;
    for (int j = 0; j < g_tensorflow_input_size; ++j) {
       // Copy 3 values
      input_tensor_mapped(0, i, j, 0) =
          static_cast<float>(src->red) - g_image_mean;
      input_tensor_mapped(0, i, j, 1) =
          static_cast<float>(src->green) - g_image_mean;
      input_tensor_mapped(0, i, j, 2) =
          static_cast<float>(src->blue) - g_image_mean;
      ++src;
    }
  }

  std::vector<std::pair<std::string, tensorflow::Tensor> > input_tensors(
      {{"input:0", input_tensor}});

  VLOG(0) << "Start computing.";
  std::vector<tensorflow::Tensor> output_tensors;
  std::vector<std::string> output_names({"output:0"});

  const int64 start_time = CurrentThreadTimeUs();
  tensorflow::Status s =
      session->Run(input_tensors, output_names, {}, &output_tensors);
  const int64 end_time = CurrentThreadTimeUs();

  const int64 elapsed_time_inf = end_time - start_time;
  g_timing_total_us += elapsed_time_inf;
  VLOG(0) << "End computing. Ran in " << elapsed_time_inf / 1000 << "ms ("
          << (g_timing_total_us / g_num_runs / 1000) << "ms avg over "
          << g_num_runs << " runs)";

  if (!s.ok()) {
    LOG(ERROR) << "Error during inference: " << s;
    return "";
  }

  VLOG(0) << "Reading from layer " << output_names[0];
  tensorflow::Tensor* output = &output_tensors[0];
  const int kNumResults = 5;
  const float kThreshold = 0.1f;
  std::vector<std::pair<float, int> > top_results;
  GetTopN(output->flat<float>(), kNumResults, kThreshold, &top_results);

  std::stringstream ss;
  ss.precision(3);
  for (const auto& result : top_results) {
    const float confidence = result.first;
    const int index = result.second;

    ss << index << " " << confidence << " ";

    // Write out the result as a string
    if (index < g_label_strings.size()) {
      // just for safety: theoretically, the output is under 1000 unless there
      // is some numerical issues leading to a wrong prediction.
      ss << g_label_strings[index];
    } else {
      ss << "Prediction: " << index;
    }

    ss << "\n";
  }

  LOG(INFO) << "Predictions: " << ss.str();
  return ss.str();
}

JNIEXPORT jstring JNICALL
TENSORFLOW_METHOD(classifyImageRgb)(
    JNIEnv* env, jobject thiz, jintArray image, jint width, jint height) {
  // Copy image into currFrame.
  jboolean iCopied = JNI_FALSE;
  jint* pixels = env->GetIntArrayElements(image, &iCopied);

  std::string result = ClassifyImage(
      reinterpret_cast<const RGBA*>(pixels), width * 4, width, height);

  env->ReleaseIntArrayElements(image, pixels, JNI_ABORT);

  return env->NewStringUTF(result.c_str());
}

JNIEXPORT jstring JNICALL
TENSORFLOW_METHOD(classifyImageBmp)(
    JNIEnv* env, jobject thiz, jobject bitmap) {
  // Obtains the bitmap information.
  AndroidBitmapInfo info;
  CHECK_EQ(AndroidBitmap_getInfo(env, bitmap, &info),
           ANDROID_BITMAP_RESULT_SUCCESS);
  void* pixels;
  CHECK_EQ(AndroidBitmap_lockPixels(env, bitmap, &pixels),
           ANDROID_BITMAP_RESULT_SUCCESS);
  LOG(INFO) << "Height: " << info.height;
  LOG(INFO) << "Width: " << info.width;
  LOG(INFO) << "Stride: " << info.stride;
  // TODO(jiayq): deal with other formats if necessary.
  if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
    return env->NewStringUTF(
        "Error: Android system is not using RGBA_8888 in default.");
  }

  std::string result = ClassifyImage(
      static_cast<const RGBA*>(pixels), info.stride, info.width, info.height);

  // Finally, unlock the pixels
  CHECK_EQ(AndroidBitmap_unlockPixels(env, bitmap),
           ANDROID_BITMAP_RESULT_SUCCESS);

  return env->NewStringUTF(result.c_str());
}
<commit_msg>Move "using namespace tensorflow" declaration in tensorflow_jni.cc so that int64 global variable will be covered. Change: 116880050<commit_after>/* Copyright 2015 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/examples/android/jni/tensorflow_jni.h"

#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
#include <android/bitmap.h>

#include <jni.h>
#include <pthread.h>
#include <unistd.h>
#include <queue>
#include <sstream>
#include <string>

#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/platform/env.h"
#include "tensorflow/core/platform/logging.h"
#include "tensorflow/core/platform/mutex.h"
#include "tensorflow/core/platform/types.h"
#include "tensorflow/core/public/session.h"
#include "tensorflow/examples/android/jni/jni_utils.h"

using namespace tensorflow;

// Global variables that holds the Tensorflow classifier.
static std::unique_ptr<tensorflow::Session> session;

static std::vector<std::string> g_label_strings;
static bool g_compute_graph_initialized = false;
//static mutex g_compute_graph_mutex(base::LINKER_INITIALIZED);

static int g_tensorflow_input_size;  // The image size for the mognet input.
static int g_image_mean;  // The image mean.

// For basic benchmarking.
static int g_num_runs = 0;
static int64 g_timing_total_us = 0;

inline static int64 CurrentThreadTimeUs() {
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return tv.tv_sec * 1000000 + tv.tv_usec;
}

JNIEXPORT jint JNICALL
TENSORFLOW_METHOD(initializeTensorflow)(
    JNIEnv* env, jobject thiz, jobject java_asset_manager,
    jstring model, jstring labels,
    jint num_classes, jint mognet_input_size, jint image_mean) {
  g_num_runs = 0;
  g_timing_total_us = 0;

  //MutexLock input_lock(&g_compute_graph_mutex);
  if (g_compute_graph_initialized) {
    LOG(INFO) << "Compute graph already loaded. skipping.";
    return 0;
  }

  const char* const model_cstr = env->GetStringUTFChars(model, NULL);
  const char* const labels_cstr = env->GetStringUTFChars(labels, NULL);

  g_tensorflow_input_size = mognet_input_size;
  g_image_mean = image_mean;

  LOG(INFO) << "Loading Tensorflow.";

  LOG(INFO) << "Making new SessionOptions.";
  tensorflow::SessionOptions options;
  tensorflow::ConfigProto& config = options.config;
  LOG(INFO) << "Got config, " << config.device_count_size() << " devices";

  session.reset(tensorflow::NewSession(options));
  LOG(INFO) << "Session created.";

  tensorflow::GraphDef tensorflow_graph;
  LOG(INFO) << "Graph created.";

  AAssetManager* const asset_manager =
      AAssetManager_fromJava(env, java_asset_manager);
  LOG(INFO) << "Acquired AssetManager.";

  LOG(INFO) << "Reading file to proto: " << model_cstr;
  ReadFileToProto(asset_manager, model_cstr, &tensorflow_graph);

  LOG(INFO) << "Creating session.";
  tensorflow::Status s = session->Create(tensorflow_graph);
  if (!s.ok()) {
    LOG(ERROR) << "Could not create Tensorflow Graph: " << s;
    return -1;
  }

  // Clear the proto to save memory space.
  tensorflow_graph.Clear();
  LOG(INFO) << "Tensorflow graph loaded from: " << model_cstr;

  // Read the label list
  ReadFileToVector(asset_manager, labels_cstr, &g_label_strings);
  LOG(INFO) << g_label_strings.size() << " label strings loaded from: "
            << labels_cstr;
  g_compute_graph_initialized = true;

  return 0;
}

namespace {
typedef struct {
  uint8 red;
  uint8 green;
  uint8 blue;
  uint8 alpha;
} RGBA;
}  // namespace

// Returns the top N confidence values over threshold in the provided vector,
// sorted by confidence in descending order.
static void GetTopN(
    const Eigen::TensorMap<Eigen::Tensor<float, 1, Eigen::RowMajor>,
                           Eigen::Aligned>& prediction,
    const int num_results, const float threshold,
    std::vector<std::pair<float, int> >* top_results) {
  // Will contain top N results in ascending order.
  std::priority_queue<std::pair<float, int>,
      std::vector<std::pair<float, int> >,
      std::greater<std::pair<float, int> > > top_result_pq;

  const int count = prediction.size();
  for (int i = 0; i < count; ++i) {
    const float value = prediction(i);

    // Only add it if it beats the threshold and has a chance at being in
    // the top N.
    if (value < threshold) {
      continue;
    }

    top_result_pq.push(std::pair<float, int>(value, i));

    // If at capacity, kick the smallest value out.
    if (top_result_pq.size() > num_results) {
      top_result_pq.pop();
    }
  }

  // Copy to output vector and reverse into descending order.
  while (!top_result_pq.empty()) {
    top_results->push_back(top_result_pq.top());
    top_result_pq.pop();
  }
  std::reverse(top_results->begin(), top_results->end());
}

static std::string ClassifyImage(const RGBA* const bitmap_src,
                                 const int in_stride,
                                 const int width, const int height) {
  ++g_num_runs;

  // Create input tensor
  tensorflow::Tensor input_tensor(
      tensorflow::DT_FLOAT,
      tensorflow::TensorShape({
          1, g_tensorflow_input_size, g_tensorflow_input_size, 3}));

  auto input_tensor_mapped = input_tensor.tensor<float, 4>();

  LOG(INFO) << "Tensorflow: Copying Data.";
  for (int i = 0; i < g_tensorflow_input_size; ++i) {
    const RGBA* src = bitmap_src + i * g_tensorflow_input_size;
    for (int j = 0; j < g_tensorflow_input_size; ++j) {
       // Copy 3 values
      input_tensor_mapped(0, i, j, 0) =
          static_cast<float>(src->red) - g_image_mean;
      input_tensor_mapped(0, i, j, 1) =
          static_cast<float>(src->green) - g_image_mean;
      input_tensor_mapped(0, i, j, 2) =
          static_cast<float>(src->blue) - g_image_mean;
      ++src;
    }
  }

  std::vector<std::pair<std::string, tensorflow::Tensor> > input_tensors(
      {{"input:0", input_tensor}});

  VLOG(0) << "Start computing.";
  std::vector<tensorflow::Tensor> output_tensors;
  std::vector<std::string> output_names({"output:0"});

  const int64 start_time = CurrentThreadTimeUs();
  tensorflow::Status s =
      session->Run(input_tensors, output_names, {}, &output_tensors);
  const int64 end_time = CurrentThreadTimeUs();

  const int64 elapsed_time_inf = end_time - start_time;
  g_timing_total_us += elapsed_time_inf;
  VLOG(0) << "End computing. Ran in " << elapsed_time_inf / 1000 << "ms ("
          << (g_timing_total_us / g_num_runs / 1000) << "ms avg over "
          << g_num_runs << " runs)";

  if (!s.ok()) {
    LOG(ERROR) << "Error during inference: " << s;
    return "";
  }

  VLOG(0) << "Reading from layer " << output_names[0];
  tensorflow::Tensor* output = &output_tensors[0];
  const int kNumResults = 5;
  const float kThreshold = 0.1f;
  std::vector<std::pair<float, int> > top_results;
  GetTopN(output->flat<float>(), kNumResults, kThreshold, &top_results);

  std::stringstream ss;
  ss.precision(3);
  for (const auto& result : top_results) {
    const float confidence = result.first;
    const int index = result.second;

    ss << index << " " << confidence << " ";

    // Write out the result as a string
    if (index < g_label_strings.size()) {
      // just for safety: theoretically, the output is under 1000 unless there
      // is some numerical issues leading to a wrong prediction.
      ss << g_label_strings[index];
    } else {
      ss << "Prediction: " << index;
    }

    ss << "\n";
  }

  LOG(INFO) << "Predictions: " << ss.str();
  return ss.str();
}

JNIEXPORT jstring JNICALL
TENSORFLOW_METHOD(classifyImageRgb)(
    JNIEnv* env, jobject thiz, jintArray image, jint width, jint height) {
  // Copy image into currFrame.
  jboolean iCopied = JNI_FALSE;
  jint* pixels = env->GetIntArrayElements(image, &iCopied);

  std::string result = ClassifyImage(
      reinterpret_cast<const RGBA*>(pixels), width * 4, width, height);

  env->ReleaseIntArrayElements(image, pixels, JNI_ABORT);

  return env->NewStringUTF(result.c_str());
}

JNIEXPORT jstring JNICALL
TENSORFLOW_METHOD(classifyImageBmp)(
    JNIEnv* env, jobject thiz, jobject bitmap) {
  // Obtains the bitmap information.
  AndroidBitmapInfo info;
  CHECK_EQ(AndroidBitmap_getInfo(env, bitmap, &info),
           ANDROID_BITMAP_RESULT_SUCCESS);
  void* pixels;
  CHECK_EQ(AndroidBitmap_lockPixels(env, bitmap, &pixels),
           ANDROID_BITMAP_RESULT_SUCCESS);
  LOG(INFO) << "Height: " << info.height;
  LOG(INFO) << "Width: " << info.width;
  LOG(INFO) << "Stride: " << info.stride;
  // TODO(jiayq): deal with other formats if necessary.
  if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
    return env->NewStringUTF(
        "Error: Android system is not using RGBA_8888 in default.");
  }

  std::string result = ClassifyImage(
      static_cast<const RGBA*>(pixels), info.stride, info.width, info.height);

  // Finally, unlock the pixels
  CHECK_EQ(AndroidBitmap_unlockPixels(env, bitmap),
           ANDROID_BITMAP_RESULT_SUCCESS);

  return env->NewStringUTF(result.c_str());
}
<|endoftext|>


<commit_before>//===- tools/dsymutil/MachODebugMapParser.cpp - Parse STABS debug maps ----===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "BinaryHolder.h"
#include "DebugMap.h"
#include "dsymutil.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

namespace {
using namespace llvm;
using namespace llvm::dsymutil;
using namespace llvm::object;

class MachODebugMapParser {
public:
  MachODebugMapParser(StringRef BinaryPath, StringRef PathPrefix = "",
                      bool Verbose = false)
      : BinaryPath(BinaryPath), PathPrefix(PathPrefix),
        MainBinaryHolder(Verbose), CurrentObjectHolder(Verbose) {}

  /// \brief Parses and returns the DebugMap of the input binary.
  /// \returns an error in case the provided BinaryPath doesn't exist
  /// or isn't of a supported type.
  ErrorOr<std::unique_ptr<DebugMap>> parse();

private:
  std::string BinaryPath;
  std::string PathPrefix;

  /// Owns the MemoryBuffer for the main binary.
  BinaryHolder MainBinaryHolder;
  /// Map of the binary symbol addresses.
  StringMap<uint64_t> MainBinarySymbolAddresses;
  StringRef MainBinaryStrings;
  /// The constructed DebugMap.
  std::unique_ptr<DebugMap> Result;

  /// Owns the MemoryBuffer for the currently handled object file.
  BinaryHolder CurrentObjectHolder;
  /// Map of the currently processed object file symbol addresses.
  StringMap<uint64_t> CurrentObjectAddresses;
  /// Element of the debug map corresponfing to the current object file.
  DebugMapObject *CurrentDebugMapObject;

  void switchToNewDebugMapObject(StringRef Filename);
  void resetParserState();
  uint64_t getMainBinarySymbolAddress(StringRef Name);
  void loadMainBinarySymbols();
  void loadCurrentObjectFileSymbols();
  void handleStabSymbolTableEntry(uint32_t StringIndex, uint8_t Type,
                                  uint8_t SectionIndex, uint16_t Flags,
                                  uint64_t Value);

  template <typename STEType> void handleStabDebugMapEntry(const STEType &STE) {
    handleStabSymbolTableEntry(STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc,
                               STE.n_value);
  }
};

static void Warning(const Twine &Msg) { errs() << "warning: " + Msg + "\n"; }
}

/// Reset the parser state coresponding to the current object
/// file. This is to be called after an object file is finished
/// processing.
void MachODebugMapParser::resetParserState() {
  CurrentObjectAddresses.clear();
  CurrentDebugMapObject = nullptr;
}

/// Create a new DebugMapObject. This function resets the state of the
/// parser that was referring to the last object file and sets
/// everything up to add symbols to the new one.
void MachODebugMapParser::switchToNewDebugMapObject(StringRef Filename) {
  resetParserState();

  SmallString<80> Path(PathPrefix);
  sys::path::append(Path, Filename);

  auto MachOOrError = CurrentObjectHolder.GetFileAs<MachOObjectFile>(Path);
  if (auto Error = MachOOrError.getError()) {
    Warning(Twine("cannot open debug object \"") + Path.str() + "\": " +
            Error.message() + "\n");
    return;
  }

  loadCurrentObjectFileSymbols();
  CurrentDebugMapObject = &Result->addDebugMapObject(Path);
}

/// This main parsing routine tries to open the main binary and if
/// successful iterates over the STAB entries. The real parsing is
/// done in handleStabSymbolTableEntry.
ErrorOr<std::unique_ptr<DebugMap>> MachODebugMapParser::parse() {
  auto MainBinOrError = MainBinaryHolder.GetFileAs<MachOObjectFile>(BinaryPath);
  if (auto Error = MainBinOrError.getError())
    return Error;

  const MachOObjectFile &MainBinary = *MainBinOrError;
  loadMainBinarySymbols();
  Result = make_unique<DebugMap>();
  MainBinaryStrings = MainBinary.getStringTableData();
  for (const SymbolRef &Symbol : MainBinary.symbols()) {
    const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
    if (MainBinary.is64Bit())
      handleStabDebugMapEntry(MainBinary.getSymbol64TableEntry(DRI));
    else
      handleStabDebugMapEntry(MainBinary.getSymbolTableEntry(DRI));
  }

  resetParserState();
  return std::move(Result);
}

/// Interpret the STAB entries to fill the DebugMap.
void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
                                                     uint8_t Type,
                                                     uint8_t SectionIndex,
                                                     uint16_t Flags,
                                                     uint64_t Value) {
  if (!(Type & MachO::N_STAB))
    return;

  const char *Name = &MainBinaryStrings.data()[StringIndex];

  // An N_OSO entry represents the start of a new object file description.
  if (Type == MachO::N_OSO)
    return switchToNewDebugMapObject(Name);

  // If the last N_OSO object file wasn't found,
  // CurrentDebugMapObject will be null. Do not update anything
  // until we find the next valid N_OSO entry.
  if (!CurrentDebugMapObject)
    return;

  switch (Type) {
  case MachO::N_GSYM:
    // This is a global variable. We need to query the main binary
    // symbol table to find its address as it might not be in the
    // debug map (for common symbols).
    Value = getMainBinarySymbolAddress(Name);
    if (Value == UnknownAddressOrSize)
      return;
    break;
  case MachO::N_FUN:
    // Functions are scopes in STABS. They have an end marker that we
    // need to ignore.
    if (Name[0] == '\0')
      return;
    break;
  case MachO::N_STSYM:
    break;
  default:
    return;
  }

  auto ObjectSymIt = CurrentObjectAddresses.find(Name);
  if (ObjectSymIt == CurrentObjectAddresses.end())
    return Warning("could not find object file symbol for symbol " +
                   Twine(Name));
  if (!CurrentDebugMapObject->addSymbol(Name, ObjectSymIt->getValue(), Value))
    return Warning(Twine("failed to insert symbol '") + Name +
                   "' in the debug map.");
}

/// Load the current object file symbols into CurrentObjectAddresses.
void MachODebugMapParser::loadCurrentObjectFileSymbols() {
  CurrentObjectAddresses.clear();

  for (auto Sym : CurrentObjectHolder.Get().symbols()) {
    StringRef Name;
    uint64_t Addr;
    if (Sym.getAddress(Addr) || Addr == UnknownAddressOrSize ||
        Sym.getName(Name))
      continue;
    CurrentObjectAddresses[Name] = Addr;
  }
}

/// Lookup a symbol address in the main binary symbol table. The
/// parser only needs to query common symbols, thus not every symbol's
/// address is available through this function.
uint64_t MachODebugMapParser::getMainBinarySymbolAddress(StringRef Name) {
  auto Sym = MainBinarySymbolAddresses.find(Name);
  if (Sym == MainBinarySymbolAddresses.end())
    return UnknownAddressOrSize;
  return Sym->second;
}

/// Load the interesting main binary symbols' addresses into
/// MainBinarySymbolAddresses.
void MachODebugMapParser::loadMainBinarySymbols() {
  const MachOObjectFile &MainBinary = MainBinaryHolder.GetAs<MachOObjectFile>();
  section_iterator Section = MainBinary.section_end();
  for (const auto &Sym : MainBinary.symbols()) {
    SymbolRef::Type Type;
    // Skip undefined and STAB entries.
    if (Sym.getType(Type) || (Type & SymbolRef::ST_Debug) ||
        (Type & SymbolRef::ST_Unknown))
      continue;
    StringRef Name;
    uint64_t Addr;
    // The only symbols of interest are the global variables. These
    // are the only ones that need to be queried because the address
    // of common data won't be described in the debug map. All other
    // addresses should be fetched for the debug map.
    if (Sym.getAddress(Addr) || Addr == UnknownAddressOrSize ||
        !(Sym.getFlags() & SymbolRef::SF_Global) || Sym.getSection(Section) ||
        Section->isText() || Sym.getName(Name) || Name.size() == 0 ||
        Name[0] == '\0')
      continue;
    MainBinarySymbolAddresses[Name] = Addr;
  }
}

namespace llvm {
namespace dsymutil {
llvm::ErrorOr<std::unique_ptr<DebugMap>> parseDebugMap(StringRef InputFile,
                                                       StringRef PrependPath,
                                                       bool Verbose) {
  MachODebugMapParser Parser(InputFile, PrependPath, Verbose);
  return Parser.parse();
}
}
}
<commit_msg>Fix uninitialized memory read in llvm-dsymutil for the second time.<commit_after>//===- tools/dsymutil/MachODebugMapParser.cpp - Parse STABS debug maps ----===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "BinaryHolder.h"
#include "DebugMap.h"
#include "dsymutil.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"

namespace {
using namespace llvm;
using namespace llvm::dsymutil;
using namespace llvm::object;

class MachODebugMapParser {
public:
  MachODebugMapParser(StringRef BinaryPath, StringRef PathPrefix = "",
                      bool Verbose = false)
      : BinaryPath(BinaryPath), PathPrefix(PathPrefix),
        MainBinaryHolder(Verbose), CurrentObjectHolder(Verbose),
        CurrentDebugMapObject(nullptr) {}

  /// \brief Parses and returns the DebugMap of the input binary.
  /// \returns an error in case the provided BinaryPath doesn't exist
  /// or isn't of a supported type.
  ErrorOr<std::unique_ptr<DebugMap>> parse();

private:
  std::string BinaryPath;
  std::string PathPrefix;

  /// Owns the MemoryBuffer for the main binary.
  BinaryHolder MainBinaryHolder;
  /// Map of the binary symbol addresses.
  StringMap<uint64_t> MainBinarySymbolAddresses;
  StringRef MainBinaryStrings;
  /// The constructed DebugMap.
  std::unique_ptr<DebugMap> Result;

  /// Owns the MemoryBuffer for the currently handled object file.
  BinaryHolder CurrentObjectHolder;
  /// Map of the currently processed object file symbol addresses.
  StringMap<uint64_t> CurrentObjectAddresses;
  /// Element of the debug map corresponfing to the current object file.
  DebugMapObject *CurrentDebugMapObject;

  void switchToNewDebugMapObject(StringRef Filename);
  void resetParserState();
  uint64_t getMainBinarySymbolAddress(StringRef Name);
  void loadMainBinarySymbols();
  void loadCurrentObjectFileSymbols();
  void handleStabSymbolTableEntry(uint32_t StringIndex, uint8_t Type,
                                  uint8_t SectionIndex, uint16_t Flags,
                                  uint64_t Value);

  template <typename STEType> void handleStabDebugMapEntry(const STEType &STE) {
    handleStabSymbolTableEntry(STE.n_strx, STE.n_type, STE.n_sect, STE.n_desc,
                               STE.n_value);
  }
};

static void Warning(const Twine &Msg) { errs() << "warning: " + Msg + "\n"; }
}

/// Reset the parser state coresponding to the current object
/// file. This is to be called after an object file is finished
/// processing.
void MachODebugMapParser::resetParserState() {
  CurrentObjectAddresses.clear();
  CurrentDebugMapObject = nullptr;
}

/// Create a new DebugMapObject. This function resets the state of the
/// parser that was referring to the last object file and sets
/// everything up to add symbols to the new one.
void MachODebugMapParser::switchToNewDebugMapObject(StringRef Filename) {
  resetParserState();

  SmallString<80> Path(PathPrefix);
  sys::path::append(Path, Filename);

  auto MachOOrError = CurrentObjectHolder.GetFileAs<MachOObjectFile>(Path);
  if (auto Error = MachOOrError.getError()) {
    Warning(Twine("cannot open debug object \"") + Path.str() + "\": " +
            Error.message() + "\n");
    return;
  }

  loadCurrentObjectFileSymbols();
  CurrentDebugMapObject = &Result->addDebugMapObject(Path);
}

/// This main parsing routine tries to open the main binary and if
/// successful iterates over the STAB entries. The real parsing is
/// done in handleStabSymbolTableEntry.
ErrorOr<std::unique_ptr<DebugMap>> MachODebugMapParser::parse() {
  auto MainBinOrError = MainBinaryHolder.GetFileAs<MachOObjectFile>(BinaryPath);
  if (auto Error = MainBinOrError.getError())
    return Error;

  const MachOObjectFile &MainBinary = *MainBinOrError;
  loadMainBinarySymbols();
  Result = make_unique<DebugMap>();
  MainBinaryStrings = MainBinary.getStringTableData();
  for (const SymbolRef &Symbol : MainBinary.symbols()) {
    const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
    if (MainBinary.is64Bit())
      handleStabDebugMapEntry(MainBinary.getSymbol64TableEntry(DRI));
    else
      handleStabDebugMapEntry(MainBinary.getSymbolTableEntry(DRI));
  }

  resetParserState();
  return std::move(Result);
}

/// Interpret the STAB entries to fill the DebugMap.
void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
                                                     uint8_t Type,
                                                     uint8_t SectionIndex,
                                                     uint16_t Flags,
                                                     uint64_t Value) {
  if (!(Type & MachO::N_STAB))
    return;

  const char *Name = &MainBinaryStrings.data()[StringIndex];

  // An N_OSO entry represents the start of a new object file description.
  if (Type == MachO::N_OSO)
    return switchToNewDebugMapObject(Name);

  // If the last N_OSO object file wasn't found,
  // CurrentDebugMapObject will be null. Do not update anything
  // until we find the next valid N_OSO entry.
  if (!CurrentDebugMapObject)
    return;

  switch (Type) {
  case MachO::N_GSYM:
    // This is a global variable. We need to query the main binary
    // symbol table to find its address as it might not be in the
    // debug map (for common symbols).
    Value = getMainBinarySymbolAddress(Name);
    if (Value == UnknownAddressOrSize)
      return;
    break;
  case MachO::N_FUN:
    // Functions are scopes in STABS. They have an end marker that we
    // need to ignore.
    if (Name[0] == '\0')
      return;
    break;
  case MachO::N_STSYM:
    break;
  default:
    return;
  }

  auto ObjectSymIt = CurrentObjectAddresses.find(Name);
  if (ObjectSymIt == CurrentObjectAddresses.end())
    return Warning("could not find object file symbol for symbol " +
                   Twine(Name));
  if (!CurrentDebugMapObject->addSymbol(Name, ObjectSymIt->getValue(), Value))
    return Warning(Twine("failed to insert symbol '") + Name +
                   "' in the debug map.");
}

/// Load the current object file symbols into CurrentObjectAddresses.
void MachODebugMapParser::loadCurrentObjectFileSymbols() {
  CurrentObjectAddresses.clear();

  for (auto Sym : CurrentObjectHolder.Get().symbols()) {
    StringRef Name;
    uint64_t Addr;
    if (Sym.getAddress(Addr) || Addr == UnknownAddressOrSize ||
        Sym.getName(Name))
      continue;
    CurrentObjectAddresses[Name] = Addr;
  }
}

/// Lookup a symbol address in the main binary symbol table. The
/// parser only needs to query common symbols, thus not every symbol's
/// address is available through this function.
uint64_t MachODebugMapParser::getMainBinarySymbolAddress(StringRef Name) {
  auto Sym = MainBinarySymbolAddresses.find(Name);
  if (Sym == MainBinarySymbolAddresses.end())
    return UnknownAddressOrSize;
  return Sym->second;
}

/// Load the interesting main binary symbols' addresses into
/// MainBinarySymbolAddresses.
void MachODebugMapParser::loadMainBinarySymbols() {
  const MachOObjectFile &MainBinary = MainBinaryHolder.GetAs<MachOObjectFile>();
  section_iterator Section = MainBinary.section_end();
  for (const auto &Sym : MainBinary.symbols()) {
    SymbolRef::Type Type;
    // Skip undefined and STAB entries.
    if (Sym.getType(Type) || (Type & SymbolRef::ST_Debug) ||
        (Type & SymbolRef::ST_Unknown))
      continue;
    StringRef Name;
    uint64_t Addr;
    // The only symbols of interest are the global variables. These
    // are the only ones that need to be queried because the address
    // of common data won't be described in the debug map. All other
    // addresses should be fetched for the debug map.
    if (Sym.getAddress(Addr) || Addr == UnknownAddressOrSize ||
        !(Sym.getFlags() & SymbolRef::SF_Global) || Sym.getSection(Section) ||
        Section->isText() || Sym.getName(Name) || Name.size() == 0 ||
        Name[0] == '\0')
      continue;
    MainBinarySymbolAddresses[Name] = Addr;
  }
}

namespace llvm {
namespace dsymutil {
llvm::ErrorOr<std::unique_ptr<DebugMap>> parseDebugMap(StringRef InputFile,
                                                       StringRef PrependPath,
                                                       bool Verbose) {
  MachODebugMapParser Parser(InputFile, PrependPath, Verbose);
  return Parser.parse();
}
}
}
<|endoftext|>


<commit_before>
#include "DelaunayTri.h"
#include "Interpolator.h"
#include "Point.h"

#include <algorithm>
#include <cassert>
#include <cmath>
#include <fstream>
#include <iostream>
#include <random>
#include <vector>

std::vector<Point> pointsToAdd(
    const double xmin, const double xmax,
    const double ymin, const double ymax)
{
  std::vector<Point> points;

  // edge points
  const int resolution = 16;
  const int nx = fabs(ceil( (xmax-xmin) * resolution));
  const int ny = fabs(ceil( (ymax-ymin) * resolution));
  for (int ix = 1; ix < nx-1; ++ix) {
    const double dx = (xmax-xmin) * ix/(nx-1.0);
    points.push_back({{xmin + dx, ymin}});
    points.push_back({{xmin + dx, ymax}});
  }
  for (int iy = 1; iy < ny-1; ++iy) {
    const double dy = (ymax-ymin) * iy/(ny-1.0);
    points.push_back({{xmin, ymin + dy}});
    points.push_back({{xmax, ymin + dy}});
  }

  // interior points
  std::random_device rd;
  std::mt19937 mt(rd());
  std::uniform_real_distribution<> dist(0,1);
  for (int i = 0; i < nx*ny; ++i) {
    const double x = xmin + dist(mt) * (xmax-xmin);
    const double y = ymin + dist(mt) * (ymax-ymin);
    points.push_back({{x, y}});
  }
  return points;
}

int main() {
  // parameters of the triangulation
  const double xmin = 0;
  const double xmax = 1;
  const double ymin = 0;
  const double ymax = 1;

  // construct triangulation
  DelaunayTri delaunay(xmin, xmax, ymin, ymax);
  {
    std::vector<Point> points = pointsToAdd(xmin, xmax, ymin, ymax);
    std::random_device rd;
    std::mt19937 mt(rd());
    std::shuffle(points.begin(), points.end(), mt);

    bool status = delaunay.addPoints(points);
    assert(status and "couldn't add points?");
    delaunay.writeToFile("triangulation.data");
  }

  // three functions to be interpolated
  // 1) x^2 * y
  // 2) exp(-5 (x-0.5)^2 + (y-0.5)^2)
  // 3) sin(6x) * cos(9y)
  const int numfns = 3;
  const size_t numpts = delaunay.getNumPoints(); // not the same as points.size() !!
  std::vector<std::vector<double>> data(numfns, std::vector<double>(numpts, 0));
  for (size_t i=0; i<numpts; ++i) {
    const double x = delaunay.point(i)[0];
    const double y = delaunay.point(i)[1];
    data[0][i] = x*x*y;
    data[1][i] = exp(-5 * ((x-0.5)*(x-0.5) + (y-0.5)*(y-0.5)));
    data[2][i] = sin(6*x) * cos(9*y);
  }

  // grid to interpolate the data onto
  const int intres = 50;
  std::vector<Point> intgrid;
  for (int iy=0; iy<intres; ++iy) {
    for (int ix=0; ix<intres; ++ix) {
      const double x = xmin + (ix/(intres-1.0)) * (xmax-xmin);
      const double y = ymin + (iy/(intres-1.0)) * (ymax-ymin);
      intgrid.push_back({{x,y}});
    }
  }

  // interpolate
  const Interpolator interp(delaunay, data);
  std::vector<std::vector<double>> intdata(numfns, std::vector<double>(intres*intres, 0));
  for (int i=0; i<intres*intres; ++i) {
    const std::vector<double> intpt = interp.evaluateAt(intgrid[i]);
    intdata[0][i] = intpt[0];
    intdata[1][i] = intpt[1];
    intdata[2][i] = intpt[2];
  }

  // print to file
  std::ofstream outfile("interpolated.data");
  for (int i=0; i<intres*intres; ++i) {
    outfile << intgrid[i][0] << "  " << intgrid[i][1] << "  "
            << intdata[0][i] << "  " << intdata[1][i] << "  " << intdata[2][i] << "\n";
  }
  outfile.close();

}
<commit_msg>main: Also dump exact function values<commit_after>
#include "DelaunayTri.h"
#include "Interpolator.h"
#include "Point.h"

#include <algorithm>
#include <cassert>
#include <cmath>
#include <fstream>
#include <iostream>
#include <random>
#include <vector>

namespace {
  std::vector<Point> pointsToAdd(
      const double xmin, const double xmax,
      const double ymin, const double ymax)
  {
    std::vector<Point> points;

    // edge points
    const int resolution = 16;
    const int nx = fabs(ceil( (xmax-xmin) * resolution));
    const int ny = fabs(ceil( (ymax-ymin) * resolution));
    for (int ix = 1; ix < nx-1; ++ix) {
      const double dx = (xmax-xmin) * ix/(nx-1.0);
      points.push_back({{xmin + dx, ymin}});
      points.push_back({{xmin + dx, ymax}});
    }
    for (int iy = 1; iy < ny-1; ++iy) {
      const double dy = (ymax-ymin) * iy/(ny-1.0);
      points.push_back({{xmin, ymin + dy}});
      points.push_back({{xmax, ymin + dy}});
    }

    // interior points
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_real_distribution<> dist(0,1);
    for (int i = 0; i < nx*ny; ++i) {
      const double x = xmin + dist(mt) * (xmax-xmin);
      const double y = ymin + dist(mt) * (ymax-ymin);
      points.push_back({{x, y}});
    }
    return points;
  }

  double f(const double x, const double y) {
    return x*x*y;
  }

  double g(const double x, const double y) {
    return exp(-5 * ((x-0.5)*(x-0.5) + (y-0.5)*(y-0.5)));
  }

  double h(const double x, const double y) {
    return sin(6*x) * cos(9*y);
  }
}

int main() {
  // parameters of the triangulation
  const double xmin = 0;
  const double xmax = 1;
  const double ymin = 0;
  const double ymax = 1;

  // construct triangulation
  DelaunayTri delaunay(xmin, xmax, ymin, ymax);
  {
    std::vector<Point> points = pointsToAdd(xmin, xmax, ymin, ymax);
    std::random_device rd;
    std::mt19937 mt(rd());
    std::shuffle(points.begin(), points.end(), mt);

    bool status = delaunay.addPoints(points);
    assert(status and "couldn't add points?");
    delaunay.writeToFile("triangulation.data");
  }

  // three functions to be interpolated
  // 1) x^2 * y
  // 2) exp(-5 (x-0.5)^2 + (y-0.5)^2)
  // 3) sin(6x) * cos(9y)
  const int numfns = 3;
  const size_t numpts = delaunay.getNumPoints(); // not the same as points.size() !!
  std::vector<std::vector<double>> data(numfns, std::vector<double>(numpts, 0));
  for (size_t i=0; i<numpts; ++i) {
    const double x = delaunay.point(i)[0];
    const double y = delaunay.point(i)[1];
    data[0][i] = f(x,y);
    data[1][i] = g(x,y);
    data[2][i] = h(x,y);
  }

  // grid to interpolate the data onto
  const int intres = 50;
  std::vector<Point> intgrid;
  for (int iy=0; iy<intres; ++iy) {
    for (int ix=0; ix<intres; ++ix) {
      const double x = xmin + (ix/(intres-1.0)) * (xmax-xmin);
      const double y = ymin + (iy/(intres-1.0)) * (ymax-ymin);
      intgrid.push_back({{x,y}});
    }
  }

  // interpolate
  const Interpolator interp(delaunay, data);
  std::vector<std::vector<double>> intdata(numfns, std::vector<double>(intres*intres, 0));
  for (int i=0; i<intres*intres; ++i) {
    const std::vector<double> intpt = interp.evaluateAt(intgrid[i]);
    intdata[0][i] = intpt[0];
    intdata[1][i] = intpt[1];
    intdata[2][i] = intpt[2];
  }

  // print to file
  std::ofstream outfile("interpolated.data");
  for (int i=0; i<intres*intres; ++i) {
    const double x = intgrid[i][0];
    const double y = intgrid[i][1];
    outfile << x << "  " << y << "  "
            << intdata[0][i] << "  " << intdata[1][i] << "  " << intdata[2][i] << "  "
            << f(x,y) << "  " << g(x,y) << "  " << h(x,y) << "\n";
  }
  outfile.close();

}
<|endoftext|>


<commit_before>8c9b6759-4b02-11e5-b647-28cfe9171a43<commit_msg>lets try again<commit_after>8ca7ebd9-4b02-11e5-afc1-28cfe9171a43<|endoftext|>


<commit_before>//
//  main.cpp
//  Plecaki
//
//  Created by Mateusz Marzęcki on 13.04.2015.
//  Copyright (c) 2015 Mateusz Marzęcki. All rights reserved.
//

#include <iostream>

int main(int argc, const char * argv[])
{

    // insert code here...
    std::cout << "Hello, World!\n";
    return 0;
}

<commit_msg>problem z alokacja pamieci dynamicznej<commit_after>#include <iostream>
#include <cstdio>

void printMap (int **table, int width, int height) {
    for (int m=0; m<height; m++) {
        for (int n=0; n<width; n++) {
            printf("%d ", table[m][n]);
        }
        printf("\n");
    }
}

int max (int a, int b) {
    return a > b ? a : b;
}

int max3(int a, int b, int c) {
    return max(a, max(b, c));
}

int main() {
    int n, weight; // items, sack1, sack2, gain, cost
    float kp1, kp2, weight_helper;
    int s1, s2, gain;

    scanf("%f %f", &kp1, &kp2);
    s1 = kp1 * 10;
    s2 = kp2 * 10;
    scanf("%d", &n);

    int **knapsack = new int *[s1];
    for (int j = 0; j < s1; j++) {
        knapsack[j] = new int [s2];
    }
    s1--;
    s2--;

    // filing knapsack
    for (int i = 0; i < n; i++) {
        scanf("%d %f", &gain, &weight_helper);
        weight = weight_helper * 10;
        for (int w1 = s1; w1 >= 0; w1--) {
            for (int w2 = s2; w2 >= 0; w2--) {
                int val1 = 0, val2 = 0;

                if(weight<=w1) {
                    val1 = knapsack[w1 - weight][w2] + gain;
                }
                if(weight<=w2) {
                    val2 = knapsack[w1][w2 - weight] + gain;
                }

                knapsack[w1][w2] = max3(
                        knapsack[w1][w2]                   // we have best option
                        ,val1              // put into sack one
                        ,val2               // put into sack two
                );

                printMap(knapsack, s2, s1);
                printf("---------------\n");
            }
        }
    }
    printf("\n\n");
    printMap(knapsack, s2+1, s1+1);
    printf("\n%d %d\n%d\n", s1, s2, knapsack[s1][s2]);

    return 0;
}<|endoftext|>


<commit_before>29ff17e8-2748-11e6-b14f-e0f84713e7b8<commit_msg>This'll fix that<commit_after>2a0f3fc5-2748-11e6-b348-e0f84713e7b8<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <vector>
#include <ostream>
#include <string>
#include "ast.h"
#include "generator.h"
#include "ecc.tab.h"

extern int _yylex(void);

#define YY_NULL (0)

namespace ecc
{
    extern const std::string version = "ecc v0.0alpha"; /**< Version string */
    ast::elist_t MasterList;				/**< Parser places output here */
    ast::enumdef* CurrentEnumDef;			/**< Used during parsing */
}

namespace
{
    /** Holds a pointer to the current input stream, for ecc::input to access */
    std::istream* pStream;

    /** String to print in the event that the command line is malformed */
    const std::string StrMalformed = "Usage: ecc -c <infile> [-o <outfile>]";
    const std::string StrFilespec = "Input cannot be the same file as the output";

    /** Name of the input file */
    std::string inputFile="";

    /** Name of the output file */
    std::string outputFile="";

    /** Valid set of exit status codes */
    enum class es
    {
	ok=0,			/**< Command completed successfully */
	badParams=1,		/**< Bad command line / options */
	inputError=2,		/**< Couldn't open or read the input file */
        outputError=3,	        /**< Couldn't create or write the output file */
	syntaxError=4 	        /**< Malformed input file */
    };

}

namespace ecc
{
    /** Provides stream input functionality to the lexer. */
    void input(char* buf, int& result, size_t max_size)
    {
 	if (pStream->peek()==EOF)
 	    result = YY_NULL;
 	else
	{
	    pStream->read(buf,max_size);
	    result = pStream->gcount();
 	}

    }

}

/**
 * Included for future use
 */
int yylex(void) { return _yylex(); }

/** Parses input options */
static es parse_options(int argc, char** argv)
{
    // Skip over executable name
    argc--; argv++;

    // Check minimum params
    if (argc<2)
	goto malformed;

    // Loop over param pairs
    while (argc)
    {
	const std::string option(*argv); argc--; argv++;

	if ( (!argc) || (option[0]!='-') ) goto malformed;

	const std::string param(*argv); argc--; argv++;

	switch (option[1])
	{
	case 'c':
	    inputFile = param;
	    break;

	case 'o':
	    outputFile = param;
	    break;

	default:
	    goto malformed;
	}

    }

    // Check that we got mandatory options
    if ( inputFile.length() < 1 )
	goto malformed;

    // If no output file was set, calculate name from input file
    if ( outputFile.length() < 1 )
    {
	size_t index_ext = inputFile.rfind('.');
	size_t index_leaf = inputFile.rfind('/');

	if ( (index_ext == std::string::npos)
	     || ( index_leaf!=std::string::npos && (index_leaf > index_ext) ) )
	{
	    // There's no file extension, simply add one
	    outputFile = inputFile + ".c";
	}
	else
	{
	    // There is a file extension
	    outputFile = inputFile.substr(0,index_ext) + ".c";
	}
    }

    // Check that the input and output files are different
    if ( inputFile==outputFile) goto filespec;

    // All good
    return es::ok;

malformed:
    std::cerr << StrMalformed << std::endl;
    return es::badParams;

filespec:
    std::cerr << StrFilespec << std::endl;
    return es::badParams;

}

/**
 * Main execution loop of the ecc utility
 */
int main(int argc, char** argv)
{
    es exit_code=es::ok;

    // Parse the command line parameters
    if (es::ok!=(exit_code = parse_options(argc,argv)))
	exit((int)exit_code);

    // Set up example input
    std::stringstream ss;

    ss << "typedef enum { frog=9, tree, banana = 7 } enum_t;"
       << "typedef enum { willow } other_t;";

    // Tell the scanner where to get its input
    std::ifstream fs(inputFile);
    pStream = &fs;

    // Parse the stream
    yyparse();

    fs.close();

    // Generate the output (defaults to std::cout)
    ecc::generator* pGen = new ecc::defgen();
    pGen->translate( ecc::MasterList );
    delete pGen;

    exit((int)es::ok);
}
<commit_msg>Added output file functionality<commit_after>#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <vector>
#include <ostream>
#include <string>
#include "ast.h"
#include "generator.h"
#include "ecc.tab.h"

extern int _yylex(void);

#define YY_NULL (0)

namespace ecc
{
    extern const std::string version = "ecc v0.0alpha"; /**< Version string */
    ast::elist_t MasterList;				/**< Parser places output here */
    ast::enumdef* CurrentEnumDef;			/**< Used during parsing */
}

namespace
{
    /** Holds a pointer to the current input stream, for ecc::input to access */
    std::istream* pStream;

    /** String to print in the event that the command line is malformed */
    const std::string StrMalformed = "Usage: ecc -c <infile> [-o <outfile>]";
    const std::string StrFilespec = "ERROR: Input cannot be the same file as the output";
    const std::string StrOpenInputFailed = "ERROR: Cannot open input file ";
    const std::string StrOpenOutputFailed = "ERROR: Cannot open output file ";

    /** Name of the input file */
    std::string inputFile="";

    /** Name of the output file */
    std::string outputFile="";

    /** Valid set of exit status codes */
    enum class es
    {
	ok=0,			/**< Command completed successfully */
	badParams=1,		/**< Bad command line / options */
	inputError=2,		/**< Couldn't open or read the input file */
        outputError=3,	        /**< Couldn't create or write the output file */
	syntaxError=4 	        /**< Malformed input file */
    };

}

namespace ecc
{
    /** Provides stream input functionality to the lexer. */
    void input(char* buf, int& result, size_t max_size)
    {
 	if (pStream->peek()==EOF)
 	    result = YY_NULL;
 	else
	{
	    pStream->read(buf,max_size);
	    result = pStream->gcount();
 	}

    }

}

/**
 * Included for future use
 */
int yylex(void) { return _yylex(); }

/** Parses input options */
static es parse_options(int argc, char** argv)
{
    // Skip over executable name
    argc--; argv++;

    // Check minimum params
    if (argc<2)
	goto malformed;

    // Loop over param pairs
    while (argc)
    {
	const std::string option(*argv); argc--; argv++;

	if ( (!argc) || (option[0]!='-') ) goto malformed;

	const std::string param(*argv); argc--; argv++;

	switch (option[1])
	{
	case 'c':
	    inputFile = param;
	    break;

	case 'o':
	    outputFile = param;
	    break;

	default:
	    goto malformed;
	}

    }

    // Check that we got mandatory options
    if ( inputFile.length() < 1 )
	goto malformed;

    // If no output file was set, calculate name from input file
    if ( outputFile.length() < 1 )
    {
	size_t index_ext = inputFile.rfind('.');
	size_t index_leaf = inputFile.rfind('/');

	if ( (index_ext == std::string::npos)
	     || ( index_leaf!=std::string::npos && (index_leaf > index_ext) ) )
	{
	    // There's no file extension, simply add one
	    outputFile = inputFile + ".c";
	}
	else
	{
	    // There is a file extension
	    outputFile = inputFile.substr(0,index_ext) + ".c";
	}
    }

    // Check that the input and output files are different
    if ( inputFile==outputFile) goto filespec;

    // All good
    return es::ok;

malformed:
    std::cerr << StrMalformed << std::endl;
    return es::badParams;

filespec:
    std::cerr << StrFilespec << std::endl;
    return es::badParams;

}

/**
 * Main execution loop of the ecc utility
 */
int main(int argc, char** argv)
{
    es exit_code=es::ok;

    // Parse the command line parameters
    if (es::ok!=(exit_code = parse_options(argc,argv)))
	exit((int)exit_code);

    // Attempt to open the input file
    std::ifstream ifs(inputFile);

    if (ifs.fail() )
    {
	std::cerr << StrOpenInputFailed << inputFile << std::endl;
	exit((int)es::inputError);
    }

    // Tell the scanner where to get its input
    pStream = &ifs;

    // Parse the stream, close the input
    yyparse();
    ifs.close();

    // Attempt to open the output file
    std::ofstream ofs(outputFile, std::ofstream::trunc);

    if ( ofs.fail() )
    {
	std::cerr << StrOpenOutputFailed << outputFile << std::endl;
	exit((int)es::outputError);
    }

    // Generate the output (defaults to std::cout)
    ecc::generator* pGen = new ecc::defgen();
    pGen->translate( ecc::MasterList, ofs );
    delete pGen;

    ofs.close();

    exit((int)es::ok);
}
<|endoftext|>


<commit_before>
/*

Copyright (c) 2007, 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/bind.hpp>
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/connection_queue.hpp"
#include "libtorrent/socket.hpp"

namespace libtorrent
{

	connection_queue::connection_queue(io_service& ios): m_next_ticket(0)
		, m_num_connecting(0)
		, m_half_open_limit(0)
		, m_abort(false)
		, m_timer(ios)
#ifndef NDEBUG
		, m_in_timeout_function(false)
#endif
	{
#ifdef TORRENT_CONNECTION_LOGGING
		m_log.open("connection_queue.log");
#endif
	}

	int connection_queue::free_slots() const
	{
		mutex_t::scoped_lock l(m_mutex);
		return m_half_open_limit == 0 ? (std::numeric_limits<int>::max)()
			: m_half_open_limit - m_queue.size();
	}

	void connection_queue::enqueue(boost::function<void(int)> const& on_connect
		, boost::function<void()> const& on_timeout
		, time_duration timeout, int priority)
	{
		mutex_t::scoped_lock l(m_mutex);

		INVARIANT_CHECK;

		TORRENT_ASSERT(priority >= 0);
		TORRENT_ASSERT(priority < 2);

		entry* e = 0;

		switch (priority)
		{
			case 0:
				m_queue.push_back(entry());
				e = &m_queue.back();
				break;
			case 1:
				m_queue.push_front(entry());
				e = &m_queue.front();
				break;
		}

		e->priority = priority;
		e->on_connect = on_connect;
		e->on_timeout = on_timeout;
		e->ticket = m_next_ticket;
		e->timeout = timeout;
		++m_next_ticket;
		try_connect();
	}

	void connection_queue::done(int ticket)
	{
		mutex_t::scoped_lock l(m_mutex);

		INVARIANT_CHECK;

		std::list<entry>::iterator i = std::find_if(m_queue.begin()
			, m_queue.end(), boost::bind(&entry::ticket, _1) == ticket);
		if (i == m_queue.end())
		{
			// this might not be here in case on_timeout calls remove
			return;
		}
		if (i->connecting) --m_num_connecting;
		m_queue.erase(i);
		try_connect();
	}

	void connection_queue::close()
	{
		error_code ec;
		mutex_t::scoped_lock l(m_mutex);
		m_timer.cancel(ec);
		m_abort = true;

		while (!m_queue.empty())
		{
			// we don't want to call the timeout callback while we're locked
			// since that is a recepie for dead-locks
			l.unlock();
			try { m_queue.front().on_timeout(); } catch (std::exception&) {}
			l.lock();
			m_queue.pop_front();
		}
	}

	void connection_queue::limit(int limit)
	{
		TORRENT_ASSERT(limit >= 0);
		m_half_open_limit = limit;
	}

	int connection_queue::limit() const
	{ return m_half_open_limit; }

#ifndef NDEBUG

	void connection_queue::check_invariant() const
	{
		int num_connecting = 0;
		for (std::list<entry>::const_iterator i = m_queue.begin();
			i != m_queue.end(); ++i)
		{
			if (i->connecting) ++num_connecting;
		}
		TORRENT_ASSERT(num_connecting == m_num_connecting);
	}

#endif

	void connection_queue::try_connect()
	{
		INVARIANT_CHECK;

#ifdef TORRENT_CONNECTION_LOGGING
		m_log << log_time() << " " << free_slots() << std::endl;
#endif
		if (m_abort) return;

		if (m_num_connecting >= m_half_open_limit
			&& m_half_open_limit > 0) return;

		if (m_queue.empty())
		{
			error_code ec;
			m_timer.cancel(ec);
			return;
		}

		std::list<entry>::iterator i = std::find_if(m_queue.begin()
			, m_queue.end(), boost::bind(&entry::connecting, _1) == false);
		while (i != m_queue.end())
		{
			TORRENT_ASSERT(i->connecting == false);
			ptime expire = time_now() + i->timeout;
			if (m_num_connecting == 0)
			{
				error_code ec;
				m_timer.expires_at(expire, ec);
				m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
			}
			i->connecting = true;
			++m_num_connecting;
			i->expires = expire;

			INVARIANT_CHECK;

			entry& ent = *i;
			++i;
#ifndef BOOST_NO_EXCEPTIONS
			try {
#endif
				ent.on_connect(ent.ticket);
#ifndef BOOST_NO_EXCEPTIONS
			} catch (std::exception&) {}
#endif

#ifdef TORRENT_CONNECTION_LOGGING
			m_log << log_time() << " " << free_slots() << std::endl;
#endif

			if (m_num_connecting >= m_half_open_limit
				&& m_half_open_limit > 0) break;
			i = std::find_if(i, m_queue.end(), boost::bind(&entry::connecting, _1) == false);
		}
	}

#ifndef NDEBUG
	struct function_guard
	{
		function_guard(bool& v): val(v) { TORRENT_ASSERT(!val); val = true; }
		~function_guard() { val = false; }

		bool& val;
	};
#endif

	void connection_queue::on_timeout(error_code const& e)
	{
		mutex_t::scoped_lock l(m_mutex);

		INVARIANT_CHECK;
#ifndef NDEBUG
		function_guard guard_(m_in_timeout_function);
#endif

		TORRENT_ASSERT(!e || e == asio::error::operation_aborted);
		if (e) return;

		ptime next_expire = max_time();
		ptime now = time_now();
		std::list<entry> timed_out;
		for (std::list<entry>::iterator i = m_queue.begin();
			!m_queue.empty() && i != m_queue.end();)
		{
			if (i->connecting && i->expires < now)
			{
				std::list<entry>::iterator j = i;
				++i;
				timed_out.splice(timed_out.end(), m_queue, j, i);
				--m_num_connecting;
				continue;
			}
			if (i->expires < next_expire)
				next_expire = i->expires;
			++i;
		}

		// we don't want to call the timeout callback while we're locked
		// since that is a recepie for dead-locks
		l.unlock();

		for (std::list<entry>::iterator i = timed_out.begin()
			, end(timed_out.end()); i != end; ++i)
		{
			try { i->on_timeout(); } catch (std::exception&) {}
		}

		l.lock();

		if (next_expire < max_time())
		{
			error_code ec;
			m_timer.expires_at(next_expire, ec);
			m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
		}
		try_connect();
	}

}

<commit_msg>connection_queue::close() fix<commit_after>
/*

Copyright (c) 2007, 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/bind.hpp>
#include "libtorrent/invariant_check.hpp"
#include "libtorrent/connection_queue.hpp"
#include "libtorrent/socket.hpp"

namespace libtorrent
{

	connection_queue::connection_queue(io_service& ios): m_next_ticket(0)
		, m_num_connecting(0)
		, m_half_open_limit(0)
		, m_abort(false)
		, m_timer(ios)
#ifndef NDEBUG
		, m_in_timeout_function(false)
#endif
	{
#ifdef TORRENT_CONNECTION_LOGGING
		m_log.open("connection_queue.log");
#endif
	}

	int connection_queue::free_slots() const
	{
		mutex_t::scoped_lock l(m_mutex);
		return m_half_open_limit == 0 ? (std::numeric_limits<int>::max)()
			: m_half_open_limit - m_queue.size();
	}

	void connection_queue::enqueue(boost::function<void(int)> const& on_connect
		, boost::function<void()> const& on_timeout
		, time_duration timeout, int priority)
	{
		mutex_t::scoped_lock l(m_mutex);

		INVARIANT_CHECK;

		TORRENT_ASSERT(priority >= 0);
		TORRENT_ASSERT(priority < 2);

		entry* e = 0;

		switch (priority)
		{
			case 0:
				m_queue.push_back(entry());
				e = &m_queue.back();
				break;
			case 1:
				m_queue.push_front(entry());
				e = &m_queue.front();
				break;
		}

		e->priority = priority;
		e->on_connect = on_connect;
		e->on_timeout = on_timeout;
		e->ticket = m_next_ticket;
		e->timeout = timeout;
		++m_next_ticket;
		try_connect();
	}

	void connection_queue::done(int ticket)
	{
		mutex_t::scoped_lock l(m_mutex);

		INVARIANT_CHECK;

		std::list<entry>::iterator i = std::find_if(m_queue.begin()
			, m_queue.end(), boost::bind(&entry::ticket, _1) == ticket);
		if (i == m_queue.end())
		{
			// this might not be here in case on_timeout calls remove
			return;
		}
		if (i->connecting) --m_num_connecting;
		m_queue.erase(i);
		try_connect();
	}

	void connection_queue::close()
	{
		error_code ec;
		mutex_t::scoped_lock l(m_mutex);
		m_timer.cancel(ec);
		m_abort = true;

		while (!m_queue.empty())
		{
			// we don't want to call the timeout callback while we're locked
			// since that is a recepie for dead-locks
			entry e = m_queue.front();
			m_queue.pop_front();
			l.unlock();
			try { e.on_timeout(); } catch (std::exception&) {}
			l.lock();
		}
	}

	void connection_queue::limit(int limit)
	{
		TORRENT_ASSERT(limit >= 0);
		m_half_open_limit = limit;
	}

	int connection_queue::limit() const
	{ return m_half_open_limit; }

#ifndef NDEBUG

	void connection_queue::check_invariant() const
	{
		int num_connecting = 0;
		for (std::list<entry>::const_iterator i = m_queue.begin();
			i != m_queue.end(); ++i)
		{
			if (i->connecting) ++num_connecting;
		}
		TORRENT_ASSERT(num_connecting == m_num_connecting);
	}

#endif

	void connection_queue::try_connect()
	{
		INVARIANT_CHECK;

#ifdef TORRENT_CONNECTION_LOGGING
		m_log << log_time() << " " << free_slots() << std::endl;
#endif
		if (m_abort) return;

		if (m_num_connecting >= m_half_open_limit
			&& m_half_open_limit > 0) return;

		if (m_queue.empty())
		{
			error_code ec;
			m_timer.cancel(ec);
			return;
		}

		std::list<entry>::iterator i = std::find_if(m_queue.begin()
			, m_queue.end(), boost::bind(&entry::connecting, _1) == false);
		while (i != m_queue.end())
		{
			TORRENT_ASSERT(i->connecting == false);
			ptime expire = time_now() + i->timeout;
			if (m_num_connecting == 0)
			{
				error_code ec;
				m_timer.expires_at(expire, ec);
				m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
			}
			i->connecting = true;
			++m_num_connecting;
			i->expires = expire;

			INVARIANT_CHECK;

			entry& ent = *i;
			++i;
#ifndef BOOST_NO_EXCEPTIONS
			try {
#endif
				ent.on_connect(ent.ticket);
#ifndef BOOST_NO_EXCEPTIONS
			} catch (std::exception&) {}
#endif

#ifdef TORRENT_CONNECTION_LOGGING
			m_log << log_time() << " " << free_slots() << std::endl;
#endif

			if (m_num_connecting >= m_half_open_limit
				&& m_half_open_limit > 0) break;
			i = std::find_if(i, m_queue.end(), boost::bind(&entry::connecting, _1) == false);
		}
	}

#ifndef NDEBUG
	struct function_guard
	{
		function_guard(bool& v): val(v) { TORRENT_ASSERT(!val); val = true; }
		~function_guard() { val = false; }

		bool& val;
	};
#endif

	void connection_queue::on_timeout(error_code const& e)
	{
		mutex_t::scoped_lock l(m_mutex);

		INVARIANT_CHECK;
#ifndef NDEBUG
		function_guard guard_(m_in_timeout_function);
#endif

		TORRENT_ASSERT(!e || e == asio::error::operation_aborted);
		if (e) return;

		ptime next_expire = max_time();
		ptime now = time_now();
		std::list<entry> timed_out;
		for (std::list<entry>::iterator i = m_queue.begin();
			!m_queue.empty() && i != m_queue.end();)
		{
			if (i->connecting && i->expires < now)
			{
				std::list<entry>::iterator j = i;
				++i;
				timed_out.splice(timed_out.end(), m_queue, j, i);
				--m_num_connecting;
				continue;
			}
			if (i->expires < next_expire)
				next_expire = i->expires;
			++i;
		}

		// we don't want to call the timeout callback while we're locked
		// since that is a recepie for dead-locks
		l.unlock();

		for (std::list<entry>::iterator i = timed_out.begin()
			, end(timed_out.end()); i != end; ++i)
		{
			try { i->on_timeout(); } catch (std::exception&) {}
		}

		l.lock();

		if (next_expire < max_time())
		{
			error_code ec;
			m_timer.expires_at(next_expire, ec);
			m_timer.async_wait(boost::bind(&connection_queue::on_timeout, this, _1));
		}
		try_connect();
	}

}

<|endoftext|>


<commit_before>// Copyright (c) 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "local_redundancy_elimination.h"

#include "value_number_table.h"

namespace spvtools {
namespace opt {

Pass::Status LocalRedundancyEliminationPass::Process(ir::IRContext* c) {
  InitializeProcessing(c);

  bool modified = false;
  ValueNumberTable vnTable(context());

  for (auto& func : *get_module()) {
    for (auto& bb : func) {
      // Keeps track of all ids that contain a given value number. We keep
      // track of multiple values because they could have the same value, but
      // different decorations.
      std::map<uint32_t, uint32_t> value_to_ids;
      if (EliminateRedundanciesInBB(&bb, vnTable, &value_to_ids))
        modified = true;
    }
  }
  return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange);
}

bool LocalRedundancyEliminationPass::EliminateRedundanciesInBB(
    ir::BasicBlock* block, const ValueNumberTable& vnTable,
    std::map<uint32_t, uint32_t>* value_to_ids) {
  bool modified = false;

  auto func = [this, vnTable, &modified, value_to_ids](ir::Instruction* inst) {
    if (inst->result_id() == 0) {
      return;
    }

    uint32_t value = vnTable.GetValueNumber(inst);

    if (value == 0) {
      return;
    }

    auto candidate = value_to_ids->insert({value, inst->result_id()});
    if (!candidate.second) {
      context()->KillNamesAndDecorates(inst);
      context()->ReplaceAllUsesWith(inst->result_id(), candidate.first->second);
      context()->KillInst(inst);
      modified = true;
    }
  };
  block->ForEachInst(func);
  return modified;
}
}  // namespace opt
}  // namespace spvtools
<commit_msg>Capturing value table by reference in local redundancy elim<commit_after>// Copyright (c) 2017 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "local_redundancy_elimination.h"

#include "value_number_table.h"

namespace spvtools {
namespace opt {

Pass::Status LocalRedundancyEliminationPass::Process(ir::IRContext* c) {
  InitializeProcessing(c);

  bool modified = false;
  ValueNumberTable vnTable(context());

  for (auto& func : *get_module()) {
    for (auto& bb : func) {
      // Keeps track of all ids that contain a given value number. We keep
      // track of multiple values because they could have the same value, but
      // different decorations.
      std::map<uint32_t, uint32_t> value_to_ids;
      if (EliminateRedundanciesInBB(&bb, vnTable, &value_to_ids))
        modified = true;
    }
  }
  return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange);
}

bool LocalRedundancyEliminationPass::EliminateRedundanciesInBB(
    ir::BasicBlock* block, const ValueNumberTable& vnTable,
    std::map<uint32_t, uint32_t>* value_to_ids) {
  bool modified = false;

  auto func = [this, &vnTable, &modified, value_to_ids](ir::Instruction* inst) {
    if (inst->result_id() == 0) {
      return;
    }

    uint32_t value = vnTable.GetValueNumber(inst);

    if (value == 0) {
      return;
    }

    auto candidate = value_to_ids->insert({value, inst->result_id()});
    if (!candidate.second) {
      context()->KillNamesAndDecorates(inst);
      context()->ReplaceAllUsesWith(inst->result_id(), candidate.first->second);
      context()->KillInst(inst);
      modified = true;
    }
  };
  block->ForEachInst(func);
  return modified;
}
}  // namespace opt
}  // namespace spvtools
<|endoftext|>


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

#ifndef SD_TOOLPANEL_CONTROLS_RECENTLY_USED_MASTER_PAGES_HXX
#define SD_TOOLPANEL_CONTROLS_RECENTLY_USED_MASTER_PAGES_HXX

#include "tools/SdGlobalResourceContainer.hxx"
#include <osl/mutex.hxx>
#include <tools/link.hxx>
#include <vcl/image.hxx>
#include <vector>
#include <tools/string.hxx>

#include "DrawDocShell.hxx"
#include "MasterPageContainer.hxx"

#ifndef _COM_SUN_STAR_UNO_XINTERFACE_HPP_
#include <com/sun/star/uno/XInterface.hpp>
#endif

class SdPage;

namespace sd {
class MasterPageObserverEvent;
}

namespace sd { namespace toolpanel { namespace controls {

/** This singleton holds a list of the most recently used master pages.
*/
class RecentlyUsedMasterPages
    : public SdGlobalResource
{
public:
    /** Return the single instance of this class.
    */
    static RecentlyUsedMasterPages& Instance (void);

    void AddEventListener (const Link& rEventListener);
    void RemoveEventListener (const Link& rEventListener);

    int GetMasterPageCount (void) const;
    MasterPageContainer::Token GetTokenForIndex (sal_uInt32 nIndex) const;

private:
    /** The single instance of this class.  It is created on demand when
        Instance() is called for the first time.
    */
    static RecentlyUsedMasterPages* mpInstance;

    ::std::vector<Link> maListeners;

    class MasterPageList;
    ::std::auto_ptr<MasterPageList> mpMasterPages;
    unsigned long int mnMaxListSize;
    ::boost::shared_ptr<MasterPageContainer> mpContainer;

    RecentlyUsedMasterPages (void);
    virtual ~RecentlyUsedMasterPages (void);

    /** Call this method after a new object has been created.
    */
    void LateInit (void);

    /// The copy constructor is not implemented.  Do not use!
    RecentlyUsedMasterPages (const RecentlyUsedMasterPages&);

    /// The assignment operator is not implemented.  Do not use!
    RecentlyUsedMasterPages& operator= (const RecentlyUsedMasterPages&);

    void SendEvent (void);
    DECL_LINK(MasterPageChangeListener, MasterPageObserverEvent*);
    DECL_LINK(MasterPageContainerChangeListener, MasterPageContainerChangeEvent*);

    /** Add a descriptor for the specified master page to the end of the
        list of most recently used master pages.  When the page is already a
        member of that list the associated descriptor is moved to the end of
        the list to make it the most recently used entry.
        @param bMakePersistent
            When <TRUE/> is given then the new list of recently used master
            pages is written back into the configuration to make it
            persistent.  Giving <FALSE/> to ommit this is used while loading
            the persistent list from the configuration.
    */
    void AddMasterPage (
        MasterPageContainer::Token aToken,
        bool bMakePersistent = true);

    /** Load the list of recently used master pages from the registry where
        it was saved to make it persistent.
    */
    void LoadPersistentValues (void);

    /** Save the list of recently used master pages to the registry to make
        it presistent.
    */
    void SavePersistentValues (void);

    void ResolveList (void);
};

} } } // end of namespace ::sd::toolpanel::controls

#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.8.234); FILE MERGED 2008/04/01 12:39:22 thb 1.8.234.2: #i85898# Stripping all external header guards 2008/03/31 13:59:03 rt 1.8.234.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: RecentlyUsedMasterPages.hxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef SD_TOOLPANEL_CONTROLS_RECENTLY_USED_MASTER_PAGES_HXX
#define SD_TOOLPANEL_CONTROLS_RECENTLY_USED_MASTER_PAGES_HXX

#include "tools/SdGlobalResourceContainer.hxx"
#include <osl/mutex.hxx>
#include <tools/link.hxx>
#include <vcl/image.hxx>
#include <vector>
#include <tools/string.hxx>

#include "DrawDocShell.hxx"
#include "MasterPageContainer.hxx"
#include <com/sun/star/uno/XInterface.hpp>

class SdPage;

namespace sd {
class MasterPageObserverEvent;
}

namespace sd { namespace toolpanel { namespace controls {

/** This singleton holds a list of the most recently used master pages.
*/
class RecentlyUsedMasterPages
    : public SdGlobalResource
{
public:
    /** Return the single instance of this class.
    */
    static RecentlyUsedMasterPages& Instance (void);

    void AddEventListener (const Link& rEventListener);
    void RemoveEventListener (const Link& rEventListener);

    int GetMasterPageCount (void) const;
    MasterPageContainer::Token GetTokenForIndex (sal_uInt32 nIndex) const;

private:
    /** The single instance of this class.  It is created on demand when
        Instance() is called for the first time.
    */
    static RecentlyUsedMasterPages* mpInstance;

    ::std::vector<Link> maListeners;

    class MasterPageList;
    ::std::auto_ptr<MasterPageList> mpMasterPages;
    unsigned long int mnMaxListSize;
    ::boost::shared_ptr<MasterPageContainer> mpContainer;

    RecentlyUsedMasterPages (void);
    virtual ~RecentlyUsedMasterPages (void);

    /** Call this method after a new object has been created.
    */
    void LateInit (void);

    /// The copy constructor is not implemented.  Do not use!
    RecentlyUsedMasterPages (const RecentlyUsedMasterPages&);

    /// The assignment operator is not implemented.  Do not use!
    RecentlyUsedMasterPages& operator= (const RecentlyUsedMasterPages&);

    void SendEvent (void);
    DECL_LINK(MasterPageChangeListener, MasterPageObserverEvent*);
    DECL_LINK(MasterPageContainerChangeListener, MasterPageContainerChangeEvent*);

    /** Add a descriptor for the specified master page to the end of the
        list of most recently used master pages.  When the page is already a
        member of that list the associated descriptor is moved to the end of
        the list to make it the most recently used entry.
        @param bMakePersistent
            When <TRUE/> is given then the new list of recently used master
            pages is written back into the configuration to make it
            persistent.  Giving <FALSE/> to ommit this is used while loading
            the persistent list from the configuration.
    */
    void AddMasterPage (
        MasterPageContainer::Token aToken,
        bool bMakePersistent = true);

    /** Load the list of recently used master pages from the registry where
        it was saved to make it persistent.
    */
    void LoadPersistentValues (void);

    /** Save the list of recently used master pages to the registry to make
        it presistent.
    */
    void SavePersistentValues (void);

    void ResolveList (void);
};

} } } // end of namespace ::sd::toolpanel::controls

#endif
<|endoftext|>


<commit_before>/*
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "QtBackend.h"
#include <QKeyEvent>
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <boost/format.hpp>
#include <iostream>
#include "../exceptions.h"

#ifdef _WIN32
#include <windows.h>
#endif

#ifdef _WIN32
HBITMAP screen_bmp = 0;
void *oldPixels = 0;
#endif

QtBackend::QtBackend() {
	viewport = 0;
	needsrender = false;

	for (unsigned int i = 0; i < 256; i++) {
		downkeys[i] = false;
	}
}

void QtBackend::shutdown() {
	if (!viewport) return;

#ifdef _WIN32
	if (screen_bmp) DeleteObject(screen_bmp);

	SDL_Surface *surf = getMainSDLSurface();
	if (surf) surf->pixels = oldPixels;
#endif

	SDLBackend::shutdown();
}

void QtBackend::init() {
}

void QtBackend::setup(QWidget *vp) {
	viewport = vp;

#if defined(Q_WS_X11)
	// on X11, using SDL_WINDOWID works, thank goodness.
	static char windowid_str[64]; // possibly big, but who cares
	((QApplication *)QApplication::instance())->syncX();

	if (sizeof windowid_str <=
			snprintf(windowid_str, sizeof windowid_str, "SDL_WINDOWID=0x%lx", viewport->winId())) {
		std::cerr << "windowid_str buffer was too small - how big are your longs, anyway? Panicing..." << std::endl;
		abort();
	}
	// ->winId() may have created the window for us
	((QApplication *)QApplication::instance())->syncX();
	putenv(windowid_str);
#else
	// alas, it sucks on Windows and OS X, so we use an offscreen buffer instead
	putenv("SDL_VIDEODRIVER=dummy");
#endif

	SDLBackend::init();

	/*
	char videodrivername[200];
	std::cout << "SDL video driver: " << SDL_VideoDriverName(videodrivername, 200) << std::endl;
	std::cout << "SDL requested colour depth: " << idealBpp() << std::endl;
	*/

	viewport->setCursor(Qt::BlankCursor);
}

int QtBackend::idealBpp() {
#if defined(Q_WS_X11)
	return SDLBackend::idealBpp();
#endif

	// TODO: handle 8bpp for C1

#ifdef _WIN32
	// TODO: how to pick up real depth on windows?
	if (viewport->depth() == 16) return 16;
	return 24;
#endif

	return 32;
}

void QtBackend::resized(int w, int h) {
	resizeNotify(w, h);

#ifdef _WIN32
	// We need to construct a DIB for blitting, based on the surface data.

	// Delete the old one if needed.
	if (screen_bmp) DeleteObject(screen_bmp);

	// Setup a BITMAPINFO structure for this.
	BITMAPINFO *binfo = (BITMAPINFO *)malloc(sizeof(BITMAPINFO) + 12); // TODO: wrong wrong wrong
	binfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	binfo->bmiHeader.biPlanes = 1;
	binfo->bmiHeader.biClrUsed = 0;
	binfo->bmiHeader.biClrImportant = 0;

	binfo->bmiHeader.biXPelsPerMeter = 0;
	binfo->bmiHeader.biYPelsPerMeter = 0;

	SDL_Surface *surf = getMainSDLSurface();
	assert(idealBpp() == surf->format->BitsPerPixel);

	// Set the relevant entries of the structure.
	binfo->bmiHeader.biWidth = w;
	binfo->bmiHeader.biHeight = -h;
	binfo->bmiHeader.biSizeImage = w * h * (idealBpp() / 8);
	binfo->bmiHeader.biBitCount = idealBpp();

	// Describe the format of the data and any additional information needed (eg masks/palette)
	if (idealBpp() == 16) {
		binfo->bmiHeader.biCompression = BI_BITFIELDS;
		unsigned int *masks = (unsigned int *)binfo->bmiColors;
		masks[0] = surf->format->Rmask;
		masks[1] = surf->format->Gmask;
		masks[2] = surf->format->Bmask;
	} else {
		binfo->bmiHeader.biCompression = BI_RGB;
		if (idealBpp() == 8) {
			// TODO: set binfo.bmiColors
		}
	}

	// Create the actual DIB.
	void *pixels = 0;
	HDC hdc = GetDC(viewport->winId());
	screen_bmp = CreateDIBSection(hdc, binfo, DIB_RGB_COLORS, (void **)(&pixels), NULL, 0);
	ReleaseDC(viewport->winId(), hdc);

	// Free the BITMAPINFO structure now we're done with it.
	free(binfo);

	// TODO: fall back to Qt?
	if (!screen_bmp || !pixels) {
		// Windows helpfully provides no useful error information :(
		throw creaturesException("Internal error: failed to create DIB");
	}

	// TODO: Observe how this helpfully stomps over surf->pixels. :-/
	oldPixels = surf->pixels; // store so we can restore before SDL shutdown
	surf->pixels = pixels;

	// So, CreateDIBSection doesn't pay a lot of attention to what we ask for.
	// Let's snaffle the information back from the DIB object.
	// TODO: Observe how this helpfully stomps over surf->w/h/pitch. :-/
	BITMAP dibsection;
	GetObject(screen_bmp, sizeof(BITMAP), &dibsection);
	surf->w = dibsection.bmWidth;
	surf->h = dibsection.bmHeight;
	surf->pitch = dibsection.bmWidthBytes;
	assert(dibsection.bmBitsPixel == surf->format->BitsPerPixel);

#endif

	// add resize window event to backend queue
	SomeEvent e;
	e.type = eventresizewindow;
	e.x = w;
	e.y = h;
	pushEvent(e);
}

void QtBackend::renderDone() {
	needsrender = false;

	// If we're not on X11, we need to copy the contents of the offscreen buffer into the window.

#if defined(_WIN32)
	// We need to blit from the DIB we made earlier. Easy!
	HDC hdc, mdc;
	SDL_Surface *surf = getMainSDLSurface(); // for width/height

	// Obtain the DC for our viewport and create a compatible one, then select the DIB into it.
	hdc = GetDC(viewport->winId());
	mdc = CreateCompatibleDC(hdc);
	SelectObject(mdc, screen_bmp);

	// Blit!
	BitBlt(hdc, 0, 0, surf->w, surf->h, mdc, 0, 0, SRCCOPY);

	// Tidy up by deleting our temporary one and releasing the viewport DC.
	DeleteDC(mdc);
	ReleaseDC(viewport->winId(), hdc);

	// TODO: call GdiFlush? SDL doesn't seem to bother.

#elif !defined(Q_WS_X11)
	// As a generic method, we use Qt's code.
	// Note that we don't bother to lock because we know the dummy driver doesn't bother with locking.

	SDL_Surface *surf = getMainSDLSurface();
	QImage img((uchar *)surf->pixels, surf->w, surf->h, QImage::Format_RGB32);
	QPainter painter(viewport);
	painter.drawImage(0, 0, img);
#endif
}

bool QtBackend::pollEvent(SomeEvent &e) {
	// obtain events from backend
	if (SDLBackend::pollEvent(e)) return true;

	if (events.size() == 0)
		return false;

	e = events.front();
	events.pop_front();
	return true;
}

void QtBackend::pushEvent(SomeEvent e) {
	events.push_back(e);
}

// TODO: handle f keys (112-123 under windows, SDLK_F1 = 282 under sdl)
// see SDLBackend

int translateQtKey(int qtkey) {
	switch (qtkey) {
		case Qt::Key_Backspace: return 8;
		case Qt::Key_Tab: return 9;
		case Qt::Key_Clear: return 12;
		case Qt::Key_Return: return 13;
		case Qt::Key_Enter: return 13;
		case Qt::Key_Shift: return 16;
		case Qt::Key_Control: return 17;
		case Qt::Key_Pause: return 19;
		case Qt::Key_CapsLock: return 20;
		case Qt::Key_Escape: return 27;
		case Qt::Key_PageUp: return 33;
		case Qt::Key_PageDown: return 34;
		case Qt::Key_End: return 35;
		case Qt::Key_Home: return 36;
		case Qt::Key_Left: return 37;
		case Qt::Key_Up: return 38;
		case Qt::Key_Right: return 39;
		case Qt::Key_Down: return 40;
		case Qt::Key_Print: return 42;
		case Qt::Key_Insert: return 45;
		case Qt::Key_Delete: return 46;
		case Qt::Key_NumLock: return 144;
		default: return -1;
	}
}

void QtBackend::keyEvent(QKeyEvent *k, bool pressed) {
	int translatedkey = translateQtKey(k->key());
	int key = translatedkey;
	if (key == -1) {
		if (k->key() >= Qt::Key_0 && k->key() <= Qt::Key_9) {
			key = k->key();
		} else if (k->key() >= Qt::Key_A && k->key() <= Qt::Key_Z) {
			key = k->key();
		}
	}
	if (key != -1) {
		SomeEvent e;
		if (pressed)
			e.type = eventspecialkeydown;
		else
			e.type = eventspecialkeyup;
		e.key = key;
		pushEvent(e);
		downkeys[key] = pressed;
		if (translatedkey != -1) return;
	}

	for (int i = 0; i < k->text().size(); i++) {
		// TODO: openc2e probably doesn't like latin1
		unsigned char x = k->text().at(i).toLatin1();
		if (x > 31) { // Qt helpfully hands us non-text chars for some crazy reason
			// We have a Latin-1 key which we can process.
			SomeEvent e;

			// the engine only handles eventkeydown at present
			if (pressed) {
				e.type = eventkeydown;
				e.key = x;
				pushEvent(e);
			}
		}
	}
}

bool QtBackend::keyDown(int key) {
	return downkeys[key];
}

<commit_msg>Silence warning<commit_after>/*
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "QtBackend.h"
#include <QKeyEvent>
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <boost/format.hpp>
#include <iostream>
#include "../exceptions.h"

#ifdef _WIN32
#include <windows.h>
#endif

#ifdef _WIN32
HBITMAP screen_bmp = 0;
void *oldPixels = 0;
#endif

QtBackend::QtBackend() {
	viewport = 0;
	needsrender = false;

	for (unsigned int i = 0; i < 256; i++) {
		downkeys[i] = false;
	}
}

void QtBackend::shutdown() {
	if (!viewport) return;

#ifdef _WIN32
	if (screen_bmp) DeleteObject(screen_bmp);

	SDL_Surface *surf = getMainSDLSurface();
	if (surf) surf->pixels = oldPixels;
#endif

	SDLBackend::shutdown();
}

void QtBackend::init() {
}

void QtBackend::setup(QWidget *vp) {
	viewport = vp;

#if defined(Q_WS_X11)
	// on X11, using SDL_WINDOWID works, thank goodness.
	static char windowid_str[64]; // possibly big, but who cares
	((QApplication *)QApplication::instance())->syncX();

	if (sizeof windowid_str <=
			(size_t)snprintf(windowid_str, sizeof windowid_str, "SDL_WINDOWID=0x%lx", viewport->winId())) {
		std::cerr << "windowid_str buffer was too small - how big are your longs, anyway? Panicing..." << std::endl;
		abort();
	}
	// ->winId() may have created the window for us
	((QApplication *)QApplication::instance())->syncX();
	putenv(windowid_str);
#else
	// alas, it sucks on Windows and OS X, so we use an offscreen buffer instead
	putenv("SDL_VIDEODRIVER=dummy");
#endif

	SDLBackend::init();

	/*
	char videodrivername[200];
	std::cout << "SDL video driver: " << SDL_VideoDriverName(videodrivername, 200) << std::endl;
	std::cout << "SDL requested colour depth: " << idealBpp() << std::endl;
	*/

	viewport->setCursor(Qt::BlankCursor);
}

int QtBackend::idealBpp() {
#if defined(Q_WS_X11)
	return SDLBackend::idealBpp();
#endif

	// TODO: handle 8bpp for C1

#ifdef _WIN32
	// TODO: how to pick up real depth on windows?
	if (viewport->depth() == 16) return 16;
	return 24;
#endif

	return 32;
}

void QtBackend::resized(int w, int h) {
	resizeNotify(w, h);

#ifdef _WIN32
	// We need to construct a DIB for blitting, based on the surface data.

	// Delete the old one if needed.
	if (screen_bmp) DeleteObject(screen_bmp);

	// Setup a BITMAPINFO structure for this.
	BITMAPINFO *binfo = (BITMAPINFO *)malloc(sizeof(BITMAPINFO) + 12); // TODO: wrong wrong wrong
	binfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	binfo->bmiHeader.biPlanes = 1;
	binfo->bmiHeader.biClrUsed = 0;
	binfo->bmiHeader.biClrImportant = 0;

	binfo->bmiHeader.biXPelsPerMeter = 0;
	binfo->bmiHeader.biYPelsPerMeter = 0;

	SDL_Surface *surf = getMainSDLSurface();
	assert(idealBpp() == surf->format->BitsPerPixel);

	// Set the relevant entries of the structure.
	binfo->bmiHeader.biWidth = w;
	binfo->bmiHeader.biHeight = -h;
	binfo->bmiHeader.biSizeImage = w * h * (idealBpp() / 8);
	binfo->bmiHeader.biBitCount = idealBpp();

	// Describe the format of the data and any additional information needed (eg masks/palette)
	if (idealBpp() == 16) {
		binfo->bmiHeader.biCompression = BI_BITFIELDS;
		unsigned int *masks = (unsigned int *)binfo->bmiColors;
		masks[0] = surf->format->Rmask;
		masks[1] = surf->format->Gmask;
		masks[2] = surf->format->Bmask;
	} else {
		binfo->bmiHeader.biCompression = BI_RGB;
		if (idealBpp() == 8) {
			// TODO: set binfo.bmiColors
		}
	}

	// Create the actual DIB.
	void *pixels = 0;
	HDC hdc = GetDC(viewport->winId());
	screen_bmp = CreateDIBSection(hdc, binfo, DIB_RGB_COLORS, (void **)(&pixels), NULL, 0);
	ReleaseDC(viewport->winId(), hdc);

	// Free the BITMAPINFO structure now we're done with it.
	free(binfo);

	// TODO: fall back to Qt?
	if (!screen_bmp || !pixels) {
		// Windows helpfully provides no useful error information :(
		throw creaturesException("Internal error: failed to create DIB");
	}

	// TODO: Observe how this helpfully stomps over surf->pixels. :-/
	oldPixels = surf->pixels; // store so we can restore before SDL shutdown
	surf->pixels = pixels;

	// So, CreateDIBSection doesn't pay a lot of attention to what we ask for.
	// Let's snaffle the information back from the DIB object.
	// TODO: Observe how this helpfully stomps over surf->w/h/pitch. :-/
	BITMAP dibsection;
	GetObject(screen_bmp, sizeof(BITMAP), &dibsection);
	surf->w = dibsection.bmWidth;
	surf->h = dibsection.bmHeight;
	surf->pitch = dibsection.bmWidthBytes;
	assert(dibsection.bmBitsPixel == surf->format->BitsPerPixel);

#endif

	// add resize window event to backend queue
	SomeEvent e;
	e.type = eventresizewindow;
	e.x = w;
	e.y = h;
	pushEvent(e);
}

void QtBackend::renderDone() {
	needsrender = false;

	// If we're not on X11, we need to copy the contents of the offscreen buffer into the window.

#if defined(_WIN32)
	// We need to blit from the DIB we made earlier. Easy!
	HDC hdc, mdc;
	SDL_Surface *surf = getMainSDLSurface(); // for width/height

	// Obtain the DC for our viewport and create a compatible one, then select the DIB into it.
	hdc = GetDC(viewport->winId());
	mdc = CreateCompatibleDC(hdc);
	SelectObject(mdc, screen_bmp);

	// Blit!
	BitBlt(hdc, 0, 0, surf->w, surf->h, mdc, 0, 0, SRCCOPY);

	// Tidy up by deleting our temporary one and releasing the viewport DC.
	DeleteDC(mdc);
	ReleaseDC(viewport->winId(), hdc);

	// TODO: call GdiFlush? SDL doesn't seem to bother.

#elif !defined(Q_WS_X11)
	// As a generic method, we use Qt's code.
	// Note that we don't bother to lock because we know the dummy driver doesn't bother with locking.

	SDL_Surface *surf = getMainSDLSurface();
	QImage img((uchar *)surf->pixels, surf->w, surf->h, QImage::Format_RGB32);
	QPainter painter(viewport);
	painter.drawImage(0, 0, img);
#endif
}

bool QtBackend::pollEvent(SomeEvent &e) {
	// obtain events from backend
	if (SDLBackend::pollEvent(e)) return true;

	if (events.size() == 0)
		return false;

	e = events.front();
	events.pop_front();
	return true;
}

void QtBackend::pushEvent(SomeEvent e) {
	events.push_back(e);
}

// TODO: handle f keys (112-123 under windows, SDLK_F1 = 282 under sdl)
// see SDLBackend

int translateQtKey(int qtkey) {
	switch (qtkey) {
		case Qt::Key_Backspace: return 8;
		case Qt::Key_Tab: return 9;
		case Qt::Key_Clear: return 12;
		case Qt::Key_Return: return 13;
		case Qt::Key_Enter: return 13;
		case Qt::Key_Shift: return 16;
		case Qt::Key_Control: return 17;
		case Qt::Key_Pause: return 19;
		case Qt::Key_CapsLock: return 20;
		case Qt::Key_Escape: return 27;
		case Qt::Key_PageUp: return 33;
		case Qt::Key_PageDown: return 34;
		case Qt::Key_End: return 35;
		case Qt::Key_Home: return 36;
		case Qt::Key_Left: return 37;
		case Qt::Key_Up: return 38;
		case Qt::Key_Right: return 39;
		case Qt::Key_Down: return 40;
		case Qt::Key_Print: return 42;
		case Qt::Key_Insert: return 45;
		case Qt::Key_Delete: return 46;
		case Qt::Key_NumLock: return 144;
		default: return -1;
	}
}

void QtBackend::keyEvent(QKeyEvent *k, bool pressed) {
	int translatedkey = translateQtKey(k->key());
	int key = translatedkey;
	if (key == -1) {
		if (k->key() >= Qt::Key_0 && k->key() <= Qt::Key_9) {
			key = k->key();
		} else if (k->key() >= Qt::Key_A && k->key() <= Qt::Key_Z) {
			key = k->key();
		}
	}
	if (key != -1) {
		SomeEvent e;
		if (pressed)
			e.type = eventspecialkeydown;
		else
			e.type = eventspecialkeyup;
		e.key = key;
		pushEvent(e);
		downkeys[key] = pressed;
		if (translatedkey != -1) return;
	}

	for (int i = 0; i < k->text().size(); i++) {
		// TODO: openc2e probably doesn't like latin1
		unsigned char x = k->text().at(i).toLatin1();
		if (x > 31) { // Qt helpfully hands us non-text chars for some crazy reason
			// We have a Latin-1 key which we can process.
			SomeEvent e;

			// the engine only handles eventkeydown at present
			if (pressed) {
				e.type = eventkeydown;
				e.key = x;
				pushEvent(e);
			}
		}
	}
}

bool QtBackend::keyDown(int key) {
	return downkeys[key];
}

<|endoftext|>


<commit_before><commit_msg>tests: Add one more XPath optimization test<commit_after><|endoftext|>