<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include <algorithm>
#include <iterator>
#include <map>
#include <string>

#include "caf/string_view.hpp"

namespace caf {

/// Maps strings to values of type `V`, but unlike `std::map<std::string, V>`
/// accepts `string_view` for looking up keys efficiently.
template <class V>
class dictionary {
public:
  // -- member types ----------------------------------------------------------

  using map_type = std::map<std::string, V>;

  using key_type = typename map_type::key_type;

  using mapped_type = typename map_type::mapped_type;

  using value_type = typename map_type::value_type;

  using allocator_type = typename map_type::allocator_type;

  using size_type = typename map_type::size_type;

  using difference_type = typename map_type::difference_type;

  using reference = typename map_type::reference;

  using const_reference = typename map_type::const_reference;

  using pointer = typename map_type::pointer;

  using const_pointer = typename map_type::const_pointer;

  using iterator = typename map_type::iterator;

  using const_iterator = typename map_type::const_iterator;

  using reverse_iterator = typename map_type::reverse_iterator;

  using const_reverse_iterator = typename map_type::const_reverse_iterator;

  using iterator_bool_pair = std::pair<iterator, bool>;

  struct mapped_type_less {
    inline bool operator()(const value_type& x, string_view y) const {
      return x.first < y;
    }

    inline bool operator()(const value_type& x, const value_type& y) const {
      return x.first < y.first;
    }

    inline bool operator()(string_view x, const value_type& y) const {
      return x < y.first;
    }
  };

  // -- constructors, destructors, and assignment operators -------------------

  dictionary() = default;

  dictionary(dictionary&&) = default;

  dictionary(const dictionary&) = default;

  dictionary(std::initializer_list<value_type> xs) : xs_(xs) {
    // nop
  }

  template <class InputIterator>
  dictionary(InputIterator first, InputIterator last) : xs_(first, last) {
    // nop
  }

  dictionary& operator=(dictionary&&) = default;

  dictionary& operator=(const dictionary&) = default;

  // -- iterator access --------------------------------------------------------

  iterator begin() noexcept {
    return xs_.begin();
  }

  const_iterator begin() const noexcept {
    return xs_.begin();
  }

  const_iterator cbegin() const noexcept {
    return begin();
  }

  reverse_iterator rbegin() noexcept {
    return xs_.rbegin();
  }

  const_reverse_iterator rbegin() const noexcept {
    return xs_.rbegin();
  }

  const_reverse_iterator crbegin() const noexcept {
    return rbegin();
  }

  iterator end() noexcept {
    return xs_.end();
  }

  const_iterator end() const noexcept {
    return xs_.end();
  }

  const_iterator cend() const noexcept {
    return end();
  }

  reverse_iterator rend() noexcept {
    return xs_.rend();
  }

  const_reverse_iterator rend() const noexcept {
    return xs_.rend();
  }

  const_reverse_iterator crend() const noexcept {
    return rend();
  }

  // -- size -------------------------------------------------------------------

  bool empty() const noexcept {
    return xs_.empty();
  }

  size_type size() const noexcept {
    return xs_.size();
  }

  // -- access to members ------------------------------------------------------

  /// Gives raw access to the underlying container.
  map_type& container() noexcept {
    return xs_;
  }

  /// Gives raw access to the underlying container.
  const map_type& container() const noexcept {
    return xs_;
  }

  // -- modifiers -------------------------------------------------------------

  void clear() noexcept {
    return xs_.clear();
  }

  void swap(dictionary& other) {
    xs_.swap(other.xs_);
  }

  // -- insertion --------------------------------------------------------------

  template <class K, class T>
  iterator_bool_pair emplace(K&& key, T&& value) {
    auto i = lower_bound(key);
    if (i == end())
      return xs_.emplace(copy(std::forward<K>(key)), V{std::forward<T>(value)});
    if (i->first == key)
      return {i, false};
    return {xs_.emplace_hint(i, copy(std::forward<K>(key)),
                             V{std::forward<T>(value)}),
            true};
  }

  iterator_bool_pair insert(value_type kvp) {
    return emplace(kvp.first, std::move(kvp.second));
  }

  iterator insert(iterator hint, value_type kvp) {
    return emplace_hint(hint, kvp.first, std::move(kvp.second));
  }

  template <class T>
  iterator_bool_pair insert(string_view key, T&& value) {
    return emplace(key, V{std::forward<T>(value)});
  }

  template <class K, class T>
  iterator emplace_hint(iterator hint, K&& key, T&& value) {
    if (hint == end() || hint->first > key)
      return xs_.emplace(copy(std::forward<K>(key)), V{std::forward<T>(value)})
             .first;
    if (hint->first == key)
      return hint;
    return xs_.emplace_hint(hint, copy(std::forward<K>(key)),
                            V{std::forward<T>(value)});
  }

  template <class T>
  iterator insert(iterator hint, string_view key, T&& value) {
    return emplace_hint(hint, key, std::forward<T>(value));
  }

  void insert(const_iterator first, const_iterator last) {
    xs_.insert(first, last);
  }

  template <class T>
  iterator_bool_pair insert_or_assign(string_view key, T&& value) {
    auto i = lower_bound(key);
    if (i == end())
      return xs_.emplace(copy(key), V{std::forward<T>(value)});
    if (i->first == key) {
      i->second = V{std::forward<T>(value)};
      return {i, false};
    }
    return {xs_.emplace_hint(i, copy(key), V{std::forward<T>(value)}), true};
  }

  template <class T>
  iterator insert_or_assign(iterator hint, string_view key, T&& value) {
    if (hint == end() || hint->first > key)
      return insert_or_assign(key, std::forward<T>(value)).first;
    hint = lower_bound(hint, key);
    if (hint != end() && hint->first == key) {
      hint->second = std::forward<T>(value);
      return hint;
    }
    return xs_.emplace_hint(hint, copy(key), V{std::forward<T>(value)});
  }

  // -- lookup -----------------------------------------------------------------

  bool contains(string_view key) const noexcept {
    auto i = lower_bound(key);
    return !(i == end() || i->first != key);
  }

  size_t count(string_view key) const noexcept {
    return contains(key) ? 1u : 0u;
  }

  iterator find(string_view key) noexcept {
    auto i = lower_bound(key);
    return i != end() && i->first == key ? i : end();
  }

  const_iterator find(string_view key) const noexcept {
    auto i = lower_bound(key);
    return i != end() && i->first == key ? i : end();
  }

  iterator lower_bound(string_view key) {
    return lower_bound(begin(), key);
  }

  const_iterator lower_bound(string_view key) const {
    return lower_bound(begin(), key);
  }

  iterator upper_bound(string_view key) {
    mapped_type_less cmp;
    return std::upper_bound(begin(), end(), key, cmp);
  }

  const_iterator upper_bound(string_view key) const {
    mapped_type_less cmp;
    return std::upper_bound(begin(), end(), key, cmp);
  }

  // -- element access ---------------------------------------------------------

  mapped_type& operator[](string_view key) {
    return insert(key, mapped_type{}).first->second;
  }

private:
  iterator lower_bound(iterator from, string_view key) {
    mapped_type_less cmp;
    return std::lower_bound(from, end(), key, cmp);
  }

  const_iterator lower_bound(const_iterator from, string_view key) const {
    mapped_type_less cmp;
    return std::lower_bound(from, end(), key, cmp);
  }

  template <size_t N>
  static inline std::string copy(const char (&str)[N]) {
    return std::string{str};
  }

  // Copies the content of `str` into a new string.
  static inline std::string copy(string_view str) {
    return std::string{str.begin(), str.end()};
  }

  // Moves the content of `str` into a new string.
  static inline std::string copy(std::string str) {
    return str;
  }

  map_type xs_;
};

// @relates dictionary
template <class T>
bool operator==(const dictionary<T>& xs, const dictionary<T>& ys) {
  return xs.container() == ys.container();
}

// @relates dictionary
template <class T>
bool operator!=(const dictionary<T>& xs, const dictionary<T>& ys) {
  return xs.container() != ys.container();
}

// @relates dictionary
template <class T>
bool operator<(const dictionary<T>& xs, const dictionary<T>& ys) {
  return xs.container() < ys.container();
}

// @relates dictionary
template <class T>
bool operator<=(const dictionary<T>& xs, const dictionary<T>& ys) {
  return xs.container() <= ys.container();
}

// @relates dictionary
template <class T>
bool operator>(const dictionary<T>& xs, const dictionary<T>& ys) {
  return xs.container() > ys.container();
}

// @relates dictionary
template <class T>
bool operator>=(const dictionary<T>& xs, const dictionary<T>& ys) {
  return xs.container() >= ys.container();
}

} // namespace caf
<commit_msg>Add free convenience function<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include <algorithm>
#include <iterator>
#include <map>
#include <string>

#include "caf/string_view.hpp"

namespace caf {

/// Maps strings to values of type `V`, but unlike `std::map<std::string, V>`
/// accepts `string_view` for looking up keys efficiently.
template <class V>
class dictionary {
public:
  // -- member types ----------------------------------------------------------

  using map_type = std::map<std::string, V>;

  using key_type = typename map_type::key_type;

  using mapped_type = typename map_type::mapped_type;

  using value_type = typename map_type::value_type;

  using allocator_type = typename map_type::allocator_type;

  using size_type = typename map_type::size_type;

  using difference_type = typename map_type::difference_type;

  using reference = typename map_type::reference;

  using const_reference = typename map_type::const_reference;

  using pointer = typename map_type::pointer;

  using const_pointer = typename map_type::const_pointer;

  using iterator = typename map_type::iterator;

  using const_iterator = typename map_type::const_iterator;

  using reverse_iterator = typename map_type::reverse_iterator;

  using const_reverse_iterator = typename map_type::const_reverse_iterator;

  using iterator_bool_pair = std::pair<iterator, bool>;

  struct mapped_type_less {
    inline bool operator()(const value_type& x, string_view y) const {
      return x.first < y;
    }

    inline bool operator()(const value_type& x, const value_type& y) const {
      return x.first < y.first;
    }

    inline bool operator()(string_view x, const value_type& y) const {
      return x < y.first;
    }
  };

  // -- constructors, destructors, and assignment operators -------------------

  dictionary() = default;

  dictionary(dictionary&&) = default;

  dictionary(const dictionary&) = default;

  dictionary(std::initializer_list<value_type> xs) : xs_(xs) {
    // nop
  }

  template <class InputIterator>
  dictionary(InputIterator first, InputIterator last) : xs_(first, last) {
    // nop
  }

  dictionary& operator=(dictionary&&) = default;

  dictionary& operator=(const dictionary&) = default;

  // -- iterator access --------------------------------------------------------

  iterator begin() noexcept {
    return xs_.begin();
  }

  const_iterator begin() const noexcept {
    return xs_.begin();
  }

  const_iterator cbegin() const noexcept {
    return begin();
  }

  reverse_iterator rbegin() noexcept {
    return xs_.rbegin();
  }

  const_reverse_iterator rbegin() const noexcept {
    return xs_.rbegin();
  }

  const_reverse_iterator crbegin() const noexcept {
    return rbegin();
  }

  iterator end() noexcept {
    return xs_.end();
  }

