<commit_before>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "ExecutionContext.h"

#include "cling/Interpreter/StoredValueRef.h"

#include "clang/AST/Type.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DynamicLibrary.h"

using namespace cling;

std::set<std::string> ExecutionContext::m_unresolvedSymbols;
std::vector<ExecutionContext::LazyFunctionCreatorFunc_t>
  ExecutionContext::m_lazyFuncCreator;

bool ExecutionContext::m_LazyFuncCreatorDiagsSuppressed = false;

// Keep in source: OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext::ExecutionContext(llvm::Module* m)
  : m_RunningStaticInits(false), m_CxaAtExitRemapped(false)
{
  assert(m && "llvm::Module must not be null!");
  m_AtExitFuncs.reserve(256);
  InitializeBuilder(m);
}

// Keep in source: ~OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext::~ExecutionContext() {
  for (size_t I = 0, N = m_AtExitFuncs.size(); I < N; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[N - I - 1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

void ExecutionContext::InitializeBuilder(llvm::Module* m) {
  //
  //  Create an execution engine to use.
  //
  assert(m && "Module cannot be null");

  // Note: Engine takes ownership of the module.
  llvm::EngineBuilder builder(m);

  std::string errMsg;
  builder.setErrorStr(&errMsg);
  builder.setOptLevel(llvm::CodeGenOpt::Less);
  builder.setEngineKind(llvm::EngineKind::JIT);
  builder.setAllocateGVsWithCode(false);

  // EngineBuilder uses default c'ted TargetOptions, too:
  llvm::TargetOptions TargetOpts;
  TargetOpts.NoFramePointerElim = 1;
  TargetOpts.JITEmitDebugInfo = 1;

  builder.setTargetOptions(TargetOpts);

  m_engine.reset(builder.create());
  if (!m_engine)
     llvm::errs() << "cling::ExecutionContext::InitializeBuilder(): " << errMsg;
  assert(m_engine && "Cannot create module!");

  // install lazy function creators
  m_engine->InstallLazyFunctionCreator(NotifyLazyFunctionCreators);
}

int ExecutionContext::CXAAtExit(void (*func) (void*), void* arg, void* dso,
                                void* clangDecl) {
  // Register a CXAAtExit function
  clang::Decl* LastTLD = (clang::Decl*)clangDecl;
  m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, dso, LastTLD));
  return 0; // happiness
}

void unresolvedSymbol()
{
  // throw exception?
  llvm::errs() << "ExecutionContext: calling unresolved symbol, "
    "see previous error message!\n";
}

void* ExecutionContext::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    llvm::errs() << "ExecutionContext: use of undefined symbol '"
                 << mangled_name << "'!\n";
  }

  // Avoid "ISO C++ forbids casting between pointer-to-function and
  // pointer-to-object":
  return (void*)reinterpret_cast<size_t>(unresolvedSymbol);
}

void*
ExecutionContext::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret)
      return ret;
  }

  if (m_LazyFuncCreatorDiagsSuppressed)
    return 0;

  return HandleMissingFunction(mangled_name);
}

static void
freeCallersOfUnresolvedSymbols(llvm::SmallVectorImpl<llvm::Function*>&
                               funcsToFree, llvm::ExecutionEngine* engine) {
  llvm::SmallPtrSet<llvm::Function*, 40> funcsToFreeUnique;
  for (size_t i = 0; i < funcsToFree.size(); ++i) {
    llvm::Function* func = funcsToFree[i];
    if (!func) continue;
    if (funcsToFreeUnique.insert(func)) {
      for (llvm::Value::use_iterator IU = func->use_begin(),
             EU = func->use_end(); IU != EU; ++IU) {
        llvm::Instruction* instUser = llvm::dyn_cast<llvm::Instruction>(*IU);
        if (!instUser) continue;
        if (!instUser->getParent()) continue;
        if (llvm::Function* userFunc = instUser->getParent()->getParent())
          funcsToFree.push_back(userFunc);
      }
    }
  }
  for (llvm::SmallPtrSet<llvm::Function*, 40>::iterator
         I = funcsToFreeUnique.begin(), E = funcsToFreeUnique.end();
       I != E; ++I) {
    // This should force the JIT to recompile the function. But the stubs stay,
    // and the JIT reuses the stubs now pointing nowhere, i.e. without updating
    // the machine code address. Fix the JIT, or hope that MCJIT helps.
    //engine->freeMachineCodeForFunction(*I);
    engine->updateGlobalMapping(*I, 0);
  }
}

ExecutionContext::ExecutionResult
ExecutionContext::executeFunction(llvm::StringRef funcname,
                                  const clang::ASTContext& Ctx,
                                  clang::QualType retType,
                                  StoredValueRef* returnValue)
{
  // Call a function without arguments, or with an SRet argument, see SRet below

  if (!m_CxaAtExitRemapped) {
    // Rewire atexit:
    llvm::Function* atExit = m_engine->FindFunctionNamed("__cxa_atexit");
    llvm::Function* clingAtExit
      = m_engine->FindFunctionNamed("cling_cxa_atexit");
    if (atExit && clingAtExit) {
      void* clingAtExitAddr = m_engine->getPointerToFunction(clingAtExit);
      assert(clingAtExitAddr && "cannot find cling_cxa_atexit");
      m_engine->updateGlobalMapping(atExit, clingAtExitAddr);
      m_CxaAtExitRemapped = true;
    }
  }

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  llvm::Function* f = m_engine->FindFunctionNamed(funcname.str().c_str());
  if (!f) {
    llvm::errs() << "ExecutionContext::executeFunction: "
      "could not find function named " << funcname << '\n';
    return kExeFunctionNotCompiled;
  }
  m_engine->getPointerToFunction(f);
  // check if there is any unresolved symbol in the list
  if (!m_unresolvedSymbols.empty()) {
    llvm::SmallVector<llvm::Function*, 100> funcsToFree;
    for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
           e = m_unresolvedSymbols.end(); i != e; ++i) {
      llvm::errs() << "ExecutionContext::executeFunction: symbol '" << *i
                   << "' unresolved while linking function '" << funcname
                   << "'!\n";
      llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
      assert(ff && "cannot find function to free");
      funcsToFree.push_back(ff);
    }
    freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
    m_unresolvedSymbols.clear();
    return kExeUnresolvedSymbols;
  }

  std::vector<llvm::GenericValue> args;
  bool wantReturn = (returnValue);
  StoredValueRef aggregateRet;

  if (f->hasStructRetAttr()) {
    // Function expects to receive the storage for the returned aggregate as
    // first argument. Allocate returnValue:
    aggregateRet = StoredValueRef::allocate(Ctx, retType, f->getReturnType());
    if (returnValue) {
      *returnValue = aggregateRet;
    } else {
      returnValue = &aggregateRet;
    }
    args.push_back(returnValue->get().getGV());
    // will get set as arg0, must not assign.
    wantReturn = false;
  }

  if (wantReturn) {
    llvm::GenericValue gvRet = m_engine->runFunction(f, args);
    // rescue the ret value (which might be aggregate) from the stack
    *returnValue = StoredValueRef::bitwiseCopy(Ctx, Value(gvRet, retType));
  } else {
    m_engine->runFunction(f, args);
  }

  return kExeSuccess;
}

ExecutionContext::ExecutionResult
ExecutionContext::runStaticInitializersOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  if (m_RunningStaticInits)
     return kExeSuccess;

  llvm::GlobalVariable* GV
     = m->getGlobalVariable("llvm.global_ctors", true);
  // Nothing to do is good, too.
  if (!GV) return kExeSuccess;

  // Close similarity to
  // m_engine->runStaticConstructorsDestructors(false) aka
  // llvm::ExecutionEngine::runStaticConstructorsDestructors()
  // is intentional; we do an extra pass to check whether the JIT
  // managed to collect all the symbols needed by the niitializers.
  // Should be an array of '{ i32, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  llvm::ConstantArray *InitList
    = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer());
  if (InitList == 0)
    return kExeSuccess;

  m_RunningStaticInits = true;

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    llvm::ConstantStruct *CS
      = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i));
    if (CS == 0) continue;

    llvm::Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      continue;  // Found a sentinal value, ignore.

    // Strip off constant expression casts.
    if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP))
      if (CE->isCast())
        FP = CE->getOperand(0);

    // Execute the ctor/dtor function!
    if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) {
      m_engine->getPointerToFunction(F);
      // check if there is any unresolved symbol in the list
      if (!m_unresolvedSymbols.empty()) {
        llvm::SmallVector<llvm::Function*, 100> funcsToFree;
        for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
               e = m_unresolvedSymbols.end(); i != e; ++i) {
          llvm::errs() << "ExecutionContext::runStaticInitializersOnce: symbol '" << *i
                       << "' unresolved while linking static initializer '"
                       << F->getName() << "'!\n";
          llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
          assert(ff && "cannot find function to free");
          funcsToFree.push_back(ff);
        }
        freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
        m_unresolvedSymbols.clear();
        m_RunningStaticInits = false;
        return kExeUnresolvedSymbols;
      }
      m_engine->runFunction(F, std::vector<llvm::GenericValue>());
    }
  }

  GV->eraseFromParent();

  m_RunningStaticInits = false;
  return kExeSuccess;
}

void
ExecutionContext::runStaticDestructorsOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  llvm::GlobalVariable* gdtors
    = m->getGlobalVariable("llvm.global_dtors", true);
  if (gdtors) {
    m_engine->runStaticConstructorsDestructors(true);
  }

  // 'Unload' the cxa_atexit entities.
  for (size_t I = 0, E = m_AtExitFuncs.size(); I < E; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[E-I-1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
  m_AtExitFuncs.clear();
}

int
ExecutionContext::verifyModule(llvm::Module* m)
{
  //
  //  Verify generated module.
  //
  bool mod_has_errs = llvm::verifyModule(*m, llvm::PrintMessageAction);
  if (mod_has_errs) {
    return 1;
  }
  return 0;
}

void
ExecutionContext::printModule(llvm::Module* m)
{
  //
  //  Print module LLVM code in human-readable form.
  //
  llvm::PassManager PM;
  PM.add(llvm::createPrintModulePass(&llvm::errs()));
  PM.run(*m);
}

void
ExecutionContext::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool ExecutionContext::addSymbol(const char* symbolName,  void* symbolAddress) {

  void* actualAddress
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (actualAddress)
    return false;

  llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolAddress);
  return true;
}

