<commit_before>//===- FunctionResolution.cpp - Resolve declarations to implementations ---===//
//
// Loop over the functions that are in the module and look for functions that
// have the same name.  More often than not, there will be things like:
//
//    declare void %foo(...)
//    void %foo(int, int) { ... }
//
// because of the way things are declared in C.  If this is the case, patch
// things up.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Module.h"
#include "llvm/SymbolTable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Pass.h"
#include "llvm/iOther.h"
#include "llvm/Constants.h"
#include "llvm/Assembly/Writer.h"  // FIXME: remove when varargs implemented
#include "Support/Statistic.h"
#include <algorithm>

namespace {
  Statistic<>NumResolved("funcresolve", "Number of varargs functions resolved");
  Statistic<> NumGlobals("funcresolve", "Number of global variables resolved");

  struct FunctionResolvingPass : public Pass {
    bool run(Module &M);
  };
  RegisterOpt<FunctionResolvingPass> X("funcresolve", "Resolve Functions");
}

Pass *createFunctionResolvingPass() {
  return new FunctionResolvingPass();
}

// ConvertCallTo - Convert a call to a varargs function with no arg types
// specified to a concrete nonvarargs function.
//
static void ConvertCallTo(CallInst *CI, Function *Dest) {
  const FunctionType::ParamTypes &ParamTys =
    Dest->getFunctionType()->getParamTypes();
  BasicBlock *BB = CI->getParent();

  // Keep an iterator to where we want to insert cast instructions if the
  // argument types don't agree.
  //
  unsigned NumArgsToCopy = CI->getNumOperands()-1;
  if (NumArgsToCopy != ParamTys.size() &&
      !(NumArgsToCopy > ParamTys.size() &&
        Dest->getFunctionType()->isVarArg())) {
    std::cerr << "WARNING: Call arguments do not match expected number of"
              << " parameters.\n";
    std::cerr << "WARNING: In function '"
              << CI->getParent()->getParent()->getName() << "': call: " << *CI;
    std::cerr << "Function resolved to: ";
    WriteAsOperand(std::cerr, Dest);
    std::cerr << "\n";
    if (NumArgsToCopy > ParamTys.size())
      NumArgsToCopy = ParamTys.size();
  }

  std::vector<Value*> Params;

  // Convert all of the call arguments over... inserting cast instructions if
  // the types are not compatible.
  for (unsigned i = 1; i <= NumArgsToCopy; ++i) {
    Value *V = CI->getOperand(i);

    if (i-1 < ParamTys.size() && V->getType() != ParamTys[i-1]) {
      // Must insert a cast...
      V = new CastInst(V, ParamTys[i-1], "argcast", CI);
    }

    Params.push_back(V);
  }

  // If the function takes extra parameters that are not being passed in, pass
  // null values in now...
  for (unsigned i = NumArgsToCopy; i < ParamTys.size(); ++i)
    Params.push_back(Constant::getNullValue(ParamTys[i]));

  // Replace the old call instruction with a new call instruction that calls
  // the real function.
  //
  Instruction *NewCall = new CallInst(Dest, Params, "", CI);
  std::string Name = CI->getName(); CI->setName("");

  // Transfer the name over...
  if (NewCall->getType() != Type::VoidTy)
    NewCall->setName(Name);

  // Replace uses of the old instruction with the appropriate values...
  //
  if (NewCall->getType() == CI->getType()) {
    CI->replaceAllUsesWith(NewCall);
    NewCall->setName(Name);

  } else if (NewCall->getType() == Type::VoidTy) {
    // Resolved function does not return a value but the prototype does.  This
    // often occurs because undefined functions default to returning integers.
    // Just replace uses of the call (which are broken anyway) with dummy
    // values.
    CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
  } else if (CI->getType() == Type::VoidTy) {
    // If we are gaining a new return value, we don't have to do anything
    // special here, because it will automatically be ignored.
  } else {
    // Insert a cast instruction to convert the return value of the function
    // into it's new type.  Of course we only need to do this if the return
    // value of the function is actually USED.
    //
    if (!CI->use_empty()) {
      // Insert the new cast instruction...
      CastInst *NewCast = new CastInst(NewCall, CI->getType(), Name, CI);
      CI->replaceAllUsesWith(NewCast);
    }
  }

  // The old instruction is no longer needed, destroy it!
  BB->getInstList().erase(CI);
}

static bool ResolveFunctions(Module &M, std::vector<GlobalValue*> &Globals,
                             Function *Concrete) {
  bool Changed = false;
  for (unsigned i = 0; i != Globals.size(); ++i)
    if (Globals[i] != Concrete) {
      Function *Old = cast<Function>(Globals[i]);
      const FunctionType *OldMT = Old->getFunctionType();
      const FunctionType *ConcreteMT = Concrete->getFunctionType();

      if (OldMT->getParamTypes().size() > ConcreteMT->getParamTypes().size() &&
          !ConcreteMT->isVarArg())
        if (!Old->use_empty()) {
          std::cerr << "WARNING: Linking function '" << Old->getName()
                    << "' is causing arguments to be dropped.\n";
          std::cerr << "WARNING: Prototype: ";
          WriteAsOperand(std::cerr, Old);
          std::cerr << " resolved to ";
          WriteAsOperand(std::cerr, Concrete);
          std::cerr << "\n";
        }

      // Check to make sure that if there are specified types, that they
      // match...
      //
      unsigned NumArguments = std::min(OldMT->getParamTypes().size(),
                                       ConcreteMT->getParamTypes().size());

      if (!Old->use_empty() && !Concrete->use_empty())
        for (unsigned i = 0; i < NumArguments; ++i)
          if (OldMT->getParamTypes()[i] != ConcreteMT->getParamTypes()[i]) {
            std::cerr << "WARNING: Function [" << Old->getName()
                      << "]: Parameter types conflict for: '" << OldMT
                      << "' and '" << ConcreteMT << "'\n";
            return Changed;
          }

      // Attempt to convert all of the uses of the old function to the concrete
      // form of the function.  If there is a use of the fn that we don't
      // understand here we punt to avoid making a bad transformation.
      //
      // At this point, we know that the return values are the same for our two
      // functions and that the Old function has no varargs fns specified.  In
      // otherwords it's just <retty> (...)
      //
      for (unsigned i = 0; i < Old->use_size(); ) {
        User *U = *(Old->use_begin()+i);
        if (CastInst *CI = dyn_cast<CastInst>(U)) {
          // Convert casts directly
          assert(CI->getOperand(0) == Old);
          CI->setOperand(0, Concrete);
          Changed = true;
          ++NumResolved;
        } else if (CallInst *CI = dyn_cast<CallInst>(U)) {
          // Can only fix up calls TO the argument, not args passed in.
          if (CI->getCalledValue() == Old) {
            ConvertCallTo(CI, Concrete);
            Changed = true;
            ++NumResolved;
          } else {
            ++i;
          }
        } else {
          ++i;
        }
      }

      // If there are any more uses that we could not resolve, force them to use
      // a casted pointer now.
      if (!Old->use_empty()) {
        Constant *NewCPR = ConstantPointerRef::get(Concrete);
        Old->replaceAllUsesWith(ConstantExpr::getCast(NewCPR, Old->getType()));
      }
    }
  return Changed;
}

static bool ResolveGlobalVariables(Module &M,
                                   std::vector<GlobalValue*> &Globals,
                                   GlobalVariable *Concrete) {
  bool Changed = false;
  assert(isa<ArrayType>(Concrete->getType()->getElementType()) &&
         "Concrete version should be an array type!");

  // Get the type of the things that may be resolved to us...
  const ArrayType *CATy =cast<ArrayType>(Concrete->getType()->getElementType());
  const Type *AETy = CATy->getElementType();

  Constant *CCPR = ConstantPointerRef::get(Concrete);

  for (unsigned i = 0; i != Globals.size(); ++i)
    if (Globals[i] != Concrete) {
      GlobalVariable *Old = cast<GlobalVariable>(Globals[i]);
      const ArrayType *OATy = cast<ArrayType>(Old->getType()->getElementType());
      if (OATy->getElementType() != AETy || OATy->getNumElements() != 0) {
        std::cerr << "WARNING: Two global variables exist with the same name "
                  << "that cannot be resolved!\n";
        return false;
      }

      Old->replaceAllUsesWith(ConstantExpr::getCast(CCPR, Old->getType()));

      // Since there are no uses of Old anymore, remove it from the module.
      M.getGlobalList().erase(Old);

      ++NumGlobals;
      Changed = true;
    }
  return Changed;
}

static bool ProcessGlobalsWithSameName(Module &M,
                                       std::vector<GlobalValue*> &Globals) {
  assert(!Globals.empty() && "Globals list shouldn't be empty here!");

  bool isFunction = isa<Function>(Globals[0]);   // Is this group all functions?
  GlobalValue *Concrete = 0;  // The most concrete implementation to resolve to

  assert((isFunction ^ isa<GlobalVariable>(Globals[0])) &&
         "Should either be function or gvar!");

  for (unsigned i = 0; i != Globals.size(); ) {
    if (isa<Function>(Globals[i]) != isFunction) {
      std::cerr << "WARNING: Found function and global variable with the "
                << "same name: '" << Globals[i]->getName() << "'.\n";
      return false;                 // Don't know how to handle this, bail out!
    }

    if (isFunction) {
      // For functions, we look to merge functions definitions of "int (...)"
      // to 'int (int)' or 'int ()' or whatever else is not completely generic.
      //
      Function *F = cast<Function>(Globals[i]);
      if (!F->isExternal()) {
        if (Concrete && !Concrete->isExternal())
          return false;   // Found two different functions types.  Can't choose!

        Concrete = Globals[i];
      } else if (Concrete) {
        if (Concrete->isExternal()) // If we have multiple external symbols...x
          if (F->getFunctionType()->getNumParams() >
              cast<Function>(Concrete)->getFunctionType()->getNumParams())
            Concrete = F;  // We are more concrete than "Concrete"!

      } else {
        Concrete = F;
      }
    } else {
      // For global variables, we have to merge C definitions int A[][4] with
      // int[6][4].  A[][4] is represented as A[0][4] by the CFE.
      GlobalVariable *GV = cast<GlobalVariable>(Globals[i]);
      if (!isa<ArrayType>(GV->getType()->getElementType())) {
        Concrete = 0;
        break;  // Non array's cannot be compatible with other types.
      } else if (Concrete == 0) {
        Concrete = GV;
      } else {
        // Must have different types... allow merging A[0][4] w/ A[6][4] if
        // A[0][4] is external.
        const ArrayType *NAT = cast<ArrayType>(GV->getType()->getElementType());
        const ArrayType *CAT =
          cast<ArrayType>(Concrete->getType()->getElementType());

        if (NAT->getElementType() != CAT->getElementType()) {
          Concrete = 0;  // Non-compatible types
          break;
        } else if (NAT->getNumElements() == 0 && GV->isExternal()) {
          // Concrete remains the same
        } else if (CAT->getNumElements() == 0 && Concrete->isExternal()) {
          Concrete = GV;   // Concrete becomes GV
        } else {
          Concrete = 0;    // Cannot merge these types...
          break;
        }
      }
    }
    ++i;
  }

  if (Globals.size() > 1) {         // Found a multiply defined global...
    // We should find exactly one concrete function definition, which is
    // probably the implementation.  Change all of the function definitions and
    // uses to use it instead.
    //
    if (!Concrete) {
      std::cerr << "WARNING: Found global types that are not compatible:\n";
      for (unsigned i = 0; i < Globals.size(); ++i) {
        std::cerr << "\t" << Globals[i]->getType()->getDescription() << " %"
                  << Globals[i]->getName() << "\n";
      }
      std::cerr << "  No linkage of globals named '" << Globals[0]->getName()
                << "' performed!\n";
      return false;
    }

    if (isFunction)
      return ResolveFunctions(M, Globals, cast<Function>(Concrete));
    else
      return ResolveGlobalVariables(M, Globals,
                                    cast<GlobalVariable>(Concrete));
  }
  return false;
}