  const_iterator end() const noexcept {
    return xs_.end();
  }

  const_iterator cend() const noexcept {
    return end();
  }

  reverse_iterator rend() noexcept {
    return xs_.rend();
  }

  const_reverse_iterator rend() const noexcept {
    return xs_.rend();
  }

  const_reverse_iterator crend() const noexcept {
    return rend();
  }

  // -- size -------------------------------------------------------------------

  bool empty() const noexcept {
    return xs_.empty();
  }

  size_type size() const noexcept {
    return xs_.size();
  }

  // -- access to members ------------------------------------------------------

  /// Gives raw access to the underlying container.
  map_type& container() noexcept {
    return xs_;
  }

  /// Gives raw access to the underlying container.
  const map_type& container() const noexcept {
    return xs_;
  }

  // -- modifiers -------------------------------------------------------------

  void clear() noexcept {
    return xs_.clear();
  }

  void swap(dictionary& other) {
    xs_.swap(other.xs_);
  }

  // -- insertion --------------------------------------------------------------

  template <class K, class T>
  iterator_bool_pair emplace(K&& key, T&& value) {
    auto i = lower_bound(key);
    if (i == end())
      return xs_.emplace(copy(std::forward<K>(key)), V{std::forward<T>(value)});
    if (i->first == key)
      return {i, false};
    return {xs_.emplace_hint(i, copy(std::forward<K>(key)),
                             V{std::forward<T>(value)}),
            true};
  }

  iterator_bool_pair insert(value_type kvp) {
    return emplace(kvp.first, std::move(kvp.second));
  }

  iterator insert(iterator hint, value_type kvp) {
    return emplace_hint(hint, kvp.first, std::move(kvp.second));
  }

  template <class T>
  iterator_bool_pair insert(string_view key, T&& value) {
    return emplace(key, V{std::forward<T>(value)});
  }

  template <class K, class T>
  iterator emplace_hint(iterator hint, K&& key, T&& value) {
    if (hint == end() || hint->first > key)
      return xs_.emplace(copy(std::forward<K>(key)), V{std::forward<T>(value)})
             .first;
    if (hint->first == key)
      return hint;
    return xs_.emplace_hint(hint, copy(std::forward<K>(key)),
                            V{std::forward<T>(value)});
  }

  template <class T>
  iterator insert(iterator hint, string_view key, T&& value) {
    return emplace_hint(hint, key, std::forward<T>(value));
  }

  void insert(const_iterator first, const_iterator last) {
    xs_.insert(first, last);
  }

  template <class T>
  iterator_bool_pair insert_or_assign(string_view key, T&& value) {
    auto i = lower_bound(key);
    if (i == end())
      return xs_.emplace(copy(key), V{std::forward<T>(value)});
    if (i->first == key) {
      i->second = V{std::forward<T>(value)};
      return {i, false};
    }
    return {xs_.emplace_hint(i, copy(key), V{std::forward<T>(value)}), true};
  }

  template <class T>
  iterator insert_or_assign(iterator hint, string_view key, T&& value) {
    if (hint == end() || hint->first > key)
      return insert_or_assign(key, std::forward<T>(value)).first;
    hint = lower_bound(hint, key);
    if (hint != end() && hint->first == key) {
      hint->second = std::forward<T>(value);
      return hint;
    }
    return xs_.emplace_hint(hint, copy(key), V{std::forward<T>(value)});
  }

  // -- lookup -----------------------------------------------------------------

  bool contains(string_view key) const noexcept {
    auto i = lower_bound(key);
    return !(i == end() || i->first != key);
  }

  size_t count(string_view key) const noexcept {
    return contains(key) ? 1u : 0u;
  }

  iterator find(string_view key) noexcept {
    auto i = lower_bound(key);
    return i != end() && i->first == key ? i : end();
  }

  const_iterator find(string_view key) const noexcept {
    auto i = lower_bound(key);
    return i != end() && i->first == key ? i : end();
  }

  iterator lower_bound(string_view key) {
    return lower_bound(begin(), key);
  }

  const_iterator lower_bound(string_view key) const {
    return lower_bound(begin(), key);
  }

  iterator upper_bound(string_view key) {
    mapped_type_less cmp;
    return std::upper_bound(begin(), end(), key, cmp);
  }

  const_iterator upper_bound(string_view key) const {
    mapped_type_less cmp;
    return std::upper_bound(begin(), end(), key, cmp);
  }

  // -- element access ---------------------------------------------------------

  mapped_type& operator[](string_view key) {
    return insert(key, mapped_type{}).first->second;
  }

private:
  iterator lower_bound(iterator from, string_view key) {
    mapped_type_less cmp;
    return std::lower_bound(from, end(), key, cmp);
  }

  const_iterator lower_bound(const_iterator from, string_view key) const {
    mapped_type_less cmp;
    return std::lower_bound(from, end(), key, cmp);
  }

  template <size_t N>
  static inline std::string copy(const char (&str)[N]) {
    return std::string{str};
  }

  // Copies the content of `str` into a new string.
  static inline std::string copy(string_view str) {
    return std::string{str.begin(), str.end()};
  }

  // Moves the content of `str` into a new string.
  static inline std::string copy(std::string str) {
    return str;
  }

  map_type xs_;
};

// -- operators ----------------------------------------------------------------

// @relates dictionary
template <class T>
bool operator==(const dictionary<T>& xs, const dictionary<T>& ys) {
  return xs.container() == ys.container();
}

// @relates dictionary
template <class T>
bool operator!=(const dictionary<T>& xs, const dictionary<T>& ys) {
  return xs.container() != ys.container();
}

// @relates dictionary
template <class T>
bool operator<(const dictionary<T>& xs, const dictionary<T>& ys) {
  return xs.container() < ys.container();
}

// @relates dictionary
template <class T>
bool operator<=(const dictionary<T>& xs, const dictionary<T>& ys) {
  return xs.container() <= ys.container();
}

// @relates dictionary
template <class T>
bool operator>(const dictionary<T>& xs, const dictionary<T>& ys) {
  return xs.container() > ys.container();
}

// @relates dictionary
template <class T>
bool operator>=(const dictionary<T>& xs, const dictionary<T>& ys) {
  return xs.container() >= ys.container();
}

// -- free functions -----------------------------------------------------------

/// Convenience function for calling `dict.insert_or_assign(key, value)`.
// @relates dictionary
template <class T>
void put(dictionary<T>& dict, string_view key, T value) {
  dict.insert_or_assign(key, std::move(value));
}

} // namespace caf
<|endoftext|>


<commit_before>#include <mtp/ptp/Session.h>
#include <mtp/ptp/Messages.h>
#include <mtp/ptp/Container.h>
#include <mtp/ptp/OperationRequest.h>

namespace mtp
{
#define THROW_INVALID_RESPONSE

	void Session::Close()
	{
		OperationRequest req(OperationCode::CloseSession, 0, _sessionId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(0, data, response);
		//HexDump("payload", data);
	}

	msg::ObjectHandles Session::GetObjectHandles(u32 storageId, u32 objectFormat, u32 parent)
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::GetObjectHandles, transaction, storageId, objectFormat, parent);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		InputStream stream(data, 8); //operation code + session id

		msg::ObjectHandles goh;
		goh.Read(stream);
		return goh;
	}

	msg::StorageIDs Session::GetStorageIDs()
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::GetStorageIDs, transaction, 0xffffffffu);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		InputStream stream(data, 8); //operation code + session id

		msg::StorageIDs gsi;
		gsi.Read(stream);
		return gsi;
	}

	msg::StorageInfo Session::GetStorageInfo(u32 storageId)
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::GetStorageInfo, transaction, storageId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		InputStream stream(data, 8); //operation code + session id
		msg::StorageInfo gsi;
		gsi.Read(stream);
		return gsi;
	}

	msg::ObjectInfo Session::GetObjectInfo(u32 objectId)
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::GetObjectInfo, transaction, objectId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		InputStream stream(data, 8); //operation code + session id
		msg::ObjectInfo goi;
		goi.Read(stream);
		return goi;
	}

	msg::ObjectPropsSupported Session::GetObjectPropsSupported(u32 objectId)
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::GetObjectPropsSupported, transaction, objectId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		InputStream stream(data, 8); //operation code + session id
		msg::ObjectPropsSupported ops;
		ops.Read(stream);
		return ops;
	}

	ByteArray Session::GetObject(u32 objectId)
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::GetObject, transaction, objectId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		return ByteArray(data.begin() + 8, data.end());
	}

	Session::NewObjectInfo Session::SendObjectInfo(const msg::ObjectInfo &objectInfo, u32 storageId, u32 parentObject)
	{
		u32 transaction = _transactionId++;
		{
			OperationRequest req(OperationCode::SendObjectInfo, transaction, storageId, parentObject);
			Container container(req);
			_packeter.Write(container.Data);
		}
		{
			DataRequest req(OperationCode::SendObjectInfo, transaction);
			OutputStream stream(req.Data);
			objectInfo.Write(stream);
			Container container(req);
			_packeter.Write(container.Data);
		}
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		//HexDump("response", response);
		InputStream stream(response, 8); //operation code + session id
		NewObjectInfo noi;
		stream >> noi.StorageId;
		stream >> noi.ParentObjectId;
		stream >> noi.ObjectId;
		return noi;
	}

	void Session::SendObject(const ByteArray &object)
	{
		u32 transaction = _transactionId++;
		{
			OperationRequest req(OperationCode::SendObject, transaction);
			Container container(req);
			_packeter.Write(container.Data);
		}
		{
			DataRequest req(OperationCode::SendObject, transaction);
			req.Append(object);
			Container container(req);
			_packeter.Write(container.Data, 0);
		}
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		HexDump("response", response);
	}

	void Session::DeleteObject(u32 objectId)
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::DeleteObject, transaction, objectId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
	}

}
<commit_msg>added CHECK_RESPONSE macro, check every response<commit_after>#include <mtp/ptp/Session.h>
#include <mtp/ptp/Messages.h>
#include <mtp/ptp/Container.h>
#include <mtp/ptp/OperationRequest.h>