void* ExecutionContext::getAddressOfGlobal(llvm::Module* m,
                                           const char* symbolName,
                                           bool* fromJIT /*=0*/) const {
  // Return a symbol's address, and whether it was jitted.
  void* address
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (address) {
    if (fromJIT) *fromJIT = false;
  } else {
    if (fromJIT) *fromJIT = true;
    llvm::GlobalVariable* gvar = m->getGlobalVariable(symbolName, true);
    if (!gvar)
      return 0;

    address = m_engine->getPointerToGlobal(gvar);
  }
  return address;
}
<commit_msg>Capture non-functions in caller insted of passing 0; add assert against 0.<commit_after>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------

#include "ExecutionContext.h"

#include "cling/Interpreter/StoredValueRef.h"

#include "clang/AST/Type.h"

#include "llvm/IR/Constants.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/JIT.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/DynamicLibrary.h"

using namespace cling;

std::set<std::string> ExecutionContext::m_unresolvedSymbols;
std::vector<ExecutionContext::LazyFunctionCreatorFunc_t>
  ExecutionContext::m_lazyFuncCreator;

bool ExecutionContext::m_LazyFuncCreatorDiagsSuppressed = false;

// Keep in source: OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext::ExecutionContext(llvm::Module* m)
  : m_RunningStaticInits(false), m_CxaAtExitRemapped(false)
{
  assert(m && "llvm::Module must not be null!");
  m_AtExitFuncs.reserve(256);
  InitializeBuilder(m);
}

// Keep in source: ~OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext::~ExecutionContext() {
  for (size_t I = 0, N = m_AtExitFuncs.size(); I < N; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[N - I - 1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
}

void ExecutionContext::InitializeBuilder(llvm::Module* m) {
  //
  //  Create an execution engine to use.
  //
  assert(m && "Module cannot be null");

  // Note: Engine takes ownership of the module.
  llvm::EngineBuilder builder(m);

  std::string errMsg;
  builder.setErrorStr(&errMsg);
  builder.setOptLevel(llvm::CodeGenOpt::Less);
  builder.setEngineKind(llvm::EngineKind::JIT);
  builder.setAllocateGVsWithCode(false);

  // EngineBuilder uses default c'ted TargetOptions, too:
  llvm::TargetOptions TargetOpts;
  TargetOpts.NoFramePointerElim = 1;
  TargetOpts.JITEmitDebugInfo = 1;

  builder.setTargetOptions(TargetOpts);

  m_engine.reset(builder.create());
  if (!m_engine)
     llvm::errs() << "cling::ExecutionContext::InitializeBuilder(): " << errMsg;
  assert(m_engine && "Cannot create module!");

  // install lazy function creators
  m_engine->InstallLazyFunctionCreator(NotifyLazyFunctionCreators);
}

int ExecutionContext::CXAAtExit(void (*func) (void*), void* arg, void* dso,
                                void* clangDecl) {
  // Register a CXAAtExit function
  clang::Decl* LastTLD = (clang::Decl*)clangDecl;
  m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, dso, LastTLD));
  return 0; // happiness
}

void unresolvedSymbol()
{
  // throw exception?
  llvm::errs() << "ExecutionContext: calling unresolved symbol, "
    "see previous error message!\n";
}

void* ExecutionContext::HandleMissingFunction(const std::string& mangled_name)
{
  // Not found in the map, add the symbol in the list of unresolved symbols
  if (m_unresolvedSymbols.insert(mangled_name).second) {
    llvm::errs() << "ExecutionContext: use of undefined symbol '"
                 << mangled_name << "'!\n";
  }

  // Avoid "ISO C++ forbids casting between pointer-to-function and
  // pointer-to-object":
  return (void*)reinterpret_cast<size_t>(unresolvedSymbol);
}

void*
ExecutionContext::NotifyLazyFunctionCreators(const std::string& mangled_name)
{
  for (std::vector<LazyFunctionCreatorFunc_t>::iterator it
         = m_lazyFuncCreator.begin(), et = m_lazyFuncCreator.end();
       it != et; ++it) {
    void* ret = (void*)((LazyFunctionCreatorFunc_t)*it)(mangled_name);
    if (ret)
      return ret;
  }

  if (m_LazyFuncCreatorDiagsSuppressed)
    return 0;

  return HandleMissingFunction(mangled_name);
}

static void
freeCallersOfUnresolvedSymbols(llvm::SmallVectorImpl<llvm::Function*>&
                               funcsToFree, llvm::ExecutionEngine* engine) {
  llvm::SmallPtrSet<llvm::Function*, 40> funcsToFreeUnique;
  for (size_t i = 0; i < funcsToFree.size(); ++i) {
    llvm::Function* func = funcsToFree[i];
    assert(func && "Cannot free NULL function");
    if (funcsToFreeUnique.insert(func)) {
      for (llvm::Value::use_iterator IU = func->use_begin(),
             EU = func->use_end(); IU != EU; ++IU) {
        llvm::Instruction* instUser = llvm::dyn_cast<llvm::Instruction>(*IU);
        if (!instUser) continue;
        if (!instUser->getParent()) continue;
        if (llvm::Function* userFunc = instUser->getParent()->getParent())
          funcsToFree.push_back(userFunc);
      }
    }
  }
  for (llvm::SmallPtrSet<llvm::Function*, 40>::iterator
         I = funcsToFreeUnique.begin(), E = funcsToFreeUnique.end();
       I != E; ++I) {
    // This should force the JIT to recompile the function. But the stubs stay,
    // and the JIT reuses the stubs now pointing nowhere, i.e. without updating
    // the machine code address. Fix the JIT, or hope that MCJIT helps.
    //engine->freeMachineCodeForFunction(*I);
    engine->updateGlobalMapping(*I, 0);
  }
}

ExecutionContext::ExecutionResult
ExecutionContext::executeFunction(llvm::StringRef funcname,
                                  const clang::ASTContext& Ctx,
                                  clang::QualType retType,
                                  StoredValueRef* returnValue)
{
  // Call a function without arguments, or with an SRet argument, see SRet below

  if (!m_CxaAtExitRemapped) {
    // Rewire atexit:
    llvm::Function* atExit = m_engine->FindFunctionNamed("__cxa_atexit");
    llvm::Function* clingAtExit
      = m_engine->FindFunctionNamed("cling_cxa_atexit");
    if (atExit && clingAtExit) {
      void* clingAtExitAddr = m_engine->getPointerToFunction(clingAtExit);
      assert(clingAtExitAddr && "cannot find cling_cxa_atexit");
      m_engine->updateGlobalMapping(atExit, clingAtExitAddr);
      m_CxaAtExitRemapped = true;
    }
  }

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  llvm::Function* f = m_engine->FindFunctionNamed(funcname.str().c_str());
  if (!f) {
    llvm::errs() << "ExecutionContext::executeFunction: "
      "could not find function named " << funcname << '\n';
    return kExeFunctionNotCompiled;
  }
  m_engine->getPointerToFunction(f);
  // check if there is any unresolved symbol in the list
  if (!m_unresolvedSymbols.empty()) {
    llvm::SmallVector<llvm::Function*, 100> funcsToFree;
    for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
           e = m_unresolvedSymbols.end(); i != e; ++i) {
      llvm::errs() << "ExecutionContext::executeFunction: symbol '" << *i
                   << "' unresolved while linking function '" << funcname
                   << "'!\n";
      llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
      // i could also reference a global variable, in which case ff == 0.
      if (ff)
        funcsToFree.push_back(ff);
    }
    freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
    m_unresolvedSymbols.clear();
    return kExeUnresolvedSymbols;
  }

  std::vector<llvm::GenericValue> args;
  bool wantReturn = (returnValue);
  StoredValueRef aggregateRet;

  if (f->hasStructRetAttr()) {
    // Function expects to receive the storage for the returned aggregate as
    // first argument. Allocate returnValue:
    aggregateRet = StoredValueRef::allocate(Ctx, retType, f->getReturnType());
    if (returnValue) {
      *returnValue = aggregateRet;
    } else {
      returnValue = &aggregateRet;
    }
    args.push_back(returnValue->get().getGV());
    // will get set as arg0, must not assign.
    wantReturn = false;
  }

  if (wantReturn) {
    llvm::GenericValue gvRet = m_engine->runFunction(f, args);
    // rescue the ret value (which might be aggregate) from the stack
    *returnValue = StoredValueRef::bitwiseCopy(Ctx, Value(gvRet, retType));
  } else {
    m_engine->runFunction(f, args);
  }

  return kExeSuccess;
}

ExecutionContext::ExecutionResult
ExecutionContext::runStaticInitializersOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  if (m_RunningStaticInits)
     return kExeSuccess;

  llvm::GlobalVariable* GV
     = m->getGlobalVariable("llvm.global_ctors", true);
  // Nothing to do is good, too.
  if (!GV) return kExeSuccess;

  // Close similarity to
  // m_engine->runStaticConstructorsDestructors(false) aka
  // llvm::ExecutionEngine::runStaticConstructorsDestructors()
  // is intentional; we do an extra pass to check whether the JIT
  // managed to collect all the symbols needed by the niitializers.
  // Should be an array of '{ i32, void ()* }' structs.  The first value is
  // the init priority, which we ignore.
  llvm::ConstantArray *InitList
    = llvm::dyn_cast<llvm::ConstantArray>(GV->getInitializer());
  if (InitList == 0)
    return kExeSuccess;

  m_RunningStaticInits = true;

  // We don't care whether something was unresolved before.
  m_unresolvedSymbols.clear();

  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
    llvm::ConstantStruct *CS
      = llvm::dyn_cast<llvm::ConstantStruct>(InitList->getOperand(i));
    if (CS == 0) continue;

    llvm::Constant *FP = CS->getOperand(1);
    if (FP->isNullValue())
      continue;  // Found a sentinal value, ignore.

    // Strip off constant expression casts.
    if (llvm::ConstantExpr *CE = llvm::dyn_cast<llvm::ConstantExpr>(FP))
      if (CE->isCast())
        FP = CE->getOperand(0);

    // Execute the ctor/dtor function!
    if (llvm::Function *F = llvm::dyn_cast<llvm::Function>(FP)) {
      m_engine->getPointerToFunction(F);
      // check if there is any unresolved symbol in the list
      if (!m_unresolvedSymbols.empty()) {
        llvm::SmallVector<llvm::Function*, 100> funcsToFree;
        for (std::set<std::string>::const_iterator i = m_unresolvedSymbols.begin(),
               e = m_unresolvedSymbols.end(); i != e; ++i) {
          llvm::errs() << "ExecutionContext::runStaticInitializersOnce: symbol '" << *i
                       << "' unresolved while linking static initializer '"
                       << F->getName() << "'!\n";
          llvm::Function *ff = m_engine->FindFunctionNamed(i->c_str());
          assert(ff && "cannot find function to free");
          funcsToFree.push_back(ff);
        }
        freeCallersOfUnresolvedSymbols(funcsToFree, m_engine.get());
        m_unresolvedSymbols.clear();
        m_RunningStaticInits = false;
        return kExeUnresolvedSymbols;
      }
      m_engine->runFunction(F, std::vector<llvm::GenericValue>());
    }
  }

  GV->eraseFromParent();

  m_RunningStaticInits = false;
  return kExeSuccess;
}