bool FunctionResolvingPass::run(Module &M) {
  SymbolTable &ST = M.getSymbolTable();

  std::map<std::string, std::vector<GlobalValue*> > Globals;

  // Loop over the entries in the symbol table. If an entry is a func pointer,
  // then add it to the Functions map.  We do a two pass algorithm here to avoid
  // problems with iterators getting invalidated if we did a one pass scheme.
  //
  for (SymbolTable::iterator I = ST.begin(), E = ST.end(); I != E; ++I)
    if (const PointerType *PT = dyn_cast<PointerType>(I->first)) {
      SymbolTable::VarMap &Plane = I->second;
      for (SymbolTable::type_iterator PI = Plane.begin(), PE = Plane.end();
           PI != PE; ++PI) {
        GlobalValue *GV = cast<GlobalValue>(PI->second);
        assert(PI->first == GV->getName() &&
               "Global name and symbol table do not agree!");
        if (!GV->hasInternalLinkage())  // Only resolve decls to external fns
          Globals[PI->first].push_back(GV);
      }
    }

  bool Changed = false;

  // Now we have a list of all functions with a particular name.  If there is
  // more than one entry in a list, merge the functions together.
  //
  for (std::map<std::string, std::vector<GlobalValue*> >::iterator
         I = Globals.begin(), E = Globals.end(); I != E; ++I)
    Changed |= ProcessGlobalsWithSameName(M, I->second);

  // Now loop over all of the globals, checking to see if any are trivially
  // dead.  If so, remove them now.

  for (Module::iterator I = M.begin(), E = M.end(); I != E; )
    if (I->isExternal() && I->use_empty()) {
      Function *F = I;
      ++I;
      M.getFunctionList().erase(F);
      ++NumResolved;
      Changed = true;
    } else {
      ++I;
    }

  for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; )
    if (I->isExternal() && I->use_empty()) {
      GlobalVariable *GV = I;
      ++I;
      M.getGlobalList().erase(GV);
      ++NumGlobals;
      Changed = true;
    } else {
      ++I;
    }

  return Changed;
}
<commit_msg>Fix bug: FuncResolve/2003-05-31-InternalDecl.ll Count resolutions correctly.<commit_after>//===- FunctionResolution.cpp - Resolve declarations to implementations ---===//
//
// Loop over the functions that are in the module and look for functions that
// have the same name.  More often than not, there will be things like:
//
//    declare void %foo(...)
//    void %foo(int, int) { ... }
//
// because of the way things are declared in C.  If this is the case, patch
// things up.
//
//===----------------------------------------------------------------------===//

#include "llvm/Transforms/IPO.h"
#include "llvm/Module.h"
#include "llvm/SymbolTable.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Pass.h"
#include "llvm/iOther.h"
#include "llvm/Constants.h"
#include "llvm/Assembly/Writer.h"  // FIXME: remove when varargs implemented
#include "Support/Statistic.h"
#include <algorithm>

namespace {
  Statistic<>NumResolved("funcresolve", "Number of varargs functions resolved");
  Statistic<> NumGlobals("funcresolve", "Number of global variables resolved");

  struct FunctionResolvingPass : public Pass {
    bool run(Module &M);
  };
  RegisterOpt<FunctionResolvingPass> X("funcresolve", "Resolve Functions");
}

Pass *createFunctionResolvingPass() {
  return new FunctionResolvingPass();
}

// ConvertCallTo - Convert a call to a varargs function with no arg types
// specified to a concrete nonvarargs function.
//
static void ConvertCallTo(CallInst *CI, Function *Dest) {
  const FunctionType::ParamTypes &ParamTys =
    Dest->getFunctionType()->getParamTypes();
  BasicBlock *BB = CI->getParent();

  // Keep an iterator to where we want to insert cast instructions if the
  // argument types don't agree.
  //
  unsigned NumArgsToCopy = CI->getNumOperands()-1;
  if (NumArgsToCopy != ParamTys.size() &&
      !(NumArgsToCopy > ParamTys.size() &&
        Dest->getFunctionType()->isVarArg())) {
    std::cerr << "WARNING: Call arguments do not match expected number of"
              << " parameters.\n";
    std::cerr << "WARNING: In function '"
              << CI->getParent()->getParent()->getName() << "': call: " << *CI;
    std::cerr << "Function resolved to: ";
    WriteAsOperand(std::cerr, Dest);
    std::cerr << "\n";
    if (NumArgsToCopy > ParamTys.size())
      NumArgsToCopy = ParamTys.size();
  }

  std::vector<Value*> Params;

  // Convert all of the call arguments over... inserting cast instructions if
  // the types are not compatible.
  for (unsigned i = 1; i <= NumArgsToCopy; ++i) {
    Value *V = CI->getOperand(i);

    if (i-1 < ParamTys.size() && V->getType() != ParamTys[i-1]) {
      // Must insert a cast...
      V = new CastInst(V, ParamTys[i-1], "argcast", CI);
    }

    Params.push_back(V);
  }

  // If the function takes extra parameters that are not being passed in, pass
  // null values in now...
  for (unsigned i = NumArgsToCopy; i < ParamTys.size(); ++i)
    Params.push_back(Constant::getNullValue(ParamTys[i]));

  // Replace the old call instruction with a new call instruction that calls
  // the real function.
  //
  Instruction *NewCall = new CallInst(Dest, Params, "", CI);
  std::string Name = CI->getName(); CI->setName("");

  // Transfer the name over...
  if (NewCall->getType() != Type::VoidTy)
    NewCall->setName(Name);

  // Replace uses of the old instruction with the appropriate values...
  //
  if (NewCall->getType() == CI->getType()) {
    CI->replaceAllUsesWith(NewCall);
    NewCall->setName(Name);

  } else if (NewCall->getType() == Type::VoidTy) {
    // Resolved function does not return a value but the prototype does.  This
    // often occurs because undefined functions default to returning integers.
    // Just replace uses of the call (which are broken anyway) with dummy
    // values.
    CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
  } else if (CI->getType() == Type::VoidTy) {
    // If we are gaining a new return value, we don't have to do anything
    // special here, because it will automatically be ignored.
  } else {
    // Insert a cast instruction to convert the return value of the function
    // into it's new type.  Of course we only need to do this if the return
    // value of the function is actually USED.
    //
    if (!CI->use_empty()) {
      // Insert the new cast instruction...
      CastInst *NewCast = new CastInst(NewCall, CI->getType(), Name, CI);
      CI->replaceAllUsesWith(NewCast);
    }
  }

  // The old instruction is no longer needed, destroy it!
  BB->getInstList().erase(CI);
}

static bool ResolveFunctions(Module &M, std::vector<GlobalValue*> &Globals,
                             Function *Concrete) {
  bool Changed = false;
  for (unsigned i = 0; i != Globals.size(); ++i)
    if (Globals[i] != Concrete) {
      Function *Old = cast<Function>(Globals[i]);
      const FunctionType *OldMT = Old->getFunctionType();
      const FunctionType *ConcreteMT = Concrete->getFunctionType();

      if (OldMT->getParamTypes().size() > ConcreteMT->getParamTypes().size() &&
          !ConcreteMT->isVarArg())
        if (!Old->use_empty()) {
          std::cerr << "WARNING: Linking function '" << Old->getName()
                    << "' is causing arguments to be dropped.\n";
          std::cerr << "WARNING: Prototype: ";
          WriteAsOperand(std::cerr, Old);
          std::cerr << " resolved to ";
          WriteAsOperand(std::cerr, Concrete);
          std::cerr << "\n";
        }

      // Check to make sure that if there are specified types, that they
      // match...
      //
      unsigned NumArguments = std::min(OldMT->getParamTypes().size(),
                                       ConcreteMT->getParamTypes().size());

      if (!Old->use_empty() && !Concrete->use_empty())
        for (unsigned i = 0; i < NumArguments; ++i)
          if (OldMT->getParamTypes()[i] != ConcreteMT->getParamTypes()[i]) {
            std::cerr << "WARNING: Function [" << Old->getName()
                      << "]: Parameter types conflict for: '" << OldMT
                      << "' and '" << ConcreteMT << "'\n";
            return Changed;
          }

      // Attempt to convert all of the uses of the old function to the concrete
      // form of the function.  If there is a use of the fn that we don't
      // understand here we punt to avoid making a bad transformation.
      //
      // At this point, we know that the return values are the same for our two
      // functions and that the Old function has no varargs fns specified.  In
      // otherwords it's just <retty> (...)
      //
      for (unsigned i = 0; i < Old->use_size(); ) {
        User *U = *(Old->use_begin()+i);
        if (CastInst *CI = dyn_cast<CastInst>(U)) {
          // Convert casts directly
          assert(CI->getOperand(0) == Old);
          CI->setOperand(0, Concrete);
          Changed = true;
          ++NumResolved;
        } else if (CallInst *CI = dyn_cast<CallInst>(U)) {
          // Can only fix up calls TO the argument, not args passed in.
          if (CI->getCalledValue() == Old) {
            ConvertCallTo(CI, Concrete);
            Changed = true;
            ++NumResolved;
          } else {
            ++i;
          }
        } else {
          ++i;
        }
      }

      // If there are any more uses that we could not resolve, force them to use
      // a casted pointer now.
      if (!Old->use_empty()) {
        NumResolved += Old->use_size();
        Constant *NewCPR = ConstantPointerRef::get(Concrete);
        Old->replaceAllUsesWith(ConstantExpr::getCast(NewCPR, Old->getType()));
        Changed = true;
      }

      // Since there are no uses of Old anymore, remove it from the module.
      M.getFunctionList().erase(Old);
    }
  return Changed;
}

static bool ResolveGlobalVariables(Module &M,
                                   std::vector<GlobalValue*> &Globals,
                                   GlobalVariable *Concrete) {
  bool Changed = false;
  assert(isa<ArrayType>(Concrete->getType()->getElementType()) &&
         "Concrete version should be an array type!");

  // Get the type of the things that may be resolved to us...
  const ArrayType *CATy =cast<ArrayType>(Concrete->getType()->getElementType());
  const Type *AETy = CATy->getElementType();

  Constant *CCPR = ConstantPointerRef::get(Concrete);

  for (unsigned i = 0; i != Globals.size(); ++i)
    if (Globals[i] != Concrete) {
      GlobalVariable *Old = cast<GlobalVariable>(Globals[i]);
      const ArrayType *OATy = cast<ArrayType>(Old->getType()->getElementType());
      if (OATy->getElementType() != AETy || OATy->getNumElements() != 0) {
        std::cerr << "WARNING: Two global variables exist with the same name "
                  << "that cannot be resolved!\n";
        return false;
      }

      Old->replaceAllUsesWith(ConstantExpr::getCast(CCPR, Old->getType()));

      // Since there are no uses of Old anymore, remove it from the module.
      M.getGlobalList().erase(Old);

      ++NumGlobals;
      Changed = true;
    }
  return Changed;
}

