<commit_before>#ifndef DUNE_STUFF_GRID_BOUNDARYINFO_HH
#define DUNE_STUFF_GRID_BOUNDARYINFO_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#elif defined (HAVE_CONFIG_H)
  #include <config.h>
#endif // ifdef HAVE_CMAKE_CONFIG

#include <map>
#include <set>
#include <string>

#include <dune/common/shared_ptr.hh>

#include <dune/stuff/common/parameter/tree.hh>

namespace Dune {
namespace Stuff {
namespace Grid {
namespace BoundaryInfo {

class AllDirichlet
{
public:
  template< class IntersectionType >
  bool dirichlet(const IntersectionType& intersection) const
  {
    if (intersection.boundary())
      return true;
    else
      return false;
  }

  template< class IntersectionType >
  bool neumann(const IntersectionType&) const
  {
    return false;
  }
}; // class AllDirichlet

class AllNeumann
{
public:
  template< class IntersectionType >
  bool dirichlet(const IntersectionType& intersection) const
  {
    return false;
  }

  template< class IntersectionType >
  bool neumann(const IntersectionType& intersection) const
  {
    if (intersection.boundary())
      return true;
    else
      return false;
  }
}; // class AllNeumann

class IdBased
{
public:
  typedef IdBased ThisType;

  typedef int IdType;

  typedef std::set< IdType > IdSetType;

  typedef std::map< std::string, IdSetType > IdSetMapType;

  static const std::string id()
  {
    return "stuff.boundaryinfo.idbased";
  }

  IdBased(const Dune::shared_ptr< const IdSetMapType > _boundaryInfoMap)
    : boundaryInfoMap_(_boundaryInfoMap)
  {}

  IdBased(const ThisType& other)
    : boundaryInfoMap_(other.boundaryInfoMap_)
    , hasDirichlet_(other.hasDirichlet_)
    , hasNeumann_(other.hasNeumann_)
  {}

  static ThisType createFromParamTree(const Dune::ParameterTree& paramTree, const std::string subName = id())
  {
    // get correct paramTree
    Common::ParameterTreeX paramTreeX;
    if (paramTree.hasSub(subName))
      paramTreeX = paramTree.sub(subName);
    else
      paramTreeX = paramTree;
    // get dirichlet
    const std::vector< int > dirichletIds = paramTreeX.getVector< int >("dirichlet", 0, 0);
    IdSetType dirichletSet;
    for (unsigned int i = 0; i < dirichletIds.size(); ++i)
      dirichletSet.insert(dirichletIds[i]);
    // get neumann
    const std::vector< int > neumannIds = paramTreeX.getVector< int >("neumann", 0, 0);
    IdSetType neumannSet;
    for (unsigned int i = 0; i < neumannIds.size(); ++i)
      neumannSet.insert(neumannIds[i]);
    // create map and return
    shared_ptr< IdSetMapType > idSetMap(new IdSetMapType());
    idSetMap->insert(std::pair< std::string, IdSetType >("dirichlet", dirichletSet));
    idSetMap->insert(std::pair< std::string, IdSetType >("neumann", neumannSet));
    return ThisType(idSetMap);
  }

  ThisType& operator=(ThisType& other)
  {
    if (this != &other) {
      boundaryInfoMap_ = other.boundaryInfoMap();
      setup();
    }
    return *this;
  }

  const Dune::shared_ptr< const IdSetMapType > boundaryInfoMap()
  {
    return boundaryInfoMap_;
  }

  template< class IntersectionType >
  bool dirichlet(const IntersectionType& intersection) const
  {
    if (hasDirichlet_ && intersection.boundary()) {
      // get boundary id
      const IdType boundaryId = intersection.boundaryId();
      // get set of dirichlet ids (has to be found, otherwise hasDirichlet_ would be false)
      const typename IdSetMapType::const_iterator result = boundaryInfoMap_->find("dirichlet");
      assert(result != boundaryInfoMap_->end());
      const IdSetType& idSet = result->second;
      return (idSet.count(boundaryId) > 0);
    } else
      return false;
  } // bool dirichlet(const IntersectionType& intersection) const

  template< class IntersectionType >
  bool neumann(const IntersectionType& intersection) const
  {
    if (hasNeumann_ && intersection.boundary()) {
      // get boundary id
      const IdType boundaryId = intersection.boundaryId();
      // get set of neumann ids (has to be found, otherwise hasNeumann_ would be false)
      const typename IdSetMapType::const_iterator result = boundaryInfoMap_->find("neumann");
      assert(result != boundaryInfoMap_->end());
      const IdSetType& idSet = result->second;
      return (idSet.count(boundaryId) > 0);
    } else
      return false;
  } // bool neumann(const IntersectionType& intersection) const

private:
  void setup()
  {
    hasDirichlet_ = boundaryInfoMap_->find("dirichlet") != boundaryInfoMap_->end();
    hasNeumann_ = boundaryInfoMap_->find("neumann") != boundaryInfoMap_->end();
  }

  Dune::shared_ptr< const IdSetMapType > boundaryInfoMap_;
  bool hasDirichlet_;
  bool hasNeumann_;
}; // class IdBased

} // namespace BoundaryInfo
} // namespace Grid
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_GRID_BOUNDARYINFO_HH
<commit_msg>[grid.boundaryinfo] added common Interface and create()<commit_after>#ifndef DUNE_STUFF_GRID_BOUNDARYINFO_HH
#define DUNE_STUFF_GRID_BOUNDARYINFO_HH

#ifdef HAVE_CMAKE_CONFIG
  #include "cmake_config.h"
#elif defined (HAVE_CONFIG_H)
  #include <config.h>
#endif // ifdef HAVE_CMAKE_CONFIG

#include <map>
#include <set>
#include <string>

#include <dune/common/shared_ptr.hh>
#include <dune/common/exceptions.hh>

#include <dune/stuff/common/parameter/tree.hh>

namespace Dune {
namespace Stuff {
namespace Grid {
namespace BoundaryInfo {

template< class GridViewImp >
class Interface
{
public:
  typedef GridViewImp GridViewType;

  typedef typename GridViewType::Intersection IntersectionType;

  static const std::string id()
  {
    return "stuff.grid.boundaryinfo";
  }

  virtual bool dirichlet(const IntersectionType&) const = 0;

