<commit_before>//===- FunctionResolution.cpp - Resolve declarations to implementations ---===//
//
//                     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.
//
//===----------------------------------------------------------------------===//
//
// 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/DerivedTypes.h"
#include "llvm/Pass.h"
#include "llvm/iOther.h"
#include "llvm/Constants.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Assembly/Writer.h"
#include "Support/Statistic.h"
#include <algorithm>

namespace llvm {

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

  struct FunctionResolvingPass : public Pass {
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<TargetData>();
    }

    bool run(Module &M);
  };
  RegisterOpt<FunctionResolvingPass> X("funcresolve", "Resolve Functions");
}

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

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])
            if (OldMT->getParamTypes()[i]->getPrimitiveID() !=
                ConcreteMT->getParamTypes()[i]->getPrimitiveID()) {
              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> (...)
      //
      if (!Old->use_empty()) {  // Avoid making the CPR unless we really need it
        Value *Replacement = Concrete;
        if (Concrete->getType() != Old->getType())
          Replacement = ConstantExpr::getCast(ConstantPointerRef::get(Concrete),
                                              Old->getType());
        NumResolved += Old->use_size();
        Old->replaceAllUsesWith(Replacement);
      }

      // 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;
  Constant *CCPR = ConstantPointerRef::get(Concrete);

  for (unsigned i = 0; i != Globals.size(); ++i)
    if (Globals[i] != Concrete) {
      Constant *Cast = ConstantExpr::getCast(CCPR, Globals[i]->getType());
      Globals[i]->replaceAllUsesWith(Cast);

      // Since there are no uses of Old anymore, remove it from the module.
      M.getGlobalList().erase(cast<GlobalVariable>(Globals[i]));

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

static bool ProcessGlobalsWithSameName(Module &M, TargetData &TD,
                                       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

  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 {
      GlobalVariable *GV = cast<GlobalVariable>(Globals[i]);
      if (!GV->isExternal()) {
        if (Concrete) {
          std::cerr << "WARNING: Two global variables with external linkage"
                    << " exist with the same name: '" << GV->getName()
                    << "'!\n";
          return false;
        }
        Concrete = GV;
      }
    }
    ++i;
  }

  if (Globals.size() > 1) {         // Found a multiply defined global...
    // If there are no external declarations, and there is at most one
    // externally visible instance of the global, then there is nothing to do.
    //
    bool HasExternal = false;
    unsigned NumInstancesWithExternalLinkage = 0;

    for (unsigned i = 0, e = Globals.size(); i != e; ++i) {
      if (Globals[i]->isExternal())
        HasExternal = true;
      else if (!Globals[i]->hasInternalLinkage())
        NumInstancesWithExternalLinkage++;
    }

    if (!HasExternal && NumInstancesWithExternalLinkage <= 1)
      return false;  // Nothing to do?  Must have multiple internal definitions.

    // There are a couple of special cases we don't want to print the warning
    // for, check them now.
    bool DontPrintWarning = false;
    if (Concrete && Globals.size() == 2) {
      GlobalValue *Other = Globals[Globals[0] == Concrete];
      // If the non-concrete global is a function which takes (...) arguments,
      // and the return values match, do not warn.
      if (Function *ConcreteF = dyn_cast<Function>(Concrete))
        if (Function *OtherF = dyn_cast<Function>(Other))
          if (ConcreteF->getReturnType() == OtherF->getReturnType() &&
              OtherF->getFunctionType()->isVarArg() &&
              OtherF->getFunctionType()->getParamTypes().empty())
            DontPrintWarning = true;

      // Otherwise, if the non-concrete global is a global array variable with a
      // size of 0, and the concrete global is an array with a real size, don't
      // warn.  This occurs due to declaring 'extern int A[];'.
      if (GlobalVariable *ConcreteGV = dyn_cast<GlobalVariable>(Concrete))
        if (GlobalVariable *OtherGV = dyn_cast<GlobalVariable>(Other))
          if (const ArrayType *OtherAT =
              dyn_cast<ArrayType>(OtherGV->getType()->getElementType()))
            if (const ArrayType *ConcreteAT =
                dyn_cast<ArrayType>(ConcreteGV->getType()->getElementType()))
              if (OtherAT->getElementType() == ConcreteAT->getElementType() &&
                  OtherAT->getNumElements() == 0)
                DontPrintWarning = true;
    }

    if (!DontPrintWarning) {
      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() << " %"
                  << Globals[i]->getName() << "\n";
      }
    }

    if (!Concrete)
      Concrete = Globals[0];
    else if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Concrete)) {
      // Handle special case hack to change globals if it will make their types
      // happier in the long run.  The situation we do this is intentionally
      // extremely limited.
      if (GV->use_empty() && GV->hasInitializer() &&
          GV->getInitializer()->isNullValue()) {
        // Check to see if there is another (external) global with the same size
        // and a non-empty use-list.  If so, we will make IT be the real
        // implementation.
        unsigned TS = TD.getTypeSize(Concrete->getType()->getElementType());
        for (unsigned i = 0, e = Globals.size(); i != e; ++i)
          if (Globals[i] != Concrete && !Globals[i]->use_empty() &&
              isa<GlobalVariable>(Globals[i]) &&
              TD.getTypeSize(Globals[i]->getType()->getElementType()) == TS) {
            // At this point we want to replace Concrete with Globals[i].  Make
            // concrete external, and Globals[i] have an initializer.
            GlobalVariable *NGV = cast<GlobalVariable>(Globals[i]);
            const Type *ElTy = NGV->getType()->getElementType();
            NGV->setInitializer(Constant::getNullValue(ElTy));
            cast<GlobalVariable>(Concrete)->setInitializer(0);
            Concrete = NGV;
            break;
          }
      }
    }

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

bool FunctionResolvingPass::run(Module &M) {
  std::map<std::string, std::vector<GlobalValue*> > Globals;

  // Loop over the globals, adding them to the Globals map.  We use a two pass
  // algorithm here to avoid problems with iterators getting invalidated if we
  // did a one pass scheme.
  //
  bool Changed = false;
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ) {
    Function *F = I++;
    if (F->use_empty() && F->isExternal()) {
      M.getFunctionList().erase(F);
      Changed = true;
    } else if (!F->hasInternalLinkage() && !F->getName().empty())
      Globals[F->getName()].push_back(F);
  }

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

  TargetData &TD = getAnalysis<TargetData>();

  // 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, TD, 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;
}

} // End llvm namespace
<commit_msg>When spewing out warnings during function resolution, do not vomit out pages and pages of non-symbolic types.<commit_after>//===- FunctionResolution.cpp - Resolve declarations to implementations ---===//
//
//                     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.
//
//===----------------------------------------------------------------------===//
//
// 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/DerivedTypes.h"
#include "llvm/Pass.h"
#include "llvm/iOther.h"
#include "llvm/Constants.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Assembly/Writer.h"
#include "Support/Statistic.h"
#include <algorithm>

namespace llvm {

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

  struct FunctionResolvingPass : public Pass {
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequired<TargetData>();
    }