namespace mtp
{

#define CHECK_RESPONSE(RDATA) do { \
	InputStream s(response); \
	Response header(s);\
	if (header.ResponseType != ResponseType::OK && header.ResponseType != ResponseType::SessionAlreadyOpen) \
		throw InvalidResponseException(__func__, header.ResponseType); \
} while(false)

	void Session::Close()
	{
		OperationRequest req(OperationCode::CloseSession, 0, _sessionId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(0, data, response);
		//HexDump("payload", data);
	}

	msg::ObjectHandles Session::GetObjectHandles(u32 storageId, u32 objectFormat, u32 parent)
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::GetObjectHandles, transaction, storageId, objectFormat, parent);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		CHECK_RESPONSE(response);
		InputStream stream(data, 8); //operation code + session id

		msg::ObjectHandles goh;
		goh.Read(stream);
		return goh;
	}

	msg::StorageIDs Session::GetStorageIDs()
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::GetStorageIDs, transaction, 0xffffffffu);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		CHECK_RESPONSE(response);
		InputStream stream(data, 8); //operation code + session id

		msg::StorageIDs gsi;
		gsi.Read(stream);
		return gsi;
	}

	msg::StorageInfo Session::GetStorageInfo(u32 storageId)
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::GetStorageInfo, transaction, storageId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		CHECK_RESPONSE(response);
		InputStream stream(data, 8); //operation code + session id
		msg::StorageInfo gsi;
		gsi.Read(stream);
		return gsi;
	}

	msg::ObjectInfo Session::GetObjectInfo(u32 objectId)
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::GetObjectInfo, transaction, objectId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		CHECK_RESPONSE(response);
		InputStream stream(data, 8); //operation code + session id
		msg::ObjectInfo goi;
		goi.Read(stream);
		return goi;
	}

	msg::ObjectPropsSupported Session::GetObjectPropsSupported(u32 objectId)
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::GetObjectPropsSupported, transaction, objectId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		CHECK_RESPONSE(response);
		InputStream stream(data, 8); //operation code + session id
		msg::ObjectPropsSupported ops;
		ops.Read(stream);
		return ops;
	}

	ByteArray Session::GetObject(u32 objectId)
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::GetObject, transaction, objectId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		CHECK_RESPONSE(response);
		return ByteArray(data.begin() + 8, data.end());
	}

	Session::NewObjectInfo Session::SendObjectInfo(const msg::ObjectInfo &objectInfo, u32 storageId, u32 parentObject)
	{
		u32 transaction = _transactionId++;
		{
			OperationRequest req(OperationCode::SendObjectInfo, transaction, storageId, parentObject);
			Container container(req);
			_packeter.Write(container.Data);
		}
		{
			DataRequest req(OperationCode::SendObjectInfo, transaction);
			OutputStream stream(req.Data);
			objectInfo.Write(stream);
			Container container(req);
			_packeter.Write(container.Data);
		}
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		//HexDump("response", response);
		CHECK_RESPONSE(response);
		InputStream stream(response, 8); //operation code + session id
		NewObjectInfo noi;
		stream >> noi.StorageId;
		stream >> noi.ParentObjectId;
		stream >> noi.ObjectId;
		return noi;
	}

	void Session::SendObject(const ByteArray &object)
	{
		u32 transaction = _transactionId++;
		{
			OperationRequest req(OperationCode::SendObject, transaction);
			Container container(req);
			_packeter.Write(container.Data);
		}
		{
			DataRequest req(OperationCode::SendObject, transaction);
			req.Append(object);
			Container container(req);
			_packeter.Write(container.Data, 0);
		}
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		CHECK_RESPONSE(response);
	}

	void Session::DeleteObject(u32 objectId)
	{
		u32 transaction = _transactionId++;
		OperationRequest req(OperationCode::DeleteObject, transaction, objectId);
		Container container(req);
		_packeter.Write(container.Data);
		ByteArray data, response;
		_packeter.Read(transaction, data, response);
		CHECK_RESPONSE(response);
	}

}
<|endoftext|>


<commit_before>//===--- lib/CodeGen/DIE.cpp - DWARF Info Entries -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Data structures for DWARF info entries.
//
//===----------------------------------------------------------------------===//

#include "DIE.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// DIEAbbrevData Implementation
//===----------------------------------------------------------------------===//

/// Profile - Used to gather unique data for the abbreviation folding set.
///
void DIEAbbrevData::Profile(FoldingSetNodeID &ID) const {
  ID.AddInteger(Attribute);
  ID.AddInteger(Form);
}

//===----------------------------------------------------------------------===//
// DIEAbbrev Implementation
//===----------------------------------------------------------------------===//

/// Profile - Used to gather unique data for the abbreviation folding set.
///
void DIEAbbrev::Profile(FoldingSetNodeID &ID) const {
  ID.AddInteger(Tag);
  ID.AddInteger(ChildrenFlag);

  // For each attribute description.
  for (unsigned i = 0, N = Data.size(); i < N; ++i)
    Data[i].Profile(ID);
}

/// Emit - Print the abbreviation using the specified asm printer.
///
void DIEAbbrev::Emit(AsmPrinter *AP) const {
  // Emit its Dwarf tag type.
  // FIXME: Doing work even in non-asm-verbose runs.
  AP->EmitULEB128(Tag, dwarf::TagString(Tag));

  // Emit whether it has children DIEs.
  // FIXME: Doing work even in non-asm-verbose runs.
  AP->EmitULEB128(ChildrenFlag, dwarf::ChildrenString(ChildrenFlag));

  // For each attribute description.
  for (unsigned i = 0, N = Data.size(); i < N; ++i) {
    const DIEAbbrevData &AttrData = Data[i];

    // Emit attribute type.
    // FIXME: Doing work even in non-asm-verbose runs.
    AP->EmitULEB128(AttrData.getAttribute(),
                    dwarf::AttributeString(AttrData.getAttribute()));

    // Emit form type.
    // FIXME: Doing work even in non-asm-verbose runs.
    AP->EmitULEB128(AttrData.getForm(),
                    dwarf::FormEncodingString(AttrData.getForm()));
  }

  // Mark end of abbreviation.
  AP->EmitULEB128(0, "EOM(1)");
  AP->EmitULEB128(0, "EOM(2)");
}

#ifndef NDEBUG
void DIEAbbrev::print(raw_ostream &O) {
  O << "Abbreviation @"
    << format("0x%lx", (long)(intptr_t)this)
    << "  "
    << dwarf::TagString(Tag)
    << " "
    << dwarf::ChildrenString(ChildrenFlag)
    << '\n';

  for (unsigned i = 0, N = Data.size(); i < N; ++i) {
    O << "  "
      << dwarf::AttributeString(Data[i].getAttribute())
      << "  "
      << dwarf::FormEncodingString(Data[i].getForm())
      << '\n';
  }
}
void DIEAbbrev::dump() { print(dbgs()); }
#endif

//===----------------------------------------------------------------------===//
// DIE Implementation
//===----------------------------------------------------------------------===//

DIE::~DIE() {
  for (unsigned i = 0, N = Children.size(); i < N; ++i)
    delete Children[i];
}

/// Climb up the parent chain to get the compile unit DIE this DIE belongs to.
DIE *DIE::getCompileUnit() const{
  DIE *p = getParent();
  while (p) {
    if (p->getTag() == dwarf::DW_TAG_compile_unit)
      return p;
    p = p->getParent();
  }
  return NULL;
}

#ifndef NDEBUG
void DIE::print(raw_ostream &O, unsigned IncIndent) {
  IndentCount += IncIndent;
  const std::string Indent(IndentCount, ' ');
  bool isBlock = Abbrev.getTag() == 0;

  if (!isBlock) {
    O << Indent
      << "Die: "
      << format("0x%lx", (long)(intptr_t)this)
      << ", Offset: " << Offset
      << ", Size: " << Size << "\n";

    O << Indent
      << dwarf::TagString(Abbrev.getTag())
      << " "
      << dwarf::ChildrenString(Abbrev.getChildrenFlag()) << "\n";
  } else {
    O << "Size: " << Size << "\n";
  }

  const SmallVector<DIEAbbrevData, 8> &Data = Abbrev.getData();

  IndentCount += 2;
  for (unsigned i = 0, N = Data.size(); i < N; ++i) {
    O << Indent;

    if (!isBlock)
      O << dwarf::AttributeString(Data[i].getAttribute());
    else
      O << "Blk[" << i << "]";

    O <<  "  "
      << dwarf::FormEncodingString(Data[i].getForm())
      << " ";
    Values[i]->print(O);
    O << "\n";
  }
  IndentCount -= 2;

  for (unsigned j = 0, M = Children.size(); j < M; ++j) {
    Children[j]->print(O, 4);
  }

  if (!isBlock) O << "\n";
  IndentCount -= IncIndent;
}

void DIE::dump() {
  print(dbgs());
}
#endif

void DIEValue::anchor() { }

#ifndef NDEBUG
void DIEValue::dump() {
  print(dbgs());
}
#endif

//===----------------------------------------------------------------------===//
// DIEInteger Implementation
//===----------------------------------------------------------------------===//

/// EmitValue - Emit integer of appropriate size.
///
void DIEInteger::EmitValue(AsmPrinter *Asm, unsigned Form) const {
  unsigned Size = ~0U;
  switch (Form) {
  case dwarf::DW_FORM_flag_present:
    // Emit something to keep the lines and comments in sync.
    // FIXME: Is there a better way to do this?
    if (Asm->OutStreamer.hasRawTextSupport())
      Asm->OutStreamer.EmitRawText(StringRef(""));
    return;
  case dwarf::DW_FORM_flag:  // Fall thru
  case dwarf::DW_FORM_ref1:  // Fall thru
  case dwarf::DW_FORM_data1: Size = 1; break;
  case dwarf::DW_FORM_ref2:  // Fall thru
  case dwarf::DW_FORM_data2: Size = 2; break;
  case dwarf::DW_FORM_sec_offset: // Fall thru
  case dwarf::DW_FORM_ref4:  // Fall thru
  case dwarf::DW_FORM_data4: Size = 4; break;
  case dwarf::DW_FORM_ref8:  // Fall thru
  case dwarf::DW_FORM_data8: Size = 8; break;
  case dwarf::DW_FORM_GNU_str_index: Asm->EmitULEB128(Integer); return;
  case dwarf::DW_FORM_GNU_addr_index: Asm->EmitULEB128(Integer); return;
  case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return;
  case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return;
  case dwarf::DW_FORM_addr:
    Size = Asm->getDataLayout().getPointerSize(); break;
  default: llvm_unreachable("DIE Value form not supported yet");
  }
  Asm->OutStreamer.EmitIntValue(Integer, Size);
}

/// SizeOf - Determine size of integer value in bytes.
///
unsigned DIEInteger::SizeOf(AsmPrinter *AP, unsigned Form) const {
  switch (Form) {
  case dwarf::DW_FORM_flag_present: return 0;
  case dwarf::DW_FORM_flag:  // Fall thru
  case dwarf::DW_FORM_ref1:  // Fall thru
  case dwarf::DW_FORM_data1: return sizeof(int8_t);
  case dwarf::DW_FORM_ref2:  // Fall thru
  case dwarf::DW_FORM_data2: return sizeof(int16_t);
  case dwarf::DW_FORM_sec_offset: // Fall thru
  case dwarf::DW_FORM_ref4:  // Fall thru
  case dwarf::DW_FORM_data4: return sizeof(int32_t);
  case dwarf::DW_FORM_ref8:  // Fall thru
  case dwarf::DW_FORM_data8: return sizeof(int64_t);
  case dwarf::DW_FORM_GNU_str_index: return MCAsmInfo::getULEB128Size(Integer);
  case dwarf::DW_FORM_GNU_addr_index: return MCAsmInfo::getULEB128Size(Integer);
  case dwarf::DW_FORM_udata: return MCAsmInfo::getULEB128Size(Integer);
  case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer);
  case dwarf::DW_FORM_addr:  return AP->getDataLayout().getPointerSize();
  default: llvm_unreachable("DIE Value form not supported yet");
  }
}

#ifndef NDEBUG
void DIEInteger::print(raw_ostream &O) {
  O << "Int: " << (int64_t)Integer << "  0x";
  O.write_hex(Integer);
}
#endif

