<commit_before>//===- CrashDebugger.cpp - Debug compilation crashes ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the bugpoint internals that narrow down compilation crashes
//
//===----------------------------------------------------------------------===//

#include "BugDriver.h"
#include "ListReducer.h"
#include "llvm/Constant.h"
#include "llvm/iTerminators.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/SymbolTable.h"
#include "llvm/Type.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/Writer.h"
#include "llvm/Support/CFG.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "Support/FileUtilities.h"
#include <fstream>
#include <set>

class DebugCrashes : public ListReducer<const PassInfo*> {
  BugDriver &BD;
public:
  DebugCrashes(BugDriver &bd) : BD(bd) {}

  // doTest - Return true iff running the "removed" passes succeeds, and running
  // the "Kept" passes fail when run on the output of the "removed" passes.  If
  // we return true, we update the current module of bugpoint.
  //
  virtual TestResult doTest(std::vector<const PassInfo*> &Removed,
                            std::vector<const PassInfo*> &Kept);
};

DebugCrashes::TestResult
DebugCrashes::doTest(std::vector<const PassInfo*> &Prefix,
                     std::vector<const PassInfo*> &Suffix) {
  std::string PrefixOutput;
  Module *OrigProgram = 0;
  if (!Prefix.empty()) {
    std::cout << "Checking to see if these passes crash: "
              << getPassesString(Prefix) << ": ";
    if (BD.runPasses(Prefix, PrefixOutput))
      return KeepPrefix;

    OrigProgram = BD.Program;

    BD.Program = BD.ParseInputFile(PrefixOutput);
    if (BD.Program == 0) {
      std::cerr << BD.getToolName() << ": Error reading bytecode file '"
                << PrefixOutput << "'!\n";
      exit(1);
    }
    removeFile(PrefixOutput);
  }

  std::cout << "Checking to see if these passes crash: "
            << getPassesString(Suffix) << ": ";

  if (BD.runPasses(Suffix)) {
    delete OrigProgram;            // The suffix crashes alone...
    return KeepSuffix;
  }

  // Nothing failed, restore state...
  if (OrigProgram) {
    delete BD.Program;
    BD.Program = OrigProgram;
  }
  return NoFailure;
}

class ReduceCrashingFunctions : public ListReducer<Function*> {
  BugDriver &BD;
public:
  ReduceCrashingFunctions(BugDriver &bd) : BD(bd) {}