void
ExecutionContext::runStaticDestructorsOnce(llvm::Module* m) {
  assert(m && "Module must not be null");
  assert(m_engine && "Code generation did not create an engine!");

  llvm::GlobalVariable* gdtors
    = m->getGlobalVariable("llvm.global_dtors", true);
  if (gdtors) {
    m_engine->runStaticConstructorsDestructors(true);
  }

  // 'Unload' the cxa_atexit entities.
  for (size_t I = 0, E = m_AtExitFuncs.size(); I < E; ++I) {
    const CXAAtExitElement& AEE = m_AtExitFuncs[E-I-1];
    (*AEE.m_Func)(AEE.m_Arg);
  }
  m_AtExitFuncs.clear();
}

int
ExecutionContext::verifyModule(llvm::Module* m)
{
  //
  //  Verify generated module.
  //
  bool mod_has_errs = llvm::verifyModule(*m, llvm::PrintMessageAction);
  if (mod_has_errs) {
    return 1;
  }
  return 0;
}

void
ExecutionContext::printModule(llvm::Module* m)
{
  //
  //  Print module LLVM code in human-readable form.
  //
  llvm::PassManager PM;
  PM.add(llvm::createPrintModulePass(&llvm::errs()));
  PM.run(*m);
}

void
ExecutionContext::installLazyFunctionCreator(LazyFunctionCreatorFunc_t fp)
{
  m_lazyFuncCreator.push_back(fp);
}

bool ExecutionContext::addSymbol(const char* symbolName,  void* symbolAddress) {

  void* actualAddress
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (actualAddress)
    return false;

  llvm::sys::DynamicLibrary::AddSymbol(symbolName, symbolAddress);
  return true;
}

void* ExecutionContext::getAddressOfGlobal(llvm::Module* m,
                                           const char* symbolName,
                                           bool* fromJIT /*=0*/) const {
  // Return a symbol's address, and whether it was jitted.
  void* address
    = llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(symbolName);
  if (address) {
    if (fromJIT) *fromJIT = false;
  } else {
    if (fromJIT) *fromJIT = true;
    llvm::GlobalVariable* gvar = m->getGlobalVariable(symbolName, true);
    if (!gvar)
      return 0;

    address = m_engine->getPointerToGlobal(gvar);
  }
  return address;
}
<|endoftext|>


<commit_before>
// =================================================================================================
// This file is part of the CLBlast project. The project is licensed under Apache Version 2.0. This
// project loosely follows the Google C++ styleguide and uses a tab-size of two spaces and a max-
// width of 100 characters per line.
//
// Author(s):
//   Cedric Nugteren <www.cedricnugteren.nl>
//
// This file uses the auto-tuner to tune the xgemm OpenCL kernels.
//
// =================================================================================================

#include "tuning/kernels/xgemm.hpp"

// Shortcuts to the clblast namespace
using half = clblast::half;
using float2 = clblast::float2;
using double2 = clblast::double2;

// Function to tune a specific variation V (not within the clblast namespace)
template <int V>
void StartVariation(int argc, char *argv[]) {
  const auto command_line_args = clblast::RetrieveCommandLineArguments(argc, argv);
  switch(clblast::GetPrecision(command_line_args)) {
    case clblast::Precision::kHalf: clblast::Tuner<half>(argc, argv, V, clblast::XgemmGetTunerDefaults, clblast::XgemmGetTunerSettings<half>, clblast::XgemmTestValidArguments<half>, clblast::XgemmSetConstraints, clblast::XgemmComputeLocalMemSize<half>, clblast::XgemmSetArguments<half>); break;
    case clblast::Precision::kSingle: clblast::Tuner<float>(argc, argv, V, clblast::XgemmGetTunerDefaults, clblast::XgemmGetTunerSettings<float>, clblast::XgemmTestValidArguments<float>, clblast::XgemmSetConstraints, clblast::XgemmComputeLocalMemSize<float>, clblast::XgemmSetArguments<float>); break;
    case clblast::Precision::kDouble: clblast::Tuner<double>(argc, argv, V, clblast::XgemmGetTunerDefaults, clblast::XgemmGetTunerSettings<double>, clblast::XgemmTestValidArguments<double>, clblast::XgemmSetConstraints, clblast::XgemmComputeLocalMemSize<double>, clblast::XgemmSetArguments<double>); break;
    case clblast::Precision::kComplexSingle: clblast::Tuner<float2>(argc, argv, V, clblast::XgemmGetTunerDefaults, clblast::XgemmGetTunerSettings<float2>, clblast::XgemmTestValidArguments<float2>, clblast::XgemmSetConstraints, clblast::XgemmComputeLocalMemSize<float2>, clblast::XgemmSetArguments<float2>); break;
    case clblast::Precision::kComplexDouble: clblast::Tuner<double2>(argc, argv, V, clblast::XgemmGetTunerDefaults, clblast::XgemmGetTunerSettings<double2>, clblast::XgemmTestValidArguments<double2>, clblast::XgemmSetConstraints, clblast::XgemmComputeLocalMemSize<double2>, clblast::XgemmSetArguments<double2>); break;
  }
}

// Main function (not within the clblast namespace)
int main(int argc, char *argv[]) {
  //StartVariation<1>(argc, argv);
  //StartVariation<2>(argc, argv);
  StartVariation<11>(argc, argv);
  StartVariation<12>(argc, argv);
  return 0;
}

// =================================================================================================
<commit_msg>forgot to add test cases back in, oops<commit_after>
// =================================================================================================
// This file is part of the CLBlast project. The project is licensed under Apache Version 2.0. This
// project loosely follows the Google C++ styleguide and uses a tab-size of two spaces and a max-
// width of 100 characters per line.
//
// Author(s):
//   Cedric Nugteren <www.cedricnugteren.nl>
//
// This file uses the auto-tuner to tune the xgemm OpenCL kernels.
//
// =================================================================================================

#include "tuning/kernels/xgemm.hpp"

// Shortcuts to the clblast namespace
using half = clblast::half;
using float2 = clblast::float2;
using double2 = clblast::double2;

// Function to tune a specific variation V (not within the clblast namespace)
template <int V>
void StartVariation(int argc, char *argv[]) {
  const auto command_line_args = clblast::RetrieveCommandLineArguments(argc, argv);
  switch(clblast::GetPrecision(command_line_args)) {
    case clblast::Precision::kHalf: clblast::Tuner<half>(argc, argv, V, clblast::XgemmGetTunerDefaults, clblast::XgemmGetTunerSettings<half>, clblast::XgemmTestValidArguments<half>, clblast::XgemmSetConstraints, clblast::XgemmComputeLocalMemSize<half>, clblast::XgemmSetArguments<half>); break;
    case clblast::Precision::kSingle: clblast::Tuner<float>(argc, argv, V, clblast::XgemmGetTunerDefaults, clblast::XgemmGetTunerSettings<float>, clblast::XgemmTestValidArguments<float>, clblast::XgemmSetConstraints, clblast::XgemmComputeLocalMemSize<float>, clblast::XgemmSetArguments<float>); break;
    case clblast::Precision::kDouble: clblast::Tuner<double>(argc, argv, V, clblast::XgemmGetTunerDefaults, clblast::XgemmGetTunerSettings<double>, clblast::XgemmTestValidArguments<double>, clblast::XgemmSetConstraints, clblast::XgemmComputeLocalMemSize<double>, clblast::XgemmSetArguments<double>); break;
    case clblast::Precision::kComplexSingle: clblast::Tuner<float2>(argc, argv, V, clblast::XgemmGetTunerDefaults, clblast::XgemmGetTunerSettings<float2>, clblast::XgemmTestValidArguments<float2>, clblast::XgemmSetConstraints, clblast::XgemmComputeLocalMemSize<float2>, clblast::XgemmSetArguments<float2>); break;
    case clblast::Precision::kComplexDouble: clblast::Tuner<double2>(argc, argv, V, clblast::XgemmGetTunerDefaults, clblast::XgemmGetTunerSettings<double2>, clblast::XgemmTestValidArguments<double2>, clblast::XgemmSetConstraints, clblast::XgemmComputeLocalMemSize<double2>, clblast::XgemmSetArguments<double2>); break;
  }
}

// Main function (not within the clblast namespace)
int main(int argc, char *argv[]) {
  StartVariation<1>(argc, argv);
  StartVariation<2>(argc, argv);
  StartVariation<11>(argc, argv);
  StartVariation<12>(argc, argv);
  return 0;
}

// =================================================================================================
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "desktopprocesssignaloperation.h"

#include "localprocesslist.h"

#include <utils/winutils.h>

#include <QDir>

#ifdef Q_OS_WIN
#define _WIN32_WINNT 0x0502
#include <windows.h>
#ifndef PROCESS_SUSPEND_RESUME
#define PROCESS_SUSPEND_RESUME 0x0800
#endif // PROCESS_SUSPEND_RESUME
#else // Q_OS_WIN
#include <errno.h>
#include <signal.h>
#endif // else Q_OS_WIN