static bool ProcessGlobalsWithSameName(Module &M,
                                       std::vector<GlobalValue*> &Globals) {
  assert(!Globals.empty() && "Globals list shouldn't be empty here!");

  bool isFunction = isa<Function>(Globals[0]);   // Is this group all functions?
  GlobalValue *Concrete = 0;  // The most concrete implementation to resolve to

  assert((isFunction ^ isa<GlobalVariable>(Globals[0])) &&
         "Should either be function or gvar!");

  for (unsigned i = 0; i != Globals.size(); ) {
    if (isa<Function>(Globals[i]) != isFunction) {
      std::cerr << "WARNING: Found function and global variable with the "
                << "same name: '" << Globals[i]->getName() << "'.\n";
      return false;                 // Don't know how to handle this, bail out!
    }

    if (isFunction) {
      // For functions, we look to merge functions definitions of "int (...)"
      // to 'int (int)' or 'int ()' or whatever else is not completely generic.
      //
      Function *F = cast<Function>(Globals[i]);
      if (!F->isExternal()) {
        if (Concrete && !Concrete->isExternal())
          return false;   // Found two different functions types.  Can't choose!

        Concrete = Globals[i];
      } else if (Concrete) {
        if (Concrete->isExternal()) // If we have multiple external symbols...x
          if (F->getFunctionType()->getNumParams() >
              cast<Function>(Concrete)->getFunctionType()->getNumParams())
            Concrete = F;  // We are more concrete than "Concrete"!

      } else {
        Concrete = F;
      }
    } else {
      // For global variables, we have to merge C definitions int A[][4] with
      // int[6][4].  A[][4] is represented as A[0][4] by the CFE.
      GlobalVariable *GV = cast<GlobalVariable>(Globals[i]);
      if (!isa<ArrayType>(GV->getType()->getElementType())) {
        Concrete = 0;
        break;  // Non array's cannot be compatible with other types.
      } else if (Concrete == 0) {
        Concrete = GV;
      } else {
        // Must have different types... allow merging A[0][4] w/ A[6][4] if
        // A[0][4] is external.
        const ArrayType *NAT = cast<ArrayType>(GV->getType()->getElementType());
        const ArrayType *CAT =
          cast<ArrayType>(Concrete->getType()->getElementType());

        if (NAT->getElementType() != CAT->getElementType()) {
          Concrete = 0;  // Non-compatible types
          break;
        } else if (NAT->getNumElements() == 0 && GV->isExternal()) {
          // Concrete remains the same
        } else if (CAT->getNumElements() == 0 && Concrete->isExternal()) {
          Concrete = GV;   // Concrete becomes GV
        } else {
          Concrete = 0;    // Cannot merge these types...
          break;
        }
      }
    }
    ++i;
  }

  if (Globals.size() > 1) {         // Found a multiply defined global...
    // We should find exactly one concrete function definition, which is
    // probably the implementation.  Change all of the function definitions and
    // uses to use it instead.
    //
    if (!Concrete) {
      std::cerr << "WARNING: Found global types that are not compatible:\n";
      for (unsigned i = 0; i < Globals.size(); ++i) {
        std::cerr << "\t" << Globals[i]->getType()->getDescription() << " %"
                  << Globals[i]->getName() << "\n";
      }
      std::cerr << "  No linkage of globals named '" << Globals[0]->getName()
                << "' performed!\n";
      return false;
    }

    if (isFunction)
      return ResolveFunctions(M, Globals, cast<Function>(Concrete));
    else
      return ResolveGlobalVariables(M, Globals,
                                    cast<GlobalVariable>(Concrete));
  }
  return false;
}

bool FunctionResolvingPass::run(Module &M) {
  SymbolTable &ST = M.getSymbolTable();

  std::map<std::string, std::vector<GlobalValue*> > Globals;

  // Loop over the entries in the symbol table. If an entry is a func pointer,
  // then add it to the Functions map.  We do a two pass algorithm here to avoid
  // problems with iterators getting invalidated if we did a one pass scheme.
  //
  for (SymbolTable::iterator I = ST.begin(), E = ST.end(); I != E; ++I)
    if (const PointerType *PT = dyn_cast<PointerType>(I->first)) {
      SymbolTable::VarMap &Plane = I->second;
      for (SymbolTable::type_iterator PI = Plane.begin(), PE = Plane.end();
           PI != PE; ++PI) {
        GlobalValue *GV = cast<GlobalValue>(PI->second);
        assert(PI->first == GV->getName() &&
               "Global name and symbol table do not agree!");
        Globals[PI->first].push_back(GV);
      }
    }

  bool Changed = false;

  // Now we have a list of all functions with a particular name.  If there is
  // more than one entry in a list, merge the functions together.
  //
  for (std::map<std::string, std::vector<GlobalValue*> >::iterator
         I = Globals.begin(), E = Globals.end(); I != E; ++I)
    Changed |= ProcessGlobalsWithSameName(M, I->second);

  // Now loop over all of the globals, checking to see if any are trivially
  // dead.  If so, remove them now.

  for (Module::iterator I = M.begin(), E = M.end(); I != E; )
    if (I->isExternal() && I->use_empty()) {
      Function *F = I;
      ++I;
      M.getFunctionList().erase(F);
      ++NumResolved;
      Changed = true;
    } else {
      ++I;
    }

  for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; )
    if (I->isExternal() && I->use_empty()) {
      GlobalVariable *GV = I;
      ++I;
      M.getGlobalList().erase(GV);
      ++NumGlobals;
      Changed = true;
    } else {
      ++I;
    }

  return Changed;
}
<|endoftext|>


<commit_before>#include "Consensus.h"

#define _USE_MATH_DEFINES //Necessary for M_PI to be available on Windows
#include <cmath>

#include "fastcluster/fastcluster.h"

using std::max_element;
using std::distance;

namespace cmt {

void Consensus::initialize(const vector<Point2f> & points_normalized)
{
    FILE_LOG(logDEBUG) << "Consensus::initialize() call";

    //Copy normalized points
    this->points_normalized = points_normalized;

    size_t num_points = points_normalized.size();

    //Create matrices of pairwise distances/angles
    distances_pairwise = Mat(num_points, num_points, CV_32FC1);
    angles_pairwise = Mat(num_points, num_points, CV_32FC1);

    for (size_t i = 0; i < num_points; i++)
    {
        for (size_t j = 0; j < num_points; j++)
        {
            Point2f v = points_normalized[i] - points_normalized[j];

            float distance = norm(v);
            float angle = atan2(v.y,v.x);

            distances_pairwise.at<float>(i,j) = distance;
            angles_pairwise.at<float>(i,j) = angle;
        }

    }

    FILE_LOG(logDEBUG) << "Consensus::initialize() return";
}

//TODO: Check for estimate_scale, estimate_rotation
void Consensus::estimateScaleRotation(const vector<Point2f> & points, const vector<int> & classes,
        float & scale, float & rotation)
{
    FILE_LOG(logDEBUG) << "Consensus::estimateScaleRotation() call";

    //Compute pairwise changes in scale/rotation
    vector<float> changes_scale;
    if (estimate_scale) changes_scale.reserve(points.size()*points.size());
    vector<float> changes_angles;
    if (estimate_rotation) changes_angles.reserve(points.size()*points.size());

    for (size_t i = 0; i < points.size(); i++)
    {
        for (size_t j = 0; j < points.size(); j++)
        {
            if (classes[i] != classes[j])
            {
                Point2f v = points[i] - points[j];

                if (estimate_scale)
                {
                    float distance = norm(v);
                    float distance_original = distances_pairwise.at<float>(classes[i],classes[j]);
                    float change_scale = distance / distance_original;
                    changes_scale.push_back(change_scale);
                }

                if (estimate_rotation)
                {
                    float angle = atan2(v.y,v.x);
                    float angle_original = angles_pairwise.at<float>(classes[i],classes[j]);
                    float change_angle = angle - angle_original;

                    //Fix long way angles
                    if (fabs(change_angle) > M_PI) {
                        change_angle = sgn(change_angle) * 2 * M_PI + change_angle;
                    }

                    changes_angles.push_back(change_angle);
                }
            }

        }

    }

    //Do not use changes_scale, changes_angle after this point as their order is changed by median()
    if (changes_scale.size() < 2) scale = 1;
    else scale = median(changes_scale);

    if (changes_angles.size() < 2) rotation = 0;
    else rotation = median(changes_angles);

    FILE_LOG(logDEBUG) << "Consensus::estimateScaleRotation() return";
}

void Consensus::findConsensus(const vector<Point2f> & points, const vector<int> & classes,
        const float scale, const float rotation,
        Point2f & center, vector<Point2f> & points_inlier, vector<int> & classes_inlier)
{
    FILE_LOG(logDEBUG) << "Consensus::findConsensus() call";

    //If no points are available, reteurn nan
    if (points.size() == 0)
    {
        center.x = numeric_limits<float>::quiet_NaN();
        center.y = numeric_limits<float>::quiet_NaN();

        FILE_LOG(logDEBUG) << "Consensus::findConsensus() return";

        return;
    }

    //Compute votes
    vector<Point2f> votes(points.size());
    for (size_t i = 0; i < points.size(); i++)
    {
        votes[i] = points[i] - scale * rotate(points_normalized[classes[i]], rotation);
    }

    t_index N = points.size();

    float * D = new float[N*(N-1)/2]; //This is a lot of memory, so we put it on the heap
    cluster_result Z(N-1);

    //Compute pairwise distances between votes
    int index = 0;
    for (size_t i = 0; i < points.size(); i++)
    {
        for (size_t j = i+1; j < points.size(); j++)
        {
            //TODO: This index calculation is correct, but is it a good thing?
            //int index = i * (points.size() - 1) - (i*i + i) / 2 + j - 1;
            D[index] = norm(votes[i] - votes[j]);
            index++;
        }
    }

    FILE_LOG(logDEBUG) << "Consensus::MST_linkage_core() call";
    MST_linkage_core(N,D,Z);
    FILE_LOG(logDEBUG) << "Consensus::MST_linkage_core() return";

    union_find nodes(N);

    //Sort linkage by distance ascending
    std::stable_sort(Z[0], Z[N-1]);

    //S are cluster sizes
    int S[2*N-1];
    //TODO: Why does this loop go to 2*N-1? Shouldn't it be simply N? Everything > N gets overwritten later
    for(int i = 0; i < 2*N-1; i++)
    {
        S[i] = 1;
    }

    t_index parent = 0; //After the loop ends, parent contains the index of the last cluster
    for (node const * NN=Z[0]; NN!=Z[N-1]; ++NN)
    {
        // Get two data points whose clusters are merged in step i.
        // Find the cluster identifiers for these points.
        t_index node1 = nodes.Find(NN->node1);
        t_index node2 = nodes.Find(NN->node2);

        // Merge the nodes in the union-find data structure by making them
        // children of a new node
        // if the distance is appropriate
        if (NN->dist < thr_cutoff)
        {
            parent = nodes.Union(node1, node2);
            S[parent] = S[node1] + S[node2];
        }
    }

    //Get cluster labels
    int T[N];
    for (t_index i = 0; i < N; i++)
    {
        T[i] = nodes.Find(i);
    }

    //Find largest cluster
    int S_max = distance(S, max_element(S, S + 2*N-1));

    //Find inliers, compute center of votes
    points_inlier.reserve(S[S_max]);
    classes_inlier.reserve(S[S_max]);
    center.x = center.y = 0;

    for (size_t i = 0; i < points.size(); i++)
    {
        //If point is in consensus cluster
        if (T[i] == S_max)
        {
            points_inlier.push_back(points[i]);
            classes_inlier.push_back(classes[i]);
            center.x += votes[i].x;
            center.y += votes[i].y;
        }

    }

    center.x /= points_inlier.size();
    center.y /= points_inlier.size();

    delete[] D;

    FILE_LOG(logDEBUG) << "Consensus::findConsensus() return";
}

} /* namespace cmt */
<commit_msg>Replaced variable length arrays with heap allocation<commit_after>#include "Consensus.h"

#define _USE_MATH_DEFINES //Necessary for M_PI to be available on Windows
#include <cmath>

#include "fastcluster/fastcluster.h"

using std::max_element;
using std::distance;