  virtual bool neumann(const IntersectionType&) const = 0;
}; // class Interface

template< class GridViewImp >
class AllDirichlet
  : public Interface< GridViewImp >
{
public:
  typedef Interface< GridViewImp > BaseType;

  typedef typename BaseType::IntersectionType IntersectionType;

  static const std::string id()
  {
    return BaseType::id() + ".alldirichlet";
  }

  virtual bool dirichlet(const IntersectionType& intersection) const
  {
    if (intersection.boundary())
      return true;
    else
      return false;
  } // virtual bool dirichlet(const IntersectionType& intersection) const

  virtual bool neumann(const IntersectionType&) const
  {
    return false;
  }
}; // class AllDirichlet

template< class GridViewImp >
class AllNeumann
  : public Interface< GridViewImp >
{
public:
  typedef Interface< GridViewImp > BaseType;

  typedef typename BaseType::IntersectionType IntersectionType;

  static const std::string id()
  {
    return BaseType::id() + ".allneumann";
  }

  virtual bool dirichlet(const IntersectionType& intersection) const
  {
    return false;
  }

  virtual bool neumann(const IntersectionType& intersection) const
  {
    if (intersection.boundary())
      return true;
    else
      return false;
  } // virtual bool neumann(const IntersectionType& intersection) const
}; // class AllNeumann

template< class GridViewImp >
class IdBased
  : public Interface< GridViewImp >
{
public:
  typedef Interface< GridViewImp > BaseType;

  typedef typename BaseType::IntersectionType IntersectionType;

  static const std::string id()
  {
    return BaseType::id() + ".idbased";
  }

  typedef IdBased ThisType;

  typedef int IdType;

  typedef std::set< IdType > IdSetType;

  typedef std::map< std::string, IdSetType > IdSetMapType;

  IdBased(const Dune::shared_ptr< const IdSetMapType > _boundaryInfoMap)
    : boundaryInfoMap_(_boundaryInfoMap)
  {}

  IdBased(const ThisType& other)
    : boundaryInfoMap_(other.boundaryInfoMap_)
    , hasDirichlet_(other.hasDirichlet_)
    , hasNeumann_(other.hasNeumann_)
  {}

  static ThisType createFromParamTree(const Dune::ParameterTree& paramTree, const std::string subName = id())
  {
    // get correct paramTree
    Common::ParameterTreeX paramTreeX;
    if (paramTree.hasSub(subName))
      paramTreeX = paramTree.sub(subName);
    else
      paramTreeX = paramTree;
    // get dirichlet
    const std::vector< int > dirichletIds = paramTreeX.getVector< int >("dirichlet", 0, 0);
    IdSetType dirichletSet;
    for (unsigned int i = 0; i < dirichletIds.size(); ++i)
      dirichletSet.insert(dirichletIds[i]);
    // get neumann
    const std::vector< int > neumannIds = paramTreeX.getVector< int >("neumann", 0, 0);
    IdSetType neumannSet;
    for (unsigned int i = 0; i < neumannIds.size(); ++i)
      neumannSet.insert(neumannIds[i]);
    // create map and return
    shared_ptr< IdSetMapType > idSetMap(new IdSetMapType());
    idSetMap->insert(std::pair< std::string, IdSetType >("dirichlet", dirichletSet));
    idSetMap->insert(std::pair< std::string, IdSetType >("neumann", neumannSet));
    return ThisType(idSetMap);
  }

  ThisType& operator=(ThisType& other)
  {
    if (this != &other) {
      boundaryInfoMap_ = other.boundaryInfoMap();
      setup();
    }
    return *this;
  }

  const Dune::shared_ptr< const IdSetMapType > boundaryInfoMap()
  {
    return boundaryInfoMap_;
  }

  virtual bool dirichlet(const IntersectionType& intersection) const
  {
    if (hasDirichlet_ && intersection.boundary()) {
      // get boundary id
      const IdType boundaryId = intersection.boundaryId();
      // get set of dirichlet ids (has to be found, otherwise hasDirichlet_ would be false)
      const typename IdSetMapType::const_iterator result = boundaryInfoMap_->find("dirichlet");
      assert(result != boundaryInfoMap_->end());
      const IdSetType& idSet = result->second;
      return (idSet.count(boundaryId) > 0);
    } else
      return false;
  } // bool dirichlet(const IntersectionType& intersection) const

  virtual bool neumann(const IntersectionType& intersection) const
  {
    if (hasNeumann_ && intersection.boundary()) {
      // get boundary id
      const IdType boundaryId = intersection.boundaryId();
      // get set of neumann ids (has to be found, otherwise hasNeumann_ would be false)
      const typename IdSetMapType::const_iterator result = boundaryInfoMap_->find("neumann");
      assert(result != boundaryInfoMap_->end());
      const IdSetType& idSet = result->second;
      return (idSet.count(boundaryId) > 0);
    } else
      return false;
  } // bool neumann(const IntersectionType& intersection) const

private:
  void setup()
  {
    hasDirichlet_ = boundaryInfoMap_->find("dirichlet") != boundaryInfoMap_->end();
    hasNeumann_ = boundaryInfoMap_->find("neumann") != boundaryInfoMap_->end();
  }

  Dune::shared_ptr< const IdSetMapType > boundaryInfoMap_;
  bool hasDirichlet_;
  bool hasNeumann_;
}; // class IdBased

template< class GridViewType >
Interface< GridViewType >* create(const std::string& type = "stuff.grid.boundaryinfo.alldirichlet",
                                  const Dune::ParameterTree paramTree = Dune::ParameterTree())
{
  if (type == "stuff.grid.boundaryinfo.alldirichlet") {
    typedef AllDirichlet< GridViewType > AllDirichletType;
    AllDirichletType* allDirichlet = new AllDirichletType(AllDirichletType());
    return allDirichlet;
  } else if (type == "stuff.grid.boundaryinfo.allneumann") {
    typedef AllNeumann< GridViewType > AllNeumannType;
    AllNeumannType* allNeumann = new AllNeumannType(AllNeumannType());
    return allNeumann;
  } else if (type == "stuff.grid.boundaryinfo.idbased") {
    typedef IdBased< GridViewType > IdBasedType;
    IdBasedType* idBased = new IdBasedType(IdBasedType::createFromParamTree(paramTree));
    return idBased;
  } else
    DUNE_THROW(Dune::RangeError,
               "\nERROR: unknown boundaryinfo '" << type << "' requested!");
} // Interface< GridViewType >* create(...)

} // namespace BoundaryInfo
} // namespace Grid
} // namespace Stuff
} // namespace Dune

#endif // DUNE_STUFF_GRID_BOUNDARYINFO_HH
<|endoftext|>


<commit_before>/* (potential) File sections:
 * Service: constructors, destructors
 * Input: functions directly related to input of data
 * xCheck: functions directly related to cross-checking the input
 *         against itself for consistency and completeness
 * Preproc: functions directly related to preprocessing of input
 *          prior to solution
 * Solution: functions directly related to the solution of a (sub)problem
 * Utility: advanced member access such as searching and counting
 */

#include "Mixture.h"
#include "Component.h"
#include "Loading.h"
#include "Volume.h"
#include "CoolingTime.h"

#include "Chains/Root.h"

#include "Calc/topScheduleT.h"

#include "Output/Result.h"

/***************************
 ********* Service *********
 **************************/

Mixture::Mixture(char *name)
{
  volume = 0;
  mixName = NULL;
  if (name != NULL)
    {
      mixName = new char[strlen(name)+1];
      memCheck(mixName,"Mixture::Mixture(...) constructor: mixName");
      strcpy(mixName,name);
    }

  compListHead = new Component(COMP_HEAD);
  targetCompListHead = new Component(COMP_HEAD);

  volList = new Volume(VOL_HEAD);

  rootList = NULL;
  targetList = NULL;
  nComps = 0;
  outputList = NULL;
  total = NULL;

  next = NULL;
}

Mixture::Mixture(const Mixture &m)
{
  volume = m.volume;
  mixName = NULL;
  if (m.mixName != NULL)
    {
      mixName = new char[strlen(m.mixName)+1];
      memCheck(mixName,"Mixture::Mixture(...) copy constructor: mixName");
      strcpy(mixName,m.mixName);
    }

  compListHead = new Component(COMP_HEAD);
  targetCompListHead = new Component(COMP_HEAD);

  volList = new Volume(VOL_HEAD);

  rootList = NULL;
  targetList = NULL;
  nComps = 0;
  outputList = NULL;
  total = NULL;

  next = NULL;
}

Mixture::~Mixture()
{
  delete mixName;
  delete compListHead;
  delete targetCompListHead;
  delete rootList;
  delete targetList;
  delete volList;
  delete [] outputList;
  delete next;
}

Mixture& Mixture::operator=(const Mixture &m)
{

  if (this == &m)
    return *this;

  volume = m.volume;
  delete mixName;
  mixName = NULL;
  if (m.mixName != NULL)
    {
      mixName = new char[strlen(m.mixName)+1];
      memCheck(mixName,"Mixture::operator=(...): mixName");
      strcpy(mixName,m.mixName);
    }

  delete compListHead;
  compListHead = new Component(COMP_HEAD);
  delete targetCompListHead;
  targetCompListHead = new Component(COMP_HEAD);

  delete volList;
  volList = new Volume(VOL_HEAD);

  delete rootList;
  rootList = NULL;
  delete targetList;
  targetList = NULL;

  delete [] outputList;
  nComps = 0;
  outputList = NULL;

  delete total;
  total = NULL;

  return *this;

}

/***************************
 *********** Input *********
 ***************************/

/* get each mixture and add components */
/* called by Input::read(...) */
Mixture* Mixture::getMixture(istream &input)
{
  char name[256], token[64];
  int type;

  input >> name;
  next = new Mixture(name);
  memCheck(next,"Mixture::getMixture(...): next");

  Mixture *mixPtr = next;

  /* read a list of componenets until keyword "end" */
  Component* compList = mixPtr->compListHead;
  Component* targetCompList = mixPtr->targetCompListHead;
  mixPtr->nComps = 0;

  verbose(2,"Reading component list for Mixture %s with components:",name);
  clearComment(input);
  input >> token;
  while (strcmp(token,"end"))
    {
      mixPtr->nComps++;

      switch(tolower(token[0]))
	{
	case 'm':
	  debug(2,"Creating new Component object of material type");
	  type = COMP_MAT;
	  break;
	case 'e':
	  debug(2,"Creating new Component object of element type");
	  type = COMP_ELE;
	  break;
	case 'i':
	  debug(2,"Creating new Component object of isotope type");
	  type = COMP_ISO;
	  break;
	case 'l':
	  debug(2,"Creating new Component object of similar type");
	  type = COMP_SIM;
	  break;
	case 't':
	  Chain::modeReverse();
	  /* don't count this in component list */
	  mixPtr->nComps--;
	  clearComment(input);
	  input >> token;
	  switch(tolower(token[0]))
	    {
	    case 'e':
	      type = TARGET_ELE;
	      break;
	    case 'i':
	      type = TARGET_ISO;
	      break;
	    default:
	      error(101,"Target materials for reverse calculations can only be elements or isotopes and not '%s'",token);
	    }
	  break;
	default:
	  error(101,"Invalid material constituent: %s", token);
	}
      if (type <= COMP_SIM)
	/* add each component to the list */
	compList = compList->getComponent(type,input);
      else
	targetCompList = targetCompList->getComponent(type,input);

      clearComment(input);
      input >> token;
    }

  if (compList->head())
    warning(102,"Mixture %s has no components",name);

  /* treat a single component as if there is no component:
   * total only */
  if (mixPtr->nComps == 1)
    mixPtr->nComps = 0;
  mixPtr->outputList = new Result[mixPtr->nComps+1];

  debug(1,"Finished reading Mixture %s.", name);
  return mixPtr;
}

/***************************
 ********* xCheck **********
 **************************/

/* cross-check mixtures internally:
 *  ensure that all referenced mixtures exist */
/* called by Input::xCheck(...) */
void Mixture::xCheck()
{
  Mixture *head = this;
  Mixture *ptr = this;
  Component *current;

  verbose(2,"Checking for all internally referenced mixtures.");

  /* for each mixture */
  while (ptr->next != NULL)
    {
      ptr = ptr->next;
      /* search the component list for type 'l' = similar */
      current = ptr->compListHead->exists(COMP_SIM);
      /* for each type 'l' */
      while(current != NULL)
	{
	  /* search for the referenced name */
	  if (head->find(current->getName()) == NULL)
	      error(123, "Component type 'l' of mixture %s references a non-existent mixture: %s",
		      ptr->mixName,current->getName());

	  current = current->exists(COMP_SIM);
	}
    }

  verbose(3,"All internally referenced mixtures were found.");
}

/****************************
 ********* Preproc **********
 ***************************/

/* search material loading and similarity components for mixture definition */
/* called by Input::preproc(...) */
void Mixture::removeUnused(Loading *loadList)
{
  Mixture *head = this;
  Mixture *prev, *ptr = this;

  verbose(2,"Replacing all 'similar' components and removing unused mixtures.");

  while (ptr->next != NULL)
    {
      prev = ptr;
      ptr = ptr->next;
      /* expand "similar" entries with current mixture definition */
      head->copySim(ptr);

      /* if this mixture is not used in the material loading, remove it */
      if (loadList->findMix(ptr->mixName) == NULL)
	{
	  /* remove current mixture def from list */
	  prev->next = ptr->next;
	  warning(140,"Removing mixture %s not used in any zones.",
		  ptr->mixName);

	  /* this ensures that the entire list is not deleted */
	  ptr->next = NULL;
	  delete ptr;

	  /* go back to last item for testing while loop */
	  ptr = prev;
	}
    }

  verbose(3,"Mixture list has been cleaned up and 'similar' components expanded.");
}

/* copy mixture definition to similar components */
/* called by Mixture::removeUnused(...) */
void Mixture::copySim(Mixture *cpyPtr)
{
  Mixture *ptr = this;
  Component *current;

  verbose(3,"Replacing all components similar to %s with their expanded definition.", cpyPtr->mixName);

  while (ptr->next != NULL)
    {
      ptr = ptr->next;

      current = ptr->compListHead->exists(COMP_SIM);
      while (current != NULL)
	{
	  /* if this component is similar to mixture of interest */
	  if (!strcmp(cpyPtr->mixName,current->getName()))
	    {
	      /* replace the similar component */
	      current = current->replaceSim(cpyPtr->compListHead);
	      verbose(4,"Replaced component of mixture %s with definition of mixture %s",
		      ptr->mixName,cpyPtr->mixName);
	    }
	  current = current->exists(COMP_SIM);
	}
    }

  verbose(4,"All components similar to %s have been replaced.", cpyPtr->mixName);
}

/* cross-referencing mixtures and intervals:
 * add an interval to the list of intervals */
/* called by Volume::xRef(Mixture*) */
void Mixture::xRef(Volume *volPtr)
{
  volList->addMixList(volPtr);
}

/* make a list of root isotopes for this mixture */
/* called by Input::preproc(...) */
void Mixture::makeRootList(Root *&masterRootList)
{
  Mixture *ptr = this;

  verbose(2,"Making list of root isotopes.");
  while (ptr->next != NULL)
    {
      ptr = ptr->next;
      /* expand the components into a root list */
      verbose(3,"Expanding mixture %s",ptr->mixName);
      ptr->rootList = ptr->compListHead->expand(ptr);
      switch(NuclearData::getMode())
	{
	case MODE_FORWARD:
	  /* merge this root list into the master */
	  masterRootList = masterRootList->merge(ptr->rootList);
	  verbose(4,"Merged rootlist for mixture %s to master root list.",
		  ptr->mixName);
	  break;
	case MODE_REVERSE:
	  /* expand the target components into a target list */
	  ptr->targetList = ptr->targetCompListHead->expand(ptr);
	  /* merge this root list into the master */
	  masterRootList = masterRootList->merge(ptr->targetList);
	  verbose(4,"Merged targetList for mixture %s to master root list.",
		  ptr->mixName);
	  break;
	}
    }

  verbose(3,"Expanded all mixtures to master root list.");

}

/****************************
 ********* Solution *********
 ***************************/

void Mixture::refFlux(VolFlux *fluxHead)
{
  volList->refFlux(fluxHead);
}

void Mixture::solve(Chain* chain, topSchedule* schedule)
{
  volList->solve(chain,schedule);
}

void Mixture::writeDump()
{
  volList->writeDump();
}

/*****************************
 ********* PostProc **********
 ****************************/

void Mixture::readDump(int kza)
{
  volList->readDump(kza);
}

void Mixture::tally(Result *volOutputList, double vol)
{
  int compNum;
  volume += vol;

  for (compNum=0;compNum<nComps;compNum++)
    volOutputList[compNum].postProc(outputList[compNum],vol);

  volOutputList[compNum].postProc(outputList[compNum],vol);
}

void Mixture::write(int response, int writeComp, CoolingTime* coolList,
		    int targetKza)
{
  Mixture *head = this;
  Mixture *ptr = head;
  int mixCntr = 0;

  /* for each mixture */
  while (ptr->next != NULL)
    {
      ptr = ptr->next;

      /* write header information */
      cout << "Mixture #" << ++mixCntr << ": " << ptr->mixName << endl;
      cout << "\tVolume: " << ptr->volume << endl;

      /* write the component breakdown if requested */
      if (writeComp)
	{
	  /* get the list of components for this mixture */
	  Component *compPtr = ptr->compListHead;
	  int compNum=0;
	  compPtr = compPtr->advance();

	  /* for each component */
	  while (compPtr != NULL)
	    {
	      /* write component header */
	      cout << "Component: " << compPtr->getName() << endl;
	      ptr->outputList[compNum].write(response,targetKza,coolList,ptr->total,
					     ptr->volume);
	      compPtr = compPtr->advance();
	      compNum++;
	    }
	}

      /* if components were written and there is only one */
      if (writeComp && ptr->nComps == 0)
	/* write comment refering total to component total */
	cout << "** Interval totals are the same as those of the single component."
	     << endl << endl;
      else
	{
	  /* otherwise write the total response for the zone */
	  cout << "Total" << endl;
	  ptr->outputList[ptr->nComps].write(response,targetKza,coolList,ptr->total,
					     ptr->volume);
	}
    }

  /** WRITE TOTAL TABLE **/
  /* reset mixture pointer and counter */
  ptr = head;
  mixCntr = 0;

  int resNum,nResults = topScheduleT::getNumCoolingTimes()+1;
  char isoSym[15];

  cout << "Totals for all mixtures." << endl;

  /* write header for totals */
  coolList->writeTotalHeader("mixture");

  /* for each mixture */
  while (ptr->next != NULL)
    {
      ptr = ptr->next;
      cout << ++mixCntr << "\t";
      for (resNum=0;resNum<nResults;resNum++)
	{
	  sprintf(isoSym,"%-11.4e ",ptr->total[resNum]);
	  cout << isoSym;
	}
      cout << "\t" << ptr->mixName << endl;
    }
  coolList->writeSeparator();

  cout << endl << endl;
}

/****************************
 ********* Utility **********
 ***************************/

Component* Mixture::getComp(int kza,double &density, Component *lastComp)
{
  Root *root = rootList->find(kza);

  if (root)
    return root->getComp(density,this,lastComp);
  else
    return NULL;
}

int Mixture::getCompNum(Component* compPtr)
{
  return compListHead->getCompNum(compPtr);

}

/* find a named mixture in the list */
Mixture* Mixture::find(char* srchName)
{

  Mixture *ptr = this;

  while (ptr->next != NULL)
    {
      ptr = ptr->next;
      if (!strcmp(ptr->mixName,srchName))
	return ptr;
    }

  return NULL;
}

/* find a named mixture in the list */
void Mixture::resetVolume()
{

  Mixture *ptr = this;

  while (ptr != NULL)
    {
      ptr->volume = 0;
      ptr = ptr->next;
    }
}

<commit_msg>In reverse mode, root may not exist in a mixture, in which case make sure density is set to 0 in getComp(...)<commit_after>/* (potential) File sections:
 * Service: constructors, destructors
 * Input: functions directly related to input of data
 * xCheck: functions directly related to cross-checking the input
 *         against itself for consistency and completeness
 * Preproc: functions directly related to preprocessing of input
 *          prior to solution
 * Solution: functions directly related to the solution of a (sub)problem
 * Utility: advanced member access such as searching and counting
 */

#include "Mixture.h"
#include "Component.h"
#include "Loading.h"
#include "Volume.h"
#include "CoolingTime.h"

#include "Chains/Root.h"

#include "Calc/topScheduleT.h"

#include "Output/Result.h"

/***************************
 ********* Service *********
 **************************/

Mixture::Mixture(char *name)
{
  volume = 0;
  mixName = NULL;
  if (name != NULL)
    {
      mixName = new char[strlen(name)+1];
      memCheck(mixName,"Mixture::Mixture(...) constructor: mixName");
      strcpy(mixName,name);
    }

  compListHead = new Component(COMP_HEAD);
  targetCompListHead = new Component(COMP_HEAD);

  volList = new Volume(VOL_HEAD);

  rootList = NULL;
  targetList = NULL;
  nComps = 0;
  outputList = NULL;
  total = NULL;

  next = NULL;
}

Mixture::Mixture(const Mixture &m)
{
  volume = m.volume;
  mixName = NULL;
  if (m.mixName != NULL)
    {
      mixName = new char[strlen(m.mixName)+1];
      memCheck(mixName,"Mixture::Mixture(...) copy constructor: mixName");
      strcpy(mixName,m.mixName);
    }

  compListHead = new Component(COMP_HEAD);
  targetCompListHead = new Component(COMP_HEAD);

  volList = new Volume(VOL_HEAD);

  rootList = NULL;
  targetList = NULL;
  nComps = 0;
  outputList = NULL;
  total = NULL;

  next = NULL;
}

Mixture::~Mixture()
{
  delete mixName;
  delete compListHead;
  delete targetCompListHead;
  delete rootList;
  delete targetList;
  delete volList;
  delete [] outputList;
  delete next;
}

Mixture& Mixture::operator=(const Mixture &m)
{

  if (this == &m)
    return *this;

  volume = m.volume;
  delete mixName;
  mixName = NULL;
  if (m.mixName != NULL)
    {
      mixName = new char[strlen(m.mixName)+1];
      memCheck(mixName,"Mixture::operator=(...): mixName");
      strcpy(mixName,m.mixName);
    }

  delete compListHead;
  compListHead = new Component(COMP_HEAD);
  delete targetCompListHead;
  targetCompListHead = new Component(COMP_HEAD);

  delete volList;
  volList = new Volume(VOL_HEAD);

  delete rootList;
  rootList = NULL;
  delete targetList;
  targetList = NULL;

  delete [] outputList;
  nComps = 0;
  outputList = NULL;

  delete total;
  total = NULL;

  return *this;

}

/***************************
 *********** Input *********
 ***************************/

/* get each mixture and add components */
/* called by Input::read(...) */
Mixture* Mixture::getMixture(istream &input)
{
  char name[256], token[64];
  int type;

  input >> name;
  next = new Mixture(name);
  memCheck(next,"Mixture::getMixture(...): next");

  Mixture *mixPtr = next;

  /* read a list of componenets until keyword "end" */
  Component* compList = mixPtr->compListHead;
  Component* targetCompList = mixPtr->targetCompListHead;
  mixPtr->nComps = 0;

  verbose(2,"Reading component list for Mixture %s with components:",name);
  clearComment(input);
  input >> token;
  while (strcmp(token,"end"))
    {
      mixPtr->nComps++;

      switch(tolower(token[0]))
	{
	case 'm':
	  debug(2,"Creating new Component object of material type");
	  type = COMP_MAT;
	  break;
	case 'e':
	  debug(2,"Creating new Component object of element type");
	  type = COMP_ELE;
	  break;
	case 'i':
	  debug(2,"Creating new Component object of isotope type");
	  type = COMP_ISO;
	  break;
	case 'l':
	  debug(2,"Creating new Component object of similar type");
	  type = COMP_SIM;
	  break;
	case 't':
	  Chain::modeReverse();
	  /* don't count this in component list */
	  mixPtr->nComps--;
	  clearComment(input);
	  input >> token;
	  switch(tolower(token[0]))
	    {
	    case 'e':
	      type = TARGET_ELE;
	      break;
	    case 'i':
	      type = TARGET_ISO;
	      break;
	    default:
	      error(101,"Target materials for reverse calculations can only be elements or isotopes and not '%s'",token);
	    }
	  break;
	default:
	  error(101,"Invalid material constituent: %s", token);
	}
      if (type <= COMP_SIM)
	/* add each component to the list */
	compList = compList->getComponent(type,input);
      else
	targetCompList = targetCompList->getComponent(type,input);

      clearComment(input);
      input >> token;
    }

  if (compList->head())
    warning(102,"Mixture %s has no components",name);

  /* treat a single component as if there is no component:
   * total only */
  if (mixPtr->nComps == 1)
    mixPtr->nComps = 0;
  mixPtr->outputList = new Result[mixPtr->nComps+1];

  debug(1,"Finished reading Mixture %s.", name);
  return mixPtr;
}

/***************************
 ********* xCheck **********
 **************************/

/* cross-check mixtures internally:
 *  ensure that all referenced mixtures exist */
/* called by Input::xCheck(...) */
void Mixture::xCheck()
{
  Mixture *head = this;
  Mixture *ptr = this;
  Component *current;

  verbose(2,"Checking for all internally referenced mixtures.");

  /* for each mixture */
  while (ptr->next != NULL)
    {
      ptr = ptr->next;
      /* search the component list for type 'l' = similar */
      current = ptr->compListHead->exists(COMP_SIM);
      /* for each type 'l' */
      while(current != NULL)
	{
	  /* search for the referenced name */
	  if (head->find(current->getName()) == NULL)
	      error(123, "Component type 'l' of mixture %s references a non-existent mixture: %s",
		      ptr->mixName,current->getName());

	  current = current->exists(COMP_SIM);
	}
    }

  verbose(3,"All internally referenced mixtures were found.");
}

/****************************
 ********* Preproc **********
 ***************************/

/* search material loading and similarity components for mixture definition */
/* called by Input::preproc(...) */
void Mixture::removeUnused(Loading *loadList)
{
  Mixture *head = this;
  Mixture *prev, *ptr = this;

  verbose(2,"Replacing all 'similar' components and removing unused mixtures.");

  while (ptr->next != NULL)
    {
      prev = ptr;
      ptr = ptr->next;
      /* expand "similar" entries with current mixture definition */
      head->copySim(ptr);

      /* if this mixture is not used in the material loading, remove it */
      if (loadList->findMix(ptr->mixName) == NULL)
	{
	  /* remove current mixture def from list */
	  prev->next = ptr->next;
	  warning(140,"Removing mixture %s not used in any zones.",
		  ptr->mixName);

	  /* this ensures that the entire list is not deleted */
	  ptr->next = NULL;
	  delete ptr;

	  /* go back to last item for testing while loop */
	  ptr = prev;
	}
    }

  verbose(3,"Mixture list has been cleaned up and 'similar' components expanded.");
}

/* copy mixture definition to similar components */
/* called by Mixture::removeUnused(...) */
void Mixture::copySim(Mixture *cpyPtr)
{
  Mixture *ptr = this;
  Component *current;

  verbose(3,"Replacing all components similar to %s with their expanded definition.", cpyPtr->mixName);

  while (ptr->next != NULL)
    {
      ptr = ptr->next;

      current = ptr->compListHead->exists(COMP_SIM);
      while (current != NULL)
	{
	  /* if this component is similar to mixture of interest */
	  if (!strcmp(cpyPtr->mixName,current->getName()))
	    {
	      /* replace the similar component */
	      current = current->replaceSim(cpyPtr->compListHead);
	      verbose(4,"Replaced component of mixture %s with definition of mixture %s",
		      ptr->mixName,cpyPtr->mixName);
	    }
	  current = current->exists(COMP_SIM);
	}
    }

  verbose(4,"All components similar to %s have been replaced.", cpyPtr->mixName);
}

/* cross-referencing mixtures and intervals:
 * add an interval to the list of intervals */
/* called by Volume::xRef(Mixture*) */
void Mixture::xRef(Volume *volPtr)
{
  volList->addMixList(volPtr);
}

/* make a list of root isotopes for this mixture */
/* called by Input::preproc(...) */
void Mixture::makeRootList(Root *&masterRootList)
{
  Mixture *ptr = this;

  verbose(2,"Making list of root isotopes.");
  while (ptr->next != NULL)
    {
      ptr = ptr->next;
      /* expand the components into a root list */
      verbose(3,"Expanding mixture %s",ptr->mixName);
      ptr->rootList = ptr->compListHead->expand(ptr);
      switch(NuclearData::getMode())
	{
	case MODE_FORWARD:
	  /* merge this root list into the master */
	  masterRootList = masterRootList->merge(ptr->rootList);
	  verbose(4,"Merged rootlist for mixture %s to master root list.",
		  ptr->mixName);
	  break;
	case MODE_REVERSE:
	  /* expand the target components into a target list */
	  ptr->targetList = ptr->targetCompListHead->expand(ptr);
	  /* merge this root list into the master */
	  masterRootList = masterRootList->merge(ptr->targetList);
	  verbose(4,"Merged targetList for mixture %s to master root list.",
		  ptr->mixName);
	  break;
	}
    }

  verbose(3,"Expanded all mixtures to master root list.");

}

/****************************
 ********* Solution *********
 ***************************/

void Mixture::refFlux(VolFlux *fluxHead)
{
  volList->refFlux(fluxHead);
}

void Mixture::solve(Chain* chain, topSchedule* schedule)
{
  volList->solve(chain,schedule);
}

void Mixture::writeDump()
{
  volList->writeDump();
}

/*****************************
 ********* PostProc **********
 ****************************/

void Mixture::readDump(int kza)
{
  volList->readDump(kza);
}

void Mixture::tally(Result *volOutputList, double vol)
{
  int compNum;
  volume += vol;

  for (compNum=0;compNum<nComps;compNum++)
    volOutputList[compNum].postProc(outputList[compNum],vol);

  volOutputList[compNum].postProc(outputList[compNum],vol);
}

void Mixture::write(int response, int writeComp, CoolingTime* coolList,
		    int targetKza)
{
  Mixture *head = this;
  Mixture *ptr = head;
  int mixCntr = 0;

  /* for each mixture */
  while (ptr->next != NULL)
    {
      ptr = ptr->next;

      /* write header information */
      cout << "Mixture #" << ++mixCntr << ": " << ptr->mixName << endl;
      cout << "\tVolume: " << ptr->volume << endl;

      /* write the component breakdown if requested */
      if (writeComp)
	{
	  /* get the list of components for this mixture */
	  Component *compPtr = ptr->compListHead;
	  int compNum=0;
	  compPtr = compPtr->advance();

	  /* for each component */
	  while (compPtr != NULL)
	    {
	      /* write component header */
	      cout << "Component: " << compPtr->getName() << endl;
	      ptr->outputList[compNum].write(response,targetKza,coolList,ptr->total,
					     ptr->volume);

	      compPtr = compPtr->advance();
	      compNum++;
	    }
	}

      /* if components were written and there is only one */
      if (writeComp && ptr->nComps == 0)
	/* write comment refering total to component total */
	cout << "** Interval totals are the same as those of the single component."
	     << endl << endl;
      else
	{
	  /* otherwise write the total response for the zone */
	  cout << "Total" << endl;
	  ptr->outputList[ptr->nComps].write(response,targetKza,coolList,ptr->total,
					     ptr->volume);

	}
    }

  /** WRITE TOTAL TABLE **/
  /* reset mixture pointer and counter */
  ptr = head;
  mixCntr = 0;

  int resNum,nResults = topScheduleT::getNumCoolingTimes()+1;
  char isoSym[15];

  cout << "Totals for all mixtures." << endl;

  /* write header for totals */
  coolList->writeTotalHeader("mixture");

  /* for each mixture */
  while (ptr->next != NULL)
    {
      ptr = ptr->next;
      cout << ++mixCntr << "\t";
      for (resNum=0;resNum<nResults;resNum++)
	{
	  sprintf(isoSym,"%-11.4e ",ptr->total[resNum]);
	  cout << isoSym;
	}
      cout << "\t" << ptr->mixName << endl;
    }
  coolList->writeSeparator();

  cout << endl << endl;
}

/****************************
 ********* Utility **********
 ***************************/

Component* Mixture::getComp(int kza,double &density, Component *lastComp)
{
  Root *root = rootList->find(kza);

  if (root)
    return root->getComp(density,this,lastComp);
  else
    {
      density = 0;
      return NULL;
    }
}

int Mixture::getCompNum(Component* compPtr)
{
  return compListHead->getCompNum(compPtr);

}

/* find a named mixture in the list */
Mixture* Mixture::find(char* srchName)
{

  Mixture *ptr = this;

  while (ptr->next != NULL)
    {
      ptr = ptr->next;
      if (!strcmp(ptr->mixName,srchName))
	return ptr;
    }

  return NULL;
}

/* find a named mixture in the list */
void Mixture::resetOutList()
{
  int compNum;
  Mixture *ptr = this;

  while (ptr->next != NULL)
    {
      ptr = ptr->next;
      ptr->volume = 0;
      for (compNum=0;compNum<=ptr->nComps;compNum++)
	ptr->outputList[compNum].clear();
    }
}

<|endoftext|>


<commit_before>/// @file using_Hg.cpp
///
/// Implements message parsing by using Hg.
///
/// The MIT License(MIT)
/// @copyright 2014 Paul M Watt
//  ****************************************************************************
//  Includes *******************************************************************
#include <using_Hg.h>
#include <Hg.h>
#include <Hg/static_msg_buffer.h>
#include <iostream>

using std::cout;
using std::endl;

namespace alchemy
{
namespace benchmark
{

//  ****************************************************************************
typedef Hg::basic_msg<Hg::NoConversion, Hg::BufferedStaticStoragePolicy>   HgNoConversion;

void UsingHg::test_no_conversion( DataBuffer &data,
                                  DataBuffer &out)
{
  size_t len = Hg::SizeOf<Hg::NoConversion>::value;
  size_t count = data.Size() / len;

  cout << "no_conversion size: " << len   << "\t\tcount: " << count << endl;
  for (size_t index = 0; index < count; ++index)
  {
    HgNoConversion::host_t host((HgNoConversion::data_type*)data.GetBytes(len), len);

    HgNoConversion::host_t  net = Hg::to_network(host);

    net.data((unsigned char*)out.GetBytes(len), len);
  }

}

//  ****************************************************************************
typedef Hg::basic_msg<Hg::Basic, Hg::BufferedStaticStoragePolicy>   HgBasic;

void UsingHg::test_basic(DataBuffer &data,
                         DataBuffer &out)
{
  size_t len   = Hg::SizeOf<Hg::Basic>::value;
  size_t count = data.Size() / len;

  cout << "        basic size: " << len   << "\t\tcount: " << count << endl;
  for (size_t index = 0; index < count; ++index)
  {
    HgBasic::host_t host((HgBasic::data_type*)data.GetBytes(len), len);

    HgBasic::net_t  net = Hg::to_network(host);

    net.data((unsigned char*)out.GetBytes(len), len);
  }
}

//  ****************************************************************************
typedef Hg::basic_msg<Hg::Packed, Hg::BufferedStaticStoragePolicy>   HgPacked;

void UsingHg::test_packed_bits( DataBuffer &data,
                                DataBuffer &out)
{
  size_t len   = Hg::SizeOf<Hg::Packed>::value;
  size_t count = data.Size() / len;

  cout << "       packed size: " << len   << "\t\tcount: " << count << endl;
  for (size_t index = 0; index < count; ++index)
  {
    HgPacked::host_t host((HgPacked::data_type*)data.GetBytes(len), len);

    HgPacked::net_t  net = Hg::to_network(host);

    net.data((unsigned char*)out.GetBytes(len), len);
  }
}

//  ****************************************************************************
typedef Hg::basic_msg<Hg::Unaligned, Hg::BufferedStaticStoragePolicy>   HgUnaligned;

void UsingHg::test_unaligned( DataBuffer &data,
                              DataBuffer &out)
{
  size_t len   = Hg::SizeOf<Hg::Unaligned>::value;
  size_t count = data.Size() / len;

  cout << "    unaligned size: " << len   << "\t\tcount: " << count << endl;
  for (size_t index = 0; index < count; ++index)
  {
    HgUnaligned::host_t host((HgUnaligned::data_type*)data.GetBytes(len), len);

    HgUnaligned::net_t  net = Hg::to_network(host);

    net.data((unsigned char*)out.GetBytes(len), len);
  }

}

//  ****************************************************************************
typedef Hg::basic_msg<Hg::Complex, Hg::BufferedStaticStoragePolicy>   HgComplex;

void UsingHg::test_complex(DataBuffer &data,
                           DataBuffer &out)
{
  size_t len = Hg::SizeOf<Hg::Complex>::value;
  size_t count = data.Size() / len;

  cout << "      complex size: " << len   << "\t\tcount: " << count << endl;
  for (size_t index = 0; index < count; ++index)
  {
    HgComplex::host_t host((HgComplex::data_type*)data.GetBytes(len), len);

    HgComplex::net_t  net = Hg::to_network(host);

    net.data((unsigned char*)out.GetBytes(len), len);
  }

}

//  ****************************************************************************
typedef Hg::basic_msg<Hg::Array_test, Hg::BufferedStaticStoragePolicy>   HgArray;

void UsingHg::test_array(DataBuffer &data,
                         DataBuffer &out)
{
  size_t len = Hg::SizeOf<Hg::Array_test>::value;
  size_t count = data.Size() / len;

  cout << "        array size: " << len   << "\tcount: " << count << endl;
  for (size_t index = 0; index < count; ++index)
  {
    HgArray::host_t host((HgArray::data_type*)data.GetBytes(len), len);

    HgArray::net_t  net = Hg::to_network(host);

    net.data((unsigned char*)out.GetBytes(len), len);
  }

}

} // benchmark
} // alchemy

<commit_msg>Simplified the Hg benchmark tests<commit_after>/// @file using_Hg.cpp
///
/// Implements message parsing by using Hg.
///
/// The MIT License(MIT)
/// @copyright 2014 Paul M Watt
//  ****************************************************************************
//  Includes *******************************************************************
#include <using_Hg.h>
#include <Hg.h>
#include <Hg/static_msg_buffer.h>
#include <iostream>

using std::cout;
using std::endl;

namespace alchemy
{
namespace benchmark
{
namespace detail
{

//  ****************************************************************************
template< typename T >
void test_impl( DataBuffer &data,
                DataBuffer &out,
                const char (&name)[14])
{
  typedef Hg::basic_msg<T, Hg::BufferedStaticStoragePolicy>   HgType;

  size_t len = Hg::SizeOf<HgType>::value;
  size_t count = data.Size() / len;

  cout << name << " size: " << len   << "\t\tcount: " << count << endl;
  for (size_t index = 0; index < count; ++index)
  {
    HgType::host_t host((HgType::data_type*)data.GetBytes(len), len);

    HgType::net_t  net = Hg::to_network(host);

    net.data((unsigned char*)out.GetBytes(len), len);
  }

}

} // namespace detail

//  ****************************************************************************
typedef Hg::basic_msg<Hg::NoConversion, Hg::BufferedStaticStoragePolicy>   HgNoConversion;

void UsingHg::test_no_conversion( DataBuffer &data,
                                  DataBuffer &out)
{
  detail::test_impl<Hg::NoConversion>(data, out, "no_conversion");
}

//  ****************************************************************************
void UsingHg::test_basic(DataBuffer &data,
                         DataBuffer &out)
{
  detail::test_impl<Hg::Basic>(data, out, "        basic");
}

//  ****************************************************************************
void UsingHg::test_packed_bits( DataBuffer &data,
                                DataBuffer &out)
{
  detail::test_impl<Hg::Packed>(data, out, "       packed");
}

//  ****************************************************************************
void UsingHg::test_unaligned( DataBuffer &data,
                              DataBuffer &out)
{
  detail::test_impl<Hg::Unaligned>(data, out, "    unaligned");
}

//  ****************************************************************************
void UsingHg::test_complex(DataBuffer &data,
                           DataBuffer &out)
{
  detail::test_impl<Hg::Complex>(data, out, "      complex");
}

//  ****************************************************************************
void UsingHg::test_array(DataBuffer &data,
                         DataBuffer &out)
{
  detail::test_impl<Hg::Array_test>(data, out, "        array");
}

} // benchmark
} // alchemy

<|endoftext|>


<commit_before>/*
    DOS support for Crystal Space 3D library
    Written by David N. Arnold <derek_arnold@fuse.net>
    Written by Andrew Zabolotny <bit@eltech.ru>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <dpmi.h>
#include <go32.h>
#include <pc.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/nearptr.h>
#include <sys/farptr.h>
#include <crt0.h>

#include "cssysdef.h"
#include "djgpp.h"
#include "csutil/inifile.h"
#include "isystem.h"
#include "inputq.h"
#include "djkeysys.h"
#include "djmousys.h"

static KeyboardHandler KH;
static MouseHandler MH;
bool EnablePrintf;

static unsigned short ScanCodeToChar[128] =
{
  0,        CSKEY_ESC,'1',      '2',      '3',      '4',      '5',      '6',    // 00..07
  '7',      '8',      '9',      '0',      '-',      '=',      '\b',     '\t',   // 08..0F
  'q',      'w',      'e',      'r',      't',      'y',      'u',      'i',    // 10..17
  'o',      'p',      '[',      ']',      '\n',     CSKEY_CTRL,'a',     's',    // 18..1F
  'd',      'f',      'g',      'h',      'j',      'k',      'l',      ';',    // 20..27
  39,       '`',      CSKEY_SHIFT,'\\',   'z',      'x',      'c',      'v',    // 28..2F
  'b',      'n',      'm',      ',',      '.',      '/',CSKEY_SHIFT,CSKEY_PADMULT,// 30..37
  CSKEY_ALT,' ',      0,        CSKEY_F1, CSKEY_F2, CSKEY_F3, CSKEY_F4, CSKEY_F5,// 38..3F
  CSKEY_F6,  CSKEY_F7, CSKEY_F8, CSKEY_F9, CSKEY_F10,0,       0,        CSKEY_HOME,// 40..47
  CSKEY_UP,  CSKEY_PGUP,CSKEY_PADMINUS,CSKEY_LEFT,CSKEY_CENTER,CSKEY_RIGHT,CSKEY_PADPLUS,CSKEY_END,// 48..4F
  CSKEY_DOWN,CSKEY_PGDN,CSKEY_INS,CSKEY_DEL,0,      0,        0,        CSKEY_F11,// 50..57
  CSKEY_F12,0,        0,        0,        0,        0,        0,        0,      // 58..5F
  0,        0,        0,        0,        0,        0,        0,        0,      // 60..67
  0,        0,        0,        0,        0,        0,        0,        CSKEY_PADDIV,// 68..6F
  0,        0,        0,        0,        0,        0,        0,        0,      // 70..77
  0,        0,        0,        0,        0,        0,        0,        0       // 78..7F
};

//================================================================== System ====

IMPLEMENT_IBASE_EXT (SysSystemDriver)
  IMPLEMENTS_INTERFACE (iEventPlug)
IMPLEMENT_IBASE_EXT_END

SysSystemDriver::SysSystemDriver () : csSystemDriver ()
{
  // Sanity check
  if (sizeof (event_queue [0]) != 12)
  {
    Printf (MSG_FATAL_ERROR, "ERROR! Your compiler does not handle packed structures!\n");
    Printf (MSG_FATAL_ERROR, "sizeof (event_queue [0]) == %d instead of 12!\n", sizeof (event_queue [0]));
    exit (-1);
  }

  __dpmi_regs regs;
  regs.x.ax = 0x0000;
  __dpmi_int (0x33, &regs);
  MouseExists = !!(regs.x.ax);
  MouseOpened = false;
  EnablePrintf = true;
  EventOutlet = CreateEventOutlet (this);
}

SysSystemDriver::~SysSystemDriver ()
{
  if (EventOutlet)
    EventOutlet->DecRef ();
}

void SysSystemDriver::NextFrame ()
{
  bool ExtKey = false;
  // Fill in events ...
  while (event_queue_tail != event_queue_head)
  {
    switch (event_queue [event_queue_tail].Type)
    {
      case 1:
      {
        int ScanCode = event_queue [event_queue_tail].Keyboard.ScanCode;
        bool Down = (ScanCode < 0x80);

        if ((ScanCode == 0xe0) || (ScanCode == 0xe1))
          ExtKey = true;
        else
        {
          // handle keypad '/'
          if (ExtKey && (ScanCode == 0x35))
            ScanCode = 0x6f;

          ScanCode = ScanCodeToChar [ScanCode & 0x7F];
          if (ScanCode)
            EventOutlet->Key (ScanCode, -1, Down);
        }
        break;
      }
      case 2:
      {
        int Button = event_queue [event_queue_tail].Mouse.Button;
        bool Down = event_queue [event_queue_tail].Mouse.Down;
        int x = event_queue [event_queue_tail].Mouse.x;
        int y = event_queue [event_queue_tail].Mouse.y;

        EventOutlet->Mouse (Button, Down, x, y);
        break;
      }
    } /* endswitch */
    event_queue_tail = (event_queue_tail + 1) & EVENT_QUEUE_MASK;
  } /* endwhile */
}

