<commit_before>#include "mitkImageMapper2D.h"
//#include "mitkRenderWindow.h"
#include "widget.h"
#include "picimage.h"
#include "pic2vtk.h"
#include "mitkPlaneGeometry.h"
#include "mitkBaseRenderer.h"
#include "mitkDataTreeNode.h"

#include "mitkLookupTableProperty.h"
#include "mitkBoolProperty.h"
#include "mitkLevelWindowProperty.h"

#include "mitkRenderWindow.h"
#include "mitkAbstractTransformGeometry.h"

#include <vtkImageReslice.h>
#include <vtkTransform.h>
#include <vtkMatrix4x4.h>
#include <vtkLookupTable.h>

int mitk::ImageMapper2D::numRenderer = 0;

mitk::ImageMapper2D::ImageMapper2D() : m_SliceSelector(NULL)
{
  // Modify superclass default values, can be overridden by subclasses
  this->SetNumberOfRequiredInputs(1);

  m_SliceSelector = ImageSliceSelector::New();
  m_Reslicer = vtkImageReslice::New();

}

//##ModelId=3E32DCF60043
mitk::ImageMapper2D::~ImageMapper2D()
{
  //@FIXME: durch die folgende Zeile sollte doch wohl der desctructor von RendererInfo aufgerufen werden. Das passiert aber nie. Deshalb wird bei der Programm-Beendung auch das iilImage und damit die textur nicht rechtzeitig freigegeben und das Programm crashed.
  m_RendererInfo.clear();
}

//##ModelId=3E3D834B003A
void mitk::ImageMapper2D::GenerateData()
{

}

void mitk::ImageMapper2D::Paint(mitk::BaseRenderer * renderer)
{
  if(IsVisible(renderer)==false) return;

  RendererInfo& renderinfo=m_RendererInfo[renderer];
  iilPicImage*& image = renderinfo.m_iilImage;

  Update(renderer);

  const mitk::DisplayGeometry* displayGeometry = renderer->GetDisplayGeometry();

  Vector2D oldtopLeft=displayGeometry->GetOriginInUnits();
  Vector2D oldbottomRight=displayGeometry->GetOriginInUnits()+displayGeometry->GetSizeInUnits();

  Vector2D topLeft;
  Vector2D bottomRight;
  topLeft=displayGeometry->GetOriginInDisplayUnits();
  bottomRight=topLeft+displayGeometry->GetSizeInDisplayUnits();

  displayGeometry->DisplayToMM(topLeft, topLeft); topLeft.x*=renderinfo.m_PixelsPerMM.x;  topLeft.y*=renderinfo.m_PixelsPerMM.y;
  displayGeometry->DisplayToMM(bottomRight, bottomRight); bottomRight.x*=renderinfo.m_PixelsPerMM.x;  bottomRight.y*=renderinfo.m_PixelsPerMM.y;

  //test - small differences noticed for unisotropic datasets.
  if((Vector2D(oldtopLeft-topLeft).length()>0.1) || (Vector2D(oldbottomRight-bottomRight).length()>0.1))
  {
    bottomRight*=1.0;
  }

  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  gluOrtho2D(topLeft.x, bottomRight.x, topLeft.y, bottomRight.y );
  glMatrixMode( GL_MODELVIEW );

  GLdouble eqn0[4] = {0.0, 1.0, 0.0, 0.0};
  GLdouble eqn1[4] = {1.0, 0.0, 0.0, 0.0};
  GLdouble eqn2[4] = {-1.0, 0.0 , 0.0, image->width()};
  GLdouble eqn3[4] = {0, -1.0, 0.0, image->height() };

  glClipPlane (GL_CLIP_PLANE0, eqn0);
  glEnable (GL_CLIP_PLANE0);
  glClipPlane (GL_CLIP_PLANE1, eqn1);
  glEnable (GL_CLIP_PLANE1);
  glClipPlane (GL_CLIP_PLANE2, eqn2);
  glEnable (GL_CLIP_PLANE2);
  glClipPlane (GL_CLIP_PLANE3, eqn3);
  glEnable (GL_CLIP_PLANE3);

  image->display(renderer->GetRenderWindow());

  glDisable (GL_CLIP_PLANE0);
  glDisable (GL_CLIP_PLANE1);
  glDisable (GL_CLIP_PLANE2);
  glDisable (GL_CLIP_PLANE3);

  glPushMatrix ();
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  gluOrtho2D(0, displayGeometry->GetDisplayWidth(), 0, displayGeometry->GetDisplayHeight() );
  glMatrixMode( GL_MODELVIEW );
  glPopMatrix ();
}

//##ModelId=3E3D834B0008
const mitk::ImageMapper2D::InputImageType *mitk::ImageMapper2D::GetInput(void)
{
  if (this->GetNumberOfInputs() < 1)
  {
    return 0;
  }

  return static_cast<const mitk::ImageMapper2D::InputImageType * >
    ( GetData() );
}

//##ModelId=3E6E83B00343
int mitk::ImageMapper2D::GetAssociatedChannelNr(mitk::BaseRenderer *renderer)
{
  RendererInfo& renderinfo=m_RendererInfo[renderer];
  if(renderinfo.m_RendererId < 0)
    renderinfo.m_RendererId = ImageMapper2D::numRenderer++;

  return renderinfo.m_RendererId;
}

//##ModelId=3E8607D20380
void mitk::ImageMapper2D::GenerateOutputInformation()
{
  mitk::Image::Pointer output = this->GetOutput();
  mitk::PixelType pt(typeid(int));
  unsigned int dim[]={256,256};
  output->Initialize(mitk::PixelType(typeid(short int)), 2, dim, 10);
}

//##ModelId=3ED932B00140
void mitk::ImageMapper2D::GenerateData(mitk::BaseRenderer *renderer)
{
  RendererInfo& renderinfo=m_RendererInfo[renderer];

  iilPicImage*& image = renderinfo.m_iilImage;

  mitk::Image::Pointer input  = const_cast<mitk::ImageMapper2D::InputImageType *>(this->GetInput());

  if(image!= NULL)
  {
    delete image;
    image = NULL;
  }

  if(renderinfo.m_Pic)
  {
    ipPicFree(renderinfo.m_Pic);
    renderinfo.m_Pic = NULL;
  }

  if(renderinfo.m_RendererId < 0)
    renderinfo.m_RendererId = ImageMapper2D::numRenderer++;

  if(input.IsNotNull())
  {
    vtkImageData* inputData = input->GetVtkImageData();
    const PlaneView* planeview=NULL;

    const Geometry2D* worldgeometry = renderer->GetWorldGeometry();

    if(dynamic_cast<const PlaneGeometry *>(worldgeometry)!=NULL)
    {
      planeview=&dynamic_cast<const PlaneGeometry *>(worldgeometry)->GetPlaneView();
      m_Reslicer->SetResliceTransform(NULL);
    }
    else
      if(dynamic_cast<const AbstractTransformGeometry *>(worldgeometry)!=NULL)
      {
        const AbstractTransformGeometry *abstractGeometry=dynamic_cast<const AbstractTransformGeometry *>(worldgeometry);
        planeview=&abstractGeometry->GetPlaneView();
        m_Reslicer->SetResliceTransform(abstractGeometry->GetVtkAbstractTransform());
        //m_Reslicer->DebugOn();
      }
      else
        return;

    assert(planeview!=NULL);
    assert(planeview->normal.length()>0.1);

    vtkMatrix4x4* geometry = vtkMatrix4x4::New();
    geometry->Identity();

    m_Reslicer->SetInput(inputData);
    m_Reslicer->SetOutputDimensionality(2);
    m_Reslicer->SetOutputOrigin(0,0,0);

    m_Reslicer->SetBackgroundLevel(-1024);

    int width, height;
    width=worldgeometry->GetWidthInUnits();
    height=worldgeometry->GetHeightInUnits();
    renderinfo.m_PixelsPerMM.set(planeview->getLengthOfOrientation1()/width, planeview->getLengthOfOrientation2()/height);

    m_Reslicer->SetOutputSpacing(renderinfo.m_PixelsPerMM.x, renderinfo.m_PixelsPerMM.y, 1.0);
    m_Reslicer->SetOutputExtent(0, width-1, 0, height-1, 0, 1);

    double origin[3];
    origin[0]=planeview->point.x;
    origin[1]=planeview->point.y;
    origin[2]=planeview->point.z;

    m_Reslicer->SetResliceAxes(geometry);
    m_Reslicer->SetResliceAxesOrigin(origin);
    //        m_Reslicer->SetInterpolationModeToLinear();
    double cosines[9];
    Vector3f orient1 = planeview->getOrientation1();
    orient1.normalize();

    Vector3f orient2 = planeview->getOrientation2();
    orient2.normalize();

    // Richtung der X-Achse der Ergebnisschicht im Volumen,
    cosines[0]=orient1.x;
    cosines[1]=orient1.y;
    cosines[2]=orient1.z;

    //Richtung der Y-Achse der Ergebnisschicht im Volumen
    cosines[3]=orient2.x;
    cosines[4]=orient2.y;
    cosines[5]=orient2.z;

    // Schichtfolge/Projektionsrichtung
    cosines[6]= planeview->normal.x;
    cosines[7]= planeview->normal.y;
    cosines[8]= planeview->normal.z;
    m_Reslicer->SetResliceAxesDirectionCosines(cosines);

    m_Reslicer->Update();

    vtkImageData* vtkoutput = m_Reslicer->GetOutput();

    assert(vtkoutput);

    //	std::cout << vtkoutput <<std::endl;
    ipPicDescriptor* pic = Pic2vtk::convert(vtkoutput);
    assert(pic);
    if(pic->dim==1)
    {
      pic->dim=2;
      pic->n[1]=1;
    }
    assert(pic->dim == 2);

    renderinfo.m_Pic = pic;

    //std::cout << "Pic dimensions:" << pic->dim << std::endl;

    image = new iilPicImage(NULL, "ll", 512);

    ApplyProperties(renderer);
//   image->setImage(pic, iilImage::INTENSITY_ALPHA);
	  image->setImage(pic, m_iilMode);
    image->setInterpolation(true);
    image->setRegion(0,0,pic->n[0],pic->n[1]);

    mitk::Image::Pointer output = this->GetOutput();

    //if(renderinfo.m_RendererId < 10)
    //	output->SetPicSlice(pic,0,0,renderinfo.m_RendererId);
    output->Modified();
    renderinfo.m_LastUpdateTime=output->GetMTime();
  }
  return;
}

void mitk::ImageMapper2D::GenerateAllData()
{
  std::map<mitk::BaseRenderer*,RendererInfo>::iterator it=m_RendererInfo.begin();
  for(;it!=m_RendererInfo.end();++it)
    Update(it->first);
}