namespace cmt {

void Consensus::initialize(const vector<Point2f> & points_normalized)
{
    FILE_LOG(logDEBUG) << "Consensus::initialize() call";

    //Copy normalized points
    this->points_normalized = points_normalized;

    size_t num_points = points_normalized.size();

    //Create matrices of pairwise distances/angles
    distances_pairwise = Mat(num_points, num_points, CV_32FC1);
    angles_pairwise = Mat(num_points, num_points, CV_32FC1);

    for (size_t i = 0; i < num_points; i++)
    {
        for (size_t j = 0; j < num_points; j++)
        {
            Point2f v = points_normalized[i] - points_normalized[j];

            float distance = norm(v);
            float angle = atan2(v.y,v.x);

            distances_pairwise.at<float>(i,j) = distance;
            angles_pairwise.at<float>(i,j) = angle;
        }

    }

    FILE_LOG(logDEBUG) << "Consensus::initialize() return";
}

//TODO: Check for estimate_scale, estimate_rotation
void Consensus::estimateScaleRotation(const vector<Point2f> & points, const vector<int> & classes,
        float & scale, float & rotation)
{
    FILE_LOG(logDEBUG) << "Consensus::estimateScaleRotation() call";

    //Compute pairwise changes in scale/rotation
    vector<float> changes_scale;
    if (estimate_scale) changes_scale.reserve(points.size()*points.size());
    vector<float> changes_angles;
    if (estimate_rotation) changes_angles.reserve(points.size()*points.size());

    for (size_t i = 0; i < points.size(); i++)
    {
        for (size_t j = 0; j < points.size(); j++)
        {
            if (classes[i] != classes[j])
            {
                Point2f v = points[i] - points[j];

                if (estimate_scale)
                {
                    float distance = norm(v);
                    float distance_original = distances_pairwise.at<float>(classes[i],classes[j]);
                    float change_scale = distance / distance_original;
                    changes_scale.push_back(change_scale);
                }

                if (estimate_rotation)
                {
                    float angle = atan2(v.y,v.x);
                    float angle_original = angles_pairwise.at<float>(classes[i],classes[j]);
                    float change_angle = angle - angle_original;

                    //Fix long way angles
                    if (fabs(change_angle) > M_PI) {
                        change_angle = sgn(change_angle) * 2 * M_PI + change_angle;
                    }

                    changes_angles.push_back(change_angle);
                }
            }

        }

    }

    //Do not use changes_scale, changes_angle after this point as their order is changed by median()
    if (changes_scale.size() < 2) scale = 1;
    else scale = median(changes_scale);

    if (changes_angles.size() < 2) rotation = 0;
    else rotation = median(changes_angles);

    FILE_LOG(logDEBUG) << "Consensus::estimateScaleRotation() return";
}

void Consensus::findConsensus(const vector<Point2f> & points, const vector<int> & classes,
        const float scale, const float rotation,
        Point2f & center, vector<Point2f> & points_inlier, vector<int> & classes_inlier)
{
    FILE_LOG(logDEBUG) << "Consensus::findConsensus() call";

    //If no points are available, reteurn nan
    if (points.size() == 0)
    {
        center.x = numeric_limits<float>::quiet_NaN();
        center.y = numeric_limits<float>::quiet_NaN();

        FILE_LOG(logDEBUG) << "Consensus::findConsensus() return";

        return;
    }

    //Compute votes
    vector<Point2f> votes(points.size());
    for (size_t i = 0; i < points.size(); i++)
    {
        votes[i] = points[i] - scale * rotate(points_normalized[classes[i]], rotation);
    }

    t_index N = points.size();

    float * D = new float[N*(N-1)/2]; //This is a lot of memory, so we put it on the heap
    cluster_result Z(N-1);

    //Compute pairwise distances between votes
    int index = 0;
    for (size_t i = 0; i < points.size(); i++)
    {
        for (size_t j = i+1; j < points.size(); j++)
        {
            //TODO: This index calculation is correct, but is it a good thing?
            //int index = i * (points.size() - 1) - (i*i + i) / 2 + j - 1;
            D[index] = norm(votes[i] - votes[j]);
            index++;
        }
    }

    FILE_LOG(logDEBUG) << "Consensus::MST_linkage_core() call";
    MST_linkage_core(N,D,Z);
    FILE_LOG(logDEBUG) << "Consensus::MST_linkage_core() return";

    union_find nodes(N);

    //Sort linkage by distance ascending
    std::stable_sort(Z[0], Z[N-1]);

    //S are cluster sizes
    int * S = new int[2*N-1];
    //TODO: Why does this loop go to 2*N-1? Shouldn't it be simply N? Everything > N gets overwritten later
    for(int i = 0; i < 2*N-1; i++)
    {
        S[i] = 1;
    }

    t_index parent = 0; //After the loop ends, parent contains the index of the last cluster
    for (node const * NN=Z[0]; NN!=Z[N-1]; ++NN)
    {
        // Get two data points whose clusters are merged in step i.
        // Find the cluster identifiers for these points.
        t_index node1 = nodes.Find(NN->node1);
        t_index node2 = nodes.Find(NN->node2);

        // Merge the nodes in the union-find data structure by making them
        // children of a new node
        // if the distance is appropriate
        if (NN->dist < thr_cutoff)
        {
            parent = nodes.Union(node1, node2);
            S[parent] = S[node1] + S[node2];
        }
    }

    //Get cluster labels
    int * T = new int[N];
    for (t_index i = 0; i < N; i++)
    {
        T[i] = nodes.Find(i);
    }

    //Find largest cluster
    int S_max = distance(S, max_element(S, S + 2*N-1));

    //Find inliers, compute center of votes
    points_inlier.reserve(S[S_max]);
    classes_inlier.reserve(S[S_max]);
    center.x = center.y = 0;

    for (size_t i = 0; i < points.size(); i++)
    {
        //If point is in consensus cluster
        if (T[i] == S_max)
        {
            points_inlier.push_back(points[i]);
            classes_inlier.push_back(classes[i]);
            center.x += votes[i].x;
            center.y += votes[i].y;
        }

    }

    center.x /= points_inlier.size();
    center.y /= points_inlier.size();

    delete[] D;
	delete[] S;
	delete[] T;

    FILE_LOG(logDEBUG) << "Consensus::findConsensus() return";
}

} /* namespace cmt */
<|endoftext|>


<commit_before>#pragma once

#include <UI_Event.h>
#include <MY_ResourceManager.h>
#include <scenario/Dialogue.h>

UI_Event::UI_Event(BulletWorld * _world, Shader * _textShader) :
	VerticalLinearLayout(_world),
	image(new NodeUI(_world)),
	text(new TextArea(_world, MY_ResourceManager::scenario->getFont("HURLY-BURLY")->font, _textShader, 1.f)),
	nextButton(new MY_Button(_world, MY_ResourceManager::scenario->getFont("HURLY-BURLY")->font, _textShader, 282, 45)),
	optionOne(new MY_Button(_world, MY_ResourceManager::scenario->getFont("HURLY-BURLY")->font, _textShader, 282, 45)),
	optionTwo(new MY_Button(_world, MY_ResourceManager::scenario->getFont("HURLY-BURLY")->font, _textShader, 282, 45)),
	done(false),
	optionsLayout(new HorizontalLinearLayout(_world)),
	currentEvent(nullptr)
{
	setRenderMode(kTEXTURE);

	//optionOne->renderMode = kTEXTURE;

	verticalAlignment = kTOP;
	horizontalAlignment = kCENTER;

	setBackgroundColour(1.f, 1.f, 1.f, 1.f);
	background->mesh->pushTexture2D(MY_ResourceManager::scenario->getTexture("SCROLL_EVENT")->texture);

	setMargin(0.05f);
	setPadding(0.125f, 0.125f);
	setRationalWidth(1.f);
	setRationalHeight(1.f);

	addChild(image);
	addChild(text);
	addChild(optionsLayout);
	optionsLayout->addChild(optionOne);
	optionsLayout->addChild(optionTwo);

	optionsLayout->setVisible(false);

	addChild(nextButton);

	image->setRationalWidth(1.0f);
	image->setRationalHeight(0.8f);
	image->background->mesh->scaleModeMag = image->background->mesh->scaleModeMin = GL_NEAREST;

	text->setWidth(1.f);
	//text->setHeight(0.4f);
	text->setText(L"Bacon ipsum dolor amet anim occaecat pork loin.");
	text->verticalAlignment = kTOP;
	text->setWrapMode(kWORD);

	nextButton->label->setText("NEXT");

	nextButton->eventManager.addEventListener("click", [this](sweet::Event * _event){
		done = !this->sayNext();
		if(done){
			nextButton->setMouseEnabled(false);
			optionOne->setMouseEnabled(false);
			optionTwo->setMouseEnabled(false);
		}
	});
	optionOne->eventManager.addEventListener("click", [this](sweet::Event * _event){
		select(0);
	});
	optionTwo->eventManager.addEventListener("click", [this](sweet::Event * _event){
		select(1);
	});

	nextButton->setMouseEnabled(false);
	optionOne->setMouseEnabled(false);
	optionTwo->setMouseEnabled(false);
	setVisible(false);
}

UI_Event::~UI_Event(){}

void UI_Event::startEvent(Event * _event){
	currentEvent = _event;
	done = false;
	setVisible(true);

	currentConversation = _event->scenario->conversations["intro"];
	currentConversation->reset();
	sayNext();
}

bool UI_Event::sayNext(){
	invalidateLayout();
	if(ConversationIterator::sayNext()){
		// remove existing images
		while(image->background->mesh->textures.size() > 0){
			delete image->background->mesh->textures.back();
			image->background->mesh->textures.pop_back();
		}
		// make the image "textures/event/SCENARIO_CONVERSATION.png"
		std::stringstream imgSrc;
		imgSrc << currentEvent->scenario->id << "_" << currentConversation->id << ".png";
		Texture * tex = new Texture(imgSrc.str(), false, false, false);
		tex->load();
		image->background->mesh->pushTexture2D(tex);

		text->setText(currentConversation->getCurrentDialogue()->getCurrentText());

		if(waitingForInput){
			nextButton->setVisible(false);
			optionsLayout->setVisible(true);

			nextButton->setMouseEnabled(false);
			optionOne->setMouseEnabled(true);
			optionTwo->setMouseEnabled(true);

			optionOne->label->setText(currentConversation->options.at(0)->text);
			optionTwo->label->setText(currentConversation->options.at(1)->text);
		}else{
			nextButton->setVisible(true);
			optionsLayout->setVisible(false);

			nextButton->setMouseEnabled(true);
			optionOne->setMouseEnabled(false);
			optionTwo->setMouseEnabled(false);
		}

		return true;
	}else{
		return false;
	}
}<commit_msg>comments<commit_after>#pragma once

#include <UI_Event.h>
#include <MY_ResourceManager.h>
#include <scenario/Dialogue.h>

UI_Event::UI_Event(BulletWorld * _world, Shader * _textShader) :
	VerticalLinearLayout(_world),
	image(new NodeUI(_world)),
	text(new TextArea(_world, MY_ResourceManager::scenario->getFont("HURLY-BURLY")->font, _textShader, 1.f)),
	nextButton(new MY_Button(_world, MY_ResourceManager::scenario->getFont("HURLY-BURLY")->font, _textShader, 282, 45)),
	optionOne(new MY_Button(_world, MY_ResourceManager::scenario->getFont("HURLY-BURLY")->font, _textShader, 282, 45)),
	optionTwo(new MY_Button(_world, MY_ResourceManager::scenario->getFont("HURLY-BURLY")->font, _textShader, 282, 45)),
	done(false),
	optionsLayout(new HorizontalLinearLayout(_world)),
	currentEvent(nullptr)
{
	setRenderMode(kTEXTURE);

	//optionOne->renderMode = kTEXTURE;

	verticalAlignment = kTOP;
	horizontalAlignment = kCENTER;

	setBackgroundColour(1.f, 1.f, 1.f, 1.f);
	background->mesh->pushTexture2D(MY_ResourceManager::scenario->getTexture("SCROLL_EVENT")->texture);

	setMargin(0.05f);
	setPadding(0.125f, 0.125f);
	setRationalWidth(1.f);
	setRationalHeight(1.f);

	addChild(image);
	addChild(text);
	addChild(optionsLayout);
	optionsLayout->addChild(optionOne);
	optionsLayout->addChild(optionTwo);

	optionsLayout->setVisible(false);

	addChild(nextButton);

	image->setRationalWidth(1.0f);
	image->setRationalHeight(0.8f);
	image->background->mesh->scaleModeMag = image->background->mesh->scaleModeMin = GL_NEAREST;

	text->setWidth(1.f);
	//text->setHeight(0.4f);
	text->setText(L"Bacon ipsum dolor amet anim occaecat pork loin.");
	text->verticalAlignment = kTOP;
	text->setWrapMode(kWORD);

	nextButton->label->setText("NEXT");

	nextButton->eventManager.addEventListener("click", [this](sweet::Event * _event){
		done = !this->sayNext();

		// prevent the user from clicking buttons while they're not visible
		if(done){
			nextButton->setMouseEnabled(false);
			optionOne->setMouseEnabled(false);
			optionTwo->setMouseEnabled(false);
		}
	});
	optionOne->eventManager.addEventListener("click", [this](sweet::Event * _event){
		select(0);
	});
	optionTwo->eventManager.addEventListener("click", [this](sweet::Event * _event){
		select(1);
	});

	// prevent the user from clicking buttons while they're not visible
	nextButton->setMouseEnabled(false);
	optionOne->setMouseEnabled(false);
	optionTwo->setMouseEnabled(false);
	setVisible(false);
}