  virtual TestResult doTest(std::vector<Function*> &Prefix,
                            std::vector<Function*> &Kept) {
    if (!Kept.empty() && TestFuncs(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestFuncs(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestFuncs(std::vector<Function*> &Prefix);
};

bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) {
  // Clone the program to try hacking it apart...
  Module *M = CloneModule(BD.Program);

  // Convert list to set for fast lookup...
  std::set<Function*> Functions;
  for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
    Function *CMF = M->getFunction(Funcs[i]->getName(),
                                   Funcs[i]->getFunctionType());
    assert(CMF && "Function not in module?!");
    Functions.insert(CMF);
  }

  std::cout << "Checking for crash with only these functions:";
  for (unsigned i = 0, e = Funcs.size(); i != e; ++i)
    std::cout << " " << Funcs[i]->getName();
  std::cout << ": ";

  // Loop over and delete any functions which we aren't supposed to be playing
  // with...
  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (!I->isExternal() && !Functions.count(I))
      DeleteFunctionBody(I);

  // Try running the hacked up program...
  std::swap(BD.Program, M);
  if (BD.runPasses(BD.PassesToRun)) {
    delete M;         // It crashed, keep the trimmed version...

    // Make sure to use function pointers that point into the now-current
    // module.
    Funcs.assign(Functions.begin(), Functions.end());
    return true;
  }
  delete BD.Program;  // It didn't crash, revert...
  BD.Program = M;
  return false;
}

/// ReduceCrashingBlocks reducer - This works by setting the terminators of all
/// terminators except the specified basic blocks to a 'ret' instruction, then
/// running the simplify-cfg pass.  This has the effect of chopping up the CFG
/// really fast which can reduce large functions quickly.
///
class ReduceCrashingBlocks : public ListReducer<BasicBlock*> {
  BugDriver &BD;
public:
  ReduceCrashingBlocks(BugDriver &bd) : BD(bd) {}

  virtual TestResult doTest(std::vector<BasicBlock*> &Prefix,
                            std::vector<BasicBlock*> &Kept) {
    if (!Kept.empty() && TestBlocks(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestBlocks(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestBlocks(std::vector<BasicBlock*> &Prefix);
};

bool ReduceCrashingBlocks::TestBlocks(std::vector<BasicBlock*> &BBs) {
  // Clone the program to try hacking it apart...
  Module *M = CloneModule(BD.Program);

  // Convert list to set for fast lookup...
  std::set<BasicBlock*> Blocks;
  for (unsigned i = 0, e = BBs.size(); i != e; ++i) {
    // Convert the basic block from the original module to the new module...
    Function *F = BBs[i]->getParent();
    Function *CMF = M->getFunction(F->getName(), F->getFunctionType());
    assert(CMF && "Function not in module?!");

    // Get the mapped basic block...
    Function::iterator CBI = CMF->begin();
    std::advance(CBI, std::distance(F->begin(), Function::iterator(BBs[i])));
    Blocks.insert(CBI);
  }

  std::cout << "Checking for crash with only these blocks:";
  for (unsigned i = 0, e = Blocks.size(); i != e; ++i)
    std::cout << " " << BBs[i]->getName();
  std::cout << ": ";

  // Loop over and delete any hack up any blocks that are not listed...
  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB)
      if (!Blocks.count(BB) && !isa<ReturnInst>(BB->getTerminator())) {
        // Loop over all of the successors of this block, deleting any PHI nodes
        // that might include it.
        for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI)
          (*SI)->removePredecessor(BB);

        // Delete the old terminator instruction...
        BB->getInstList().pop_back();

        // Add a new return instruction of the appropriate type...
        const Type *RetTy = BB->getParent()->getReturnType();
        ReturnInst *RI = new ReturnInst(RetTy == Type::VoidTy ? 0 :
                                        Constant::getNullValue(RetTy));
        BB->getInstList().push_back(RI);
      }

  // The CFG Simplifier pass may delete one of the basic blocks we are
  // interested in.  If it does we need to take the block out of the list.  Make
  // a "persistent mapping" by turning basic blocks into <function, name> pairs.
  // This won't work well if blocks are unnamed, but that is just the risk we
  // have to take.
  std::vector<std::pair<Function*, std::string> > BlockInfo;

  for (std::set<BasicBlock*>::iterator I = Blocks.begin(), E = Blocks.end();
       I != E; ++I)
    BlockInfo.push_back(std::make_pair((*I)->getParent(), (*I)->getName()));

  // Now run the CFG simplify pass on the function...
  PassManager Passes;
  Passes.add(createCFGSimplificationPass());
  Passes.add(createVerifierPass());
  Passes.run(*M);

  // Try running on the hacked up program...
  std::swap(BD.Program, M);
  if (BD.runPasses(BD.PassesToRun)) {
    delete M;         // It crashed, keep the trimmed version...

    // Make sure to use basic block pointers that point into the now-current
    // module, and that they don't include any deleted blocks.
    BBs.clear();
    for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) {
      SymbolTable &ST = BlockInfo[i].first->getSymbolTable();
      SymbolTable::iterator I = ST.find(Type::LabelTy);
      if (I != ST.end() && I->second.count(BlockInfo[i].second))
        BBs.push_back(cast<BasicBlock>(I->second[BlockInfo[i].second]));
    }
    return true;
  }
  delete BD.Program;  // It didn't crash, revert...
  BD.Program = M;
  return false;
}

/// debugCrash - This method is called when some pass crashes on input.  It
/// attempts to prune down the testcase to something reasonable, and figure
/// out exactly which pass is crashing.
///
bool BugDriver::debugCrash() {
  bool AnyReduction = false;
  std::cout << "\n*** Debugging optimizer crash!\n";

  // Reduce the list of passes which causes the optimizer to crash...
  unsigned OldSize = PassesToRun.size();
  DebugCrashes(*this).reduceList(PassesToRun);

  std::cout << "\n*** Found crashing pass"
            << (PassesToRun.size() == 1 ? ": " : "es: ")
            << getPassesString(PassesToRun) << "\n";

  EmitProgressBytecode("passinput");

  // See if we can get away with nuking all of the global variable initializers
  // in the program...
  if (Program->gbegin() != Program->gend()) {
    Module *M = CloneModule(Program);
    bool DeletedInit = false;
    for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I)
      if (I->hasInitializer()) {
        I->setInitializer(0);
        I->setLinkage(GlobalValue::ExternalLinkage);
        DeletedInit = true;
      }

    if (!DeletedInit) {
      delete M;  // No change made...
    } else {
      // See if the program still causes a crash...
      std::cout << "\nChecking to see if we can delete global inits: ";
      std::swap(Program, M);
      if (runPasses(PassesToRun)) {  // Still crashes?
        AnyReduction = true;
        delete M;
        std::cout << "\n*** Able to remove all global initializers!\n";
      } else {                       // No longer crashes?
        delete Program;              // Restore program.
        Program = M;
        std::cout << "  - Removing all global inits hides problem!\n";
      }
    }
  }

  // Now try to reduce the number of functions in the module to something small.
  std::vector<Function*> Functions;
  for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
    if (!I->isExternal())
      Functions.push_back(I);

  if (Functions.size() > 1) {
    std::cout << "\n*** Attempting to reduce the number of functions "
      "in the testcase\n";

    OldSize = Functions.size();
    ReduceCrashingFunctions(*this).reduceList(Functions);

    if (Functions.size() < OldSize) {
      EmitProgressBytecode("reduced-function");
      AnyReduction = true;
    }
  }

  // Attempt to delete entire basic blocks at a time to speed up
  // convergence... this actually works by setting the terminator of the blocks
  // to a return instruction then running simplifycfg, which can potentially
  // shrinks the code dramatically quickly
  //
  if (!DisableSimplifyCFG) {
    std::vector<BasicBlock*> Blocks;
    for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
      for (Function::iterator FI = I->begin(), E = I->end(); FI != E; ++FI)
        Blocks.push_back(FI);
    ReduceCrashingBlocks(*this).reduceList(Blocks);
  }

  // FIXME: This should use the list reducer to converge faster by deleting
  // larger chunks of instructions at a time!
  unsigned Simplification = 4;
  do {
    --Simplification;
    std::cout << "\n*** Attempting to reduce testcase by deleting instruc"
              << "tions: Simplification Level #" << Simplification << "\n";

    // Now that we have deleted the functions that are unnecessary for the
    // program, try to remove instructions that are not necessary to cause the
    // crash.  To do this, we loop through all of the instructions in the
    // remaining functions, deleting them (replacing any values produced with
    // nulls), and then running ADCE and SimplifyCFG.  If the transformed input
    // still triggers failure, keep deleting until we cannot trigger failure
    // anymore.
    //
  TryAgain:

    // Loop over all of the (non-terminator) instructions remaining in the
    // function, attempting to delete them.
    for (Module::iterator FI = Program->begin(), E = Program->end();
         FI != E; ++FI)
      if (!FI->isExternal()) {
        for (Function::iterator BI = FI->begin(), E = FI->end(); BI != E; ++BI)
          for (BasicBlock::iterator I = BI->begin(), E = --BI->end();
               I != E; ++I) {
            Module *M = deleteInstructionFromProgram(I, Simplification);

            // Make the function the current program...
            std::swap(Program, M);

            // Find out if the pass still crashes on this pass...
            std::cout << "Checking instruction '" << I->getName() << "': ";
            if (runPasses(PassesToRun)) {
              // Yup, it does, we delete the old module, and continue trying to
              // reduce the testcase...
              delete M;
              AnyReduction = true;
              goto TryAgain;  // I wish I had a multi-level break here!
            }

            // This pass didn't crash without this instruction, try the next
            // one.
            delete Program;
            Program = M;
          }
      }
  } while (Simplification);

  // Try to clean up the testcase by running funcresolve and globaldce...
  std::cout << "\n*** Attempting to perform final cleanups: ";
  Module *M = performFinalCleanups();
  std::swap(Program, M);

  // Find out if the pass still crashes on the cleaned up program...
  if (runPasses(PassesToRun)) {
    // Yup, it does, keep the reduced version...
    delete M;
    AnyReduction = true;
  } else {
    delete Program;   // Otherwise, restore the original module...
    Program = M;
  }

  if (AnyReduction)
    EmitProgressBytecode("reduced-simplified");

  return false;
}
<commit_msg>Do not print out lists with thousands of elements in them, that's kinda silly<commit_after>//===- CrashDebugger.cpp - Debug compilation crashes ----------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the bugpoint internals that narrow down compilation crashes
//
//===----------------------------------------------------------------------===//

#include "BugDriver.h"
#include "ListReducer.h"
#include "llvm/Constant.h"
#include "llvm/iTerminators.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/SymbolTable.h"
#include "llvm/Type.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Bytecode/Writer.h"
#include "llvm/Support/CFG.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "Support/FileUtilities.h"
#include <fstream>
#include <set>

class DebugCrashes : public ListReducer<const PassInfo*> {
  BugDriver &BD;
public:
  DebugCrashes(BugDriver &bd) : BD(bd) {}

  // doTest - Return true iff running the "removed" passes succeeds, and running
  // the "Kept" passes fail when run on the output of the "removed" passes.  If
  // we return true, we update the current module of bugpoint.
  //
  virtual TestResult doTest(std::vector<const PassInfo*> &Removed,
                            std::vector<const PassInfo*> &Kept);
};

DebugCrashes::TestResult
DebugCrashes::doTest(std::vector<const PassInfo*> &Prefix,
                     std::vector<const PassInfo*> &Suffix) {
  std::string PrefixOutput;
  Module *OrigProgram = 0;
  if (!Prefix.empty()) {
    std::cout << "Checking to see if these passes crash: "
              << getPassesString(Prefix) << ": ";
    if (BD.runPasses(Prefix, PrefixOutput))
      return KeepPrefix;

    OrigProgram = BD.Program;

    BD.Program = BD.ParseInputFile(PrefixOutput);
    if (BD.Program == 0) {
      std::cerr << BD.getToolName() << ": Error reading bytecode file '"
                << PrefixOutput << "'!\n";
      exit(1);
    }
    removeFile(PrefixOutput);
  }

  std::cout << "Checking to see if these passes crash: "
            << getPassesString(Suffix) << ": ";

  if (BD.runPasses(Suffix)) {
    delete OrigProgram;            // The suffix crashes alone...
    return KeepSuffix;
  }

  // Nothing failed, restore state...
  if (OrigProgram) {
    delete BD.Program;
    BD.Program = OrigProgram;
  }
  return NoFailure;
}

class ReduceCrashingFunctions : public ListReducer<Function*> {
  BugDriver &BD;
public:
  ReduceCrashingFunctions(BugDriver &bd) : BD(bd) {}

  virtual TestResult doTest(std::vector<Function*> &Prefix,
                            std::vector<Function*> &Kept) {
    if (!Kept.empty() && TestFuncs(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestFuncs(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestFuncs(std::vector<Function*> &Prefix);
};

bool ReduceCrashingFunctions::TestFuncs(std::vector<Function*> &Funcs) {
  // Clone the program to try hacking it apart...
  Module *M = CloneModule(BD.Program);

  // Convert list to set for fast lookup...
  std::set<Function*> Functions;
  for (unsigned i = 0, e = Funcs.size(); i != e; ++i) {
    Function *CMF = M->getFunction(Funcs[i]->getName(),
                                   Funcs[i]->getFunctionType());
    assert(CMF && "Function not in module?!");
    Functions.insert(CMF);
  }

  std::cout << "Checking for crash with only these functions:";
  unsigned NumPrint = Funcs.size();
  if (NumPrint > 10) NumPrint = 10;
  for (unsigned i = 0; i != NumPrint; ++i)
    std::cout << " " << Funcs[i]->getName();
  if (NumPrint < Funcs.size())
    std::cout << "... <" << Funcs.size() << " total>";
  std::cout << ": ";

  // Loop over and delete any functions which we aren't supposed to be playing
  // with...
  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (!I->isExternal() && !Functions.count(I))
      DeleteFunctionBody(I);

  // Try running the hacked up program...
  std::swap(BD.Program, M);
  if (BD.runPasses(BD.PassesToRun)) {
    delete M;         // It crashed, keep the trimmed version...

    // Make sure to use function pointers that point into the now-current
    // module.
    Funcs.assign(Functions.begin(), Functions.end());
    return true;
  }
  delete BD.Program;  // It didn't crash, revert...
  BD.Program = M;
  return false;
}

/// ReduceCrashingBlocks reducer - This works by setting the terminators of all
/// terminators except the specified basic blocks to a 'ret' instruction, then
/// running the simplify-cfg pass.  This has the effect of chopping up the CFG
/// really fast which can reduce large functions quickly.
///
class ReduceCrashingBlocks : public ListReducer<BasicBlock*> {
  BugDriver &BD;
public:
  ReduceCrashingBlocks(BugDriver &bd) : BD(bd) {}

  virtual TestResult doTest(std::vector<BasicBlock*> &Prefix,
                            std::vector<BasicBlock*> &Kept) {
    if (!Kept.empty() && TestBlocks(Kept))
      return KeepSuffix;
    if (!Prefix.empty() && TestBlocks(Prefix))
      return KeepPrefix;
    return NoFailure;
  }

  bool TestBlocks(std::vector<BasicBlock*> &Prefix);
};

bool ReduceCrashingBlocks::TestBlocks(std::vector<BasicBlock*> &BBs) {
  // Clone the program to try hacking it apart...
  Module *M = CloneModule(BD.Program);

  // Convert list to set for fast lookup...
  std::set<BasicBlock*> Blocks;
  for (unsigned i = 0, e = BBs.size(); i != e; ++i) {
    // Convert the basic block from the original module to the new module...
    Function *F = BBs[i]->getParent();
    Function *CMF = M->getFunction(F->getName(), F->getFunctionType());
    assert(CMF && "Function not in module?!");

    // Get the mapped basic block...
    Function::iterator CBI = CMF->begin();
    std::advance(CBI, std::distance(F->begin(), Function::iterator(BBs[i])));
    Blocks.insert(CBI);
  }

  std::cout << "Checking for crash with only these blocks:";
  unsigned NumPrint = Blocks.size();
  if (NumPrint > 10) NumPrint = 10;
  for (unsigned i = 0, e = NumPrint; i != e; ++i)
    std::cout << " " << BBs[i]->getName();
  if (NumPrint < Blocks.size())
    std::cout << "... <" << Blocks.size() << " total>";
  std::cout << ": ";

  // Loop over and delete any hack up any blocks that are not listed...
  for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
    for (Function::iterator BB = I->begin(), E = I->end(); BB != E; ++BB)
      if (!Blocks.count(BB) && !isa<ReturnInst>(BB->getTerminator())) {
        // Loop over all of the successors of this block, deleting any PHI nodes
        // that might include it.
        for (succ_iterator SI = succ_begin(BB), E = succ_end(BB); SI != E; ++SI)
          (*SI)->removePredecessor(BB);

        // Delete the old terminator instruction...
        BB->getInstList().pop_back();

        // Add a new return instruction of the appropriate type...
        const Type *RetTy = BB->getParent()->getReturnType();
        ReturnInst *RI = new ReturnInst(RetTy == Type::VoidTy ? 0 :
                                        Constant::getNullValue(RetTy));
        BB->getInstList().push_back(RI);
      }

  // The CFG Simplifier pass may delete one of the basic blocks we are
  // interested in.  If it does we need to take the block out of the list.  Make
  // a "persistent mapping" by turning basic blocks into <function, name> pairs.
  // This won't work well if blocks are unnamed, but that is just the risk we
  // have to take.
  std::vector<std::pair<Function*, std::string> > BlockInfo;

  for (std::set<BasicBlock*>::iterator I = Blocks.begin(), E = Blocks.end();
       I != E; ++I)
    BlockInfo.push_back(std::make_pair((*I)->getParent(), (*I)->getName()));

  // Now run the CFG simplify pass on the function...
  PassManager Passes;
  Passes.add(createCFGSimplificationPass());
  Passes.add(createVerifierPass());
  Passes.run(*M);

  // Try running on the hacked up program...
  std::swap(BD.Program, M);
  if (BD.runPasses(BD.PassesToRun)) {
    delete M;         // It crashed, keep the trimmed version...

    // Make sure to use basic block pointers that point into the now-current
    // module, and that they don't include any deleted blocks.
    BBs.clear();
    for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) {
      SymbolTable &ST = BlockInfo[i].first->getSymbolTable();
      SymbolTable::iterator I = ST.find(Type::LabelTy);
      if (I != ST.end() && I->second.count(BlockInfo[i].second))
        BBs.push_back(cast<BasicBlock>(I->second[BlockInfo[i].second]));
    }
    return true;
  }
  delete BD.Program;  // It didn't crash, revert...
  BD.Program = M;
  return false;
}

/// debugCrash - This method is called when some pass crashes on input.  It
/// attempts to prune down the testcase to something reasonable, and figure
/// out exactly which pass is crashing.
///
bool BugDriver::debugCrash() {
  bool AnyReduction = false;
  std::cout << "\n*** Debugging optimizer crash!\n";

  // Reduce the list of passes which causes the optimizer to crash...
  unsigned OldSize = PassesToRun.size();
  DebugCrashes(*this).reduceList(PassesToRun);

  std::cout << "\n*** Found crashing pass"
            << (PassesToRun.size() == 1 ? ": " : "es: ")
            << getPassesString(PassesToRun) << "\n";

  EmitProgressBytecode("passinput");

  // See if we can get away with nuking all of the global variable initializers
  // in the program...
  if (Program->gbegin() != Program->gend()) {
    Module *M = CloneModule(Program);
    bool DeletedInit = false;
    for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I)
      if (I->hasInitializer()) {
        I->setInitializer(0);
        I->setLinkage(GlobalValue::ExternalLinkage);
        DeletedInit = true;
      }

    if (!DeletedInit) {
      delete M;  // No change made...
    } else {
      // See if the program still causes a crash...
      std::cout << "\nChecking to see if we can delete global inits: ";
      std::swap(Program, M);
      if (runPasses(PassesToRun)) {  // Still crashes?
        AnyReduction = true;
        delete M;
        std::cout << "\n*** Able to remove all global initializers!\n";
      } else {                       // No longer crashes?
        delete Program;              // Restore program.
        Program = M;
        std::cout << "  - Removing all global inits hides problem!\n";
      }
    }
  }

  // Now try to reduce the number of functions in the module to something small.
  std::vector<Function*> Functions;
  for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
    if (!I->isExternal())
      Functions.push_back(I);

  if (Functions.size() > 1) {
    std::cout << "\n*** Attempting to reduce the number of functions "
      "in the testcase\n";

    OldSize = Functions.size();
    ReduceCrashingFunctions(*this).reduceList(Functions);

    if (Functions.size() < OldSize) {
      EmitProgressBytecode("reduced-function");
      AnyReduction = true;
    }
  }

  // Attempt to delete entire basic blocks at a time to speed up
  // convergence... this actually works by setting the terminator of the blocks
  // to a return instruction then running simplifycfg, which can potentially
  // shrinks the code dramatically quickly
  //
  if (!DisableSimplifyCFG) {
    std::vector<BasicBlock*> Blocks;
    for (Module::iterator I = Program->begin(), E = Program->end(); I != E; ++I)
      for (Function::iterator FI = I->begin(), E = I->end(); FI != E; ++FI)
        Blocks.push_back(FI);
    ReduceCrashingBlocks(*this).reduceList(Blocks);
  }

  // FIXME: This should use the list reducer to converge faster by deleting
  // larger chunks of instructions at a time!
  unsigned Simplification = 4;
  do {
    --Simplification;
    std::cout << "\n*** Attempting to reduce testcase by deleting instruc"
              << "tions: Simplification Level #" << Simplification << "\n";

    // Now that we have deleted the functions that are unnecessary for the
    // program, try to remove instructions that are not necessary to cause the
    // crash.  To do this, we loop through all of the instructions in the
    // remaining functions, deleting them (replacing any values produced with
    // nulls), and then running ADCE and SimplifyCFG.  If the transformed input
    // still triggers failure, keep deleting until we cannot trigger failure
    // anymore.
    //
  TryAgain:

    // Loop over all of the (non-terminator) instructions remaining in the
    // function, attempting to delete them.
    for (Module::iterator FI = Program->begin(), E = Program->end();
         FI != E; ++FI)
      if (!FI->isExternal()) {
        for (Function::iterator BI = FI->begin(), E = FI->end(); BI != E; ++BI)
          for (BasicBlock::iterator I = BI->begin(), E = --BI->end();
               I != E; ++I) {
            Module *M = deleteInstructionFromProgram(I, Simplification);

            // Make the function the current program...
            std::swap(Program, M);

            // Find out if the pass still crashes on this pass...
            std::cout << "Checking instruction '" << I->getName() << "': ";
            if (runPasses(PassesToRun)) {
              // Yup, it does, we delete the old module, and continue trying to
              // reduce the testcase...
              delete M;
              AnyReduction = true;
              goto TryAgain;  // I wish I had a multi-level break here!
            }

            // This pass didn't crash without this instruction, try the next
            // one.
            delete Program;
            Program = M;
          }
      }
  } while (Simplification);

  // Try to clean up the testcase by running funcresolve and globaldce...
  std::cout << "\n*** Attempting to perform final cleanups: ";
  Module *M = performFinalCleanups();
  std::swap(Program, M);

  // Find out if the pass still crashes on the cleaned up program...
  if (runPasses(PassesToRun)) {
    // Yup, it does, keep the reduced version...
    delete M;
    AnyReduction = true;
  } else {
    delete Program;   // Otherwise, restore the original module...
    Program = M;
  }

  if (AnyReduction)
    EmitProgressBytecode("reduced-simplified");

  return false;
}
<|endoftext|>


<commit_before>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2015 Intel Corporation. All Rights Reserved.

#include <librealsense2/rs.hpp>

#include <vector>
#include <map>
#include <string>
#include <iostream>
#include <fstream>
#include <thread>
#include <mutex>
#include <chrono>
#include <condition_variable>

#include "tclap/CmdLine.h"
#include "tclap/ValueArg.h"

using namespace TCLAP;

#define WAIT_FOR_DEVICE_TIMEOUT 10

#if _WIN32
#include <io.h>
#define ISATTY _isatty
#define FILENO _fileno
#else
#include <unistd.h>
#define ISATTY isatty
#define FILENO fileno
#endif

std::vector<uint8_t> read_fw_file(std::string file_path)
{
    std::vector<uint8_t> rv;

    std::ifstream file(file_path, std::ios::in | std::ios::binary | std::ios::ate);
    if (file.is_open())
    {
        rv.resize(file.tellg());

        file.seekg(0, std::ios::beg);
        file.read((char*)rv.data(), rv.size());
        file.close();
    }

    return rv;
}

void print_device_info(rs2::device d)
{
    std::map<rs2_camera_info, std::string> camera_info;

    for (int i = 0; i < RS2_CAMERA_INFO_COUNT; i++)
    {
        auto info = (rs2_camera_info)i;
        camera_info[info] = d.supports(info) ? d.get_info(info) : "unknown";
    }

    std::cout << "Name: " << camera_info[RS2_CAMERA_INFO_NAME] <<
        ", serial number: " << camera_info[RS2_CAMERA_INFO_SERIAL_NUMBER] <<
        ", update serial number: " << camera_info[RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID] <<
        ", firmware version: " << camera_info[RS2_CAMERA_INFO_FIRMWARE_VERSION] <<
        ", USB type: " << camera_info[RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR] << std::endl;
}

std::vector<uint8_t> read_firmware_data(bool is_set, const std::string& file_path)
{
    if (!is_set)
    {
        throw rs2::error("firmware file must be selected");
    }

    std::vector<uint8_t> fw_image = read_fw_file(file_path);

    if (fw_image.size() == 0)
    {
        throw rs2::error("failed to read firmware file");
    }

    return fw_image;
}

void update(rs2::update_device fwu_dev, std::vector<uint8_t> fw_image)
{
    std::cout << std::endl << "firmware update started"<< std::endl << std::endl;

    if (ISATTY(FILENO(stdout)))
    {
        fwu_dev.update(fw_image, [&](const float progress)
            {
                printf("\rfirmware update progress: %d[%%]", (int)(progress * 100));
            });
    }
    else
        fwu_dev.update(fw_image, [&](const float progress){});

    std::cout << std::endl << std::endl << "firmware update done" << std::endl;
}

void list_devices(rs2::context ctx)
{
    auto devs = ctx.query_devices();
    if (devs.size() == 0)
    {
        std::cout << std::endl << "there are no connected devices" << std::endl;
        return;
    }

    std::cout << std::endl << "connected devices:" << std::endl;

    int counter = 0;
    for (auto&& d : devs)
    {
        std::cout << ++counter << ") ";
        print_device_info(d);
    }
}

int main(int argc, char** argv) try
{
#ifdef BUILD_EASYLOGGINGPP
    rs2::log_to_console(RS2_LOG_SEVERITY_ERROR);
#endif

    rs2::context ctx;

    std::condition_variable cv;
    std::mutex mutex;
    std::string selected_serial_number;

    rs2::device new_device;
    rs2::update_device new_fw_update_device;

    bool done = false;

    CmdLine cmd("librealsense rs-fw-update tool", ' ', RS2_API_VERSION_STR);

    SwitchArg list_devices_arg("l", "list_devices", "List all available devices");
    SwitchArg recover_arg("r", "recover", "Recover all connected devices which are in recovery mode");
    SwitchArg unsigned_arg("u", "unsigned", "Update unsigned firmware, available only for unlocked cameras");
    ValueArg<std::string> backup_arg("b", "backup", "Create a backup to the camera flash and saved it to the given path", false, "", "string");
    ValueArg<std::string> file_arg("f", "file", "Path of the firmware image file", false, "", "string");
    ValueArg<std::string> serial_number_arg("s", "serial_number", "The serial number of the device to be update, this is mandetory if more than one device is connected", false, "", "string");

    cmd.add(list_devices_arg);
    cmd.add(recover_arg);
    cmd.add(unsigned_arg);
    cmd.add(file_arg);
    cmd.add(serial_number_arg);
    cmd.add(backup_arg);

    cmd.parse(argc, argv);

    bool recovery_request = recover_arg.getValue();

    if (list_devices_arg.isSet())
    {
        list_devices(ctx);
        return EXIT_SUCCESS;
    }

    if (!file_arg.isSet() && !backup_arg.isSet())
    {
        std::cout << std::endl << "nothing to do, run again with -h for help" << std::endl;
        return EXIT_FAILURE;
    }

    if (serial_number_arg.isSet())
    {
        selected_serial_number = serial_number_arg.getValue();
        std::cout << std::endl << "search for device with serial number: " << selected_serial_number << std::endl;
    }

    std::string update_serial_number;

    // Recovery
    bool recovery_executed = false;
    if (recover_arg.isSet() )
    {
        std::vector<uint8_t> fw_image = read_firmware_data(file_arg.isSet(), file_arg.getValue());

        std::cout << std::endl << "update to FW: " << file_arg.getValue() << std::endl;
        auto devs = ctx.query_devices(RS2_PRODUCT_LINE_DEPTH);
        for (auto&& d : devs)
        {
            if (!d.is<rs2::update_device>())
                continue;
            try
            {
                std::cout << std::endl << "recovering device: " << std::endl;
                print_device_info(d);
                update(d, fw_image);
                recovery_executed = true;
            }
            catch (...)
            {
                std::cout << std::endl << "failed to recover device" << std::endl;
            }
        }
        if (recovery_executed)
        {
            std::cout << std::endl << "recovery done" << std::endl;
            return EXIT_SUCCESS;
        }
        return EXIT_FAILURE;
    }

    // Update device
    ctx.set_devices_changed_callback([&](rs2::event_information& info)
    {
        if (info.get_new_devices().size() == 0)
        {
            return;
        }

        for (auto&& d : info.get_new_devices())
        {
            std::lock_guard<std::mutex> lk(mutex);
            if (d.is<rs2::update_device>() && (d.get_info(RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID) == update_serial_number))
                new_fw_update_device = d;
            else
                new_device = d;
        }
        if(new_fw_update_device || new_device)
            cv.notify_one();
    });

    auto devs = ctx.query_devices(RS2_PRODUCT_LINE_DEPTH);

    if (!serial_number_arg.isSet() && devs.size() > 1)
    {
        std::cout << std::endl << "more than one device is connected, serial number must be selected" << std::endl << std::endl;
        return EXIT_FAILURE;
    }

    bool device_found = false;

    for (auto&& d : devs)
    {
        if (!d.is<rs2::updatable>() || !(d.supports(RS2_CAMERA_INFO_SERIAL_NUMBER) && d.supports(RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID)))
            continue;

        if (d.supports(RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR))
        {
            std::string usb_type = d.get_info(RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR);
            if (usb_type.find("2.") != std::string::npos) {
                std::cout << std::endl << "Warning! the camera is connected via USB 2 port, in case the process fails, connect the camera to a USB 3 port and try again" << std::endl;
            }
        }

        update_serial_number = d.get_info(RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID);

        auto sn = d.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
        if (sn != selected_serial_number && devs.size() != 1)
            continue;
        device_found = true;
        auto fw = d.get_info(RS2_CAMERA_INFO_FIRMWARE_VERSION);

        if (backup_arg.isSet())
        {
            std::cout << std::endl << "backing-up device flash: " << std::endl;

            if (ISATTY(FILENO(stdout)))
            {
                auto flash = d.as<rs2::updatable>().create_flash_backup([&](const float progress)
                    {
                        printf("\rflash backup progress: %d[%%]", (int)(progress * 100));
                    });
            }
            else
                auto flash = d.as<rs2::updatable>().create_flash_backup([&](const float progress){});

            auto temp = backup_arg.getValue();
            std::ofstream file(temp.c_str(), std::ios::binary);
            file.write((const char*)flash.data(), flash.size());
        }

        if (!file_arg.isSet())
            continue;

        std::vector<uint8_t> fw_image = read_firmware_data(file_arg.isSet(), file_arg.getValue());

        std::cout << std::endl << "updating device: " << std::endl;
        print_device_info(d);

        if (unsigned_arg.isSet())
        {
            std::cout << std::endl << "firmware update started" << std::endl << std::endl;

            if (ISATTY(FILENO(stdout)))
            {
                d.as<rs2::updatable>().update_unsigned(fw_image, [&](const float progress)
                    {
                        printf("\rfirmware update progress: %d[%%]", (int)(progress * 100));
                    });
            }
            else
                d.as<rs2::updatable>().update_unsigned(fw_image, [&](const float progress){});

            std::cout << std::endl << std::endl << "firmware update done" << std::endl;
        }
        else
        {
            d.as<rs2::updatable>().enter_update_state();

            std::unique_lock<std::mutex> lk(mutex);
            if (!cv.wait_for(lk, std::chrono::seconds(WAIT_FOR_DEVICE_TIMEOUT), [&] { return new_fw_update_device; }))
            {
                std::cout << std::endl << "failed to locate a device in FW update mode" << std::endl;
                return EXIT_FAILURE;
            }

            update(new_fw_update_device, fw_image);
            done = true;
            break;
        }
    }

    if (!device_found)
    {
        if(serial_number_arg.isSet())
            std::cout << std::endl << "couldn't find the requested serial number" << std::endl;
        else if (devs.size() == 1)
        {
            std::cout << std::endl << "nothing to do, run again with -h for help" << std::endl;
        }
        return EXIT_FAILURE;
    }

    std::unique_lock<std::mutex> lk(mutex);
    cv.wait_for(lk, std::chrono::seconds(WAIT_FOR_DEVICE_TIMEOUT), [&] { return !done || new_device; });

    if (done)
    {
        auto devs = ctx.query_devices();
        for (auto&& d : devs)
        {
            auto sn = d.supports(RS2_CAMERA_INFO_SERIAL_NUMBER) ? d.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER) : "unknown";
            if (serial_number_arg.isSet() && sn != selected_serial_number)
                continue;

            auto fw = d.supports(RS2_CAMERA_INFO_FIRMWARE_VERSION) ? d.get_info(RS2_CAMERA_INFO_FIRMWARE_VERSION) : "unknown";
            std::cout << std::endl << "device " << sn << " successfully updated to FW: " << fw << std::endl;
        }
    }

    return EXIT_SUCCESS;
}
catch (const rs2::error & e)
{
    std::cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n    " << e.what() << std::endl;
    return EXIT_FAILURE;
}
<commit_msg>fix for bug<commit_after>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2015 Intel Corporation. All Rights Reserved.

#include <librealsense2/rs.hpp>

#include <vector>
#include <map>
#include <string>
#include <iostream>
#include <fstream>
#include <thread>
#include <mutex>
#include <chrono>
#include <condition_variable>

#include "tclap/CmdLine.h"
#include "tclap/ValueArg.h"

using namespace TCLAP;

#define WAIT_FOR_DEVICE_TIMEOUT 10

#if _WIN32
#include <io.h>
#define ISATTY _isatty
#define FILENO _fileno
#else
#include <unistd.h>
#define ISATTY isatty
#define FILENO fileno
#endif

std::vector<uint8_t> read_fw_file(std::string file_path)
{
    std::vector<uint8_t> rv;

    std::ifstream file(file_path, std::ios::in | std::ios::binary | std::ios::ate);
    if (file.is_open())
    {
        rv.resize(file.tellg());

        file.seekg(0, std::ios::beg);
        file.read((char*)rv.data(), rv.size());
        file.close();
    }

    return rv;
}

void print_device_info(rs2::device d)
{
    std::map<rs2_camera_info, std::string> camera_info;

    for (int i = 0; i < RS2_CAMERA_INFO_COUNT; i++)
    {
        auto info = (rs2_camera_info)i;
        camera_info[info] = d.supports(info) ? d.get_info(info) : "unknown";
    }

    std::cout << "Name: " << camera_info[RS2_CAMERA_INFO_NAME] <<
        ", serial number: " << camera_info[RS2_CAMERA_INFO_SERIAL_NUMBER] <<
        ", update serial number: " << camera_info[RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID] <<
        ", firmware version: " << camera_info[RS2_CAMERA_INFO_FIRMWARE_VERSION] <<
        ", USB type: " << camera_info[RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR] << std::endl;
}

std::vector<uint8_t> read_firmware_data(bool is_set, const std::string& file_path)
{
    if (!is_set)
    {
        throw rs2::error("firmware file must be selected");
    }

    std::vector<uint8_t> fw_image = read_fw_file(file_path);

    if (fw_image.size() == 0)
    {
        throw rs2::error("failed to read firmware file");
    }

    return fw_image;
}

void update(rs2::update_device fwu_dev, std::vector<uint8_t> fw_image)
{
    std::cout << std::endl << "firmware update started"<< std::endl << std::endl;

    if (ISATTY(FILENO(stdout)))
    {
        fwu_dev.update(fw_image, [&](const float progress)
            {
                printf("\rfirmware update progress: %d[%%]", (int)(progress * 100));
            });
    }
    else
        fwu_dev.update(fw_image, [&](const float progress){});

    std::cout << std::endl << std::endl << "firmware update done" << std::endl;
}

void list_devices(rs2::context ctx)
{
    auto devs = ctx.query_devices();
    if (devs.size() == 0)
    {
        std::cout << std::endl << "there are no connected devices" << std::endl;
        return;
    }

    std::cout << std::endl << "connected devices:" << std::endl;

    int counter = 0;
    for (auto&& d : devs)
    {
        std::cout << ++counter << ") ";
        print_device_info(d);
    }
}

int main(int argc, char** argv) try
{
#ifdef BUILD_EASYLOGGINGPP
    rs2::log_to_console(RS2_LOG_SEVERITY_ERROR);
#endif

    rs2::context ctx;

    std::condition_variable cv;
    std::mutex mutex;
    std::string selected_serial_number;

    rs2::device new_device;
    rs2::update_device new_fw_update_device;

    bool done = false;

    CmdLine cmd("librealsense rs-fw-update tool", ' ', RS2_API_VERSION_STR);

    SwitchArg list_devices_arg("l", "list_devices", "List all available devices");
    SwitchArg recover_arg("r", "recover", "Recover all connected devices which are in recovery mode");
    SwitchArg unsigned_arg("u", "unsigned", "Update unsigned firmware, available only for unlocked cameras");
    ValueArg<std::string> backup_arg("b", "backup", "Create a backup to the camera flash and saved it to the given path", false, "", "string");
    ValueArg<std::string> file_arg("f", "file", "Path of the firmware image file", false, "", "string");
    ValueArg<std::string> serial_number_arg("s", "serial_number", "The serial number of the device to be update, this is mandetory if more than one device is connected", false, "", "string");

    cmd.add(list_devices_arg);
    cmd.add(recover_arg);
    cmd.add(unsigned_arg);
    cmd.add(file_arg);
    cmd.add(serial_number_arg);
    cmd.add(backup_arg);

    cmd.parse(argc, argv);

    bool recovery_request = recover_arg.getValue();

    if (list_devices_arg.isSet())
    {
        list_devices(ctx);
        return EXIT_SUCCESS;
    }

    if (!file_arg.isSet() && !backup_arg.isSet())
    {
        std::cout << std::endl << "nothing to do, run again with -h for help" << std::endl;
        return EXIT_FAILURE;
    }

    if (serial_number_arg.isSet())
    {
        selected_serial_number = serial_number_arg.getValue();
        std::cout << std::endl << "search for device with serial number: " << selected_serial_number << std::endl;
    }

    std::string update_serial_number;

    // Recovery
    bool recovery_executed = false;
    if (recover_arg.isSet() )
    {
        std::vector<uint8_t> fw_image = read_firmware_data(file_arg.isSet(), file_arg.getValue());

        std::cout << std::endl << "update to FW: " << file_arg.getValue() << std::endl;
        auto devs = ctx.query_devices(RS2_PRODUCT_LINE_DEPTH);
        for (auto&& d : devs)
        {
            if (!d.is<rs2::update_device>())
                continue;
            try
            {
                std::cout << std::endl << "recovering device: " << std::endl;
                print_device_info(d);
                update(d, fw_image);
                recovery_executed = true;
            }
            catch (...)
            {
                std::cout << std::endl << "failed to recover device" << std::endl;
            }
        }
        if (recovery_executed)
        {
            std::cout << std::endl << "recovery done" << std::endl;
            return EXIT_SUCCESS;
        }
        return EXIT_FAILURE;
    }

    // Update device
    ctx.set_devices_changed_callback([&](rs2::event_information& info)
    {
        if (info.get_new_devices().size() == 0)
        {
            return;
        }

        for (auto&& d : info.get_new_devices())
        {
            std::lock_guard<std::mutex> lk(mutex);
            if (d.is<rs2::update_device>() && (d.get_info(RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID) == update_serial_number))
                new_fw_update_device = d;
            else
                new_device = d;
        }
        if(new_fw_update_device || new_device)
            cv.notify_one();
    });

    auto devs = ctx.query_devices(RS2_PRODUCT_LINE_DEPTH);

    if (!serial_number_arg.isSet() && devs.size() > 1)
    {
        std::cout << std::endl << "more than one device is connected, serial number must be selected" << std::endl << std::endl;
        return EXIT_FAILURE;
    }

    bool device_found = false;

    for (auto&& d : devs)
    {
        if (!d.is<rs2::updatable>() || !(d.supports(RS2_CAMERA_INFO_SERIAL_NUMBER) && d.supports(RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID)))
            continue;

        if (d.supports(RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR))
        {
            std::string usb_type = d.get_info(RS2_CAMERA_INFO_USB_TYPE_DESCRIPTOR);
            if (usb_type.find("2.") != std::string::npos) {
                std::cout << std::endl << "Warning! the camera is connected via USB 2 port, in case the process fails, connect the camera to a USB 3 port and try again" << std::endl;
            }
        }

        update_serial_number = d.get_info(RS2_CAMERA_INFO_FIRMWARE_UPDATE_ID);

        auto sn = d.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER);
        if (sn != selected_serial_number && devs.size() != 1)
            continue;
        device_found = true;
        auto fw = d.get_info(RS2_CAMERA_INFO_FIRMWARE_VERSION);

        if (backup_arg.isSet())
        {
            std::cout << std::endl << "backing-up device flash: " << std::endl;

            std::vector< uint8_t > flash;
            if( ISATTY( FILENO( stdout )))
            {
                flash = d.as< rs2::updatable >().create_flash_backup( [&]( const float progress ) {
                    printf( "\rflash backup progress: %d[%%]", (int)( progress * 100 ) );
                } );
            }
            else
                flash = d.as<rs2::updatable>().create_flash_backup([&](const float progress){});

            auto temp = backup_arg.getValue();
            std::ofstream file(temp.c_str(), std::ios::binary);
            file.write((const char*)flash.data(), flash.size());
        }

        if (!file_arg.isSet())
            continue;

        std::vector<uint8_t> fw_image = read_firmware_data(file_arg.isSet(), file_arg.getValue());

        std::cout << std::endl << "updating device: " << std::endl;
        print_device_info(d);

        if (unsigned_arg.isSet())
        {
            std::cout << std::endl << "firmware update started" << std::endl << std::endl;

            if (ISATTY(FILENO(stdout)))
            {
                d.as<rs2::updatable>().update_unsigned(fw_image, [&](const float progress)
                    {
                        printf("\rfirmware update progress: %d[%%]", (int)(progress * 100));
                    });
            }
            else
                d.as<rs2::updatable>().update_unsigned(fw_image, [&](const float progress){});

            std::cout << std::endl << std::endl << "firmware update done" << std::endl;
        }
        else
        {
            d.as<rs2::updatable>().enter_update_state();

            std::unique_lock<std::mutex> lk(mutex);
            if (!cv.wait_for(lk, std::chrono::seconds(WAIT_FOR_DEVICE_TIMEOUT), [&] { return new_fw_update_device; }))
            {
                std::cout << std::endl << "failed to locate a device in FW update mode" << std::endl;
                return EXIT_FAILURE;
            }

            update(new_fw_update_device, fw_image);
            done = true;
            break;
        }
    }

    if (!device_found)
    {
        if(serial_number_arg.isSet())
            std::cout << std::endl << "couldn't find the requested serial number" << std::endl;
        else if (devs.size() == 1)
        {
            std::cout << std::endl << "nothing to do, run again with -h for help" << std::endl;
        }
        return EXIT_FAILURE;
    }

    std::unique_lock<std::mutex> lk(mutex);
    cv.wait_for(lk, std::chrono::seconds(WAIT_FOR_DEVICE_TIMEOUT), [&] { return !done || new_device; });

    if (done)
    {
        auto devs = ctx.query_devices();
        for (auto&& d : devs)
        {
            auto sn = d.supports(RS2_CAMERA_INFO_SERIAL_NUMBER) ? d.get_info(RS2_CAMERA_INFO_SERIAL_NUMBER) : "unknown";
            if (serial_number_arg.isSet() && sn != selected_serial_number)
                continue;

            auto fw = d.supports(RS2_CAMERA_INFO_FIRMWARE_VERSION) ? d.get_info(RS2_CAMERA_INFO_FIRMWARE_VERSION) : "unknown";
            std::cout << std::endl << "device " << sn << " successfully updated to FW: " << fw << std::endl;
        }
    }

    return EXIT_SUCCESS;
}
catch (const rs2::error & e)
{
    std::cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n    " << e.what() << std::endl;
    return EXIT_FAILURE;
}
<|endoftext|>


<commit_before>#include "rsys/common.h"
#include "rsys/host.h"
#include "rsys/vdriver.h"
#include "rsys/cquick.h" /* for ROMlib_log2 */
#include "rsys/adb.h"
#include "rsys/osevent.h"
#include "rsys/scrap.h"
#include "rsys/keyboard.h"
#include "OSEvent.h"
#include "ToolboxEvent.h"
#include "SegmentLdr.h"
#include "ScrapMgr.h"

#include "keycode_map.h"

#include <SDL.h>

namespace Executor
{
/* These variables are required by the vdriver interface. */
uint8_t *vdriver_fbuf;
int vdriver_row_bytes;
int vdriver_width = 1024;
int vdriver_height = 768;
int vdriver_bpp = 8, vdriver_log2_bpp;
int vdriver_max_bpp, vdriver_log2_max_bpp;
vdriver_modes_t *vdriver_mode_list;

int host_cursor_depth = 1;
}

using namespace Executor;

namespace
{
vdriver_modes_t sdl_impotent_modes = { 0, 0 };
SDL_Window *sdlWindow;
SDL_Renderer *sdlRenderer;
SDL_Texture *sdlTexture;
SDL_Surface *sdlSurface;
}

void Executor::vdriver_opt_register(void)
{
}
bool Executor::vdriver_init(int _max_width, int _max_height, int _max_bpp,
                            bool fixed_p, int *argc, char *argv[])
{
    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0)
    {
        SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
        return false;
    }
    return true;
}

bool Executor::vdriver_acceptable_mode_p(int width, int height, int bpp,
                                         bool grayscale_p, bool exact_match_p)
{
    if(bpp == 1 || bpp == 4 || bpp == 8 || bpp == 16 || bpp == 32)
        return true;
    else
        return false;
}

bool Executor::vdriver_set_mode(int width, int height, int bpp, bool grayscale_p)
{
    printf("set_mode: %d %d %d", width, height, bpp);
    if(vdriver_fbuf)
        delete[] vdriver_fbuf;

    if(width)
        vdriver_width = width;
    if(height)
        vdriver_height = height;
    if(bpp)
        vdriver_bpp = bpp;
    vdriver_row_bytes = vdriver_width * vdriver_bpp / 8;
    vdriver_log2_bpp = ROMlib_log2[vdriver_bpp];
    vdriver_mode_list = &sdl_impotent_modes;

    vdriver_max_bpp = 8; //32;
    vdriver_log2_max_bpp = 3; //5;

    sdlWindow = SDL_CreateWindow("Window",
                                 SDL_WINDOWPOS_UNDEFINED,
                                 SDL_WINDOWPOS_UNDEFINED,
                                 vdriver_width, vdriver_height,
                                 0);
    //SDL_WINDOW_FULLSCREEN_DESKTOP);

    /*sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0);

    SDL_RenderSetLogicalSize(sdlRenderer, vdriver_width, vdriver_height);
    SDL_SetRenderDrawColor(sdlRenderer, 128, 128, 128, 255);
    SDL_RenderClear(sdlRenderer);
    SDL_RenderPresent(sdlRenderer);*/

    uint32_t pixelFormat;

    switch(vdriver_bpp)
    {
        case 1:
            pixelFormat = SDL_PIXELFORMAT_INDEX1LSB;
            break;
        case 4:
            pixelFormat = SDL_PIXELFORMAT_INDEX4LSB;
            break;
        case 8:
            pixelFormat = SDL_PIXELFORMAT_INDEX8;
            break;
        case 16:
            pixelFormat = SDL_PIXELFORMAT_RGB555;
            break;
        case 32:
            pixelFormat = SDL_PIXELFORMAT_BGRX8888;
            break;
        default:
            std::abort();
    }

    vdriver_fbuf = new uint8_t[vdriver_width * vdriver_height * 4];

    sdlSurface = SDL_CreateRGBSurfaceWithFormatFrom(
        vdriver_fbuf,
        vdriver_width, vdriver_height,
        vdriver_bpp,
        vdriver_row_bytes,
        pixelFormat);

    return true;
}
void Executor::vdriver_set_colors(int first_color, int num_colors, const ColorSpec *colors)
{
    SDL_Color *sdlColors = (SDL_Color *)alloca(sizeof(SDL_Color) * num_colors);
    for(int i = 0; i < num_colors; i++)
    {
        sdlColors[i].a = 255;
        sdlColors[i].r = CW(colors[i].rgb.red) >> 8;
        sdlColors[i].g = CW(colors[i].rgb.green) >> 8;
        sdlColors[i].b = CW(colors[i].rgb.blue) >> 8;
    }

    SDL_SetPaletteColors(sdlSurface->format->palette, sdlColors, first_color, num_colors);
}

void Executor::vdriver_get_colors(int first_color, int num_colors, ColorSpec *colors)
{
    SDL_Color *sdlColors = sdlSurface->format->palette->colors;
    for(int i = 0; i < num_colors; i++)
    {
        SDL_Color &c = sdlColors[first_color + i];

        colors[i].value = CW(first_color + i);
        colors[i].rgb.red = CW(c.r << 8 | c.r);
        colors[i].rgb.green = CW(c.g << 8 | c.g);
        colors[i].rgb.blue = CW(c.b << 8 | c.b);
    }
}
int Executor::vdriver_update_screen_rects(int num_rects, const vdriver_rect_t *r,
                                          bool cursor_p)
{
    /*SDL_UpdateTexture(sdlTexture, NULL, vdriver_fbuf, vdriver_row_bytes);
    SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
    SDL_RenderPresent(sdlRenderer);*/
    SDL_BlitSurface(sdlSurface, NULL, SDL_GetWindowSurface(sdlWindow), NULL);
    SDL_UpdateWindowSurface(sdlWindow);
}

int Executor::vdriver_update_screen(int top, int left, int bottom, int right,
                                    bool cursor_p)
{
    /*SDL_UpdateTexture(sdlTexture, NULL, vdriver_fbuf, vdriver_row_bytes);
    SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
    SDL_RenderPresent(sdlRenderer);*/
    SDL_BlitSurface(sdlSurface, NULL, SDL_GetWindowSurface(sdlWindow), NULL);
    SDL_UpdateWindowSurface(sdlWindow);
}

void Executor::vdriver_flush_display(void)
{
}

void Executor::vdriver_shutdown(void)
{
}

void Executor::host_flush_shadow_screen(void)
{
}

static bool ConfirmQuit()
{
    const SDL_MessageBoxButtonData buttons[] = {
        { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 2, "Cancel" },
        { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "Force Quit" },
    };
    const SDL_MessageBoxData messageboxdata = {
        SDL_MESSAGEBOX_INFORMATION, /* .flags */
        sdlWindow, /* .window */
        "Quit", /* .title */
        "Do you want to quit Executor?", /* .message */
        SDL_arraysize(buttons), /* .numbuttons */
        buttons, /* .buttons */
        NULL /* .colorScheme */
    };
    int buttonid;
    SDL_ShowMessageBox(&messageboxdata, &buttonid);
    return buttonid == 1;
}

static bool isModifier(unsigned char virt, uint16 *modstore)
{
    /* Note: shift and control can be cleared if right* and left* are pressed */
    switch(virt)
    {
        case MKV_LEFTSHIFT:
        case MKV_RIGHTSHIFT:
            *modstore = shiftKey;
            break;
        case MKV_CAPS:
            *modstore = alphaLock;
            break;
        case MKV_LEFTCNTL:
        case MKV_RIGHTCNTL:
            *modstore = ControlKey;
            break;
        case MKV_CLOVER:
            *modstore = cmdKey;
            break;
        case MKV_LEFTOPTION:
        case MKV_RIGHTOPTION:
            *modstore = optionKey;
            break;
        default:
            *modstore = 0;
            return false;
    }
    return true;
}

void Executor::vdriver_pump_events()
{
    SDL_Event event;
    static uint16_t keymod = 0;

    while(SDL_PollEvent(&event))
    {
        switch(event.type)
        {
            case SDL_MOUSEMOTION:
                MouseLocation.h = CW(event.motion.x);
                MouseLocation.v = CW(event.motion.y);

                adb_apeiron_hack(false);
                break;
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP:
            {
                bool down_p;
                int32 when;
                Point where;

                down_p = (event.button.state == SDL_PRESSED);
                if(down_p)
                    keymod &= ~btnState;
                else
                    keymod |= btnState;
                when = TickCount();
                where.h = event.button.x;
                where.v = event.button.y;
                ROMlib_PPostEvent(down_p ? mouseDown : mouseUp,
                                  0, (GUEST<EvQElPtr> *)0, when, where,
                                  keymod);
                adb_apeiron_hack(false);
            }
            break;
            case SDL_KEYDOWN:
            case SDL_KEYUP:
            {
                bool down_p;
                unsigned char mkvkey;
                uint16 mod;
                LONGINT keywhat;
                int32 when;
                Point where;

                init_sdlk_to_mkv();
                down_p = (event.key.state == SDL_PRESSED);

                /*if(use_scan_codes)
                    mkvkey = ibm_virt_to_mac_virt[event.key.keysym.scancode];
                else*/
                {
                    auto p = sdlk_to_mkv.find(event.key.keysym.sym);
                    if(p == sdlk_to_mkv.end())
                        mkvkey = NOTAKEY;
                    else
                        mkvkey = p->second;
                }
                mkvkey = ROMlib_right_to_left_key_map(mkvkey);
                if(isModifier(mkvkey, &mod))
                {
                    if(down_p)
                        keymod |= mod;
                    else
                        keymod &= ~mod;
                }
                when = TickCount();
                where.h = CW(MouseLocation.h);
                where.v = CW(MouseLocation.v);
                keywhat = ROMlib_xlate(mkvkey, keymod, down_p);
                post_keytrans_key_events(down_p ? keyDown : keyUp,
                                         keywhat, when, where,
                                         keymod, mkvkey);
            }
            break;
            case SDL_WINDOWEVENT_FOCUS_GAINED:
                //if(!we_lost_clipboard())
                    sendresumeevent(false);
                //else
                //{
                //    ZeroScrap();
                //    sendresumeevent(true);
                //}
                break;
            case SDL_WINDOWEVENT_FOCUS_LOST:
                sendsuspendevent();
                break;
            case SDL_QUIT:
                if(ConfirmQuit())
                    ExitToShell();
                break;
        }
    }
}

extern "C" void
ROMlib_SetTitle(char *title)
{
}

extern "C" char *
ROMlib_GetTitle(void)
{
    static char str[] = "Foo";
    return str;
}

extern "C" void
ROMlib_FreeTitle(char *title)
{
}

/* This is really inefficient.  We should hash the cursors */
void Executor::host_set_cursor(char *cursor_data,
                               unsigned short cursor_mask[16],
                               int hotspot_x, int hotspot_y)
{
    SDL_Cursor *old_cursor, *new_cursor;

    old_cursor = SDL_GetCursor();
    new_cursor = SDL_CreateCursor((unsigned char *)cursor_data,
                                  (unsigned char *)cursor_mask,
                                  16, 16, hotspot_x, hotspot_y);
    if(new_cursor != NULL)
    {
        SDL_SetCursor(new_cursor);
        SDL_FreeCursor(old_cursor);
    }
}

int Executor::host_set_cursor_visible(int show_p)
{
    return (SDL_ShowCursor(show_p));
}
<commit_msg>sdl2: SDL_CreateRGBSurfaceWithFormatFrom is only available starting in sdl 2.0.5, be conservative and use PixelFormatEnumToMasks and CreateRGBSurfaceFrom instead<commit_after>#include "rsys/common.h"
#include "rsys/host.h"
#include "rsys/vdriver.h"
#include "rsys/cquick.h" /* for ROMlib_log2 */
#include "rsys/adb.h"
#include "rsys/osevent.h"
#include "rsys/scrap.h"
#include "rsys/keyboard.h"
#include "OSEvent.h"
#include "ToolboxEvent.h"
#include "SegmentLdr.h"
#include "ScrapMgr.h"

#include "keycode_map.h"

#include <SDL.h>

namespace Executor
{
/* These variables are required by the vdriver interface. */
uint8_t *vdriver_fbuf;
int vdriver_row_bytes;
int vdriver_width = 1024;
int vdriver_height = 768;
int vdriver_bpp = 8, vdriver_log2_bpp;
int vdriver_max_bpp, vdriver_log2_max_bpp;
vdriver_modes_t *vdriver_mode_list;

int host_cursor_depth = 1;
}

using namespace Executor;

namespace
{
vdriver_modes_t sdl_impotent_modes = { 0, 0 };
SDL_Window *sdlWindow;
SDL_Renderer *sdlRenderer;
SDL_Texture *sdlTexture;
SDL_Surface *sdlSurface;
}

void Executor::vdriver_opt_register(void)
{
}
bool Executor::vdriver_init(int _max_width, int _max_height, int _max_bpp,
                            bool fixed_p, int *argc, char *argv[])
{
    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0)
    {
        SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
        return false;
    }
    return true;
}