bool SysSystemDriver::Open (const char *Title)
{
  if (!csSystemDriver::Open (Title))
    return false;

  // Initialize keyboard handler
  if (KH.install ())
    return false;
  // Give us exclusive access of the keyboard.
  KH.chain (0);
  KeyboardOpened = true;

  SensivityFactor = Config->GetFloat ("MouseDriver", "MouseSensivity", 1.0);

  if (MH.install ())
    return false;

  // Query screen size
  int FrameWidth, FrameHeight, Depth;
  bool FullScreen;
  GetSettings (FrameWidth, FrameHeight, Depth, FullScreen);

  // Query mouse sensivity
  __dpmi_regs regs;
  regs.x.ax = 0x1B;
  __dpmi_int (0x33, &regs);
  mouse_sensivity_x = regs.x.bx;
  mouse_sensivity_y = regs.x.cx;
  mouse_sensivity_threshold = regs.x.dx;

  // Compute mouse sensivity
  regs.x.cx = 8;
  regs.x.dx = 8;
  regs.x.ax = 0x0F;
  __dpmi_int (0x33, &regs);
  regs.x.bx = (int) ((50 + FrameWidth / 32) * SensivityFactor);
  regs.x.cx = (int) ((50 + FrameHeight / 24) * SensivityFactor);
  regs.x.dx = MAX (regs.x.bx, regs.x.cx); // ? not sure about this
  regs.x.ax = 0x1A;
  __dpmi_int (0x33, &regs);

  // Set mouse range to full-screen
  regs.x.ax = 0x07;
  regs.x.cx = 0;
  regs.x.dx = FrameWidth - 1;
  __dpmi_int (0x33, &regs);
  regs.x.ax = 0x08;
  regs.x.cx = 0;
  regs.x.dx = FrameHeight - 1;
  __dpmi_int (0x33, &regs);

  // Set mouse to (0, 0)
  regs.x.ax = 0x04;
  regs.x.cx = 0;
  regs.x.dx = 0;
  __dpmi_int (0x33, &regs);

  MouseOpened = true;

  return true;
}