void mitk::ImageMapper2D::ApplyProperties(mitk::BaseRenderer* renderer)
{
  RendererInfo& renderinfo=m_RendererInfo[renderer];
  iilPicImage*& image = renderinfo.m_iilImage;

  assert(image != NULL);

  float rgba[4]={1.0f,1.0f,1.0f,1.0f};
  // check for color prop and use it for rendering if it exists
  GetColor(rgba, renderer);
  // check for opacity prop and use it for rendering if it exists
  GetOpacity(rgba[3], renderer);

  mitk::LevelWindow levelWindow;
  // check for level window prop and use it for display if it exists
  GetLevelWindow(levelWindow, renderer);

  mitk::LookupTableProperty::Pointer LookupTable;
  LookupTable = dynamic_cast<mitk::LookupTableProperty*>(this->GetDataTreeNode()->GetProperty("LookupTable").GetPointer());
	if (LookupTable.IsNull() )
	{
		m_iilMode = iilImage::INTENSITY_ALPHA;
	  image->setColor(rgba[0], rgba[1], rgba[2], rgba[3]);
	}
	else {
		m_iilMode = iilImage::COLOR_ALPHA;
		image->setColors(LookupTable->GetLookupTable().GetRawLookupTable());
	}

  mitk::BoolProperty::Pointer binary;
  binary = dynamic_cast<mitk::BoolProperty*>(this->GetDataTreeNode()->GetProperty("binary").GetPointer());

  mitk::LevelWindowProperty::Pointer overwriteLevelWindow;
  overwriteLevelWindow = dynamic_cast<mitk::LevelWindowProperty*>(this->GetDataTreeNode()->GetProperty("levelWindow").GetPointer());

  if (binary.IsNotNull() )
  {
    image->setExtrema(0, 1);
  }
  else if (overwriteLevelWindow.IsNotNull() )
  {
    image->setExtrema(overwriteLevelWindow->GetLevelWindow().GetMin(), overwriteLevelWindow->GetLevelWindow().GetMax());
  }
  else
  {
  // set the properties
    image->setExtrema(levelWindow.GetMin(), levelWindow.GetMax());
  }
//  image->setColor(rgba[0], rgba[1], rgba[2], rgba[3]);
}

void mitk::ImageMapper2D::Update(mitk::BaseRenderer* renderer)
{

  RendererInfo& renderinfo=m_RendererInfo[renderer];
  DataTreeNode* node=GetDataTreeNode();
  iilPicImage*& image = renderinfo.m_iilImage;

  if(
      (image == NULL) ||
      (renderinfo.m_RendererId < 0) ||
      (renderinfo.m_LastUpdateTime < node->GetMTime()) ||
      (renderinfo.m_LastUpdateTime < renderer->GetWorldGeometryUpdateTime()) ||
      (renderinfo.m_LastUpdateTime < renderer->GetDisplayGeometryUpdateTime())
    )
    GenerateData(renderer);
  else
  if(
      (renderinfo.m_LastUpdateTime < renderer->GetWorldGeometry()->GetMTime())
      //&&
      //(renderinfo.m_LastUpdateTime < renderer->GetMTime())
    )
    GenerateData(renderer);
  else
  if(
      (renderinfo.m_LastUpdateTime < node->GetPropertyList()->GetMTime()) ||
      (renderinfo.m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime())
    )
  {
    ApplyProperties(renderer);
    // since we have checked that nothing important has changed, we can set m_LastUpdateTime
    // to the current time
    mitk::Image::Pointer output = this->GetOutput();
    output->Modified();
    renderinfo.m_LastUpdateTime=output->GetMTime();
  }
}
<commit_msg>fixed bug concerning correct positioning of non-isotropic/non-1pixel==1mm-data.<commit_after>#include "mitkImageMapper2D.h"
//#include "mitkRenderWindow.h"
#include "widget.h"
#include "picimage.h"
#include "pic2vtk.h"
#include "mitkPlaneGeometry.h"
#include "mitkBaseRenderer.h"
#include "mitkDataTreeNode.h"

#include "mitkLookupTableProperty.h"
#include "mitkBoolProperty.h"
#include "mitkLevelWindowProperty.h"

#include "mitkRenderWindow.h"
#include "mitkAbstractTransformGeometry.h"

#include <vtkImageReslice.h>
#include <vtkTransform.h>
#include <vtkMatrix4x4.h>
#include <vtkLookupTable.h>

int mitk::ImageMapper2D::numRenderer = 0;

mitk::ImageMapper2D::ImageMapper2D() : m_SliceSelector(NULL)
{
  // Modify superclass default values, can be overridden by subclasses
  this->SetNumberOfRequiredInputs(1);

  m_SliceSelector = ImageSliceSelector::New();
  m_Reslicer = vtkImageReslice::New();

}

//##ModelId=3E32DCF60043
mitk::ImageMapper2D::~ImageMapper2D()
{
  //@FIXME: durch die folgende Zeile sollte doch wohl der desctructor von RendererInfo aufgerufen werden. Das passiert aber nie. Deshalb wird bei der Programm-Beendung auch das iilImage und damit die textur nicht rechtzeitig freigegeben und das Programm crashed.
  m_RendererInfo.clear();
}

//##ModelId=3E3D834B003A
void mitk::ImageMapper2D::GenerateData()
{

}

void mitk::ImageMapper2D::Paint(mitk::BaseRenderer * renderer)
{
  if(IsVisible(renderer)==false) return;

  RendererInfo& renderinfo=m_RendererInfo[renderer];
  iilPicImage*& image = renderinfo.m_iilImage;

  Update(renderer);

  const mitk::DisplayGeometry* displayGeometry = renderer->GetDisplayGeometry();

  Vector2D oldtopLeft=displayGeometry->GetOriginInUnits();
  Vector2D oldbottomRight=displayGeometry->GetOriginInUnits()+displayGeometry->GetSizeInUnits();

  Vector2D topLeft;
  Vector2D bottomRight;
  topLeft=displayGeometry->GetOriginInDisplayUnits();
  bottomRight=topLeft+displayGeometry->GetSizeInDisplayUnits();

  displayGeometry->DisplayToMM(topLeft, topLeft); topLeft.x*=renderinfo.m_PixelsPerMM.x;  topLeft.y*=renderinfo.m_PixelsPerMM.y;
  displayGeometry->DisplayToMM(bottomRight, bottomRight); bottomRight.x*=renderinfo.m_PixelsPerMM.x;  bottomRight.y*=renderinfo.m_PixelsPerMM.y;

  //test - small differences noticed for unisotropic datasets.
  if((Vector2D(oldtopLeft-topLeft).length()>0.1) || (Vector2D(oldbottomRight-bottomRight).length()>0.1))
  {
    itkWarningMacro("oldtopLeft!=topLeft in ImageMapper2D");
  }

  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  gluOrtho2D(topLeft.x, bottomRight.x, topLeft.y, bottomRight.y );
  glMatrixMode( GL_MODELVIEW );

  GLdouble eqn0[4] = {0.0, 1.0, 0.0, 0.0};
  GLdouble eqn1[4] = {1.0, 0.0, 0.0, 0.0};
  GLdouble eqn2[4] = {-1.0, 0.0 , 0.0, image->width()};
  GLdouble eqn3[4] = {0, -1.0, 0.0, image->height() };

  glClipPlane (GL_CLIP_PLANE0, eqn0);
  glEnable (GL_CLIP_PLANE0);
  glClipPlane (GL_CLIP_PLANE1, eqn1);
  glEnable (GL_CLIP_PLANE1);
  glClipPlane (GL_CLIP_PLANE2, eqn2);
  glEnable (GL_CLIP_PLANE2);
  glClipPlane (GL_CLIP_PLANE3, eqn3);
  glEnable (GL_CLIP_PLANE3);

  image->display(renderer->GetRenderWindow());

  glDisable (GL_CLIP_PLANE0);
  glDisable (GL_CLIP_PLANE1);
  glDisable (GL_CLIP_PLANE2);
  glDisable (GL_CLIP_PLANE3);

  glPushMatrix ();
  glMatrixMode (GL_PROJECTION);
  glLoadIdentity ();
  gluOrtho2D(0, displayGeometry->GetDisplayWidth(), 0, displayGeometry->GetDisplayHeight() );
  glMatrixMode( GL_MODELVIEW );
  glPopMatrix ();
}

//##ModelId=3E3D834B0008
const mitk::ImageMapper2D::InputImageType *mitk::ImageMapper2D::GetInput(void)
{
  if (this->GetNumberOfInputs() < 1)
  {
    return 0;
  }

  return static_cast<const mitk::ImageMapper2D::InputImageType * >
    ( GetData() );
}

//##ModelId=3E6E83B00343
int mitk::ImageMapper2D::GetAssociatedChannelNr(mitk::BaseRenderer *renderer)
{
  RendererInfo& renderinfo=m_RendererInfo[renderer];
  if(renderinfo.m_RendererId < 0)
    renderinfo.m_RendererId = ImageMapper2D::numRenderer++;

  return renderinfo.m_RendererId;
}

//##ModelId=3E8607D20380
void mitk::ImageMapper2D::GenerateOutputInformation()
{
  mitk::Image::Pointer output = this->GetOutput();
  mitk::PixelType pt(typeid(int));
  unsigned int dim[]={256,256};
  output->Initialize(mitk::PixelType(typeid(short int)), 2, dim, 10);
}