//===----------------------------------------------------------------------===//
// DIELabel Implementation
//===----------------------------------------------------------------------===//

/// EmitValue - Emit label value.
///
void DIELabel::EmitValue(AsmPrinter *AP, unsigned Form) const {
  AP->OutStreamer.EmitSymbolValue(Label, SizeOf(AP, Form));
}

/// SizeOf - Determine size of label value in bytes.
///
unsigned DIELabel::SizeOf(AsmPrinter *AP, unsigned Form) const {
  if (Form == dwarf::DW_FORM_data4) return 4;
  if (Form == dwarf::DW_FORM_sec_offset) return 4;
  if (Form == dwarf::DW_FORM_strp) return 4;
  return AP->getDataLayout().getPointerSize();
}

#ifndef NDEBUG
void DIELabel::print(raw_ostream &O) {
  O << "Lbl: " << Label->getName();
}
#endif

//===----------------------------------------------------------------------===//
// DIEDelta Implementation
//===----------------------------------------------------------------------===//

/// EmitValue - Emit delta value.
///
void DIEDelta::EmitValue(AsmPrinter *AP, unsigned Form) const {
  AP->EmitLabelDifference(LabelHi, LabelLo, SizeOf(AP, Form));
}

/// SizeOf - Determine size of delta value in bytes.
///
unsigned DIEDelta::SizeOf(AsmPrinter *AP, unsigned Form) const {
  if (Form == dwarf::DW_FORM_data4) return 4;
  if (Form == dwarf::DW_FORM_strp) return 4;
  return AP->getDataLayout().getPointerSize();
}

#ifndef NDEBUG
void DIEDelta::print(raw_ostream &O) {
  O << "Del: " << LabelHi->getName() << "-" << LabelLo->getName();
}
#endif

//===----------------------------------------------------------------------===//
// DIEEntry Implementation
//===----------------------------------------------------------------------===//

/// EmitValue - Emit debug information entry offset.
///
void DIEEntry::EmitValue(AsmPrinter *AP, unsigned Form) const {
  AP->EmitInt32(Entry->getOffset());
}

#ifndef NDEBUG
void DIEEntry::print(raw_ostream &O) {
  O << format("Die: 0x%lx", (long)(intptr_t)Entry);
}
#endif

//===----------------------------------------------------------------------===//
// DIEBlock Implementation
//===----------------------------------------------------------------------===//

/// ComputeSize - calculate the size of the block.
///
unsigned DIEBlock::ComputeSize(AsmPrinter *AP) {
  if (!Size) {
    const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData();
    for (unsigned i = 0, N = Values.size(); i < N; ++i)
      Size += Values[i]->SizeOf(AP, AbbrevData[i].getForm());
  }

  return Size;
}

/// EmitValue - Emit block data.
///
void DIEBlock::EmitValue(AsmPrinter *Asm, unsigned Form) const {
  switch (Form) {
  default: llvm_unreachable("Improper form for block");
  case dwarf::DW_FORM_block1: Asm->EmitInt8(Size);    break;
  case dwarf::DW_FORM_block2: Asm->EmitInt16(Size);   break;
  case dwarf::DW_FORM_block4: Asm->EmitInt32(Size);   break;
  case dwarf::DW_FORM_block:  Asm->EmitULEB128(Size); break;
  }

  const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData();
  for (unsigned i = 0, N = Values.size(); i < N; ++i)
    Values[i]->EmitValue(Asm, AbbrevData[i].getForm());
}

/// SizeOf - Determine size of block data in bytes.
///
unsigned DIEBlock::SizeOf(AsmPrinter *AP, unsigned Form) const {
  switch (Form) {
  case dwarf::DW_FORM_block1: return Size + sizeof(int8_t);
  case dwarf::DW_FORM_block2: return Size + sizeof(int16_t);
  case dwarf::DW_FORM_block4: return Size + sizeof(int32_t);
  case dwarf::DW_FORM_block:  return Size + MCAsmInfo::getULEB128Size(Size);
  default: llvm_unreachable("Improper form for block");
  }
}

#ifndef NDEBUG
void DIEBlock::print(raw_ostream &O) {
  O << "Blk: ";
  DIE::print(O, 5);
}
#endif
<commit_msg>No functionality change. Use unreachable in getCompileUnit.<commit_after>//===--- lib/CodeGen/DIE.cpp - DWARF Info Entries -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Data structures for DWARF info entries.
//
//===----------------------------------------------------------------------===//

#include "DIE.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
using namespace llvm;

//===----------------------------------------------------------------------===//
// DIEAbbrevData Implementation
//===----------------------------------------------------------------------===//

/// Profile - Used to gather unique data for the abbreviation folding set.
///
void DIEAbbrevData::Profile(FoldingSetNodeID &ID) const {
  ID.AddInteger(Attribute);
  ID.AddInteger(Form);
}

//===----------------------------------------------------------------------===//
// DIEAbbrev Implementation
//===----------------------------------------------------------------------===//

/// Profile - Used to gather unique data for the abbreviation folding set.
///
void DIEAbbrev::Profile(FoldingSetNodeID &ID) const {
  ID.AddInteger(Tag);
  ID.AddInteger(ChildrenFlag);

  // For each attribute description.
  for (unsigned i = 0, N = Data.size(); i < N; ++i)
    Data[i].Profile(ID);
}

/// Emit - Print the abbreviation using the specified asm printer.
///
void DIEAbbrev::Emit(AsmPrinter *AP) const {
  // Emit its Dwarf tag type.
  // FIXME: Doing work even in non-asm-verbose runs.
  AP->EmitULEB128(Tag, dwarf::TagString(Tag));

  // Emit whether it has children DIEs.
  // FIXME: Doing work even in non-asm-verbose runs.
  AP->EmitULEB128(ChildrenFlag, dwarf::ChildrenString(ChildrenFlag));

  // For each attribute description.
  for (unsigned i = 0, N = Data.size(); i < N; ++i) {
    const DIEAbbrevData &AttrData = Data[i];

    // Emit attribute type.
    // FIXME: Doing work even in non-asm-verbose runs.
    AP->EmitULEB128(AttrData.getAttribute(),
                    dwarf::AttributeString(AttrData.getAttribute()));

    // Emit form type.
    // FIXME: Doing work even in non-asm-verbose runs.
    AP->EmitULEB128(AttrData.getForm(),
                    dwarf::FormEncodingString(AttrData.getForm()));
  }

  // Mark end of abbreviation.
  AP->EmitULEB128(0, "EOM(1)");
  AP->EmitULEB128(0, "EOM(2)");
}

#ifndef NDEBUG
void DIEAbbrev::print(raw_ostream &O) {
  O << "Abbreviation @"
    << format("0x%lx", (long)(intptr_t)this)
    << "  "
    << dwarf::TagString(Tag)
    << " "
    << dwarf::ChildrenString(ChildrenFlag)
    << '\n';

  for (unsigned i = 0, N = Data.size(); i < N; ++i) {
    O << "  "
      << dwarf::AttributeString(Data[i].getAttribute())
      << "  "
      << dwarf::FormEncodingString(Data[i].getForm())
      << '\n';
  }
}
void DIEAbbrev::dump() { print(dbgs()); }
#endif

//===----------------------------------------------------------------------===//
// DIE Implementation
//===----------------------------------------------------------------------===//

DIE::~DIE() {
  for (unsigned i = 0, N = Children.size(); i < N; ++i)
    delete Children[i];
}

/// Climb up the parent chain to get the compile unit DIE this DIE belongs to.
DIE *DIE::getCompileUnit() const{
  DIE *p = getParent();
  while (p) {
    if (p->getTag() == dwarf::DW_TAG_compile_unit)
      return p;
    p = p->getParent();
  }
  llvm_unreachable("We should not have orphaned DIEs.");
}

#ifndef NDEBUG
void DIE::print(raw_ostream &O, unsigned IncIndent) {
  IndentCount += IncIndent;
  const std::string Indent(IndentCount, ' ');
  bool isBlock = Abbrev.getTag() == 0;

  if (!isBlock) {
    O << Indent
      << "Die: "
      << format("0x%lx", (long)(intptr_t)this)
      << ", Offset: " << Offset
      << ", Size: " << Size << "\n";

    O << Indent
      << dwarf::TagString(Abbrev.getTag())
      << " "
      << dwarf::ChildrenString(Abbrev.getChildrenFlag()) << "\n";
  } else {
    O << "Size: " << Size << "\n";
  }

  const SmallVector<DIEAbbrevData, 8> &Data = Abbrev.getData();

  IndentCount += 2;
  for (unsigned i = 0, N = Data.size(); i < N; ++i) {
    O << Indent;

    if (!isBlock)
      O << dwarf::AttributeString(Data[i].getAttribute());
    else
      O << "Blk[" << i << "]";

    O <<  "  "
      << dwarf::FormEncodingString(Data[i].getForm())
      << " ";
    Values[i]->print(O);
    O << "\n";
  }
  IndentCount -= 2;

  for (unsigned j = 0, M = Children.size(); j < M; ++j) {
    Children[j]->print(O, 4);
  }

  if (!isBlock) O << "\n";
  IndentCount -= IncIndent;
}

void DIE::dump() {
  print(dbgs());
}
#endif

void DIEValue::anchor() { }

#ifndef NDEBUG
void DIEValue::dump() {
  print(dbgs());
}
#endif

//===----------------------------------------------------------------------===//
// DIEInteger Implementation
//===----------------------------------------------------------------------===//

/// EmitValue - Emit integer of appropriate size.
///
void DIEInteger::EmitValue(AsmPrinter *Asm, unsigned Form) const {
  unsigned Size = ~0U;
  switch (Form) {
  case dwarf::DW_FORM_flag_present:
    // Emit something to keep the lines and comments in sync.
    // FIXME: Is there a better way to do this?
    if (Asm->OutStreamer.hasRawTextSupport())
      Asm->OutStreamer.EmitRawText(StringRef(""));
    return;
  case dwarf::DW_FORM_flag:  // Fall thru
  case dwarf::DW_FORM_ref1:  // Fall thru
  case dwarf::DW_FORM_data1: Size = 1; break;
  case dwarf::DW_FORM_ref2:  // Fall thru
  case dwarf::DW_FORM_data2: Size = 2; break;
  case dwarf::DW_FORM_sec_offset: // Fall thru
  case dwarf::DW_FORM_ref4:  // Fall thru
  case dwarf::DW_FORM_data4: Size = 4; break;
  case dwarf::DW_FORM_ref8:  // Fall thru
  case dwarf::DW_FORM_data8: Size = 8; break;
  case dwarf::DW_FORM_GNU_str_index: Asm->EmitULEB128(Integer); return;
  case dwarf::DW_FORM_GNU_addr_index: Asm->EmitULEB128(Integer); return;
  case dwarf::DW_FORM_udata: Asm->EmitULEB128(Integer); return;
  case dwarf::DW_FORM_sdata: Asm->EmitSLEB128(Integer); return;
  case dwarf::DW_FORM_addr:
    Size = Asm->getDataLayout().getPointerSize(); break;
  default: llvm_unreachable("DIE Value form not supported yet");
  }
  Asm->OutStreamer.EmitIntValue(Integer, Size);
}