UI_Event::~UI_Event(){}

void UI_Event::startEvent(Event * _event){
	currentEvent = _event;
	done = false;
	setVisible(true);

	currentConversation = _event->scenario->conversations["intro"];
	currentConversation->reset();
	sayNext();
}

bool UI_Event::sayNext(){
	invalidateLayout();
	if(ConversationIterator::sayNext()){
		// remove existing images
		while(image->background->mesh->textures.size() > 0){
			delete image->background->mesh->textures.back();
			image->background->mesh->textures.pop_back();
		}
		// make the image "textures/event/SCENARIO_CONVERSATION.png"
		std::stringstream imgSrc;
		imgSrc << currentEvent->scenario->id << "_" << currentConversation->id << ".png";
		Texture * tex = new Texture(imgSrc.str(), false, false, false);
		tex->load();
		image->background->mesh->pushTexture2D(tex);

		text->setText(currentConversation->getCurrentDialogue()->getCurrentText());

		if(waitingForInput){
			nextButton->setVisible(false);
			optionsLayout->setVisible(true);

			nextButton->setMouseEnabled(false);
			optionOne->setMouseEnabled(true);
			optionTwo->setMouseEnabled(true);

			optionOne->label->setText(currentConversation->options.at(0)->text);
			optionTwo->label->setText(currentConversation->options.at(1)->text);
		}else{
			nextButton->setVisible(true);
			optionsLayout->setVisible(false);

			nextButton->setMouseEnabled(true);
			optionOne->setMouseEnabled(false);
			optionTwo->setMouseEnabled(false);
		}

		return true;
	}else{
		return false;
	}
}<|endoftext|>


<commit_before><commit_msg>fixed coefficient bug<commit_after><|endoftext|>


<commit_before>// (c) COPYRIGHT URI/MIT 1997-98
// Please read the full copyright statement in the file COPYRIGH.
//
// Authors: reza (Reza Nekovei)

// FreeFrom sub-class implementation for FFByte,...FFGrid.
// The files are patterned after the subcalssing examples
// Test<type>.c,h files.
//
// ReZa 6/16/97

// $Log: FFSequence.cc,v $
// Revision 1.9  1998/11/10 19:22:15  jimg
// Added calls to the new BaseType accessor synthesized_p(). This means that
// the projection functions now work.
//
// Revision 1.8  1998/08/31 04:06:03  reza
// Added String support.
// Fixed data alignment problem (64-bit Architectures).
// Removed Warnings and added a check for file existence.
// Updated FFND to fix a bug in stride.
//
// Revision 1.7  1998/08/18 16:58:23  reza
// Files with headers are now handled correctly
//
// Revision 1.6  1998/08/14 18:20:14  reza
// Fixed extra records read for sequences.
//
// Revision 1.5  1998/08/13 20:24:32  jimg
// Fixed read mfunc semantics
//
// Revision 1.4  1998/08/12 21:20:56  jimg
// Massive changes from Reza. Compatible with the new FFND library
//
// Revision 1.3  1998/04/21 17:13:57  jimg
// Fixes for warnings, etc
//
// Revision 1.2  1998/04/16 18:11:14  jimg
// Sequence support added by Reza

#include "config_ff.h"

static char rcsid[] __unused__ ={"$Id"};

#ifdef _GNUG_
#pragma implementation
#endif

#include <strstream.h>

#include "FFSequence.h"
#include "util_ff.h"

extern long BufPtr;
extern char *BufVal;
extern long BufSiz;

int StrLength = 0; // Sets string length befor reading it
extern int StrLens[MaxStr]; // List of string length in this sequence

Sequence *
NewSequence(const String &n)
{
    return new FFSequence(n);
}

// protected

BaseType *
FFSequence::ptr_duplicate()
{
    return new FFSequence(*this);
}

// public

FFSequence::FFSequence(const String &n) : Sequence(n)
{
}

FFSequence::~FFSequence()
{
}

long
Records(const String &filename)
{
    int error = 0;
    DATA_BIN_PTR dbin = NULL;
    FF_STD_ARGS_PTR SetUps = NULL;
    PROCESS_INFO_LIST pinfo_list = NULL;
    PROCESS_INFO_PTR  pinfo = NULL;
    static char Msgt[255];

    char * FileName = new char [filename.length()+1];
    (void) strcpy(FileName, (const char *)filename);

    SetUps = ff_create_std_args();
    if (!SetUps)
	return -1;

    /** set the structure values to create the FreeForm DB**/
    SetUps->user.is_stdin_redirected = 0;
    SetUps->input_file = FileName;
    String iff = find_ancillary_file(filename);
    char *if_f = new char[iff.length() + 1];
    strcpy(if_f, iff);
    SetUps->input_format_file = if_f;
    SetUps->output_file = NULL;

    error = SetDodsDB(SetUps, &dbin, Msgt);
    if (error && error < ERR_WARNING_ONLY) {
	db_destroy(dbin);
	return -1;
    }

    error = db_ask(dbin, DBASK_PROCESS_INFO, FFF_INPUT | FFF_DATA, &pinfo_list);
    if (error)
	return(-1);

    pinfo_list = dll_first(pinfo_list);

    //    pinfo = FF_PI(pinfo_list);
    pinfo = ((PROCESS_INFO_PTR)(pinfo_list)->data.u.pi);

    long num_records = PINFO_SUPER_ARRAY_ELS(pinfo);
    ff_destroy_process_info_list(pinfo_list);

    return num_records;
}

bool
FFSequence::read(const String &dataset, int &error)
{

  int StrCnt = 0;

    if (read_p())  // Nothing to do
      return false;

    if((BufPtr >= BufSiz) && (BufSiz != 0))
      return false; // End of sequence

    if (!BufVal) { // Make the cache
	char *ds = new char[dataset.length() + 1];
	strcpy(ds, (const char*)dataset);

	// Create the output Sequence format
	ostrstream str;
	int endbyte = 0;
	int stbyte = 1;

	str << "binary_output_data \"DODS binary output data\"" << endl;
	StrCnt = 0;
	for(Pix p = first_var(); p; next_var(p)) {
	  if (var(p)->synthesized_p())
	      continue;
	  if (var(p)->type() == dods_str_c) {
	    endbyte +=StrLens[StrCnt];
	    StrCnt++;
	  }
	  else
	    endbyte += var(p)->width();

	  str << var(p)->name() << " " << stbyte << " " << endbyte
	      << " " << ff_types(var(p)->type_name())
	      << " " << ff_prec(var(p)->type_name()) << endl;
	  stbyte = endbyte + 1;
	}

#ifdef TEST
	cout << str.str();
#endif

	String output_format = str.str();

	char *o_fmt = new char[output_format.length() + 1];
	strcpy(o_fmt, (const char*)output_format);

	String input_format_file = find_ancillary_file(dataset);
	char *if_fmt = new char[input_format_file.length() + 1];
	strcpy(if_fmt, input_format_file);

	long num_rec = Records(dataset); // It could come from DDS if sequence length was known

	if (num_rec == -1)
	    return false;

	BufSiz = num_rec * (stbyte - 1);

	BufVal = (char *)new char[BufSiz];
	long bytes = read_ff(ds, if_fmt, o_fmt, BufVal, BufSiz);
	if (bytes == -1) {
	    error = 1;
	    return false;
	}

	// clean up
	delete[] ds;
	delete[] o_fmt;
	delete[] if_fmt;
    }
    StrCnt = 0;
    for (Pix p = first_var(); p; next_var(p)) {
      if(var(p)->type()== dods_str_c){
	StrLength = StrLens[StrCnt];
	StrCnt++;
      }
         var(p)->read(dataset, error);
	 if (error)
	     return false;
    }

    return true;
}
<commit_msg>Minor changes, formatting sanity. Added ends to ostrstream object using to builf output format string. Added debug.h<commit_after>// (c) COPYRIGHT URI/MIT 1997-98
// Please read the full copyright statement in the file COPYRIGH.
//
// Authors: reza (Reza Nekovei)

// FreeFrom sub-class implementation for FFByte,...FFGrid.
// The files are patterned after the subcalssing examples
// Test<type>.c,h files.
//
// ReZa 6/16/97

// $Log: FFSequence.cc,v $
// Revision 1.10  1998/11/13 05:39:15  jimg
// Minor changes, formatting sanity.
// Added ends to ostrstream object using to builf output format string.
// Added debug.h
//
// Revision 1.9  1998/11/10 19:22:15  jimg
// Added calls to the new BaseType accessor synthesized_p(). This means that
// the projection functions now work.
//
// Revision 1.8  1998/08/31 04:06:03  reza
// Added String support.
// Fixed data alignment problem (64-bit Architectures).
// Removed Warnings and added a check for file existence.
// Updated FFND to fix a bug in stride.
//
// Revision 1.7  1998/08/18 16:58:23  reza
// Files with headers are now handled correctly
//
// Revision 1.6  1998/08/14 18:20:14  reza
// Fixed extra records read for sequences.
//
// Revision 1.5  1998/08/13 20:24:32  jimg
// Fixed read mfunc semantics
//
// Revision 1.4  1998/08/12 21:20:56  jimg
// Massive changes from Reza. Compatible with the new FFND library
//
// Revision 1.3  1998/04/21 17:13:57  jimg
// Fixes for warnings, etc
//
// Revision 1.2  1998/04/16 18:11:14  jimg
// Sequence support added by Reza

#include "config_ff.h"

static char rcsid[] __unused__ ={"$Id: FFSequence.cc,v 1.10 1998/11/13 05:39:15 jimg Exp $"};

#ifdef _GNUG_
#pragma implementation
#endif

#include <strstream.h>

#include "FFSequence.h"
#include "util_ff.h"
#include "debug.h"

extern long BufPtr;
extern char *BufVal;
extern long BufSiz;

int StrLength = 0; // Sets string length befor reading it
extern int StrLens[MaxStr]; // List of string length in this sequence

Sequence *
NewSequence(const String &n)
{
    return new FFSequence(n);
}

// protected

BaseType *
FFSequence::ptr_duplicate()
{
    return new FFSequence(*this);
}

// public

FFSequence::FFSequence(const String &n) : Sequence(n)
{
}

FFSequence::~FFSequence()
{
}