void SysSystemDriver::Close ()
{
  if (KeyboardOpened)
  {
    KH.uninstall ();
    KeyboardOpened = false;
  }

  if (MouseOpened)
  {
    MH.uninstall ();

    // Restore mouse sensivity
    __dpmi_regs regs;
    regs.x.cx = 8;
    regs.x.dx = 16;
    regs.x.ax = 0x0F;
    __dpmi_int (0x33, &regs);
    regs.x.ax = 0x1A;
    regs.x.bx = mouse_sensivity_x;
    regs.x.cx = mouse_sensivity_y;
    regs.x.dx = mouse_sensivity_threshold;
    __dpmi_int (0x33, &regs);

    MouseOpened = false;
  }
}

bool SysSystemDriver::SystemExtension (const char *iCommand, ...)
{
  va_list args;
  va_start (args, iCommand);

  bool rc = true;
  if (!strcmp (iCommand, "SetMousePosition"))
  {
    int x = va_arg (args, int);
    int y = va_arg (args, int);

    if (MouseOpened)
    {
      __dpmi_regs regs;
      regs.x.cx = x;
      regs.x.dx = y;
      regs.x.ax = 0x04;
      __dpmi_int (0x33, &regs);
    }
  }
  else if (!strcmp (iCommand, "EnablePrintf"))
    EnablePrintf = va_arg (args, bool);
  else
    rc = false;

  va_end (args);
  return rc;
}
<commit_msg>fixes include<commit_after>/*
    DOS support for Crystal Space 3D library
    Written by David N. Arnold <derek_arnold@fuse.net>
    Written by Andrew Zabolotny <bit@eltech.ru>

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

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

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <dpmi.h>
#include <go32.h>
#include <pc.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/nearptr.h>
#include <sys/farptr.h>
#include <crt0.h>

#include "cssysdef.h"
#include "cssys/djgpp/djgpp.h"
#include "csutil/inifile.h"
#include "isystem.h"
#include "inputq.h"
#include "djkeysys.h"
#include "djmousys.h"

static KeyboardHandler KH;
static MouseHandler MH;
bool EnablePrintf;

static unsigned short ScanCodeToChar[128] =
{
  0,        CSKEY_ESC,'1',      '2',      '3',      '4',      '5',      '6',    // 00..07
  '7',      '8',      '9',      '0',      '-',      '=',      '\b',     '\t',   // 08..0F
  'q',      'w',      'e',      'r',      't',      'y',      'u',      'i',    // 10..17
  'o',      'p',      '[',      ']',      '\n',     CSKEY_CTRL,'a',     's',    // 18..1F
  'd',      'f',      'g',      'h',      'j',      'k',      'l',      ';',    // 20..27
  39,       '`',      CSKEY_SHIFT,'\\',   'z',      'x',      'c',      'v',    // 28..2F
  'b',      'n',      'm',      ',',      '.',      '/',CSKEY_SHIFT,CSKEY_PADMULT,// 30..37
  CSKEY_ALT,' ',      0,        CSKEY_F1, CSKEY_F2, CSKEY_F3, CSKEY_F4, CSKEY_F5,// 38..3F
  CSKEY_F6,  CSKEY_F7, CSKEY_F8, CSKEY_F9, CSKEY_F10,0,       0,        CSKEY_HOME,// 40..47
  CSKEY_UP,  CSKEY_PGUP,CSKEY_PADMINUS,CSKEY_LEFT,CSKEY_CENTER,CSKEY_RIGHT,CSKEY_PADPLUS,CSKEY_END,// 48..4F
  CSKEY_DOWN,CSKEY_PGDN,CSKEY_INS,CSKEY_DEL,0,      0,        0,        CSKEY_F11,// 50..57
  CSKEY_F12,0,        0,        0,        0,        0,        0,        0,      // 58..5F
  0,        0,        0,        0,        0,        0,        0,        0,      // 60..67
  0,        0,        0,        0,        0,        0,        0,        CSKEY_PADDIV,// 68..6F
  0,        0,        0,        0,        0,        0,        0,        0,      // 70..77
  0,        0,        0,        0,        0,        0,        0,        0       // 78..7F
};

//================================================================== System ====

IMPLEMENT_IBASE_EXT (SysSystemDriver)
  IMPLEMENTS_INTERFACE (iEventPlug)
IMPLEMENT_IBASE_EXT_END

SysSystemDriver::SysSystemDriver () : csSystemDriver ()
{
  // Sanity check
  if (sizeof (event_queue [0]) != 12)
  {
    Printf (MSG_FATAL_ERROR, "ERROR! Your compiler does not handle packed structures!\n");
    Printf (MSG_FATAL_ERROR, "sizeof (event_queue [0]) == %d instead of 12!\n", sizeof (event_queue [0]));
    exit (-1);
  }

  __dpmi_regs regs;
  regs.x.ax = 0x0000;
  __dpmi_int (0x33, &regs);
  MouseExists = !!(regs.x.ax);
  MouseOpened = false;
  EnablePrintf = true;
  EventOutlet = CreateEventOutlet (this);
}

SysSystemDriver::~SysSystemDriver ()
{
  if (EventOutlet)
    EventOutlet->DecRef ();
}

void SysSystemDriver::NextFrame ()
{
  bool ExtKey = false;
  // Fill in events ...
  while (event_queue_tail != event_queue_head)
  {
    switch (event_queue [event_queue_tail].Type)
    {
      case 1:
      {
        int ScanCode = event_queue [event_queue_tail].Keyboard.ScanCode;
        bool Down = (ScanCode < 0x80);

        if ((ScanCode == 0xe0) || (ScanCode == 0xe1))
          ExtKey = true;
        else
        {
          // handle keypad '/'
          if (ExtKey && (ScanCode == 0x35))
            ScanCode = 0x6f;

          ScanCode = ScanCodeToChar [ScanCode & 0x7F];
          if (ScanCode)
            EventOutlet->Key (ScanCode, -1, Down);
        }
        break;
      }
      case 2:
      {
        int Button = event_queue [event_queue_tail].Mouse.Button;
        bool Down = event_queue [event_queue_tail].Mouse.Down;
        int x = event_queue [event_queue_tail].Mouse.x;
        int y = event_queue [event_queue_tail].Mouse.y;

        EventOutlet->Mouse (Button, Down, x, y);
        break;
      }
    } /* endswitch */
    event_queue_tail = (event_queue_tail + 1) & EVENT_QUEUE_MASK;
  } /* endwhile */
}