/// SizeOf - Determine size of integer value in bytes.
///
unsigned DIEInteger::SizeOf(AsmPrinter *AP, unsigned Form) const {
  switch (Form) {
  case dwarf::DW_FORM_flag_present: return 0;
  case dwarf::DW_FORM_flag:  // Fall thru
  case dwarf::DW_FORM_ref1:  // Fall thru
  case dwarf::DW_FORM_data1: return sizeof(int8_t);
  case dwarf::DW_FORM_ref2:  // Fall thru
  case dwarf::DW_FORM_data2: return sizeof(int16_t);
  case dwarf::DW_FORM_sec_offset: // Fall thru
  case dwarf::DW_FORM_ref4:  // Fall thru
  case dwarf::DW_FORM_data4: return sizeof(int32_t);
  case dwarf::DW_FORM_ref8:  // Fall thru
  case dwarf::DW_FORM_data8: return sizeof(int64_t);
  case dwarf::DW_FORM_GNU_str_index: return MCAsmInfo::getULEB128Size(Integer);
  case dwarf::DW_FORM_GNU_addr_index: return MCAsmInfo::getULEB128Size(Integer);
  case dwarf::DW_FORM_udata: return MCAsmInfo::getULEB128Size(Integer);
  case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer);
  case dwarf::DW_FORM_addr:  return AP->getDataLayout().getPointerSize();
  default: llvm_unreachable("DIE Value form not supported yet");
  }
}

#ifndef NDEBUG
void DIEInteger::print(raw_ostream &O) {
  O << "Int: " << (int64_t)Integer << "  0x";
  O.write_hex(Integer);
}
#endif

//===----------------------------------------------------------------------===//
// DIELabel Implementation
//===----------------------------------------------------------------------===//

/// EmitValue - Emit label value.
///
void DIELabel::EmitValue(AsmPrinter *AP, unsigned Form) const {
  AP->OutStreamer.EmitSymbolValue(Label, SizeOf(AP, Form));
}

/// SizeOf - Determine size of label value in bytes.
///
unsigned DIELabel::SizeOf(AsmPrinter *AP, unsigned Form) const {
  if (Form == dwarf::DW_FORM_data4) return 4;
  if (Form == dwarf::DW_FORM_sec_offset) return 4;
  if (Form == dwarf::DW_FORM_strp) return 4;
  return AP->getDataLayout().getPointerSize();
}

#ifndef NDEBUG
void DIELabel::print(raw_ostream &O) {
  O << "Lbl: " << Label->getName();
}
#endif

//===----------------------------------------------------------------------===//
// DIEDelta Implementation
//===----------------------------------------------------------------------===//

/// EmitValue - Emit delta value.
///
void DIEDelta::EmitValue(AsmPrinter *AP, unsigned Form) const {
  AP->EmitLabelDifference(LabelHi, LabelLo, SizeOf(AP, Form));
}

/// SizeOf - Determine size of delta value in bytes.
///
unsigned DIEDelta::SizeOf(AsmPrinter *AP, unsigned Form) const {
  if (Form == dwarf::DW_FORM_data4) return 4;
  if (Form == dwarf::DW_FORM_strp) return 4;
  return AP->getDataLayout().getPointerSize();
}

#ifndef NDEBUG
void DIEDelta::print(raw_ostream &O) {
  O << "Del: " << LabelHi->getName() << "-" << LabelLo->getName();
}
#endif

//===----------------------------------------------------------------------===//
// DIEEntry Implementation
//===----------------------------------------------------------------------===//

/// EmitValue - Emit debug information entry offset.
///
void DIEEntry::EmitValue(AsmPrinter *AP, unsigned Form) const {
  AP->EmitInt32(Entry->getOffset());
}

#ifndef NDEBUG
void DIEEntry::print(raw_ostream &O) {
  O << format("Die: 0x%lx", (long)(intptr_t)Entry);
}
#endif

//===----------------------------------------------------------------------===//
// DIEBlock Implementation
//===----------------------------------------------------------------------===//

/// ComputeSize - calculate the size of the block.
///
unsigned DIEBlock::ComputeSize(AsmPrinter *AP) {
  if (!Size) {
    const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData();
    for (unsigned i = 0, N = Values.size(); i < N; ++i)
      Size += Values[i]->SizeOf(AP, AbbrevData[i].getForm());
  }

  return Size;
}

/// EmitValue - Emit block data.
///
void DIEBlock::EmitValue(AsmPrinter *Asm, unsigned Form) const {
  switch (Form) {
  default: llvm_unreachable("Improper form for block");
  case dwarf::DW_FORM_block1: Asm->EmitInt8(Size);    break;
  case dwarf::DW_FORM_block2: Asm->EmitInt16(Size);   break;
  case dwarf::DW_FORM_block4: Asm->EmitInt32(Size);   break;
  case dwarf::DW_FORM_block:  Asm->EmitULEB128(Size); break;
  }

  const SmallVector<DIEAbbrevData, 8> &AbbrevData = Abbrev.getData();
  for (unsigned i = 0, N = Values.size(); i < N; ++i)
    Values[i]->EmitValue(Asm, AbbrevData[i].getForm());
}

/// SizeOf - Determine size of block data in bytes.
///
unsigned DIEBlock::SizeOf(AsmPrinter *AP, unsigned Form) const {
  switch (Form) {
  case dwarf::DW_FORM_block1: return Size + sizeof(int8_t);
  case dwarf::DW_FORM_block2: return Size + sizeof(int16_t);
  case dwarf::DW_FORM_block4: return Size + sizeof(int32_t);
  case dwarf::DW_FORM_block:  return Size + MCAsmInfo::getULEB128Size(Size);
  default: llvm_unreachable("Improper form for block");
  }
}

#ifndef NDEBUG
void DIEBlock::print(raw_ostream &O) {
  O << "Blk: ";
  DIE::print(O, 5);
}
#endif
<|endoftext|>


<commit_before>/* This file is part of the KDE project
   Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk>
   Copyright (C) 2007 Anders Lund <anders@alweb.dk>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 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
   Library General Public License for more details.

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

#include "kateconsole.h"

#include <kiconloader.h>
#include <klocalizedstring.h>
#include <ktexteditor/document.h>
#include <ktexteditor/view.h>

#include <kde_terminal_interface.h>
#include <kshell.h>
#include <kparts/part.h>
#include <QAction>
#include <kactioncollection.h>

#include <kmessagebox.h>

#include <QApplication>
#include <QStyle>
#include <QIcon>
#include <QShowEvent>
#include <QLabel>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QFileInfo>

#include <kpluginloader.h>
#include <kservice.h>
#include <kaboutdata.h>
#include <kpluginfactory.h>
#include <kauthorized.h>
#include <KConfigGroup>
#include <KXMLGUIFactory>

K_PLUGIN_FACTORY_WITH_JSON (KateKonsolePluginFactory, "katekonsoleplugin.json", registerPlugin<KateKonsolePlugin>();)

KateKonsolePlugin::KateKonsolePlugin( QObject* parent, const QList<QVariant>& ):
    KTextEditor::Plugin ( parent )
{
  m_previousEditorEnv=qgetenv("EDITOR");
  if (!KAuthorized::authorizeKAction(QStringLiteral("shell_access")))
  {
    KMessageBox::sorry(0, i18n ("You do not have enough karma to access a shell or terminal emulation"));
  }
}

KateKonsolePlugin::~KateKonsolePlugin()
{
  ::setenv( "EDITOR", m_previousEditorEnv.data(), 1 );
}

QObject *KateKonsolePlugin::createView (KTextEditor::MainWindow *mainWindow)
{
  KateKonsolePluginView *view = new KateKonsolePluginView (this, mainWindow);
  return view;
}

KTextEditor::ConfigPage *KateKonsolePlugin::configPage (int number, QWidget *parent)
{
  if (number != 0)
    return 0;
  return new KateKonsoleConfigPage(parent, this);
}

QString KateKonsolePlugin::configPageName (int number) const
{
  if (number != 0) return QString();
  return i18n("Terminal");
}

QString KateKonsolePlugin::configPageFullName (int number) const
{
  if (number != 0) return QString();
  return i18n("Terminal Settings");
}

QIcon KateKonsolePlugin::configPageIcon (int number) const
{
  if (number != 0) return QIcon();
  return QIcon::fromTheme(QStringLiteral("utilities-terminal"));
}

void KateKonsolePlugin::readConfig()
{
  foreach ( KateKonsolePluginView *view, mViews )
    view->readConfig();
}

KateKonsolePluginView::KateKonsolePluginView (KateKonsolePlugin* plugin, KTextEditor::MainWindow *mainWindow)
    : QObject(mainWindow),m_plugin(plugin)
{
  // init console
  QWidget *toolview = mainWindow->createToolView (plugin, QStringLiteral("kate_private_plugin_katekonsoleplugin"), KTextEditor::MainWindow::Bottom, SmallIcon(QStringLiteral("utilities-terminal")), i18n("Terminal"));
  m_console = new KateConsole(m_plugin, mainWindow, toolview);

  // register this view
  m_plugin->mViews.append ( this );
}

KateKonsolePluginView::~KateKonsolePluginView ()
{
  // unregister this view
  m_plugin->mViews.removeAll (this);

  // cleanup, kill toolview + console
  QWidget *toolview = m_console->parentWidget();
  delete m_console;
  delete toolview;
}

void KateKonsolePluginView::readConfig()
{
  m_console->readConfig();
}

KateConsole::KateConsole (KateKonsolePlugin* plugin, KTextEditor::MainWindow *mw, QWidget *parent)
    : QWidget (parent)
    , m_part (0)
    , m_mw (mw)
    , m_toolView (parent)
    , m_plugin(plugin)
{
  KXMLGUIClient::setComponentName (QStringLiteral("katekonsole"), i18n ("Kate Terminal"));
  setXMLFile( QStringLiteral("ui.rc") );

  // make sure we have a vertical layout
  new QVBoxLayout(this);

  QAction* a = actionCollection()->addAction(QStringLiteral("katekonsole_tools_pipe_to_terminal"));
  a->setIcon(QIcon::fromTheme(QStringLiteral("utilities-terminal")));
  a->setText(i18nc("@action", "&Pipe to Terminal"));
  connect(a, SIGNAL(triggered()), this, SLOT(slotPipeToConsole()));

  a = actionCollection()->addAction(QStringLiteral("katekonsole_tools_sync"));
  a->setText(i18nc("@action", "S&ynchronize Terminal with Current Document"));
  connect(a, SIGNAL(triggered()), this, SLOT(slotManualSync()));

  a = actionCollection()->addAction(QStringLiteral("katekonsole_tools_toggle_focus"));
  a->setIcon(QIcon::fromTheme(QStringLiteral("utilities-terminal")));
  a->setText(i18nc("@action", "&Focus Terminal"));
  connect(a, SIGNAL(triggered()), this, SLOT(slotToggleFocus()));

  m_mw->guiFactory()->addClient (this);

  readConfig();
}

KateConsole::~KateConsole ()
{
  m_mw->guiFactory()->removeClient (this);
  if (m_part)
    disconnect ( m_part, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
}

void KateConsole::loadConsoleIfNeeded()
{
  if (m_part) return;

  if (!window() || !parentWidget()) return;
  if (!window() || !isVisibleTo(window())) return;

  KPluginFactory* factory = 0;
  KService::Ptr service = KService::serviceByDesktopName(QStringLiteral("konsolepart"));
  if (service) {
      factory = KPluginLoader(service->library()).factory();
  }

  if (!factory) return;

  m_part = static_cast<KParts::ReadOnlyPart *>(factory->create<QObject>(this, this));

  if (!m_part) return;

  layout()->addWidget(m_part->widget());

  // start the terminal
  qobject_cast<TerminalInterface*>(m_part)->showShellInDir( QString() );

//   KGlobal::locale()->insertCatalog("konsole"); // FIXME KF5: insert catalog

  setFocusProxy(m_part->widget());
  m_part->widget()->show();

  connect ( m_part, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
  connect ( m_part, SIGNAL(overrideShortcut(QKeyEvent*,bool&)),
                    this, SLOT(overrideShortcut(QKeyEvent*,bool&)));
  slotSync();
}

void KateConsole::slotDestroyed ()
{
  m_part = 0;
  m_currentPath.clear ();

  // hide the dockwidget
  if (parentWidget()) {
    m_mw->hideToolView (m_toolView);
  }
}

void KateConsole::overrideShortcut (QKeyEvent *, bool &override)
{
  /**
   * let konsole handle all shortcuts
   */
  override = true;
}