    bool run(Module &M);
  };
  RegisterOpt<FunctionResolvingPass> X("funcresolve", "Resolve Functions");
}

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

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])
            if (OldMT->getParamTypes()[i]->getPrimitiveID() !=
                ConcreteMT->getParamTypes()[i]->getPrimitiveID()) {
              std::cerr << "WARNING: Function [" << Old->getName()
                        << "]: Parameter types conflict for: '";
              WriteTypeSymbolic(std::cerr, OldMT, &M);
              std::cerr << "' and '";
              WriteTypeSymbolic(std::cerr, ConcreteMT, &M);
              std::cerr << "'\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> (...)
      //
      if (!Old->use_empty()) {  // Avoid making the CPR unless we really need it
        Value *Replacement = Concrete;
        if (Concrete->getType() != Old->getType())
          Replacement = ConstantExpr::getCast(ConstantPointerRef::get(Concrete),
                                              Old->getType());
        NumResolved += Old->use_size();
        Old->replaceAllUsesWith(Replacement);
      }

      // 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;
  Constant *CCPR = ConstantPointerRef::get(Concrete);

  for (unsigned i = 0; i != Globals.size(); ++i)
    if (Globals[i] != Concrete) {
      Constant *Cast = ConstantExpr::getCast(CCPR, Globals[i]->getType());
      Globals[i]->replaceAllUsesWith(Cast);

      // Since there are no uses of Old anymore, remove it from the module.
      M.getGlobalList().erase(cast<GlobalVariable>(Globals[i]));

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

static bool ProcessGlobalsWithSameName(Module &M, TargetData &TD,
                                       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

  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 {
      GlobalVariable *GV = cast<GlobalVariable>(Globals[i]);
      if (!GV->isExternal()) {
        if (Concrete) {
          std::cerr << "WARNING: Two global variables with external linkage"
                    << " exist with the same name: '" << GV->getName()
                    << "'!\n";
          return false;
        }
        Concrete = GV;
      }
    }
    ++i;
  }

  if (Globals.size() > 1) {         // Found a multiply defined global...
    // If there are no external declarations, and there is at most one
    // externally visible instance of the global, then there is nothing to do.
    //
    bool HasExternal = false;
    unsigned NumInstancesWithExternalLinkage = 0;

    for (unsigned i = 0, e = Globals.size(); i != e; ++i) {
      if (Globals[i]->isExternal())
        HasExternal = true;
      else if (!Globals[i]->hasInternalLinkage())
        NumInstancesWithExternalLinkage++;
    }

    if (!HasExternal && NumInstancesWithExternalLinkage <= 1)
      return false;  // Nothing to do?  Must have multiple internal definitions.

    // There are a couple of special cases we don't want to print the warning
    // for, check them now.
    bool DontPrintWarning = false;
    if (Concrete && Globals.size() == 2) {
      GlobalValue *Other = Globals[Globals[0] == Concrete];
      // If the non-concrete global is a function which takes (...) arguments,
      // and the return values match, do not warn.
      if (Function *ConcreteF = dyn_cast<Function>(Concrete))
        if (Function *OtherF = dyn_cast<Function>(Other))
          if (ConcreteF->getReturnType() == OtherF->getReturnType() &&
              OtherF->getFunctionType()->isVarArg() &&
              OtherF->getFunctionType()->getParamTypes().empty())
            DontPrintWarning = true;

      // Otherwise, if the non-concrete global is a global array variable with a
      // size of 0, and the concrete global is an array with a real size, don't
      // warn.  This occurs due to declaring 'extern int A[];'.
      if (GlobalVariable *ConcreteGV = dyn_cast<GlobalVariable>(Concrete))
        if (GlobalVariable *OtherGV = dyn_cast<GlobalVariable>(Other))
          if (const ArrayType *OtherAT =
              dyn_cast<ArrayType>(OtherGV->getType()->getElementType()))
            if (const ArrayType *ConcreteAT =
                dyn_cast<ArrayType>(ConcreteGV->getType()->getElementType()))
              if (OtherAT->getElementType() == ConcreteAT->getElementType() &&
                  OtherAT->getNumElements() == 0)
                DontPrintWarning = true;
    }

    if (!DontPrintWarning) {
      std::cerr << "WARNING: Found global types that are not compatible:\n";
      for (unsigned i = 0; i < Globals.size(); ++i) {
        std::cerr << "\t";
        WriteTypeSymbolic(std::cerr, Globals[i]->getType(), &M);
        std::cerr << " %" << Globals[i]->getName() << "\n";
      }
    }

    if (!Concrete)
      Concrete = Globals[0];
    else if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Concrete)) {
      // Handle special case hack to change globals if it will make their types
      // happier in the long run.  The situation we do this is intentionally
      // extremely limited.
      if (GV->use_empty() && GV->hasInitializer() &&
          GV->getInitializer()->isNullValue()) {
        // Check to see if there is another (external) global with the same size
        // and a non-empty use-list.  If so, we will make IT be the real
        // implementation.
        unsigned TS = TD.getTypeSize(Concrete->getType()->getElementType());
        for (unsigned i = 0, e = Globals.size(); i != e; ++i)
          if (Globals[i] != Concrete && !Globals[i]->use_empty() &&
              isa<GlobalVariable>(Globals[i]) &&
              TD.getTypeSize(Globals[i]->getType()->getElementType()) == TS) {
            // At this point we want to replace Concrete with Globals[i].  Make
            // concrete external, and Globals[i] have an initializer.
            GlobalVariable *NGV = cast<GlobalVariable>(Globals[i]);
            const Type *ElTy = NGV->getType()->getElementType();
            NGV->setInitializer(Constant::getNullValue(ElTy));
            cast<GlobalVariable>(Concrete)->setInitializer(0);
            Concrete = NGV;
            break;
          }
      }
    }

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

bool FunctionResolvingPass::run(Module &M) {
  std::map<std::string, std::vector<GlobalValue*> > Globals;

  // Loop over the globals, adding them to the Globals map.  We use a two pass
  // algorithm here to avoid problems with iterators getting invalidated if we
  // did a one pass scheme.
  //
  bool Changed = false;
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ) {
    Function *F = I++;
    if (F->use_empty() && F->isExternal()) {
      M.getFunctionList().erase(F);
      Changed = true;
    } else if (!F->hasInternalLinkage() && !F->getName().empty())
      Globals[F->getName()].push_back(F);
  }

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

  TargetData &TD = getAnalysis<TargetData>();

  // 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, TD, 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;
}

} // End llvm namespace
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "PINSFVMomentumFrictionCorrection.h"
#include "INSFVRhieChowInterpolator.h"
#include "NS.h"
#include "SystemBase.h"

registerMooseObject("NavierStokesApp", PINSFVMomentumFrictionCorrection);

InputParameters
PINSFVMomentumFrictionCorrection::validParams()
{
  auto params = INSFVFluxKernel::validParams();
  params.addClassDescription(
      "Computes the diffusion kernel to avoid pressure-driven oscillations.");
  params.addParam<MooseFunctorName>("Darcy_name", "Name of the Darcy coefficients property.");
  params.addParam<MooseFunctorName>("Forchheimer_name",
                                    "Name of the Forchheimer coefficients property.");
  params.addParam<MooseFunctorName>(NS::porosity, NS::porosity, "The porosity");
  params.addRequiredParam<MooseFunctorName>(NS::density, "The density.");
  params.addRangeCheckedParam<Real>("consistent_scaling",
                                    1,
                                    "consistent_scaling >= 0",
                                    "Smoothing scaling parameter to control "
                                    "collocated mesh oscillations");
  return params;
}

PINSFVMomentumFrictionCorrection::PINSFVMomentumFrictionCorrection(const InputParameters & params)
  : INSFVFluxKernel(params),
    _cL(isParamValid("Darcy_name") ? &getFunctor<ADRealVectorValue>("Darcy_name") : nullptr),
    _cQ(isParamValid("Forchheimer_name") ? &getFunctor<ADRealVectorValue>("Forchheimer_name")
                                         : nullptr),
    _use_Darcy_friction_model(isParamValid("Darcy_name")),
    _use_Forchheimer_friction_model(isParamValid("Forchheimer_name")),
    _eps(getFunctor<ADReal>(NS::porosity)),
    _rho(getFunctor<ADReal>(NS::density)),
    _consistent_scaling(getParam<Real>("consistent_scaling"))
{
  if (!_use_Darcy_friction_model && !_use_Forchheimer_friction_model)
    mooseError("At least one friction model needs to be specified.");
#ifndef MOOSE_GLOBAL_AD_INDEXING
  mooseError("PINSFV is not supported by local AD indexing. In order to use PINSFV, please run "
             "the configure script in the root MOOSE directory with the configure option "
             "'--with-ad-indexing-type=global'");
#endif
}

void
PINSFVMomentumFrictionCorrection::gatherRCData(const FaceInfo & fi)
{
  if (skipForBoundary(fi))
    return;

  _face_info = &fi;
  _normal = fi.normal();
  _face_type = fi.faceType(_var.name());

#ifdef MOOSE_GLOBAL_AD_INDEXING
  using namespace Moose::FV;

  const auto elem_face = elemFromFace();
  const auto neighbor_face = neighborFromFace();

  ADReal friction_term_elem = 0;
  ADReal friction_term_neighbor = 0;

  if (_use_Darcy_friction_model)
  {
    friction_term_elem += (*_cL)(elem_face)(_index)*_rho(elem_face) / _eps(elem_face);
    friction_term_neighbor +=
        (*_cL)(neighbor_face)(_index)*_rho(neighbor_face) / _eps(neighbor_face);
  }
  if (_use_Forchheimer_friction_model)
  {
    friction_term_elem += (*_cQ)(elem_face)(_index)*_rho(elem_face) / _eps(elem_face);
    friction_term_neighbor +=
        (*_cQ)(neighbor_face)(_index)*_rho(neighbor_face) / _eps(neighbor_face);
  }

  Point _face_centroid = _face_info->faceCentroid();
  Point _elem_centroid = _face_info->elemCentroid();
  Point _neighbor_centroid = _face_info->neighborCentroid();

  Real geometric_factor = _consistent_scaling * (_neighbor_centroid - _face_centroid).norm() *
                          (_elem_centroid - _face_centroid).norm();

  // Compute the diffusion driven by the velocity gradient
  // Interpolate viscosity divided by porosity on the face
  ADReal diff_face;
  interpolate(Moose::FV::InterpMethod::Average,
              diff_face,
              friction_term_elem * geometric_factor,
              friction_term_neighbor * geometric_factor,
              *_face_info,
              true);

  // Compute face superficial velocity gradient
  auto dudn =
      _var.gradient(Moose::FV::makeCDFace(*_face_info, faceArgSubdomains())) * _face_info->normal();

  if (_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
      _face_type == FaceInfo::VarFaceNeighbors::BOTH)
  {
    const auto dof_number = _face_info->elem().dof_number(_sys.number(), _var.number(), 0);
    // A gradient is a linear combination of degrees of freedom so it's safe to straight-up index
    // into the derivatives vector at the dof we care about
    ADReal ae = dudn.derivatives()[dof_number];
    ae *= -diff_face;
    _rc_uo.addToA(&fi.elem(), _index, ae * (fi.faceArea() * fi.faceCoord()));
  }
  if (_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR ||
      _face_type == FaceInfo::VarFaceNeighbors::BOTH)
  {
    const auto dof_number = _face_info->neighbor().dof_number(_sys.number(), _var.number(), 0);
    ADReal an = dudn.derivatives()[dof_number];
    an *= diff_face;
    _rc_uo.addToA(fi.neighborPtr(), _index, an * (fi.faceArea() * fi.faceCoord()));
  }

  const auto strong_resid = -diff_face * dudn;

  processResidual(strong_resid * (fi.faceArea() * fi.faceCoord()));
#endif
}
<commit_msg>Resolve old Guillaume conversation about doc string<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "PINSFVMomentumFrictionCorrection.h"
#include "INSFVRhieChowInterpolator.h"
#include "NS.h"
#include "SystemBase.h"

registerMooseObject("NavierStokesApp", PINSFVMomentumFrictionCorrection);