bool Executor::vdriver_acceptable_mode_p(int width, int height, int bpp,
                                         bool grayscale_p, bool exact_match_p)
{
    if(bpp == 1 || bpp == 4 || bpp == 8 || bpp == 16 || bpp == 32)
        return true;
    else
        return false;
}

bool Executor::vdriver_set_mode(int width, int height, int bpp, bool grayscale_p)
{
    printf("set_mode: %d %d %d", width, height, bpp);
    if(vdriver_fbuf)
        delete[] vdriver_fbuf;

    if(width)
        vdriver_width = width;
    if(height)
        vdriver_height = height;
    if(bpp)
        vdriver_bpp = bpp;
    vdriver_row_bytes = vdriver_width * vdriver_bpp / 8;
    vdriver_log2_bpp = ROMlib_log2[vdriver_bpp];
    vdriver_mode_list = &sdl_impotent_modes;

    vdriver_max_bpp = 8; //32;
    vdriver_log2_max_bpp = 3; //5;

    sdlWindow = SDL_CreateWindow("Window",
                                 SDL_WINDOWPOS_UNDEFINED,
                                 SDL_WINDOWPOS_UNDEFINED,
                                 vdriver_width, vdriver_height,
                                 0);
    //SDL_WINDOW_FULLSCREEN_DESKTOP);

    /*sdlRenderer = SDL_CreateRenderer(sdlWindow, -1, 0);

    SDL_RenderSetLogicalSize(sdlRenderer, vdriver_width, vdriver_height);
    SDL_SetRenderDrawColor(sdlRenderer, 128, 128, 128, 255);
    SDL_RenderClear(sdlRenderer);
    SDL_RenderPresent(sdlRenderer);*/

    uint32_t pixelFormat;

    switch(vdriver_bpp)
    {
        case 1:
            pixelFormat = SDL_PIXELFORMAT_INDEX1LSB;
            break;
        case 4:
            pixelFormat = SDL_PIXELFORMAT_INDEX4LSB;
            break;
        case 8:
            pixelFormat = SDL_PIXELFORMAT_INDEX8;
            break;
        case 16:
            pixelFormat = SDL_PIXELFORMAT_RGB555;
            break;
        case 32:
            pixelFormat = SDL_PIXELFORMAT_BGRX8888;
            break;
        default:
            std::abort();
    }

    vdriver_fbuf = new uint8_t[vdriver_width * vdriver_height * 4];

#if 1
    uint32_t rmask, gmask, bmask, amask;
    int sdlBpp;
    SDL_PixelFormatEnumToMasks(pixelFormat, &sdlBpp, &rmask, &gmask, &bmask, &amask);

    sdlSurface = SDL_CreateRGBSurfaceFrom(
        vdriver_fbuf,
        vdriver_width, vdriver_height,
        sdlBpp,
        vdriver_row_bytes,
        rmask, gmask, bmask, amask);
#else
    sdlSurface = SDL_CreateRGBSurfaceWithFormatFrom(
        vdriver_fbuf,
        vdriver_width, vdriver_height,
        vdriver_bpp,
        vdriver_row_bytes,
        pixelFormat);
#endif

    return true;
}
void Executor::vdriver_set_colors(int first_color, int num_colors, const ColorSpec *colors)
{
    SDL_Color *sdlColors = (SDL_Color *)alloca(sizeof(SDL_Color) * num_colors);
    for(int i = 0; i < num_colors; i++)
    {
        sdlColors[i].a = 255;
        sdlColors[i].r = CW(colors[i].rgb.red) >> 8;
        sdlColors[i].g = CW(colors[i].rgb.green) >> 8;
        sdlColors[i].b = CW(colors[i].rgb.blue) >> 8;
    }

    SDL_SetPaletteColors(sdlSurface->format->palette, sdlColors, first_color, num_colors);
}