long
Records(const String &filename)
{
    int error = 0;
    DATA_BIN_PTR dbin = NULL;
    FF_STD_ARGS_PTR SetUps = NULL;
    PROCESS_INFO_LIST pinfo_list = NULL;
    PROCESS_INFO_PTR  pinfo = NULL;
    static char Msgt[255];

    char * FileName = new char [filename.length()+1];
    (void) strcpy(FileName, (const char *)filename);

    SetUps = ff_create_std_args();
    if (!SetUps)
	return -1;

    /** set the structure values to create the FreeForm DB**/
    SetUps->user.is_stdin_redirected = 0;
    SetUps->input_file = FileName;
    String iff = find_ancillary_file(filename);
    char *if_f = new char[iff.length() + 1];
    strcpy(if_f, iff);
    SetUps->input_format_file = if_f;
    SetUps->output_file = NULL;

    error = SetDodsDB(SetUps, &dbin, Msgt);
    if (error && error < ERR_WARNING_ONLY) {
	db_destroy(dbin);
	return -1;
    }

    error = db_ask(dbin, DBASK_PROCESS_INFO, FFF_INPUT | FFF_DATA, &pinfo_list);
    if (error)
	return(-1);

    pinfo_list = dll_first(pinfo_list);

    //    pinfo = FF_PI(pinfo_list);
    pinfo = ((PROCESS_INFO_PTR)(pinfo_list)->data.u.pi);

    long num_records = PINFO_SUPER_ARRAY_ELS(pinfo);
    ff_destroy_process_info_list(pinfo_list);

    return num_records;
}

bool
FFSequence::read(const String &dataset, int &error)
{

  int StrCnt = 0;

    if (read_p())  // Nothing to do
      return false;

    if((BufPtr >= BufSiz) && (BufSiz != 0))
      return false; // End of sequence

    if (!BufVal) { // Make the cache
	// Create the output Sequence format
	ostrstream str;
	int endbyte = 0;
	int stbyte = 1;

	str << "binary_output_data \"DODS binary output data\"" << endl;
	StrCnt = 0;
	for(Pix p = first_var(); p; next_var(p)) {
	    if (var(p)->synthesized_p())
		continue;
	    if (var(p)->type() == dods_str_c) {
		endbyte +=StrLens[StrCnt];
		StrCnt++;
	    }
	    else
		endbyte += var(p)->width();

	    str << var(p)->name() << " " << stbyte << " " << endbyte
		<< " " << ff_types(var(p)->type_name())
		<< " " << ff_prec(var(p)->type_name()) << endl;
	    stbyte = endbyte + 1;
	}
	str << ends;

	DBG(cerr << str.str());

	str.freeze(1);
	char *o_fmt = new char[strlen(str.str()) + 1];
	strcpy(o_fmt, str.str());
	str.freeze(0);

	String input_format_file = find_ancillary_file(dataset);
	char *if_fmt = new char[input_format_file.length() + 1];
	strcpy(if_fmt, input_format_file);

	long num_rec = Records(dataset); // It could come from DDS if sequence length was known

	if (num_rec == -1)
	    return false;

	BufSiz = num_rec * (stbyte - 1);
	BufVal = (char *)new char[BufSiz];
	char *ds = new char[dataset.length() + 1];
	strcpy(ds, (const char*)dataset);

	long bytes = read_ff(ds, if_fmt, o_fmt, BufVal, BufSiz);
	if (bytes == -1) {
	    error = 1;
	    return false;
	}

	// clean up
	delete[] ds;
	delete[] o_fmt;
	delete[] if_fmt;
    }

    StrCnt = 0;
    for (Pix p = first_var(); p; next_var(p)) {
	if(var(p)->type()== dods_str_c){
	    StrLength = StrLens[StrCnt];
	    StrCnt++;
	}
	var(p)->read(dataset, error);
	if (error)
	    return false;
    }

    return true;
}
<|endoftext|>


<commit_before>/**
 * Appcelerator Kroll - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
 */
#include "../utils.h"
#include <windows.h>
#include <shlobj.h>
#include <Iphlpapi.h>
#include <process.h>
#include <shellapi.h>
#include <sstream>

#ifndef NO_UNZIP
#include "../unzip/unzip.h"
#endif

namespace UTILS_NS
{
namespace FileUtils
{
	static bool FileHasAttributes(const std::wstring& widePath, DWORD attributes)
	{
		WIN32_FIND_DATA findFileData;
		ZeroMemory(&findFileData, sizeof(WIN32_FIND_DATA));

		HANDLE hFind = FindFirstFile(widePath.c_str(), &findFileData);
		if (hFind != INVALID_HANDLE_VALUE)
		{
			FindClose(hFind);

			// We do this check, because we may have passed in 0 for attributse
			// in which case the callee just wants to know if the path exists.
			return (findFileData.dwFileAttributes & attributes) == attributes;
		}
		else
		{
			return false;
		}
	}

	static bool FileHasAttributes(const std::string& path, DWORD attributes)
	{
		std::wstring widePath(UTILS_NS::UTF8ToWide(path));
		return FileHasAttributes(widePath, attributes);
	}

	std::string GetExecutableDirectory()
	{
		wchar_t path[MAX_PATH];
		path[MAX_PATH-1] = '\0';
		GetModuleFileNameW(NULL, path, MAX_PATH - 1);
		std::string fullPath(UTILS_NS::WideToUTF8(path));
		return Dirname(fullPath);
	}

	std::string GetTempDirectory()
	{
		wchar_t tempDirectory[MAX_PATH];
		tempDirectory[MAX_PATH-1] = '\0';
		GetTempPathW(MAX_PATH - 1, tempDirectory);

		// This function seem to return Windows stubby paths, so
		// let's convert it to a full path name.
		std::wstring dir(tempDirectory);
		GetLongPathNameW(dir.c_str(), tempDirectory, MAX_PATH - 1);
		std::string out(UTILS_NS::WideToUTF8(tempDirectory));
		srand(GetTickCount()); // initialize seed
		std::ostringstream s;
		s << "k" << (double) rand();
		std::string end(s.str());
		return FileUtils::Join(out.c_str(), end.c_str(), NULL);
	}

	bool IsFile(const std::string& file)
	{
		return FileHasAttributes(file, 0);
	}

	bool IsFile(const std::wstring& file)
	{
		return FileHasAttributes(file, 0);
	}

	void WriteFile(const std::string& path, const std::string& content)
	{
		std::wstring widePath(UTF8ToWide(path));
		// CreateFile doesn't have a path length limitation
		HANDLE file = CreateFileW(widePath.c_str(),
			GENERIC_WRITE,
			0,
			NULL,
			CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL,
			NULL);

		DWORD bytesWritten = 0;
		DWORD bytesToWrite = (DWORD)content.size();

		if (file != INVALID_HANDLE_VALUE)
		{
			while (bytesWritten < bytesToWrite)
			{
				if (FALSE == ::WriteFile(file, content.c_str() + bytesWritten,
					bytesToWrite - bytesWritten, &bytesWritten, NULL))
				{
					CloseHandle(file);
					fprintf(stderr, "Could not write to file. Error: %s\n",
						Win32Utils::QuickFormatMessage(GetLastError()).c_str());
				}
			}
		}

		CloseHandle(file);
	}

	std::string ReadFile(const std::string& path)
	{
		return ReadFile(UTF8ToWide(path));
	}

	std::string ReadFile(const std::wstring& widePath)
	{
		std::ostringstream contents;
		// CreateFile doesn't have a path length limitation
		HANDLE file = CreateFileW(widePath.c_str(), GENERIC_READ,
			FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
			NULL);

		DWORD bytesRead;
		const int bufferSize = 4096;
		char readBuffer[bufferSize];

		do
		{
			BOOL result = ::ReadFile(file, readBuffer,
				bufferSize-2, &bytesRead, NULL);

			if (!result && GetLastError() != ERROR_HANDLE_EOF)
			{
				fprintf(stderr, "Could not read from file(%s). Error: %s\n",
					UTILS_NS::WideToUTF8(widePath).c_str(),
					Win32Utils::QuickFormatMessage(GetLastError()).c_str());
				CloseHandle(file);
				return std::string();
			}
			readBuffer[bytesRead] = '\0'; // NULL character
			contents << readBuffer;
		} while (bytesRead > 0);

		CloseHandle(file);
		return contents.str();
	}

	std::string Dirname(const std::string& path)
	{
		wchar_t pathBuffer[_MAX_PATH];
		wchar_t drive[_MAX_DRIVE];
		wchar_t dir[_MAX_DIR];
		wchar_t fname[_MAX_FNAME];
		wchar_t ext[_MAX_EXT];

		std::wstring widePath(UTILS_NS::UTF8ToWide(path));
		wcsncpy(pathBuffer, widePath.c_str(), MAX_PATH - 1);
		pathBuffer[MAX_PATH - 1] = '\0';

		_wsplitpath(pathBuffer, drive, dir, fname, ext);
		if (dir[wcslen(dir)-1] == '\\')
			dir[wcslen(dir)-1] = '\0';

		std::wstring dirname(drive);
		dirname.append(dir);
		return UTILS_NS::WideToUTF8(dirname);
	}

	bool CreateDirectoryImpl(const std::string& dir)
	{
		std::wstring wideDir(UTILS_NS::UTF8ToWide(dir));
		return (::CreateDirectoryW(wideDir.c_str(), NULL) == TRUE);
	}

	bool DeleteFile(const std::string& path)
	{
		// SHFileOperation doesn't care if it's a dir or file -- delegate
		return DeleteDirectory(path);
	}

	bool DeleteDirectory(const std::string& dir)
	{
		std::wstring wideDir(UTILS_NS::UTF8ToWide(dir));
		SHFILEOPSTRUCT op;
		op.hwnd = NULL;
		op.wFunc = FO_DELETE;
		op.pFrom = wideDir.c_str();
		op.pTo = NULL;
		op.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
		int rc = SHFileOperation(&op);
		return (rc == 0);
	}

	bool IsDirectory(const std::string& path)
	{
		return FileHasAttributes(path, FILE_ATTRIBUTE_DIRECTORY);
	}

	std::string GetUserRuntimeHomeDirectory()
	{
		wchar_t widePath[MAX_PATH];
		if (SHGetSpecialFolderPath(NULL, widePath, CSIDL_APPDATA, FALSE))
		{
			std::string path(UTILS_NS::WideToUTF8(widePath));
			return Join(path.c_str(), PRODUCT_NAME, NULL);
		}
		else
		{
			// Not good! What do we do in this case? I guess just use  a reasonable
			// default for Windows. Ideally this should *never* happen.
			return Join("C:", PRODUCT_NAME, NULL);
		}
	}

	std::string GetSystemRuntimeHomeDirectory()
	{
		wchar_t widePath[MAX_PATH];
		if (SHGetSpecialFolderPath(NULL, widePath, CSIDL_COMMON_APPDATA, FALSE))
		{
			std::string path(UTILS_NS::WideToUTF8(widePath));
			return Join(path.c_str(), PRODUCT_NAME, NULL);
		}
		else
		{
			return GetUserRuntimeHomeDirectory();
		}
	}

	bool IsHidden(const std::string& path)
	{
		return FileHasAttributes(path, FILE_ATTRIBUTE_HIDDEN);
	}

	void ListDir(const std::string& path, std::vector<std::string> &files)
	{
		if (!IsDirectory(path))
			return;

		files.clear();

		WIN32_FIND_DATA findFileData;
		ZeroMemory(&findFileData, sizeof(WIN32_FIND_DATA));

		std::wstring widePath(UTILS_NS::UTF8ToWide(path));
		std::wstring searchString(widePath + L"\\*");

		HANDLE hFind = FindFirstFile(searchString.c_str(), &findFileData);
		if (hFind != INVALID_HANDLE_VALUE)
		{
			do
			{
				std::wstring wideFilename(findFileData.cFileName);
				if (wideFilename != L"." && wideFilename != L"..")
				{
					std::string filename(UTILS_NS::WideToUTF8(wideFilename));
					files.push_back(filename);
				}

			} while (FindNextFile(hFind, &findFileData));
			FindClose(hFind);
		}
	}

