<commit_before>//===- IdentifierResolver.cpp - Lexical Scope Name lookup -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the IdentifierResolver class, which is used for lexical
// scoped lookup, based on identifier.
//
//===----------------------------------------------------------------------===//

#include "IdentifierResolver.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/AST/Decl.h"
#include "clang/Parse/Scope.h"
#include <list>
#include <vector>

using namespace clang;

namespace {

class IdDeclInfo;

/// Identifier's FETokenInfo contains a Decl pointer if lower bit == 0.
static inline bool isDeclPtr(void *Ptr) {
  return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
}

/// Identifier's FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
  return reinterpret_cast<IdDeclInfo*>(
                  reinterpret_cast<uintptr_t>(Ptr) & ~0x1
                                                          );
}

/// IdDeclInfo - Keeps track of information about decls associated to a
/// particular identifier. IdDeclInfos are lazily constructed and assigned
/// to an identifier the first time a decl with that identifier is shadowed
/// in some scope.
class IdDeclInfo {
  typedef llvm::SmallVector<NamedDecl *, 2> ShadowedTy;
  ShadowedTy ShadowedDecls;

public:
  typedef ShadowedTy::iterator ShadowedIter;

  inline ShadowedIter shadowed_begin() { return ShadowedDecls.begin(); }
  inline ShadowedIter shadowed_end() { return ShadowedDecls.end(); }

  /// Add a decl in the scope chain.
  void PushShadowed(NamedDecl *D) {
    assert(D && "Decl null");
    ShadowedDecls.push_back(D);
  }

  /// Add the decl at the top of scope chain.
  void PushGlobalShadowed(NamedDecl *D) {
    assert(D && "Decl null");
    ShadowedDecls.insert(ShadowedDecls.begin(), D);
  }

  /// RemoveShadowed - Remove the decl from the scope chain.
  /// The decl must already be part of the decl chain.
  void RemoveShadowed(NamedDecl *D);
};

/// IdDeclInfoMap - Associates IdDeclInfos with Identifiers.
/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
/// individual IdDeclInfo to heap.
class IdDeclInfoMap {
  static const unsigned int VECTOR_SIZE = 512;
  // Holds vectors of IdDeclInfos that serve as 'pools'.
  // New vectors are added when the current one is full.
  std::list< std::vector<IdDeclInfo> > IDIVecs;
  unsigned int CurIndex;

public:
  IdDeclInfoMap() : CurIndex(VECTOR_SIZE) {}

  /// Returns the IdDeclInfo associated to the IdentifierInfo.
  /// It creates a new IdDeclInfo if one was not created before for this id.
  IdDeclInfo &operator[](IdentifierInfo *II);
};

} // end anonymous namespace

IdentifierResolver::IdentifierResolver() : IdDeclInfos(new IdDeclInfoMap) {}
IdentifierResolver::~IdentifierResolver() {
  delete static_cast<IdDeclInfoMap*>(IdDeclInfos);
}

/// AddDecl - Link the decl to its shadowed decl chain.
void IdentifierResolver::AddDecl(NamedDecl *D, Scope *S) {
  assert(D && S && "null param passed");
  IdentifierInfo *II = D->getIdentifier();
  void *Ptr = II->getFETokenInfo<void>();

  if (!Ptr) {
    II->setFETokenInfo(D);
    return;
  }

  IdDeclInfo *IDI;

  if (isDeclPtr(Ptr)) {
    II->setFETokenInfo(NULL);
    IdDeclInfoMap &Map = *static_cast<IdDeclInfoMap*>(IdDeclInfos);
    IDI = &Map[II];
    IDI->PushShadowed(static_cast<NamedDecl*>(Ptr));
  } else
    IDI = toIdDeclInfo(Ptr);

  // C++ [basic.scope]p4:
  //   -- exactly one declaration shall declare a class name or
  //   enumeration name that is not a typedef name and the other
  //   declarations shall all refer to the same object or
  //   enumerator, or all refer to functions and function templates;
  //   in this case the class name or enumeration name is hidden.
  if (isa<TagDecl>(D)) {
    // We are pushing the name of a tag (enum or class).
    IdDeclInfo::ShadowedIter TopIter = IDI->shadowed_end() - 1;
    if (S->isDeclScope(*TopIter)) {
      // There is already a declaration with the same name in the same
      // scope. It must be found before we find the new declaration,
      // so swap the order on the shadowed declaration stack.
      NamedDecl *Temp = *TopIter;
      *TopIter = D;
      D = Temp;
    }
  }

  IDI->PushShadowed(D);
}

/// AddGlobalDecl - Link the decl at the top of the shadowed decl chain.
void IdentifierResolver::AddGlobalDecl(NamedDecl *D) {
  assert(D && "null param passed");
  IdentifierInfo *II = D->getIdentifier();
  void *Ptr = II->getFETokenInfo<void>();

  if (!Ptr) {
    II->setFETokenInfo(D);
    return;
  }

  IdDeclInfo *IDI;

  if (isDeclPtr(Ptr)) {
    II->setFETokenInfo(NULL);
    IdDeclInfoMap &Map = *static_cast<IdDeclInfoMap*>(IdDeclInfos);
    IDI = &Map[II];
    IDI->PushShadowed(static_cast<NamedDecl*>(Ptr));
  } else
    IDI = toIdDeclInfo(Ptr);

  IDI->PushGlobalShadowed(D);
}

/// RemoveDecl - Unlink the decl from its shadowed decl chain.
/// The decl must already be part of the decl chain.
void IdentifierResolver::RemoveDecl(NamedDecl *D) {
  assert(D && "null param passed");
  IdentifierInfo *II = D->getIdentifier();
  void *Ptr = II->getFETokenInfo<void>();

  assert(Ptr && "Didn't find this decl on its identifier's chain!");

  if (isDeclPtr(Ptr)) {
    assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
    II->setFETokenInfo(NULL);
    return;
  }

  return toIdDeclInfo(Ptr)->RemoveShadowed(D);
}

/// Lookup - Find the non-shadowed decl that belongs to a particular
/// Decl::IdentifierNamespace.
NamedDecl *IdentifierResolver::Lookup(const IdentifierInfo *II, unsigned NS) {
  assert(II && "null param passed");
  void *Ptr = II->getFETokenInfo<void>();

  if (!Ptr) return NULL;

  if (isDeclPtr(Ptr)) {
    NamedDecl *D = static_cast<NamedDecl*>(Ptr);
    return (D->getIdentifierNamespace() & NS) ? D : NULL;
  }

  IdDeclInfo *IDI = toIdDeclInfo(Ptr);

  // ShadowedDecls are ordered from most shadowed to less shadowed.
  // So we do a reverse iteration from end to begin.
  for (IdDeclInfo::ShadowedIter SI = IDI->shadowed_end();
       SI != IDI->shadowed_begin(); --SI) {
    NamedDecl *D = *(SI-1);
    if (D->getIdentifierNamespace() & NS)
      return D;
  }

  // we didn't find the decl.
  return NULL;
}

/// RemoveShadowed - Remove the decl from the scope chain.
/// The decl must already be part of the decl chain.
void IdDeclInfo::RemoveShadowed(NamedDecl *D) {
  assert(D && "null decl passed");
  assert(!ShadowedDecls.empty() &&
         "Didn't find this decl on its identifier's chain!");

  // common case
  if (D == ShadowedDecls.back()) {
    ShadowedDecls.pop_back();
    return;
  }

  for (ShadowedIter SI = ShadowedDecls.end()-1;
       SI != ShadowedDecls.begin(); --SI) {
    if (*(SI-1) == D) {
      ShadowedDecls.erase(SI-1);
      return;
    }
  }

  assert(false && "Didn't find this decl on its identifier's chain!");
}

/// Returns the IdDeclInfo associated to the IdentifierInfo.
/// It creates a new IdDeclInfo if one was not created before for this id.
IdDeclInfo &IdDeclInfoMap::operator[](IdentifierInfo *II) {
  assert (II && "null IdentifierInfo passed");
  void *Ptr = II->getFETokenInfo<void>();

  if (Ptr) {
    assert(!isDeclPtr(Ptr) && "didn't clear decl for FEToken");
    return *toIdDeclInfo(Ptr);
  }

  if (CurIndex == VECTOR_SIZE) {
    // Add a IdDeclInfo vector 'pool'
    IDIVecs.push_back(std::vector<IdDeclInfo>());
    // Fill the vector
    IDIVecs.back().resize(VECTOR_SIZE);
    CurIndex = 0;
  }
  IdDeclInfo *IDI = &IDIVecs.back()[CurIndex];
  II->setFETokenInfo(reinterpret_cast<void*>(
                              reinterpret_cast<uintptr_t>(IDI) | 0x1)
                                                                     );
  ++CurIndex;
  return *IDI;
}
<commit_msg>Argiris Kirtzidis's fix for handling empty IdDeclInfo's in IdentifierResolver::AddDecl<commit_after>//===- IdentifierResolver.cpp - Lexical Scope Name lookup -------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the IdentifierResolver class, which is used for lexical
// scoped lookup, based on identifier.
//
//===----------------------------------------------------------------------===//

#include "IdentifierResolver.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/AST/Decl.h"
#include "clang/Parse/Scope.h"
#include <list>
#include <vector>

using namespace clang;