void Executor::vdriver_get_colors(int first_color, int num_colors, ColorSpec *colors)
{
    SDL_Color *sdlColors = sdlSurface->format->palette->colors;
    for(int i = 0; i < num_colors; i++)
    {
        SDL_Color &c = sdlColors[first_color + i];

        colors[i].value = CW(first_color + i);
        colors[i].rgb.red = CW(c.r << 8 | c.r);
        colors[i].rgb.green = CW(c.g << 8 | c.g);
        colors[i].rgb.blue = CW(c.b << 8 | c.b);
    }
}
int Executor::vdriver_update_screen_rects(int num_rects, const vdriver_rect_t *r,
                                          bool cursor_p)
{
    /*SDL_UpdateTexture(sdlTexture, NULL, vdriver_fbuf, vdriver_row_bytes);
    SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
    SDL_RenderPresent(sdlRenderer);*/
    SDL_BlitSurface(sdlSurface, NULL, SDL_GetWindowSurface(sdlWindow), NULL);
    SDL_UpdateWindowSurface(sdlWindow);
}

int Executor::vdriver_update_screen(int top, int left, int bottom, int right,
                                    bool cursor_p)
{
    /*SDL_UpdateTexture(sdlTexture, NULL, vdriver_fbuf, vdriver_row_bytes);
    SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
    SDL_RenderPresent(sdlRenderer);*/
    SDL_BlitSurface(sdlSurface, NULL, SDL_GetWindowSurface(sdlWindow), NULL);
    SDL_UpdateWindowSurface(sdlWindow);
}