//##ModelId=3ED932B00140
void mitk::ImageMapper2D::GenerateData(mitk::BaseRenderer *renderer)
{
  RendererInfo& renderinfo=m_RendererInfo[renderer];

  iilPicImage*& image = renderinfo.m_iilImage;

  mitk::Image::Pointer input  = const_cast<mitk::ImageMapper2D::InputImageType *>(this->GetInput());

  if(image!= NULL)
  {
    delete image;
    image = NULL;
  }

  if(renderinfo.m_Pic)
  {
    ipPicFree(renderinfo.m_Pic);
    renderinfo.m_Pic = NULL;
  }

  if(renderinfo.m_RendererId < 0)
    renderinfo.m_RendererId = ImageMapper2D::numRenderer++;

  if(input.IsNotNull())
  {
    vtkImageData* inputData = input->GetVtkImageData();
    const PlaneView* planeview=NULL;

    const Geometry2D* worldgeometry = renderer->GetWorldGeometry();

    if(dynamic_cast<const PlaneGeometry *>(worldgeometry)!=NULL)
    {
      planeview=&dynamic_cast<const PlaneGeometry *>(worldgeometry)->GetPlaneView();
      m_Reslicer->SetResliceTransform(NULL);
    }
    else
      if(dynamic_cast<const AbstractTransformGeometry *>(worldgeometry)!=NULL)
      {
        const AbstractTransformGeometry *abstractGeometry=dynamic_cast<const AbstractTransformGeometry *>(worldgeometry);
        planeview=&abstractGeometry->GetPlaneView();
        m_Reslicer->SetResliceTransform(abstractGeometry->GetVtkAbstractTransform());
        //m_Reslicer->DebugOn();
      }
      else
        return;

    assert(planeview!=NULL);
    assert(planeview->normal.length()>0.1);

    vtkMatrix4x4* geometry = vtkMatrix4x4::New();
    geometry->Identity();

    m_Reslicer->SetInput(inputData);
    m_Reslicer->SetOutputDimensionality(2);
    m_Reslicer->SetOutputOrigin(0,0,0);

    m_Reslicer->SetBackgroundLevel(-1024);

    //let's define how many pixels we really want to sample: width x height pixels
    int width, height;
    //let's use the values of worldgeometry->GetWidthInUnits() and worldgeometry->GetHeightInUnits() for that purpose
    //maybe it is useful to add here a more sophisticated rule that depends on the actual size of the current display, so not to
    //sample 1000x1000 pixels for a display of 10x10 pixels
    width=worldgeometry->GetWidthInUnits();
    height=worldgeometry->GetHeightInUnits();
    renderinfo.m_PixelsPerMM.set(width/planeview->getLengthOfOrientation1(), height/planeview->getLengthOfOrientation2());

    m_Reslicer->SetOutputSpacing(1.0/renderinfo.m_PixelsPerMM.x, 1.0/renderinfo.m_PixelsPerMM.y, 1.0);
    m_Reslicer->SetOutputExtent(0, width-1, 0, height-1, 0, 1);

    //calulate the origin and the orientations for the reslice-filter
    double origin[3];
    vec2vtk(planeview->point, origin);

    m_Reslicer->SetResliceAxes(geometry);
    m_Reslicer->SetResliceAxesOrigin(origin);
    //        m_Reslicer->SetInterpolationModeToLinear();
    double cosines[9];
    Vector3f orient1 = planeview->getOrientation1();
    orient1.normalize();

    Vector3f orient2 = planeview->getOrientation2();
    orient2.normalize();

    // direction of the X-axis of the sampled result
    vec2vtk(orient1, cosines);

    // direction of the Y-axis of the sampled result
    vec2vtk(orient2, cosines+3);

    // normal of the plane
    vec2vtk(planeview->normal, cosines+6);

    m_Reslicer->SetResliceAxesDirectionCosines(cosines);

    //do the reslicing
    m_Reslicer->Update();

    vtkImageData* vtkoutput = m_Reslicer->GetOutput();

    assert(vtkoutput);

    //	std::cout << vtkoutput <<std::endl;
    ipPicDescriptor* pic = Pic2vtk::convert(vtkoutput);
    assert(pic);
    if(pic->dim==1)
    {
      pic->dim=2;
      pic->n[1]=1;
    }
    assert(pic->dim == 2);

    renderinfo.m_Pic = pic;

    //std::cout << "Pic dimensions:" << pic->dim << std::endl;

    image = new iilPicImage(NULL, "ll", 512);

    ApplyProperties(renderer);
//   image->setImage(pic, iilImage::INTENSITY_ALPHA);
	  image->setImage(pic, m_iilMode);
    image->setInterpolation(true);
    image->setRegion(0,0,pic->n[0],pic->n[1]);

    mitk::Image::Pointer output = this->GetOutput();

    //if(renderinfo.m_RendererId < 10)
    //	output->SetPicSlice(pic,0,0,renderinfo.m_RendererId);
    output->Modified();
    renderinfo.m_LastUpdateTime=output->GetMTime();
  }
  return;
}

void mitk::ImageMapper2D::GenerateAllData()
{
  std::map<mitk::BaseRenderer*,RendererInfo>::iterator it=m_RendererInfo.begin();
  for(;it!=m_RendererInfo.end();++it)
    Update(it->first);
}

void mitk::ImageMapper2D::ApplyProperties(mitk::BaseRenderer* renderer)
{
  RendererInfo& renderinfo=m_RendererInfo[renderer];
  iilPicImage*& image = renderinfo.m_iilImage;

  assert(image != NULL);

  float rgba[4]={1.0f,1.0f,1.0f,1.0f};
  // check for color prop and use it for rendering if it exists
  GetColor(rgba, renderer);
  // check for opacity prop and use it for rendering if it exists
  GetOpacity(rgba[3], renderer);

  mitk::LevelWindow levelWindow;
  // check for level window prop and use it for display if it exists
  GetLevelWindow(levelWindow, renderer);

  mitk::LookupTableProperty::Pointer LookupTable;
  LookupTable = dynamic_cast<mitk::LookupTableProperty*>(this->GetDataTreeNode()->GetProperty("LookupTable").GetPointer());
	if (LookupTable.IsNull() )
	{
		m_iilMode = iilImage::INTENSITY_ALPHA;
	  image->setColor(rgba[0], rgba[1], rgba[2], rgba[3]);
	}
	else {
		m_iilMode = iilImage::COLOR_ALPHA;
		image->setColors(LookupTable->GetLookupTable().GetRawLookupTable());
	}

  mitk::BoolProperty::Pointer binary;
  binary = dynamic_cast<mitk::BoolProperty*>(this->GetDataTreeNode()->GetProperty("binary").GetPointer());

  mitk::LevelWindowProperty::Pointer overwriteLevelWindow;
  overwriteLevelWindow = dynamic_cast<mitk::LevelWindowProperty*>(this->GetDataTreeNode()->GetProperty("levelWindow").GetPointer());

  if (binary.IsNotNull() )
  {
    image->setExtrema(0, 1);
  }
  else if (overwriteLevelWindow.IsNotNull() )
  {
    image->setExtrema(overwriteLevelWindow->GetLevelWindow().GetMin(), overwriteLevelWindow->GetLevelWindow().GetMax());
  }
  else
  {
  // set the properties
    image->setExtrema(levelWindow.GetMin(), levelWindow.GetMax());
  }
//  image->setColor(rgba[0], rgba[1], rgba[2], rgba[3]);
}

void mitk::ImageMapper2D::Update(mitk::BaseRenderer* renderer)
{

  RendererInfo& renderinfo=m_RendererInfo[renderer];
  DataTreeNode* node=GetDataTreeNode();
  iilPicImage*& image = renderinfo.m_iilImage;

  if(
      (image == NULL) ||
      (renderinfo.m_RendererId < 0) ||
      (renderinfo.m_LastUpdateTime < node->GetMTime()) ||
      (renderinfo.m_LastUpdateTime < renderer->GetWorldGeometryUpdateTime()) ||
      (renderinfo.m_LastUpdateTime < renderer->GetDisplayGeometryUpdateTime())
    )
    GenerateData(renderer);
  else
  if(
      (renderinfo.m_LastUpdateTime < renderer->GetWorldGeometry()->GetMTime())
      //&&
      //(renderinfo.m_LastUpdateTime < renderer->GetMTime())
    )
    GenerateData(renderer);
  else
  if(
      (renderinfo.m_LastUpdateTime < node->GetPropertyList()->GetMTime()) ||
      (renderinfo.m_LastUpdateTime < node->GetPropertyList(renderer)->GetMTime())
    )
  {
    ApplyProperties(renderer);
    // since we have checked that nothing important has changed, we can set m_LastUpdateTime
    // to the current time
    mitk::Image::Pointer output = this->GetOutput();
    output->Modified();
    renderinfo.m_LastUpdateTime=output->GetMTime();
  }
}
<|endoftext|>


<commit_before>// Copyright 2013 Velodyne Acoustics, 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.
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    PacketFileSender.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// .NAME PacketFileSender -
// .SECTION Description
// This program reads a pcap file and sends the packets using UDP.

#include "vtkPacketFileReader.h"
#include "vvPacketSender.h"

#include <cstdlib>
#include <ctime>
#include <iostream>
#include <string>

#include <boost/thread/thread.hpp>

int main(int argc, char* argv[])
{

  if (argc < 2) {
    std::cout << "Usage: " << argv[0] << " <packet file> [loop] [ip] [dataPort] [position Port] [PlaybackSpeedMultiplier]" << std::endl;
    return 1;
  }
  std::string filename(argv[1]);

  int loop = 0;
  double speed = 1;
  std::string destinationIp = "127.0.0.1";
  int dataPort=2368;
  int positionPort=8308;
  if(argc > 2)
    {
    loop = atoi(argv[2]);
    }
  if(argc > 3)
    {
    destinationIp = argv[3];
    }
  if(argc>5)
    {
      dataPort=atoi(argv[4]);
      positionPort=atoi(argv[5]);
    }
  if(argc>6)
    {
      speed = static_cast<double>(atof(argv[6]));
    }

  // Default time to wait -> it is the elapsed
  // time between two firing of a HDL-32 sensor
  const int defaultTimeToWait = 553;

  // The sensor send one packet every hundreds microseconds
  // thus, the first initialization of timeToWait is defaultTimeToWait
  int timeToWaitPerPacket = static_cast<int>(1.0 / speed * defaultTimeToWait);

  // The timer's resolution is only 1000 microsecond
  // But we need to send packets every X microseconds
  // Thus, we send packet by group of NumberPacketsByPool
  // and then wait the necessary time
  int NumberPacketsByPool = 40;

  // The minimalTimeToWait resolution so that
  // timeToWait * NumberPacketsByPool > 1000
  double minimalTimeToWait = 1000.0/NumberPacketsByPool;

  // Measurement of the sleep
  clock_t T1, T2;
  double elapsedTimeMeasured;
  double timeMicroSecond = 0;
  double elapsedTimeBetweenPackets = 0;

  std::cout << "Start sending" << std::endl;
  try
    {
    do
      {
      vvPacketSender sender(filename, destinationIp, dataPort, positionPort);
      // socket.connect(destinationEndpoint);

      sender.pumpPacket();
      while (!sender.done())
        {
        // Get the timestamp of the packet to compute
        // the next timeToWait
        int currentTimeDiff = sender.pumpPacket();

        // Elapsed time measured from the timestamp of the packets
        // This timestamp will be used to compute the next time to wait
        elapsedTimeBetweenPackets += currentTimeDiff;

        // Every 1000 packets sent, give some information
        // about the number of packet sent, the elapsed time
        // and the next time to wait for the 1000 next packets
        if ((sender.packetCount() % 1000) == 0)
          {
          // Elapsed time measured from the clock of the computer
          // This timestamp will be used to inform the user
          // This timestamp should be greater than elapsedTime2
          T2 = std::clock();
          elapsedTimeMeasured = T2 - T1;
          std::cout << "total sent packets : " << sender.packetCount() << std::endl
                    <<" Elapsed time per packets asked    : " << timeToWaitPerPacket << " microseconds" << std::endl
                    <<" Elapsed time per packets measured : " << elapsedTimeMeasured * 1e6 / 1000
                    << " microseconds" << std::endl
                    << std::endl;

          timeToWaitPerPacket = static_cast<int>(1.0 / speed * elapsedTimeBetweenPackets / 1000);

          // If the computed timeToWait is too high we assume that
          // there is a corruption into the packets timestamp
          // then we set the timeToWait to the HDL-32 firing rate
          if(timeToWaitPerPacket > 2500)
            {
            timeToWaitPerPacket = static_cast<int>(1.0 / speed * defaultTimeToWait);
            }

          // If the computed timeToWait is under the minimal resolution
          // we set the timeToWait to this minimal resolution
          if(timeToWaitPerPacket < minimalTimeToWait)
            {
            timeToWaitPerPacket = static_cast<int>(minimalTimeToWait);
            }

          // Refresh the measured timestamps
          T1 = std::clock();
          elapsedTimeBetweenPackets = 0;
          }

        // boost::this_thread::sleep(boost::posix_time::microseconds(553));
        // Every NumberPacketsByPool packets we wait to be consistent with
        // the real recording of the data. The number of packets should not be
        // too small -> the clock resolution is 1000 microsecond. Hence,
        // NumberPacketsByPool * timeToWait should be greater than 1000
        if ((sender.packetCount() % NumberPacketsByPool) == 0)
          {
          sleep(NumberPacketsByPool * timeToWaitPerPacket);
          }
        }
      } while(loop);
    }
  catch( std::exception & e )
    {
    std::cout << "Caught Exception: " << e.what() << std::endl;
    return 1;
    }

  return 0;
}
<commit_msg>sleep is a GCC function. Changed by boost::this_thread::sleep<commit_after>// Copyright 2013 Velodyne Acoustics, 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.
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    PacketFileSender.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
// .NAME PacketFileSender -
// .SECTION Description
// This program reads a pcap file and sends the packets using UDP.