void KateConsole::showEvent(QShowEvent *)
{
  if (m_part) return;

  loadConsoleIfNeeded();
}

void KateConsole::cd (const QString & path)
{
  if (m_currentPath == path)
    return;

  if (!m_part)
    return;

  m_currentPath = path;
  sendInput(QStringLiteral("cd ") + KShell::quoteArg(m_currentPath) + QLatin1Char('\n'));
}

void KateConsole::sendInput( const QString& text )
{
  loadConsoleIfNeeded();

  if (!m_part) return;

  TerminalInterface *t = qobject_cast<TerminalInterface *>(m_part);

  if (!t) return;

  t->sendInput (text);
}

void KateConsole::slotPipeToConsole ()
{
  if (KMessageBox::warningContinueCancel
      (m_mw->window()
       , i18n ("Do you really want to pipe the text to the console? This will execute any contained commands with your user rights.")
       , i18n ("Pipe to Terminal?")
       , KGuiItem(i18n("Pipe to Terminal")), KStandardGuiItem::cancel(), QStringLiteral("Pipe To Terminal Warning")) != KMessageBox::Continue)
    return;

  KTextEditor::View *v = m_mw->activeView();

  if (!v)
    return;

  if (v->selection())
    sendInput (v->selectionText());
  else
    sendInput (v->document()->text());
}

void KateConsole::slotSync(KTextEditor::View *)
{
  if (m_mw->activeView() ) {
    QUrl u = m_mw->activeView()->document()->url();
    if ( u.isValid() && u.isLocalFile() ) {
      QFileInfo fi(u.toLocalFile());
      cd(fi.absoluteFilePath() );
    } else if ( !u.isEmpty() ) {
      sendInput( QStringLiteral("### ") + i18n("Sorry, cannot cd into '%1'", u.toLocalFile() ) + QLatin1Char('\n') );
    }
  }
}

void KateConsole::slotManualSync()
{
  m_currentPath.clear ();
  slotSync();
  if ( ! m_part || ! m_part->widget()->isVisible() )
    m_mw->showToolView( parentWidget() );
}
void KateConsole::slotToggleFocus()
{
  QAction *action = actionCollection()->action(QStringLiteral("katekonsole_tools_toggle_focus"));
  if ( ! m_part ) {
    m_mw->showToolView( parentWidget() );
    action->setText( i18n("Defocus Terminal") );
    return; // this shows and focuses the konsole
  }

  if ( ! m_part ) return;

  if (m_part->widget()->hasFocus()) {
    if (m_mw->activeView())
      m_mw->activeView()->setFocus();
      action->setText( i18n("Focus Terminal") );
  } else {
    // show the view if it is hidden
    if (parentWidget()->isHidden())
      m_mw->showToolView( parentWidget() );
    else // should focus the widget too!
      m_part->widget()->setFocus( Qt::OtherFocusReason );
    action->setText( i18n("Defocus Terminal") );
  }
}

void KateConsole::readConfig()
{
  disconnect(m_mw, &KTextEditor::MainWindow::viewChanged, this, &KateConsole::slotSync);
  if ( KConfigGroup(KSharedConfig::openConfig(), "Konsole").readEntry("AutoSyncronize", false) ) {
    connect(m_mw, &KTextEditor::MainWindow::viewChanged, this, &KateConsole::slotSync);
  }

  if ( KConfigGroup(KSharedConfig::openConfig(), "Konsole").readEntry("SetEditor", false) )
    ::setenv( "EDITOR", "kate -b",1);
  else
    ::setenv( "EDITOR", m_plugin->previousEditorEnv().data(), 1 );
}

KateKonsoleConfigPage::KateKonsoleConfigPage( QWidget* parent, KateKonsolePlugin *plugin )
  : KTextEditor::ConfigPage( parent )
  , mPlugin( plugin )
{
  QVBoxLayout *lo = new QVBoxLayout( this );
  lo->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));

  cbAutoSyncronize = new QCheckBox( i18n("&Automatically synchronize the terminal with the current document when possible"), this );
  lo->addWidget( cbAutoSyncronize );
  cbSetEditor = new QCheckBox( i18n("Set &EDITOR environment variable to 'kate -b'"), this );
  lo->addWidget( cbSetEditor );
  QLabel *tmp = new QLabel(this);
  tmp->setText(i18n("Important: The document has to be closed to make the console application continue"));
  lo->addWidget(tmp);
  reset();
  lo->addStretch();
  connect( cbAutoSyncronize, SIGNAL(stateChanged(int)), SIGNAL(changed()) );
  connect( cbSetEditor, SIGNAL(stateChanged(int)), SIGNAL(changed()) );
}

void KateKonsoleConfigPage::apply()
{
  KConfigGroup config(KSharedConfig::openConfig(), "Konsole");
  config.writeEntry("AutoSyncronize", cbAutoSyncronize->isChecked());
  config.writeEntry("SetEditor", cbSetEditor->isChecked());
  config.sync();
  mPlugin->readConfig();
}

void KateKonsoleConfigPage::reset()
{
  KConfigGroup config(KSharedConfig::openConfig(), "Konsole");
  cbAutoSyncronize->setChecked(config.readEntry("AutoSyncronize", false));
  cbSetEditor->setChecked(config.readEntry("SetEditor", false));
}

#include "kateconsole.moc"

// kate: space-indent on; indent-width 2; replace-tabs on;

<commit_msg>absoluteFilePath() -> absolutePath()<commit_after>/* This file is part of the KDE project
   Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org>
   Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
   Copyright (C) 2002 Anders Lund <anders.lund@lund.tdcadsl.dk>
   Copyright (C) 2007 Anders Lund <anders@alweb.dk>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License version 2 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
   Library General Public License for more details.

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

#include "kateconsole.h"

#include <kiconloader.h>
#include <klocalizedstring.h>
#include <ktexteditor/document.h>
#include <ktexteditor/view.h>

#include <kde_terminal_interface.h>
#include <kshell.h>
#include <kparts/part.h>
#include <QAction>
#include <kactioncollection.h>

#include <kmessagebox.h>

#include <QApplication>
#include <QStyle>
#include <QIcon>
#include <QShowEvent>
#include <QLabel>
#include <QCheckBox>
#include <QVBoxLayout>
#include <QFileInfo>

#include <kpluginloader.h>
#include <kservice.h>
#include <kaboutdata.h>
#include <kpluginfactory.h>
#include <kauthorized.h>
#include <KConfigGroup>
#include <KXMLGUIFactory>

K_PLUGIN_FACTORY_WITH_JSON (KateKonsolePluginFactory, "katekonsoleplugin.json", registerPlugin<KateKonsolePlugin>();)

KateKonsolePlugin::KateKonsolePlugin( QObject* parent, const QList<QVariant>& ):
    KTextEditor::Plugin ( parent )
{
  m_previousEditorEnv=qgetenv("EDITOR");
  if (!KAuthorized::authorizeKAction(QStringLiteral("shell_access")))
  {
    KMessageBox::sorry(0, i18n ("You do not have enough karma to access a shell or terminal emulation"));
  }
}

KateKonsolePlugin::~KateKonsolePlugin()
{
  ::setenv( "EDITOR", m_previousEditorEnv.data(), 1 );
}

QObject *KateKonsolePlugin::createView (KTextEditor::MainWindow *mainWindow)
{
  KateKonsolePluginView *view = new KateKonsolePluginView (this, mainWindow);
  return view;
}

KTextEditor::ConfigPage *KateKonsolePlugin::configPage (int number, QWidget *parent)
{
  if (number != 0)
    return 0;
  return new KateKonsoleConfigPage(parent, this);
}

QString KateKonsolePlugin::configPageName (int number) const
{
  if (number != 0) return QString();
  return i18n("Terminal");
}

QString KateKonsolePlugin::configPageFullName (int number) const
{
  if (number != 0) return QString();
  return i18n("Terminal Settings");
}

QIcon KateKonsolePlugin::configPageIcon (int number) const
{
  if (number != 0) return QIcon();
  return QIcon::fromTheme(QStringLiteral("utilities-terminal"));
}

void KateKonsolePlugin::readConfig()
{
  foreach ( KateKonsolePluginView *view, mViews )
    view->readConfig();
}

KateKonsolePluginView::KateKonsolePluginView (KateKonsolePlugin* plugin, KTextEditor::MainWindow *mainWindow)
    : QObject(mainWindow),m_plugin(plugin)
{
  // init console
  QWidget *toolview = mainWindow->createToolView (plugin, QStringLiteral("kate_private_plugin_katekonsoleplugin"), KTextEditor::MainWindow::Bottom, SmallIcon(QStringLiteral("utilities-terminal")), i18n("Terminal"));
  m_console = new KateConsole(m_plugin, mainWindow, toolview);

  // register this view
  m_plugin->mViews.append ( this );
}

KateKonsolePluginView::~KateKonsolePluginView ()
{
  // unregister this view
  m_plugin->mViews.removeAll (this);

  // cleanup, kill toolview + console
  QWidget *toolview = m_console->parentWidget();
  delete m_console;
  delete toolview;
}

void KateKonsolePluginView::readConfig()
{
  m_console->readConfig();
}

KateConsole::KateConsole (KateKonsolePlugin* plugin, KTextEditor::MainWindow *mw, QWidget *parent)
    : QWidget (parent)
    , m_part (0)
    , m_mw (mw)
    , m_toolView (parent)
    , m_plugin(plugin)
{
  KXMLGUIClient::setComponentName (QStringLiteral("katekonsole"), i18n ("Kate Terminal"));
  setXMLFile( QStringLiteral("ui.rc") );

  // make sure we have a vertical layout
  new QVBoxLayout(this);

  QAction* a = actionCollection()->addAction(QStringLiteral("katekonsole_tools_pipe_to_terminal"));
  a->setIcon(QIcon::fromTheme(QStringLiteral("utilities-terminal")));
  a->setText(i18nc("@action", "&Pipe to Terminal"));
  connect(a, SIGNAL(triggered()), this, SLOT(slotPipeToConsole()));

  a = actionCollection()->addAction(QStringLiteral("katekonsole_tools_sync"));
  a->setText(i18nc("@action", "S&ynchronize Terminal with Current Document"));
  connect(a, SIGNAL(triggered()), this, SLOT(slotManualSync()));

  a = actionCollection()->addAction(QStringLiteral("katekonsole_tools_toggle_focus"));
  a->setIcon(QIcon::fromTheme(QStringLiteral("utilities-terminal")));
  a->setText(i18nc("@action", "&Focus Terminal"));
  connect(a, SIGNAL(triggered()), this, SLOT(slotToggleFocus()));

  m_mw->guiFactory()->addClient (this);

  readConfig();
}

KateConsole::~KateConsole ()
{
  m_mw->guiFactory()->removeClient (this);
  if (m_part)
    disconnect ( m_part, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
}

void KateConsole::loadConsoleIfNeeded()
{
  if (m_part) return;

  if (!window() || !parentWidget()) return;
  if (!window() || !isVisibleTo(window())) return;

  KPluginFactory* factory = 0;
  KService::Ptr service = KService::serviceByDesktopName(QStringLiteral("konsolepart"));
  if (service) {
      factory = KPluginLoader(service->library()).factory();
  }

  if (!factory) return;

  m_part = static_cast<KParts::ReadOnlyPart *>(factory->create<QObject>(this, this));

  if (!m_part) return;

  layout()->addWidget(m_part->widget());

  // start the terminal
  qobject_cast<TerminalInterface*>(m_part)->showShellInDir( QString() );

//   KGlobal::locale()->insertCatalog("konsole"); // FIXME KF5: insert catalog

  setFocusProxy(m_part->widget());
  m_part->widget()->show();

  connect ( m_part, SIGNAL(destroyed()), this, SLOT(slotDestroyed()) );
  connect ( m_part, SIGNAL(overrideShortcut(QKeyEvent*,bool&)),
                    this, SLOT(overrideShortcut(QKeyEvent*,bool&)));
  slotSync();
}

void KateConsole::slotDestroyed ()
{
  m_part = 0;
  m_currentPath.clear ();

  // hide the dockwidget
  if (parentWidget()) {
    m_mw->hideToolView (m_toolView);
  }
}

void KateConsole::overrideShortcut (QKeyEvent *, bool &override)
{
  /**
   * let konsole handle all shortcuts
   */
  override = true;
}