bool SysSystemDriver::Open (const char *Title)
{
  if (!csSystemDriver::Open (Title))
    return false;

  // Initialize keyboard handler
  if (KH.install ())
    return false;
  // Give us exclusive access of the keyboard.
  KH.chain (0);
  KeyboardOpened = true;

  SensivityFactor = Config->GetFloat ("MouseDriver", "MouseSensivity", 1.0);

  if (MH.install ())
    return false;

  // Query screen size
  int FrameWidth, FrameHeight, Depth;
  bool FullScreen;
  GetSettings (FrameWidth, FrameHeight, Depth, FullScreen);

  // Query mouse sensivity
  __dpmi_regs regs;
  regs.x.ax = 0x1B;
  __dpmi_int (0x33, &regs);
  mouse_sensivity_x = regs.x.bx;
  mouse_sensivity_y = regs.x.cx;
  mouse_sensivity_threshold = regs.x.dx;

  // Compute mouse sensivity
  regs.x.cx = 8;
  regs.x.dx = 8;
  regs.x.ax = 0x0F;
  __dpmi_int (0x33, &regs);
  regs.x.bx = (int) ((50 + FrameWidth / 32) * SensivityFactor);
  regs.x.cx = (int) ((50 + FrameHeight / 24) * SensivityFactor);
  regs.x.dx = MAX (regs.x.bx, regs.x.cx); // ? not sure about this
  regs.x.ax = 0x1A;
  __dpmi_int (0x33, &regs);

  // Set mouse range to full-screen
  regs.x.ax = 0x07;
  regs.x.cx = 0;
  regs.x.dx = FrameWidth - 1;
  __dpmi_int (0x33, &regs);
  regs.x.ax = 0x08;
  regs.x.cx = 0;
  regs.x.dx = FrameHeight - 1;
  __dpmi_int (0x33, &regs);

  // Set mouse to (0, 0)
  regs.x.ax = 0x04;
  regs.x.cx = 0;
  regs.x.dx = 0;
  __dpmi_int (0x33, &regs);

  MouseOpened = true;

  return true;
}