#include "vtkPacketFileReader.h"
#include "vvPacketSender.h"

#include <cstdlib>
#include <ctime>
#include <iostream>
#include <string>

#include <boost/thread/thread.hpp>

int main(int argc, char* argv[])
{

  if (argc < 2) {
    std::cout << "Usage: " << argv[0] << " <packet file> [loop] [ip] [dataPort] [position Port] [PlaybackSpeedMultiplier]" << std::endl;
    return 1;
  }
  std::string filename(argv[1]);

  int loop = 0;
  double speed = 1;
  std::string destinationIp = "127.0.0.1";
  int dataPort=2368;
  int positionPort=8308;
  if(argc > 2)
    {
    loop = atoi(argv[2]);
    }
  if(argc > 3)
    {
    destinationIp = argv[3];
    }
  if(argc>5)
    {
      dataPort=atoi(argv[4]);
      positionPort=atoi(argv[5]);
    }
  if(argc>6)
    {
      speed = static_cast<double>(atof(argv[6]));
    }

  // Default time to wait -> it is the elapsed
  // time between two firing of a HDL-32 sensor
  const int defaultTimeToWait = 553;

  // The sensor send one packet every hundreds microseconds
  // thus, the first initialization of timeToWait is defaultTimeToWait
  int timeToWaitPerPacket = static_cast<int>(1.0 / speed * defaultTimeToWait);

  // The timer's resolution is only 1000 microsecond
  // But we need to send packets every X microseconds
  // Thus, we send packet by group of NumberPacketsByPool
  // and then wait the necessary time
  int NumberPacketsByPool = 40;

  // The minimalTimeToWait resolution so that
  // timeToWait * NumberPacketsByPool > 1000
  double minimalTimeToWait = 1000.0/NumberPacketsByPool;

  // Measurement of the sleep
  clock_t T1, T2;
  double elapsedTimeMeasured;
  double timeMicroSecond = 0;
  double elapsedTimeBetweenPackets = 0;

  std::cout << "Start sending" << std::endl;
  try
    {
    do
      {
      vvPacketSender sender(filename, destinationIp, dataPort, positionPort);
      // socket.connect(destinationEndpoint);

      sender.pumpPacket();
      while (!sender.done())
        {
        // Get the timestamp of the packet to compute
        // the next timeToWait
        int currentTimeDiff = sender.pumpPacket();

        // Elapsed time measured from the timestamp of the packets
        // This timestamp will be used to compute the next time to wait
        elapsedTimeBetweenPackets += currentTimeDiff;

        // Every 1000 packets sent, give some information
        // about the number of packet sent, the elapsed time
        // and the next time to wait for the 1000 next packets
        if ((sender.packetCount() % 1000) == 0)
          {
          // Elapsed time measured from the clock of the computer
          // This timestamp will be used to inform the user
          // This timestamp should be greater than elapsedTime2
          T2 = std::clock();
          elapsedTimeMeasured = T2 - T1;
          std::cout << "total sent packets : " << sender.packetCount() << std::endl
                    <<" Elapsed time per packets asked    : " << timeToWaitPerPacket << " microseconds" << std::endl
                    <<" Elapsed time per packets measured : " << elapsedTimeMeasured
                    << " microseconds" << std::endl
                    << std::endl;

          timeToWaitPerPacket = static_cast<int>(1.0 / speed * elapsedTimeBetweenPackets / 1000);

          // If the computed timeToWait is too high we assume that
          // there is a corruption into the packets timestamp
          // then we set the timeToWait to the HDL-32 firing rate
          if(timeToWaitPerPacket > 2500)
            {
            timeToWaitPerPacket = static_cast<int>(1.0 / speed * defaultTimeToWait);
            }

          // If the computed timeToWait is under the minimal resolution
          // we set the timeToWait to this minimal resolution
          if(timeToWaitPerPacket < minimalTimeToWait)
            {
            timeToWaitPerPacket = static_cast<int>(minimalTimeToWait);
            }

          // Refresh the measured timestamps
          T1 = std::clock();
          elapsedTimeBetweenPackets = 0;
          }

        // boost::this_thread::sleep(boost::posix_time::microseconds(553));
        // Every NumberPacketsByPool packets we wait to be consistent with
        // the real recording of the data. The number of packets should not be
        // too small -> the clock resolution is 1000 microsecond. Hence,
        // NumberPacketsByPool * timeToWait should be greater than 1000
        if ((sender.packetCount() % NumberPacketsByPool) == 0)
          {
          boost::this_thread::sleep(boost::posix_time::microseconds(NumberPacketsByPool * timeToWaitPerPacket));
          }
        }
      } while(loop);
    }
  catch( std::exception & e )
    {
    std::cout << "Caught Exception: " << e.what() << std::endl;
    return 1;
    }

  return 0;
}
<|endoftext|>


<commit_before>// $Id$
// -*-C++-*-
// * BeginRiceCopyright *****************************************************
//
// Copyright ((c)) 2002, Rice University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// * Neither the name of Rice University (RICE) nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// This software is provided by RICE and contributors "as is" and any
// express or implied warranties, including, but not limited to, the
// implied warranties of merchantability and fitness for a particular
// purpose are disclaimed. In no event shall RICE or contributors be
// liable for any direct, indirect, incidental, special, exemplary, or
// consequential damages (including, but not limited to, procurement of
// substitute goods or services; loss of use, data, or profits; or
// business interruption) however caused and on any theory of liability,
// whether in contract, strict liability, or tort (including negligence
// or otherwise) arising in any way out of the use of this software, even
// if advised of the possibility of such damage.
//
// ******************************************************* EndRiceCopyright *

//***************************************************************************

//************************* System Include Files ****************************

#include <iostream>

#include <unistd.h> // for 'getopt'

//*************************** User Include Files ****************************

#include "Args.h"
#include <lib/support/String.h>
#include <lib/support/Trace.h>

//*************************** Forward Declarations **************************

using std::cerr;
using std::endl;

//***************************************************************************

const char* hpctoolsVerInfo=
#include <include/HPCToolkitVersionInfo.h>

void Args::Version()
{
  cerr << cmd << ": " << hpctoolsVerInfo << endl;
}

void Args::Usage()
{
  cerr
    << "Usage: " << endl
    << "  " << cmd << " [-l | -L]  <binary> <profile>\n"
    << "  " << cmd << " [-V] [ [-M <mlist>] [-X <xlist>] [-R] ] <binary> <profile>\n"

    << endl;
  cerr
    << "Converts various types of profile output into the PROFILE format,\n"
    << "which, in particular, associates source file line information from\n"
    << "<binary> with profile data from <profile>. In effect, the output is\n"
    << "a [source-line -> PC-profile-data] map represented as a XML scope\n"
    << "tree (e.g. file, procedure, statement).  Output is sent to stdout.\n"
    << "\n"
    << "By default, xprof determines a set of metrics available for the\n"
    << "given profile data and includes all of them in the PROFILE output.\n"
    << "\n"
#if 0  // FIXME '[-m <bloop-pcmap>]'
    << "If no <bloop-pcmap> -- a map extended with analysis information\n"
    << "from 'bloop' -- is provided, the program attempts to construct\n"
    << "the PROFILE by querying the <binary>'s debugging information.\n"
    << "Because of the better analysis ability of 'bloop', a <bloop-pcmap>\n"
    << "usually improves the accuracy of the PROFILE.  Moreover, because\n"
    << "no loop recovery is performed, providing <bloop-pcmap> enables\n"
    << "the PROFILE to represent loop nesting information.\n"
    << "[*Not fully implemented.*]\n"
    << "\n"
    << "  -m: specify <bloop-pcmap>\n"
#endif
    << "The following <profile> formats are currently supported: \n"
    << "  - DEC/Compaq/HP's DCPI 'dcpicat' (including ProfileMe) \n"
    << "\n"
    << "Listing available metrics:\n"
    << "  -l       List all derived metrics, in compact form, available from\n"
    << "           <profile> and suppress generation of PROFILE output.\n"
    << "           Note that this output can be used with the -M option.\n"
    << "  -L       List all derived metrics, in long form, available from\n"
    << "           <profile> and suppress generation of PROFILE output.\n"
    << "\n"
    << "Normal Mode:\n"
    << "  -V       Print version information.\n"
    << "  -M mlist Optional colon-separated metric inclusion list. Replaces\n"
    << "           the default metric list. Metrics in PROFILE output will.\n"
    << "           follow this ordering.  Duplicates are allowed (though\n"
    << "           not recommended).\n"
    << "  -X xlist Optional colon-separated metric exclusion list. Excludes\n"
    << "           the listed metrics from either the default metric list or\n"
    << "           the list specified with -M.\n"
    << "  -R       (Most will not find this useful.) For some profile data,\n"
    << "           such as DCPI's ProfileMe, the default is to output derived\n"
    << "           metrics, not the underlying raw metrics; this option\n"
    << "           forces output of only the raw metrics.  Should not be\n"
    << "           used with -M or -X.\n"
    << endl;
}

Args::Args(int argc, char* const* argv)
{
  cmd = argv[0];

  bool printVersion = false;
  listAvailableMetrics = 0; // 0: no, 1: short, 2: long
  outputRawMetrics = false;

  extern char *optarg;
  extern int optind;
  bool error = false;
  trace = 0;
  int c;
  while ((c = getopt(argc, argv, "Vm:lLM:X:Rd")) != EOF) {
    switch (c) {
    case 'V': {
      printVersion = true;
      break;
    }
    case 'm': {
      // A non-null value of 'pcMapFile' indicates it has been set
      if (optarg == NULL) { error = true; }
      pcMapFile = optarg;
      break;
    }

    case 'l': {
      listAvailableMetrics = 1;
      break;
    }
    case 'L': {
      listAvailableMetrics = 2;
      break;
    }

    case 'M': {
      if (optarg == NULL) { error = true; }
      metricList = optarg;
      break;
    }
    case 'X': {
      if (optarg == NULL) { error = true; }
      excludeMList = optarg;
      break;
    }
    case 'R': {
      outputRawMetrics = true;
      break;
    }

    case 'd': { // debug
      trace++;
      break;
    }
    case ':':
    case '?': { // error
      error = true;
      break;
    }
    }
  }

  error = error || (optind != argc-2);
  if (!error) {
    progFile = argv[optind];
    profFile = argv[optind+1];
  }

  // Sanity check: -M,-X and -R should not be used at the same time
  if ( (!metricList.Empty() || !excludeMList.Empty()) && outputRawMetrics) {
    cerr << "Error: -M or -X cannot be used with -R.\n";
    error = true;
  }

  IFTRACE << "Args.cmd= " << cmd << endl;
  IFTRACE << "Args.progFile= " << progFile << endl;
  IFTRACE << "Args.profFile= " << profFile << endl;
  IFTRACE << "Args.pcMapFile= " << pcMapFile << endl;
  IFTRACE << "::trace " << ::trace << endl;

  if (printVersion) {
    Version();
    exit(1);
  }

  if (error) {
    Usage();
    exit(1);
  }
}