void KateConsole::showEvent(QShowEvent *)
{
  if (m_part) return;

  loadConsoleIfNeeded();
}

void KateConsole::cd (const QString & path)
{
  if (m_currentPath == path)
    return;

  if (!m_part)
    return;

  m_currentPath = path;
  sendInput(QStringLiteral("cd ") + KShell::quoteArg(m_currentPath) + QLatin1Char('\n'));
}

void KateConsole::sendInput( const QString& text )
{
  loadConsoleIfNeeded();

  if (!m_part) return;

  TerminalInterface *t = qobject_cast<TerminalInterface *>(m_part);

  if (!t) return;

  t->sendInput (text);
}

void KateConsole::slotPipeToConsole ()
{
  if (KMessageBox::warningContinueCancel
      (m_mw->window()
       , i18n ("Do you really want to pipe the text to the console? This will execute any contained commands with your user rights.")
       , i18n ("Pipe to Terminal?")
       , KGuiItem(i18n("Pipe to Terminal")), KStandardGuiItem::cancel(), QStringLiteral("Pipe To Terminal Warning")) != KMessageBox::Continue)
    return;

  KTextEditor::View *v = m_mw->activeView();

  if (!v)
    return;

  if (v->selection())
    sendInput (v->selectionText());
  else
    sendInput (v->document()->text());
}

void KateConsole::slotSync(KTextEditor::View *)
{
  if (m_mw->activeView()) {
    QUrl u = m_mw->activeView()->document()->url();
    if (u.isValid() && u.isLocalFile()) {
      QFileInfo fi(u.toLocalFile());
      cd(fi.absolutePath());
    } else if (!u.isEmpty()) {
      sendInput( QStringLiteral("### ") + i18n("Sorry, cannot cd into '%1'", u.toLocalFile() ) + QLatin1Char('\n') );
    }
  }
}

void KateConsole::slotManualSync()
{
  m_currentPath.clear ();
  slotSync();
  if ( ! m_part || ! m_part->widget()->isVisible() )
    m_mw->showToolView( parentWidget() );
}
void KateConsole::slotToggleFocus()
{
  QAction *action = actionCollection()->action(QStringLiteral("katekonsole_tools_toggle_focus"));
  if ( ! m_part ) {
    m_mw->showToolView( parentWidget() );
    action->setText( i18n("Defocus Terminal") );
    return; // this shows and focuses the konsole
  }

  if ( ! m_part ) return;

  if (m_part->widget()->hasFocus()) {
    if (m_mw->activeView())
      m_mw->activeView()->setFocus();
      action->setText( i18n("Focus Terminal") );
  } else {
    // show the view if it is hidden
    if (parentWidget()->isHidden())
      m_mw->showToolView( parentWidget() );
    else // should focus the widget too!
      m_part->widget()->setFocus( Qt::OtherFocusReason );
    action->setText( i18n("Defocus Terminal") );
  }
}

void KateConsole::readConfig()
{
  disconnect(m_mw, &KTextEditor::MainWindow::viewChanged, this, &KateConsole::slotSync);
  if ( KConfigGroup(KSharedConfig::openConfig(), "Konsole").readEntry("AutoSyncronize", false) ) {
    connect(m_mw, &KTextEditor::MainWindow::viewChanged, this, &KateConsole::slotSync);
  }

  if ( KConfigGroup(KSharedConfig::openConfig(), "Konsole").readEntry("SetEditor", false) )
    ::setenv( "EDITOR", "kate -b",1);
  else
    ::setenv( "EDITOR", m_plugin->previousEditorEnv().data(), 1 );
}

KateKonsoleConfigPage::KateKonsoleConfigPage( QWidget* parent, KateKonsolePlugin *plugin )
  : KTextEditor::ConfigPage( parent )
  , mPlugin( plugin )
{
  QVBoxLayout *lo = new QVBoxLayout( this );
  lo->setSpacing(QApplication::style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing));

  cbAutoSyncronize = new QCheckBox( i18n("&Automatically synchronize the terminal with the current document when possible"), this );
  lo->addWidget( cbAutoSyncronize );
  cbSetEditor = new QCheckBox( i18n("Set &EDITOR environment variable to 'kate -b'"), this );
  lo->addWidget( cbSetEditor );
  QLabel *tmp = new QLabel(this);
  tmp->setText(i18n("Important: The document has to be closed to make the console application continue"));
  lo->addWidget(tmp);
  reset();
  lo->addStretch();
  connect( cbAutoSyncronize, SIGNAL(stateChanged(int)), SIGNAL(changed()) );
  connect( cbSetEditor, SIGNAL(stateChanged(int)), SIGNAL(changed()) );
}

void KateKonsoleConfigPage::apply()
{
  KConfigGroup config(KSharedConfig::openConfig(), "Konsole");
  config.writeEntry("AutoSyncronize", cbAutoSyncronize->isChecked());
  config.writeEntry("SetEditor", cbSetEditor->isChecked());
  config.sync();
  mPlugin->readConfig();
}

void KateKonsoleConfigPage::reset()
{
  KConfigGroup config(KSharedConfig::openConfig(), "Konsole");
  cbAutoSyncronize->setChecked(config.readEntry("AutoSyncronize", false));
  cbSetEditor->setChecked(config.readEntry("SetEditor", false));
}

#include "kateconsole.moc"

// kate: space-indent on; indent-width 2; replace-tabs on;

<|endoftext|>


<commit_before><commit_msg>Fixed name for xapiand_max_time_delete<commit_after><|endoftext|>


<commit_before>/*
 * Copyright © 2012 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "main/core.h"
#include "ir.h"
#include "linker.h"
#include "ir_uniform.h"
#include "glsl_symbol_table.h"
#include "program/hash_table.h"

/* These functions are put in a "private" namespace instead of being marked
 * static so that the unit tests can access them.  See
 * http://code.google.com/p/googletest/wiki/AdvancedGuide#Testing_Private_Code
 */
namespace linker {

gl_uniform_storage *
get_storage(gl_uniform_storage *storage, unsigned num_storage,
	    const char *name)
{
   for (unsigned int i = 0; i < num_storage; i++) {
      if (strcmp(name, storage[i].name) == 0)
	 return &storage[i];
   }

   return NULL;
}

void
copy_constant_to_storage(union gl_constant_value *storage,
			 const ir_constant *val,
			 const enum glsl_base_type base_type,
			 const unsigned int elements)
{
   for (unsigned int i = 0; i < elements; i++) {
      switch (base_type) {
      case GLSL_TYPE_UINT:
	 storage[i].u = val->value.u[i];
	 break;
      case GLSL_TYPE_INT:
      case GLSL_TYPE_SAMPLER:
	 storage[i].i = val->value.i[i];
	 break;
      case GLSL_TYPE_FLOAT:
	 storage[i].f = val->value.f[i];
	 break;
      case GLSL_TYPE_BOOL:
	 storage[i].b = int(val->value.b[i]);
	 break;
      case GLSL_TYPE_ARRAY:
      case GLSL_TYPE_STRUCT:
      case GLSL_TYPE_IMAGE:
      case GLSL_TYPE_ATOMIC_UINT:
      case GLSL_TYPE_INTERFACE:
      case GLSL_TYPE_VOID:
      case GLSL_TYPE_ERROR:
	 /* All other types should have already been filtered by other
	  * paths in the caller.
	  */
	 assert(!"Should not get here.");
	 break;
      }
   }
}

void
set_uniform_binding(void *mem_ctx, gl_shader_program *prog,
                    const char *name, const glsl_type *type, int binding)
{
   struct gl_uniform_storage *const storage =
      get_storage(prog->UniformStorage, prog->NumUserUniformStorage, name);

   if (storage == NULL) {
      assert(storage != NULL);
      return;
   }

   if (storage->type->is_sampler()) {
      unsigned elements = MAX2(storage->array_elements, 1);

      /* From section 4.4.4 of the GLSL 4.20 specification:
       * "If the binding identifier is used with an array, the first element
       *  of the array takes the specified unit and each subsequent element
       *  takes the next consecutive unit."
       */
      for (unsigned int i = 0; i < elements; i++) {
         storage->storage[i].i = binding + i;
      }

      for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
         gl_shader *shader = prog->_LinkedShaders[sh];

         if (shader && storage->sampler[sh].active) {
            for (unsigned i = 0; i < elements; i++) {
               unsigned index = storage->sampler[sh].index + i;

               shader->SamplerUnits[index] = storage->storage[i].i;
            }
         }
      }
   } else if (storage->block_index != -1) {
      /* This is a field of a UBO.  val is the binding index. */
      for (int i = 0; i < MESA_SHADER_STAGES; i++) {
         int stage_index = prog->UniformBlockStageIndex[i][storage->block_index];

         if (stage_index != -1) {
            struct gl_shader *sh = prog->_LinkedShaders[i];
            sh->UniformBlocks[stage_index].Binding = binding;
         }
      }
   }