void Executor::vdriver_flush_display(void)
{
}

void Executor::vdriver_shutdown(void)
{
}

void Executor::host_flush_shadow_screen(void)
{
}

static bool ConfirmQuit()
{
    const SDL_MessageBoxButtonData buttons[] = {
        { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 2, "Cancel" },
        { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "Force Quit" },
    };
    const SDL_MessageBoxData messageboxdata = {
        SDL_MESSAGEBOX_INFORMATION, /* .flags */
        sdlWindow, /* .window */
        "Quit", /* .title */
        "Do you want to quit Executor?", /* .message */
        SDL_arraysize(buttons), /* .numbuttons */
        buttons, /* .buttons */
        NULL /* .colorScheme */
    };
    int buttonid;
    SDL_ShowMessageBox(&messageboxdata, &buttonid);
    return buttonid == 1;
}

static bool isModifier(unsigned char virt, uint16 *modstore)
{
    /* Note: shift and control can be cleared if right* and left* are pressed */
    switch(virt)
    {
        case MKV_LEFTSHIFT:
        case MKV_RIGHTSHIFT:
            *modstore = shiftKey;
            break;
        case MKV_CAPS:
            *modstore = alphaLock;
            break;
        case MKV_LEFTCNTL:
        case MKV_RIGHTCNTL:
            *modstore = ControlKey;
            break;
        case MKV_CLOVER:
            *modstore = cmdKey;
            break;
        case MKV_LEFTOPTION:
        case MKV_RIGHTOPTION:
            *modstore = optionKey;
            break;
        default:
            *modstore = 0;
            return false;
    }
    return true;
}