	int RunAndWait(const std::string& path, std::vector<std::string> &args)
	{
		std::string cmdLine = "\"" + path + "\"";
		for (size_t i = 0; i < args.size(); i++)
		{
			cmdLine += " \"" + args.at(i) + "\"";
		}

#ifdef DEBUG
		std::cout << "running: " << cmdLine << std::endl;
#endif

		STARTUPINFO startupInfo;
		ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
		PROCESS_INFORMATION processInfo;
		ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
		startupInfo.cb = sizeof(STARTUPINFO);

		// Get the current working directory
		wchar_t cwd[MAX_PATH];
		DWORD size = GetCurrentDirectoryW(MAX_PATH, (wchar_t*) cwd);
		std::wstring wideCmdLine(UTILS_NS::UTF8ToWide(cmdLine));

		DWORD rc = -1;
		if (CreateProcessW(
			NULL,                           // No module name (use command line)
			(wchar_t*) wideCmdLine.c_str(), // Command line
			NULL,                           // Process handle not inheritable
			NULL,                           // Thread handle not inheritable
			FALSE,                          // Set handle inheritance to FALSE
			0,                              // No creation flags
			NULL,                           // Use parent's environment block
			(wchar_t*) cwd,                 // Use parent's starting directory
			&startupInfo,                   // Pointer to STARTUPINFO structure
			&processInfo))                  // Pointer to PROCESS_INFORMATION structure
		{
			// Wait until child process exits.
			WaitForSingleObject(processInfo.hProcess, INFINITE);

			// set the exit code
			GetExitCodeProcess(processInfo.hProcess, &rc);

			// Close process and thread handles.
			CloseHandle(processInfo.hProcess);
			CloseHandle(processInfo.hThread);
		}
		return rc;
	}

#ifndef NO_UNZIP
	bool Unzip(const std::string& source, const std::string& destination,
		UnzipCallback callback, void *data)
	{
		bool success = true;
		std::wstring wideSource(UTILS_NS::UTF8ToWide(source));
		std::wstring wideDestination(UTILS_NS::UTF8ToWide(destination));

		HZIP handle = OpenZip(wideSource.c_str(), 0);
		SetUnzipBaseDir(handle, wideDestination.c_str());

		ZIPENTRY zipEntry; ZeroMemory(&zipEntry, sizeof(ZIPENTRY));

		GetZipItem(handle, -1, &zipEntry);
		int numItems = zipEntry.index;
		if (callback)
		{
			std::ostringstream message;
			message << "Starting extraction of " << numItems
				<< " items from " << source << "to " << destination;
			std::string messageString(message.str());
			callback((char*) messageString.c_str(), 0, numItems, data);
		}

		for (int zi = 0; zi < numItems; zi++)
		{
			ZeroMemory(&zipEntry, sizeof(ZIPENTRY));
			GetZipItem(handle, zi, &zipEntry);

			if (callback)
			{
				std::string name(WideToUTF8(zipEntry.name));
				std::string message("Extracting ");
				message.append(name);
				message.append("...");
				bool result = callback((char*) message.c_str(), zi, numItems, data);
				if (!result)
				{
					success = false;
					break;
				}
			}

			UnzipItem(handle, zi, zipEntry.name);
		}
		CloseZip(handle);
		return success;
	}
#endif

	// TODO: implement this for other platforms
	void CopyRecursive(const std::string& dir, const std::string& dest, const std::string& exclude)
	{
		if (!IsDirectory(dest))
		{
			CreateDirectory(dest);
		}

#ifdef DEBUG
std::cout << "\n>Recursive copy " << dir << " to " << dest << std::endl;
#endif
		std::vector<std::string> files;
		ListDir(dir, files);
		for (size_t i = 0; i < files.size(); i++)
		{
			std::string& filename = files[i];
			if (!exclude.empty() && exclude == filename)
				continue;

			std::string srcName(Join(dir.c_str(), filename.c_str(), NULL));
			std::string destName(Join(dest.c_str(), filename.c_str(), NULL));

			if (IsDirectory(srcName))
			{
#ifdef DEBUG
				std::cout << "create dir: " << destName << std::endl;
#endif
				CreateDirectory(destName);
				CopyRecursive(srcName, destName);
			}
			else
			{
				std::wstring wideSrcName(UTILS_NS::UTF8ToWide(srcName));
				std::wstring wideDestName(UTILS_NS::UTF8ToWide(destName));
				CopyFileW(wideSrcName.c_str(), wideDestName.c_str(), FALSE);
			}
		}
	}
}
}

<commit_msg>Fixes for DeleteFile and DeleteDirectory.<commit_after>/**
 * Appcelerator Kroll - licensed under the Apache Public License 2
 * see LICENSE in the root folder for details on the license.
 * Copyright (c) 2008 Appcelerator, Inc. All Rights Reserved.
 */
#include "../utils.h"
#include <windows.h>
#include <shlobj.h>
#include <Iphlpapi.h>
#include <process.h>
#include <shellapi.h>
#include <sstream>

#ifndef NO_UNZIP
#include "../unzip/unzip.h"
#endif

namespace UTILS_NS
{
namespace FileUtils
{
	static bool FileHasAttributes(const std::wstring& widePath, DWORD attributes)
	{
		WIN32_FIND_DATA findFileData;
		ZeroMemory(&findFileData, sizeof(WIN32_FIND_DATA));

		HANDLE hFind = FindFirstFile(widePath.c_str(), &findFileData);
		if (hFind != INVALID_HANDLE_VALUE)
		{
			FindClose(hFind);

			// We do this check, because we may have passed in 0 for attributse
			// in which case the callee just wants to know if the path exists.
			return (findFileData.dwFileAttributes & attributes) == attributes;
		}
		else
		{
			return false;
		}
	}

	static bool FileHasAttributes(const std::string& path, DWORD attributes)
	{
		std::wstring widePath(UTILS_NS::UTF8ToWide(path));
		return FileHasAttributes(widePath, attributes);
	}

	std::string GetExecutableDirectory()
	{
		wchar_t path[MAX_PATH];
		path[MAX_PATH-1] = '\0';
		GetModuleFileNameW(NULL, path, MAX_PATH - 1);
		std::string fullPath(UTILS_NS::WideToUTF8(path));
		return Dirname(fullPath);
	}

	std::string GetTempDirectory()
	{
		wchar_t tempDirectory[MAX_PATH];
		tempDirectory[MAX_PATH-1] = '\0';
		GetTempPathW(MAX_PATH - 1, tempDirectory);

		// This function seem to return Windows stubby paths, so
		// let's convert it to a full path name.
		std::wstring dir(tempDirectory);
		GetLongPathNameW(dir.c_str(), tempDirectory, MAX_PATH - 1);
		std::string out(UTILS_NS::WideToUTF8(tempDirectory));
		srand(GetTickCount()); // initialize seed
		std::ostringstream s;
		s << "k" << (double) rand();
		std::string end(s.str());
		return FileUtils::Join(out.c_str(), end.c_str(), NULL);
	}

	bool IsFile(const std::string& file)
	{
		return FileHasAttributes(file, 0);
	}

	bool IsFile(const std::wstring& file)
	{
		return FileHasAttributes(file, 0);
	}

	void WriteFile(const std::string& path, const std::string& content)
	{
		std::wstring widePath(UTF8ToWide(path));
		// CreateFile doesn't have a path length limitation
		HANDLE file = CreateFileW(widePath.c_str(),
			GENERIC_WRITE,
			0,
			NULL,
			CREATE_ALWAYS,
			FILE_ATTRIBUTE_NORMAL,
			NULL);

		DWORD bytesWritten = 0;
		DWORD bytesToWrite = (DWORD)content.size();

		if (file != INVALID_HANDLE_VALUE)
		{
			while (bytesWritten < bytesToWrite)
			{
				if (FALSE == ::WriteFile(file, content.c_str() + bytesWritten,
					bytesToWrite - bytesWritten, &bytesWritten, NULL))
				{
					CloseHandle(file);
					fprintf(stderr, "Could not write to file. Error: %s\n",
						Win32Utils::QuickFormatMessage(GetLastError()).c_str());
				}
			}
		}

		CloseHandle(file);
	}

	std::string ReadFile(const std::string& path)
	{
		return ReadFile(UTF8ToWide(path));
	}

	std::string ReadFile(const std::wstring& widePath)
	{
		std::ostringstream contents;
		// CreateFile doesn't have a path length limitation
		HANDLE file = CreateFileW(widePath.c_str(), GENERIC_READ,
			FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
			NULL);

		DWORD bytesRead;
		const int bufferSize = 4096;
		char readBuffer[bufferSize];

		do
		{
			BOOL result = ::ReadFile(file, readBuffer,
				bufferSize-2, &bytesRead, NULL);

			if (!result && GetLastError() != ERROR_HANDLE_EOF)
			{
				fprintf(stderr, "Could not read from file(%s). Error: %s\n",
					UTILS_NS::WideToUTF8(widePath).c_str(),
					Win32Utils::QuickFormatMessage(GetLastError()).c_str());
				CloseHandle(file);
				return std::string();
			}
			readBuffer[bytesRead] = '\0'; // NULL character
			contents << readBuffer;
		} while (bytesRead > 0);

		CloseHandle(file);
		return contents.str();
	}

	std::string Dirname(const std::string& path)
	{
		wchar_t pathBuffer[_MAX_PATH];
		wchar_t drive[_MAX_DRIVE];
		wchar_t dir[_MAX_DIR];
		wchar_t fname[_MAX_FNAME];
		wchar_t ext[_MAX_EXT];

		std::wstring widePath(UTILS_NS::UTF8ToWide(path));
		wcsncpy(pathBuffer, widePath.c_str(), MAX_PATH - 1);
		pathBuffer[MAX_PATH - 1] = '\0';

		_wsplitpath(pathBuffer, drive, dir, fname, ext);
		if (dir[wcslen(dir)-1] == '\\')
			dir[wcslen(dir)-1] = '\0';

		std::wstring dirname(drive);
		dirname.append(dir);
		return UTILS_NS::WideToUTF8(dirname);
	}

	bool CreateDirectoryImpl(const std::string& dir)
	{
		std::wstring wideDir(UTILS_NS::UTF8ToWide(dir));
		return (::CreateDirectoryW(wideDir.c_str(), NULL) == TRUE);
	}

	bool DeleteFile(const std::string& path)
	{
		// SHFileOperation doesn't care if it's a dir or file -- delegate
		// Use DeleteFile here instead of SHFileOperation (DeleteDirectory),
		// because that is the best way to ensure that the file does not
		// end up in the Recycle Bin and DeleteFile has saner handling
		// of paths with spaces.
		//return ::DeleteFile(path);
		return DeleteDirectory(path);
	}

	bool DeleteDirectory(const std::string& dir)
	{
		std::wstring wideDir(UTILS_NS::UTF8ToWide(dir));

		// SHFileOperation does not handle paths with spaces well, so
		// convert to a Windows stubby path here. Ugh.
		wchar_t stubbyPath[MAX_PATH];
		GetShortPathNameW(wideDir.c_str(), stubbyPath, MAX_PATH - 1);

		SHFILEOPSTRUCT op;
		op.hwnd = NULL;
		op.wFunc = FO_DELETE;
		op.pFrom = stubbyPath;
		op.pTo = NULL;
		op.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_NOERRORUI;
		int rc = SHFileOperation(&op);
		return (rc == 0);
	}

	bool IsDirectory(const std::string& path)
	{
		return FileHasAttributes(path, FILE_ATTRIBUTE_DIRECTORY);
	}

	std::string GetUserRuntimeHomeDirectory()
	{
		wchar_t widePath[MAX_PATH];
		if (SHGetSpecialFolderPath(NULL, widePath, CSIDL_APPDATA, FALSE))
		{
			std::string path(UTILS_NS::WideToUTF8(widePath));
			return Join(path.c_str(), PRODUCT_NAME, NULL);
		}
		else
		{
			// Not good! What do we do in this case? I guess just use  a reasonable
			// default for Windows. Ideally this should *never* happen.
			return Join("C:", PRODUCT_NAME, NULL);
		}
	}