InputParameters
PINSFVMomentumFrictionCorrection::validParams()
{
  auto params = INSFVFluxKernel::validParams();
  params.addClassDescription(
      "Computes a correction term to avoid oscillations from average pressure interpolation in "
      "regions of high changes in friction coefficients.");
  params.addParam<MooseFunctorName>("Darcy_name", "Name of the Darcy coefficients property.");
  params.addParam<MooseFunctorName>("Forchheimer_name",
                                    "Name of the Forchheimer coefficients property.");
  params.addParam<MooseFunctorName>(NS::porosity, NS::porosity, "The porosity");
  params.addRequiredParam<MooseFunctorName>(NS::density, "The density.");
  params.addRangeCheckedParam<Real>("consistent_scaling",
                                    1,
                                    "consistent_scaling >= 0",
                                    "Smoothing scaling parameter to control "
                                    "collocated mesh oscillations");
  return params;
}

PINSFVMomentumFrictionCorrection::PINSFVMomentumFrictionCorrection(const InputParameters & params)
  : INSFVFluxKernel(params),
    _cL(isParamValid("Darcy_name") ? &getFunctor<ADRealVectorValue>("Darcy_name") : nullptr),
    _cQ(isParamValid("Forchheimer_name") ? &getFunctor<ADRealVectorValue>("Forchheimer_name")
                                         : nullptr),
    _use_Darcy_friction_model(isParamValid("Darcy_name")),
    _use_Forchheimer_friction_model(isParamValid("Forchheimer_name")),
    _eps(getFunctor<ADReal>(NS::porosity)),
    _rho(getFunctor<ADReal>(NS::density)),
    _consistent_scaling(getParam<Real>("consistent_scaling"))
{
  if (!_use_Darcy_friction_model && !_use_Forchheimer_friction_model)
    mooseError("At least one friction model needs to be specified.");
#ifndef MOOSE_GLOBAL_AD_INDEXING
  mooseError("PINSFV is not supported by local AD indexing. In order to use PINSFV, please run "
             "the configure script in the root MOOSE directory with the configure option "
             "'--with-ad-indexing-type=global'");
#endif
}

void
PINSFVMomentumFrictionCorrection::gatherRCData(const FaceInfo & fi)
{
  if (skipForBoundary(fi))
    return;

  _face_info = &fi;
  _normal = fi.normal();
  _face_type = fi.faceType(_var.name());

#ifdef MOOSE_GLOBAL_AD_INDEXING
  using namespace Moose::FV;

  const auto elem_face = elemFromFace();
  const auto neighbor_face = neighborFromFace();

  ADReal friction_term_elem = 0;
  ADReal friction_term_neighbor = 0;

  if (_use_Darcy_friction_model)
  {
    friction_term_elem += (*_cL)(elem_face)(_index)*_rho(elem_face) / _eps(elem_face);
    friction_term_neighbor +=
        (*_cL)(neighbor_face)(_index)*_rho(neighbor_face) / _eps(neighbor_face);
  }
  if (_use_Forchheimer_friction_model)
  {
    friction_term_elem += (*_cQ)(elem_face)(_index)*_rho(elem_face) / _eps(elem_face);
    friction_term_neighbor +=
        (*_cQ)(neighbor_face)(_index)*_rho(neighbor_face) / _eps(neighbor_face);
  }

  Point _face_centroid = _face_info->faceCentroid();
  Point _elem_centroid = _face_info->elemCentroid();
  Point _neighbor_centroid = _face_info->neighborCentroid();

  Real geometric_factor = _consistent_scaling * (_neighbor_centroid - _face_centroid).norm() *
                          (_elem_centroid - _face_centroid).norm();

  // Compute the diffusion driven by the velocity gradient
  // Interpolate viscosity divided by porosity on the face
  ADReal diff_face;
  interpolate(Moose::FV::InterpMethod::Average,
              diff_face,
              friction_term_elem * geometric_factor,
              friction_term_neighbor * geometric_factor,
              *_face_info,
              true);

  // Compute face superficial velocity gradient
  auto dudn =
      _var.gradient(Moose::FV::makeCDFace(*_face_info, faceArgSubdomains())) * _face_info->normal();

  if (_face_type == FaceInfo::VarFaceNeighbors::ELEM ||
      _face_type == FaceInfo::VarFaceNeighbors::BOTH)
  {
    const auto dof_number = _face_info->elem().dof_number(_sys.number(), _var.number(), 0);
    // A gradient is a linear combination of degrees of freedom so it's safe to straight-up index
    // into the derivatives vector at the dof we care about
    ADReal ae = dudn.derivatives()[dof_number];
    ae *= -diff_face;
    _rc_uo.addToA(&fi.elem(), _index, ae * (fi.faceArea() * fi.faceCoord()));
  }
  if (_face_type == FaceInfo::VarFaceNeighbors::NEIGHBOR ||
      _face_type == FaceInfo::VarFaceNeighbors::BOTH)
  {
    const auto dof_number = _face_info->neighbor().dof_number(_sys.number(), _var.number(), 0);
    ADReal an = dudn.derivatives()[dof_number];
    an *= diff_face;
    _rc_uo.addToA(fi.neighborPtr(), _index, an * (fi.faceArea() * fi.faceCoord()));
  }

  const auto strong_resid = -diff_face * dudn;

  processResidual(strong_resid * (fi.faceArea() * fi.faceCoord()));
#endif
}
<|endoftext|>


<commit_before>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * Ethereum client.
 */

#include <fstream>
#include <iostream>
#include <clocale>
#include <liblll/Compiler.h>
#include <libdevcore/CommonIO.h>
#include <libdevcore/CommonData.h>
#include <libevmasm/Instruction.h>
using namespace std;
using namespace dev;
using namespace dev::solidity;
using namespace dev::eth;

void help()
{
	cout
		<< "Usage lllc [OPTIONS] <file>" << endl
        << "Options:" << endl
		<< "    -b,--binary  Parse, compile and assemble; output byte code in binary." << endl
		<< "    -x,--hex  Parse, compile and assemble; output byte code in hex." << endl
		<< "    -a,--assembly  Only parse and compile; show assembly." << endl
		<< "    -t,--parse-tree  Only parse; show parse tree." << endl
		<< "    -h,--help  Show this help message and exit." << endl
		<< "    -V,--version  Show the version and exit." << endl;
        exit(0);
}

void version()
{
	cout << "LLLC, the Lovely Little Language Compiler " << endl;
	cout << "  By Gav Wood, (c) 2014." << endl;
	exit(0);
}

/*
The equivalent of setlocale(LC_ALL, "C") is called before any user code is run.
If the user has an invalid environment setting then it is possible for the call
to set locale to fail, so there are only two possible actions, the first is to
throw a runtime exception and cause the program to quit (default behaviour),
or the second is to modify the environment to something sensible (least
surprising behaviour).

The follow code produces the least surprising behaviour. It will use the user
specified default locale if it is valid, and if not then it will modify the
environment the process is running in to use a sensible default. This also means
that users do not need to install language packs for their OS.
*/
void setDefaultOrCLocale()
{
#if __unix__
	if (!std::setlocale(LC_ALL, ""))
	{
		setenv("LC_ALL", "C", 1);
	}
#endif
}

enum Mode { Binary, Hex, Assembly, ParseTree, Disassemble };

int main(int argc, char** argv)
{
	setDefaultOrCLocale();
	unsigned optimise = 1;
	string infile;
	Mode mode = Hex;

	for (int i = 1; i < argc; ++i)
	{
		string arg = argv[i];
		if (arg == "-h" || arg == "--help")
			help();
		else if (arg == "-b" || arg == "--binary")
			mode = Binary;
		else if (arg == "-x" || arg == "--hex")
			mode = Hex;
		else if (arg == "-a" || arg == "--assembly")
			mode = Assembly;
		else if (arg == "-t" || arg == "--parse-tree")
			mode = ParseTree;
		else if ((arg == "-o" || arg == "--optimise") && argc > i + 1)
			optimise = atoi(argv[++i]);
		else if (arg == "-d" || arg == "--disassemble")
			mode = Disassemble;
		else if (arg == "-V" || arg == "--version")
			version();
		else
			infile = argv[i];
	}

	string src;
	if (infile.empty())
	{
		string s;
		while (!cin.eof())
		{
			getline(cin, s);
			src.append(s);
		}
	}
	else
		src = contentsString(infile);

	vector<string> errors;
	if (src.empty())
		errors.push_back("Empty file.");
	else if (mode == Disassemble)
	{
		cout << disassemble(fromHex(src)) << endl;
	}
	else if (mode == Binary || mode == Hex)
	{
		auto bs = compileLLL(src, optimise ? true : false, &errors);
		if (mode == Hex)
			cout << toHex(bs) << endl;
		else if (mode == Binary)
			cout.write((char const*)bs.data(), bs.size());
	}
	else if (mode == ParseTree)
		cout << parseLLL(src) << endl;
	else if (mode == Assembly)
		cout << compileLLLToAsm(src, optimise ? true : false, &errors) << endl;
	for (auto const& i: errors)
		cerr << i << endl;
	if ( errors.size() )
		return 1;
	return 0;
}
<commit_msg>LLL: document optimise flag<commit_after>/*
	This file is part of cpp-ethereum.

	cpp-ethereum is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	cpp-ethereum is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with cpp-ethereum.  If not, see <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
 * @author Gav Wood <i@gavwood.com>
 * @date 2014
 * Ethereum client.
 */

#include <fstream>
#include <iostream>
#include <clocale>
#include <liblll/Compiler.h>
#include <libdevcore/CommonIO.h>
#include <libdevcore/CommonData.h>
#include <libevmasm/Instruction.h>
using namespace std;
using namespace dev;
using namespace dev::solidity;
using namespace dev::eth;