void Executor::vdriver_pump_events()
{
    SDL_Event event;
    static uint16_t keymod = 0;

    while(SDL_PollEvent(&event))
    {
        switch(event.type)
        {
            case SDL_MOUSEMOTION:
                MouseLocation.h = CW(event.motion.x);
                MouseLocation.v = CW(event.motion.y);

                adb_apeiron_hack(false);
                break;
            case SDL_MOUSEBUTTONDOWN:
            case SDL_MOUSEBUTTONUP:
            {
                bool down_p;
                int32 when;
                Point where;

                down_p = (event.button.state == SDL_PRESSED);
                if(down_p)
                    keymod &= ~btnState;
                else
                    keymod |= btnState;
                when = TickCount();
                where.h = event.button.x;
                where.v = event.button.y;
                ROMlib_PPostEvent(down_p ? mouseDown : mouseUp,
                                  0, (GUEST<EvQElPtr> *)0, when, where,
                                  keymod);
                adb_apeiron_hack(false);
            }
            break;
            case SDL_KEYDOWN:
            case SDL_KEYUP:
            {
                bool down_p;
                unsigned char mkvkey;
                uint16 mod;
                LONGINT keywhat;
                int32 when;
                Point where;

                init_sdlk_to_mkv();
                down_p = (event.key.state == SDL_PRESSED);

                /*if(use_scan_codes)
                    mkvkey = ibm_virt_to_mac_virt[event.key.keysym.scancode];
                else*/
                {
                    auto p = sdlk_to_mkv.find(event.key.keysym.sym);
                    if(p == sdlk_to_mkv.end())
                        mkvkey = NOTAKEY;
                    else
                        mkvkey = p->second;
                }
                mkvkey = ROMlib_right_to_left_key_map(mkvkey);
                if(isModifier(mkvkey, &mod))
                {
                    if(down_p)
                        keymod |= mod;
                    else
                        keymod &= ~mod;
                }
                when = TickCount();
                where.h = CW(MouseLocation.h);
                where.v = CW(MouseLocation.v);
                keywhat = ROMlib_xlate(mkvkey, keymod, down_p);
                post_keytrans_key_events(down_p ? keyDown : keyUp,
                                         keywhat, when, where,
                                         keymod, mkvkey);
            }
            break;
            case SDL_WINDOWEVENT_FOCUS_GAINED:
                //if(!we_lost_clipboard())
                    sendresumeevent(false);
                //else
                //{
                //    ZeroScrap();
                //    sendresumeevent(true);
                //}
                break;
            case SDL_WINDOWEVENT_FOCUS_LOST:
                sendsuspendevent();
                break;
            case SDL_QUIT:
                if(ConfirmQuit())
                    ExitToShell();
                break;
        }
    }
}