	std::string GetSystemRuntimeHomeDirectory()
	{
		wchar_t widePath[MAX_PATH];
		if (SHGetSpecialFolderPath(NULL, widePath, CSIDL_COMMON_APPDATA, FALSE))
		{
			std::string path(UTILS_NS::WideToUTF8(widePath));
			return Join(path.c_str(), PRODUCT_NAME, NULL);
		}
		else
		{
			return GetUserRuntimeHomeDirectory();
		}
	}

	bool IsHidden(const std::string& path)
	{
		return FileHasAttributes(path, FILE_ATTRIBUTE_HIDDEN);
	}

	void ListDir(const std::string& path, std::vector<std::string> &files)
	{
		if (!IsDirectory(path))
			return;

		files.clear();

		WIN32_FIND_DATA findFileData;
		ZeroMemory(&findFileData, sizeof(WIN32_FIND_DATA));

		std::wstring widePath(UTILS_NS::UTF8ToWide(path));
		std::wstring searchString(widePath + L"\\*");

		HANDLE hFind = FindFirstFile(searchString.c_str(), &findFileData);
		if (hFind != INVALID_HANDLE_VALUE)
		{
			do
			{
				std::wstring wideFilename(findFileData.cFileName);
				if (wideFilename != L"." && wideFilename != L"..")
				{
					std::string filename(UTILS_NS::WideToUTF8(wideFilename));
					files.push_back(filename);
				}

			} while (FindNextFile(hFind, &findFileData));
			FindClose(hFind);
		}
	}

	int RunAndWait(const std::string& path, std::vector<std::string> &args)
	{
		std::string cmdLine = "\"" + path + "\"";
		for (size_t i = 0; i < args.size(); i++)
		{
			cmdLine += " \"" + args.at(i) + "\"";
		}

#ifdef DEBUG
		std::cout << "running: " << cmdLine << std::endl;
#endif

		STARTUPINFO startupInfo;
		ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
		PROCESS_INFORMATION processInfo;
		ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
		startupInfo.cb = sizeof(STARTUPINFO);

		// Get the current working directory
		wchar_t cwd[MAX_PATH];
		DWORD size = GetCurrentDirectoryW(MAX_PATH, (wchar_t*) cwd);
		std::wstring wideCmdLine(UTILS_NS::UTF8ToWide(cmdLine));

		DWORD rc = -1;
		if (CreateProcessW(
			NULL,                           // No module name (use command line)
			(wchar_t*) wideCmdLine.c_str(), // Command line
			NULL,                           // Process handle not inheritable
			NULL,                           // Thread handle not inheritable
			FALSE,                          // Set handle inheritance to FALSE
			0,                              // No creation flags
			NULL,                           // Use parent's environment block
			(wchar_t*) cwd,                 // Use parent's starting directory
			&startupInfo,                   // Pointer to STARTUPINFO structure
			&processInfo))                  // Pointer to PROCESS_INFORMATION structure
		{
			// Wait until child process exits.
			WaitForSingleObject(processInfo.hProcess, INFINITE);

			// set the exit code
			GetExitCodeProcess(processInfo.hProcess, &rc);

			// Close process and thread handles.
			CloseHandle(processInfo.hProcess);
			CloseHandle(processInfo.hThread);
		}
		return rc;
	}

#ifndef NO_UNZIP
	bool Unzip(const std::string& source, const std::string& destination,
		UnzipCallback callback, void *data)
	{
		bool success = true;
		std::wstring wideSource(UTILS_NS::UTF8ToWide(source));
		std::wstring wideDestination(UTILS_NS::UTF8ToWide(destination));

		HZIP handle = OpenZip(wideSource.c_str(), 0);
		SetUnzipBaseDir(handle, wideDestination.c_str());

		ZIPENTRY zipEntry; ZeroMemory(&zipEntry, sizeof(ZIPENTRY));

		GetZipItem(handle, -1, &zipEntry);
		int numItems = zipEntry.index;
		if (callback)
		{
			std::ostringstream message;
			message << "Starting extraction of " << numItems
				<< " items from " << source << "to " << destination;
			std::string messageString(message.str());
			callback((char*) messageString.c_str(), 0, numItems, data);
		}

		for (int zi = 0; zi < numItems; zi++)
		{
			ZeroMemory(&zipEntry, sizeof(ZIPENTRY));
			GetZipItem(handle, zi, &zipEntry);

			if (callback)
			{
				std::string name(WideToUTF8(zipEntry.name));
				std::string message("Extracting ");
				message.append(name);
				message.append("...");
				bool result = callback((char*) message.c_str(), zi, numItems, data);
				if (!result)
				{
					success = false;
					break;
				}
			}

			UnzipItem(handle, zi, zipEntry.name);
		}
		CloseZip(handle);
		return success;
	}
#endif

	// TODO: implement this for other platforms
	void CopyRecursive(const std::string& dir, const std::string& dest, const std::string& exclude)
	{
		if (!IsDirectory(dest))
		{
			CreateDirectory(dest);
		}

#ifdef DEBUG
std::cout << "\n>Recursive copy " << dir << " to " << dest << std::endl;
#endif
		std::vector<std::string> files;
		ListDir(dir, files);
		for (size_t i = 0; i < files.size(); i++)
		{
			std::string& filename = files[i];
			if (!exclude.empty() && exclude == filename)
				continue;

			std::string srcName(Join(dir.c_str(), filename.c_str(), NULL));
			std::string destName(Join(dest.c_str(), filename.c_str(), NULL));

			if (IsDirectory(srcName))
			{
#ifdef DEBUG
				std::cout << "create dir: " << destName << std::endl;
#endif
				CreateDirectory(destName);
				CopyRecursive(srcName, destName);
			}
			else
			{
				std::wstring wideSrcName(UTILS_NS::UTF8ToWide(srcName));
				std::wstring wideDestName(UTILS_NS::UTF8ToWide(destName));
				CopyFileW(wideSrcName.c_str(), wideDestName.c_str(), FALSE);
			}
		}
	}
}
}

<|endoftext|>


<commit_before>// Copyright (c) 2011 Sirikata Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can
// be found in the LICENSE file.

#include "Environment.hpp"
#include <sirikata/oh/HostedObject.hpp>

#define ENVIRONMENT_SERVICE_PORT 23
#define ENV_LOG(lvl,msg) SILOG(environment,lvl,msg);

namespace Sirikata {

using namespace boost::property_tree;

EnvironmentSimulation::EnvironmentSimulation(HostedObjectPtr ho, const SpaceObjectReference& pres)
 : mParent(ho),
   mPresence(pres)
{
}

void EnvironmentSimulation::start() {
    ODPSST::Stream::Ptr stream = mParent->getSpaceStream(mPresence);
    if (!stream) return;

    stream->createChildStream(
        std::tr1::bind(&EnvironmentSimulation::handleCreatedStream, this, std::tr1::placeholders::_1, std::tr1::placeholders::_2),
        NULL, 0,
        ENVIRONMENT_SERVICE_PORT, ENVIRONMENT_SERVICE_PORT
    );
}

void EnvironmentSimulation::stop() {
}

boost::any EnvironmentSimulation::invoke(std::vector<boost::any>& params) {
    // Decode the command. First argument is the "function name"
    if (params.empty() || !Invokable::anyIsString(params[0]))
        return boost::any();

    String name = Invokable::anyAsString(params[0]);

    if (name == "get") {
        if (params.size() < 2 || !Invokable::anyIsString(params[1]))
            return boost::any();
        String key = Invokable::anyAsString(params[1]);
        String val = mEnvironment.get<std::string>(key);
        return Invokable::asAny(val);
    }
    else if (name == "set") {
        if (params.size() < 3
            || !Invokable::anyIsString(params[1])
            || !Invokable::anyIsString(params[2]))
            return boost::any();
        String key = Invokable::anyAsString(params[1]);
        String val = Invokable::anyAsString(params[2]);
        mEnvironment.put(key, val);
        sendUpdate();
        return Invokable::asAny(true);
    }

    return boost::any();
}

void EnvironmentSimulation::handleCreatedStream(int err, ODPSST::Stream::Ptr strm) {
    mStream = strm;
    mRecordStream.initialize(
        mStream,
        std::tr1::bind(&EnvironmentSimulation::handleMessage, this, std::tr1::placeholders::_1)
    );
}

void EnvironmentSimulation::handleMessage(MemoryReference data) {
    ENV_LOG(insane, "Received message: " << String((char*)data.begin(), data.size()));

    // Currently just receiving whole thing every time
    std::stringstream env_json(std::string((char*)data.begin(), data.size()));
    read_json(env_json, mEnvironment);
}

void EnvironmentSimulation::sendUpdate() {
    // Currently we just always serialize and send the whole thing
    std::stringstream data_json;
    write_json(data_json, mEnvironment);
    String serialized = data_json.str();
    ENV_LOG(insane, "Sending update: " << serialized);
    mRecordStream.write(MemoryReference(serialized));
}

} // namespace Sirikata
<commit_msg>Handle keys that don't exist in environment client.<commit_after>// Copyright (c) 2011 Sirikata Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can
// be found in the LICENSE file.

#include "Environment.hpp"
#include <sirikata/oh/HostedObject.hpp>

#define ENVIRONMENT_SERVICE_PORT 23
#define ENV_LOG(lvl,msg) SILOG(environment,lvl,msg);

namespace Sirikata {

using namespace boost::property_tree;

EnvironmentSimulation::EnvironmentSimulation(HostedObjectPtr ho, const SpaceObjectReference& pres)
 : mParent(ho),
   mPresence(pres)
{
}

void EnvironmentSimulation::start() {
    ODPSST::Stream::Ptr stream = mParent->getSpaceStream(mPresence);
    if (!stream) return;

    stream->createChildStream(
        std::tr1::bind(&EnvironmentSimulation::handleCreatedStream, this, std::tr1::placeholders::_1, std::tr1::placeholders::_2),
        NULL, 0,
        ENVIRONMENT_SERVICE_PORT, ENVIRONMENT_SERVICE_PORT
    );
}

void EnvironmentSimulation::stop() {
}

boost::any EnvironmentSimulation::invoke(std::vector<boost::any>& params) {
    // Decode the command. First argument is the "function name"
    if (params.empty() || !Invokable::anyIsString(params[0]))
        return boost::any();

    String name = Invokable::anyAsString(params[0]);

    if (name == "get") {
        if (params.size() < 2 || !Invokable::anyIsString(params[1]))
            return boost::any();
        String key = Invokable::anyAsString(params[1]);
        String val;
        try {
            val = mEnvironment.get<std::string>(key);
        } catch (ptree_bad_path exc) {
            return boost::any();
        }
        return Invokable::asAny(val);
    }
    else if (name == "set") {
        if (params.size() < 3
            || !Invokable::anyIsString(params[1])
            || !Invokable::anyIsString(params[2]))
            return boost::any();
        String key = Invokable::anyAsString(params[1]);
        String val = Invokable::anyAsString(params[2]);
        mEnvironment.put(key, val);
        sendUpdate();
        return Invokable::asAny(true);
    }

    return boost::any();
}

void EnvironmentSimulation::handleCreatedStream(int err, ODPSST::Stream::Ptr strm) {
    mStream = strm;
    mRecordStream.initialize(
        mStream,
        std::tr1::bind(&EnvironmentSimulation::handleMessage, this, std::tr1::placeholders::_1)
    );
}

void EnvironmentSimulation::handleMessage(MemoryReference data) {
    ENV_LOG(insane, "Received message: " << String((char*)data.begin(), data.size()));

    // Currently just receiving whole thing every time
    std::stringstream env_json(std::string((char*)data.begin(), data.size()));
    read_json(env_json, mEnvironment);
}

void EnvironmentSimulation::sendUpdate() {
    // Currently we just always serialize and send the whole thing
    std::stringstream data_json;
    write_json(data_json, mEnvironment);
    String serialized = data_json.str();
    ENV_LOG(insane, "Sending update: " << serialized);
    mRecordStream.write(MemoryReference(serialized));
}

} // namespace Sirikata
<|endoftext|>