void help()
{
	cout
		<< "Usage lllc [OPTIONS] <file>" << endl
        << "Options:" << endl
		<< "    -b,--binary  Parse, compile and assemble; output byte code in binary." << endl
		<< "    -x,--hex  Parse, compile and assemble; output byte code in hex." << endl
		<< "    -a,--assembly  Only parse and compile; show assembly." << endl
		<< "    -t,--parse-tree  Only parse; show parse tree." << endl
		<< "    -o,--optimise  Turn on/off the optimiser; on by default." << endl
		<< "    -h,--help  Show this help message and exit." << endl
		<< "    -V,--version  Show the version and exit." << endl;
        exit(0);
}

void version()
{
	cout << "LLLC, the Lovely Little Language Compiler " << endl;
	cout << "  By Gav Wood, (c) 2014." << endl;
	exit(0);
}

/*
The equivalent of setlocale(LC_ALL, "C") is called before any user code is run.
If the user has an invalid environment setting then it is possible for the call
to set locale to fail, so there are only two possible actions, the first is to
throw a runtime exception and cause the program to quit (default behaviour),
or the second is to modify the environment to something sensible (least
surprising behaviour).

The follow code produces the least surprising behaviour. It will use the user
specified default locale if it is valid, and if not then it will modify the
environment the process is running in to use a sensible default. This also means
that users do not need to install language packs for their OS.
*/
void setDefaultOrCLocale()
{
#if __unix__
	if (!std::setlocale(LC_ALL, ""))
	{
		setenv("LC_ALL", "C", 1);
	}
#endif
}

enum Mode { Binary, Hex, Assembly, ParseTree, Disassemble };

int main(int argc, char** argv)
{
	setDefaultOrCLocale();
	unsigned optimise = 1;
	string infile;
	Mode mode = Hex;

	for (int i = 1; i < argc; ++i)
	{
		string arg = argv[i];
		if (arg == "-h" || arg == "--help")
			help();
		else if (arg == "-b" || arg == "--binary")
			mode = Binary;
		else if (arg == "-x" || arg == "--hex")
			mode = Hex;
		else if (arg == "-a" || arg == "--assembly")
			mode = Assembly;
		else if (arg == "-t" || arg == "--parse-tree")
			mode = ParseTree;
		else if ((arg == "-o" || arg == "--optimise") && argc > i + 1)
			optimise = atoi(argv[++i]);
		else if (arg == "-d" || arg == "--disassemble")
			mode = Disassemble;
		else if (arg == "-V" || arg == "--version")
			version();
		else
			infile = argv[i];
	}

	string src;
	if (infile.empty())
	{
		string s;
		while (!cin.eof())
		{
			getline(cin, s);
			src.append(s);
		}
	}
	else
		src = contentsString(infile);

	vector<string> errors;
	if (src.empty())
		errors.push_back("Empty file.");
	else if (mode == Disassemble)
	{
		cout << disassemble(fromHex(src)) << endl;
	}
	else if (mode == Binary || mode == Hex)
	{
		auto bs = compileLLL(src, optimise ? true : false, &errors);
		if (mode == Hex)
			cout << toHex(bs) << endl;
		else if (mode == Binary)
			cout.write((char const*)bs.data(), bs.size());
	}
	else if (mode == ParseTree)
		cout << parseLLL(src) << endl;
	else if (mode == Assembly)
		cout << compileLLLToAsm(src, optimise ? true : false, &errors) << endl;
	for (auto const& i: errors)
		cerr << i << endl;
	if ( errors.size() )
		return 1;
	return 0;
}
<|endoftext|>


<commit_before>#include "RdRobotManager.hpp"

//-- This is very important:
rd::RdRobotManager * rd::RdRobotManager::robotManager = NULL;

void rd::RdRobotManager::registerManager(std::string name, rd::RdRobotManager *manager)
{
    if ( robotManagerRegistry.find(name) == robotManagerRegistry.end() )
    {
        robotManagerRegistry[name] = manager;
    }
    else
    {
        RD_ERROR("RdManager with name \"%s\" already exists!\n", name.c_str());
    }
}

std::vector<std::string> rd::RdRobotManager::listAll()
{
    std::vector<std::string> robot_manager_list;

    for( std::map<std::string, RdRobotManager*>::const_iterator it = robotManagerRegistry.begin(); it != robotManagerRegistry.end(); ++it)
    {
        robot_manager_list.push_back(it->first);
    }

    return robot_manager_list;
}

rd::RdRobotManager *rd::RdRobotManager::getRobotManager(std::string name)
{
    if (robotManager == NULL)
    {
        if ( robotManagerRegistry.find(name) != robotManagerRegistry.end() )
        {
            robotManager = robotManagerRegistry[name];
        }
        else
        {
            RD_ERROR("RdRobotManager requested (\"%s\") does not exist.\n", name.c_str());
        }
    }

    return robotManager;
}

bool rd::RdRobotManager::destroyRobotManager()
{
    if (robotManager == NULL)
        return false;

    delete robotManager;
    robotManager = NULL;

    return true;
}

rd::RdRobotManager::~RdRobotManager()
{
    this->onDestroy();
}
<commit_msg>Now it compiles<commit_after>#include "RdRobotManager.hpp"
<|endoftext|>


<commit_before>/*-
 * linux_wire.cc
 *
 * Implementation of Wire for linux, may work on other UN*X systems
 * too...
 */
#include "config.h"

#if !HAVE_LIBPCAP
#include <cstring>
#include <cerrno>

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <net/ethernet.h>

#if 0
/* Including this is incompatible with including linux/if_arp.h */
#include <net/if.h>
#include <netpacket/packet.h>
#else
#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#endif

#include <unistd.h>
#include <sys/types.h>   /* Required for class EUID */

#include "nslu2_upgrade.h"

namespace NSLU2Upgrade {
	/* The basic class implemented to transmit and receive packets over the
	 * wire.
	 */
	class EthernetWire : public Wire {
	public:
		EthernetWire(int s, int hw_index, const unsigned char address[6]) :
			socket(s), broadcast(true) {
			/* Most of these fields aren't used in any given request,
			 * but it does no harm to fill them all correctly.
			 */
			nslu2To.sll_family = AF_PACKET;
			nslu2To.sll_protocol = NSLU2Protocol::UpgradeProtocol;
			nslu2To.sll_ifindex = hw_index;
			nslu2To.sll_hatype = ARPHRD_IEEE802;
			nslu2To.sll_pkttype = address ? PACKET_HOST : PACKET_BROADCAST;
			nslu2To.sll_halen = 6;
			/* The 255 gives the ethernet hardware broadcast address,
			 * overwrite this if a host address is provided.
			 */
			std::memset(nslu2To.sll_addr, 255, sizeof nslu2To.sll_addr);
			if (address) {
				broadcast = false;
				std::memcpy(nslu2To.sll_addr, address, 6);
			}

			/* This is set just in case of a call to LastAddress before
			 * Receive has succeeded - the result will be all 0's
			 */
			std::memset(nslu2From.sll_addr, 0, sizeof nslu2From.sll_addr);
		}

		virtual ~EthernetWire() {
			(void)close(socket);
		}

		/* Throws SendError on a fatal error. */
		virtual void Send(const void *packet, size_t length) {
			/* Set no flags (0) - we block on the sendto if
			 * required, the socket is *not* set O_NONBLOCK.
			 */
			while (sendto(socket, packet, length, 0,
					reinterpret_cast<sockaddr*>(&nslu2To),
					sizeof nslu2To) == (-1)) {
				if (errno != EINTR)
					throw SendError(errno);
			}
		}

		/* Receive throws ReceiveError on a fatal error and must update
		 * size with the received packet size.  0 must be used to
		 * indicate failure to receive a packet (and this must not
		 * be fatal).  If timeout is greater than 0 the implementation
		 * should wait that number of microseconds until a packet is
		 * received or the timeout has expired (in which case a size
		 * of 0 must be returned).
		 */
		virtual void Receive(void *buffer, size_t &size, unsigned long timeout) {
			/* The socket is blocking (O_NONBLOCK is not set) therefore
			 * handle the 'block' option by polling.  Even if 'block'
			 * is true this call must not actually block - just
			 * time out - because the response packet we are waiting
			 * for may actually have been dropped.
			 */
			do {
				fd_set readfds;
				FD_ZERO(&readfds);
				FD_SET(socket, &readfds);

				/* Timeout as requested by the caller. */
				struct timeval tv;
				tv.tv_sec = timeout >> 20;
				tv.tv_usec = timeout & 0xfffff;
				if (tv.tv_usec >= 1000000)
					++tv.tv_sec, tv.tv_usec = 0;

				/* See if there is anything to read... */
				do {
					int fds(select(socket+1, &readfds, 0, 0, &tv));
					if (fds == 0) {
						size = 0;
						return;
					}
					if (fds != (-1))
						break;
					if (errno != EINTR)
						throw ReceiveError(errno);
				} while (1);

				/* There is something to read... */
				socklen_t resultSize(sizeof nslu2From);
				ssize_t result(recvfrom(socket, buffer, size, 0,
						reinterpret_cast<sockaddr*>(&nslu2From),
						&resultSize));
				if (result == (-1)) {
					if (errno != EINTR)
						throw ReceiveError(errno);
				} else if (broadcast || std::memcmp(nslu2To.sll_addr,
							nslu2From.sll_addr, 6) == 0) {
					/* otherwise this is not a packet for this
					 * program and it is just ignored.
					 */
					size = result;
					return;
				}
			} while (1);
		}