namespace {

class IdDeclInfo;

/// Identifier's FETokenInfo contains a Decl pointer if lower bit == 0.
static inline bool isDeclPtr(void *Ptr) {
  return (reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 0;
}

/// Identifier's FETokenInfo contains a IdDeclInfo pointer if lower bit == 1.
static inline IdDeclInfo *toIdDeclInfo(void *Ptr) {
  return reinterpret_cast<IdDeclInfo*>(
                  reinterpret_cast<uintptr_t>(Ptr) & ~0x1
                                                          );
}

/// IdDeclInfo - Keeps track of information about decls associated to a
/// particular identifier. IdDeclInfos are lazily constructed and assigned
/// to an identifier the first time a decl with that identifier is shadowed
/// in some scope.
class IdDeclInfo {
  typedef llvm::SmallVector<NamedDecl *, 2> ShadowedTy;
  ShadowedTy ShadowedDecls;

public:
  typedef ShadowedTy::iterator ShadowedIter;

  inline ShadowedIter shadowed_begin() { return ShadowedDecls.begin(); }
  inline ShadowedIter shadowed_end() { return ShadowedDecls.end(); }

  /// Add a decl in the scope chain.
  void PushShadowed(NamedDecl *D) {
    assert(D && "Decl null");
    ShadowedDecls.push_back(D);
  }

  /// Add the decl at the top of scope chain.
  void PushGlobalShadowed(NamedDecl *D) {
    assert(D && "Decl null");
    ShadowedDecls.insert(ShadowedDecls.begin(), D);
  }

  /// RemoveShadowed - Remove the decl from the scope chain.
  /// The decl must already be part of the decl chain.
  void RemoveShadowed(NamedDecl *D);
};

/// IdDeclInfoMap - Associates IdDeclInfos with Identifiers.
/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
/// individual IdDeclInfo to heap.
class IdDeclInfoMap {
  static const unsigned int VECTOR_SIZE = 512;
  // Holds vectors of IdDeclInfos that serve as 'pools'.
  // New vectors are added when the current one is full.
  std::list< std::vector<IdDeclInfo> > IDIVecs;
  unsigned int CurIndex;

public:
  IdDeclInfoMap() : CurIndex(VECTOR_SIZE) {}

  /// Returns the IdDeclInfo associated to the IdentifierInfo.
  /// It creates a new IdDeclInfo if one was not created before for this id.
  IdDeclInfo &operator[](IdentifierInfo *II);
};

} // end anonymous namespace

IdentifierResolver::IdentifierResolver() : IdDeclInfos(new IdDeclInfoMap) {}
IdentifierResolver::~IdentifierResolver() {
  delete static_cast<IdDeclInfoMap*>(IdDeclInfos);
}

/// AddDecl - Link the decl to its shadowed decl chain.
void IdentifierResolver::AddDecl(NamedDecl *D, Scope *S) {
  assert(D && S && "null param passed");
  IdentifierInfo *II = D->getIdentifier();
  void *Ptr = II->getFETokenInfo<void>();

  if (!Ptr) {
    II->setFETokenInfo(D);
    return;
  }

  IdDeclInfo *IDI;

  if (isDeclPtr(Ptr)) {
    II->setFETokenInfo(NULL);
    IdDeclInfoMap &Map = *static_cast<IdDeclInfoMap*>(IdDeclInfos);
    IDI = &Map[II];
    IDI->PushShadowed(static_cast<NamedDecl*>(Ptr));
  } else
    IDI = toIdDeclInfo(Ptr);

  // C++ [basic.scope]p4:
  //   -- exactly one declaration shall declare a class name or
  //   enumeration name that is not a typedef name and the other
  //   declarations shall all refer to the same object or
  //   enumerator, or all refer to functions and function templates;
  //   in this case the class name or enumeration name is hidden.
  if (isa<TagDecl>(D) && IDI->shadowed_end() != IDI->shadowed_begin()) {
    // We are pushing the name of a tag (enum or class).
    IdDeclInfo::ShadowedIter TopIter = IDI->shadowed_end() - 1;
    if (S->isDeclScope(*TopIter)) {
      // There is already a declaration with the same name in the same
      // scope. It must be found before we find the new declaration,
      // so swap the order on the shadowed declaration stack.
      NamedDecl *Temp = *TopIter;
      *TopIter = D;
      D = Temp;
    }
  }

  IDI->PushShadowed(D);
}

/// AddGlobalDecl - Link the decl at the top of the shadowed decl chain.
void IdentifierResolver::AddGlobalDecl(NamedDecl *D) {
  assert(D && "null param passed");
  IdentifierInfo *II = D->getIdentifier();
  void *Ptr = II->getFETokenInfo<void>();

  if (!Ptr) {
    II->setFETokenInfo(D);
    return;
  }

  IdDeclInfo *IDI;

  if (isDeclPtr(Ptr)) {
    II->setFETokenInfo(NULL);
    IdDeclInfoMap &Map = *static_cast<IdDeclInfoMap*>(IdDeclInfos);
    IDI = &Map[II];
    IDI->PushShadowed(static_cast<NamedDecl*>(Ptr));
  } else
    IDI = toIdDeclInfo(Ptr);

  IDI->PushGlobalShadowed(D);
}

/// RemoveDecl - Unlink the decl from its shadowed decl chain.
/// The decl must already be part of the decl chain.
void IdentifierResolver::RemoveDecl(NamedDecl *D) {
  assert(D && "null param passed");
  IdentifierInfo *II = D->getIdentifier();
  void *Ptr = II->getFETokenInfo<void>();

  assert(Ptr && "Didn't find this decl on its identifier's chain!");

  if (isDeclPtr(Ptr)) {
    assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
    II->setFETokenInfo(NULL);
    return;
  }

  return toIdDeclInfo(Ptr)->RemoveShadowed(D);
}

/// Lookup - Find the non-shadowed decl that belongs to a particular
/// Decl::IdentifierNamespace.
NamedDecl *IdentifierResolver::Lookup(const IdentifierInfo *II, unsigned NS) {
  assert(II && "null param passed");
  void *Ptr = II->getFETokenInfo<void>();

  if (!Ptr) return NULL;

  if (isDeclPtr(Ptr)) {
    NamedDecl *D = static_cast<NamedDecl*>(Ptr);
    return (D->getIdentifierNamespace() & NS) ? D : NULL;
  }

  IdDeclInfo *IDI = toIdDeclInfo(Ptr);

  // ShadowedDecls are ordered from most shadowed to less shadowed.
  // So we do a reverse iteration from end to begin.
  for (IdDeclInfo::ShadowedIter SI = IDI->shadowed_end();
       SI != IDI->shadowed_begin(); --SI) {
    NamedDecl *D = *(SI-1);
    if (D->getIdentifierNamespace() & NS)
      return D;
  }

  // we didn't find the decl.
  return NULL;
}

/// RemoveShadowed - Remove the decl from the scope chain.
/// The decl must already be part of the decl chain.
void IdDeclInfo::RemoveShadowed(NamedDecl *D) {
  assert(D && "null decl passed");
  assert(!ShadowedDecls.empty() &&
         "Didn't find this decl on its identifier's chain!");

  // common case
  if (D == ShadowedDecls.back()) {
    ShadowedDecls.pop_back();
    return;
  }

  for (ShadowedIter SI = ShadowedDecls.end()-1;
       SI != ShadowedDecls.begin(); --SI) {
    if (*(SI-1) == D) {
      ShadowedDecls.erase(SI-1);
      return;
    }
  }

  assert(false && "Didn't find this decl on its identifier's chain!");
}

/// Returns the IdDeclInfo associated to the IdentifierInfo.
/// It creates a new IdDeclInfo if one was not created before for this id.
IdDeclInfo &IdDeclInfoMap::operator[](IdentifierInfo *II) {
  assert (II && "null IdentifierInfo passed");
  void *Ptr = II->getFETokenInfo<void>();

  if (Ptr) {
    assert(!isDeclPtr(Ptr) && "didn't clear decl for FEToken");
    return *toIdDeclInfo(Ptr);
  }

  if (CurIndex == VECTOR_SIZE) {
    // Add a IdDeclInfo vector 'pool'
    IDIVecs.push_back(std::vector<IdDeclInfo>());
    // Fill the vector
    IDIVecs.back().resize(VECTOR_SIZE);
    CurIndex = 0;
  }
  IdDeclInfo *IDI = &IDIVecs.back()[CurIndex];
  II->setFETokenInfo(reinterpret_cast<void*>(
                              reinterpret_cast<uintptr_t>(IDI) | 0x1)
                                                                     );
  ++CurIndex;
  return *IDI;
}
<|endoftext|>


<commit_before><commit_msg>remove useless comment lines<commit_after><|endoftext|>


<commit_before>#include "fn++.hpp"
#include <stdio.h>
#include <vector>
#include <map>
#include <utility>
#include <gtest/gtest.h>

using namespace fn;

TEST(A_range,
goes_from_zero_to_the_upper_limit_not_including_the_limit)
{
    std::vector<int> expected{0,1,2,3,4,5,6,7,8,9};
    auto it = range(10);
    auto count = 0;
    for(auto i: it){
        EXPECT_EQ(expected[count],i);
        count++;
    }
    EXPECT_EQ(10,count);
}

TEST(The_map_function,
applies_a_functor_to_all_elements_of_an_iterator)
{
    std::vector<int> expected{0,2,4,6,8,10,12,14,16,18};
    auto twice = [](int x){return 2*x;};
    auto count = 0;
    for(auto i: map(twice,range(10))){
        EXPECT_EQ(expected[count],i) << i;
        count++;
    }
    EXPECT_EQ(10,count);
}

TEST(The_filter_function,
returns_an_iterator_for_all_elements_a_functor_is_true)
{
    std::vector<int> expected{0,2,4,6,8};
    auto even = [](int x){return x%2 == 0;};
    auto count = 0;
    for(auto i: filter(even,range(10))){
        EXPECT_EQ(expected[count],i) << i;
        count++;
    }
    EXPECT_EQ(5,count);
}

TEST(The_filter_function,
defaults_to_a_functor_thats_tests_the_truth_value_of_the_elements_themselves)
{
    std::vector<int> expected{1,1,1,1,1};
    auto even = [](int x){return x%2 == 0;};
    auto count = 0;
    for(auto i: filter(map(even,range(10)))){
        EXPECT_EQ(expected[count],i) << i;
        count++;
    }
    EXPECT_EQ(5,count);
}

TEST(The_map_function,
can_take_the_result_of_the_filter_function_as_input)
{
    std::vector<int> expected{2,4,6,8,10,12,14,16,18};
    auto twice = [](int x){return 2*x;};
    auto count = 0;
    for(auto i: map(twice,filter(range(10)))){
        EXPECT_EQ(expected[count],i) << i;
        count++;
    }
    EXPECT_EQ(9,count);
}

TEST(The_filter_function,
can_take_an_std_vector_as_input)
{
    std::vector<int> input{23,6,0,8,0,12,4,10,0};
    std::vector<int> expected{11,3,4,6,2,5};
    auto half = [](int x){return x/2;};
    auto count = 0;
    for(auto i: map(half,filter(input))){
        EXPECT_EQ(expected[count],i) << i;
        count++;
    }
    EXPECT_EQ(6,count);
}

template<typename G,typename FN>
void iterate(G const& g, FN const& fn)
{
    for(auto const& x: g){ fn(x); }
}

TEST(The_filter_function,
can_take_an_std_vector_as_input_and_then_be_passed_into_map)
{
    std::vector<int> input{23,6,0,8,0,12,4,10,0};
    auto half = [](int x){return x/2;};

    std::vector<int> v;
    iterate(map(half,filter(input)),[&](int x){
        v.push_back(x);
    });
    EXPECT_EQ(6,v.size());
}

TEST(The_zip_function,
allows_parallel_iteration_over_two_iterators)
{
    std::vector<int> input{23,6,0,8,0,12,4,10,0};

    int count = 0;
    for(auto const& item : zip(input,range(input.size()*2))){
        EXPECT_EQ(input[item.second],item.first);
        count++;
    }
    EXPECT_EQ(count,input.size());

    count = 0;
    for(auto const& item : zip(range(input.size()*2),input)){
        EXPECT_EQ(input[item.first],item.second);
        count++;
    }
    EXPECT_EQ(count,input.size());
}

TEST(The_enumerate_function,
allows_iteration_with_an_index)
{
    std::vector<int> input{23,6,0,8,0,12,4,10,0};

    int count = 0;
    for(auto const& i : enumerate(input)){
        EXPECT_EQ(input[i.nr],i.item);
        count++;
    }
    EXPECT_EQ(count,input.size());
}

TEST(The_reduce_function,
does_reduction)
{
    std::vector<int> input{23,6,0,8,0,12,4,10,0};

    auto sum = reduce(input,0,[](int a, int b){ return a+b; });
    EXPECT_EQ(63,sum);
}

optional<int> twice_in_range(int from, int to, int i)
{
    if(i>to){
        return {};
    }
    if(i<from){
        return {};
    }
    return {i*2};
}

TEST(An_optional_value,
can_be_defaulted_to_a_constant)
{
    std::vector<int> in{1,4,6,2,10,55};
    std::vector<int> expected{-1,8,12,-1,-1,-1};
    for(size_t i=0;i<in.size();i++){
        auto r = twice_in_range(3,7,in[i]) or -1;
        EXPECT_EQ(expected[i],r);
    }
}

TEST(An_optional_value,
can_change_if_it_is_a_reference)
{
    int i = 5;
    int j = 7;
    optional<int&> o = i;

    auto& r = o or j;

    EXPECT_EQ(5,r);
    r = 6;
    EXPECT_EQ(6,i);

    with_(o,{ o = 9; });

    EXPECT_EQ(9,i);
}

TEST(An_optional_value,
keeps_beeing_optional_if_only_the_exists_case_is_handled)
{
    std::vector<int> in{1,4,6,2,10,55};
    std::vector<int> expected{-1,8,12,-1,-1,-1};
    std::vector<int> expected2{0,8*3,12*3,0,0,0};
    for(size_t i=0;i<in.size();i++){
        int out = 0;
        optional<int> const& result = twice_in_range(3,7,in[i]);
        optional<int> const& still_optional = result([&](int v){out=v*3;});
        auto r = still_optional or -1;
        EXPECT_EQ(expected[i],r);
        EXPECT_EQ(expected2[i],out);
    }
}

TEST(An_optional_value,
can_be_used_by_providing_handlers_for_both_cases)
{
    std::vector<int> in{1,4,6,2,10,55};
    std::vector<int> expected{-1,16,24,-1,-1,-1};
    for(size_t i=0;i<in.size();i++){
        auto result = twice_in_range(3,7,in[i]);
        typedef decltype(result)::Type T;
        auto r = result(
            [](T v){return 2*v;},
            [](){return -1;}
        );
        EXPECT_EQ(expected[i],r);
    }
}

TEST(An_optional_value,
can_be_tested_if_it_has_a_value)
{
    auto t = optional<int>{1};
    EXPECT_TRUE(t.has_value);

    auto t0 = optional<int>{0};
    EXPECT_TRUE(t0.has_value);

    auto f = optional<int>{};
    EXPECT_FALSE(f.has_value);
}

void take(optional<int> const& i)
{
    EXPECT_EQ(12,i or 0);
}

TEST(An_optional_value,
can_be_passed_into_a_function)
{
    auto r = twice_in_range(3,9,6);
    take(r);
    EXPECT_EQ(12,r or 0);
}

optional<int> getnr(int nr)
{
    if(nr % 2){
        return {};
    }
    else{
        return nr;
    }
}

TEST(An_optional_value,
can_be_accessed_easier_using_macros)
{
    for(auto const i: range(5)){
        int out;
        auto nr = getnr(i);

        out = -2;
        with_(nr,{
            out = nr;
        });
        if(!(i%2)){ EXPECT_EQ(i,out); }
        else{ EXPECT_EQ(-2,out); }

        out = -2;
        without_(nr,{
            out = -1;
        });
        if(!(i%2)){ EXPECT_EQ(-2,out); }
        else{ EXPECT_EQ(-1,out); }

        out = -2;
        use_(getnr(i))_as(nr,{
            out = nr;
        });
        if(!(i%2)){ EXPECT_EQ(i,out) << i; }
        else{ EXPECT_EQ(-2,out) << i; }

        out = -2;
        use_(getnr(i))_as_(nr,{
            out = nr;
        },{
            out = -1;
        });
        if(!(i%2)){ EXPECT_EQ(i,out) << i; }
        else{ EXPECT_EQ(-1,out) << i; }
    }
}

TEST(The_macros,
work_also_with_references_to_optionals)
{
    for(auto const i: range(5)){
        int out;
        auto x = getnr(i);
        auto const& nr = x;

        out = -2;
        with_(nr,{
            out = nr;
        });
        if(!(i%2)){ EXPECT_EQ(i,out); }
        else{ EXPECT_EQ(-2,out); }

        out = -2;
        without_(nr,{
            out = -1;
        });
        if(!(i%2)){ EXPECT_EQ(-2,out); }
        else{ EXPECT_EQ(-1,out); }

        out = -2;
        use_(nr)_as(nr,{
            out = nr;
        });
        if(!(i%2)){ EXPECT_EQ(i,out) << i; }
        else{ EXPECT_EQ(-2,out) << i; }

        out = -2;
        use_(nr)_as_(nr,{
            out = nr;
        },{
            out = -1;
        });
        if(!(i%2)){ EXPECT_EQ(i,out) << i; }
        else{ EXPECT_EQ(-1,out) << i; }
    }
}

TEST(as_range,makes_begin_end_pairs_compatible_with_range_based_for)
{
    std::vector<int> in{1,4,6,2,10,55};
    size_t n = 0;

    for(auto const i: as_range(in.begin(),in.end())){
        EXPECT_EQ(in[n],i);
        n++;
    }

    EXPECT_EQ(in.size(),n);
}

TEST(The_element_function,
accesses_containers_with_range_checking_returning_an_optional)
{
    std::vector<int> v{11,3,4,6,2,5};
    int n = 0;

    {
        auto t = element(3).of(v);
        EXPECT_TRUE(t.has_value);
        EXPECT_EQ(6, t or n);
    }

    {
        auto t = element(30).of(v);
        EXPECT_FALSE(t.has_value);
        EXPECT_EQ(0, t or n);
    }

    {
        auto second = element(1);
        auto t = second.of(v);
        EXPECT_TRUE(t.has_value);
        EXPECT_EQ(3, t or n);
    }

    {
        auto t = element(-1).of(v);
        EXPECT_TRUE(t.has_value);
        EXPECT_EQ(5, t or n);
    }

    {
        EXPECT_EQ(6, v.at(3));
        use_(element(3).of(v))_as_(i,{
            i = 4;
        },{ ADD_FAILURE(); });
        EXPECT_EQ(4, v.at(3));
    }

    std::map<std::string,int> m = {{
        {"one",1},
        {"two",2},
    }};

    {
        auto o = element("one").in(m);
        EXPECT_TRUE(o.has_value);
        EXPECT_EQ(1, o or n);
    }

    {
        auto o = element("not").in(m);
        EXPECT_FALSE(o.has_value);
    }

    {
        auto two = element("two");
        auto o = two.in(m);
        EXPECT_TRUE(o.has_value);
        EXPECT_EQ(2, o or n);
    }
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>test element with empty containers<commit_after>#include "fn++.hpp"
#include <stdio.h>
#include <vector>
#include <map>
#include <utility>
#include <gtest/gtest.h>

using namespace fn;

TEST(A_range,
goes_from_zero_to_the_upper_limit_not_including_the_limit)
{
    std::vector<int> expected{0,1,2,3,4,5,6,7,8,9};
    auto it = range(10);
    auto count = 0;
    for(auto i: it){
        EXPECT_EQ(expected[count],i);
        count++;
    }
    EXPECT_EQ(10,count);
}

TEST(The_map_function,
applies_a_functor_to_all_elements_of_an_iterator)
{
    std::vector<int> expected{0,2,4,6,8,10,12,14,16,18};
    auto twice = [](int x){return 2*x;};
    auto count = 0;
    for(auto i: map(twice,range(10))){
        EXPECT_EQ(expected[count],i) << i;
        count++;
    }
    EXPECT_EQ(10,count);
}

TEST(The_filter_function,
returns_an_iterator_for_all_elements_a_functor_is_true)
{
    std::vector<int> expected{0,2,4,6,8};
    auto even = [](int x){return x%2 == 0;};
    auto count = 0;
    for(auto i: filter(even,range(10))){
        EXPECT_EQ(expected[count],i) << i;
        count++;
    }
    EXPECT_EQ(5,count);
}

TEST(The_filter_function,
defaults_to_a_functor_thats_tests_the_truth_value_of_the_elements_themselves)
{
    std::vector<int> expected{1,1,1,1,1};
    auto even = [](int x){return x%2 == 0;};
    auto count = 0;
    for(auto i: filter(map(even,range(10)))){
        EXPECT_EQ(expected[count],i) << i;
        count++;
    }
    EXPECT_EQ(5,count);
}

TEST(The_map_function,
can_take_the_result_of_the_filter_function_as_input)
{
    std::vector<int> expected{2,4,6,8,10,12,14,16,18};
    auto twice = [](int x){return 2*x;};
    auto count = 0;
    for(auto i: map(twice,filter(range(10)))){
        EXPECT_EQ(expected[count],i) << i;
        count++;
    }
    EXPECT_EQ(9,count);
}

TEST(The_filter_function,
can_take_an_std_vector_as_input)
{
    std::vector<int> input{23,6,0,8,0,12,4,10,0};
    std::vector<int> expected{11,3,4,6,2,5};
    auto half = [](int x){return x/2;};
    auto count = 0;
    for(auto i: map(half,filter(input))){
        EXPECT_EQ(expected[count],i) << i;
        count++;
    }
    EXPECT_EQ(6,count);
}

template<typename G,typename FN>
void iterate(G const& g, FN const& fn)
{
    for(auto const& x: g){ fn(x); }
}

TEST(The_filter_function,
can_take_an_std_vector_as_input_and_then_be_passed_into_map)
{
    std::vector<int> input{23,6,0,8,0,12,4,10,0};
    auto half = [](int x){return x/2;};

    std::vector<int> v;
    iterate(map(half,filter(input)),[&](int x){
        v.push_back(x);
    });
    EXPECT_EQ(6,v.size());
}

TEST(The_zip_function,
allows_parallel_iteration_over_two_iterators)
{
    std::vector<int> input{23,6,0,8,0,12,4,10,0};

    int count = 0;
    for(auto const& item : zip(input,range(input.size()*2))){
        EXPECT_EQ(input[item.second],item.first);
        count++;
    }
    EXPECT_EQ(count,input.size());

    count = 0;
    for(auto const& item : zip(range(input.size()*2),input)){
        EXPECT_EQ(input[item.first],item.second);
        count++;
    }
    EXPECT_EQ(count,input.size());
}

TEST(The_enumerate_function,
allows_iteration_with_an_index)
{
    std::vector<int> input{23,6,0,8,0,12,4,10,0};

    int count = 0;
    for(auto const& i : enumerate(input)){
        EXPECT_EQ(input[i.nr],i.item);
        count++;
    }
    EXPECT_EQ(count,input.size());
}

TEST(The_reduce_function,
does_reduction)
{
    std::vector<int> input{23,6,0,8,0,12,4,10,0};

    auto sum = reduce(input,0,[](int a, int b){ return a+b; });
    EXPECT_EQ(63,sum);
}

optional<int> twice_in_range(int from, int to, int i)
{
    if(i>to){
        return {};
    }
    if(i<from){
        return {};
    }
    return {i*2};
}

TEST(An_optional_value,
can_be_defaulted_to_a_constant)
{
    std::vector<int> in{1,4,6,2,10,55};
    std::vector<int> expected{-1,8,12,-1,-1,-1};
    for(size_t i=0;i<in.size();i++){
        auto r = twice_in_range(3,7,in[i]) or -1;
        EXPECT_EQ(expected[i],r);
    }
}

TEST(An_optional_value,
can_change_if_it_is_a_reference)
{
    int i = 5;
    int j = 7;
    optional<int&> o = i;

    auto& r = o or j;

    EXPECT_EQ(5,r);
    r = 6;
    EXPECT_EQ(6,i);

    with_(o,{ o = 9; });

    EXPECT_EQ(9,i);
}

TEST(An_optional_value,
keeps_beeing_optional_if_only_the_exists_case_is_handled)
{
    std::vector<int> in{1,4,6,2,10,55};
    std::vector<int> expected{-1,8,12,-1,-1,-1};
    std::vector<int> expected2{0,8*3,12*3,0,0,0};
    for(size_t i=0;i<in.size();i++){
        int out = 0;
        optional<int> const& result = twice_in_range(3,7,in[i]);
        optional<int> const& still_optional = result([&](int v){out=v*3;});
        auto r = still_optional or -1;
        EXPECT_EQ(expected[i],r);
        EXPECT_EQ(expected2[i],out);
    }
}

TEST(An_optional_value,
can_be_used_by_providing_handlers_for_both_cases)
{
    std::vector<int> in{1,4,6,2,10,55};
    std::vector<int> expected{-1,16,24,-1,-1,-1};
    for(size_t i=0;i<in.size();i++){
        auto result = twice_in_range(3,7,in[i]);
        typedef decltype(result)::Type T;
        auto r = result(
            [](T v){return 2*v;},
            [](){return -1;}
        );
        EXPECT_EQ(expected[i],r);
    }
}

TEST(An_optional_value,
can_be_tested_if_it_has_a_value)
{
    auto t = optional<int>{1};
    EXPECT_TRUE(t.has_value);

    auto t0 = optional<int>{0};
    EXPECT_TRUE(t0.has_value);

    auto f = optional<int>{};
    EXPECT_FALSE(f.has_value);
}

void take(optional<int> const& i)
{
    EXPECT_EQ(12,i or 0);
}

TEST(An_optional_value,
can_be_passed_into_a_function)
{
    auto r = twice_in_range(3,9,6);
    take(r);
    EXPECT_EQ(12,r or 0);
}

optional<int> getnr(int nr)
{
    if(nr % 2){
        return {};
    }
    else{
        return nr;
    }
}

TEST(An_optional_value,
can_be_accessed_easier_using_macros)
{
    for(auto const i: range(5)){
        int out;
        auto nr = getnr(i);

        out = -2;
        with_(nr,{
            out = nr;
        });
        if(!(i%2)){ EXPECT_EQ(i,out); }
        else{ EXPECT_EQ(-2,out); }

        out = -2;
        without_(nr,{
            out = -1;
        });
        if(!(i%2)){ EXPECT_EQ(-2,out); }
        else{ EXPECT_EQ(-1,out); }

        out = -2;
        use_(getnr(i))_as(nr,{
            out = nr;
        });
        if(!(i%2)){ EXPECT_EQ(i,out) << i; }
        else{ EXPECT_EQ(-2,out) << i; }

        out = -2;
        use_(getnr(i))_as_(nr,{
            out = nr;
        },{
            out = -1;
        });
        if(!(i%2)){ EXPECT_EQ(i,out) << i; }
        else{ EXPECT_EQ(-1,out) << i; }
    }
}

TEST(The_macros,
work_also_with_references_to_optionals)
{
    for(auto const i: range(5)){
        int out;
        auto x = getnr(i);
        auto const& nr = x;

        out = -2;
        with_(nr,{
            out = nr;
        });
        if(!(i%2)){ EXPECT_EQ(i,out); }
        else{ EXPECT_EQ(-2,out); }

        out = -2;
        without_(nr,{
            out = -1;
        });
        if(!(i%2)){ EXPECT_EQ(-2,out); }
        else{ EXPECT_EQ(-1,out); }

        out = -2;
        use_(nr)_as(nr,{
            out = nr;
        });
        if(!(i%2)){ EXPECT_EQ(i,out) << i; }
        else{ EXPECT_EQ(-2,out) << i; }

        out = -2;
        use_(nr)_as_(nr,{
            out = nr;
        },{
            out = -1;
        });
        if(!(i%2)){ EXPECT_EQ(i,out) << i; }
        else{ EXPECT_EQ(-1,out) << i; }
    }
}

TEST(as_range,makes_begin_end_pairs_compatible_with_range_based_for)
{
    std::vector<int> in{1,4,6,2,10,55};
    size_t n = 0;

    for(auto const i: as_range(in.begin(),in.end())){
        EXPECT_EQ(in[n],i);
        n++;
    }

    EXPECT_EQ(in.size(),n);
}

TEST(The_element_function,
accesses_containers_with_range_checking_returning_an_optional)
{
    std::vector<int> v{11,3,4,6,2,5};
    int n = 0;

    {
        auto t = element(3).of(v);
        EXPECT_TRUE(t.has_value);
        EXPECT_EQ(6, t or n);
    }

    {
        auto t = element(30).of(v);
        EXPECT_FALSE(t.has_value);
        EXPECT_EQ(0, t or n);
    }

    {
        auto second = element(1);
        auto t = second.of(v);
        EXPECT_TRUE(t.has_value);
        EXPECT_EQ(3, t or n);
    }

    {
        auto t = element(-1).of(v);
        EXPECT_TRUE(t.has_value);
        EXPECT_EQ(5, t or n);
    }

    {
        std::vector<int> w;
        EXPECT_FALSE(element(-1).of(w).has_value);
        EXPECT_FALSE(element(0).of(w).has_value);
    }

    {
        EXPECT_EQ(6, v.at(3));
        use_(element(3).of(v))_as_(i,{
            i = 4;
        },{ ADD_FAILURE(); });
        EXPECT_EQ(4, v.at(3));
    }

    std::map<std::string,int> m = {{
        {"one",1},
        {"two",2},
    }};

    {
        auto o = element("one").in(m);
        EXPECT_TRUE(o.has_value);
        EXPECT_EQ(1, o or n);
    }

    {
        auto o = element("not").in(m);
        EXPECT_FALSE(o.has_value);
    }

    {
        auto two = element("two");
        auto o = two.in(m);
        EXPECT_TRUE(o.has_value);
        EXPECT_EQ(2, o or n);
    }
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/**
 * @file ct2ctml.cpp
 *
 * $Author$
 * $Revision$
 * $Date$
 */

// Copyright 2001  California Institute of Technology

// turn off warnings under Windows
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif

#include "ct_defs.h"
#include "ctexceptions.h"
#include <fstream>
#include <string>
#include <stdlib.h>
#include <time.h>
#include "ctml.h"

//#define DEBUG_PATHS

using namespace Cantera;

namespace ctml {

    // return the full path to the Python interpreter.  Use
    // environment variable PYTHON_CMD if it is set, otherwise use the
    // definition PYTHON_EXE if it is defined. Failing that, return
    // the string 'python'.
    static string pypath() {
        string s = "python";
        const char* py = getenv("PYTHON_CMD");
        if (py) {
            string sp = stripws(string(py));
            if (sp.size() > 0) s = sp;
        }
        //#ifdef PYTHON_EXE
            //else {
        //string se = stripws(string(PYTHON_EXE));
        //  if (se.size() > 0) s = se;
        //}
        //#endif
        return s;
    }

    static bool checkPython() {
        time_t aclock;
        time( &aclock );
        int ia = static_cast<int>(aclock);
        string path = tmpDir() + "/.check"+int2str(ia)+".pyw";
        ofstream f(path.c_str());
        if (!f) {
            throw CanteraError("checkPython","cannot open "+path+" for writing");
        }
        f << "import ctml_writer\n";
        f.close();
        int ierr = 0;
#ifdef WIN32
        string cmd = "cmd /C "+pypath() + " " + path + ">> log 2>&1";
#else
        string cmd = pypath() + " " + path + " &> " + tmpDir() + "/log";
#endif
        try {
            ierr = system(cmd.c_str());
            if (ierr != 0) {
                string msg;
                msg = cmd +"\n\n########################################################################\n\n"
                      "The Cantera Python interface is required in order to process\n"
                      "Cantera input files, but it does not seem to be correctly installed.\n\n"
                      "Check that you can invoke the Python interpreter with \n"
                      "the command \"python\", and that typing \"from Cantera import *\"  \n"
                      "at the Python prompt does not produce an error. If Python on your system\n"
                      "is invoked with some other command, set environment variable PYTHON_CMD\n"
                      "to the full path to the Python interpreter. \n\n"
                      "#########################################################################\n\n";
                writelog(msg);
                return false;
            }
        }
        catch (...) {
            return false;
        }
#ifdef WIN32
        cmd = "cmd /C rm " + path;
#else
        cmd = "rm -f " + path;
        try {
            system(cmd.c_str());
        }
        catch (...) { ; }
#endif
        return true;
    }

    void ct2ctml(const char* file) {

        time_t aclock;
        time( &aclock );
        int ia = static_cast<int>(aclock);
        string path = tmpDir()+"/.cttmp"+int2str(ia)+".pyw";
        ofstream f(path.c_str());
        if (!f) {
            throw CanteraError("ct2ctml","cannot open "+path+" for writing.");
        }
        f << "from ctml_writer import *\n"
          << "import sys, os, os.path\n"
          << "file = \"" << file << "\"\n"
          << "base = os.path.basename(file)\n"
          << "root, ext = os.path.splitext(base)\n"
          << "dataset(root)\n"
          << "execfile(file)\n"
          << "write()\n";
        f.close();
#ifdef WIN32
        string cmd = pypath() + " " + path + "> ct2ctml.log 2>&1";
#else
        string cmd = "sleep " + sleep() + "; " + pypath() +
                     " " + path + " &> ct2ctml.log";
#endif
#ifdef DEBUG_PATHS
        writelog("ct2ctml: executing the command " + cmd + "\n");
#endif
        int ierr = 0;
        try {
            ierr = system(cmd.c_str());
        }
        catch (...) {
            ierr = -10;
        }

        /*
         * HKM -> This next section may seem a bit weird. However,
         *        it is in response to an issue that arises when
         *        running cantera with cygwin, using cygwin's
         *        python intepreter. Basically, the xml file is
         *        written to the local directory by the last
         *        system command. Then, the xml file is read
         *        immediately after by an ifstream() c++
         *        command. Unfortunately, it seems that the
         *        directory info is not being synched fast enough
         *        so that the ifstream() read fails, even
         *        though the file is actually there. Putting in a
         *        sleep system call here fixes this problem. Also,
         *        having the xml file pre-existing fixes the
         *        problem as well. There may be more direct ways
         *        to fix this bug; however, I am not aware of them.
         */
#if defined(CYGWIN)
#ifdef DEBUG_PATHS
        writelog("sleeping for 3 secs+\n");
#endif
        cmd = "sleep 3";
        try {
            ierr = system(cmd.c_str());
        }
        catch (...) {
            ierr = -10;
        }
#endif

        try {
            char ch=0;
            string s = "";
            ifstream ferr("ct2ctml.log");
            if (ferr) {
                while (!ferr.eof()) {
                    ferr.get(ch);
                    s += ch;
                    if (ch == '\n') {
                        writelog(s);
                        s = "";
                    }
                }
                ferr.close();
            }
        }
        catch (...) {
            ;
        }
        if (ierr != 0) {
            string msg = cmd;
            //bool pyok = checkPython();
            //if (!pyok)
            //    msg += "\nError in Python installation.";
            //else
            //    msg += "\nCheck error messages above for syntax errors.";
            throw CanteraError("ct2ctml",
			       "could not convert input file to CTML\n "
			       "command line was: " + msg);
        }
#ifndef DEBUG_PATHS
#ifdef WIN32
        cmd = "cmd /C rm " + path;
#else
        cmd = "rm -f " + path;
        try {
            if (ierr == 0)
                system(cmd.c_str());
        }
        catch (...) { ; }
#endif
#endif
    }

    /**
     * Get an CTML tree from a file, possibly preprocessing the file
     * first.
     */
    void get_CTML_Tree(XML_Node* rootPtr, string file) {
        string ff, ext = "";

        // find the input file on the Cantera search path
        string inname = findInputFile(file);
#ifdef DEBUG_PATHS
        writelog("Found file: "+inname+"\n");
#endif
        if (inname == "")
            throw CanteraError("get_CTML_tree", "file "+file+" not found");

        /**
         * Check whether or not the file is XML. If not, it will be first
         * processed with the preprocessor.
         */
        string::size_type idot = inname.rfind('.');
	if (idot != string::npos) {
	  ext = inname.substr(idot, inname.size());
	}
        if (ext != ".xml" && ext != ".ctml") {
	  ct2ctml(inname.c_str());
	  ff = inname.substr(0,idot) + ".xml";
        }
        else {
	  ff = inname;
	}
#ifdef DEBUG_PATHS
        writelog("Attempting to parse xml file " + ff + "\n");
#endif
        ifstream fin(ff.c_str());
        if (!fin) {
          throw
            CanteraError("get_CTML_tree",
                         "XML file " + ff + " not found");
        }
        rootPtr->build(fin);
        fin.close();
    }
}
<commit_msg>ifdeffed out a static function that was not used.<commit_after>/**
 * @file ct2ctml.cpp
 *
 * $Author$
 * $Revision$
 * $Date$
 */

// Copyright 2001  California Institute of Technology

// turn off warnings under Windows
#ifdef WIN32
#pragma warning(disable:4786)
#pragma warning(disable:4503)
#endif

#include "ct_defs.h"
#include "ctexceptions.h"
#include <fstream>
#include <string>
#include <stdlib.h>
#include <time.h>
#include "ctml.h"

//#define DEBUG_PATHS

using namespace Cantera;

namespace ctml {

    // return the full path to the Python interpreter.  Use
    // environment variable PYTHON_CMD if it is set, otherwise use the
    // definition PYTHON_EXE if it is defined. Failing that, return
    // the string 'python'.
    static string pypath() {
        string s = "python";
        const char* py = getenv("PYTHON_CMD");
        if (py) {
            string sp = stripws(string(py));
            if (sp.size() > 0) s = sp;
        }
        //#ifdef PYTHON_EXE
            //else {
        //string se = stripws(string(PYTHON_EXE));
        //  if (se.size() > 0) s = se;
        //}
        //#endif
        return s;
    }

#ifdef NOT_USED
    static bool checkPython() {
        time_t aclock;
        time( &aclock );
        int ia = static_cast<int>(aclock);
        string path = tmpDir() + "/.check"+int2str(ia)+".pyw";
        ofstream f(path.c_str());
        if (!f) {
            throw CanteraError("checkPython","cannot open "+path+" for writing");
        }
        f << "import ctml_writer\n";
        f.close();
        int ierr = 0;
#ifdef WIN32
        string cmd = "cmd /C "+pypath() + " " + path + ">> log 2>&1";
#else
        string cmd = pypath() + " " + path + " &> " + tmpDir() + "/log";
#endif
        try {
            ierr = system(cmd.c_str());
            if (ierr != 0) {
                string msg;
                msg = cmd +"\n\n########################################################################\n\n"
                      "The Cantera Python interface is required in order to process\n"
                      "Cantera input files, but it does not seem to be correctly installed.\n\n"
                      "Check that you can invoke the Python interpreter with \n"
                      "the command \"python\", and that typing \"from Cantera import *\"  \n"
                      "at the Python prompt does not produce an error. If Python on your system\n"
                      "is invoked with some other command, set environment variable PYTHON_CMD\n"
                      "to the full path to the Python interpreter. \n\n"
                      "#########################################################################\n\n";
                writelog(msg);
                return false;
            }
        }
        catch (...) {
            return false;
        }
#ifdef WIN32
        cmd = "cmd /C rm " + path;
#else
        cmd = "rm -f " + path;
        try {
            system(cmd.c_str());
        }
        catch (...) { ; }
#endif
        return true;
    }
#endif

    void ct2ctml(const char* file) {

        time_t aclock;
        time( &aclock );
        int ia = static_cast<int>(aclock);
        string path = tmpDir()+"/.cttmp"+int2str(ia)+".pyw";
        ofstream f(path.c_str());
        if (!f) {
            throw CanteraError("ct2ctml","cannot open "+path+" for writing.");
        }
        f << "from ctml_writer import *\n"
          << "import sys, os, os.path\n"
          << "file = \"" << file << "\"\n"
          << "base = os.path.basename(file)\n"
          << "root, ext = os.path.splitext(base)\n"
          << "dataset(root)\n"
          << "execfile(file)\n"
          << "write()\n";
        f.close();
#ifdef WIN32
        string cmd = pypath() + " " + path + "> ct2ctml.log 2>&1";
#else
        string cmd = "sleep " + sleep() + "; " + pypath() +
                     " " + path + " &> ct2ctml.log";
#endif
#ifdef DEBUG_PATHS
        writelog("ct2ctml: executing the command " + cmd + "\n");
#endif
        int ierr = 0;
        try {
            ierr = system(cmd.c_str());
        }
        catch (...) {
            ierr = -10;
        }

        /*
         * HKM -> This next section may seem a bit weird. However,
         *        it is in response to an issue that arises when
         *        running cantera with cygwin, using cygwin's
         *        python intepreter. Basically, the xml file is
         *        written to the local directory by the last
         *        system command. Then, the xml file is read
         *        immediately after by an ifstream() c++
         *        command. Unfortunately, it seems that the
         *        directory info is not being synched fast enough
         *        so that the ifstream() read fails, even
         *        though the file is actually there. Putting in a
         *        sleep system call here fixes this problem. Also,
         *        having the xml file pre-existing fixes the
         *        problem as well. There may be more direct ways
         *        to fix this bug; however, I am not aware of them.
         */
#ifdef CYGWIN
#ifdef DEBUG_PATHS
        writelog("sleeping for 3 secs+\n");
#endif
        cmd = "sleep 3";
        try {
            ierr = system(cmd.c_str());
        }
        catch (...) {
            ierr = -10;
        }
#endif

        try {
            char ch=0;
            string s = "";
            ifstream ferr("ct2ctml.log");
            if (ferr) {
                while (!ferr.eof()) {
                    ferr.get(ch);
                    s += ch;
                    if (ch == '\n') {
                        writelog(s);
                        s = "";
                    }
                }
                ferr.close();
            }
        }
        catch (...) {
            ;
        }
        if (ierr != 0) {
            string msg = cmd;
            //bool pyok = checkPython();
            //if (!pyok)
            //    msg += "\nError in Python installation.";
            //else
            //    msg += "\nCheck error messages above for syntax errors.";
            throw CanteraError("ct2ctml",
			       "could not convert input file to CTML\n "
			       "command line was: " + msg);
        }
#ifndef DEBUG_PATHS
#ifdef WIN32
        cmd = "cmd /C rm " + path;
#else
        cmd = "rm -f " + path;
        try {
            if (ierr == 0)
                system(cmd.c_str());
        }
        catch (...) { ; }
#endif
#endif
    }

    /**
     * Get an CTML tree from a file, possibly preprocessing the file
     * first.
     */
    void get_CTML_Tree(XML_Node* rootPtr, string file) {
        string ff, ext = "";

        // find the input file on the Cantera search path
        string inname = findInputFile(file);
#ifdef DEBUG_PATHS
        writelog("Found file: "+inname+"\n");
#endif
        if (inname == "")
            throw CanteraError("get_CTML_tree", "file "+file+" not found");

        /**
         * Check whether or not the file is XML. If not, it will be first
         * processed with the preprocessor.
         */
        string::size_type idot = inname.rfind('.');
	if (idot != string::npos) {
	  ext = inname.substr(idot, inname.size());
	}
        if (ext != ".xml" && ext != ".ctml") {
	  ct2ctml(inname.c_str());
	  ff = inname.substr(0,idot) + ".xml";
        }
        else {
	  ff = inname;
	}
#ifdef DEBUG_PATHS
        writelog("Attempting to parse xml file " + ff + "\n");
#endif
        ifstream fin(ff.c_str());
        if (!fin) {
          throw
            CanteraError("get_CTML_tree",
                         "XML file " + ff + " not found");
        }
        rootPtr->build(fin);
        fin.close();
    }
}
<|endoftext|>


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

#ifndef _UCBHELPER_REGISTERUCB_HXX_
#include <registerucb.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTPROVIDERMANAGER_HPP_
#include <com/sun/star/ucb/XContentProviderManager.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XPARAMETERIZEDCONTENTPROVIDER_HPP_
#include <com/sun/star/ucb/XParameterizedContentProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTPROVIDERFACTORY_HPP_
#include <com/sun/star/ucb/XContentProviderFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_RUNTIMEEXCEPTION_HPP_
#include <com/sun/star/uno/RuntimeException.hpp>
#endif
#ifndef _VOS_DIAGNOSE_H_
#include <vos/diagnose.hxx>
#endif

#ifndef _UCBHELPER_CONFIGUREUCB_HXX_
#include <ucbhelper/configureucb.hxx>
#endif

using namespace com::sun;
using namespace com::sun::star;

namespace ucb {

//============================================================================
//
//  registerAtUcb
//
//============================================================================

void
registerAtUcb(
    uno::Reference< star::ucb::XContentProviderManager > const & rManager,
    uno::Reference< lang::XMultiServiceFactory > const & rServiceFactory,
    rtl::OUString const & rName,
    rtl::OUString const & rArguments,
    rtl::OUString const & rTemplate,
    ContentProviderRegistrationInfo * pInfo)
    throw (uno::RuntimeException)
{
    VOS_ENSURE(rServiceFactory.is(),
               "ucb::registerAtUcb(): No service factory");

    uno::Reference< star::ucb::XContentProviderFactory > xProxyFactory;
    try
    {
        xProxyFactory
            = uno::Reference< star::ucb::XContentProviderFactory >(
                  rServiceFactory->
                      createInstance(
                          rtl::OUString::createFromAscii(
                              "com.sun.star.ucb."
                                  "ContentProviderProxyFactory")),
                  uno::UNO_QUERY);
    }
    catch (uno::RuntimeException const &) { throw; }
    catch (uno::Exception const &) {}

    // First, try to instantiate proxy for provider:
    uno::Reference< star::ucb::XContentProvider > xProvider;
    if (xProxyFactory.is())
        xProvider = xProxyFactory->createContentProvider(rName);

    // Then, try to instantiate provider directly:
    if (!xProvider.is())
        try
        {
            xProvider = uno::Reference< star::ucb::XContentProvider >(
                            rServiceFactory->createInstance(rName),
                            uno::UNO_QUERY);
        }
        catch (uno::RuntimeException const &) { throw; }
        catch (uno::Exception const &) {}

    uno::Reference< star::ucb::XContentProvider >
        xOriginalProvider(xProvider);
    uno::Reference< star::ucb::XParameterizedContentProvider >
        xParameterized(xProvider, uno::UNO_QUERY);
    if (xParameterized.is())
    {
        uno::Reference< star::ucb::XContentProvider > xInstance;
        try
        {
            xInstance
                = xParameterized->registerInstance(rTemplate,
                                                   rArguments,
                                                   true);
                //@@@ if this call replaces an old instance, the commit-or-
                // rollback code below will not work
        }
        catch (lang::IllegalArgumentException const &) {}

        if (xInstance.is())
            xProvider = xInstance;
    }

    if (rManager.is() && xProvider.is())
        try
        {
            rManager->registerContentProvider(xProvider, rTemplate, true);
        }
        catch (star::ucb::DuplicateProviderException const &)
        {
            if (xParameterized.is())
                try
                {
                    xParameterized->deregisterInstance(rTemplate, rArguments);
                }
                catch (lang::IllegalArgumentException const &) {}
            xOriginalProvider = 0;
        }
        catch (...)
        {
            if (xParameterized.is())
                try
                {
                    xParameterized->deregisterInstance(rTemplate, rArguments);
                }
                catch (lang::IllegalArgumentException const &) {}
            throw;
        }

    if (pInfo)
    {
        pInfo->m_xProvider = xOriginalProvider;
        pInfo->m_aArguments = rArguments;
        pInfo->m_aTemplate = rTemplate;
    }
}

//============================================================================
//
//  deregisterFromUcb
//
//============================================================================

void
deregisterFromUcb(
    uno::Reference< star::ucb::XContentProviderManager > const & rManager,
    ContentProviderRegistrationInfo const & rInfo)
    throw (uno::RuntimeException)
{
    uno::Reference< star::ucb::XContentProvider >
        xProvider(rInfo.m_xProvider);
    uno::Reference< star::ucb::XParameterizedContentProvider >
        xParameterized(xProvider, uno::UNO_QUERY);
    if (xParameterized.is())
    {
        uno::Reference< star::ucb::XContentProvider > xInstance;
        try
        {
            xInstance
                = xParameterized->deregisterInstance(rInfo.m_aTemplate,
                                                     rInfo.m_aArguments);
        }
        catch (lang::IllegalArgumentException const &) {}

        if (xInstance.is())
            xProvider = xInstance;
    }

    if (rManager.is() && xProvider.is())
        rManager->deregisterContentProvider(xProvider, rInfo.m_aTemplate);
            //@@@ if this fails, a roll-back of deregisterInstance() is
            // missing
}

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

#ifndef _UCBHELPER_REGISTERUCB_HXX_
#include <registerucb.hxx>
#endif

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTPROVIDERMANAGER_HPP_
#include <com/sun/star/ucb/XContentProviderManager.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XPARAMETERIZEDCONTENTPROVIDER_HPP_
#include <com/sun/star/ucb/XParameterizedContentProvider.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENTPROVIDERFACTORY_HPP_
#include <com/sun/star/ucb/XContentProviderFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_RUNTIMEEXCEPTION_HPP_
#include <com/sun/star/uno/RuntimeException.hpp>
#endif
#ifndef _VOS_DIAGNOSE_H_
#include <vos/diagnose.hxx>
#endif

#ifndef _UCBHELPER_CONFIGUREUCB_HXX_
#include <ucbhelper/configureucb.hxx>
#endif

using namespace com::sun;
using namespace com::sun::star;

namespace ucb {

//============================================================================
//
//  registerAtUcb
//
//============================================================================

void
registerAtUcb(
    uno::Reference< star::ucb::XContentProviderManager > const & rManager,
    uno::Reference< lang::XMultiServiceFactory > const & rServiceFactory,
    rtl::OUString const & rName,
    rtl::OUString const & rArguments,
    rtl::OUString const & rTemplate,
    ContentProviderRegistrationInfo * pInfo)
    throw (uno::RuntimeException)
{
    VOS_ENSURE(rServiceFactory.is(),
               "ucb::registerAtUcb(): No service factory");

    bool bNoProxy
        = rArguments.compareToAscii(RTL_CONSTASCII_STRINGPARAM("{noproxy}"))
              == 0;
    rtl::OUString
        aProviderArguments(bNoProxy ?
                               rArguments.
                                   copy(RTL_CONSTASCII_LENGTH("{noproxy}")) :
                               rArguments);

    uno::Reference< star::ucb::XContentProviderFactory > xProxyFactory;
    if (!bNoProxy)
        try
        {
            xProxyFactory
                = uno::Reference< star::ucb::XContentProviderFactory >(
                      rServiceFactory->
                          createInstance(
                              rtl::OUString::createFromAscii(
                                  "com.sun.star.ucb."
                                      "ContentProviderProxyFactory")),
                      uno::UNO_QUERY);
        }
        catch (uno::RuntimeException const &) { throw; }
        catch (uno::Exception const &) {}

    // First, try to instantiate proxy for provider:
    uno::Reference< star::ucb::XContentProvider > xProvider;
    if (xProxyFactory.is())
        xProvider = xProxyFactory->createContentProvider(rName);

    // Then, try to instantiate provider directly:
    if (!xProvider.is())
        try
        {
            xProvider = uno::Reference< star::ucb::XContentProvider >(
                            rServiceFactory->createInstance(rName),
                            uno::UNO_QUERY);
        }
        catch (uno::RuntimeException const &) { throw; }
        catch (uno::Exception const &) {}

    uno::Reference< star::ucb::XContentProvider >
        xOriginalProvider(xProvider);
    uno::Reference< star::ucb::XParameterizedContentProvider >
        xParameterized(xProvider, uno::UNO_QUERY);
    if (xParameterized.is())
    {
        uno::Reference< star::ucb::XContentProvider > xInstance;
        try
        {
            xInstance
                = xParameterized->registerInstance(rTemplate,
                                                   aProviderArguments,
                                                   true);
                //@@@ if this call replaces an old instance, the commit-or-
                // rollback code below will not work
        }
        catch (lang::IllegalArgumentException const &) {}

        if (xInstance.is())
            xProvider = xInstance;
    }

    if (rManager.is() && xProvider.is())
        try
        {
            rManager->registerContentProvider(xProvider, rTemplate, true);
        }
        catch (star::ucb::DuplicateProviderException const &)
        {
            if (xParameterized.is())
                try
                {
                    xParameterized->deregisterInstance(rTemplate,
                                                       aProviderArguments);
                }
                catch (lang::IllegalArgumentException const &) {}
            xOriginalProvider = 0;
        }
        catch (...)
        {
            if (xParameterized.is())
                try
                {
                    xParameterized->deregisterInstance(rTemplate,
                                                       aProviderArguments);
                }
                catch (lang::IllegalArgumentException const &) {}
            throw;
        }

    if (pInfo)
    {
        pInfo->m_xProvider = xOriginalProvider;
        pInfo->m_aArguments = aProviderArguments;
        pInfo->m_aTemplate = rTemplate;
    }
}

//============================================================================
//
//  deregisterFromUcb
//
//============================================================================

void
deregisterFromUcb(
    uno::Reference< star::ucb::XContentProviderManager > const & rManager,
    ContentProviderRegistrationInfo const & rInfo)
    throw (uno::RuntimeException)
{
    uno::Reference< star::ucb::XContentProvider >
        xProvider(rInfo.m_xProvider);
    uno::Reference< star::ucb::XParameterizedContentProvider >
        xParameterized(xProvider, uno::UNO_QUERY);
    if (xParameterized.is())
    {
        uno::Reference< star::ucb::XContentProvider > xInstance;
        try
        {
            xInstance
                = xParameterized->deregisterInstance(rInfo.m_aTemplate,
                                                     rInfo.m_aArguments);
        }
        catch (lang::IllegalArgumentException const &) {}

        if (xInstance.is())
            xProvider = xInstance;
    }

    if (rManager.is() && xProvider.is())
        rManager->deregisterContentProvider(xProvider, rInfo.m_aTemplate);
            //@@@ if this fails, a roll-back of deregisterInstance() is
            // missing
}

}
<|endoftext|>


<commit_before>//===-- ELFTargetAsmInfo.cpp - ELF asm properties ---------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target asm properties related what form asm statements
// should take in general on ELF-based targets
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetData.h"

using namespace llvm;

ELFTargetAsmInfo::ELFTargetAsmInfo(const TargetMachine &TM)
  : TargetAsmInfo(TM) {

  BSSSection_  = getUnnamedSection("\t.bss",
                                   SectionFlags::Writeable | SectionFlags::BSS);
  ReadOnlySection = getNamedSection("\t.rodata", SectionFlags::None);
  TLSDataSection = getNamedSection("\t.tdata",
                                   SectionFlags::Writeable | SectionFlags::TLS);
  TLSBSSSection = getNamedSection("\t.tbss",
                SectionFlags::Writeable | SectionFlags::TLS | SectionFlags::BSS);

  DataRelSection = getNamedSection("\t.data.rel", SectionFlags::Writeable);
  DataRelLocalSection = getNamedSection("\t.data.rel.local",
                                        SectionFlags::Writeable);
  DataRelROSection = getNamedSection("\t.data.rel.ro",
                                     SectionFlags::Writeable);
  DataRelROLocalSection = getNamedSection("\t.data.rel.ro.local",
                                          SectionFlags::Writeable);
}

SectionKind::Kind
ELFTargetAsmInfo::SectionKindForGlobal(const GlobalValue *GV) const {
  SectionKind::Kind Kind = TargetAsmInfo::SectionKindForGlobal(GV);

  if (Kind != SectionKind::Data)
    return Kind;

  // Decide, whether we need data.rel stuff
  const GlobalVariable* GVar = dyn_cast<GlobalVariable>(GV);
  if (GVar->hasInitializer() && TM.getRelocationModel() != Reloc::Static) {
    Constant *C = GVar->getInitializer();
    bool isConstant = GVar->isConstant();

    // By default - all relocations in PIC mode would force symbol to be
    // placed in r/w section.
    switch (C->getRelocationInfo()) {
    default: break;
    case Constant::LocalRelocation:
      return isConstant ? SectionKind::DataRelROLocal :
                          SectionKind::DataRelLocal;
    case Constant::GlobalRelocations:
      return isConstant ? SectionKind::DataRelRO : SectionKind::DataRel;
    }
  }

  return Kind;
}

const Section*
ELFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const {
  SectionKind::Kind Kind = SectionKindForGlobal(GV);

  if (const Function *F = dyn_cast<Function>(GV)) {
    switch (F->getLinkage()) {
     default: llvm_unreachable("Unknown linkage type!");
     case Function::PrivateLinkage:
     case Function::LinkerPrivateLinkage:
     case Function::InternalLinkage:
     case Function::DLLExportLinkage:
     case Function::ExternalLinkage:
      return TextSection;
     case Function::WeakAnyLinkage:
     case Function::WeakODRLinkage:
     case Function::LinkOnceAnyLinkage:
     case Function::LinkOnceODRLinkage:
      std::string Name = UniqueSectionForGlobal(GV, Kind);
      unsigned Flags = SectionFlagsForGlobal(GV, Name.c_str());
      return getNamedSection(Name.c_str(), Flags);
    }
  } else if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
    if (GVar->isWeakForLinker()) {
      std::string Name = UniqueSectionForGlobal(GVar, Kind);
      unsigned Flags = SectionFlagsForGlobal(GVar, Name.c_str());
      return getNamedSection(Name.c_str(), Flags);
    } else {
      switch (Kind) {
      case SectionKind::Data:
      case SectionKind::DataRel:
        return DataRelSection;
      case SectionKind::DataRelLocal:
        return DataRelLocalSection;
      case SectionKind::DataRelRO:
        return DataRelROSection;
      case SectionKind::DataRelROLocal:
        return DataRelROLocalSection;
      case SectionKind::BSS:
        return getBSSSection_();
      case SectionKind::ROData:
        return getReadOnlySection();
      case SectionKind::RODataMergeStr:
        return MergeableStringSection(GVar);
      case SectionKind::RODataMergeConst: {
        const Type *Ty = GVar->getInitializer()->getType();
        const TargetData *TD = TM.getTargetData();
        return getSectionForMergableConstant(TD->getTypeAllocSize(Ty), 0);
      }
      case SectionKind::ThreadData:
        // ELF targets usually support TLS stuff
        return TLSDataSection;
      case SectionKind::ThreadBSS:
        return TLSBSSSection;
      default:
        llvm_unreachable("Unsuported section kind for global");
      }
    }
  } else
    llvm_unreachable("Unsupported global");

  return NULL;
}

/// getSectionForMergableConstant - Given a mergable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
const Section *
ELFTargetAsmInfo::getSectionForMergableConstant(uint64_t Size,
                                                unsigned ReloInfo) const {
  // FIXME: IF this global requires a relocation, can we really put it in
  // rodata???  This should check ReloInfo like darwin.

  const char *SecName = 0;
  switch (Size) {
  default: break;
  case 4:  SecName = ".rodata.cst4"; break;
  case 8:  SecName = ".rodata.cst8"; break;
  case 16: SecName = ".rodata.cst16"; break;
  }

  if (SecName)
    return getNamedSection(SecName,
                           SectionFlags::setEntitySize(SectionFlags::Mergeable,
                                                       Size));

  return getReadOnlySection();  // .rodata
}

const Section*
ELFTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const {
  const TargetData *TD = TM.getTargetData();
  Constant *C = cast<GlobalVariable>(GV)->getInitializer();
  const Type *Ty = cast<ArrayType>(C->getType())->getElementType();

  unsigned Size = TD->getTypeAllocSize(Ty);
  if (Size <= 16) {
    assert(getCStringSection() && "Should have string section prefix");

    // We also need alignment here
    unsigned Align = TD->getPrefTypeAlignment(Ty);
    if (Align < Size)
      Align = Size;

    std::string Name = getCStringSection() + utostr(Size) + '.' + utostr(Align);
    unsigned Flags = SectionFlags::setEntitySize(SectionFlags::Mergeable |
                                                 SectionFlags::Strings,
                                                 Size);
    return getNamedSection(Name.c_str(), Flags);
  }

  return getReadOnlySection();
}

std::string ELFTargetAsmInfo::printSectionFlags(unsigned flags) const {
  std::string Flags = ",\"";

  if (!(flags & SectionFlags::Debug))
    Flags += 'a';
  if (flags & SectionFlags::Code)
    Flags += 'x';
  if (flags & SectionFlags::Writeable)
    Flags += 'w';
  if (flags & SectionFlags::Mergeable)
    Flags += 'M';
  if (flags & SectionFlags::Strings)
    Flags += 'S';
  if (flags & SectionFlags::TLS)
    Flags += 'T';

  Flags += "\",";

  // If comment string is '@', e.g. as on ARM - use '%' instead
  if (strcmp(CommentString, "@") == 0)
    Flags += '%';
  else
    Flags += '@';

  // FIXME: There can be exceptions here
  if (flags & SectionFlags::BSS)
    Flags += "nobits";
  else
    Flags += "progbits";

  if (unsigned entitySize = SectionFlags::getEntitySize(flags))
    Flags += "," + utostr(entitySize);

  return Flags;
}
<commit_msg>fix indentation.<commit_after>//===-- ELFTargetAsmInfo.cpp - ELF asm properties ---------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target asm properties related what form asm statements
// should take in general on ELF-based targets
//
//===----------------------------------------------------------------------===//

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/ELFTargetAsmInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetData.h"

using namespace llvm;

ELFTargetAsmInfo::ELFTargetAsmInfo(const TargetMachine &TM)
  : TargetAsmInfo(TM) {

  BSSSection_  = getUnnamedSection("\t.bss",
                                   SectionFlags::Writeable | SectionFlags::BSS);
  ReadOnlySection = getNamedSection("\t.rodata", SectionFlags::None);
  TLSDataSection = getNamedSection("\t.tdata",
                                   SectionFlags::Writeable | SectionFlags::TLS);
  TLSBSSSection = getNamedSection("\t.tbss",
                SectionFlags::Writeable | SectionFlags::TLS | SectionFlags::BSS);

  DataRelSection = getNamedSection("\t.data.rel", SectionFlags::Writeable);
  DataRelLocalSection = getNamedSection("\t.data.rel.local",
                                        SectionFlags::Writeable);
  DataRelROSection = getNamedSection("\t.data.rel.ro",
                                     SectionFlags::Writeable);
  DataRelROLocalSection = getNamedSection("\t.data.rel.ro.local",
                                          SectionFlags::Writeable);
}

SectionKind::Kind
ELFTargetAsmInfo::SectionKindForGlobal(const GlobalValue *GV) const {
  SectionKind::Kind Kind = TargetAsmInfo::SectionKindForGlobal(GV);

  if (Kind != SectionKind::Data)
    return Kind;

  // Decide, whether we need data.rel stuff
  const GlobalVariable* GVar = dyn_cast<GlobalVariable>(GV);
  if (GVar->hasInitializer() && TM.getRelocationModel() != Reloc::Static) {
    Constant *C = GVar->getInitializer();
    bool isConstant = GVar->isConstant();

    // By default - all relocations in PIC mode would force symbol to be
    // placed in r/w section.
    switch (C->getRelocationInfo()) {
    default: break;
    case Constant::LocalRelocation:
      return isConstant ? SectionKind::DataRelROLocal :
                          SectionKind::DataRelLocal;
    case Constant::GlobalRelocations:
      return isConstant ? SectionKind::DataRelRO : SectionKind::DataRel;
    }
  }

  return Kind;
}

const Section*
ELFTargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const {
  SectionKind::Kind Kind = SectionKindForGlobal(GV);

  if (const Function *F = dyn_cast<Function>(GV)) {
    switch (F->getLinkage()) {
      default: llvm_unreachable("Unknown linkage type!");
      case Function::PrivateLinkage:
      case Function::LinkerPrivateLinkage:
      case Function::InternalLinkage:
      case Function::DLLExportLinkage:
      case Function::ExternalLinkage:
        return TextSection;
      case Function::WeakAnyLinkage:
      case Function::WeakODRLinkage:
      case Function::LinkOnceAnyLinkage:
      case Function::LinkOnceODRLinkage:
        std::string Name = UniqueSectionForGlobal(GV, Kind);
        unsigned Flags = SectionFlagsForGlobal(GV, Name.c_str());
        return getNamedSection(Name.c_str(), Flags);
    }
  } else if (const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV)) {
    if (GVar->isWeakForLinker()) {
      std::string Name = UniqueSectionForGlobal(GVar, Kind);
      unsigned Flags = SectionFlagsForGlobal(GVar, Name.c_str());
      return getNamedSection(Name.c_str(), Flags);
    } else {
      switch (Kind) {
      case SectionKind::Data:
      case SectionKind::DataRel:
        return DataRelSection;
      case SectionKind::DataRelLocal:
        return DataRelLocalSection;
      case SectionKind::DataRelRO:
        return DataRelROSection;
      case SectionKind::DataRelROLocal:
        return DataRelROLocalSection;
      case SectionKind::BSS:
        return getBSSSection_();
      case SectionKind::ROData:
        return getReadOnlySection();
      case SectionKind::RODataMergeStr:
        return MergeableStringSection(GVar);
      case SectionKind::RODataMergeConst: {
        const Type *Ty = GVar->getInitializer()->getType();
        const TargetData *TD = TM.getTargetData();
        return getSectionForMergableConstant(TD->getTypeAllocSize(Ty), 0);
      }
      case SectionKind::ThreadData:
        // ELF targets usually support TLS stuff
        return TLSDataSection;
      case SectionKind::ThreadBSS:
        return TLSBSSSection;
      default:
        llvm_unreachable("Unsuported section kind for global");
      }
    }
  } else
    llvm_unreachable("Unsupported global");

  return NULL;
}

/// getSectionForMergableConstant - Given a mergable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
const Section *
ELFTargetAsmInfo::getSectionForMergableConstant(uint64_t Size,
                                                unsigned ReloInfo) const {
  // FIXME: IF this global requires a relocation, can we really put it in
  // rodata???  This should check ReloInfo like darwin.

  const char *SecName = 0;
  switch (Size) {
  default: break;
  case 4:  SecName = ".rodata.cst4"; break;
  case 8:  SecName = ".rodata.cst8"; break;
  case 16: SecName = ".rodata.cst16"; break;
  }

  if (SecName)
    return getNamedSection(SecName,
                           SectionFlags::setEntitySize(SectionFlags::Mergeable,
                                                       Size));

  return getReadOnlySection();  // .rodata
}

const Section*
ELFTargetAsmInfo::MergeableStringSection(const GlobalVariable *GV) const {
  const TargetData *TD = TM.getTargetData();
  Constant *C = cast<GlobalVariable>(GV)->getInitializer();
  const Type *Ty = cast<ArrayType>(C->getType())->getElementType();

  unsigned Size = TD->getTypeAllocSize(Ty);
  if (Size <= 16) {
    assert(getCStringSection() && "Should have string section prefix");

    // We also need alignment here
    unsigned Align = TD->getPrefTypeAlignment(Ty);
    if (Align < Size)
      Align = Size;

    std::string Name = getCStringSection() + utostr(Size) + '.' + utostr(Align);
    unsigned Flags = SectionFlags::setEntitySize(SectionFlags::Mergeable |
                                                 SectionFlags::Strings,
                                                 Size);
    return getNamedSection(Name.c_str(), Flags);
  }

  return getReadOnlySection();
}

std::string ELFTargetAsmInfo::printSectionFlags(unsigned flags) const {
  std::string Flags = ",\"";

  if (!(flags & SectionFlags::Debug))
    Flags += 'a';
  if (flags & SectionFlags::Code)
    Flags += 'x';
  if (flags & SectionFlags::Writeable)
    Flags += 'w';
  if (flags & SectionFlags::Mergeable)
    Flags += 'M';
  if (flags & SectionFlags::Strings)
    Flags += 'S';
  if (flags & SectionFlags::TLS)
    Flags += 'T';

  Flags += "\",";

  // If comment string is '@', e.g. as on ARM - use '%' instead
  if (strcmp(CommentString, "@") == 0)
    Flags += '%';
  else
    Flags += '@';

  // FIXME: There can be exceptions here
  if (flags & SectionFlags::BSS)
    Flags += "nobits";
  else
    Flags += "progbits";

  if (unsigned entitySize = SectionFlags::getEntitySize(flags))
    Flags += "," + utostr(entitySize);

  return Flags;
}
<|endoftext|>