<commit_msg>Allow multiple -M and -X options.<commit_after>// $Id$
// -*-C++-*-
// * BeginRiceCopyright *****************************************************
//
// Copyright ((c)) 2002, Rice University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// * Neither the name of Rice University (RICE) nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// This software is provided by RICE and contributors "as is" and any
// express or implied warranties, including, but not limited to, the
// implied warranties of merchantability and fitness for a particular
// purpose are disclaimed. In no event shall RICE or contributors be
// liable for any direct, indirect, incidental, special, exemplary, or
// consequential damages (including, but not limited to, procurement of
// substitute goods or services; loss of use, data, or profits; or
// business interruption) however caused and on any theory of liability,
// whether in contract, strict liability, or tort (including negligence
// or otherwise) arising in any way out of the use of this software, even
// if advised of the possibility of such damage.
//
// ******************************************************* EndRiceCopyright *

//***************************************************************************

//************************* System Include Files ****************************

#include <iostream>

#include <unistd.h> // for 'getopt'

//*************************** User Include Files ****************************

#include "Args.h"
#include <lib/support/String.h>
#include <lib/support/Trace.h>

//*************************** Forward Declarations **************************

using std::cerr;
using std::endl;

//***************************************************************************

const char* hpctoolsVerInfo=
#include <include/HPCToolkitVersionInfo.h>

void Args::Version()
{
  cerr << cmd << ": " << hpctoolsVerInfo << endl;
}

void Args::Usage()
{
  cerr
    << "Usage: " << endl
    << "  " << cmd << " [-l | -L]  <binary> <profile>\n"
    << "  " << cmd << " [-V] [ [-M <mlist> -M...] [-X <xlist> -X...] [-R] ] <binary> <profile>\n"

    << endl;
  cerr
    << "Converts various types of profile output into the PROFILE format,\n"
    << "which, in particular, associates source file line information from\n"
    << "<binary> with profile data from <profile>. In effect, the output is\n"
    << "a [source-line -> PC-profile-data] map represented as a XML scope\n"
    << "tree (e.g. file, procedure, statement).  Output is sent to stdout.\n"
    << "\n"
    << "By default, xprof determines a set of metrics available for the\n"
    << "given profile data and includes all of them in the PROFILE output.\n"
    << "\n"
#if 0  // FIXME '[-m <bloop-pcmap>]'
    << "If no <bloop-pcmap> -- a map extended with analysis information\n"
    << "from 'bloop' -- is provided, the program attempts to construct\n"
    << "the PROFILE by querying the <binary>'s debugging information.\n"
    << "Because of the better analysis ability of 'bloop', a <bloop-pcmap>\n"
    << "usually improves the accuracy of the PROFILE.  Moreover, because\n"
    << "no loop recovery is performed, providing <bloop-pcmap> enables\n"
    << "the PROFILE to represent loop nesting information.\n"
    << "[*Not fully implemented.*]\n"
    << "\n"
    << "  -m: specify <bloop-pcmap>\n"
#endif
    << "The following <profile> formats are currently supported: \n"
    << "  - DEC/Compaq/HP's DCPI 'dcpicat' (including ProfileMe) \n"
    << "\n"
    << "Listing available metrics:\n"
    << "  -l       List all derived metrics, in compact form, available from\n"
    << "           <profile> and suppress generation of PROFILE output.\n"
    << "           Note that this output can be used with the -M option.\n"
    << "  -L       List all derived metrics, in long form, available from\n"
    << "           <profile> and suppress generation of PROFILE output.\n"
    << "\n"
    << "Normal Mode:\n"
    << "  -V       Print version information.\n"
    << "  -M mlist Optional colon-separated metric inclusion list. Replaces\n"
    << "           the default metric list. Metrics in PROFILE output will.\n"
    << "           follow this ordering.  Duplicates are allowed (though\n"
    << "           not recommended).\n"
    << "  -X xlist Optional colon-separated metric exclusion list. Excludes\n"
    << "           the listed metrics from either the default metric list or\n"
    << "           the list specified with -M.\n"
    << "  -R       (Most will not find this useful.) For some profile data,\n"
    << "           such as DCPI's ProfileMe, the default is to output derived\n"
    << "           metrics, not the underlying raw metrics; this option\n"
    << "           forces output of only the raw metrics.  Should not be\n"
    << "           used with -M or -X.\n"
    << endl;
}

Args::Args(int argc, char* const* argv)
{
  cmd = argv[0];

  bool printVersion = false;
  listAvailableMetrics = 0; // 0: no, 1: short, 2: long
  outputRawMetrics = false;

  extern char *optarg;
  extern int optind;
  bool error = false;
  trace = 0;
  int c;
  while ((c = getopt(argc, argv, "Vm:lLM:X:Rd")) != EOF) {
    switch (c) {
    case 'V': {
      printVersion = true;
      break;
    }
    case 'm': {
      // A non-null value of 'pcMapFile' indicates it has been set
      if (optarg == NULL) { error = true; }
      pcMapFile = optarg;
      break;
    }

    case 'l': {
      listAvailableMetrics = 1;
      break;
    }
    case 'L': {
      listAvailableMetrics = 2;
      break;
    }

    case 'M': { // may occur multiple times
      if (optarg == NULL) { error = true; }
      if (!metricList.Empty()) { metricList += ":"; }
      metricList += optarg;
      break;
    }
    case 'X': { // may occur multiple times
      if (optarg == NULL) { error = true; }
      if (!excludeMList.Empty()) { excludeMList += ":"; }
      excludeMList += optarg;
      break;
    }
    case 'R': {
      outputRawMetrics = true;
      break;
    }

    case 'd': { // debug
      trace++;
      break;
    }
    case ':':
    case '?': { // error
      error = true;
      break;
    }
    }
  }

  error = error || (optind != argc-2);
  if (!error) {
    progFile = argv[optind];
    profFile = argv[optind+1];
  }

  // Sanity check: -M,-X and -R should not be used at the same time
  if ( (!metricList.Empty() || !excludeMList.Empty()) && outputRawMetrics) {
    cerr << "Error: -M or -X cannot be used with -R.\n";
    error = true;
  }

  IFTRACE << "Args.cmd= " << cmd << endl;
  IFTRACE << "Args.progFile= " << progFile << endl;
  IFTRACE << "Args.profFile= " << profFile << endl;
  IFTRACE << "Args.pcMapFile= " << pcMapFile << endl;
  IFTRACE << "::trace " << ::trace << endl;

  if (printVersion) {
    Version();
    exit(1);
  }

  if (error) {
    Usage();
    exit(1);
  }
}

<|endoftext|>


<commit_before>/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

#include "bochs.h"
#include <assert.h>
#include "state_file.h"

static char *divider = "========================================================================";

// Just for the iofunctions

#define LOG_THIS this->log->

int Allocio=0;

void
iofunctions::flush(void) {
	if(logfd && magic == MAGIC_LOGNUM) {
		fflush(logfd);
	}
}

void
iofunctions::init(void) {
	// iofunctions methods must not be called before this magic
	// number is set.
	magic=MAGIC_LOGNUM;
	showtick = 1;
	n_logfn = 0;
	init_log(stderr);
	log = new logfunc_t(this);
	LOG_THIS put("IO");
	LOG_THIS settype(IOLOG);
	BX_DEBUG(("Init(log file: '%s').",logfn));
}

void
iofunctions::add_logfn (logfunc_t *fn)
{
  assert (n_logfn < MAX_LOGFNS);
  logfn_list[n_logfn++] = fn;
}

void
iofunctions::set_log_action (int loglevel, int action)
{
  for (int i=0; i<n_logfn; i++)
    logfn_list[i]->setonoff(loglevel, action);
}

void
iofunctions::init_log(char *fn)
{
	assert (magic==MAGIC_LOGNUM);
	// use newfd/newfn so that we can log the message to the OLD log
	// file descriptor.
	FILE *newfd = stderr;
	char *newfn = "/dev/stderr";
	if( strcmp( fn, "-" ) != 0 ) {
		newfd = fopen(fn, "w");
		if(newfd != NULL) {
			newfn = strdup(fn);
			BX_DEBUG(("Opened log file '%s'.", fn ));
		} else {
		  	BX_PANIC(("Couldn't open log file: %s", fn));
		}
	}
	logfd = newfd;
	logfn = newfn;
}

void
iofunctions::init_log(FILE *fs)
{
	assert (magic==MAGIC_LOGNUM);
	logfd = fs;

	if(fs == stderr) {
		logfn = "/dev/stderr";
	} else if(fs == stdout) {
		logfn = "/dev/stdout";
	} else {
		logfn = "(unknown)";
	}
}

void
iofunctions::init_log(int fd)
{
	assert (magic==MAGIC_LOGNUM);
	FILE *tmpfd;
	if( (tmpfd = fdopen(fd,"w")) == NULL ) {
	  BX_PANIC(("Couldn't open fd %d as a stream for writing", fd));
	  return;
	}

	init_log(tmpfd);
	return;
};

//  iofunctions::out( class, level, prefix, fmt, ap)
//  DO NOT nest out() from ::info() and the like.
//    fmt and ap retained for direct printinf from iofunctions only!

void
iofunctions::out(int f, int l, char *prefix, char *fmt, va_list ap)
{
	char c=' ';
	assert (magic==MAGIC_LOGNUM);
	assert (this != NULL);
	assert (logfd != NULL);

	if( showtick )
		fprintf(logfd, "%011lld", bx_pc_system.time_ticks());

	switch(l) {
		case LOGLEV_INFO: c='i'; break;
		case LOGLEV_PANIC: c='p'; break;
		case LOGLEV_ERROR: c='e'; break;
		case LOGLEV_DEBUG: c='d'; break;
		default: break;
	}
	fprintf(logfd, "%c",c);

	if(prefix != NULL)
		fprintf(logfd, "%s ", prefix);

	if(l==LOGLEV_PANIC)
		fprintf(logfd, ">>PANIC<< ");

	vfprintf(logfd, fmt, ap);
	fprintf(logfd, "\n");
	fflush(logfd);

	return;
}

iofunctions::iofunctions(FILE *fs)
{
	init();
	init_log(fs);
}

iofunctions::iofunctions(char *fn)
{
	init();
	init_log(fn);
}

iofunctions::iofunctions(int fd)
{
	init();
	init_log(fd);
}

iofunctions::iofunctions(void)
{
	this->init();
}

iofunctions::~iofunctions(void)
{
	// flush before erasing magic number, or flush does nothing.
	this->flush();
	this->magic=0;
}

#undef LOG_THIS
#define LOG_THIS genlog->

logfunctions::logfunctions(void)
{
	put(" ");
	settype(GENLOG);
	if(io == NULL && Allocio == 0) {
		Allocio = 1;
		io = new iofunc_t(stderr);
	}
	setio(io);
	// BUG: unfortunately this can be called before the bochsrc is read,
	// which means that the bochsrc has no effect on the actions.
	for (int i=0; i<N_LOGLEV; i++)
	  onoff[i] = bx_options.log.actions[i];
}

logfunctions::logfunctions(iofunc_t *iofunc)
{
	put(" ");
	settype(GENLOG);
	setio(iofunc);
	// BUG: unfortunately this can be called before the bochsrc is read,
	// which means that the bochsrc has no effect on the actions.
	for (int i=0; i<N_LOGLEV; i++)
	  onoff[i] = bx_options.log.actions[i];
}