		/* Return the address of the last received packet.  This is
		 * an NSLU2 so the address is a 6 byte Ethernet hardware
		 * address.
		 */
		virtual void LastAddress(unsigned char address[6]) {
			std::memcpy(address, nslu2From.sll_addr, 6);
		}

	private:
		struct sockaddr_ll nslu2To;
		struct sockaddr_ll nslu2From;
		int                socket;
		bool               broadcast;
	};

	/* Class to set and reset the user id to the effective uid. */
	/* Requires unistd.h and sys/types.h */
	class EUID {
	public:
		EUID(int uid) : euid(::geteuid()) {
			if (uid != -1 && ::seteuid(uid) != 0)
				throw WireError(errno);
		}

		~EUID() {
			::seteuid(euid);
		}

	private:
		::uid_t euid;
	};

};

/* Make a new wire, which may be deleted with delete.  The
 * address should be a value (null terminated this time) returned
 * by LastAddress, if NULL the Wire will broadcast.  'device'
 * is the hardware device name to use - the value of the
 * --device parameter on the command line (if given).  If not
 *  given (NULL) a potentially useless default will be used.
 */
NSLU2Upgrade::Wire *NSLU2Upgrade::Wire::MakeWire(const char *device,
		const unsigned char *address, int uid) {
	int packet_socket;
	struct ifreq device_interface;

		{
		EUID euid(uid);
		/* Obtain a datagram low level socket using the 'invented' NSLU2
		 * protocol number.  Change to the effective user id to do
		 * this (if given).
		 */
		packet_socket = socket(PF_PACKET, SOCK_DGRAM, NSLU2Protocol::UpgradeProtocol);
		if (packet_socket == (-1))
			throw WireError(errno);

		/* Check the device name.  If not given use 'eth0'. */
		if (device == NULL)
			device = "eth0";

		/* We are using a level which requires a hardware specific address,
		 * that's because the NSLU2 doesn't (for reasons which are far from
		 * obvious) implement a standard protocol for the upgrade, therefore
		 * there is no standard way of addressing the NSLU2.  Instead we must
		 * use the hardware, which on the NSLU2 is Ethernet, and which therefore
		 * has a 6 byte 'name'.
		 *
		 * What this means is that we need to be talking on an ethernet device;
		 * there ain't no way of getting a random ethernet packet onto some
		 * other network, because there is no way of mapping the address (which
		 * is an ethernet hardware id) into an appropriate address on another
		 * network.  (NOTE: 'tunnelling' stuff does this, it wraps the whole
		 * packet up inside another packet and sends it down the tunnel, it gets
		 * unwrapped at the other end, but that is transparent to this code.)
		 *
		 * At this point we need an ethernet device to talk to.  Notice that this
		 * could, in theory, be a fake device - just so long as the NSLU2 has a
		 * six byte ethernet address to talk back to.  We look the given device
		 * name up on the socket.  (See netdevice(7) - this is linux specific)
		 *
		 * NOTE: if you are looking at this code and trying to port it the device
		 * stuff may be irrelevant, what you need to do is receive all packets
		 * with the protocol 0x8888 (NSLU2Protocol::UpgradeProtocol) from any
		 * *ethernet* MAC to implement the broadcast stuff and from a specific
		 * ethernet MAC to implement upgrade.  The broadcast stuff isn't necessary
		 * to implement a working upslug2 - because the ethernet MAC can be
		 * determined from the label on the bottom of an NSLU2, so the user can
		 * just be obliged to turn the damn box over.  And this is a better GUI.
		 */
		strncpy(device_interface.ifr_name, device, sizeof device_interface.ifr_name);
		device_interface.ifr_name[(sizeof device_interface.ifr_name)-1] = 0;

		if (ioctl(packet_socket, SIOCGIFINDEX, &device_interface) == (-1)) {
			/* This means the device name is bogus, because if we weren't
			 * euid 0 the socket call would have EACCESed above.
			 */
			const int err(errno);
			(void)close(packet_socket);
			throw WireError(err);
		}
	}

	/* This is enough to make a new wire. */
	return new EthernetWire(packet_socket, device_interface.ifr_ifindex, address);
}
#endif
<commit_msg>Fix the use of linux specific header files - not necessary and doesn't work with later versions of glibc.<commit_after>/*-
 * linux_wire.cc
 *
 * Implementation of Wire for linux, may work on other UN*X systems
 * too...
 */
#include "config.h"

#if !HAVE_LIBPCAP
#include <cstring>
#include <cerrno>

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/select.h>

#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_arp.h>

#include <netpacket/packet.h>

#include <unistd.h>
#include <sys/types.h>   /* Required for class EUID */

#include "nslu2_upgrade.h"

namespace NSLU2Upgrade {
	/* The basic class implemented to transmit and receive packets over the
	 * wire.
	 */
	class EthernetWire : public Wire {
	public:
		EthernetWire(int s, int hw_index, const unsigned char address[6]) :
			socket(s), broadcast(true) {
			/* Most of these fields aren't used in any given request,
			 * but it does no harm to fill them all correctly.
			 */
			nslu2To.sll_family = AF_PACKET;
			nslu2To.sll_protocol = NSLU2Protocol::UpgradeProtocol;
			nslu2To.sll_ifindex = hw_index;
			nslu2To.sll_hatype = ARPHRD_IEEE802;
			nslu2To.sll_pkttype = address ? PACKET_HOST : PACKET_BROADCAST;
			nslu2To.sll_halen = 6;
			/* The 255 gives the ethernet hardware broadcast address,
			 * overwrite this if a host address is provided.
			 */
			std::memset(nslu2To.sll_addr, 255, sizeof nslu2To.sll_addr);
			if (address) {
				broadcast = false;
				std::memcpy(nslu2To.sll_addr, address, 6);
			}

			/* This is set just in case of a call to LastAddress before
			 * Receive has succeeded - the result will be all 0's
			 */
			std::memset(nslu2From.sll_addr, 0, sizeof nslu2From.sll_addr);
		}

		virtual ~EthernetWire() {
			(void)close(socket);
		}

		/* Throws SendError on a fatal error. */
		virtual void Send(const void *packet, size_t length) {
			/* Set no flags (0) - we block on the sendto if
			 * required, the socket is *not* set O_NONBLOCK.
			 */
			while (sendto(socket, packet, length, 0,
					reinterpret_cast<sockaddr*>(&nslu2To),
					sizeof nslu2To) == (-1)) {
				if (errno != EINTR)
					throw SendError(errno);
			}
		}

		/* Receive throws ReceiveError on a fatal error and must update
		 * size with the received packet size.  0 must be used to
		 * indicate failure to receive a packet (and this must not
		 * be fatal).  If timeout is greater than 0 the implementation
		 * should wait that number of microseconds until a packet is
		 * received or the timeout has expired (in which case a size
		 * of 0 must be returned).
		 */
		virtual void Receive(void *buffer, size_t &size, unsigned long timeout) {
			/* The socket is blocking (O_NONBLOCK is not set) therefore
			 * handle the 'block' option by polling.  Even if 'block'
			 * is true this call must not actually block - just
			 * time out - because the response packet we are waiting
			 * for may actually have been dropped.
			 */
			do {
				fd_set readfds;
				FD_ZERO(&readfds);
				FD_SET(socket, &readfds);

				/* Timeout as requested by the caller. */
				struct timeval tv;
				tv.tv_sec = timeout >> 20;
				tv.tv_usec = timeout & 0xfffff;
				if (tv.tv_usec >= 1000000)
					++tv.tv_sec, tv.tv_usec = 0;

				/* See if there is anything to read... */
				do {
					int fds(select(socket+1, &readfds, 0, 0, &tv));
					if (fds == 0) {
						size = 0;
						return;
					}
					if (fds != (-1))
						break;
					if (errno != EINTR)
						throw ReceiveError(errno);
				} while (1);

				/* There is something to read... */
				socklen_t resultSize(sizeof nslu2From);
				ssize_t result(recvfrom(socket, buffer, size, 0,
						reinterpret_cast<sockaddr*>(&nslu2From),
						&resultSize));
				if (result == (-1)) {
					if (errno != EINTR)
						throw ReceiveError(errno);
				} else if (broadcast || std::memcmp(nslu2To.sll_addr,
							nslu2From.sll_addr, 6) == 0) {
					/* otherwise this is not a packet for this
					 * program and it is just ignored.
					 */
					size = result;
					return;
				}
			} while (1);
		}

		/* Return the address of the last received packet.  This is
		 * an NSLU2 so the address is a 6 byte Ethernet hardware
		 * address.
		 */
		virtual void LastAddress(unsigned char address[6]) {
			std::memcpy(address, nslu2From.sll_addr, 6);
		}

	private:
		struct sockaddr_ll nslu2To;
		struct sockaddr_ll nslu2From;
		int                socket;
		bool               broadcast;
	};

	/* Class to set and reset the user id to the effective uid. */
	/* Requires unistd.h and sys/types.h */
	class EUID {
	public:
		EUID(int uid) : euid(::geteuid()) {
			if (uid != -1 && ::seteuid(uid) != 0)
				throw WireError(errno);
		}

		~EUID() {
			::seteuid(euid);
		}

	private:
		::uid_t euid;
	};

};

/* Make a new wire, which may be deleted with delete.  The
 * address should be a value (null terminated this time) returned
 * by LastAddress, if NULL the Wire will broadcast.  'device'
 * is the hardware device name to use - the value of the
 * --device parameter on the command line (if given).  If not
 *  given (NULL) a potentially useless default will be used.
 */