namespace ProjectExplorer {

void DesktopProcessSignalOperation::killProcess(int pid)
{
    killProcessSilently(pid);
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::killProcess(const QString &filePath)
{
    m_errorMessage.clear();
    foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) {
        if (process.cmdLine == filePath)
            killProcessSilently(process.pid);
    }
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::interruptProcess(int pid)
{
    m_errorMessage.clear();
    interruptProcessSilently(pid);
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::interruptProcess(const QString &filePath)
{
    interruptProcess(filePath, NoSpecialInterrupt);
}

void DesktopProcessSignalOperation::interruptProcess(int pid, SpecialInterrupt specialInterrupt)
{
    m_errorMessage.clear();
    interruptProcessSilently(pid, specialInterrupt);
}

void DesktopProcessSignalOperation::interruptProcess(const QString &filePath,
                                                     SpecialInterrupt specialInterrupt)
{
    m_errorMessage.clear();
    foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) {
        if (process.cmdLine == filePath)
            interruptProcessSilently(process.pid, specialInterrupt);
    }
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::appendMsgCannotKill(int pid, const QString &why)
{
    if (!m_errorMessage.isEmpty())
        m_errorMessage += QChar::fromLatin1('\n');
    m_errorMessage += tr("Cannot kill process with pid %1: %3 ").arg(pid).arg(why);
}

void DesktopProcessSignalOperation::appendMsgCannotInterrupt(int pid, const QString &why)
{
    if (!m_errorMessage.isEmpty())
        m_errorMessage += QChar::fromLatin1('\n');
    m_errorMessage += tr("Cannot interrupt process with pid %1: %3 ").arg(pid).arg(why);
}

void DesktopProcessSignalOperation::killProcessSilently(int pid)
{
#ifdef Q_OS_WIN
    const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION
            |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ
            |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
    if (const HANDLE handle = OpenProcess(rights, FALSE, pid)) {
        if (!TerminateProcess(handle, UINT(-1)))
            appendMsgCannotKill(pid, Utils::winErrorMessage(GetLastError()));
        CloseHandle(handle);
    } else {
        appendMsgCannotKill(pid, tr("Cannot open process."));
    }
#else
    if (pid <= 0)
        appendMsgCannotKill(pid, tr("Invalid process id."));
    else if (kill(pid, SIGKILL))
        appendMsgCannotKill(pid, QString::fromLocal8Bit(strerror(errno)));
#endif // Q_OS_WIN
}

void DesktopProcessSignalOperation::interruptProcessSilently(
        int pid, SpecialInterrupt specialInterrupt)
{
#ifdef Q_OS_WIN
    /*
    Windows 64 bit has a 32 bit subsystem (WOW64) which makes it possible to run a
    32 bit application inside a 64 bit environment.
    When GDB is used DebugBreakProcess must be called from the same system (32/64 bit) running
    the inferior. If CDB is used we could in theory break wow64 processes,
    but the break is actually a wow64 breakpoint. CDB is configured to ignore these
    breakpoints, because they also appear on module loading.
    Therefore we need helper executables (win(32/64)interrupt.exe) on Windows 64 bit calling
    DebugBreakProcess from the correct system.

    DebugBreak matrix for windows

    Api = UseDebugBreakApi
    Win64 = UseWin64InterruptHelper
    Win32 = UseWin32InterruptHelper
    N/A = This configuration is not possible

          | Windows 32bit   | Windows 64bit
          | QtCreator 32bit | QtCreator 32bit                   | QtCreator 64bit
          | Inferior 32bit  | Inferior 32bit  | Inferior 64bit  | Inferior 32bit  | Inferior 64bit
----------|-----------------|-----------------|-----------------|-----------------|----------------
CDB 32bit | Api             | Api             | N/A             | Win32           | N/A
    64bit | N/A             | Win64           | Win64           | Api             | Api
----------|-----------------|-----------------|-----------------|-----------------|----------------
GDB 32bit | Api             | Api             | N/A             | Win32           | N/A
    64bit | N/A             | N/A             | Win64           | N/A             | Api
----------|-----------------|-----------------|-----------------|-----------------|----------------

    */
    HANDLE inferior = NULL;
    do {
        const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION
                |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ
                |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
        inferior = OpenProcess(rights, FALSE, pid);
        if (inferior == NULL) {
            appendMsgCannotInterrupt(pid, tr("Cannot open process: %1")
                                     + Utils::winErrorMessage(GetLastError()));
            break;
        }
        bool creatorIs64Bit = Utils::winIs64BitBinary(qApp->applicationFilePath());
        if (!Utils::winIs64BitSystem() ||
                specialInterrupt == NoSpecialInterrupt ||
                specialInterrupt == Win64Interrupt && creatorIs64Bit ||
                specialInterrupt == Win32Interrupt && !creatorIs64Bit) {
            if (!DebugBreakProcess(inferior)) {
                appendMsgCannotInterrupt(pid, tr("DebugBreakProcess failed: ")
                                         + Utils::winErrorMessage(GetLastError()));
            }
        } else if (specialInterrupt == Win32Interrupt
                   || specialInterrupt == Win64Interrupt) {
            QString executable = QCoreApplication::applicationDirPath();
            executable += specialInterrupt == Win32Interrupt
                    ? QLatin1String("/win32interrupt.exe")
                    : QLatin1String("/win64interrupt.exe");
            if (!QFile::exists(executable)) {
                appendMsgCannotInterrupt(pid, tr( "%1 does not exist. If you have built QtCreator "
                                                  "on your own ,checkout http://qt.gitorious.org/"
                                                  "qt-creator/binary-artifacts.").
                                         arg(QDir::toNativeSeparators(executable)));
            }
            switch (QProcess::execute(executable, QStringList(QString::number(pid)))) {
            case -2:
                appendMsgCannotInterrupt(pid, tr(
                            "Cannot start %1. Check src\\tools\\win64interrupt\\win64interrupt.c "
                            "for more information.").arg(QDir::toNativeSeparators(executable)));
                break;
            case 0:
                break;
            default:
                appendMsgCannotInterrupt(pid, QDir::toNativeSeparators(executable)
                                         + tr(" could not break the process."));
                break;
            }
        }
    } while (false);
    if (inferior != NULL)
        CloseHandle(inferior);
#else
    Q_UNUSED(specialInterrupt)
    if (pid <= 0)
        appendMsgCannotInterrupt(pid, tr("Invalid process id."));
    else if (kill(pid, SIGINT))
        appendMsgCannotInterrupt(pid, QString::fromLocal8Bit(strerror(errno)));
#endif // Q_OS_WIN
}

} // namespace ProjectExplorer
<commit_msg>ProjectExplorer: Fix build.<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "desktopprocesssignaloperation.h"

#include "localprocesslist.h"

#include <utils/winutils.h>

#include <QCoreApplication>
#include <QDir>

#ifdef Q_OS_WIN
#define _WIN32_WINNT 0x0502
#include <windows.h>
#ifndef PROCESS_SUSPEND_RESUME
#define PROCESS_SUSPEND_RESUME 0x0800
#endif // PROCESS_SUSPEND_RESUME
#else // Q_OS_WIN
#include <errno.h>
#include <signal.h>
#endif // else Q_OS_WIN

namespace ProjectExplorer {

void DesktopProcessSignalOperation::killProcess(int pid)
{
    killProcessSilently(pid);
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::killProcess(const QString &filePath)
{
    m_errorMessage.clear();
    foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) {
        if (process.cmdLine == filePath)
            killProcessSilently(process.pid);
    }
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::interruptProcess(int pid)
{
    m_errorMessage.clear();
    interruptProcessSilently(pid);
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::interruptProcess(const QString &filePath)
{
    interruptProcess(filePath, NoSpecialInterrupt);
}

void DesktopProcessSignalOperation::interruptProcess(int pid, SpecialInterrupt specialInterrupt)
{
    m_errorMessage.clear();
    interruptProcessSilently(pid, specialInterrupt);
}

void DesktopProcessSignalOperation::interruptProcess(const QString &filePath,
                                                     SpecialInterrupt specialInterrupt)
{
    m_errorMessage.clear();
    foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) {
        if (process.cmdLine == filePath)
            interruptProcessSilently(process.pid, specialInterrupt);
    }
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::appendMsgCannotKill(int pid, const QString &why)
{
    if (!m_errorMessage.isEmpty())
        m_errorMessage += QChar::fromLatin1('\n');
    m_errorMessage += tr("Cannot kill process with pid %1: %3 ").arg(pid).arg(why);
}

void DesktopProcessSignalOperation::appendMsgCannotInterrupt(int pid, const QString &why)
{
    if (!m_errorMessage.isEmpty())
        m_errorMessage += QChar::fromLatin1('\n');
    m_errorMessage += tr("Cannot interrupt process with pid %1: %3 ").arg(pid).arg(why);
}

void DesktopProcessSignalOperation::killProcessSilently(int pid)
{
#ifdef Q_OS_WIN
    const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION
            |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ
            |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
    if (const HANDLE handle = OpenProcess(rights, FALSE, pid)) {
        if (!TerminateProcess(handle, UINT(-1)))
            appendMsgCannotKill(pid, Utils::winErrorMessage(GetLastError()));
        CloseHandle(handle);
    } else {
        appendMsgCannotKill(pid, tr("Cannot open process."));
    }
#else
    if (pid <= 0)
        appendMsgCannotKill(pid, tr("Invalid process id."));
    else if (kill(pid, SIGKILL))
        appendMsgCannotKill(pid, QString::fromLocal8Bit(strerror(errno)));
#endif // Q_OS_WIN
}

void DesktopProcessSignalOperation::interruptProcessSilently(
        int pid, SpecialInterrupt specialInterrupt)
{
#ifdef Q_OS_WIN
    /*
    Windows 64 bit has a 32 bit subsystem (WOW64) which makes it possible to run a
    32 bit application inside a 64 bit environment.
    When GDB is used DebugBreakProcess must be called from the same system (32/64 bit) running
    the inferior. If CDB is used we could in theory break wow64 processes,
    but the break is actually a wow64 breakpoint. CDB is configured to ignore these
    breakpoints, because they also appear on module loading.
    Therefore we need helper executables (win(32/64)interrupt.exe) on Windows 64 bit calling
    DebugBreakProcess from the correct system.

    DebugBreak matrix for windows

    Api = UseDebugBreakApi
    Win64 = UseWin64InterruptHelper
    Win32 = UseWin32InterruptHelper
    N/A = This configuration is not possible

          | Windows 32bit   | Windows 64bit
          | QtCreator 32bit | QtCreator 32bit                   | QtCreator 64bit
          | Inferior 32bit  | Inferior 32bit  | Inferior 64bit  | Inferior 32bit  | Inferior 64bit
----------|-----------------|-----------------|-----------------|-----------------|----------------
CDB 32bit | Api             | Api             | N/A             | Win32           | N/A
    64bit | N/A             | Win64           | Win64           | Api             | Api
----------|-----------------|-----------------|-----------------|-----------------|----------------
GDB 32bit | Api             | Api             | N/A             | Win32           | N/A
    64bit | N/A             | N/A             | Win64           | N/A             | Api
----------|-----------------|-----------------|-----------------|-----------------|----------------

    */
    HANDLE inferior = NULL;
    do {
        const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION
                |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ
                |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
        inferior = OpenProcess(rights, FALSE, pid);
        if (inferior == NULL) {
            appendMsgCannotInterrupt(pid, tr("Cannot open process: %1")
                                     + Utils::winErrorMessage(GetLastError()));
            break;
        }
        bool creatorIs64Bit = Utils::winIs64BitBinary(qApp->applicationFilePath());
        if (!Utils::winIs64BitSystem() ||
                specialInterrupt == NoSpecialInterrupt ||
                specialInterrupt == Win64Interrupt && creatorIs64Bit ||
                specialInterrupt == Win32Interrupt && !creatorIs64Bit) {
            if (!DebugBreakProcess(inferior)) {
                appendMsgCannotInterrupt(pid, tr("DebugBreakProcess failed: ")
                                         + Utils::winErrorMessage(GetLastError()));
            }
        } else if (specialInterrupt == Win32Interrupt
                   || specialInterrupt == Win64Interrupt) {
            QString executable = QCoreApplication::applicationDirPath();
            executable += specialInterrupt == Win32Interrupt
                    ? QLatin1String("/win32interrupt.exe")
                    : QLatin1String("/win64interrupt.exe");
            if (!QFile::exists(executable)) {
                appendMsgCannotInterrupt(pid, tr( "%1 does not exist. If you have built QtCreator "
                                                  "on your own ,checkout http://qt.gitorious.org/"
                                                  "qt-creator/binary-artifacts.").
                                         arg(QDir::toNativeSeparators(executable)));
            }
            switch (QProcess::execute(executable, QStringList(QString::number(pid)))) {
            case -2:
                appendMsgCannotInterrupt(pid, tr(
                            "Cannot start %1. Check src\\tools\\win64interrupt\\win64interrupt.c "
                            "for more information.").arg(QDir::toNativeSeparators(executable)));
                break;
            case 0:
                break;
            default:
                appendMsgCannotInterrupt(pid, QDir::toNativeSeparators(executable)
                                         + tr(" could not break the process."));
                break;
            }
        }
    } while (false);
    if (inferior != NULL)
        CloseHandle(inferior);
#else
    Q_UNUSED(specialInterrupt)
    if (pid <= 0)
        appendMsgCannotInterrupt(pid, tr("Invalid process id."));
    else if (kill(pid, SIGINT))
        appendMsgCannotInterrupt(pid, QString::fromLocal8Bit(strerror(errno)));
#endif // Q_OS_WIN
}

} // namespace ProjectExplorer
<|endoftext|>


<commit_before>//*******************************************************************
// Copyright (C) 2012  Centre National Etudes Spatiales
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// Author : Mickael Savinaud (mickael.savinaud@c-s.fr)
//
// Description:
//
// Contains definition of class ossimPleiadesModel
//
//*****************************************************************************

#include "ossimPleiadesModel.h"

#include <cmath>
#include <cstdio>

#include <ossimPleiadesModel.h>
#include <ossimPleiadesDimapSupportData.h>

#include <ossimPluginCommon.h>

#include <ossim/base/ossimCommon.h>
#include <ossim/base/ossimFilename.h>
#include <ossim/base/ossimKeywordNames.h>
#include <ossim/base/ossimNotify.h>
#include <ossim/base/ossimRefPtr.h>
#include <ossim/base/ossimString.h>
#include <ossim/base/ossimTrace.h>
#include <ossim/base/ossimXmlDocument.h>
#include <ossim/base/ossimXmlNode.h>
#include <ossim/support_data/ossimSupportFilesList.h>

namespace ossimplugins
{

// Define Trace flags for use within this file:
   static ossimTrace traceExec  ("ossimPleiadesModel:exec");
   static ossimTrace traceDebug ("ossimPleiadesModel:debug");

   RTTI_DEF1(ossimPleiadesModel, "ossimPleiadesModel", ossimRpcModel);

//*************************************************************************************************
// Constructor
//*************************************************************************************************
   ossimPleiadesModel::ossimPleiadesModel()
      :ossimRpcModel      (),
       theSupportData        (0)
   {
      for (unsigned int i = 0; i < 20; i++)
      {
         theLineDenCoef[i] = 0.0;
         theLineNumCoef[i] = 0.0;
         theSampNumCoef[i] = 0.0;
         theSampDenCoef[i] = 0.0;
      }
   }

//*************************************************************************************************
// Constructor
//*************************************************************************************************
   ossimPleiadesModel::ossimPleiadesModel(const ossimPleiadesModel& rhs)
      :ossimRpcModel      (rhs),
       theSupportData        (0)
   {
   }

//*************************************************************************************************
// Destructor
//*************************************************************************************************
   ossimPleiadesModel::~ossimPleiadesModel()
   {
      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG DESTRUCTOR: ~ossimPleiadesModel(): entering..." << std::endl;

      theSupportData = 0;

      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG DESTRUCTOR: ~ossimPleiadesModel(): returning..." << std::endl;
   }
//*************************************************************************************************
// Infamous DUP
//*************************************************************************************************
   ossimObject* ossimPleiadesModel::dup() const
   {
      return new ossimPleiadesModel(*this);
   }

//*************************************************************************************************
// Print
//*************************************************************************************************
   std::ostream& ossimPleiadesModel::print(std::ostream& out) const
   {
      // Capture stream flags since we are going to mess with them.
      std::ios_base::fmtflags f = out.flags();

      out << "\nDump of ossimPleiadesModel at address " << (hex) << this
          << (dec)
          << "\n------------------------------------------------"
          << "\n  theImageID            = " << theImageID
          << "\n  theImageSize          = " << theImageSize
          << "\n  theRefGndPt           = " << theRefGndPt
          << "\n  theRefImgPt           = " << theRefImgPt
          << "\n  theProcessingLevel    = " << theSupportData->getProcessingLevel()
          << "\n------------------------------------------------"
          << "\n  " << endl;

      // Set the flags back.
      out.flags(f);

      if (theSupportData->getProcessingLevel() == "SENSOR")
         return ossimRpcModel::print(out);
      else
         return out;
   }

//*************************************************************************************************
// Save State
//*************************************************************************************************
   bool ossimPleiadesModel::saveState(ossimKeywordlist& kwl,
                                      const char* prefix) const
   {
      if(theSupportData.valid())
      {
         ossimString supportPrefix = ossimString(prefix) + "support_data.";
         theSupportData->saveState(kwl, supportPrefix);
      }

      // If only it is a sensor product we save parameters from RPC model, its avoid to
      // propagate a empty RPC model
      if (theSupportData->getProcessingLevel() == "SENSOR")
      {
         ossimRpcModel::saveState(kwl, prefix);
         return true;
      }
      else
      {
         kwl.add(prefix, "sensor", theSensorID, true);
         return true;
      }
   }

//*************************************************************************************************
// Load State
//*************************************************************************************************
   bool ossimPleiadesModel::loadState(const ossimKeywordlist& kwl,
                                      const char* prefix)
   {
      if(!theSupportData)
      {
         theSupportData = new ossimPleiadesDimapSupportData;
      }

      ossimString supportPrefix = ossimString(prefix) + "support_data.";
      theSupportData->loadState(kwl, supportPrefix);

      // If only it is a sensor product we load parameters from RPC model only, its avoid to
      // add a empty RPC model
      if (theSupportData->getProcessingLevel() == "SENSOR")
      {
         ossimRpcModel::loadState(kwl, prefix);
         return true;
      }
      else
      {
         return true;
      }
   }

   bool
   ossimPleiadesModel::open(const ossimFilename& file)
   {
      static const char MODULE[] = "ossimPleiadesModel::open";
      //traceDebug.setTraceFlag(true);

      if (traceDebug())
      {
         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
      }

      // Make the gsd nan so it gets computed.
      theGSD.makeNan();

      bool result = false;

      // Filename used.
      ossimFilename DIMxmlFile;
      ossimFilename RPCxmlFile;

      // Generate metadata and rpc filename
      if ( (file.ext().downcase() != "jp2" && file.ext().downcase() != "tif")
          || !file.exists())
      {
         //not a valid file
         return false;
      }
      else
      {
        // DIMAPv1
        ossimFilename DIMv1xmlFileTmp = file;
        DIMv1xmlFileTmp.setFile("PHRDIMAP");
        DIMv1xmlFileTmp.setExtension("XML");

        if (DIMv1xmlFileTmp.exists())
          {
          DIMxmlFile = DIMv1xmlFileTmp;
          RPCxmlFile = DIMv1xmlFileTmp;
          }
        else
          {
          // DIMAPv2
          DIMxmlFile = file.path();
          RPCxmlFile = file.path();
          ossimFilename DIMxmlFileTmp = file.file();
          ossimFilename RPCxmlFileTmp;

          DIMxmlFileTmp = DIMxmlFileTmp.file().replaceStrThatMatch("^IMG_", "DIM_");
          DIMxmlFileTmp = DIMxmlFileTmp.replaceStrThatMatch("_R[0-9]+C[0-9]+\\.(JP2|TIF)$", ".XML");
          // Check if it is an XML extension
          if( DIMxmlFileTmp.ext() != "xml")
            return false;

          RPCxmlFileTmp = DIMxmlFileTmp.file().replaceStrThatMatch("^DIM_", "RPC_");

          DIMxmlFile = DIMxmlFile.dirCat(DIMxmlFileTmp);
          RPCxmlFile = RPCxmlFile.dirCat(RPCxmlFileTmp);
          }

        if (!DIMxmlFile.exists())
        {
          if (traceDebug())
          {
            ossimNotify(ossimNotifyLevel_DEBUG) << "PHR main DIMAP file " << DIMxmlFile << " doesn't exist ...\n";
          }
          return false;
        }
      }

      if (traceDebug())
      {
         ossimNotify(ossimNotifyLevel_DEBUG) << "Metadata xml file: " << DIMxmlFile << "\n";
         ossimNotify(ossimNotifyLevel_DEBUG) << "RPC xml file: " << RPCxmlFile << "\n";
      }

      ossimString processingLevel;
      // Parse the metadata xml file
      if ( !theSupportData.valid() )
         theSupportData = new ossimPleiadesDimapSupportData();

      if(!theSupportData->parseXmlFile(DIMxmlFile))
      {
         theSupportData = 0; // ossimRefPtr
         if (traceDebug())
         {
           ossimNotify(ossimNotifyLevel_DEBUG) << "ossimPleiadesModel::open DEBUG:"
                                               << "\nCould not open correctly DIMAP file" << std::endl;
         }
         return false;
      }

      theSensorID = theSupportData->getSensorID();
      theImageID = theSupportData->getImageID();
      // Get the processing level (ORTHO or SENSOR or perhaps MOSAIC ?)
      processingLevel = theSupportData->getProcessingLevel();

      // Parse the RPC xml file if necessary
      if (RPCxmlFile.exists() && processingLevel == "SENSOR")
      {
         if (!theSupportData->parseXmlFile(RPCxmlFile))
         {
            theSupportData = 0; // ossimRefPtr
            ossimNotify(ossimNotifyLevel_WARN) << "ossimPleiadesModel::open WARNING:"
                                               << "\nCould not open correctly RPC file" << std::endl;
            return false;
         }

         thePolyType = B;

         for (unsigned int i = 0 ; i < 20; i++ )
         {
            theLineNumCoef[i] = theSupportData->getLineNumCoeff()[i];
            theLineDenCoef[i] = theSupportData->getLineDenCoeff()[i];
            theSampNumCoef[i] = theSupportData->getSampNumCoeff()[i];
            theSampDenCoef[i] = theSupportData->getSampDenCoeff()[i];
         }

         theLineScale  = theSupportData->getLineScale();
         theSampScale  = theSupportData->getSampScale();
         theLatScale   = theSupportData->getLatScale();
         theLonScale   = theSupportData->getLonScale();
         theHgtScale   = theSupportData->getHeightScale();
         theLineOffset = theSupportData->getLineOffset();
         theSampOffset = theSupportData->getSampOffset();
         theLatOffset  = theSupportData->getLatOffset();
         theLonOffset  = theSupportData->getLonOffset();
         theHgtOffset  = theSupportData->getHeightOffset();
      }

      // TODO MSD Check if this part is necessary
      _productXmlFile = DIMxmlFile;
      ossimSupportFilesList::instance()->add(_productXmlFile);

      // TODO MSD WARNING File with multi tiles are not well managed
      theSupportData->getImageRect(theImageClipRect);
      theSupportData->getImageSize(theImageSize);

      finishConstruction();
      clearErrorStatus();

      result = true;
      if (traceDebug())
      {
         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exit status = " << (result ? "true" : "false\n") << std::endl;
      }

      /*std::cout << "---------------------------" << std::endl;
        print(std::cout);
        std::cout << "---------------------------" << std::endl;*/
      return result;
   }

//*************************************************************************************************
//! Collects common code among all parsers
//*************************************************************************************************
   void ossimPleiadesModel::finishConstruction()
   {
      theImageSize.line = theImageClipRect.height();
      theImageSize.samp = theImageClipRect.width();
      theRefImgPt.line = theImageClipRect.midPoint().y;
      theRefImgPt.samp = theImageClipRect.midPoint().x;
      theRefGndPt.lat = theLatOffset;
      theRefGndPt.lon = theLonOffset;
      theRefGndPt.hgt = theHgtOffset;

      //---
      // NOTE:  We must call "updateModel()" to set parameter used by base
      // ossimRpcModel prior to calling lineSampleHeightToWorld or all
      // the world points will be same.
      //---
      updateModel();

      ossimGpt v0, v1, v2, v3;
      lineSampleHeightToWorld(theImageClipRect.ul(), theHgtOffset, v0);
      lineSampleHeightToWorld(theImageClipRect.ur(), theHgtOffset, v1);
      lineSampleHeightToWorld(theImageClipRect.lr(), theHgtOffset, v2);
      lineSampleHeightToWorld(theImageClipRect.ll(), theHgtOffset, v3);

      theBoundGndPolygon = ossimPolygon (ossimDpt(v0), ossimDpt(v1), ossimDpt(v2), ossimDpt(v3));

      // Set the ground reference point using the model.
      lineSampleHeightToWorld(theRefImgPt, theHgtOffset, theRefGndPt);

      if( theGSD.hasNans() )
      {
         try
         {
            // This will set theGSD and theMeanGSD. Method throws ossimException.
            computeGsd();
         }
         catch (const ossimException& e)
         {
            ossimNotify(ossimNotifyLevel_WARN)
               << "ossimPleiadesModel::finishConstruction -- caught exception:\n"
               << e.what() << std::endl;
         }
      }
   }

}
<commit_msg>BUG: take care of the case in the test about extension<commit_after>//*******************************************************************
// Copyright (C) 2012  Centre National Etudes Spatiales
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//
// Author : Mickael Savinaud (mickael.savinaud@c-s.fr)
//
// Description:
//
// Contains definition of class ossimPleiadesModel
//
//*****************************************************************************

#include "ossimPleiadesModel.h"

#include <cmath>
#include <cstdio>

#include <ossimPleiadesModel.h>
#include <ossimPleiadesDimapSupportData.h>

#include <ossimPluginCommon.h>

#include <ossim/base/ossimCommon.h>
#include <ossim/base/ossimFilename.h>
#include <ossim/base/ossimKeywordNames.h>
#include <ossim/base/ossimNotify.h>
#include <ossim/base/ossimRefPtr.h>
#include <ossim/base/ossimString.h>
#include <ossim/base/ossimTrace.h>
#include <ossim/base/ossimXmlDocument.h>
#include <ossim/base/ossimXmlNode.h>
#include <ossim/support_data/ossimSupportFilesList.h>

namespace ossimplugins
{

// Define Trace flags for use within this file:
   static ossimTrace traceExec  ("ossimPleiadesModel:exec");
   static ossimTrace traceDebug ("ossimPleiadesModel:debug");

   RTTI_DEF1(ossimPleiadesModel, "ossimPleiadesModel", ossimRpcModel);

//*************************************************************************************************
// Constructor
//*************************************************************************************************
   ossimPleiadesModel::ossimPleiadesModel()
      :ossimRpcModel      (),
       theSupportData        (0)
   {
      for (unsigned int i = 0; i < 20; i++)
      {
         theLineDenCoef[i] = 0.0;
         theLineNumCoef[i] = 0.0;
         theSampNumCoef[i] = 0.0;
         theSampDenCoef[i] = 0.0;
      }
   }

//*************************************************************************************************
// Constructor
//*************************************************************************************************
   ossimPleiadesModel::ossimPleiadesModel(const ossimPleiadesModel& rhs)
      :ossimRpcModel      (rhs),
       theSupportData        (0)
   {
   }

//*************************************************************************************************
// Destructor
//*************************************************************************************************
   ossimPleiadesModel::~ossimPleiadesModel()
   {
      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG DESTRUCTOR: ~ossimPleiadesModel(): entering..." << std::endl;

      theSupportData = 0;

      if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG DESTRUCTOR: ~ossimPleiadesModel(): returning..." << std::endl;
   }
//*************************************************************************************************
// Infamous DUP
//*************************************************************************************************
   ossimObject* ossimPleiadesModel::dup() const
   {
      return new ossimPleiadesModel(*this);
   }

//*************************************************************************************************
// Print
//*************************************************************************************************
   std::ostream& ossimPleiadesModel::print(std::ostream& out) const
   {
      // Capture stream flags since we are going to mess with them.
      std::ios_base::fmtflags f = out.flags();

      out << "\nDump of ossimPleiadesModel at address " << (hex) << this
          << (dec)
          << "\n------------------------------------------------"
          << "\n  theImageID            = " << theImageID
          << "\n  theImageSize          = " << theImageSize
          << "\n  theRefGndPt           = " << theRefGndPt
          << "\n  theRefImgPt           = " << theRefImgPt
          << "\n  theProcessingLevel    = " << theSupportData->getProcessingLevel()
          << "\n------------------------------------------------"
          << "\n  " << endl;

      // Set the flags back.
      out.flags(f);

      if (theSupportData->getProcessingLevel() == "SENSOR")
         return ossimRpcModel::print(out);
      else
         return out;
   }

//*************************************************************************************************
// Save State
//*************************************************************************************************
   bool ossimPleiadesModel::saveState(ossimKeywordlist& kwl,
                                      const char* prefix) const
   {
      if(theSupportData.valid())
      {
         ossimString supportPrefix = ossimString(prefix) + "support_data.";
         theSupportData->saveState(kwl, supportPrefix);
      }

      // If only it is a sensor product we save parameters from RPC model, its avoid to
      // propagate a empty RPC model
      if (theSupportData->getProcessingLevel() == "SENSOR")
      {
         ossimRpcModel::saveState(kwl, prefix);
         return true;
      }
      else
      {
         kwl.add(prefix, "sensor", theSensorID, true);
         return true;
      }
   }

//*************************************************************************************************
// Load State
//*************************************************************************************************
   bool ossimPleiadesModel::loadState(const ossimKeywordlist& kwl,
                                      const char* prefix)
   {
      if(!theSupportData)
      {
         theSupportData = new ossimPleiadesDimapSupportData;
      }

      ossimString supportPrefix = ossimString(prefix) + "support_data.";
      theSupportData->loadState(kwl, supportPrefix);

      // If only it is a sensor product we load parameters from RPC model only, its avoid to
      // add a empty RPC model
      if (theSupportData->getProcessingLevel() == "SENSOR")
      {
         ossimRpcModel::loadState(kwl, prefix);
         return true;
      }
      else
      {
         return true;
      }
   }

   bool
   ossimPleiadesModel::open(const ossimFilename& file)
   {
      static const char MODULE[] = "ossimPleiadesModel::open";
      //traceDebug.setTraceFlag(true);

      if (traceDebug())
      {
         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered...\n";
      }

      // Make the gsd nan so it gets computed.
      theGSD.makeNan();

      bool result = false;

      // Filename used.
      ossimFilename DIMxmlFile;
      ossimFilename RPCxmlFile;

      // Generate metadata and rpc filename
      if ( (file.ext().downcase() != "jp2" && file.ext().downcase() != "tif")
          || !file.exists())
      {
         //not a valid file
         return false;
      }
      else
      {
        // DIMAPv1
        ossimFilename DIMv1xmlFileTmp = file;
        DIMv1xmlFileTmp.setFile("PHRDIMAP");
        DIMv1xmlFileTmp.setExtension("XML");

        if (DIMv1xmlFileTmp.exists())
          {
          DIMxmlFile = DIMv1xmlFileTmp;
          RPCxmlFile = DIMv1xmlFileTmp;
          }
        else
          {
          // DIMAPv2
          DIMxmlFile = file.path();
          RPCxmlFile = file.path();
          ossimFilename DIMxmlFileTmp = file.file();
          ossimFilename RPCxmlFileTmp;

          DIMxmlFileTmp = DIMxmlFileTmp.file().replaceStrThatMatch("^IMG_", "DIM_");
          DIMxmlFileTmp = DIMxmlFileTmp.replaceStrThatMatch("_R[0-9]+C[0-9]+\\.(JP2|TIF)$", ".XML");
          // Check if it is an XML extension
          if( DIMxmlFileTmp.ext() != "xml")
            return false;

          RPCxmlFileTmp = DIMxmlFileTmp.file().replaceStrThatMatch("^DIM_", "RPC_");
          if( DIMxmlFileTmp.ext() != "XML")
            return false;

          DIMxmlFile = DIMxmlFile.dirCat(DIMxmlFileTmp);
          RPCxmlFile = RPCxmlFile.dirCat(RPCxmlFileTmp);
          }

        if (!DIMxmlFile.exists())
        {
          if (traceDebug())
          {
            ossimNotify(ossimNotifyLevel_DEBUG) << "PHR main DIMAP file " << DIMxmlFile << " doesn't exist ...\n";
          }
          return false;
        }
      }

      if (traceDebug())
      {
         ossimNotify(ossimNotifyLevel_DEBUG) << "Metadata xml file: " << DIMxmlFile << "\n";
         ossimNotify(ossimNotifyLevel_DEBUG) << "RPC xml file: " << RPCxmlFile << "\n";
      }

      ossimString processingLevel;
      // Parse the metadata xml file
      if ( !theSupportData.valid() )
         theSupportData = new ossimPleiadesDimapSupportData();

      if(!theSupportData->parseXmlFile(DIMxmlFile))
      {
         theSupportData = 0; // ossimRefPtr
         if (traceDebug())
         {
           ossimNotify(ossimNotifyLevel_DEBUG) << "ossimPleiadesModel::open DEBUG:"
                                               << "\nCould not open correctly DIMAP file" << std::endl;
         }
         return false;
      }

      theSensorID = theSupportData->getSensorID();
      theImageID = theSupportData->getImageID();
      // Get the processing level (ORTHO or SENSOR or perhaps MOSAIC ?)
      processingLevel = theSupportData->getProcessingLevel();

      // Parse the RPC xml file if necessary
      if (RPCxmlFile.exists() && processingLevel == "SENSOR")
      {
         if (!theSupportData->parseXmlFile(RPCxmlFile))
         {
            theSupportData = 0; // ossimRefPtr
            ossimNotify(ossimNotifyLevel_WARN) << "ossimPleiadesModel::open WARNING:"
                                               << "\nCould not open correctly RPC file" << std::endl;
            return false;
         }

         thePolyType = B;

         for (unsigned int i = 0 ; i < 20; i++ )
         {
            theLineNumCoef[i] = theSupportData->getLineNumCoeff()[i];
            theLineDenCoef[i] = theSupportData->getLineDenCoeff()[i];
            theSampNumCoef[i] = theSupportData->getSampNumCoeff()[i];
            theSampDenCoef[i] = theSupportData->getSampDenCoeff()[i];
         }

         theLineScale  = theSupportData->getLineScale();
         theSampScale  = theSupportData->getSampScale();
         theLatScale   = theSupportData->getLatScale();
         theLonScale   = theSupportData->getLonScale();
         theHgtScale   = theSupportData->getHeightScale();
         theLineOffset = theSupportData->getLineOffset();
         theSampOffset = theSupportData->getSampOffset();
         theLatOffset  = theSupportData->getLatOffset();
         theLonOffset  = theSupportData->getLonOffset();
         theHgtOffset  = theSupportData->getHeightOffset();
      }

      // TODO MSD Check if this part is necessary
      _productXmlFile = DIMxmlFile;
      ossimSupportFilesList::instance()->add(_productXmlFile);

      // TODO MSD WARNING File with multi tiles are not well managed
      theSupportData->getImageRect(theImageClipRect);
      theSupportData->getImageSize(theImageSize);

      finishConstruction();
      clearErrorStatus();

      result = true;
      if (traceDebug())
      {
         ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " exit status = " << (result ? "true" : "false\n") << std::endl;
      }

      /*std::cout << "---------------------------" << std::endl;
        print(std::cout);
        std::cout << "---------------------------" << std::endl;*/
      return result;
   }

//*************************************************************************************************
//! Collects common code among all parsers
//*************************************************************************************************
   void ossimPleiadesModel::finishConstruction()
   {
      theImageSize.line = theImageClipRect.height();
      theImageSize.samp = theImageClipRect.width();
      theRefImgPt.line = theImageClipRect.midPoint().y;
      theRefImgPt.samp = theImageClipRect.midPoint().x;
      theRefGndPt.lat = theLatOffset;
      theRefGndPt.lon = theLonOffset;
      theRefGndPt.hgt = theHgtOffset;

      //---
      // NOTE:  We must call "updateModel()" to set parameter used by base
      // ossimRpcModel prior to calling lineSampleHeightToWorld or all
      // the world points will be same.
      //---
      updateModel();

      ossimGpt v0, v1, v2, v3;
      lineSampleHeightToWorld(theImageClipRect.ul(), theHgtOffset, v0);
      lineSampleHeightToWorld(theImageClipRect.ur(), theHgtOffset, v1);
      lineSampleHeightToWorld(theImageClipRect.lr(), theHgtOffset, v2);
      lineSampleHeightToWorld(theImageClipRect.ll(), theHgtOffset, v3);

      theBoundGndPolygon = ossimPolygon (ossimDpt(v0), ossimDpt(v1), ossimDpt(v2), ossimDpt(v3));

      // Set the ground reference point using the model.
      lineSampleHeightToWorld(theRefImgPt, theHgtOffset, theRefGndPt);

      if( theGSD.hasNans() )
      {
         try
         {
            // This will set theGSD and theMeanGSD. Method throws ossimException.
            computeGsd();
         }
         catch (const ossimException& e)
         {
            ossimNotify(ossimNotifyLevel_WARN)
               << "ossimPleiadesModel::finishConstruction -- caught exception:\n"
               << e.what() << std::endl;
         }
      }
   }

}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "desktopprocesssignaloperation.h"

#include "localprocesslist.h"

#include <utils/winutils.h>

#include <QCoreApplication>
#include <QDir>

#ifdef Q_OS_WIN
#define _WIN32_WINNT 0x0502
#include <windows.h>
#ifndef PROCESS_SUSPEND_RESUME
#define PROCESS_SUSPEND_RESUME 0x0800
#endif // PROCESS_SUSPEND_RESUME
#else // Q_OS_WIN
#include <errno.h>
#include <signal.h>
#endif // else Q_OS_WIN

namespace ProjectExplorer {

void DesktopProcessSignalOperation::killProcess(int pid)
{
    killProcessSilently(pid);
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::killProcess(const QString &filePath)
{
    m_errorMessage.clear();
    foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) {
        if (process.cmdLine == filePath)
            killProcessSilently(process.pid);
    }
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::interruptProcess(int pid)
{
    m_errorMessage.clear();
    interruptProcessSilently(pid);
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::interruptProcess(const QString &filePath)
{
    m_errorMessage.clear();
    foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) {
        if (process.cmdLine == filePath)
            interruptProcessSilently(process.pid);
    }
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::appendMsgCannotKill(int pid, const QString &why)
{
    if (!m_errorMessage.isEmpty())
        m_errorMessage += QChar::fromLatin1('\n');
    m_errorMessage += tr("Cannot kill process with pid %1: %3").arg(pid).arg(why);
    m_errorMessage += QLatin1Char(' ');
}

void DesktopProcessSignalOperation::appendMsgCannotInterrupt(int pid, const QString &why)
{
    if (!m_errorMessage.isEmpty())
        m_errorMessage += QChar::fromLatin1('\n');
    m_errorMessage += tr("Cannot interrupt process with pid %1: %3").arg(pid).arg(why);
    m_errorMessage += QLatin1Char(' ');
}

void DesktopProcessSignalOperation::killProcessSilently(int pid)
{
#ifdef Q_OS_WIN
    const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION
            |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ
            |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
    if (const HANDLE handle = OpenProcess(rights, FALSE, pid)) {
        if (!TerminateProcess(handle, UINT(-1)))
            appendMsgCannotKill(pid, Utils::winErrorMessage(GetLastError()));
        CloseHandle(handle);
    } else {
        appendMsgCannotKill(pid, tr("Cannot open process."));
    }
#else
    if (pid <= 0)
        appendMsgCannotKill(pid, tr("Invalid process id."));
    else if (kill(pid, SIGKILL))
        appendMsgCannotKill(pid, QString::fromLocal8Bit(strerror(errno)));
#endif // Q_OS_WIN
}

void DesktopProcessSignalOperation::interruptProcessSilently(int pid)
{
#ifdef Q_OS_WIN
    /*
    Windows 64 bit has a 32 bit subsystem (WOW64) which makes it possible to run a
    32 bit application inside a 64 bit environment.
    When GDB is used DebugBreakProcess must be called from the same system (32/64 bit) running
    the inferior. If CDB is used we could in theory break wow64 processes,
    but the break is actually a wow64 breakpoint. CDB is configured to ignore these
    breakpoints, because they also appear on module loading.
    Therefore we need helper executables (win(32/64)interrupt.exe) on Windows 64 bit calling
    DebugBreakProcess from the correct system.

    DebugBreak matrix for windows

    Api = UseDebugBreakApi
    Win64 = UseWin64InterruptHelper
    Win32 = UseWin32InterruptHelper
    N/A = This configuration is not possible

          | Windows 32bit   | Windows 64bit
          | QtCreator 32bit | QtCreator 32bit                   | QtCreator 64bit
          | Inferior 32bit  | Inferior 32bit  | Inferior 64bit  | Inferior 32bit  | Inferior 64bit
----------|-----------------|-----------------|-----------------|-----------------|----------------
CDB 32bit | Api             | Api             | N/A             | Win32           | N/A
    64bit | N/A             | Win64           | Win64           | Api             | Api
----------|-----------------|-----------------|-----------------|-----------------|----------------
GDB 32bit | Api             | Api             | N/A             | Win32           | N/A
    64bit | N/A             | N/A             | Win64           | N/A             | Api
----------|-----------------|-----------------|-----------------|-----------------|----------------

    */
    HANDLE inferior = NULL;
    do {
        const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION
                |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ
                |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
        inferior = OpenProcess(rights, FALSE, pid);
        if (inferior == NULL) {
            appendMsgCannotInterrupt(pid, tr("Cannot open process: %1")
                                     + Utils::winErrorMessage(GetLastError()));
            break;
        }
        bool creatorIs64Bit = Utils::winIs64BitBinary(qApp->applicationFilePath());
        if (!Utils::winIs64BitSystem() ||
                m_specialInterrupt == NoSpecialInterrupt ||
                m_specialInterrupt == Win64Interrupt && creatorIs64Bit ||
                m_specialInterrupt == Win32Interrupt && !creatorIs64Bit) {
            if (!DebugBreakProcess(inferior)) {
                appendMsgCannotInterrupt(pid, tr("DebugBreakProcess failed:")
                                          + QLatin1Char(' ') + Utils::winErrorMessage(GetLastError()));
            }
        } else if (m_specialInterrupt == Win32Interrupt || m_specialInterrupt == Win64Interrupt) {
            QString executable = QCoreApplication::applicationDirPath();
            executable += m_specialInterrupt == Win32Interrupt
                    ? QLatin1String("/win32interrupt.exe")
                    : QLatin1String("/win64interrupt.exe");
            if (!QFile::exists(executable)) {
                appendMsgCannotInterrupt(pid, tr( "%1 does not exist. If you built Qt Creator "
                                                  "yourself, check out http://qt.gitorious.org/"
                                                  "qt-creator/binary-artifacts.").
                                         arg(QDir::toNativeSeparators(executable)));
            }
            switch (QProcess::execute(executable, QStringList(QString::number(pid)))) {
            case -2:
                appendMsgCannotInterrupt(pid, tr(
                            "Cannot start %1. Check src\\tools\\win64interrupt\\win64interrupt.c "
                            "for more information.").arg(QDir::toNativeSeparators(executable)));
                break;
            case 0:
                break;
            default:
                appendMsgCannotInterrupt(pid, QDir::toNativeSeparators(executable)
                                         + QLatin1Char(' ') + tr("could not break the process."));
                break;
            }
        }
    } while (false);
    if (inferior != NULL)
        CloseHandle(inferior);
#else
    if (pid <= 0)
        appendMsgCannotInterrupt(pid, tr("Invalid process id."));
    else if (kill(pid, SIGINT))
        appendMsgCannotInterrupt(pid, QString::fromLocal8Bit(strerror(errno)));
#endif // Q_OS_WIN
}

} // namespace ProjectExplorer
<commit_msg>ProjectExplorer: Fix message placeholders.<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "desktopprocesssignaloperation.h"

#include "localprocesslist.h"

#include <utils/winutils.h>

#include <QCoreApplication>
#include <QDir>

#ifdef Q_OS_WIN
#define _WIN32_WINNT 0x0502
#include <windows.h>
#ifndef PROCESS_SUSPEND_RESUME
#define PROCESS_SUSPEND_RESUME 0x0800
#endif // PROCESS_SUSPEND_RESUME
#else // Q_OS_WIN
#include <errno.h>
#include <signal.h>
#endif // else Q_OS_WIN

namespace ProjectExplorer {

void DesktopProcessSignalOperation::killProcess(int pid)
{
    killProcessSilently(pid);
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::killProcess(const QString &filePath)
{
    m_errorMessage.clear();
    foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) {
        if (process.cmdLine == filePath)
            killProcessSilently(process.pid);
    }
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::interruptProcess(int pid)
{
    m_errorMessage.clear();
    interruptProcessSilently(pid);
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::interruptProcess(const QString &filePath)
{
    m_errorMessage.clear();
    foreach (const DeviceProcessItem &process, Internal::LocalProcessList::getLocalProcesses()) {
        if (process.cmdLine == filePath)
            interruptProcessSilently(process.pid);
    }
    emit finished(m_errorMessage);
}

void DesktopProcessSignalOperation::appendMsgCannotKill(int pid, const QString &why)
{
    if (!m_errorMessage.isEmpty())
        m_errorMessage += QChar::fromLatin1('\n');
    m_errorMessage += tr("Cannot kill process with pid %1: %2").arg(pid).arg(why);
    m_errorMessage += QLatin1Char(' ');
}

void DesktopProcessSignalOperation::appendMsgCannotInterrupt(int pid, const QString &why)
{
    if (!m_errorMessage.isEmpty())
        m_errorMessage += QChar::fromLatin1('\n');
    m_errorMessage += tr("Cannot interrupt process with pid %1: %2").arg(pid).arg(why);
    m_errorMessage += QLatin1Char(' ');
}

void DesktopProcessSignalOperation::killProcessSilently(int pid)
{
#ifdef Q_OS_WIN
    const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION
            |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ
            |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
    if (const HANDLE handle = OpenProcess(rights, FALSE, pid)) {
        if (!TerminateProcess(handle, UINT(-1)))
            appendMsgCannotKill(pid, Utils::winErrorMessage(GetLastError()));
        CloseHandle(handle);
    } else {
        appendMsgCannotKill(pid, tr("Cannot open process."));
    }
#else
    if (pid <= 0)
        appendMsgCannotKill(pid, tr("Invalid process id."));
    else if (kill(pid, SIGKILL))
        appendMsgCannotKill(pid, QString::fromLocal8Bit(strerror(errno)));
#endif // Q_OS_WIN
}

void DesktopProcessSignalOperation::interruptProcessSilently(int pid)
{
#ifdef Q_OS_WIN
    /*
    Windows 64 bit has a 32 bit subsystem (WOW64) which makes it possible to run a
    32 bit application inside a 64 bit environment.
    When GDB is used DebugBreakProcess must be called from the same system (32/64 bit) running
    the inferior. If CDB is used we could in theory break wow64 processes,
    but the break is actually a wow64 breakpoint. CDB is configured to ignore these
    breakpoints, because they also appear on module loading.
    Therefore we need helper executables (win(32/64)interrupt.exe) on Windows 64 bit calling
    DebugBreakProcess from the correct system.

    DebugBreak matrix for windows

    Api = UseDebugBreakApi
    Win64 = UseWin64InterruptHelper
    Win32 = UseWin32InterruptHelper
    N/A = This configuration is not possible

          | Windows 32bit   | Windows 64bit
          | QtCreator 32bit | QtCreator 32bit                   | QtCreator 64bit
          | Inferior 32bit  | Inferior 32bit  | Inferior 64bit  | Inferior 32bit  | Inferior 64bit
----------|-----------------|-----------------|-----------------|-----------------|----------------
CDB 32bit | Api             | Api             | N/A             | Win32           | N/A
    64bit | N/A             | Win64           | Win64           | Api             | Api
----------|-----------------|-----------------|-----------------|-----------------|----------------
GDB 32bit | Api             | Api             | N/A             | Win32           | N/A
    64bit | N/A             | N/A             | Win64           | N/A             | Api
----------|-----------------|-----------------|-----------------|-----------------|----------------

    */
    HANDLE inferior = NULL;
    do {
        const DWORD rights = PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION
                |PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ
                |PROCESS_DUP_HANDLE|PROCESS_TERMINATE|PROCESS_CREATE_THREAD|PROCESS_SUSPEND_RESUME;
        inferior = OpenProcess(rights, FALSE, pid);
        if (inferior == NULL) {
            appendMsgCannotInterrupt(pid, tr("Cannot open process: %1")
                                     + Utils::winErrorMessage(GetLastError()));
            break;
        }
        bool creatorIs64Bit = Utils::winIs64BitBinary(qApp->applicationFilePath());
        if (!Utils::winIs64BitSystem() ||
                m_specialInterrupt == NoSpecialInterrupt ||
                m_specialInterrupt == Win64Interrupt && creatorIs64Bit ||
                m_specialInterrupt == Win32Interrupt && !creatorIs64Bit) {
            if (!DebugBreakProcess(inferior)) {
                appendMsgCannotInterrupt(pid, tr("DebugBreakProcess failed:")
                                          + QLatin1Char(' ') + Utils::winErrorMessage(GetLastError()));
            }
        } else if (m_specialInterrupt == Win32Interrupt || m_specialInterrupt == Win64Interrupt) {
            QString executable = QCoreApplication::applicationDirPath();
            executable += m_specialInterrupt == Win32Interrupt
                    ? QLatin1String("/win32interrupt.exe")
                    : QLatin1String("/win64interrupt.exe");
            if (!QFile::exists(executable)) {
                appendMsgCannotInterrupt(pid, tr( "%1 does not exist. If you built Qt Creator "
                                                  "yourself, check out http://qt.gitorious.org/"
                                                  "qt-creator/binary-artifacts.").
                                         arg(QDir::toNativeSeparators(executable)));
            }
            switch (QProcess::execute(executable, QStringList(QString::number(pid)))) {
            case -2:
                appendMsgCannotInterrupt(pid, tr(
                            "Cannot start %1. Check src\\tools\\win64interrupt\\win64interrupt.c "
                            "for more information.").arg(QDir::toNativeSeparators(executable)));
                break;
            case 0:
                break;
            default:
                appendMsgCannotInterrupt(pid, QDir::toNativeSeparators(executable)
                                         + QLatin1Char(' ') + tr("could not break the process."));
                break;
            }
        }
    } while (false);
    if (inferior != NULL)
        CloseHandle(inferior);
#else
    if (pid <= 0)
        appendMsgCannotInterrupt(pid, tr("Invalid process id."));
    else if (kill(pid, SIGINT))
        appendMsgCannotInterrupt(pid, QString::fromLocal8Bit(strerror(errno)));
#endif // Q_OS_WIN
}

} // namespace ProjectExplorer
<|endoftext|>