logfunctions::~logfunctions(void)
{
}

void
logfunctions::setio(iofunc_t *i)
{
  	// add pointer to iofunction object to use
	this->logio = i;
	// give iofunction a pointer to me
	i->add_logfn (this);
}

void
logfunctions::put(char *p)
{
	char *tmpbuf;
	tmpbuf=strdup("[     ]");// if we ever have more than 32 chars,
						   //  we need to rethink this
	int len=strlen(p);
	for(int i=1;i<len+1;i++) {
		tmpbuf[i]=p[i-1];
	}

	switch(len) {
	case  1: tmpbuf[2]=' ';
	case  2: tmpbuf[3]=' ';
	case  3: tmpbuf[4]=' ';
	case  4: tmpbuf[5]=' ';
	default: tmpbuf[6]=']'; tmpbuf[7]='\0'; break;
	}

	this->prefix=tmpbuf;
}

void
logfunctions::settype(int t)
{
	type=t;
}

void
logfunctions::info(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_INFO]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_INFO,this->prefix, fmt, ap);
	if (onoff[LOGLEV_INFO] == ACT_ASK)
	  ask (LOGLEV_INFO, this->prefix, fmt, ap);
	if (onoff[LOGLEV_INFO] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);

}

void
logfunctions::error(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_ERROR]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_ERROR,this->prefix, fmt, ap);
	if (onoff[LOGLEV_ERROR] == ACT_ASK)
	  ask (LOGLEV_ERROR, this->prefix, fmt, ap);
	if (onoff[LOGLEV_ERROR] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);
}

void
logfunctions::panic(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_PANIC]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_PANIC,this->prefix, fmt, ap);
	if (onoff[LOGLEV_PANIC] == ACT_ASK)
	  ask (LOGLEV_PANIC, this->prefix, fmt, ap);
	if (onoff[LOGLEV_PANIC] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);
}

void
logfunctions::ldebug(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_DEBUG]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_DEBUG,this->prefix, fmt, ap);
	if (onoff[LOGLEV_DEBUG] == ACT_ASK)
	  ask (LOGLEV_DEBUG, this->prefix, fmt, ap);
	if (onoff[LOGLEV_DEBUG] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);
}

void
logfunctions::ask (int level, char *prefix, char *fmt, va_list ap)
{
  char buf1[1024], buf2[1024];
  vsprintf (buf1, fmt, ap);
  sprintf (buf2, "%s %s", prefix, buf1);
  // FIXME: facility set to 0 because it's unknown.
  int val = SIM->LOCAL_log_msg (prefix, level, buf2);
  switch (val)
  {
    case 0:   // user chose continue
      break;
    case 1:   // user said continue, and don't ask for this facility again.
      setonoff (level, ACT_REPORT);
      break;
    case 2:   // user chose die
      fatal (prefix, fmt, ap);
#if BX_DEBUGGER
    case 3:
      // user chose debugger.  To "drop into the debugger" we just set the
      // interrupt_requested bit and continue execution.  Before the next
      // instruction, it should notice the user interrupt and return to
      // the debugger.
      bx_guard.interrupt_requested = 1;
      break;
#endif
    default:
      fprintf (stderr, "WARNING: LOCAL_log_msg returned unexpected value %d\n", val);
  }
}

void
logfunctions::fatal (char *prefix, char *fmt, va_list ap)
{
  static int fatal_reentry = 0;
  if (fatal_reentry) return;
  fatal_reentry++;
  bx_atexit();
  fprintf (stderr, "%s\n", divider);
  fprintf (stderr, "Bochs is exiting with the following message:\n");
  fprintf (stderr, "%s ", prefix);
  vfprintf (stderr, fmt, ap);
  fprintf (stderr, "\n%s\n", divider);
#if 0 && defined(WIN32)
#error disabled because it  is not working yet!
  // wait for a keypress before quitting.  Depending on how bochs is
  // installed, the console window can disappear before the user has
  // a chance to read the final message.
  fprintf (stderr, "\n\nPress Enter to exit...\n");
  char buf[8];
  fgets (buf, 8, stdin);
#endif
#if !BX_DEBUGGER
  exit(1);
#else
  static Boolean dbg_exit_called = 0;
  if (dbg_exit_called == 0) {
    dbg_exit_called = 1;
    bx_dbg_exit(1);
    }
#endif
  fatal_reentry--;
}

iofunc_t *io = NULL;
logfunc_t *genlog = NULL;

void bx_center_print (FILE *file, char *line, int maxwidth)
{
  int imax;
  imax = (maxwidth - strlen(line)) >> 1;
  for (int i=0; i<imax; i++) fputc (' ', file);
  fputs (line, file);
}

<commit_msg>- bend the rules slightly so that panics get printed all the time, even   if the user tried to set action=ignore.<commit_after>/////////////////////////////////////////////////////////////////////////
// $Id$
/////////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2001  MandrakeSoft S.A.
//
//    MandrakeSoft S.A.
//    43, rue d'Aboukir
//    75002 Paris - France
//    http://www.linux-mandrake.com/
//    http://www.mandrakesoft.com/
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 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
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA

#include "bochs.h"
#include <assert.h>
#include "state_file.h"

static char *divider = "========================================================================";

// Just for the iofunctions

#define LOG_THIS this->log->

int Allocio=0;

void
iofunctions::flush(void) {
	if(logfd && magic == MAGIC_LOGNUM) {
		fflush(logfd);
	}
}

void
iofunctions::init(void) {
	// iofunctions methods must not be called before this magic
	// number is set.
	magic=MAGIC_LOGNUM;
	showtick = 1;
	n_logfn = 0;
	init_log(stderr);
	log = new logfunc_t(this);
	LOG_THIS put("IO");
	LOG_THIS settype(IOLOG);
	BX_DEBUG(("Init(log file: '%s').",logfn));
}

void
iofunctions::add_logfn (logfunc_t *fn)
{
  assert (n_logfn < MAX_LOGFNS);
  logfn_list[n_logfn++] = fn;
}

void
iofunctions::set_log_action (int loglevel, int action)
{
  for (int i=0; i<n_logfn; i++)
    logfn_list[i]->setonoff(loglevel, action);
}

void
iofunctions::init_log(char *fn)
{
	assert (magic==MAGIC_LOGNUM);
	// use newfd/newfn so that we can log the message to the OLD log
	// file descriptor.
	FILE *newfd = stderr;
	char *newfn = "/dev/stderr";
	if( strcmp( fn, "-" ) != 0 ) {
		newfd = fopen(fn, "w");
		if(newfd != NULL) {
			newfn = strdup(fn);
			BX_DEBUG(("Opened log file '%s'.", fn ));
		} else {
		  	BX_PANIC(("Couldn't open log file: %s", fn));
		}
	}
	logfd = newfd;
	logfn = newfn;
}

void
iofunctions::init_log(FILE *fs)
{
	assert (magic==MAGIC_LOGNUM);
	logfd = fs;

	if(fs == stderr) {
		logfn = "/dev/stderr";
	} else if(fs == stdout) {
		logfn = "/dev/stdout";
	} else {
		logfn = "(unknown)";
	}
}

void
iofunctions::init_log(int fd)
{
	assert (magic==MAGIC_LOGNUM);
	FILE *tmpfd;
	if( (tmpfd = fdopen(fd,"w")) == NULL ) {
	  BX_PANIC(("Couldn't open fd %d as a stream for writing", fd));
	  return;
	}

	init_log(tmpfd);
	return;
};

//  iofunctions::out( class, level, prefix, fmt, ap)
//  DO NOT nest out() from ::info() and the like.
//    fmt and ap retained for direct printinf from iofunctions only!

void
iofunctions::out(int f, int l, char *prefix, char *fmt, va_list ap)
{
	char c=' ';
	assert (magic==MAGIC_LOGNUM);
	assert (this != NULL);
	assert (logfd != NULL);

	if( showtick )
		fprintf(logfd, "%011lld", bx_pc_system.time_ticks());

	switch(l) {
		case LOGLEV_INFO: c='i'; break;
		case LOGLEV_PANIC: c='p'; break;
		case LOGLEV_ERROR: c='e'; break;
		case LOGLEV_DEBUG: c='d'; break;
		default: break;
	}
	fprintf(logfd, "%c",c);

	if(prefix != NULL)
		fprintf(logfd, "%s ", prefix);

	if(l==LOGLEV_PANIC)
		fprintf(logfd, ">>PANIC<< ");

	vfprintf(logfd, fmt, ap);
	fprintf(logfd, "\n");
	fflush(logfd);

	return;
}

iofunctions::iofunctions(FILE *fs)
{
	init();
	init_log(fs);
}

iofunctions::iofunctions(char *fn)
{
	init();
	init_log(fn);
}

iofunctions::iofunctions(int fd)
{
	init();
	init_log(fd);
}

iofunctions::iofunctions(void)
{
	this->init();
}

iofunctions::~iofunctions(void)
{
	// flush before erasing magic number, or flush does nothing.
	this->flush();
	this->magic=0;
}

#undef LOG_THIS
#define LOG_THIS genlog->

logfunctions::logfunctions(void)
{
	put(" ");
	settype(GENLOG);
	if(io == NULL && Allocio == 0) {
		Allocio = 1;
		io = new iofunc_t(stderr);
	}
	setio(io);
	// BUG: unfortunately this can be called before the bochsrc is read,
	// which means that the bochsrc has no effect on the actions.
	for (int i=0; i<N_LOGLEV; i++)
	  onoff[i] = bx_options.log.actions[i];
}

logfunctions::logfunctions(iofunc_t *iofunc)
{
	put(" ");
	settype(GENLOG);
	setio(iofunc);
	// BUG: unfortunately this can be called before the bochsrc is read,
	// which means that the bochsrc has no effect on the actions.
	for (int i=0; i<N_LOGLEV; i++)
	  onoff[i] = bx_options.log.actions[i];
}

logfunctions::~logfunctions(void)
{
}

void
logfunctions::setio(iofunc_t *i)
{
  	// add pointer to iofunction object to use
	this->logio = i;
	// give iofunction a pointer to me
	i->add_logfn (this);
}

void
logfunctions::put(char *p)
{
	char *tmpbuf;
	tmpbuf=strdup("[     ]");// if we ever have more than 32 chars,
						   //  we need to rethink this
	int len=strlen(p);
	for(int i=1;i<len+1;i++) {
		tmpbuf[i]=p[i-1];
	}

	switch(len) {
	case  1: tmpbuf[2]=' ';
	case  2: tmpbuf[3]=' ';
	case  3: tmpbuf[4]=' ';
	case  4: tmpbuf[5]=' ';
	default: tmpbuf[6]=']'; tmpbuf[7]='\0'; break;
	}

	this->prefix=tmpbuf;
}

void
logfunctions::settype(int t)
{
	type=t;
}

void
logfunctions::info(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_INFO]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_INFO,this->prefix, fmt, ap);
	if (onoff[LOGLEV_INFO] == ACT_ASK)
	  ask (LOGLEV_INFO, this->prefix, fmt, ap);
	if (onoff[LOGLEV_INFO] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);

}