NSLU2Upgrade::Wire *NSLU2Upgrade::Wire::MakeWire(const char *device,
		const unsigned char *address, int uid) {
	int packet_socket;
	struct ifreq device_interface;

		{
		EUID euid(uid);
		/* Obtain a datagram low level socket using the 'invented' NSLU2
		 * protocol number.  Change to the effective user id to do
		 * this (if given).
		 */
		packet_socket = socket(PF_PACKET, SOCK_DGRAM, NSLU2Protocol::UpgradeProtocol);
		if (packet_socket == (-1))
			throw WireError(errno);

		/* Check the device name.  If not given use 'eth0'. */
		if (device == NULL)
			device = "eth0";

		/* We are using a level which requires a hardware specific address,
		 * that's because the NSLU2 doesn't (for reasons which are far from
		 * obvious) implement a standard protocol for the upgrade, therefore
		 * there is no standard way of addressing the NSLU2.  Instead we must
		 * use the hardware, which on the NSLU2 is Ethernet, and which therefore
		 * has a 6 byte 'name'.
		 *
		 * What this means is that we need to be talking on an ethernet device;
		 * there ain't no way of getting a random ethernet packet onto some
		 * other network, because there is no way of mapping the address (which
		 * is an ethernet hardware id) into an appropriate address on another
		 * network.  (NOTE: 'tunnelling' stuff does this, it wraps the whole
		 * packet up inside another packet and sends it down the tunnel, it gets
		 * unwrapped at the other end, but that is transparent to this code.)
		 *
		 * At this point we need an ethernet device to talk to.  Notice that this
		 * could, in theory, be a fake device - just so long as the NSLU2 has a
		 * six byte ethernet address to talk back to.  We look the given device
		 * name up on the socket.  (See netdevice(7) - this is linux specific)
		 *
		 * NOTE: if you are looking at this code and trying to port it the device
		 * stuff may be irrelevant, what you need to do is receive all packets
		 * with the protocol 0x8888 (NSLU2Protocol::UpgradeProtocol) from any
		 * *ethernet* MAC to implement the broadcast stuff and from a specific
		 * ethernet MAC to implement upgrade.  The broadcast stuff isn't necessary
		 * to implement a working upslug2 - because the ethernet MAC can be
		 * determined from the label on the bottom of an NSLU2, so the user can
		 * just be obliged to turn the damn box over.  And this is a better GUI.
		 */
		strncpy(device_interface.ifr_name, device, sizeof device_interface.ifr_name);
		device_interface.ifr_name[(sizeof device_interface.ifr_name)-1] = 0;

		if (ioctl(packet_socket, SIOCGIFINDEX, &device_interface) == (-1)) {
			/* This means the device name is bogus, because if we weren't
			 * euid 0 the socket call would have EACCESed above.
			 */
			const int err(errno);
			(void)close(packet_socket);
			throw WireError(err);
		}
	}

	/* This is enough to make a new wire. */
	return new EthernetWire(packet_socket, device_interface.ifr_ifindex, address);
}
#endif
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "baseenginedebugclient.h"
#include "qmldebugconstants.h"

namespace QmlDebug {

struct QmlObjectData {
    QUrl url;
    int lineNumber;
    int columnNumber;
    QString idString;
    QString objectName;
    QString objectType;
    int objectId;
    int contextId;
};

QDataStream &operator>>(QDataStream &ds, QmlObjectData &data)
{
    ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
       >> data.objectName >> data.objectType >> data.objectId >> data.contextId;
    return ds;
}

struct QmlObjectProperty {
    enum Type { Unknown, Basic, Object, List, SignalProperty };
    Type type;
    QString name;
    QVariant value;
    QString valueTypeName;
    QString binding;
    bool hasNotifySignal;
};

QDataStream &operator>>(QDataStream &ds, QmlObjectProperty &data)
{
    int type;
    ds >> type >> data.name >> data.value >> data.valueTypeName
       >> data.binding >> data.hasNotifySignal;
    data.type = (QmlObjectProperty::Type)type;
    return ds;
}

void BaseEngineDebugClient::decode(QDataStream &ds,
                                   QmlDebugObjectReference &o,
                                   bool simple)
{
    QmlObjectData data;
    ds >> data;
    int parentId = -1;
    if (objectName() == QLatin1String("QmlDebugger") &&
            serviceVersion() >= Constants::CURRENT_SUPPORTED_VERSION )
        ds >> parentId;
    o.m_debugId = data.objectId;
    o.m_className = data.objectType;
    o.m_idString = data.idString;
    o.m_name = data.objectName;
    o.m_source.m_url = data.url;
    o.m_source.m_lineNumber = data.lineNumber;
    o.m_source.m_columnNumber = data.columnNumber;
    o.m_contextDebugId = data.contextId;
    o.m_needsMoreData = simple;
    o.m_parentId = parentId;

    if (simple)
        return;

    int childCount;
    bool recur;
    ds >> childCount >> recur;

    for (int ii = 0; ii < childCount; ++ii) {
        o.m_children.append(QmlDebugObjectReference());
        decode(ds, o.m_children.last(), !recur);
    }

    int propCount;
    ds >> propCount;

    for (int ii = 0; ii < propCount; ++ii) {
        QmlObjectProperty data;
        ds >> data;
        QmlDebugPropertyReference prop;
        prop.m_objectDebugId = o.m_debugId;
        prop.m_name = data.name;
        prop.m_binding = data.binding;
        prop.m_hasNotifySignal = data.hasNotifySignal;
        prop.m_valueTypeName = data.valueTypeName;
        switch (data.type) {
        case QmlObjectProperty::Basic:
        case QmlObjectProperty::List:
        case QmlObjectProperty::SignalProperty:
        {
            prop.m_value = data.value;
            break;
        }
        case QmlObjectProperty::Object:
        {
            QmlDebugObjectReference obj;
            obj.m_debugId = prop.m_value.toInt();
            prop.m_value = qVariantFromValue(obj);
            break;
        }
        case QmlObjectProperty::Unknown:
            break;
        }
        o.m_properties << prop;
    }
}

void BaseEngineDebugClient::decode(QDataStream &ds,
                                   QmlDebugContextReference &c)
{
    ds >> c.m_name >> c.m_debugId;

    int contextCount;
    ds >> contextCount;

    for (int ii = 0; ii < contextCount; ++ii) {
        c.m_contexts.append(QmlDebugContextReference());
        decode(ds, c.m_contexts.last());
    }

    int objectCount;
    ds >> objectCount;

    for (int ii = 0; ii < objectCount; ++ii) {
        QmlDebugObjectReference obj;
        decode(ds, obj, true);
        obj.m_contextDebugId = c.m_debugId;
        c.m_objects << obj;
    }
}

void BaseEngineDebugClient::statusChanged(Status status)
{
    emit newStatus(status);
}

void BaseEngineDebugClient::messageReceived(const QByteArray &data)
{
    QDataStream ds(data);
    int queryId;
    QByteArray type;
    ds >> type;

    if (type == "OBJECT_CREATED") {
        emit newObjects();
        return;
    }

    ds >> queryId;

    if (type == "LIST_ENGINES_R") {
        int count;
        ds >> count;
        QmlDebugEngineReferenceList engines;
        for (int ii = 0; ii < count; ++ii) {
            QmlDebugEngineReference eng;
            ds >> eng.m_name;
            ds >> eng.m_debugId;
            engines << eng;
        }
        emit result(queryId, QVariant::fromValue(engines), type);
    } else if (type == "LIST_OBJECTS_R") {
        QmlDebugContextReference rootContext;
        if (!ds.atEnd())
            decode(ds, rootContext);
        emit result(queryId, QVariant::fromValue(rootContext), type);
    } else if (type == "FETCH_OBJECT_R") {
        QmlDebugObjectReference object;
        if (!ds.atEnd())
            decode(ds, object, false);
        emit result(queryId, QVariant::fromValue(object), type);
    } else if (type == "EVAL_EXPRESSION_R") {;
        QVariant exprResult;
        ds >> exprResult;
        emit result(queryId, exprResult, type);
    } else if (type == "WATCH_PROPERTY_R" ||
               type == "WATCH_OBJECT_R" ||
               type == "WATCH_EXPR_OBJECT_R") {
        bool valid;
        ds >> valid;
        emit result(queryId, valid, type);
    } else if (type == "UPDATE_WATCH") {
        int debugId;
        QByteArray name;
        QVariant value;
        ds >> debugId >> name >> value;
        emit valueChanged(debugId, name, value);
    }
}

BaseEngineDebugClient::BaseEngineDebugClient(const QString &clientName,
                     QmlDebugConnection *conn)
    : QmlDebugClient(clientName, conn),
      m_nextId(1)
{
    setObjectName(clientName);
}

quint32 BaseEngineDebugClient::addWatch(const QmlDebugPropertyReference &property)
{
    quint32 id;
    if (status() == QmlDebugClient::Enabled) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("WATCH_PROPERTY") << id << property.m_objectDebugId
           << property.m_name.toUtf8();
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::addWatch(const QmlDebugContextReference &/*context*/,
                                       const QString &/*id*/)
{
    qWarning("QmlEngineDebugClient::addWatch(): Not implemented");
    return 0;
}

quint32 BaseEngineDebugClient::addWatch(const QmlDebugObjectReference &object,
                                       const QString &expr)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("WATCH_EXPR_OBJECT") << id << object.m_debugId << expr;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::addWatch(const QmlDebugObjectReference &object)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("WATCH_OBJECT") << id << object.m_debugId;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::addWatch(const QmlDebugFileReference &/*file*/)
{
    qWarning("QmlEngineDebugClient::addWatch(): Not implemented");
    return 0;
}

void BaseEngineDebugClient::removeWatch(quint32 id)
{
    if (status() == QmlDebugClient::Enabled) {
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("NO_WATCH") << id;
        sendMessage(message);
    }
}

quint32 BaseEngineDebugClient::queryAvailableEngines()
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("LIST_ENGINES") << id;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::queryRootContexts(const QmlDebugEngineReference &engine)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && engine.m_debugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("LIST_OBJECTS") << id << engine.m_debugId;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::queryObject(const QmlDebugObjectReference &object)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && object.m_debugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("FETCH_OBJECT") << id << object.m_debugId << false <<
              true;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::queryObjectRecursive(const QmlDebugObjectReference &object)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && object.m_debugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("FETCH_OBJECT") << id << object.m_debugId << true <<
              true;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::queryExpressionResult(int objectDebugId,
                                                     const QString &expr,
                                                     int engineId)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && objectDebugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr
           << engineId;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::setBindingForObject(
        int objectDebugId,
        const QString &propertyName,
        const QVariant &bindingExpression,
        bool isLiteralValue,
        QString source, int line)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && objectDebugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("SET_BINDING") << objectDebugId << propertyName
           << bindingExpression << isLiteralValue << source << line;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::resetBindingForObject(
        int objectDebugId,
        const QString &propertyName)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && objectDebugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("RESET_BINDING") << objectDebugId << propertyName;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::setMethodBody(
        int objectDebugId, const QString &methodName,
        const QString &methodBody)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && objectDebugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("SET_METHOD_BODY") << objectDebugId
           << methodName << methodBody;
        sendMessage(message);
    }
    return id;
}

} // namespace QmlDebug
<commit_msg>QmlDebug: Fix warning about unitialized variable<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "baseenginedebugclient.h"
#include "qmldebugconstants.h"