void SysSystemDriver::Close ()
{
  if (KeyboardOpened)
  {
    KH.uninstall ();
    KeyboardOpened = false;
  }

  if (MouseOpened)
  {
    MH.uninstall ();

    // Restore mouse sensivity
    __dpmi_regs regs;
    regs.x.cx = 8;
    regs.x.dx = 16;
    regs.x.ax = 0x0F;
    __dpmi_int (0x33, &regs);
    regs.x.ax = 0x1A;
    regs.x.bx = mouse_sensivity_x;
    regs.x.cx = mouse_sensivity_y;
    regs.x.dx = mouse_sensivity_threshold;
    __dpmi_int (0x33, &regs);

    MouseOpened = false;
  }
}

bool SysSystemDriver::SystemExtension (const char *iCommand, ...)
{
  va_list args;
  va_start (args, iCommand);

  bool rc = true;
  if (!strcmp (iCommand, "SetMousePosition"))
  {
    int x = va_arg (args, int);
    int y = va_arg (args, int);

    if (MouseOpened)
    {
      __dpmi_regs regs;
      regs.x.cx = x;
      regs.x.dx = y;
      regs.x.ax = 0x04;
      __dpmi_int (0x33, &regs);
    }
  }
  else if (!strcmp (iCommand, "EnablePrintf"))
    EnablePrintf = va_arg (args, bool);
  else
    rc = false;

  va_end (args);
  return rc;
}
<|endoftext|>


<commit_before>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#include <boost/make_shared.hpp>

#include <qitype/objecttypebuilder.hpp>
#include "boundobject.hpp"
#include "serverresult.hpp"

qiLogCategory("qimessaging.boundobject");

static const int gObjectOffset = 10;

namespace qi {

  static GenericValuePtr forwardEvent(const GenericFunctionParameters& params,
                                   unsigned int service, unsigned int object,
                                   unsigned int event, TransportSocketPtr client,
                                   ObjectHost* context)
  {
    qi::Message msg;
    msg.setValues(params, context);
    msg.setService(service);
    msg.setFunction(event);
    msg.setType(Message::Type_Event);
    msg.setObject(object);
    client->send(msg);
    return GenericValuePtr();
  }

  ServiceBoundObject::ServiceBoundObject(unsigned int serviceId, unsigned int objectId,
                                         qi::ObjectPtr object,
                                         qi::MetaCallType mct,
                                         bool bindTerminate,
                                         ObjectHost* owner)
    : ObjectHost(serviceId)
    , _links()
    , _serviceId(serviceId)
    , _objectId(objectId)
    , _object(object)
    , _callType(mct)
    , _owner(owner)
  {
    onDestroy.setCallType(MetaCallType_Direct);
    _self = createServiceBoundObjectType(this, bindTerminate);
  }

  ServiceBoundObject::~ServiceBoundObject()
  {
    ObjectHost::clear();
    if (_owner)
      _owner->removeObject(_objectId);
    onDestroy(this);
  }

  qi::ObjectPtr ServiceBoundObject::createServiceBoundObjectType(ServiceBoundObject *self, bool bindTerminate) {
    static qi::ObjectTypeBuilder<ServiceBoundObject>* ob = 0;
    if (!ob)
    {
      ob = new qi::ObjectTypeBuilder<ServiceBoundObject>();
      ob->advertiseMethod("registerEvent"  , &ServiceBoundObject::registerEvent, MetaCallType_Auto, qi::Message::BoundObjectFunction_RegisterEvent);
      ob->advertiseMethod("unregisterEvent", &ServiceBoundObject::unregisterEvent, MetaCallType_Auto, qi::Message::BoundObjectFunction_UnregisterEvent);
      ob->advertiseMethod("metaObject"     , &ServiceBoundObject::metaObject, MetaCallType_Auto, qi::Message::BoundObjectFunction_MetaObject);
      ob->advertiseMethod("terminate",       &ServiceBoundObject::terminate, MetaCallType_Auto, qi::Message::BoundObjectFunction_Terminate);
      ob->advertiseMethod("getProperty",       &ServiceBoundObject::getProperty, MetaCallType_Auto, qi::Message::BoundObjectFunction_GetProperty);
      ob->advertiseMethod("setProperty",       &ServiceBoundObject::setProperty, MetaCallType_Auto, qi::Message::BoundObjectFunction_SetProperty);
      ob->advertiseMethod("properties",       &ServiceBoundObject::properties, MetaCallType_Auto, qi::Message::BoundObjectFunction_Properties);
      //global currentSocket: we are not multithread or async capable ob->setThreadingModel(ObjectThreadingModel_MultiThread);
    }
    ObjectPtr result = ob->object(self);
    return result;
  }

  //Bound Method
  Link ServiceBoundObject::registerEvent(unsigned int objectId, unsigned int eventId, Link remoteLinkId) {
    GenericFunction mc = makeDynamicGenericFunction(boost::bind(&forwardEvent, _1, _serviceId, _objectId, eventId, _currentSocket, this));
    Link linkId = _object->connect(eventId, mc);
    qiLogDebug() << "SBO rl " << remoteLinkId <<" ll " << linkId;
    _links[_currentSocket][remoteLinkId] = RemoteLink(linkId, eventId);
    return linkId;
  }

  //Bound Method
  void ServiceBoundObject::unregisterEvent(unsigned int objectId, unsigned int QI_UNUSED(event), Link remoteLinkId) {
    ServiceLinks&          sl = _links[_currentSocket];
    ServiceLinks::iterator it = sl.find(remoteLinkId);

    if (it == sl.end())
    {
      std::stringstream ss;
      ss << "Unregister request failed for " << remoteLinkId <<" " << objectId;
      qiLogError() << ss.str();
      throw std::runtime_error(ss.str());
    }
    _object->disconnect(it->second.localLinkId);
  }

  //Bound Method
  qi::MetaObject ServiceBoundObject::metaObject(unsigned int objectId) {
    //we inject specials methods here
    return qi::MetaObject::merge(_self->metaObject(), _object->metaObject());
  }

  void ServiceBoundObject::terminate(unsigned int)
  {
    qiLogDebug() << "terminate() received";
    if (_owner)
      _owner->removeObject(_objectId);
    else
      qiLogWarning() << "terminate() received on object without owner";
  }

  void ServiceBoundObject::onMessage(const qi::Message &msg, TransportSocketPtr socket) {
    if (msg.object() > _objectId)
    {
      qiLogDebug() << "onChildMessage " << msg.address();
      ObjectHost::onMessage(msg, socket);
      return;
    }

    qiLogDebug() << "onMessage " << msg.address();
    qi::ObjectPtr    obj;
    unsigned int     funcId;
    //choose between special function (on BoundObject) or normal calls
    if (msg.function() < static_cast<unsigned int>(gObjectOffset)) {
      obj = _self;
    } else {
      obj = _object;
    }
    funcId = msg.function();

    std::string sigparam;
    GenericFunctionParameters mfp;

    if (msg.type() == qi::Message::Type_Call) {
      const qi::MetaMethod *mm = obj->metaObject().method(funcId);
      if (!mm) {
        std::stringstream ss;
        ss << "No such method " << msg.address();
        qiLogError() << ss.str();
        qi::Promise<GenericValuePtr> prom;
        prom.setError(ss.str());
        serverResultAdapter(prom.future(), this, socket, msg.address());
        return;
      }
      sigparam = mm->signature();
    }

    else if (msg.type() == qi::Message::Type_Post) {
      const qi::MetaSignal *ms = obj->metaObject().signal(funcId);
      if (ms)
        sigparam = ms->signature();
      else {
        const qi::MetaMethod *mm = obj->metaObject().method(funcId);
        if (mm)
          sigparam = mm->signature();
        else {
          qiLogError() << "No such signal/method on event message " << msg.address();
          return;
        }
      }
    }
    else
    {
      qiLogError() << "Unexpected message type " << msg.type();
      return;
    }

    sigparam = signatureSplit(sigparam)[2];
    GenericValuePtr value = msg.value(sigparam, socket);
    mfp = value.asTupleValuePtr();
    /* Because of 'global' _currentSocket, we cannot support parallel
    * executions at this point.
    * Both on self, and on obj which can use currentSocket() too.
    *
    * So put a lock, and rely on metaCall we invoke being asynchronous for// execution
    * This is decided by _callType, set from BoundObject ctor argument, passed by Server, which
    * uses its internal _defaultCallType, passed to its constructor, default
    * to queued. When Server is instanciated by ObjectHost, it uses the default
    * value.
    *
    * As a consequence, users of currentSocket() must set _callType to Direct.
    */
    switch (msg.type())
    {
    case Message::Type_Call: {
        boost::mutex::scoped_lock lock(_mutex);
        _currentSocket = socket;
        qi::Future<GenericValuePtr>  fut = obj->metaCall(funcId, mfp,
            obj==_self ? MetaCallType_Direct: _callType);
        _currentSocket.reset();
        fut.connect(boost::bind<void>(&serverResultAdapter, _1, (ObjectHost*)this, socket, msg.address()));
      }
      break;
    case Message::Type_Post: {
        obj->metaPost(funcId, mfp);
      }
      break;
    default:
        qiLogError() << "unknown request of type " << (int)msg.type() << " on service: " << msg.address();
    }
    //########################
    value.destroy();
  }

  void ServiceBoundObject::onSocketDisconnected(TransportSocketPtr client, int error)
  {
    // Disconnect event links set for this client.
    BySocketServiceLinks::iterator it = _links.find(client);
    if (it != _links.end())
    {
      for (ServiceLinks::iterator jt = it->second.begin(); jt != it->second.end(); ++jt)
        _object->disconnect(jt->second.localLinkId);
      _links.erase(it);
    }
  }

  qi::BoundObjectPtr makeServiceBoundObjectPtr(unsigned int serviceId, qi::ObjectPtr object, qi::MetaCallType mct) {
    boost::shared_ptr<ServiceBoundObject> ret = boost::make_shared<ServiceBoundObject>(serviceId, Message::GenericObject_Main, object, mct);
    return ret;
  }

  GenericValue ServiceBoundObject::getProperty(const GenericValue& prop)
  {
    if (prop.kind() == Type::String)
      return _object->getProperty<GenericValue>(prop.toString());
    else if (prop.kind() == Type::Int)
      return _object->type->getProperty(_object->value, prop.toUInt());
    else
      throw std::runtime_error("Expected int or string for property index");
  }

  void ServiceBoundObject::setProperty(const GenericValue& prop, GenericValue val)
  {
    qi::Future<void> result;
    if (prop.kind() == Type::String)
      result = _object->setProperty(prop.toString(), val);
    else if (prop.kind() == Type::Int)
      result = _object->type->setProperty(_object->value, prop.toUInt(), val);
    else
      throw std::runtime_error("Expected int or string for property index");
    if (!result.isFinished())
      qiLogWarning() << "Assertion failed, setProperty() call not finished";
    // Throw the future error
    result.value();
  }

  std::vector<std::string> ServiceBoundObject::properties()
  {
    // FIXME implement
    std::vector<std::string> res;
    const MetaObject& mo = _object->metaObject();
    MetaObject::PropertyMap map = mo.propertyMap();
    for (MetaObject::PropertyMap::iterator it = map.begin(); it != map.end(); ++it)
      res.push_back(it->second.name());
    return res;
  }
}
<commit_msg>Fix include ordering caused by qitype changes.<commit_after>/*
**  Copyright (C) 2012 Aldebaran Robotics
**  See COPYING for the license
*/

#include <boost/make_shared.hpp>

#include <qitype/genericobject.hpp>
#include "boundobject.hpp"
#include "serverresult.hpp"

qiLogCategory("qimessaging.boundobject");

static const int gObjectOffset = 10;

namespace qi {

  static GenericValuePtr forwardEvent(const GenericFunctionParameters& params,
                                   unsigned int service, unsigned int object,
                                   unsigned int event, TransportSocketPtr client,
                                   ObjectHost* context)
  {
    qi::Message msg;
    msg.setValues(params, context);
    msg.setService(service);
    msg.setFunction(event);
    msg.setType(Message::Type_Event);
    msg.setObject(object);
    client->send(msg);
    return GenericValuePtr();
  }