void
logfunctions::error(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_ERROR]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_ERROR,this->prefix, fmt, ap);
	if (onoff[LOGLEV_ERROR] == ACT_ASK)
	  ask (LOGLEV_ERROR, this->prefix, fmt, ap);
	if (onoff[LOGLEV_ERROR] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);
}

void
logfunctions::panic(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	// Special case for panics since they are so important.  Always print
	// the panic to the log, no matter what the log action says.
	//if(!onoff[LOGLEV_PANIC]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_PANIC,this->prefix, fmt, ap);
	if (onoff[LOGLEV_PANIC] == ACT_ASK)
	  ask (LOGLEV_PANIC, this->prefix, fmt, ap);
	if (onoff[LOGLEV_PANIC] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);
}

void
logfunctions::ldebug(char *fmt, ...)
{
	va_list ap;

	assert (this != NULL);
	assert (this->logio != NULL);

	if(!onoff[LOGLEV_DEBUG]) return;

	va_start(ap, fmt);
	this->logio->out(this->type,LOGLEV_DEBUG,this->prefix, fmt, ap);
	if (onoff[LOGLEV_DEBUG] == ACT_ASK)
	  ask (LOGLEV_DEBUG, this->prefix, fmt, ap);
	if (onoff[LOGLEV_DEBUG] == ACT_FATAL)
	  fatal (this->prefix, fmt, ap);
	va_end(ap);
}

void
logfunctions::ask (int level, char *prefix, char *fmt, va_list ap)
{
  char buf1[1024], buf2[1024];
  vsprintf (buf1, fmt, ap);
  sprintf (buf2, "%s %s", prefix, buf1);
  // FIXME: facility set to 0 because it's unknown.
  int val = SIM->LOCAL_log_msg (prefix, level, buf2);
  switch (val)
  {
    case 0:   // user chose continue
      break;
    case 1:   // user said continue, and don't ask for this facility again.
      setonoff (level, ACT_REPORT);
      break;
    case 2:   // user chose die
      fatal (prefix, fmt, ap);
#if BX_DEBUGGER
    case 3:
      // user chose debugger.  To "drop into the debugger" we just set the
      // interrupt_requested bit and continue execution.  Before the next
      // instruction, it should notice the user interrupt and return to
      // the debugger.
      bx_guard.interrupt_requested = 1;
      break;
#endif
    default:
      fprintf (stderr, "WARNING: LOCAL_log_msg returned unexpected value %d\n", val);
  }
}

void
logfunctions::fatal (char *prefix, char *fmt, va_list ap)
{
  static int fatal_reentry = 0;
  if (fatal_reentry) return;
  fatal_reentry++;
  bx_atexit();
  fprintf (stderr, "%s\n", divider);
  fprintf (stderr, "Bochs is exiting with the following message:\n");
  fprintf (stderr, "%s ", prefix);
  vfprintf (stderr, fmt, ap);
  fprintf (stderr, "\n%s\n", divider);
#if 0 && defined(WIN32)
#error disabled because it  is not working yet!
  // wait for a keypress before quitting.  Depending on how bochs is
  // installed, the console window can disappear before the user has
  // a chance to read the final message.
  fprintf (stderr, "\n\nPress Enter to exit...\n");
  char buf[8];
  fgets (buf, 8, stdin);
#endif
#if !BX_DEBUGGER
  exit(1);
#else
  static Boolean dbg_exit_called = 0;
  if (dbg_exit_called == 0) {
    dbg_exit_called = 1;
    bx_dbg_exit(1);
    }
#endif
  fatal_reentry--;
}

iofunc_t *io = NULL;
logfunc_t *genlog = NULL;

void bx_center_print (FILE *file, char *line, int maxwidth)
{
  int imax;
  imax = (maxwidth - strlen(line)) >> 1;
  for (int i=0; i<imax; i++) fputc (' ', file);
  fputs (line, file);
}

<|endoftext|>


<commit_before>/*
 * VerifyNoOtherInvocationsVerificationProgress.hpp
 * Copyright (c) 2014 Eran Pe'er.
 *
 * This program is made available under the terms of the MIT License.
 *
 * Created on Jul 21, 2014
 */
#ifndef VerifyNoOtherInvocationsVerificationProgress_hpp_
#define VerifyNoOtherInvocationsVerificationProgress_hpp_

#include "fakeit/FakeitContext.hpp"

namespace fakeit {

class VerifyNoOtherInvocationsVerificationProgress {

	friend class VerifyNoOtherInvocationsFunctor;

	struct VerifyNoOtherInvocationsExpectation {

		friend class VerifyNoOtherInvocationsVerificationProgress;

		~VerifyNoOtherInvocationsExpectation() THROWS {
			if (std::uncaught_exception()) {
				return;
			}
			VerifyExpectation();
		}

		void setFileInfo(std::string file, int line, std::string callingMethod) {
			_file = file;
			_line = line;
			_callingMethod = callingMethod;
		}

	private:

		FakeitContext& _fakeit;
		std::set<ActualInvocationsSource*> _mocks;

		std::string _file;
		int _line;
		std::string _callingMethod;

		VerifyNoOtherInvocationsExpectation(FakeitContext& fakeit, std::set<ActualInvocationsSource*> mocks) :
				_fakeit(fakeit),
				_mocks(mocks),
				_line(0) {
		}

		VerifyNoOtherInvocationsExpectation(VerifyNoOtherInvocationsExpectation& other) = default;

		void VerifyExpectation() {
			std::unordered_set<Invocation*> actualInvocations;
            InvocationUtils::collectActualInvocations(actualInvocations, _mocks);

			std::unordered_set<Invocation*> nonVerifedIvocations;
            InvocationUtils::selectNonVerifiedInvocations(actualInvocations, nonVerifedIvocations);

			if (nonVerifedIvocations.size() > 0) {
				std::vector<Invocation*> sortedNonVerifedIvocations;
                InvocationUtils::sortByInvocationOrder(nonVerifedIvocations, sortedNonVerifedIvocations);

				std::vector<Invocation*> sortedActualIvocations;
                InvocationUtils::sortByInvocationOrder(actualInvocations, sortedActualIvocations);

				NoMoreInvocationsVerificationEvent evt(sortedActualIvocations, sortedNonVerifedIvocations);
				evt.setFileInfo(_file, _line, _callingMethod);
				_fakeit.handle(evt);
			}
		}

	};

	fakeit::smart_ptr<VerifyNoOtherInvocationsExpectation> _ptr;

	VerifyNoOtherInvocationsVerificationProgress(VerifyNoOtherInvocationsExpectation * ptr) :
			_ptr(ptr) {
	}

	VerifyNoOtherInvocationsVerificationProgress(FakeitContext& fakeit, std::set<ActualInvocationsSource*>& invocationSources)
		: VerifyNoOtherInvocationsVerificationProgress(
			new VerifyNoOtherInvocationsExpectation(fakeit, invocationSources)
			)
	{
	}

public:

	~VerifyNoOtherInvocationsVerificationProgress() THROWS {
	};

	VerifyNoOtherInvocationsVerificationProgress setFileInfo(std::string file, int line, std::string callingMethod) {
		_ptr->setFileInfo(file, line, callingMethod);
		return *this;
	}
};

}

#endif
<commit_msg>Make VerifyNoOtherInvocations conviertible to bool<commit_after>/*
 * VerifyNoOtherInvocationsVerificationProgress.hpp
 * Copyright (c) 2014 Eran Pe'er.
 *
 * This program is made available under the terms of the MIT License.
 *
 * Created on Jul 21, 2014
 */
#ifndef VerifyNoOtherInvocationsVerificationProgress_hpp_
#define VerifyNoOtherInvocationsVerificationProgress_hpp_

#include "fakeit/FakeitContext.hpp"

namespace fakeit {

class VerifyNoOtherInvocationsVerificationProgress {

	friend class VerifyNoOtherInvocationsFunctor;

	struct VerifyNoOtherInvocationsExpectation {

		friend class VerifyNoOtherInvocationsVerificationProgress;

		~VerifyNoOtherInvocationsExpectation() THROWS {
			if (std::uncaught_exception()) {
				return;
			}

			VerifyExpectation();

		}

		void setFileInfo(std::string file, int line, std::string callingMethod) {
			_file = file;
			_line = line;
			_callingMethod = callingMethod;
		}

	private:

		FakeitContext& _fakeit;
		std::set<ActualInvocationsSource*> _mocks;

		std::string _file;
		int _line;
		std::string _callingMethod;
		bool _isVerified;
		VerifyNoOtherInvocationsExpectation(FakeitContext& fakeit, std::set<ActualInvocationsSource*> mocks) :
				_fakeit(fakeit),
				_mocks(mocks),
				_line(0),
				_isVerified(false){
		}

		VerifyNoOtherInvocationsExpectation(VerifyNoOtherInvocationsExpectation& other) = default;

		void VerifyExpectation() {
			if (_isVerified)
				return;
			_isVerified = true;

			std::unordered_set<Invocation*> actualInvocations;
            InvocationUtils::collectActualInvocations(actualInvocations, _mocks);

			std::unordered_set<Invocation*> nonVerifedIvocations;
            InvocationUtils::selectNonVerifiedInvocations(actualInvocations, nonVerifedIvocations);

			if (nonVerifedIvocations.size() > 0) {
				std::vector<Invocation*> sortedNonVerifedIvocations;
                InvocationUtils::sortByInvocationOrder(nonVerifedIvocations, sortedNonVerifedIvocations);

				std::vector<Invocation*> sortedActualIvocations;
                InvocationUtils::sortByInvocationOrder(actualInvocations, sortedActualIvocations);

				NoMoreInvocationsVerificationEvent evt(sortedActualIvocations, sortedNonVerifedIvocations);
				evt.setFileInfo(_file, _line, _callingMethod);
				_fakeit.handle(evt);
			}
		}

	};

	fakeit::smart_ptr<VerifyNoOtherInvocationsExpectation> _ptr;

	VerifyNoOtherInvocationsVerificationProgress(VerifyNoOtherInvocationsExpectation * ptr) :
			_ptr(ptr) {
	}

	VerifyNoOtherInvocationsVerificationProgress(FakeitContext& fakeit, std::set<ActualInvocationsSource*>& invocationSources)
		: VerifyNoOtherInvocationsVerificationProgress(
			new VerifyNoOtherInvocationsExpectation(fakeit, invocationSources)
			)
	{
	}

	bool toBool()  {
		try{
			_ptr->VerifyExpectation();
			return true;
		}
		catch (...){
			return false;
		}
	}

public:

	~VerifyNoOtherInvocationsVerificationProgress() THROWS {
	};

	VerifyNoOtherInvocationsVerificationProgress setFileInfo(std::string file, int line, std::string callingMethod) {
		_ptr->setFileInfo(file, line, callingMethod);
		return *this;
	}

	operator bool() {
		return toBool();
	}

	bool operator ! () const { return !const_cast<VerifyNoOtherInvocationsVerificationProgress*>(this)->toBool(); }

};

}

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2001-2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __PROCESS_HH__
#define __PROCESS_HH__

//
// The purpose of this code is to fake the loader & syscall mechanism
// when there's no OS: thus there's no reason to use it in FULL_SYSTEM
// mode when we do have an OS.
//
#ifndef FULL_SYSTEM

#include <vector>