   storage->initialized = true;
}

void
set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
			const char *name, const glsl_type *type,
			ir_constant *val)
{
   if (type->is_record()) {
      ir_constant *field_constant;

      field_constant = (ir_constant *)val->components.get_head();

      for (unsigned int i = 0; i < type->length; i++) {
	 const glsl_type *field_type = type->fields.structure[i].type;
	 const char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name,
					    type->fields.structure[i].name);
	 set_uniform_initializer(mem_ctx, prog, field_name,
				 field_type, field_constant);
	 field_constant = (ir_constant *)field_constant->next;
      }
      return;
   } else if (type->is_array() && type->fields.array->is_record()) {
      const glsl_type *const element_type = type->fields.array;

      for (unsigned int i = 0; i < type->length; i++) {
	 const char *element_name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i);

	 set_uniform_initializer(mem_ctx, prog, element_name,
				 element_type, val->array_elements[i]);
      }
      return;
   }

   struct gl_uniform_storage *const storage =
      get_storage(prog->UniformStorage,
		  prog->NumUserUniformStorage,
		  name);
   if (storage == NULL) {
      assert(storage != NULL);
      return;
   }

   if (val->type->is_array()) {
      const enum glsl_base_type base_type =
	 val->array_elements[0]->type->base_type;
      const unsigned int elements = val->array_elements[0]->type->components();
      unsigned int idx = 0;

      assert(val->type->length >= storage->array_elements);
      for (unsigned int i = 0; i < storage->array_elements; i++) {
	 copy_constant_to_storage(& storage->storage[idx],
				  val->array_elements[i],
				  base_type,
				  elements);

	 idx += elements;
      }
   } else {
      copy_constant_to_storage(storage->storage,
			       val,
			       val->type->base_type,
			       val->type->components());

      if (storage->type->is_sampler()) {
         for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
            gl_shader *shader = prog->_LinkedShaders[sh];

            if (shader && storage->sampler[sh].active) {
               unsigned index = storage->sampler[sh].index;

               shader->SamplerUnits[index] = storage->storage[0].i;
            }
         }
      }
   }

   storage->initialized = true;
}
}

void
link_set_uniform_initializers(struct gl_shader_program *prog)
{
   void *mem_ctx = NULL;

   for (unsigned int i = 0; i < MESA_SHADER_STAGES; i++) {
      struct gl_shader *shader = prog->_LinkedShaders[i];

      if (shader == NULL)
	 continue;

      foreach_list(node, shader->ir) {
	 ir_variable *const var = ((ir_instruction *) node)->as_variable();

	 if (!var || var->data.mode != ir_var_uniform)
	    continue;

	 if (!mem_ctx)
	    mem_ctx = ralloc_context(NULL);

         if (var->data.explicit_binding) {
            linker::set_uniform_binding(mem_ctx, prog, var->name,
                                        var->type, var->data.binding);
         } else if (var->constant_value) {
            linker::set_uniform_initializer(mem_ctx, prog, var->name,
                                            var->type, var->constant_value);
         }
      }
   }

   ralloc_free(mem_ctx);
}
<commit_msg>linker: Split set_uniform_binding into separate functions for blocks and samplers<commit_after>/*
 * Copyright © 2012 Intel Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#include "main/core.h"
#include "ir.h"
#include "linker.h"
#include "ir_uniform.h"
#include "glsl_symbol_table.h"
#include "program/hash_table.h"

/* These functions are put in a "private" namespace instead of being marked
 * static so that the unit tests can access them.  See
 * http://code.google.com/p/googletest/wiki/AdvancedGuide#Testing_Private_Code
 */
namespace linker {

gl_uniform_storage *
get_storage(gl_uniform_storage *storage, unsigned num_storage,
	    const char *name)
{
   for (unsigned int i = 0; i < num_storage; i++) {
      if (strcmp(name, storage[i].name) == 0)
	 return &storage[i];
   }

   return NULL;
}

void
copy_constant_to_storage(union gl_constant_value *storage,
			 const ir_constant *val,
			 const enum glsl_base_type base_type,
			 const unsigned int elements)
{
   for (unsigned int i = 0; i < elements; i++) {
      switch (base_type) {
      case GLSL_TYPE_UINT:
	 storage[i].u = val->value.u[i];
	 break;
      case GLSL_TYPE_INT:
      case GLSL_TYPE_SAMPLER:
	 storage[i].i = val->value.i[i];
	 break;
      case GLSL_TYPE_FLOAT:
	 storage[i].f = val->value.f[i];
	 break;
      case GLSL_TYPE_BOOL:
	 storage[i].b = int(val->value.b[i]);
	 break;
      case GLSL_TYPE_ARRAY:
      case GLSL_TYPE_STRUCT:
      case GLSL_TYPE_IMAGE:
      case GLSL_TYPE_ATOMIC_UINT:
      case GLSL_TYPE_INTERFACE:
      case GLSL_TYPE_VOID:
      case GLSL_TYPE_ERROR:
	 /* All other types should have already been filtered by other
	  * paths in the caller.
	  */
	 assert(!"Should not get here.");
	 break;
      }
   }
}

void
set_sampler_binding(void *mem_ctx, gl_shader_program *prog,
                    const char *name, const glsl_type *type, int binding)
{
   struct gl_uniform_storage *const storage =
      get_storage(prog->UniformStorage, prog->NumUserUniformStorage, name);

   if (storage == NULL) {
      assert(storage != NULL);
      return;
   }

   {
      unsigned elements = MAX2(storage->array_elements, 1);

      /* From section 4.4.4 of the GLSL 4.20 specification:
       * "If the binding identifier is used with an array, the first element
       *  of the array takes the specified unit and each subsequent element
       *  takes the next consecutive unit."
       */
      for (unsigned int i = 0; i < elements; i++) {
         storage->storage[i].i = binding + i;
      }

      for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
         gl_shader *shader = prog->_LinkedShaders[sh];

         if (shader && storage->sampler[sh].active) {
            for (unsigned i = 0; i < elements; i++) {
               unsigned index = storage->sampler[sh].index + i;

               shader->SamplerUnits[index] = storage->storage[i].i;
            }
         }
      }
   }

   storage->initialized = true;
}

void
set_block_binding(void *mem_ctx, gl_shader_program *prog,
                  const char *name, const glsl_type *type, int binding)
{
   struct gl_uniform_storage *const storage =
      get_storage(prog->UniformStorage, prog->NumUserUniformStorage, name);

   if (storage == NULL) {
      assert(storage != NULL);
      return;
   }

   if (storage->block_index != -1) {
      /* This is a field of a UBO.  val is the binding index. */
      for (int i = 0; i < MESA_SHADER_STAGES; i++) {
         int stage_index = prog->UniformBlockStageIndex[i][storage->block_index];

         if (stage_index != -1) {
            struct gl_shader *sh = prog->_LinkedShaders[i];
            sh->UniformBlocks[stage_index].Binding = binding;
         }
      }
   }

   storage->initialized = true;
}

void
set_uniform_binding(void *mem_ctx, gl_shader_program *prog,
                    const char *name, const glsl_type *type, int binding)
{
   struct gl_uniform_storage *const storage =
      get_storage(prog->UniformStorage, prog->NumUserUniformStorage, name);

   if (storage == NULL) {
      assert(storage != NULL);
      return;
   }

   if (storage->type->is_sampler()) {
      set_sampler_binding(mem_ctx, prog, name, type, binding);
   } else if (storage->block_index != -1) {
      set_block_binding(mem_ctx, prog, name, type, binding);
   }
}

void
set_uniform_initializer(void *mem_ctx, gl_shader_program *prog,
			const char *name, const glsl_type *type,
			ir_constant *val)
{
   if (type->is_record()) {
      ir_constant *field_constant;

      field_constant = (ir_constant *)val->components.get_head();

      for (unsigned int i = 0; i < type->length; i++) {
	 const glsl_type *field_type = type->fields.structure[i].type;
	 const char *field_name = ralloc_asprintf(mem_ctx, "%s.%s", name,
					    type->fields.structure[i].name);
	 set_uniform_initializer(mem_ctx, prog, field_name,
				 field_type, field_constant);
	 field_constant = (ir_constant *)field_constant->next;
      }
      return;
   } else if (type->is_array() && type->fields.array->is_record()) {
      const glsl_type *const element_type = type->fields.array;

      for (unsigned int i = 0; i < type->length; i++) {
	 const char *element_name = ralloc_asprintf(mem_ctx, "%s[%d]", name, i);

	 set_uniform_initializer(mem_ctx, prog, element_name,
				 element_type, val->array_elements[i]);
      }
      return;
   }

   struct gl_uniform_storage *const storage =
      get_storage(prog->UniformStorage,
		  prog->NumUserUniformStorage,
		  name);
   if (storage == NULL) {
      assert(storage != NULL);
      return;
   }

   if (val->type->is_array()) {
      const enum glsl_base_type base_type =
	 val->array_elements[0]->type->base_type;
      const unsigned int elements = val->array_elements[0]->type->components();
      unsigned int idx = 0;

      assert(val->type->length >= storage->array_elements);
      for (unsigned int i = 0; i < storage->array_elements; i++) {
	 copy_constant_to_storage(& storage->storage[idx],
				  val->array_elements[i],
				  base_type,
				  elements);

	 idx += elements;
      }
   } else {
      copy_constant_to_storage(storage->storage,
			       val,
			       val->type->base_type,
			       val->type->components());

      if (storage->type->is_sampler()) {
         for (int sh = 0; sh < MESA_SHADER_STAGES; sh++) {
            gl_shader *shader = prog->_LinkedShaders[sh];

            if (shader && storage->sampler[sh].active) {
               unsigned index = storage->sampler[sh].index;

               shader->SamplerUnits[index] = storage->storage[0].i;
            }
         }
      }
   }

   storage->initialized = true;
}
}

void
link_set_uniform_initializers(struct gl_shader_program *prog)
{
   void *mem_ctx = NULL;

   for (unsigned int i = 0; i < MESA_SHADER_STAGES; i++) {
      struct gl_shader *shader = prog->_LinkedShaders[i];

      if (shader == NULL)
	 continue;

      foreach_list(node, shader->ir) {
	 ir_variable *const var = ((ir_instruction *) node)->as_variable();

	 if (!var || var->data.mode != ir_var_uniform)
	    continue;

	 if (!mem_ctx)
	    mem_ctx = ralloc_context(NULL);

         if (var->data.explicit_binding) {
            linker::set_uniform_binding(mem_ctx, prog, var->name,
                                        var->type, var->data.binding);
         } else if (var->constant_value) {
            linker::set_uniform_initializer(mem_ctx, prog, var->name,
                                            var->type, var->constant_value);
         }
      }
   }

   ralloc_free(mem_ctx);
}
<|endoftext|>