extern "C" void
ROMlib_SetTitle(char *title)
{
}

extern "C" char *
ROMlib_GetTitle(void)
{
    static char str[] = "Foo";
    return str;
}

extern "C" void
ROMlib_FreeTitle(char *title)
{
}

/* This is really inefficient.  We should hash the cursors */
void Executor::host_set_cursor(char *cursor_data,
                               unsigned short cursor_mask[16],
                               int hotspot_x, int hotspot_y)
{
    SDL_Cursor *old_cursor, *new_cursor;

    old_cursor = SDL_GetCursor();
    new_cursor = SDL_CreateCursor((unsigned char *)cursor_data,
                                  (unsigned char *)cursor_mask,
                                  16, 16, hotspot_x, hotspot_y);
    if(new_cursor != NULL)
    {
        SDL_SetCursor(new_cursor);
        SDL_FreeCursor(old_cursor);
    }
}

int Executor::host_set_cursor_visible(int show_p)
{
    return (SDL_ShowCursor(show_p));
}
<|endoftext|>


<commit_before>#include "types/root_typemanager.h"
#include "context/root_static_context.h"
#include "system/globalenv.h"

namespace zorba {

static const char *default_ns_initializers [] = {
  "fn", XQUERY_FN_NS,
  "xml", "http://www.w3.org/XML/1998/namespace",
  "xs", "http://www.w3.org/2001/XMLSchema",
  "xsi", "http://www.w3.org/2001/XMLSchema-instance",
  "local", "http://www.w3.org/2005/xquery-local-functions",
  NULL, NULL
};

root_static_context::root_static_context()
    : static_context()
{
  typemgr.reset(new RootTypeManager());
}

void root_static_context::init() {
  set_xpath1_0compatib_mode(StaticContextConsts::xpath2_0);
  const char **p = default_ns_initializers;
  for (; *p != NULL; p += 2)
    bind_ns (p [0], p [1]);
  set_default_elem_type_ns ("");
  set_default_function_namespace (lookup_ns ("fn"));
  set_context_item_static_type(GENV_TYPESYSTEM.ITEM_TYPE_ONE);
  set_default_collation_uri ("http://www.flworfound.org/collations/IDENTICAL/en/US");
  set_construction_mode(StaticContextConsts::cons_strip);
  set_ordering_mode(StaticContextConsts::ordered);
  set_order_empty_mode(StaticContextConsts::empty_greatest);
  set_boundary_space_mode(StaticContextConsts::strip_space);
  set_inherit_mode(StaticContextConsts::no_inherit_ns);
  set_preserve_mode(StaticContextConsts::no_preserve_ns);
  set_default_collection_type(GENV_TYPESYSTEM.ITEM_TYPE_STAR);

  set_current_absolute_baseuri("");
}

root_static_context::~root_static_context()
{
}

}
/* vim:set ts=2 sw=2: */
<commit_msg>Added ns binding for err<commit_after>#include "types/root_typemanager.h"
#include "context/root_static_context.h"
#include "system/globalenv.h"

namespace zorba {

static const char *default_ns_initializers [] = {
  "fn", XQUERY_FN_NS,
  "xml", "http://www.w3.org/XML/1998/namespace",
  "xs", "http://www.w3.org/2001/XMLSchema",
  "xsi", "http://www.w3.org/2001/XMLSchema-instance",
  "local", "http://www.w3.org/2005/xquery-local-functions",
  "err", "http://www.w3.org/2005/xqt-errors",
  NULL, NULL
};

root_static_context::root_static_context()
    : static_context()
{
  typemgr.reset(new RootTypeManager());
}

void root_static_context::init() {
  set_xpath1_0compatib_mode(StaticContextConsts::xpath2_0);
  const char **p = default_ns_initializers;
  for (; *p != NULL; p += 2)
    bind_ns (p [0], p [1]);
  set_default_elem_type_ns ("");
  set_default_function_namespace (lookup_ns ("fn"));
  set_context_item_static_type(GENV_TYPESYSTEM.ITEM_TYPE_ONE);
  set_default_collation_uri ("http://www.flworfound.org/collations/IDENTICAL/en/US");
  set_construction_mode(StaticContextConsts::cons_strip);
  set_ordering_mode(StaticContextConsts::ordered);
  set_order_empty_mode(StaticContextConsts::empty_greatest);
  set_boundary_space_mode(StaticContextConsts::strip_space);
  set_inherit_mode(StaticContextConsts::no_inherit_ns);
  set_preserve_mode(StaticContextConsts::no_preserve_ns);
  set_default_collection_type(GENV_TYPESYSTEM.ITEM_TYPE_STAR);

  set_current_absolute_baseuri("");
}

root_static_context::~root_static_context()
{
}

}
/* vim:set ts=2 sw=2: */
<|endoftext|>


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