#include "targetarch/isa_traits.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
#include "base/statistics.hh"
#include "base/trace.hh"

class ExecContext;
class FunctionalMemory;
class Process : public SimObject
{
  public:

    // have we initialized an execution context from this process?  If
    // yes, subsequent contexts are assumed to be for dynamically
    // created threads and are not initialized.
    bool initialContextLoaded;

    // execution contexts associated with this process
    std::vector<ExecContext *> execContexts;

    // number of CPUs (esxec contexts, really) assigned to this process.
    unsigned int numCpus() { return execContexts.size(); }

    // record of blocked context
    struct WaitRec
    {
        Addr waitChan;
        ExecContext *waitingContext;

        WaitRec(Addr chan, ExecContext *ctx)
            : waitChan(chan), waitingContext(ctx)
        {
        }
    };

    // list of all blocked contexts
    std::list<WaitRec> waitList;

    RegFile *init_regs;		// initial register contents

    Addr text_base;		// text (code) segment base
    unsigned text_size;		// text (code) size in bytes

    Addr data_base;		// initialized data segment base
    unsigned data_size;		// initialized data + bss size in bytes

    Addr brk_point;		// top of the data segment

    Addr stack_base;		// stack segment base (highest address)
    unsigned stack_size;	// initial stack size
    Addr stack_min;		// lowest address accessed on the stack

    // addr to use for next stack region (for multithreaded apps)
    Addr next_thread_stack_base;

    // Base of region for mmaps (when user doesn't specify an address).
    Addr mmap_start;
    Addr mmap_end;

    // Base of region for nxm data
    Addr nxm_start;
    Addr nxm_end;

    std::string prog_fname;	// file name
    Addr prog_entry;		// entry point (initial PC)

    Stats::Scalar<> num_syscalls;	// number of syscalls executed

  protected:
    // constructor
    Process(const std::string &nm,
            int stdin_fd, 	// initial I/O descriptors
            int stdout_fd,
            int stderr_fd);

    // post initialization startup
    virtual void startup();

  protected:
    FunctionalMemory *memory;

  private:
    // file descriptor remapping support
    static const int MAX_FD = 100;	// max legal fd value
    int fd_map[MAX_FD+1];

  public:
    // static helper functions to generate file descriptors for constructor
    static int openInputFile(const std::string &filename);
    static int openOutputFile(const std::string &filename);

    // override of virtual SimObject method: register statistics
    virtual void regStats();

    // register an execution context for this process.
    // returns xc's cpu number (index into execContexts[])
    int registerExecContext(ExecContext *xc);

    void replaceExecContext(ExecContext *xc, int xcIndex);

    // map simulator fd sim_fd to target fd tgt_fd
    void dup_fd(int sim_fd, int tgt_fd);

    // generate new target fd for sim_fd
    int open_fd(int sim_fd);

    // look up simulator fd for given target fd
    int sim_fd(int tgt_fd);

    // is this a valid instruction fetch address?
    bool validInstAddr(Addr addr)
    {
        return (text_base <= addr &&
                addr < text_base + text_size &&
                !(addr & (sizeof(MachInst)-1)));
    }

    // is this a valid address? (used to filter data fetches)
    // note that we just assume stack size <= 16MB
    // this may be alpha-specific
    bool validDataAddr(Addr addr)
    {
        return ((data_base <= addr && addr < brk_point) ||
#ifdef FULLSYSTEM
                ((stack_base - 16*1024*1024) <= addr && addr < stack_base) ||
#else
                (next_thread_stack_base <= addr && addr < stack_base) ||
#endif
                (text_base <= addr && addr < (text_base + text_size)) ||
                (mmap_start <= addr && addr < mmap_end) ||
                (nxm_start <= addr && addr < nxm_end));
    }

    virtual void syscall(ExecContext *xc) = 0;

    virtual FunctionalMemory *getMemory() { return memory; }
};

//
// "Live" process with system calls redirected to host system
//
class ObjectFile;
class LiveProcess : public Process
{
  protected:
    LiveProcess(const std::string &nm, ObjectFile *objFile,
                int stdin_fd, int stdout_fd, int stderr_fd,
                std::vector<std::string> &argv,
                std::vector<std::string> &envp);

  public:
    // this function is used to create the LiveProcess object, since
    // we can't tell which subclass of LiveProcess to use until we
    // open and look at the object file.
    static LiveProcess *create(const std::string &nm,
                               int stdin_fd, int stdout_fd, int stderr_fd,
                               std::vector<std::string> &argv,
                               std::vector<std::string> &envp);
};

#endif // !FULL_SYSTEM

#endif // __PROCESS_HH__
<commit_msg>No need for this ifdef, since the entire process.hh is surounded by an ifndef FULL_SYSTEM<commit_after>/*
 * Copyright (c) 2001-2004 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef __PROCESS_HH__
#define __PROCESS_HH__

//
// The purpose of this code is to fake the loader & syscall mechanism
// when there's no OS: thus there's no reason to use it in FULL_SYSTEM
// mode when we do have an OS.
//
#ifndef FULL_SYSTEM

#include <vector>

#include "targetarch/isa_traits.hh"
#include "sim/sim_object.hh"
#include "sim/stats.hh"
#include "base/statistics.hh"
#include "base/trace.hh"

class ExecContext;
class FunctionalMemory;
class Process : public SimObject
{
  public:

    // have we initialized an execution context from this process?  If
    // yes, subsequent contexts are assumed to be for dynamically
    // created threads and are not initialized.
    bool initialContextLoaded;

    // execution contexts associated with this process
    std::vector<ExecContext *> execContexts;

    // number of CPUs (esxec contexts, really) assigned to this process.
    unsigned int numCpus() { return execContexts.size(); }

    // record of blocked context
    struct WaitRec
    {
        Addr waitChan;
        ExecContext *waitingContext;

        WaitRec(Addr chan, ExecContext *ctx)
            : waitChan(chan), waitingContext(ctx)
        {
        }
    };

    // list of all blocked contexts
    std::list<WaitRec> waitList;

    RegFile *init_regs;		// initial register contents

    Addr text_base;		// text (code) segment base
    unsigned text_size;		// text (code) size in bytes

    Addr data_base;		// initialized data segment base
    unsigned data_size;		// initialized data + bss size in bytes

    Addr brk_point;		// top of the data segment

    Addr stack_base;		// stack segment base (highest address)
    unsigned stack_size;	// initial stack size
    Addr stack_min;		// lowest address accessed on the stack

    // addr to use for next stack region (for multithreaded apps)
    Addr next_thread_stack_base;

    // Base of region for mmaps (when user doesn't specify an address).
    Addr mmap_start;
    Addr mmap_end;

    // Base of region for nxm data
    Addr nxm_start;
    Addr nxm_end;

    std::string prog_fname;	// file name
    Addr prog_entry;		// entry point (initial PC)

    Stats::Scalar<> num_syscalls;	// number of syscalls executed

  protected:
    // constructor
    Process(const std::string &nm,
            int stdin_fd, 	// initial I/O descriptors
            int stdout_fd,
            int stderr_fd);

    // post initialization startup
    virtual void startup();

  protected:
    FunctionalMemory *memory;

  private:
    // file descriptor remapping support
    static const int MAX_FD = 100;	// max legal fd value
    int fd_map[MAX_FD+1];

  public:
    // static helper functions to generate file descriptors for constructor
    static int openInputFile(const std::string &filename);
    static int openOutputFile(const std::string &filename);

    // override of virtual SimObject method: register statistics
    virtual void regStats();

    // register an execution context for this process.
    // returns xc's cpu number (index into execContexts[])
    int registerExecContext(ExecContext *xc);

    void replaceExecContext(ExecContext *xc, int xcIndex);

    // map simulator fd sim_fd to target fd tgt_fd
    void dup_fd(int sim_fd, int tgt_fd);

    // generate new target fd for sim_fd
    int open_fd(int sim_fd);

    // look up simulator fd for given target fd
    int sim_fd(int tgt_fd);

    // is this a valid instruction fetch address?
    bool validInstAddr(Addr addr)
    {
        return (text_base <= addr &&
                addr < text_base + text_size &&
                !(addr & (sizeof(MachInst)-1)));
    }

    // is this a valid address? (used to filter data fetches)
    // note that we just assume stack size <= 16MB
    // this may be alpha-specific
    bool validDataAddr(Addr addr)
    {
        return ((data_base <= addr && addr < brk_point) ||
                (next_thread_stack_base <= addr && addr < stack_base) ||
                (text_base <= addr && addr < (text_base + text_size)) ||
                (mmap_start <= addr && addr < mmap_end) ||
                (nxm_start <= addr && addr < nxm_end));
    }

    virtual void syscall(ExecContext *xc) = 0;

    virtual FunctionalMemory *getMemory() { return memory; }
};

//
// "Live" process with system calls redirected to host system
//
class ObjectFile;
class LiveProcess : public Process
{
  protected:
    LiveProcess(const std::string &nm, ObjectFile *objFile,
                int stdin_fd, int stdout_fd, int stderr_fd,
                std::vector<std::string> &argv,
                std::vector<std::string> &envp);

  public:
    // this function is used to create the LiveProcess object, since
    // we can't tell which subclass of LiveProcess to use until we
    // open and look at the object file.
    static LiveProcess *create(const std::string &nm,
                               int stdin_fd, int stdout_fd, int stderr_fd,
                               std::vector<std::string> &argv,
                               std::vector<std::string> &envp);
};

#endif // !FULL_SYSTEM

#endif // __PROCESS_HH__
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <fstream>

// template <class charT, class traits = char_traits<charT> >
// class basic_fstream

// explicit basic_fstream(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out);

#include <fstream>
#include <cassert>

int main()
{
    {
        std::fstream fs(std::string("test.dat"),
                        std::ios_base::in | std::ios_base::out
                                          | std::ios_base::trunc);
        double x = 0;
        fs << 3.25;
        fs.seekg(0);
        fs >> x;
        assert(x == 3.25);
    }
    std::remove("test.dat");
    {
        std::wfstream fs(std::string("test.dat"),
                         std::ios_base::in | std::ios_base::out
                                           | std::ios_base::trunc);
        double x = 0;
        fs << 3.25;
        fs.seekg(0);
        fs >> x;
        assert(x == 3.25);
    }
    std::remove("test.dat");
}
<commit_msg>Do a litmus test of using tmpnam to generate safe temporary file names for the tests that open new data files.<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// <fstream>

// template <class charT, class traits = char_traits<charT> >
// class basic_fstream

// explicit basic_fstream(const string& s, ios_base::openmode mode = ios_base::in|ios_base::out);

#include <fstream>
#include <cassert>

int main()
{
    char temp [L_tmpnam];
    tmpnam(temp);
    {
        std::fstream fs(std::string(temp),
                        std::ios_base::in | std::ios_base::out
                                          | std::ios_base::trunc);
        double x = 0;
        fs << 3.25;
        fs.seekg(0);
        fs >> x;
        assert(x == 3.25);
    }
    std::remove(temp);
    {
        std::wfstream fs(std::string(temp),
                         std::ios_base::in | std::ios_base::out
                                           | std::ios_base::trunc);
        double x = 0;
        fs << 3.25;
        fs.seekg(0);
        fs >> x;
        assert(x == 3.25);
    }
    std::remove(temp);
}
<|endoftext|>