namespace QmlDebug {

struct QmlObjectData {
    QUrl url;
    int lineNumber;
    int columnNumber;
    QString idString;
    QString objectName;
    QString objectType;
    int objectId;
    int contextId;
};

QDataStream &operator>>(QDataStream &ds, QmlObjectData &data)
{
    ds >> data.url >> data.lineNumber >> data.columnNumber >> data.idString
       >> data.objectName >> data.objectType >> data.objectId >> data.contextId;
    return ds;
}

struct QmlObjectProperty {
    enum Type { Unknown, Basic, Object, List, SignalProperty };
    Type type;
    QString name;
    QVariant value;
    QString valueTypeName;
    QString binding;
    bool hasNotifySignal;
};

QDataStream &operator>>(QDataStream &ds, QmlObjectProperty &data)
{
    int type;
    ds >> type >> data.name >> data.value >> data.valueTypeName
       >> data.binding >> data.hasNotifySignal;
    data.type = (QmlObjectProperty::Type)type;
    return ds;
}

void BaseEngineDebugClient::decode(QDataStream &ds,
                                   QmlDebugObjectReference &o,
                                   bool simple)
{
    QmlObjectData data;
    ds >> data;
    int parentId = -1;
    if (objectName() == QLatin1String("QmlDebugger") &&
            serviceVersion() >= Constants::CURRENT_SUPPORTED_VERSION )
        ds >> parentId;
    o.m_debugId = data.objectId;
    o.m_className = data.objectType;
    o.m_idString = data.idString;
    o.m_name = data.objectName;
    o.m_source.m_url = data.url;
    o.m_source.m_lineNumber = data.lineNumber;
    o.m_source.m_columnNumber = data.columnNumber;
    o.m_contextDebugId = data.contextId;
    o.m_needsMoreData = simple;
    o.m_parentId = parentId;

    if (simple)
        return;

    int childCount;
    bool recur;
    ds >> childCount >> recur;

    for (int ii = 0; ii < childCount; ++ii) {
        o.m_children.append(QmlDebugObjectReference());
        decode(ds, o.m_children.last(), !recur);
    }

    int propCount;
    ds >> propCount;

    for (int ii = 0; ii < propCount; ++ii) {
        QmlObjectProperty data;
        ds >> data;
        QmlDebugPropertyReference prop;
        prop.m_objectDebugId = o.m_debugId;
        prop.m_name = data.name;
        prop.m_binding = data.binding;
        prop.m_hasNotifySignal = data.hasNotifySignal;
        prop.m_valueTypeName = data.valueTypeName;
        switch (data.type) {
        case QmlObjectProperty::Basic:
        case QmlObjectProperty::List:
        case QmlObjectProperty::SignalProperty:
        {
            prop.m_value = data.value;
            break;
        }
        case QmlObjectProperty::Object:
        {
            QmlDebugObjectReference obj;
            obj.m_debugId = prop.m_value.toInt();
            prop.m_value = qVariantFromValue(obj);
            break;
        }
        case QmlObjectProperty::Unknown:
            break;
        }
        o.m_properties << prop;
    }
}

void BaseEngineDebugClient::decode(QDataStream &ds,
                                   QmlDebugContextReference &c)
{
    ds >> c.m_name >> c.m_debugId;

    int contextCount;
    ds >> contextCount;

    for (int ii = 0; ii < contextCount; ++ii) {
        c.m_contexts.append(QmlDebugContextReference());
        decode(ds, c.m_contexts.last());
    }

    int objectCount;
    ds >> objectCount;

    for (int ii = 0; ii < objectCount; ++ii) {
        QmlDebugObjectReference obj;
        decode(ds, obj, true);
        obj.m_contextDebugId = c.m_debugId;
        c.m_objects << obj;
    }
}

void BaseEngineDebugClient::statusChanged(Status status)
{
    emit newStatus(status);
}

void BaseEngineDebugClient::messageReceived(const QByteArray &data)
{
    QDataStream ds(data);
    int queryId;
    QByteArray type;
    ds >> type;

    if (type == "OBJECT_CREATED") {
        emit newObjects();
        return;
    }

    ds >> queryId;

    if (type == "LIST_ENGINES_R") {
        int count;
        ds >> count;
        QmlDebugEngineReferenceList engines;
        for (int ii = 0; ii < count; ++ii) {
            QmlDebugEngineReference eng;
            ds >> eng.m_name;
            ds >> eng.m_debugId;
            engines << eng;
        }
        emit result(queryId, QVariant::fromValue(engines), type);
    } else if (type == "LIST_OBJECTS_R") {
        QmlDebugContextReference rootContext;
        if (!ds.atEnd())
            decode(ds, rootContext);
        emit result(queryId, QVariant::fromValue(rootContext), type);
    } else if (type == "FETCH_OBJECT_R") {
        QmlDebugObjectReference object;
        if (!ds.atEnd())
            decode(ds, object, false);
        emit result(queryId, QVariant::fromValue(object), type);
    } else if (type == "EVAL_EXPRESSION_R") {;
        QVariant exprResult;
        ds >> exprResult;
        emit result(queryId, exprResult, type);
    } else if (type == "WATCH_PROPERTY_R" ||
               type == "WATCH_OBJECT_R" ||
               type == "WATCH_EXPR_OBJECT_R") {
        bool valid;
        ds >> valid;
        emit result(queryId, valid, type);
    } else if (type == "UPDATE_WATCH") {
        int debugId;
        QByteArray name;
        QVariant value;
        ds >> debugId >> name >> value;
        emit valueChanged(debugId, name, value);
    }
}

BaseEngineDebugClient::BaseEngineDebugClient(const QString &clientName,
                     QmlDebugConnection *conn)
    : QmlDebugClient(clientName, conn),
      m_nextId(1)
{
    setObjectName(clientName);
}

quint32 BaseEngineDebugClient::addWatch(const QmlDebugPropertyReference &property)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("WATCH_PROPERTY") << id << property.m_objectDebugId
           << property.m_name.toUtf8();
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::addWatch(const QmlDebugContextReference &/*context*/,
                                       const QString &/*id*/)
{
    qWarning("QmlEngineDebugClient::addWatch(): Not implemented");
    return 0;
}

quint32 BaseEngineDebugClient::addWatch(const QmlDebugObjectReference &object,
                                       const QString &expr)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("WATCH_EXPR_OBJECT") << id << object.m_debugId << expr;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::addWatch(const QmlDebugObjectReference &object)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("WATCH_OBJECT") << id << object.m_debugId;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::addWatch(const QmlDebugFileReference &/*file*/)
{
    qWarning("QmlEngineDebugClient::addWatch(): Not implemented");
    return 0;
}

void BaseEngineDebugClient::removeWatch(quint32 id)
{
    if (status() == QmlDebugClient::Enabled) {
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("NO_WATCH") << id;
        sendMessage(message);
    }
}

quint32 BaseEngineDebugClient::queryAvailableEngines()
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("LIST_ENGINES") << id;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::queryRootContexts(const QmlDebugEngineReference &engine)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && engine.m_debugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("LIST_OBJECTS") << id << engine.m_debugId;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::queryObject(const QmlDebugObjectReference &object)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && object.m_debugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("FETCH_OBJECT") << id << object.m_debugId << false <<
              true;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::queryObjectRecursive(const QmlDebugObjectReference &object)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && object.m_debugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("FETCH_OBJECT") << id << object.m_debugId << true <<
              true;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::queryExpressionResult(int objectDebugId,
                                                     const QString &expr,
                                                     int engineId)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && objectDebugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("EVAL_EXPRESSION") << id << objectDebugId << expr
           << engineId;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::setBindingForObject(
        int objectDebugId,
        const QString &propertyName,
        const QVariant &bindingExpression,
        bool isLiteralValue,
        QString source, int line)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && objectDebugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("SET_BINDING") << objectDebugId << propertyName
           << bindingExpression << isLiteralValue << source << line;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::resetBindingForObject(
        int objectDebugId,
        const QString &propertyName)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && objectDebugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("RESET_BINDING") << objectDebugId << propertyName;
        sendMessage(message);
    }
    return id;
}