  ServiceBoundObject::ServiceBoundObject(unsigned int serviceId, unsigned int objectId,
                                         qi::ObjectPtr object,
                                         qi::MetaCallType mct,
                                         bool bindTerminate,
                                         ObjectHost* owner)
    : ObjectHost(serviceId)
    , _links()
    , _serviceId(serviceId)
    , _objectId(objectId)
    , _object(object)
    , _callType(mct)
    , _owner(owner)
  {
    onDestroy.setCallType(MetaCallType_Direct);
    _self = createServiceBoundObjectType(this, bindTerminate);
  }

  ServiceBoundObject::~ServiceBoundObject()
  {
    ObjectHost::clear();
    if (_owner)
      _owner->removeObject(_objectId);
    onDestroy(this);
  }

  qi::ObjectPtr ServiceBoundObject::createServiceBoundObjectType(ServiceBoundObject *self, bool bindTerminate) {
    static qi::ObjectTypeBuilder<ServiceBoundObject>* ob = 0;
    if (!ob)
    {
      ob = new qi::ObjectTypeBuilder<ServiceBoundObject>();
      ob->advertiseMethod("registerEvent"  , &ServiceBoundObject::registerEvent, MetaCallType_Auto, qi::Message::BoundObjectFunction_RegisterEvent);
      ob->advertiseMethod("unregisterEvent", &ServiceBoundObject::unregisterEvent, MetaCallType_Auto, qi::Message::BoundObjectFunction_UnregisterEvent);
      ob->advertiseMethod("metaObject"     , &ServiceBoundObject::metaObject, MetaCallType_Auto, qi::Message::BoundObjectFunction_MetaObject);
      ob->advertiseMethod("terminate",       &ServiceBoundObject::terminate, MetaCallType_Auto, qi::Message::BoundObjectFunction_Terminate);
      ob->advertiseMethod("getProperty",       &ServiceBoundObject::getProperty, MetaCallType_Auto, qi::Message::BoundObjectFunction_GetProperty);
      ob->advertiseMethod("setProperty",       &ServiceBoundObject::setProperty, MetaCallType_Auto, qi::Message::BoundObjectFunction_SetProperty);
      ob->advertiseMethod("properties",       &ServiceBoundObject::properties, MetaCallType_Auto, qi::Message::BoundObjectFunction_Properties);
      //global currentSocket: we are not multithread or async capable ob->setThreadingModel(ObjectThreadingModel_MultiThread);
    }
    ObjectPtr result = ob->object(self);
    return result;
  }

  //Bound Method
  Link ServiceBoundObject::registerEvent(unsigned int objectId, unsigned int eventId, Link remoteLinkId) {
    GenericFunction mc = makeDynamicGenericFunction(boost::bind(&forwardEvent, _1, _serviceId, _objectId, eventId, _currentSocket, this));
    Link linkId = _object->connect(eventId, mc);
    qiLogDebug() << "SBO rl " << remoteLinkId <<" ll " << linkId;
    _links[_currentSocket][remoteLinkId] = RemoteLink(linkId, eventId);
    return linkId;
  }

  //Bound Method
  void ServiceBoundObject::unregisterEvent(unsigned int objectId, unsigned int QI_UNUSED(event), Link remoteLinkId) {
    ServiceLinks&          sl = _links[_currentSocket];
    ServiceLinks::iterator it = sl.find(remoteLinkId);

    if (it == sl.end())
    {
      std::stringstream ss;
      ss << "Unregister request failed for " << remoteLinkId <<" " << objectId;
      qiLogError() << ss.str();
      throw std::runtime_error(ss.str());
    }
    _object->disconnect(it->second.localLinkId);
  }

  //Bound Method
  qi::MetaObject ServiceBoundObject::metaObject(unsigned int objectId) {
    //we inject specials methods here
    return qi::MetaObject::merge(_self->metaObject(), _object->metaObject());
  }

  void ServiceBoundObject::terminate(unsigned int)
  {
    qiLogDebug() << "terminate() received";
    if (_owner)
      _owner->removeObject(_objectId);
    else
      qiLogWarning() << "terminate() received on object without owner";
  }

  void ServiceBoundObject::onMessage(const qi::Message &msg, TransportSocketPtr socket) {
    if (msg.object() > _objectId)
    {
      qiLogDebug() << "onChildMessage " << msg.address();
      ObjectHost::onMessage(msg, socket);
      return;
    }

    qiLogDebug() << "onMessage " << msg.address();
    qi::ObjectPtr    obj;
    unsigned int     funcId;
    //choose between special function (on BoundObject) or normal calls
    if (msg.function() < static_cast<unsigned int>(gObjectOffset)) {
      obj = _self;
    } else {
      obj = _object;
    }
    funcId = msg.function();

    std::string sigparam;
    GenericFunctionParameters mfp;

    if (msg.type() == qi::Message::Type_Call) {
      const qi::MetaMethod *mm = obj->metaObject().method(funcId);
      if (!mm) {
        std::stringstream ss;
        ss << "No such method " << msg.address();
        qiLogError() << ss.str();
        qi::Promise<GenericValuePtr> prom;
        prom.setError(ss.str());
        serverResultAdapter(prom.future(), this, socket, msg.address());
        return;
      }
      sigparam = mm->signature();
    }

    else if (msg.type() == qi::Message::Type_Post) {
      const qi::MetaSignal *ms = obj->metaObject().signal(funcId);
      if (ms)
        sigparam = ms->signature();
      else {
        const qi::MetaMethod *mm = obj->metaObject().method(funcId);
        if (mm)
          sigparam = mm->signature();
        else {
          qiLogError() << "No such signal/method on event message " << msg.address();
          return;
        }
      }
    }
    else
    {
      qiLogError() << "Unexpected message type " << msg.type();
      return;
    }

    sigparam = signatureSplit(sigparam)[2];
    GenericValuePtr value = msg.value(sigparam, socket);
    mfp = value.asTupleValuePtr();
    /* Because of 'global' _currentSocket, we cannot support parallel
    * executions at this point.
    * Both on self, and on obj which can use currentSocket() too.
    *
    * So put a lock, and rely on metaCall we invoke being asynchronous for// execution
    * This is decided by _callType, set from BoundObject ctor argument, passed by Server, which
    * uses its internal _defaultCallType, passed to its constructor, default
    * to queued. When Server is instanciated by ObjectHost, it uses the default
    * value.
    *
    * As a consequence, users of currentSocket() must set _callType to Direct.
    */
    switch (msg.type())
    {
    case Message::Type_Call: {
        boost::mutex::scoped_lock lock(_mutex);
        _currentSocket = socket;
        qi::Future<GenericValuePtr>  fut = obj->metaCall(funcId, mfp,
            obj==_self ? MetaCallType_Direct: _callType);
        _currentSocket.reset();
        fut.connect(boost::bind<void>(&serverResultAdapter, _1, (ObjectHost*)this, socket, msg.address()));
      }
      break;
    case Message::Type_Post: {
        obj->metaPost(funcId, mfp);
      }
      break;
    default:
        qiLogError() << "unknown request of type " << (int)msg.type() << " on service: " << msg.address();
    }
    //########################
    value.destroy();
  }

  void ServiceBoundObject::onSocketDisconnected(TransportSocketPtr client, int error)
  {
    // Disconnect event links set for this client.
    BySocketServiceLinks::iterator it = _links.find(client);
    if (it != _links.end())
    {
      for (ServiceLinks::iterator jt = it->second.begin(); jt != it->second.end(); ++jt)
        _object->disconnect(jt->second.localLinkId);
      _links.erase(it);
    }
  }

  qi::BoundObjectPtr makeServiceBoundObjectPtr(unsigned int serviceId, qi::ObjectPtr object, qi::MetaCallType mct) {
    boost::shared_ptr<ServiceBoundObject> ret = boost::make_shared<ServiceBoundObject>(serviceId, Message::GenericObject_Main, object, mct);
    return ret;
  }

  GenericValue ServiceBoundObject::getProperty(const GenericValue& prop)
  {
    if (prop.kind() == Type::String)
      return _object->getProperty<GenericValue>(prop.toString());
    else if (prop.kind() == Type::Int)
      return _object->type->getProperty(_object->value, prop.toUInt());
    else
      throw std::runtime_error("Expected int or string for property index");
  }

  void ServiceBoundObject::setProperty(const GenericValue& prop, GenericValue val)
  {
    qi::Future<void> result;
    if (prop.kind() == Type::String)
      result = _object->setProperty(prop.toString(), val);
    else if (prop.kind() == Type::Int)
      result = _object->type->setProperty(_object->value, prop.toUInt(), val);
    else
      throw std::runtime_error("Expected int or string for property index");
    if (!result.isFinished())
      qiLogWarning() << "Assertion failed, setProperty() call not finished";
    // Throw the future error
    result.value();
  }

  std::vector<std::string> ServiceBoundObject::properties()
  {
    // FIXME implement
    std::vector<std::string> res;
    const MetaObject& mo = _object->metaObject();
    MetaObject::PropertyMap map = mo.propertyMap();
    for (MetaObject::PropertyMap::iterator it = map.begin(); it != map.end(); ++it)
      res.push_back(it->second.name());
    return res;
  }
}
<|endoftext|>


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

#include <map>
#include <string>
#include <tuple>
#include <vector>

#include <llvm/DebugInfo/DWARF/DWARFContext.h>
#include <llvm/DebugInfo/DWARF/DWARFDebugLine.h>
#include <llvm/IR/Module.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCContext.h>
#include <llvm/MC/MCDisassembler/MCDisassembler.h>
#include <llvm/MC/MCInstPrinter.h>
#include <llvm/MC/MCInstrInfo.h>
#include <llvm/MC/MCObjectFileInfo.h>
#include <llvm/MC/MCRegisterInfo.h>
#include <llvm/Support/TargetRegistry.h>

#include "bcc_debug.h"

namespace ebpf {

// ld_pseudo can only be disassembled properly
// in llvm 6.0, so having this workaround now
// until disto llvm versions catch up
#define WORKAROUND_FOR_LD_PSEUDO

using std::get;
using std::map;
using std::string;
using std::tuple;
using std::vector;
using namespace llvm;
using DWARFLineTable = DWARFDebugLine::LineTable;

void SourceDebugger::adjustInstSize(uint64_t &Size, uint8_t byte0,
                                    uint8_t byte1) {
#ifdef WORKAROUND_FOR_LD_PSEUDO
  bool isLittleEndian = mod_->getDataLayout().isLittleEndian();
  if (byte0 == 0x18 && ((isLittleEndian && (byte1 & 0xf) == 0x1) ||
                        (!isLittleEndian && (byte1 & 0xf0) == 0x10)))
    Size = 16;
#endif
}

vector<string> SourceDebugger::buildLineCache() {
  vector<string> LineCache;
  size_t FileBufSize = mod_src_.size();

  for (uint32_t start = 0, end = start; end < FileBufSize; end++)
    if (mod_src_[end] == '\n' || end == FileBufSize - 1 ||
        (mod_src_[end] == '\r' && mod_src_[end + 1] == '\n')) {
      // Not including the endline
      LineCache.push_back(string(mod_src_.substr(start, end - start)));
      if (mod_src_[end] == '\r')
        end++;
      start = end + 1;
    }

  return LineCache;
}

void SourceDebugger::dumpSrcLine(const vector<string> &LineCache,
                                 const string &FileName, uint32_t Line,
                                 uint32_t &CurrentSrcLine,
                                 llvm::raw_ostream &os) {
  if (Line != 0 && Line != CurrentSrcLine && Line < LineCache.size() &&
      FileName == mod_->getSourceFileName()) {
    os << "; " << StringRef(LineCache[Line - 1]).ltrim()
       << format(
              " // Line"
              "%4" PRIu64 "\n",
              Line);
    CurrentSrcLine = Line;
  }
}

void SourceDebugger::getDebugSections(
    StringMap<std::unique_ptr<MemoryBuffer>> &DebugSections) {
  for (auto section : sections_) {
    if (strncmp(section.first.c_str(), ".debug", 6) == 0) {
      StringRef SecData(reinterpret_cast<const char *>(get<0>(section.second)),
                        get<1>(section.second));
      DebugSections[section.first.substr(1)] =
          MemoryBuffer::getMemBufferCopy(SecData);
    }
  }
}

void SourceDebugger::dump() {
  string Error;
  string TripleStr(mod_->getTargetTriple());
  Triple TheTriple(TripleStr);
  const Target *T = TargetRegistry::lookupTarget(TripleStr, Error);
  if (!T) {
    errs() << "Debug Error: cannot get target\n";
    return;
  }

  std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TripleStr));
  if (!MRI) {
    errs() << "Debug Error: cannot get register info\n";
    return;
  }
  std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TripleStr));
  if (!MAI) {
    errs() << "Debug Error: cannot get assembly info\n";
    return;
  }

  MCObjectFileInfo MOFI;
  MCContext Ctx(MAI.get(), MRI.get(), &MOFI, nullptr);
  MOFI.InitMCObjectFileInfo(TheTriple, false, Ctx, false);
  std::unique_ptr<MCSubtargetInfo> STI(
      T->createMCSubtargetInfo(TripleStr, "", ""));

  std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
  MCInstPrinter *IP = T->createMCInstPrinter(TheTriple, 0, *MAI, *MCII, *MRI);
  if (!IP) {
    errs() << "Debug Error: unable to create instruction printer\n";
    return;
  }

  std::unique_ptr<const MCDisassembler> DisAsm(
      T->createMCDisassembler(*STI, Ctx));
  if (!DisAsm) {
    errs() << "Debug Error: no disassembler\n";
    return;
  }

  // Set up the dwarf debug context
  StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
  getDebugSections(DebugSections);
  std::unique_ptr<DWARFContext> DwarfCtx =
      DWARFContext::create(DebugSections, 8);
  if (!DwarfCtx) {
    errs() << "Debug Error: dwarf context creation failed\n";
    return;
  }

  // bcc has only one compilation unit
  // getCompileUnitAtIndex() was gone in llvm 8.0 (https://reviews.llvm.org/D49741)