#include <controller/AutoCommissioner.h>

#include <controller/CHIPDeviceController.h>

namespace chip {
namespace Controller {

CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParameters & params)
{
    mParams = params;
    if (params.HasThreadOperationalDataset())
    {
        ByteSpan dataset = params.GetThreadOperationalDataset().Value();
        if (dataset.size() > CommissioningParameters::kMaxCredentialsLen)
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        memcpy(mThreadOperationalDataset, dataset.data(), dataset.size());
        mParams.SetThreadOperationalDataset(ByteSpan(mThreadOperationalDataset, dataset.size()));
    }
    if (params.HasWiFiCredentials())
    {
        WiFiCredentials creds = params.GetWiFiCredentials().Value();
        if (creds.ssid.size() > CommissioningParameters::kMaxSsidLen ||
            creds.credentials.size() > CommissioningParameters::kMaxCredentialsLen)
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        memcpy(mSsid, creds.ssid.data(), creds.ssid.size());
        memcpy(mCredentials, creds.credentials.data(), creds.credentials.size());
        mParams.SetWiFiCredentials(
            WiFiCredentials(ByteSpan(mSsid, creds.ssid.size()), ByteSpan(mCredentials, creds.credentials.size())));
    }
    return CHIP_NO_ERROR;
}

CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStage currentStage, CHIP_ERROR lastErr)
{
    if (lastErr != CHIP_NO_ERROR)
    {
        return CommissioningStage::kCleanup;
    }
    switch (currentStage)
    {
    case CommissioningStage::kSecurePairing:
        return CommissioningStage::kArmFailsafe;
    case CommissioningStage::kArmFailsafe:
        return CommissioningStage::kConfigRegulatory;
    case CommissioningStage::kConfigRegulatory:
        return CommissioningStage::kDeviceAttestation;
    case CommissioningStage::kDeviceAttestation:
        // TODO(cecille): device attestation casues operational cert provisioinging to happen, This should be a separate stage.
        // For thread and wifi, this should go to network setup then enable. For on-network we can skip right to finding the
        // operational network because the provisioning of certificates will trigger the device to start operational advertising.
        if (mParams.HasWiFiCredentials())
        {
            return CommissioningStage::kWiFiNetworkSetup;
        }
        else if (mParams.HasThreadOperationalDataset())
        {
            return CommissioningStage::kThreadNetworkSetup;
        }
        else
        {
#if CHIP_DEVICE_CONFIG_ENABLE_DNSSD
            return CommissioningStage::kFindOperational;
#else
            return CommissioningStage::kSendComplete;
#endif
        }
    case CommissioningStage::kWiFiNetworkSetup:
        if (mParams.HasThreadOperationalDataset())
        {
            return CommissioningStage::kThreadNetworkSetup;
        }
        else
        {
            return CommissioningStage::kWiFiNetworkEnable;
        }
    case CommissioningStage::kThreadNetworkSetup:
        if (mParams.HasWiFiCredentials())
        {
            return CommissioningStage::kWiFiNetworkEnable;
        }
        else
        {
            return CommissioningStage::kThreadNetworkEnable;
        }

    case CommissioningStage::kWiFiNetworkEnable:
        if (mParams.HasThreadOperationalDataset())
        {
            return CommissioningStage::kThreadNetworkEnable;
        }
        else
        {
            return CommissioningStage::kFindOperational;
        }
    case CommissioningStage::kThreadNetworkEnable:
        return CommissioningStage::kFindOperational;
    case CommissioningStage::kFindOperational:
        return CommissioningStage::kSendComplete;
    case CommissioningStage::kSendComplete:
        return CommissioningStage::kCleanup;

    // Currently unimplemented.
    case CommissioningStage::kConfigACL:
    case CommissioningStage::kCheckCertificates:
        return CommissioningStage::kError;
    // Neither of these have a next stage so return kError;
    case CommissioningStage::kCleanup:
    case CommissioningStage::kError:
        return CommissioningStage::kError;
    }
    return CommissioningStage::kError;
}

void AutoCommissioner::StartCommissioning(CommissioneeDeviceProxy * proxy)
{
    // TODO: check that there is no commissioning in progress currently.
    mCommissioneeDeviceProxy = proxy;
    mCommissioner->PerformCommissioningStep(mCommissioneeDeviceProxy, CommissioningStage::kArmFailsafe, mParams, this);
}

void AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, CommissioningDelegate::CommissioningReport report)
{
    if (report.stageCompleted == CommissioningStage::kFindOperational)
    {
        mOperationalDeviceProxy = report.OperationalNodeFoundData.operationalProxy;
    }
    CommissioningStage nextStage = GetNextCommissioningStage(report.stageCompleted, err);
    DeviceProxy * proxy          = mCommissioneeDeviceProxy;
    if (nextStage == CommissioningStage::kSendComplete ||
        (nextStage == CommissioningStage::kCleanup && mOperationalDeviceProxy != nullptr))
    {
        proxy = mOperationalDeviceProxy;
    }

    if (proxy == nullptr)
    {
        ChipLogError(Controller, "Invalid device for commissioning");
        return;
    }
    mParams.SetCompletionStatus(err);
    mCommissioner->PerformCommissioningStep(proxy, nextStage, mParams, this);
}

} // namespace Controller
} // namespace chip
<commit_msg>Fix sizing on thread data set (#13662)<commit_after>/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *    All rights reserved.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

#include <controller/AutoCommissioner.h>

#include <controller/CHIPDeviceController.h>

namespace chip {
namespace Controller {

CHIP_ERROR AutoCommissioner::SetCommissioningParameters(const CommissioningParameters & params)
{
    mParams = params;
    if (params.HasThreadOperationalDataset())
    {
        ByteSpan dataset = params.GetThreadOperationalDataset().Value();
        if (dataset.size() > CommissioningParameters::kMaxThreadDatasetLen)
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        memcpy(mThreadOperationalDataset, dataset.data(), dataset.size());
        mParams.SetThreadOperationalDataset(ByteSpan(mThreadOperationalDataset, dataset.size()));
    }
    if (params.HasWiFiCredentials())
    {
        WiFiCredentials creds = params.GetWiFiCredentials().Value();
        if (creds.ssid.size() > CommissioningParameters::kMaxSsidLen ||
            creds.credentials.size() > CommissioningParameters::kMaxCredentialsLen)
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
        memcpy(mSsid, creds.ssid.data(), creds.ssid.size());
        memcpy(mCredentials, creds.credentials.data(), creds.credentials.size());
        mParams.SetWiFiCredentials(
            WiFiCredentials(ByteSpan(mSsid, creds.ssid.size()), ByteSpan(mCredentials, creds.credentials.size())));
    }
    return CHIP_NO_ERROR;
}

CommissioningStage AutoCommissioner::GetNextCommissioningStage(CommissioningStage currentStage, CHIP_ERROR lastErr)
{
    if (lastErr != CHIP_NO_ERROR)
    {
        return CommissioningStage::kCleanup;
    }
    switch (currentStage)
    {
    case CommissioningStage::kSecurePairing:
        return CommissioningStage::kArmFailsafe;
    case CommissioningStage::kArmFailsafe:
        return CommissioningStage::kConfigRegulatory;
    case CommissioningStage::kConfigRegulatory:
        return CommissioningStage::kDeviceAttestation;
    case CommissioningStage::kDeviceAttestation:
        // TODO(cecille): device attestation casues operational cert provisioinging to happen, This should be a separate stage.
        // For thread and wifi, this should go to network setup then enable. For on-network we can skip right to finding the
        // operational network because the provisioning of certificates will trigger the device to start operational advertising.
        if (mParams.HasWiFiCredentials())
        {
            return CommissioningStage::kWiFiNetworkSetup;
        }
        else if (mParams.HasThreadOperationalDataset())
        {
            return CommissioningStage::kThreadNetworkSetup;
        }
        else
        {
#if CHIP_DEVICE_CONFIG_ENABLE_DNSSD
            return CommissioningStage::kFindOperational;
#else
            return CommissioningStage::kSendComplete;
#endif
        }
    case CommissioningStage::kWiFiNetworkSetup:
        if (mParams.HasThreadOperationalDataset())
        {
            return CommissioningStage::kThreadNetworkSetup;
        }
        else
        {
            return CommissioningStage::kWiFiNetworkEnable;
        }
    case CommissioningStage::kThreadNetworkSetup:
        if (mParams.HasWiFiCredentials())
        {
            return CommissioningStage::kWiFiNetworkEnable;
        }
        else
        {
            return CommissioningStage::kThreadNetworkEnable;
        }

    case CommissioningStage::kWiFiNetworkEnable:
        if (mParams.HasThreadOperationalDataset())
        {
            return CommissioningStage::kThreadNetworkEnable;
        }
        else
        {
            return CommissioningStage::kFindOperational;
        }
    case CommissioningStage::kThreadNetworkEnable:
        return CommissioningStage::kFindOperational;
    case CommissioningStage::kFindOperational:
        return CommissioningStage::kSendComplete;
    case CommissioningStage::kSendComplete:
        return CommissioningStage::kCleanup;

    // Currently unimplemented.
    case CommissioningStage::kConfigACL:
    case CommissioningStage::kCheckCertificates:
        return CommissioningStage::kError;
    // Neither of these have a next stage so return kError;
    case CommissioningStage::kCleanup:
    case CommissioningStage::kError:
        return CommissioningStage::kError;
    }
    return CommissioningStage::kError;
}

void AutoCommissioner::StartCommissioning(CommissioneeDeviceProxy * proxy)
{
    // TODO: check that there is no commissioning in progress currently.
    mCommissioneeDeviceProxy = proxy;
    mCommissioner->PerformCommissioningStep(mCommissioneeDeviceProxy, CommissioningStage::kArmFailsafe, mParams, this);
}

void AutoCommissioner::CommissioningStepFinished(CHIP_ERROR err, CommissioningDelegate::CommissioningReport report)
{
    if (report.stageCompleted == CommissioningStage::kFindOperational)
    {
        mOperationalDeviceProxy = report.OperationalNodeFoundData.operationalProxy;
    }
    CommissioningStage nextStage = GetNextCommissioningStage(report.stageCompleted, err);
    DeviceProxy * proxy          = mCommissioneeDeviceProxy;
    if (nextStage == CommissioningStage::kSendComplete ||
        (nextStage == CommissioningStage::kCleanup && mOperationalDeviceProxy != nullptr))
    {
        proxy = mOperationalDeviceProxy;
    }

    if (proxy == nullptr)
    {
        ChipLogError(Controller, "Invalid device for commissioning");
        return;
    }
    mParams.SetCompletionStatus(err);
    mCommissioner->PerformCommissioningStep(proxy, nextStage, mParams, this);
}

} // namespace Controller
} // namespace chip
<|endoftext|>