quint32 BaseEngineDebugClient::setMethodBody(
        int objectDebugId, const QString &methodName,
        const QString &methodBody)
{
    quint32 id = 0;
    if (status() == QmlDebugClient::Enabled && objectDebugId != -1) {
        id = getId();
        QByteArray message;
        QDataStream ds(&message, QIODevice::WriteOnly);
        ds << QByteArray("SET_METHOD_BODY") << objectDebugId
           << methodName << methodBody;
        sendMessage(message);
    }
    return id;
}

} // namespace QmlDebug
<|endoftext|>


<commit_before>//! \file
/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the BSD License.
*/

#ifndef TRITON_SYMBOLICVARIABLE_H
#define TRITON_SYMBOLICVARIABLE_H

#include <string>

#include "symbolicEnums.hpp"
#include "tritonTypes.hpp"

//! The Triton namespace
namespace triton {
/*!
 *  \addtogroup triton
 *  @{
 */

  //! The Engines namespace
  namespace engines {
  /*!
   *  \ingroup triton
   *  \addtogroup engines
   *  @{
   */

    //! The Symbolic Execution namespace
    namespace symbolic {
    /*!
     *  \ingroup engines
     *  \addtogroup symbolic
     *  @{
     */

      /*! \class SymbolicVariable
          \brief The symbolic variable class. */
      class SymbolicVariable {

        protected:

          //! The symbolic variable kind. \sa triton::engines::symbolic::symkind_e
          symkind_e kind;

          //! The comment of the symbolic variable.
          std::string comment;

          //! The name of the symbolic variable. \sa TRITON_SYMVAR_NAME
          std::string name;

          //! The id of the symbolic variable. This id is unique.
          triton::usize id;

          //! The kind value of the symbolic variable.
          /*!
            \brief If the symbolic varialbe is a triton::engines::symbolic::REG, this value contains the register ID.
            \biref If the symbolic varialbe is a triton::engines::symbolic::MEM, this value contains the memory access' address.
          */
          triton::uint64 kindValue;

          //! The size (in bits) of the symbolic variable.
          triton::uint32 size;

          //! The concrete value of the symbolic variable.
          triton::uint512 concreteValue;

        public:

          //! Constructor.
          SymbolicVariable(symkind_e kind, triton::uint64 kindValue, triton::usize id, triton::uint32 size, const std::string& comment, triton::uint512 concreteValue=0);

          //! Constructor by copy.
          SymbolicVariable(const SymbolicVariable &copy);

          //! Destructore.
          ~SymbolicVariable();

          //! Returns the symbolic variable kind. \sa triton::engines::symbolic::symkind_e.
          symkind_e getKind(void) const;

          //! Returns the comment of the symbolic variable.
          const std::string& getComment(void) const;

          //! Returns the name of the symbolic variable.
          const std::string& getName(void) const;

          //! Returns the id of the symbolic variable. This id is unique.
          triton::usize getId(void) const;

          //! Returns the kind value of the symbolic variable.
          triton::uint64 getKindValue(void) const;

          //! Returns the size (in bits) of the symbolic variable.
          triton::uint32 getSize(void) const;

          //! Returns the concrete value (if exists) of the symbolic variable.
          triton::uint512 getConcreteValue(void) const;

          //! Sets the comment of the symbolic variable.
          void setComment(const std::string& comment);

          //! Sets the concrete value of the symbolic variable.
          void setConcreteValue(triton::uint512 value);
      };

      //! Displays a symbolic variable.
      std::ostream& operator<<(std::ostream& stream, const SymbolicVariable& symVar);

      //! Displays a symbolic variable.
      std::ostream& operator<<(std::ostream& stream, const SymbolicVariable* symVar);

    /*! @} End of symbolic namespace */
    };
  /*! @} End of engines namespace */
  };
/*! @} End of triton namespace */
};

#endif /* TRITON_SYMBOLICVARIABLE_H */

<commit_msg>Update doxygen<commit_after>//! \file
/*
**  Copyright (C) - Triton
**
**  This program is under the terms of the BSD License.
*/

#ifndef TRITON_SYMBOLICVARIABLE_H
#define TRITON_SYMBOLICVARIABLE_H

#include <string>

#include "symbolicEnums.hpp"
#include "tritonTypes.hpp"

//! The Triton namespace
namespace triton {
/*!
 *  \addtogroup triton
 *  @{
 */

  //! The Engines namespace
  namespace engines {
  /*!
   *  \ingroup triton
   *  \addtogroup engines
   *  @{
   */

    //! The Symbolic Execution namespace
    namespace symbolic {
    /*!
     *  \ingroup engines
     *  \addtogroup symbolic
     *  @{
     */

      /*! \class SymbolicVariable
          \brief The symbolic variable class. */
      class SymbolicVariable {

        protected:

          //! The symbolic variable kind. \sa triton::engines::symbolic::symkind_e
          symkind_e kind;

          //! The comment of the symbolic variable.
          std::string comment;

          //! The name of the symbolic variable. \sa TRITON_SYMVAR_NAME
          std::string name;

          //! The id of the symbolic variable. This id is unique.
          triton::usize id;

          /*! \brief The kind value of the symbolic variable.
           *
           * \description If the symbolic varialbe is a triton::engines::symbolic::REG, this value contains the register ID.
           * Otherwise, if the symbolic varialbe is a triton::engines::symbolic::MEM, this value contains the address of the
           * memory access.
           */
          triton::uint64 kindValue;

          //! The size (in bits) of the symbolic variable.
          triton::uint32 size;

          //! The concrete value of the symbolic variable.
          triton::uint512 concreteValue;

        public:

          //! Constructor.
          SymbolicVariable(symkind_e kind, triton::uint64 kindValue, triton::usize id, triton::uint32 size, const std::string& comment, triton::uint512 concreteValue=0);

          //! Constructor by copy.
          SymbolicVariable(const SymbolicVariable &copy);

          //! Destructore.
          ~SymbolicVariable();

          //! Returns the symbolic variable kind. \sa triton::engines::symbolic::symkind_e.
          symkind_e getKind(void) const;

          //! Returns the comment of the symbolic variable.
          const std::string& getComment(void) const;

          //! Returns the name of the symbolic variable.
          const std::string& getName(void) const;

          //! Returns the id of the symbolic variable. This id is unique.
          triton::usize getId(void) const;

          //! Returns the kind value of the symbolic variable.
          triton::uint64 getKindValue(void) const;

          //! Returns the size (in bits) of the symbolic variable.
          triton::uint32 getSize(void) const;

          //! Returns the concrete value (if exists) of the symbolic variable.
          triton::uint512 getConcreteValue(void) const;

          //! Sets the comment of the symbolic variable.
          void setComment(const std::string& comment);

          //! Sets the concrete value of the symbolic variable.
          void setConcreteValue(triton::uint512 value);
      };

      //! Displays a symbolic variable.
      std::ostream& operator<<(std::ostream& stream, const SymbolicVariable& symVar);

      //! Displays a symbolic variable.
      std::ostream& operator<<(std::ostream& stream, const SymbolicVariable* symVar);

    /*! @} End of symbolic namespace */
    };
  /*! @} End of engines namespace */
  };
/*! @} End of triton namespace */
};

#endif /* TRITON_SYMBOLICVARIABLE_H */

<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#include "config.h"

#include <string>
#include <map>

#include "common.hh"
#include "stats.hh"
#include "kvstore.hh"
#include "sqlite-kvstore.hh"

KVStore *KVStore::create(db_type type, EPStats &stats,
                         const KVStoreConfig &conf) {
    SqliteStrategy *sqliteInstance = NULL;
    if (type == multi_db) {
        sqliteInstance = new MultiDBSingleTableSqliteStrategy(conf.location,
                                                              conf.shardPattern,
                                                              conf.initFile,
                                                              conf.postInitFile,
                                                              conf.shards);
    } else if (type == single_db) {
        sqliteInstance = new SingleTableSqliteStrategy(conf.location,
                                                       conf.initFile,
                                                       conf.postInitFile);
    } else if (type == single_mt_db) {
        sqliteInstance = new MultiTableSqliteStrategy(conf.location,
                                                      conf.initFile,
                                                      conf.postInitFile);
    } else {
        abort();
    }
    return new StrategicSqlite3(stats,
                                shared_ptr<SqliteStrategy>(sqliteInstance));
}
<commit_msg>KVStore::create should switch over the enum.<commit_after>/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#include "config.h"

#include <string>
#include <map>

#include "common.hh"
#include "stats.hh"
#include "kvstore.hh"
#include "sqlite-kvstore.hh"

KVStore *KVStore::create(db_type type, EPStats &stats,
                         const KVStoreConfig &conf) {
    SqliteStrategy *sqliteInstance = NULL;
    switch (type) {
    case multi_db:
        sqliteInstance = new MultiDBSingleTableSqliteStrategy(conf.location,
                                                              conf.shardPattern,
                                                              conf.initFile,
                                                              conf.postInitFile,
                                                              conf.shards);
        break;
    case single_db:
        sqliteInstance = new SingleTableSqliteStrategy(conf.location,
                                                       conf.initFile,
                                                       conf.postInitFile);
        break;
    case single_mt_db:
        sqliteInstance = new MultiTableSqliteStrategy(conf.location,
                                                      conf.initFile,
                                                      conf.postInitFile);
        break;
    }
    return new StrategicSqlite3(stats,
                                shared_ptr<SqliteStrategy>(sqliteInstance));
}
<|endoftext|>