#if LLVM_MAJOR_VERSION >= 8
  DWARFCompileUnit *CU = cast<DWARFCompileUnit>(DwarfCtx->getUnitAtIndex(0));
#else
  DWARFCompileUnit *CU = DwarfCtx->getCompileUnitAtIndex(0);
#endif
  if (!CU) {
    errs() << "Debug Error: dwarf context failed to get compile unit\n";
    return;
  }

  const DWARFLineTable *LineTable = DwarfCtx->getLineTableForUnit(CU);
  if (!LineTable) {
    errs() << "Debug Error: dwarf context failed to get line table\n";
    return;
  }

  // Build LineCache for later source code printing
  vector<string> LineCache = buildLineCache();

  // Start to disassemble with source code annotation section by section
  for (auto section : sections_)
    if (!strncmp(fn_prefix_.c_str(), section.first.c_str(),
                 fn_prefix_.size())) {
      MCDisassembler::DecodeStatus S;
      MCInst Inst;
      uint64_t Size;
      uint8_t *FuncStart = get<0>(section.second);
      uint64_t FuncSize = get<1>(section.second);
      unsigned SectionID = get<2>(section.second);
      ArrayRef<uint8_t> Data(FuncStart, FuncSize);
      uint32_t CurrentSrcLine = 0;
      string func_name = section.first.substr(fn_prefix_.size());

      errs() << "Disassembly of section " << section.first << ":\n"
             << func_name << ":\n";

      string src_dbg_str;
      llvm::raw_string_ostream os(src_dbg_str);
      for (uint64_t Index = 0; Index < FuncSize; Index += Size) {
        S = DisAsm->getInstruction(Inst, Size, Data.slice(Index), Index,
                                   nulls(), nulls());
        if (S != MCDisassembler::Success) {
          os << "Debug Error: disassembler failed: " << std::to_string(S)
             << '\n';
          break;
        } else {
          DILineInfo LineInfo;

          LineTable->getFileLineInfoForAddress(
#if LLVM_MAJOR_VERSION >= 9
              {(uint64_t)FuncStart + Index, SectionID},
#else
              (uint64_t)FuncStart + Index,
#endif
              CU->getCompilationDir(),
              DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
              LineInfo);

          adjustInstSize(Size, Data[Index], Data[Index + 1]);
          dumpSrcLine(LineCache, LineInfo.FileName, LineInfo.Line,
                      CurrentSrcLine, os);
          os << format("%4" PRIu64 ":", Index >> 3) << '\t';
          dumpBytes(Data.slice(Index, Size), os);
          IP->printInst(&Inst, os, "", *STI);
          os << '\n';
        }
      }
      os.flush();
      errs() << src_dbg_str << '\n';
      src_dbg_fmap_[func_name] = src_dbg_str;
    }
}

}  // namespace ebpf
<commit_msg>cc: Fix compile warning (#2346)<commit_after>/*
 * Copyright (c) 2017 Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <map>
#include <string>
#include <tuple>
#include <vector>

#include <llvm/DebugInfo/DWARF/DWARFContext.h>
#include <llvm/DebugInfo/DWARF/DWARFDebugLine.h>
#include <llvm/IR/Module.h>
#include <llvm/MC/MCAsmInfo.h>
#include <llvm/MC/MCContext.h>
#include <llvm/MC/MCDisassembler/MCDisassembler.h>
#include <llvm/MC/MCInstPrinter.h>
#include <llvm/MC/MCInstrInfo.h>
#include <llvm/MC/MCObjectFileInfo.h>
#include <llvm/MC/MCRegisterInfo.h>
#include <llvm/Support/TargetRegistry.h>

#include "bcc_debug.h"

namespace ebpf {

// ld_pseudo can only be disassembled properly
// in llvm 6.0, so having this workaround now
// until disto llvm versions catch up
#define WORKAROUND_FOR_LD_PSEUDO

using std::get;
using std::map;
using std::string;
using std::tuple;
using std::vector;
using namespace llvm;
using DWARFLineTable = DWARFDebugLine::LineTable;

void SourceDebugger::adjustInstSize(uint64_t &Size, uint8_t byte0,
                                    uint8_t byte1) {
#ifdef WORKAROUND_FOR_LD_PSEUDO
  bool isLittleEndian = mod_->getDataLayout().isLittleEndian();
  if (byte0 == 0x18 && ((isLittleEndian && (byte1 & 0xf) == 0x1) ||
                        (!isLittleEndian && (byte1 & 0xf0) == 0x10)))
    Size = 16;
#endif
}

vector<string> SourceDebugger::buildLineCache() {
  vector<string> LineCache;
  size_t FileBufSize = mod_src_.size();

  for (uint32_t start = 0, end = start; end < FileBufSize; end++)
    if (mod_src_[end] == '\n' || end == FileBufSize - 1 ||
        (mod_src_[end] == '\r' && mod_src_[end + 1] == '\n')) {
      // Not including the endline
      LineCache.push_back(string(mod_src_.substr(start, end - start)));
      if (mod_src_[end] == '\r')
        end++;
      start = end + 1;
    }

  return LineCache;
}

void SourceDebugger::dumpSrcLine(const vector<string> &LineCache,
                                 const string &FileName, uint32_t Line,
                                 uint32_t &CurrentSrcLine,
                                 llvm::raw_ostream &os) {
  if (Line != 0 && Line != CurrentSrcLine && Line < LineCache.size() &&
      FileName == mod_->getSourceFileName()) {
    os << "; " << StringRef(LineCache[Line - 1]).ltrim()
       << format(
              " // Line"
              "%4" PRIu64 "\n",
              Line);
    CurrentSrcLine = Line;
  }
}

void SourceDebugger::getDebugSections(
    StringMap<std::unique_ptr<MemoryBuffer>> &DebugSections) {
  for (auto section : sections_) {
    if (strncmp(section.first.c_str(), ".debug", 6) == 0) {
      StringRef SecData(reinterpret_cast<const char *>(get<0>(section.second)),
                        get<1>(section.second));
      DebugSections[section.first.substr(1)] =
          MemoryBuffer::getMemBufferCopy(SecData);
    }
  }
}

void SourceDebugger::dump() {
  string Error;
  string TripleStr(mod_->getTargetTriple());
  Triple TheTriple(TripleStr);
  const Target *T = TargetRegistry::lookupTarget(TripleStr, Error);
  if (!T) {
    errs() << "Debug Error: cannot get target\n";
    return;
  }

  std::unique_ptr<MCRegisterInfo> MRI(T->createMCRegInfo(TripleStr));
  if (!MRI) {
    errs() << "Debug Error: cannot get register info\n";
    return;
  }
  std::unique_ptr<MCAsmInfo> MAI(T->createMCAsmInfo(*MRI, TripleStr));
  if (!MAI) {
    errs() << "Debug Error: cannot get assembly info\n";
    return;
  }

  MCObjectFileInfo MOFI;
  MCContext Ctx(MAI.get(), MRI.get(), &MOFI, nullptr);
  MOFI.InitMCObjectFileInfo(TheTriple, false, Ctx, false);
  std::unique_ptr<MCSubtargetInfo> STI(
      T->createMCSubtargetInfo(TripleStr, "", ""));

  std::unique_ptr<MCInstrInfo> MCII(T->createMCInstrInfo());
  MCInstPrinter *IP = T->createMCInstPrinter(TheTriple, 0, *MAI, *MCII, *MRI);
  if (!IP) {
    errs() << "Debug Error: unable to create instruction printer\n";
    return;
  }

  std::unique_ptr<const MCDisassembler> DisAsm(
      T->createMCDisassembler(*STI, Ctx));
  if (!DisAsm) {
    errs() << "Debug Error: no disassembler\n";
    return;
  }

  // Set up the dwarf debug context
  StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
  getDebugSections(DebugSections);
  std::unique_ptr<DWARFContext> DwarfCtx =
      DWARFContext::create(DebugSections, 8);
  if (!DwarfCtx) {
    errs() << "Debug Error: dwarf context creation failed\n";
    return;
  }

  // bcc has only one compilation unit
  // getCompileUnitAtIndex() was gone in llvm 8.0 (https://reviews.llvm.org/D49741)
#if LLVM_MAJOR_VERSION >= 8
  DWARFCompileUnit *CU = cast<DWARFCompileUnit>(DwarfCtx->getUnitAtIndex(0));
#else
  DWARFCompileUnit *CU = DwarfCtx->getCompileUnitAtIndex(0);
#endif
  if (!CU) {
    errs() << "Debug Error: dwarf context failed to get compile unit\n";
    return;
  }

  const DWARFLineTable *LineTable = DwarfCtx->getLineTableForUnit(CU);
  if (!LineTable) {
    errs() << "Debug Error: dwarf context failed to get line table\n";
    return;
  }

  // Build LineCache for later source code printing
  vector<string> LineCache = buildLineCache();

  // Start to disassemble with source code annotation section by section
  for (auto section : sections_)
    if (!strncmp(fn_prefix_.c_str(), section.first.c_str(),
                 fn_prefix_.size())) {
      MCDisassembler::DecodeStatus S;
      MCInst Inst;
      uint64_t Size;
      uint8_t *FuncStart = get<0>(section.second);
      uint64_t FuncSize = get<1>(section.second);
#if LLVM_MAJOR_VERSION >= 9
      unsigned SectionID = get<2>(section.second);
#endif
      ArrayRef<uint8_t> Data(FuncStart, FuncSize);
      uint32_t CurrentSrcLine = 0;
      string func_name = section.first.substr(fn_prefix_.size());

      errs() << "Disassembly of section " << section.first << ":\n"
             << func_name << ":\n";

      string src_dbg_str;
      llvm::raw_string_ostream os(src_dbg_str);
      for (uint64_t Index = 0; Index < FuncSize; Index += Size) {
        S = DisAsm->getInstruction(Inst, Size, Data.slice(Index), Index,
                                   nulls(), nulls());
        if (S != MCDisassembler::Success) {
          os << "Debug Error: disassembler failed: " << std::to_string(S)
             << '\n';
          break;
        } else {
          DILineInfo LineInfo;

          LineTable->getFileLineInfoForAddress(
#if LLVM_MAJOR_VERSION >= 9
              {(uint64_t)FuncStart + Index, SectionID},
#else
              (uint64_t)FuncStart + Index,
#endif
              CU->getCompilationDir(),
              DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
              LineInfo);

          adjustInstSize(Size, Data[Index], Data[Index + 1]);
          dumpSrcLine(LineCache, LineInfo.FileName, LineInfo.Line,
                      CurrentSrcLine, os);
          os << format("%4" PRIu64 ":", Index >> 3) << '\t';
          dumpBytes(Data.slice(Index, Size), os);
          IP->printInst(&Inst, os, "", *STI);
          os << '\n';
        }
      }
      os.flush();
      errs() << src_dbg_str << '\n';
      src_dbg_fmap_[func_name] = src_dbg_str;
    }
}

}  // namespace ebpf
<|endoftext|>