<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkNarrowBandThresholdSegmentationLevelSetImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
#include "itkNarrowBandThresholdSegmentationLevelSetImageFilter.h"
//#include "itkImageFileWriter.h"
//#include "itkRawImageIO.h"
#include "itkCastImageFilter.h"
#include "itkCommand.h"
#include "itkEventObject.h"

namespace NBTS {

 typedef itk::Image<float, 3> ImageType;
typedef itk::Image<char, 3> SeedImageType;

const int V_WIDTH  = 64;
const int V_HEIGHT = 64;
const int V_DEPTH  = 64;

float sphere(float x, float y, float z)
{
    float dis;
    dis = (x - (float)V_WIDTH/2.0)*(x - (float)V_WIDTH/2.0)
      /((0.2f*V_WIDTH)*(0.2f*V_WIDTH)) +
      (y - (float)V_HEIGHT/2.0)*(y - (float)V_HEIGHT/2.0)
      /((0.2f*V_HEIGHT)*(0.2f*V_HEIGHT)) +
      (z - (float)V_DEPTH/2.0)*(z - (float)V_DEPTH/2.0)
      /((0.2f*V_DEPTH)*(0.2f*V_DEPTH));
    return(1.0f-dis);
}

void evaluate_function(itk::Image<char, 3> *im,
          float (*f)(float, float, float) )
{
  itk::Image<char, 3>::IndexType idx;

  for(int z = 0; z < V_DEPTH; ++z)
    {
      idx[2] = z;
      for (int y = 0; y < V_HEIGHT; ++y)
        {
          idx[1] = y;
          for (int x = 0; x < V_WIDTH; ++x)
            {
              idx[0] = x;
              if ( f((float)x,(float)y,(float)z) >= 0.0 )
                {  im->SetPixel(idx, 1 ); }
              else
                {  im->SetPixel(idx, 0 ); }
            }
        }
    }
}

} // end namespace

namespace itk {

class NBRMSCommand : public Command
{
public:
  /** Smart pointer declaration methods */
  typedef NBRMSCommand Self;
  typedef Command Superclass;
  typedef itk::SmartPointer<Self>  Pointer;
  typedef itk::SmartPointer<const Self>  ConstPointer;
  itkTypeMacro( NBRMSCommand, Command );
  itkNewMacro(Self);

  /** Standard Command virtual methods */
  void Execute(Object *caller, const EventObject &)
  {
    std::cout <<
      (dynamic_cast<NarrowBandLevelSetImageFilter< ::NBTS::SeedImageType,
       ::NBTS::ImageType> *>(caller))->GetSegmentationFunction()->GetPropagationWeight()
              << std::endl;

  }
  void Execute(const Object *, const EventObject &)
  {
    std::cout << "ack" << std::endl;

  }

protected:
  NBRMSCommand()  {}
  virtual ~NBRMSCommand() {}
};

}

int itkNarrowBandThresholdSegmentationLevelSetImageFilterTest(int, char * [] )
{
  NBTS::ImageType::RegionType reg;
  NBTS::ImageType::RegionType::SizeType sz;
  NBTS::ImageType::RegionType::IndexType idx;
  idx[0] = idx[1] = idx[2] = 0;
  sz[0] = sz[1] = sz[2] = 64;
  reg.SetSize(sz);
  reg.SetIndex(idx);

  NBTS::ImageType::Pointer     inputImage = NBTS::ImageType::New();
  NBTS::SeedImageType::Pointer seedImage = NBTS::SeedImageType::New();
  inputImage->SetRegions(reg);
  seedImage->SetRegions(reg);
  inputImage->Allocate();
  seedImage->Allocate();

  // Starting surface is a sphere in the center of the image.
  NBTS::evaluate_function(seedImage, NBTS::sphere);

  // Target surface is a diamond
  float val;
  unsigned int i;
  //  NBTS::ImageType::IndexType idx;
  for (idx[2] = 0; idx[2] < 64; idx[2]++)
    for (idx[1] = 0; idx[1] < 64; idx[1]++)
        for (idx[0] = 0; idx[0] < 64; idx[0]++)
          {
            val = 0;
            for (i = 0; i < 3; ++i)
              {
                if (idx[i] < 32) val+=idx[i];
                else val += 64 - idx[i];
              }
            inputImage->SetPixel(idx, val);
          }

  itk::NarrowBandThresholdSegmentationLevelSetImageFilter< ::NBTS::SeedImageType, ::NBTS::ImageType>::Pointer
    filter = itk::NarrowBandThresholdSegmentationLevelSetImageFilter< ::NBTS::SeedImageType, ::NBTS::ImageType>::New();
  filter->SetInput(seedImage);
  filter->SetFeatureImage(inputImage);

  filter->SetUpperThreshold(63);
  filter->SetLowerThreshold(50);

  filter->SetMaximumRMSError(0.04); //Does not have any effect
  filter->SetMaximumIterations(10);
  filter->ReverseExpansionDirectionOn(); // Change the default behavior of the speed
                                      // function so that negative values result in
                                      // surface growth.

  itk::NBRMSCommand::Pointer c = itk::NBRMSCommand::New();
  filter->AddObserver(itk::IterationEvent(), c);
  filter->SetIsoSurfaceValue(0.5);  //<--- IMPORTANT!  Default is zero.

  try {
    filter->Update();
    std::cout << "Done first trial" << std::endl;
    // Repeat to make sure that the filter is reinitialized properly
    filter->SetMaximumIterations(8);
    filter->Update();
    std::cout << "Done second trial" << std::endl;

    //For Debugging
    //typedef itk::ImageFileWriter< ::NBTS::ImageType> WriterType;
    //WriterType::Pointer writer = WriterType::New();
    //writer->SetInput( filter->GetOutput() );
    //writer->SetFileName( "outputThreshold.mhd" );
    //writer->Write();

    //WriterType::Pointer writer3 = WriterType::New();
    //writer3->SetInput(inputImage);
    //writer3->SetFileName("inputThreshold.mhd");
    //writer3->Write();

    // typedef itk::ImageFileWriter< ::NBTS::SeedImageType> Writer2Type;
    //Writer2Type::Pointer writer2 = Writer2Type::New();
    //writer2->SetInput(seedImage);
    //writer2->SetFileName("seedThreshold.mhd");
    //writer2->Write();

    // Write the output for debugging purposes
    //       itk::ImageFileWriter<NBTS::ImageType>::Pointer writer
    //          = itk::ImageFileWriter<NBTS::ImageType>::New();
    //        itk::RawImageIO<float, 3>::Pointer io = itk::RawImageIO<float, 3>::New();
    //        io->SetFileTypeToBinary();
    //        io->SetFileDimensionality(3);
    //        io->SetByteOrderToLittleEndian();
    //        writer->SetImageIO(io);

    //        itk::CastImageFilter<NBTS::SeedImageType, NBTS::ImageType>::Pointer
    //         caster = itk::CastImageFilter<NBTS::SeedImageType, NBTS::ImageType>::New();
    //        caster->SetInput(seedImage);
    //        caster->Update();

        // writer->SetInput(caster->GetOutput());
        //     writer->SetInput(filter->GetSpeedImage());
        //        writer->SetInput(filter->GetFeatureImage());
    // writer->SetInput(inputImage);
    //        writer->SetInput(filter->GetOutput());
    //       writer->SetFileName("output.raw");
    //        writer->Write();

  }
  catch (itk::ExceptionObject &e)
    {
      std::cerr << e << std::endl;
    }

  return 0;
}

<commit_msg>FIX: Test should return 1 if it caught an exception.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkNarrowBandThresholdSegmentationLevelSetImageFilterTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) 2002 Insight Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
#include "itkNarrowBandThresholdSegmentationLevelSetImageFilter.h"
//#include "itkImageFileWriter.h"
//#include "itkRawImageIO.h"
#include "itkCastImageFilter.h"
#include "itkCommand.h"
#include "itkEventObject.h"

namespace NBTS {

 typedef itk::Image<float, 3> ImageType;
typedef itk::Image<char, 3> SeedImageType;

const int V_WIDTH  = 64;
const int V_HEIGHT = 64;
const int V_DEPTH  = 64;

float sphere(float x, float y, float z)
{
    float dis;
    dis = (x - (float)V_WIDTH/2.0)*(x - (float)V_WIDTH/2.0)
      /((0.2f*V_WIDTH)*(0.2f*V_WIDTH)) +
      (y - (float)V_HEIGHT/2.0)*(y - (float)V_HEIGHT/2.0)
      /((0.2f*V_HEIGHT)*(0.2f*V_HEIGHT)) +
      (z - (float)V_DEPTH/2.0)*(z - (float)V_DEPTH/2.0)
      /((0.2f*V_DEPTH)*(0.2f*V_DEPTH));
    return(1.0f-dis);
}

void evaluate_function(itk::Image<char, 3> *im,
          float (*f)(float, float, float) )
{
  itk::Image<char, 3>::IndexType idx;

  for(int z = 0; z < V_DEPTH; ++z)
    {
      idx[2] = z;
      for (int y = 0; y < V_HEIGHT; ++y)
        {
          idx[1] = y;
          for (int x = 0; x < V_WIDTH; ++x)
            {
              idx[0] = x;
              if ( f((float)x,(float)y,(float)z) >= 0.0 )
                {  im->SetPixel(idx, 1 ); }
              else
                {  im->SetPixel(idx, 0 ); }
            }
        }
    }
}

} // end namespace

namespace itk {

class NBRMSCommand : public Command
{
public:
  /** Smart pointer declaration methods */
  typedef NBRMSCommand Self;
  typedef Command Superclass;
  typedef itk::SmartPointer<Self>  Pointer;
  typedef itk::SmartPointer<const Self>  ConstPointer;
  itkTypeMacro( NBRMSCommand, Command );
  itkNewMacro(Self);

  /** Standard Command virtual methods */
  void Execute(Object *caller, const EventObject &)
  {
    std::cout <<
      (dynamic_cast<NarrowBandLevelSetImageFilter< ::NBTS::SeedImageType,
       ::NBTS::ImageType> *>(caller))->GetSegmentationFunction()->GetPropagationWeight()
              << std::endl;

  }
  void Execute(const Object *, const EventObject &)
  {
    std::cout << "ack" << std::endl;

  }

protected:
  NBRMSCommand()  {}
  virtual ~NBRMSCommand() {}
};

}

int itkNarrowBandThresholdSegmentationLevelSetImageFilterTest(int, char * [] )
{
  NBTS::ImageType::RegionType reg;
  NBTS::ImageType::RegionType::SizeType sz;
  NBTS::ImageType::RegionType::IndexType idx;
  idx[0] = idx[1] = idx[2] = 0;
  sz[0] = sz[1] = sz[2] = 64;
  reg.SetSize(sz);
  reg.SetIndex(idx);

  NBTS::ImageType::Pointer     inputImage = NBTS::ImageType::New();
  NBTS::SeedImageType::Pointer seedImage = NBTS::SeedImageType::New();
  inputImage->SetRegions(reg);
  seedImage->SetRegions(reg);
  inputImage->Allocate();
  seedImage->Allocate();

  // Starting surface is a sphere in the center of the image.
  NBTS::evaluate_function(seedImage, NBTS::sphere);

  // Target surface is a diamond
  float val;
  unsigned int i;
  //  NBTS::ImageType::IndexType idx;
  for (idx[2] = 0; idx[2] < 64; idx[2]++)
    for (idx[1] = 0; idx[1] < 64; idx[1]++)
        for (idx[0] = 0; idx[0] < 64; idx[0]++)
          {
            val = 0;
            for (i = 0; i < 3; ++i)
              {
                if (idx[i] < 32) val+=idx[i];
                else val += 64 - idx[i];
              }
            inputImage->SetPixel(idx, val);
          }

  itk::NarrowBandThresholdSegmentationLevelSetImageFilter< ::NBTS::SeedImageType, ::NBTS::ImageType>::Pointer
    filter = itk::NarrowBandThresholdSegmentationLevelSetImageFilter< ::NBTS::SeedImageType, ::NBTS::ImageType>::New();
  filter->SetInput(seedImage);
  filter->SetFeatureImage(inputImage);

  filter->SetUpperThreshold(63);
  filter->SetLowerThreshold(50);

  filter->SetMaximumRMSError(0.04); //Does not have any effect
  filter->SetMaximumIterations(10);
  filter->ReverseExpansionDirectionOn(); // Change the default behavior of the speed
                                      // function so that negative values result in
                                      // surface growth.

  itk::NBRMSCommand::Pointer c = itk::NBRMSCommand::New();
  filter->AddObserver(itk::IterationEvent(), c);
  filter->SetIsoSurfaceValue(0.5);  //<--- IMPORTANT!  Default is zero.

  try {
    filter->Update();
    std::cout << "Done first trial" << std::endl;
    // Repeat to make sure that the filter is reinitialized properly
    filter->SetMaximumIterations(8);
    filter->Update();
    std::cout << "Done second trial" << std::endl;

    //For Debugging
    //typedef itk::ImageFileWriter< ::NBTS::ImageType> WriterType;
    //WriterType::Pointer writer = WriterType::New();
    //writer->SetInput( filter->GetOutput() );
    //writer->SetFileName( "outputThreshold.mhd" );
    //writer->Write();

    //WriterType::Pointer writer3 = WriterType::New();
    //writer3->SetInput(inputImage);
    //writer3->SetFileName("inputThreshold.mhd");
    //writer3->Write();

    // typedef itk::ImageFileWriter< ::NBTS::SeedImageType> Writer2Type;
    //Writer2Type::Pointer writer2 = Writer2Type::New();
    //writer2->SetInput(seedImage);
    //writer2->SetFileName("seedThreshold.mhd");
    //writer2->Write();

    // Write the output for debugging purposes
    //       itk::ImageFileWriter<NBTS::ImageType>::Pointer writer
    //          = itk::ImageFileWriter<NBTS::ImageType>::New();
    //        itk::RawImageIO<float, 3>::Pointer io = itk::RawImageIO<float, 3>::New();
    //        io->SetFileTypeToBinary();
    //        io->SetFileDimensionality(3);
    //        io->SetByteOrderToLittleEndian();
    //        writer->SetImageIO(io);

    //        itk::CastImageFilter<NBTS::SeedImageType, NBTS::ImageType>::Pointer
    //         caster = itk::CastImageFilter<NBTS::SeedImageType, NBTS::ImageType>::New();
    //        caster->SetInput(seedImage);
    //        caster->Update();

        // writer->SetInput(caster->GetOutput());
        //     writer->SetInput(filter->GetSpeedImage());
        //        writer->SetInput(filter->GetFeatureImage());
    // writer->SetInput(inputImage);
    //        writer->SetInput(filter->GetOutput());
    //       writer->SetFileName("output.raw");
    //        writer->Write();

  }
  catch (itk::ExceptionObject &e)
    {
    std::cerr << e << std::endl;
    return 1;
    }
  return 0;
}

<|endoftext|>


<commit_before><commit_msg>[jnc_ct] fix: rename m_matchSwitchCaseId -> m_matchAcceptId<commit_after><|endoftext|>


<commit_before><commit_msg>[MuLambdaES Mutation]: Fixed segfaults/memory leaks<commit_after><|endoftext|>


<commit_before><commit_msg>Remove useless checks for webkit-min/max<commit_after><|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU General Public License as published by the Free  *
* Software Foundation; either version 2 of the License, or (at your option)   *
* any later version.                                                          *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
* more details.                                                               *
*                                                                             *
* You should have received a copy of the GNU General Public License along     *
* with this program; if not, write to the Free Software Foundation, Inc., 51  *
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
*******************************************************************************
*                            SOFA :: Applications                             *
*                                                                             *
* Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
* H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
* M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include "SofaConfiguration.h"

#include <qsizepolicy.h>
#ifdef SOFA_QT4
#include <QGroupBox>
#include <QToolBox>
#include <QSpacerItem>
#include <QPushButton>
#include <Q3Process>
#else
#include <qgroupbox.h>
#include <qtoolbox.h>
#include <qpushbutton.h>
#include <qprocess.h>
typedef QProcess Q3Process;
#endif

#include <map>
#include <algorithm>
#include <fstream>

namespace sofa
{

namespace gui
{

namespace qt
{

ConfigWidget::ConfigWidget(QWidget *parent, DEFINES &d):QWidget(parent), option(d)
{
    setName(QString(option.name.c_str()));
    layout=new QHBoxLayout(this);
    check=new QCheckBox(QString(option.name.c_str()), this);
    check->setChecked(option.value);
    check->setMaximumSize(300,20);

    layout->addWidget(check);

    connect(check, SIGNAL(toggled(bool)), this, SLOT(updateValue(bool)));
}

void ConfigWidget::updateValue(bool b)
{
    option.value=b;
    emit(modified());
}

TextConfigWidget::TextConfigWidget(QWidget *parent, DEFINES &d):ConfigWidget(parent,d)
{
    description=new QLineEdit(this);
    description->setText(option.description.c_str());
    description->setAlignment(Qt::AlignBottom | Qt::AlignLeft);
    connect(description, SIGNAL(textChanged(const QString&)), this, SLOT(updateValue(const QString&)));

    layout->addWidget(description);
}

void TextConfigWidget::updateValue(const QString &s)
{
    option.description=s.ascii();
    emit(modified());
}

OptionConfigWidget::OptionConfigWidget(QWidget *parent, DEFINES &d):ConfigWidget(parent,d)
{
    description=new QLabel(this);
    description->setText(option.description.c_str());
    description->setAlignment(Qt::AlignBottom | Qt::AlignLeft);

    layout->addWidget(description);
}

SofaConfiguration::SofaConfiguration(std::string p, std::vector< DEFINES >& config):QMainWindow(),path(p),data(config)

{
    resize(800, 600);

    QWidget *appli = new QWidget(this);
    QVBoxLayout *layout = new QVBoxLayout(appli);

    QToolBox *global = new QToolBox(appli);
    global->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum);

    std::string currentCategory;

    QWidget *page=NULL;
    QVBoxLayout *pageLayout=NULL;
    for (unsigned int i=0; i<config.size(); ++i)
    {
        if (currentCategory != config[i].category)
        {
            if (page)
            {
                pageLayout->addItem( new QSpacerItem(10,10,QSizePolicy::Expanding, QSizePolicy::Expanding));
            }
            currentCategory = config[i].category;
            page = new QWidget(global);
            global->addItem(page,QString(currentCategory.c_str()));
            pageLayout=new QVBoxLayout(page);
        }
        ConfigWidget *o;
        if (config[i].typeOption) o=new OptionConfigWidget(page, config[i]);
        else                      o=new TextConfigWidget(page, config[i]);

        pageLayout->addWidget(o);
        options.push_back(o);
        connect(o, SIGNAL(modified()), this, SLOT(updateOptions()));
    }

    if (page)
    {
        pageLayout->addItem( new QSpacerItem(10,10,QSizePolicy::Expanding, QSizePolicy::Expanding));
    }
    updateConditions();

    QPushButton *button = new QPushButton(QString("Save and Update Configuration"),appli);
    connect( button, SIGNAL(clicked()), this, SLOT(saveConfiguration()));
    layout->addWidget(global);

#ifdef WIN32
    projectVC = new QLineEdit(QString("ProjectVC8.bat"),appli);
    layout->addWidget(projectVC);
#endif

    layout->addWidget(button);

    this->setCentralWidget(appli);
}

bool SofaConfiguration::getValue(CONDITION &c)
{
    unsigned int i=0;
    for (; i<options.size(); ++i)
    {
        if (options[i]->name() == c.option)
        {
            bool presence = options[i]->getValue();
            if (c.presence && presence) return true;
            if (!c.presence && !presence) return true;
            return false;
        }
    }
    return false;
}

void SofaConfiguration::updateOptions()
{
    QWidget *option = (QWidget*)sender();

    if (dynamic_cast<OptionConfigWidget*>(option))
        optionsModified.insert(option);
    updateConditions();
}

void SofaConfiguration::processCondition(QWidget *w, CONDITION &c)
{
    switch(c.type)
    {
    case OPTION:
        w->setEnabled(getValue(c));
        break;
    case ARCHI:
        if (c.option == "win32")
        {
            if (c.presence)
            {
#ifndef WIN32
                w->hide();
#endif
            }
            else
            {
#ifdef WIN32
                w->hide();
#endif
            }
        }
        else if (c.option == "unix")
        {
            if (c.presence)
            {
#ifdef WIN32
                w->hide();
#endif
            }
            else
            {
#ifndef WIN32
                w->hide();
#endif
            }
        }
        break;
    }
}

void SofaConfiguration::updateConditions()
{
    for (unsigned int i=0; i<options.size(); ++i)
    {
        std::vector< CONDITION > &conditions=options[i]->option.conditions;
        for (unsigned int c=0; c<conditions.size(); ++c)
        {
            processCondition(options[i],conditions[c]);
        }
    }
}

void SofaConfiguration::saveConfiguration()
{
    std::ofstream out((path + std::string("/sofa-local.cfg")).c_str());
    std::string currentCategory;
    std::vector< CONDITION > currentConditions;
    for (unsigned int i=0; i<options.size(); ++i)
    {
        DEFINES &option=options[i]->option;

        bool differentConditions=false;
        if (currentConditions.size() != option.conditions.size()) differentConditions=true;
        else
        {
            for (unsigned int c=0; c<currentConditions.size() && !differentConditions; ++c)
            {
                if (currentConditions[c] != option.conditions[c]) differentConditions=true;
            }
        }

        if (differentConditions)
        {
            for (unsigned int c=0; c<currentConditions.size(); ++c) out << "}\n";

            currentConditions = option.conditions;
        }

        if (currentCategory != option.category)
        {
            if (!currentCategory.empty())  out << "\n\n";
            currentCategory = option.category;
            out << "########################################################################\n";
            out << "# " << currentCategory << "\n";
            out << "########################################################################\n";
        }

        if (differentConditions)
        {
            for (unsigned int c=0; c<currentConditions.size(); ++c)
            {
                if (!currentConditions[c].presence) out << "!";
                switch( currentConditions[c].type)
                {
                case OPTION:
                    out << "contains(DEFINES," << currentConditions[c].option << "){\n";
                    break;
                case ARCHI:
                    out << currentConditions[c].option << "{\n";
                    break;
                }
            }
        }

        if (option.typeOption)
        {
            std::string description=option.description;
            for (unsigned int position=0; position<description.size(); ++position)
            {
                if (description[position] == '\n') description.insert(position+1, "# ");
            }
            out << "\n# Uncomment " << description << "\n";
            if (!option.value) out << "# ";
            out << "DEFINES += " << option.name << "\n";
        }
        else
        {
            if (!option.value) out << "# ";
            out << option.name << " " << option.description << "\n";
        }
    }

    for (unsigned int c=0; c<currentConditions.size(); ++c) out << "}\n";

    out.close();

    std::set< QWidget *>::iterator it;
    if (!optionsModified.empty())
    {
        std::vector<QString> listDir;
        listDir.push_back(QString("/applications"));
        listDir.push_back(QString("/modules"));
        listDir.push_back(QString("/framework"));
        listDir.push_back(QString("/extlibs"));

        std::set< QWidget *>::iterator it;
        for (it=optionsModified.begin(); it!=optionsModified.end(); it++)
            std::cout << "Touch file containing option \"" <<(*it)->name() << "\" ";
        std::cout << "in [ ";
        for (unsigned int i=0; i<listDir.size(); ++i)
            std::cout << listDir[i].ascii() << " ";
        std::cout << "]" << std::endl;

        for (unsigned int i=0; i<listDir.size(); ++i)
        {
            std::cout << "   Searching in " << listDir[i].ascii() << "\n";
            processDirectory(listDir[i]);
        }

        QStringList argv;
#ifndef WIN32
#if SOFA_QT4
        argv << QString("qmake-qt4");
#else
        argv << QString("qmake");
#endif
#else
        argv << QString(path.c_str()) + QString("/") + QString(projectVC->text());
#endif
        Q3Process *p = new Q3Process(argv,this);
        p->setCommunication(0);
        p->setWorkingDirectory(QDir(QString(path.c_str())));
        p->start();

        optionsModified.clear();
    }
}

void SofaConfiguration::processDirectory(const QString &dir)
{

    QDir d(QString(path.c_str())+dir);

    d.setFilter( QDir::Dirs | QDir::Hidden | QDir::NoSymLinks );

    std::vector< QString > subDir;

    const QFileInfoList &listDirectories =
#ifdef SOFA_QT4
        d.entryInfoList();
    for (int j = 0; j < listDirectories.size(); ++j)
    {
        QFileInfo fileInfo=listDirectories.at(j);
#else
        *(d.entryInfoList());
    QFileInfoListIterator it( listDirectories );
    while ( (fi = itFile.current()) != 0 )
    {
        QFileInfo fileInfo=*(itFile.current());
#endif
        subDir.push_back(fileInfo.fileName());
#ifndef SOFA_QT4
        ++itFile;
#endif
    }

    QStringList filters; filters << "*.cpp" << "*.h" << "*.inl";
    d.setNameFilters(filters);
    d.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks );

    std::vector< QString > filesInside;

    const QFileInfoList &listFiles =
#ifdef SOFA_QT4
        d.entryInfoList();
    for (int j = 0; j < listFiles.size(); ++j)
    {
        QFileInfo fileInfo=listFiles.at(j);
#else
        *(d.entryInfoList(filter));
    QFileInfoListIterator it( listFiles );
    while ( (fi = itFile.current()) != 0 )
    {
        QFileInfo fileInfo=*(itFile.current());
#endif
        filesInside.push_back(fileInfo.fileName());
        processFile(fileInfo);
#ifndef SOFA_QT4
        ++itFile;
#endif
    }

    for (unsigned int i=0; i<subDir.size(); ++i)
    {
        if (subDir[i].left(1) == QString(".")) continue;
        if (subDir[i] == QString("OBJ"))       continue;

        QString nextDir=dir+QString("/")+subDir[i];
        processDirectory(nextDir);
    }
}

void SofaConfiguration::processFile(const QFileInfo &info)
{
    std::fstream file;
    file.open(info.absFilePath(), std::ios::in | std::ios::out);
    std::string line;
    while (std::getline(file, line))
    {
        std::set< QWidget *>::iterator it;
        for (it=optionsModified.begin(); it!=optionsModified.end(); it++)
        {
            std::string option((*it)->name());
            if (line.find(option.c_str()) != std::string::npos)
            {
                //Touch the file
                file.seekg(0);
                char space; file.get(space);
                file.seekg(0);
                file.put(space);
                std::cout << "      found in " << info.absFilePath().ascii() << std::endl;
                return;
            }
        }
    }
    file.close();
}
}
}
}
<commit_msg>r4528/sofa-dev : FIX: compatibility QT3-4<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU General Public License as published by the Free  *
* Software Foundation; either version 2 of the License, or (at your option)   *
* any later version.                                                          *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
* more details.                                                               *
*                                                                             *
* You should have received a copy of the GNU General Public License along     *
* with this program; if not, write to the Free Software Foundation, Inc., 51  *
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
*******************************************************************************
*                            SOFA :: Applications                             *
*                                                                             *
* Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
* H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
* M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include "SofaConfiguration.h"

#include <qsizepolicy.h>
#ifdef SOFA_QT4
#include <QGroupBox>
#include <QToolBox>
#include <QSpacerItem>
#include <QPushButton>
#include <Q3Process>
#else
#include <qgroupbox.h>
#include <qtoolbox.h>
#include <qpushbutton.h>
#include <qprocess.h>
typedef QProcess Q3Process;
#endif

#include <map>
#include <algorithm>
#include <fstream>

namespace sofa
{

namespace gui
{

namespace qt
{

ConfigWidget::ConfigWidget(QWidget *parent, DEFINES &d):QWidget(parent), option(d)
{
    setName(QString(option.name.c_str()));
    layout=new QHBoxLayout(this);
    check=new QCheckBox(QString(option.name.c_str()), this);
    check->setChecked(option.value);
    check->setMaximumSize(300,20);

    layout->addWidget(check);

    connect(check, SIGNAL(toggled(bool)), this, SLOT(updateValue(bool)));
}

void ConfigWidget::updateValue(bool b)
{
    option.value=b;
    emit(modified());
}

TextConfigWidget::TextConfigWidget(QWidget *parent, DEFINES &d):ConfigWidget(parent,d)
{
    description=new QLineEdit(this);
    description->setText(option.description.c_str());
    description->setAlignment(Qt::AlignBottom | Qt::AlignLeft);
    connect(description, SIGNAL(textChanged(const QString&)), this, SLOT(updateValue(const QString&)));

    layout->addWidget(description);
}

void TextConfigWidget::updateValue(const QString &s)
{
    option.description=s.ascii();
    emit(modified());
}

OptionConfigWidget::OptionConfigWidget(QWidget *parent, DEFINES &d):ConfigWidget(parent,d)
{
    description=new QLabel(this);
    description->setText(option.description.c_str());
    description->setAlignment(Qt::AlignBottom | Qt::AlignLeft);

    layout->addWidget(description);
}

SofaConfiguration::SofaConfiguration(std::string p, std::vector< DEFINES >& config):QMainWindow(),path(p),data(config)

{
    resize(800, 600);

    QWidget *appli = new QWidget(this);
    QVBoxLayout *layout = new QVBoxLayout(appli);

    QToolBox *global = new QToolBox(appli);
    global->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Minimum);

    std::string currentCategory;

    QWidget *page=NULL;
    QVBoxLayout *pageLayout=NULL;
    for (unsigned int i=0; i<config.size(); ++i)
    {
        if (currentCategory != config[i].category)
        {
            if (page)
            {
                pageLayout->addItem( new QSpacerItem(10,10,QSizePolicy::Expanding, QSizePolicy::Expanding));
            }
            currentCategory = config[i].category;
            page = new QWidget(global);
            global->addItem(page,QString(currentCategory.c_str()));
            pageLayout=new QVBoxLayout(page);
        }
        ConfigWidget *o;
        if (config[i].typeOption) o=new OptionConfigWidget(page, config[i]);
        else                      o=new TextConfigWidget(page, config[i]);

        pageLayout->addWidget(o);
        options.push_back(o);
        connect(o, SIGNAL(modified()), this, SLOT(updateOptions()));
    }

    if (page)
    {
        pageLayout->addItem( new QSpacerItem(10,10,QSizePolicy::Expanding, QSizePolicy::Expanding));
    }
    updateConditions();

    QPushButton *button = new QPushButton(QString("Save and Update Configuration"),appli);
    connect( button, SIGNAL(clicked()), this, SLOT(saveConfiguration()));
    layout->addWidget(global);

#ifdef WIN32
    projectVC = new QLineEdit(QString("ProjectVC8.bat"),appli);
    layout->addWidget(projectVC);
#endif

    layout->addWidget(button);

    this->setCentralWidget(appli);
}

bool SofaConfiguration::getValue(CONDITION &c)
{
    unsigned int i=0;
    for (; i<options.size(); ++i)
    {
        if (options[i]->name() == c.option)
        {
            bool presence = options[i]->getValue();
            if (c.presence && presence) return true;
            if (!c.presence && !presence) return true;
            return false;
        }
    }
    return false;
}

void SofaConfiguration::updateOptions()
{
    QWidget *option = (QWidget*)sender();

    if (dynamic_cast<OptionConfigWidget*>(option))
        optionsModified.insert(option);
    updateConditions();
}

void SofaConfiguration::processCondition(QWidget *w, CONDITION &c)
{
    switch(c.type)
    {
    case OPTION:
        w->setEnabled(getValue(c));
        break;
    case ARCHI:
        if (c.option == "win32")
        {
            if (c.presence)
            {
#ifndef WIN32
                w->hide();
#endif
            }
            else
            {
#ifdef WIN32
                w->hide();
#endif
            }
        }
        else if (c.option == "unix")
        {
            if (c.presence)
            {
#ifdef WIN32
                w->hide();
#endif
            }
            else
            {
#ifndef WIN32
                w->hide();
#endif
            }
        }
        break;
    }
}

void SofaConfiguration::updateConditions()
{
    for (unsigned int i=0; i<options.size(); ++i)
    {
        std::vector< CONDITION > &conditions=options[i]->option.conditions;
        for (unsigned int c=0; c<conditions.size(); ++c)
        {
            processCondition(options[i],conditions[c]);
        }
    }
}

void SofaConfiguration::saveConfiguration()
{
    std::ofstream out((path + std::string("/sofa-local.cfg")).c_str());
    std::string currentCategory;
    std::vector< CONDITION > currentConditions;
    for (unsigned int i=0; i<options.size(); ++i)
    {
        DEFINES &option=options[i]->option;

        bool differentConditions=false;
        if (currentConditions.size() != option.conditions.size()) differentConditions=true;
        else
        {
            for (unsigned int c=0; c<currentConditions.size() && !differentConditions; ++c)
            {
                if (currentConditions[c] != option.conditions[c]) differentConditions=true;
            }
        }

        if (differentConditions)
        {
            for (unsigned int c=0; c<currentConditions.size(); ++c) out << "}\n";

            currentConditions = option.conditions;
        }

        if (currentCategory != option.category)
        {
            if (!currentCategory.empty())  out << "\n\n";
            currentCategory = option.category;
            out << "########################################################################\n";
            out << "# " << currentCategory << "\n";
            out << "########################################################################\n";
        }

        if (differentConditions)
        {
            for (unsigned int c=0; c<currentConditions.size(); ++c)
            {
                if (!currentConditions[c].presence) out << "!";
                switch( currentConditions[c].type)
                {
                case OPTION:
                    out << "contains(DEFINES," << currentConditions[c].option << "){\n";
                    break;
                case ARCHI:
                    out << currentConditions[c].option << "{\n";
                    break;
                }
            }
        }

        if (option.typeOption)
        {
            std::string description=option.description;
            for (unsigned int position=0; position<description.size(); ++position)
            {
                if (description[position] == '\n') description.insert(position+1, "# ");
            }
            out << "\n# Uncomment " << description << "\n";
            if (!option.value) out << "# ";
            out << "DEFINES += " << option.name << "\n";
        }
        else
        {
            if (!option.value) out << "# ";
            out << option.name << " " << option.description << "\n";
        }
    }

    for (unsigned int c=0; c<currentConditions.size(); ++c) out << "}\n";

    out.close();

    std::set< QWidget *>::iterator it;
    if (!optionsModified.empty())
    {
        std::vector<QString> listDir;
        listDir.push_back(QString("/applications"));
        listDir.push_back(QString("/modules"));
        listDir.push_back(QString("/framework"));
        listDir.push_back(QString("/extlibs"));

        std::set< QWidget *>::iterator it;
        for (it=optionsModified.begin(); it!=optionsModified.end(); it++)
            std::cout << "Touch file containing option \"" <<(*it)->name() << "\" ";
        std::cout << "in [ ";
        for (unsigned int i=0; i<listDir.size(); ++i)
            std::cout << listDir[i].ascii() << " ";
        std::cout << "]" << std::endl;

        for (unsigned int i=0; i<listDir.size(); ++i)
        {
            std::cout << "   Searching in " << listDir[i].ascii() << "\n";
            processDirectory(listDir[i]);
        }

        QStringList argv;
#ifndef WIN32
#if SOFA_QT4
        argv << QString("qmake-qt4");
#else
        argv << QString("qmake");
#endif
#else
        argv << QString(path.c_str()) + QString("/") + QString(projectVC->text());
#endif
        Q3Process *p = new Q3Process(argv,this);
        p->setCommunication(0);
        p->setWorkingDirectory(QDir(QString(path.c_str())));
        p->start();

        optionsModified.clear();
    }
}

void SofaConfiguration::processDirectory(const QString &dir)
{

    QDir d(QString(path.c_str())+dir);

    d.setFilter( QDir::Dirs | QDir::Hidden | QDir::NoSymLinks );

    std::vector< QString > subDir;

    const QFileInfoList &listDirectories =
#ifdef SOFA_QT4
        d.entryInfoList();
    QStringList filters; filters << "*.cpp" << "*.h" << "*.inl";
    d.setNameFilters(filters);
    for (int j = 0; j < listDirectories.size(); ++j)
    {
        QFileInfo fileInfo=listDirectories.at(j);
#else
        *(d.entryInfoList());
    QString filters="*.cpp *.h *.inl";
    d.setNameFilter(filters);
    QFileInfoListIterator itDir( listDirectories );
    while ( (itDir.current()) != 0 )
    {

        QFileInfo fileInfo=*(itDir.current());
#endif
        subDir.push_back(fileInfo.fileName());
#ifndef SOFA_QT4
        ++itDir;
#endif
    }

    d.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks );

    std::vector< QString > filesInside;

    const QFileInfoList &listFiles =
#ifdef SOFA_QT4
        d.entryInfoList();
    for (int j = 0; j < listFiles.size(); ++j)
    {
        QFileInfo fileInfo=listFiles.at(j);
#else
        *(d.entryInfoList());
    QFileInfoListIterator itFile( listFiles );
    while ( (itFile.current()) != 0 )
    {
        QFileInfo fileInfo=*(itFile.current());
#endif
        filesInside.push_back(fileInfo.fileName());
        processFile(fileInfo);
#ifndef SOFA_QT4
        ++itFile;
#endif
    }

    for (unsigned int i=0; i<subDir.size(); ++i)
    {
        if (subDir[i].left(1) == QString(".")) continue;
        if (subDir[i] == QString("OBJ"))       continue;

        QString nextDir=dir+QString("/")+subDir[i];
        processDirectory(nextDir);
    }
}

void SofaConfiguration::processFile(const QFileInfo &info)
{
    std::fstream file;
    file.open(info.absFilePath(), std::ios::in | std::ios::out);
    std::string line;
    while (std::getline(file, line))
    {
        std::set< QWidget *>::iterator it;
        for (it=optionsModified.begin(); it!=optionsModified.end(); it++)
        {
            std::string option((*it)->name());
            if (line.find(option.c_str()) != std::string::npos)
            {
                //Touch the file
                file.seekg(0);
                char space; file.get(space);
                file.seekg(0);
                file.put(space);
                std::cout << "      found in " << info.absFilePath().ascii() << std::endl;
                return;
            }
        }
    }
    file.close();
}
}
}
}
<|endoftext|>


<commit_before><commit_msg>track param working correctly again with correct settings.dat<commit_after><|endoftext|>


<commit_before><commit_msg>[core] Make sure {ADD,SUB}{P,S}{S,D} have a bypass delay<commit_after><|endoftext|>


<commit_before>//
// Copyright 2017 Shivansh Rai
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. 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.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
//
// $FreeBSD$

#include <array>
#include <boost/thread.hpp>
#include <cstdlib>
#include <dirent.h>
#include <fstream>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unordered_set>
#include "generate_test.h"
#include "add_testcase.h"
#include "read_annotations.h"

std::pair<std::string, int>
generate_test::exec(const char* cmd)
{
  const int bufsize = 128;
  std::array<char, bufsize> buffer;
  std::string usage_output;
  FILE* pipe = popen(cmd, "r");

  if (!pipe)
    throw std::runtime_error("popen() failed!");

  try {
    while (!feof(pipe))
      if (std::fgets(buffer.data(), bufsize, pipe) != NULL)
        usage_output += buffer.data();
  }
  catch(...) {
    pclose(pipe);
    throw "Unable to execute the command: " + std::string(cmd);
  }

  return std::make_pair<std::string, int>
         ((std::string)usage_output, WEXITSTATUS(pclose(pipe)));
}

void
generate_test::generate_test(std::string utility, std::string section)
{
  std::list<utils::opt_rel*> ident_opt_list;  // List of identified option relations.
  std::vector<std::string> usage_messages;    // Vector to store usage messages for comparison.
  std::string command;                        // Command to be executed in shell.
  std::string descr;                          // Testcase description.
  std::string testcase_list;                  // List of testcases.
  std::string testcase_buffer;                // Buffer for (temporarily) holding testcase data.
  std::string test_file;                      // atf-sh test name.
  std::string util_with_section;              // Section number appended to utility.
  std::ofstream test_ofs;                     // Output stream for the atf-sh test.
  std::ifstream license_ifs;                  // Input stream for license.
  std::pair<std::string, int> output;         // Return value type for `exec()`.
  std::unordered_set<std::string> annot;      // Hashset of utility specific annotations.

  // Read annotations and populate hash set "annot".
  annotations::read_annotations(utility, annot);

  util_with_section = utility + '(' + section + ')';

  utils::opt_def f_opts;
  ident_opt_list = f_opts.check_opts(utility);
  test_file = "generated_tests/" + utility + "_test.sh";

  // Add license in the generated test scripts.
  test_ofs.open(test_file, std::ios::out);
  license_ifs.open("license", std::ios::in);

  test_ofs << license_ifs.rdbuf();
  license_ifs.close();

  // If a known option was encountered (i.e. `ident_opt_list` is
  // populated), produce a testcase to check the validity of the
  // result of that option. If no known option was encountered,
  // produce testcases to verify the correct (generated) usage
  // message when using the supported options incorrectly.

  // Add testcases for known options.
  if (!ident_opt_list.empty()) {
    for (const auto &i : ident_opt_list) {
      command = utility + " -" + i->value + " 2>&1";
      output = generate_test::exec(command.c_str());
      if (!output.first.compare(0, 6, "usage:")) {
        add_testcase::add_known_testcase(i->value, util_with_section,
                                         descr, output.first, test_ofs);
      }
      else {
        // A usage message was produced, i.e. we
        // failed to guess the correct usage.
        add_testcase::add_unknown_testcase(i->value, util_with_section, output.first,
                                           output.second, testcase_buffer);
      }
      testcase_list.append("\tatf_add_test_case " + i->value + "_flag\n");
    }
  }

  // Add testcases for the options whose usage is not known (yet).
  if (!f_opts.opt_list.empty()) {

    // For the purpose of adding a "$usage_output" variable,
    // we choose the option which produces one.
    // TODO Avoid double executions of an option, i.e. one while
    // selecting usage message and another while generating testcase.

    if (f_opts.opt_list.size() == 1) {
      // Utility supports a single option, check if it produces a usage message.
      command = utility + " -" + f_opts.opt_list.front() + " 2>&1";
      output = generate_test::exec(command.c_str());

      if (output.second)
        test_ofs << "usage_output=\'" + output.first + "\'\n\n";
    }

    else {
      // Utility supports multiple options. In case the usage message
      // is consistent for atleast "two" options, we reduce duplication
      // by assigning a variable "usage_output" in the test script.
      for (const auto &i : f_opts.opt_list) {
        command = utility + " -" + i + " 2>&1";
        output = generate_test::exec(command.c_str());

        if (output.second && usage_messages.size() < 3)
          usage_messages.push_back(output.first);
      }

      for (int j = 0; j <= 3; j++) {
        if (!(usage_messages[j]).compare(usage_messages[(j+1) % 3])) {
          test_ofs << "usage_output=\'"
                    + output.first.substr(0, 7 + utility.size())
                    + "\'\n\n";
          break;
        }
      }
    }

    // Execute the utility with supported options
    // and add (+ve)/(-ve) testcases accordingly.
    for (const auto &i : f_opts.opt_list) {
      // If the option is annotated, skip it.
      if (annot.find(i) != annot.end())
        continue;

      command = utility + " -" + i + " 2>&1";
      output = generate_test::exec(command.c_str());

      if (output.second) {
        // Non-zero exit status was encountered.
        add_testcase::add_unknown_testcase(i, util_with_section, output.first,
                                           output.second, testcase_buffer);
      }
      else {
        // EXIT_SUCCESS was encountered. Hence,
        // the guessed usage was correct.
        add_testcase::add_known_testcase(i, util_with_section, "",
                                         output.first, test_ofs);
        testcase_list.append(std::string("\tatf_add_test_case ")
                            + i + "_flag\n");
      }
    }

    testcase_list.append("\tatf_add_test_case invalid_usage\n");
    test_ofs << std::string("atf_test_case invalid_usage\ninvalid_usage_head()\n")
                          + "{\n\tatf_set \"descr\" \"Verify that an invalid usage "
                          + "with a supported option produces a valid error message"
                          + "\"\n}\n\ninvalid_usage_body()\n{";

    test_ofs << testcase_buffer + "\n}\n\n";
  }

  // Add a testcase under "no_arguments" for
  // running the utility without any arguments.
  if (annot.find("*") == annot.end()) {
    command = utility + " 2>&1";
    output = generate_test::exec(command.c_str());
    add_testcase::add_noargs_testcase(util_with_section, output, test_ofs);
    testcase_list.append("\tatf_add_test_case no_arguments\n");
  }

  test_ofs << "atf_init_test_cases()\n{\n" + testcase_list + "}\n";
  test_ofs.close();
}

int
main()
{
  std::ifstream groff_list;
  std::list<std::pair<std::string, std::string>> utility_list;
  std::string test_file;  // atf-sh test name.
  std::string util_name;  // Utility name.
  struct stat buffer;
  struct dirent *ent;
  DIR *dir;
  char answer;            // User input to determine overwriting of test files.
  int flag = 0;

  // For testing (or generating tests for only selected utilities),
  // the utility_list can be populated above during declaration.
  if (utility_list.empty()) {
    if ((dir = opendir("groff"))) {
      while ((ent = readdir(dir))) {
        util_name = ent->d_name;
        utility_list.push_back(std::make_pair<std::string, std::string>
                              (util_name.substr(0, util_name.length() - 2),
                               util_name.substr(util_name.length() - 1, 1)));
      }
      closedir(dir);
    }
    else {
      fprintf(stderr, "Could not open directory: groff/");
      return EXIT_FAILURE;
    }
  }

  for (const auto &util : utility_list) {
    test_file = "generated_tests/" + util.first + "_test.sh";

    // Check if the test file already exists. In
    // case it does, confirm before proceeding.
    if (!flag && !stat(test_file.c_str(), &buffer)) {
      std::cout << "Test file(s) already exists. Overwrite? [y/n] ";
      std::cin >> answer;

      switch (answer) {
        case 'n':
        case 'N':
          fprintf(stderr, "Stopping execution\n");
          flag = 1;
          break;

        default:
          // TODO capture newline character
          flag = 1;
          break;
      }
    }

    std::cout << "Generating test for: " + util.first
               + '('+ util.second + ')' << " ...";

    boost::thread api_caller(generate_test::generate_test, util.first, util.second);
    if (api_caller.timed_join(boost::posix_time::seconds(1))) {
      // API call returned withing 1 second.
      std::cout << "Successful\n";
    }
    else {
      // API call timed out.
      std::cout << "Failed!\n";
    }
  }

  return EXIT_SUCCESS;
}
<commit_msg>Fix out of bounds error<commit_after>//
// Copyright 2017 Shivansh Rai
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. 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.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
//
// $FreeBSD$

#include <array>
#include <boost/thread.hpp>
#include <cstdlib>
#include <dirent.h>
#include <fstream>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unordered_set>
#include "generate_test.h"
#include "add_testcase.h"
#include "read_annotations.h"

std::pair<std::string, int>
generate_test::exec(const char* cmd)
{
  const int bufsize = 128;
  std::array<char, bufsize> buffer;
  std::string usage_output;
  FILE* pipe = popen(cmd, "r");

  if (!pipe)
    throw std::runtime_error("popen() failed!");

  try {
    while (!feof(pipe))
      if (std::fgets(buffer.data(), bufsize, pipe) != NULL)
        usage_output += buffer.data();
  }
  catch(...) {
    pclose(pipe);
    throw "Unable to execute the command: " + std::string(cmd);
  }

  return std::make_pair<std::string, int>
         ((std::string)usage_output, WEXITSTATUS(pclose(pipe)));
}

void
generate_test::generate_test(std::string utility, std::string section)
{
  std::list<utils::opt_rel*> ident_opt_list;  // List of identified option relations.
  std::vector<std::string> usage_messages;    // Vector to store usage messages for comparison.
  std::string command;                        // Command to be executed in shell.
  std::string descr;                          // Testcase description.
  std::string testcase_list;                  // List of testcases.
  std::string testcase_buffer;                // Buffer for (temporarily) holding testcase data.
  std::string test_file;                      // atf-sh test name.
  std::string util_with_section;              // Section number appended to utility.
  std::ofstream test_ofs;                     // Output stream for the atf-sh test.
  std::ifstream license_ifs;                  // Input stream for license.
  std::pair<std::string, int> output;         // Return value type for `exec()`.
  std::unordered_set<std::string> annot;      // Hashset of utility specific annotations.
  int temp;

  // Read annotations and populate hash set "annot".
  annotations::read_annotations(utility, annot);

  util_with_section = utility + '(' + section + ')';

  utils::opt_def f_opts;
  ident_opt_list = f_opts.check_opts(utility);
  test_file = "generated_tests/" + utility + "_test.sh";

  // Add license in the generated test scripts.
  test_ofs.open(test_file, std::ios::out);
  license_ifs.open("license", std::ios::in);

  test_ofs << license_ifs.rdbuf();
  license_ifs.close();

  // If a known option was encountered (i.e. `ident_opt_list` is
  // populated), produce a testcase to check the validity of the
  // result of that option. If no known option was encountered,
  // produce testcases to verify the correct (generated) usage
  // message when using the supported options incorrectly.

  // Add testcases for known options.
  if (!ident_opt_list.empty()) {
    for (const auto &i : ident_opt_list) {
      command = utility + " -" + i->value + " 2>&1";
      output = generate_test::exec(command.c_str());
      if (!output.first.compare(0, 6, "usage:")) {
        add_testcase::add_known_testcase(i->value, util_with_section,
                                         descr, output.first, test_ofs);
      }
      else {
        // A usage message was produced, i.e. we
        // failed to guess the correct usage.
        add_testcase::add_unknown_testcase(i->value, util_with_section, output.first,
                                           output.second, testcase_buffer);
      }
      testcase_list.append("\tatf_add_test_case " + i->value + "_flag\n");
    }
  }

  // Add testcases for the options whose usage is not known (yet).
  if (!f_opts.opt_list.empty()) {

    // For the purpose of adding a "$usage_output" variable,
    // we choose the option which produces one.
    // TODO Avoid double executions of an option, i.e. one while
    // selecting usage message and another while generating testcase.

    if (f_opts.opt_list.size() == 1) {
      // Utility supports a single option, check if it produces a usage message.
      command = utility + " -" + f_opts.opt_list.front() + " 2>&1";
      output = generate_test::exec(command.c_str());

      if (output.second)
        test_ofs << "usage_output=\'" + output.first + "\'\n\n";
    }

    else {
      // Utility supports multiple options. In case the usage message
      // is consistent for atleast "two" options, we reduce duplication
      // by assigning a variable "usage_output" in the test script.
      for (const auto &i : f_opts.opt_list) {
        command = utility + " -" + i + " 2>&1";
        output = generate_test::exec(command.c_str());

        if (output.second && usage_messages.size() < 3)
          usage_messages.push_back(output.first);
      }

      temp = usage_messages.size();
      for (int j = 0; j < temp; j++) {
        if (!(usage_messages.at(j)).compare(usage_messages.at((j+1) % temp))) {
          test_ofs << "usage_output=\'"
                    + output.first.substr(0, 7 + utility.size())
                    + "\'\n\n";
          break;
        }
      }
    }

    // Execute the utility with supported options
    // and add (+ve)/(-ve) testcases accordingly.
    for (const auto &i : f_opts.opt_list) {
      // If the option is annotated, skip it.
      if (annot.find(i) != annot.end())
        continue;

      command = utility + " -" + i + " 2>&1";
      output = generate_test::exec(command.c_str());

      if (output.second) {
        // Non-zero exit status was encountered.
        add_testcase::add_unknown_testcase(i, util_with_section, output.first,
                                           output.second, testcase_buffer);
      }
      else {
        // EXIT_SUCCESS was encountered. Hence,
        // the guessed usage was correct.
        add_testcase::add_known_testcase(i, util_with_section, "",
                                         output.first, test_ofs);
        testcase_list.append(std::string("\tatf_add_test_case ")
                            + i + "_flag\n");
      }
    }

    testcase_list.append("\tatf_add_test_case invalid_usage\n");
    test_ofs << std::string("atf_test_case invalid_usage\ninvalid_usage_head()\n")
                          + "{\n\tatf_set \"descr\" \"Verify that an invalid usage "
                          + "with a supported option produces a valid error message"
                          + "\"\n}\n\ninvalid_usage_body()\n{";

    test_ofs << testcase_buffer + "\n}\n\n";
  }

  // Add a testcase under "no_arguments" for
  // running the utility without any arguments.
  if (annot.find("*") == annot.end()) {
    command = utility + " 2>&1";
    output = generate_test::exec(command.c_str());
    add_testcase::add_noargs_testcase(util_with_section, output, test_ofs);
    testcase_list.append("\tatf_add_test_case no_arguments\n");
  }

  test_ofs << "atf_init_test_cases()\n{\n" + testcase_list + "}\n";
  test_ofs.close();
}

int
main()
{
  std::ifstream groff_list;
  std::list<std::pair<std::string, std::string>> utility_list;
  std::string test_file;  // atf-sh test name.
  std::string util_name;  // Utility name.
  struct stat buffer;
  struct dirent *ent;
  DIR *dir;
  char answer;            // User input to determine overwriting of test files.
  int flag = 0;

  // For testing (or generating tests for only selected utilities),
  // the utility_list can be populated above during declaration.
  if (utility_list.empty()) {
    if ((dir = opendir("groff"))) {
      while ((ent = readdir(dir))) {
        util_name = ent->d_name;
        utility_list.push_back(std::make_pair<std::string, std::string>
                              (util_name.substr(0, util_name.length() - 2),
                               util_name.substr(util_name.length() - 1, 1)));
      }
      closedir(dir);
    }
    else {
      fprintf(stderr, "Could not open directory: groff/");
      return EXIT_FAILURE;
    }
  }

  for (const auto &util : utility_list) {
    test_file = "generated_tests/" + util.first + "_test.sh";

    // Check if the test file already exists. In
    // case it does, confirm before proceeding.
    if (!flag && !stat(test_file.c_str(), &buffer)) {
      std::cout << "Test file(s) already exists. Overwrite? [y/n] ";
      std::cin >> answer;

      switch (answer) {
        case 'n':
        case 'N':
          fprintf(stderr, "Stopping execution\n");
          flag = 1;
          break;

        default:
          // TODO capture newline character
          flag = 1;
          break;
      }
    }

    std::cout << "Generating test for: " + util.first
               + '('+ util.second + ')' << " ...";

    boost::thread api_caller(generate_test::generate_test, util.first, util.second);
    if (api_caller.timed_join(boost::posix_time::seconds(1))) {
      // API call returned within 1 second.
      std::cout << "Successful\n";
    }
    else {
      // API call timed out.
      std::cout << "Failed!\n";
      // Remove the incomplete test file.
      remove(("generated_tests/" + util.first + "_test.sh").c_str());
    }
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "CrashHandler.h"

#include "SkTypes.h"

#include <stdlib.h>

// Disable SetupCrashHandler() unless SK_CRASH_HANDLER is defined.
#ifndef SK_CRASH_HANDLER
    void SetupCrashHandler() { }

#elif defined(GOOGLE3)
    #include "base/process_state.h"
    void SetupCrashHandler() { InstallSignalHandlers(); }

#else

    #if defined(SK_BUILD_FOR_MAC)

        // We only use local unwinding, so we can define this to select a faster implementation.
        #define UNW_LOCAL_ONLY
        #include <libunwind.h>
        #include <cxxabi.h>

        static void handler(int sig) {
            unw_context_t context;
            unw_getcontext(&context);

            unw_cursor_t cursor;
            unw_init_local(&cursor, &context);

            SkDebugf("\nSignal %d:\n", sig);
            while (unw_step(&cursor) > 0) {
                static const size_t kMax = 256;
                char mangled[kMax], demangled[kMax];
                unw_word_t offset;
                unw_get_proc_name(&cursor, mangled, kMax, &offset);

                int ok;
                size_t len = kMax;
                abi::__cxa_demangle(mangled, demangled, &len, &ok);

                SkDebugf("%s (+0x%zx)\n", ok == 0 ? demangled : mangled, (size_t)offset);
            }
            SkDebugf("\n");

            // Exit NOW.  Don't notify other threads, don't call anything registered with atexit().
            _Exit(sig);
        }

    #elif defined(SK_BUILD_FOR_UNIX)

        // We'd use libunwind here too, but it's a pain to get installed for
        // both 32 and 64 bit on bots.  Doesn't matter much: catchsegv is best anyway.
        #include <execinfo.h>

        static void handler(int sig) {
            static const int kMax = 64;
            void* stack[kMax];
            const int count = backtrace(stack, kMax);

            SkDebugf("\nSignal %d [%s]:\n", sig, strsignal(sig));
            backtrace_symbols_fd(stack, count, 2/*stderr*/);

            // Exit NOW.  Don't notify other threads, don't call anything registered with atexit().
            _Exit(sig);
        }

    #endif

    #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX)
        #include <signal.h>

        void SetupCrashHandler() {
            static const int kSignals[] = {
                SIGABRT,
                SIGBUS,
                SIGFPE,
                SIGILL,
                SIGSEGV,
            };

            for (size_t i = 0; i < sizeof(kSignals) / sizeof(kSignals[0]); i++) {
                // Register our signal handler unless something's already done so (e.g. catchsegv).
                void (*prev)(int) = signal(kSignals[i], handler);
                if (prev != SIG_DFL) {
                    signal(kSignals[i], prev);
                }
            }
        }

    #elif defined(SK_CRASH_HANDLER) && defined(SK_BUILD_FOR_WIN)

        #include <DbgHelp.h>

        static const struct {
            const char* name;
            int code;
        } kExceptions[] = {
        #define _(E) {#E, E}
            _(EXCEPTION_ACCESS_VIOLATION),
            _(EXCEPTION_BREAKPOINT),
            _(EXCEPTION_INT_DIVIDE_BY_ZERO),
            _(EXCEPTION_STACK_OVERFLOW),
            // TODO: more?
        #undef _
        };

        static LONG WINAPI handler(EXCEPTION_POINTERS* e) {
            const DWORD code = e->ExceptionRecord->ExceptionCode;
            SkDebugf("\nCaught exception %u", code);
            for (size_t i = 0; i < SK_ARRAY_COUNT(kExceptions); i++) {
                if (kExceptions[i].code == code) {
                    SkDebugf(" %s", kExceptions[i].name);
                }
            }
            SkDebugf("\n");

            // We need to run SymInitialize before doing any of the stack walking below.
            HANDLE hProcess = GetCurrentProcess();
            SymInitialize(hProcess, 0, true);

            STACKFRAME64 frame;
            sk_bzero(&frame, sizeof(frame));
            // Start frame off from the frame that triggered the exception.
            CONTEXT* c = e->ContextRecord;
            frame.AddrPC.Mode      = AddrModeFlat;
            frame.AddrStack.Mode   = AddrModeFlat;
            frame.AddrFrame.Mode   = AddrModeFlat;
        #if defined(_X86_)
            frame.AddrPC.Offset    = c->Eip;
            frame.AddrStack.Offset = c->Esp;
            frame.AddrFrame.Offset = c->Ebp;
            const DWORD machineType = IMAGE_FILE_MACHINE_I386;
        #elif defined(_AMD64_)
            frame.AddrPC.Offset    = c->Rip;
            frame.AddrStack.Offset = c->Rsp;
            frame.AddrFrame.Offset = c->Rbp;
            const DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
        #endif

            while (StackWalk64(machineType,
                               GetCurrentProcess(),
                               GetCurrentThread(),
                               &frame,
                               c,
                               nullptr,
                               SymFunctionTableAccess64,
                               SymGetModuleBase64,
                               nullptr)) {
                // Buffer to store symbol name in.
                static const int kMaxNameLength = 1024;
                uint8_t buffer[sizeof(IMAGEHLP_SYMBOL64) + kMaxNameLength];
                sk_bzero(buffer, sizeof(buffer));

                // We have to place IMAGEHLP_SYMBOL64 at the front, and fill in
                // how much space it can use.
                IMAGEHLP_SYMBOL64* symbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(&buffer);
                symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
                symbol->MaxNameLength = kMaxNameLength - 1;

                // Translate the current PC into a symbol and byte offset from the symbol.
                DWORD64 offset;
                SymGetSymFromAddr64(hProcess, frame.AddrPC.Offset, &offset, symbol);

                SkDebugf("%s +%x\n", symbol->Name, offset);
            }

            // Exit NOW.  Don't notify other threads, don't call anything registered with atexit().
            _exit(1);

            // The compiler wants us to return something.  This is what we'd do
            // if we didn't _exit().
            return EXCEPTION_EXECUTE_HANDLER;
        }

        void SetupCrashHandler() {
            SetUnhandledExceptionFilter(handler);
        }

    #else  // We asked for SK_CRASH_HANDLER, but it's not Mac, Linux, or Windows.  Sorry!

        void SetupCrashHandler() { }

    #endif
#endif // SK_CRASH_HANDLER
<commit_msg>Don't convert DWORD to int.<commit_after>/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "CrashHandler.h"

#include "SkTypes.h"

#include <stdlib.h>

// Disable SetupCrashHandler() unless SK_CRASH_HANDLER is defined.
#ifndef SK_CRASH_HANDLER
    void SetupCrashHandler() { }

#elif defined(GOOGLE3)
    #include "base/process_state.h"
    void SetupCrashHandler() { InstallSignalHandlers(); }

#else

    #if defined(SK_BUILD_FOR_MAC)

        // We only use local unwinding, so we can define this to select a faster implementation.
        #define UNW_LOCAL_ONLY
        #include <libunwind.h>
        #include <cxxabi.h>

        static void handler(int sig) {
            unw_context_t context;
            unw_getcontext(&context);

            unw_cursor_t cursor;
            unw_init_local(&cursor, &context);

            SkDebugf("\nSignal %d:\n", sig);
            while (unw_step(&cursor) > 0) {
                static const size_t kMax = 256;
                char mangled[kMax], demangled[kMax];
                unw_word_t offset;
                unw_get_proc_name(&cursor, mangled, kMax, &offset);

                int ok;
                size_t len = kMax;
                abi::__cxa_demangle(mangled, demangled, &len, &ok);

                SkDebugf("%s (+0x%zx)\n", ok == 0 ? demangled : mangled, (size_t)offset);
            }
            SkDebugf("\n");

            // Exit NOW.  Don't notify other threads, don't call anything registered with atexit().
            _Exit(sig);
        }

    #elif defined(SK_BUILD_FOR_UNIX)

        // We'd use libunwind here too, but it's a pain to get installed for
        // both 32 and 64 bit on bots.  Doesn't matter much: catchsegv is best anyway.
        #include <execinfo.h>

        static void handler(int sig) {
            static const int kMax = 64;
            void* stack[kMax];
            const int count = backtrace(stack, kMax);

            SkDebugf("\nSignal %d [%s]:\n", sig, strsignal(sig));
            backtrace_symbols_fd(stack, count, 2/*stderr*/);

            // Exit NOW.  Don't notify other threads, don't call anything registered with atexit().
            _Exit(sig);
        }

    #endif

    #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_UNIX)
        #include <signal.h>

        void SetupCrashHandler() {
            static const int kSignals[] = {
                SIGABRT,
                SIGBUS,
                SIGFPE,
                SIGILL,
                SIGSEGV,
            };

            for (size_t i = 0; i < sizeof(kSignals) / sizeof(kSignals[0]); i++) {
                // Register our signal handler unless something's already done so (e.g. catchsegv).
                void (*prev)(int) = signal(kSignals[i], handler);
                if (prev != SIG_DFL) {
                    signal(kSignals[i], prev);
                }
            }
        }

    #elif defined(SK_CRASH_HANDLER) && defined(SK_BUILD_FOR_WIN)

        #include <DbgHelp.h>

        static const struct {
            const char* name;
            const DWORD code;
        } kExceptions[] = {
        #define _(E) {#E, E}
            _(EXCEPTION_ACCESS_VIOLATION),
            _(EXCEPTION_BREAKPOINT),
            _(EXCEPTION_INT_DIVIDE_BY_ZERO),
            _(EXCEPTION_STACK_OVERFLOW),
            // TODO: more?
        #undef _
        };

        static LONG WINAPI handler(EXCEPTION_POINTERS* e) {
            const DWORD code = e->ExceptionRecord->ExceptionCode;
            SkDebugf("\nCaught exception %u", code);
            for (size_t i = 0; i < SK_ARRAY_COUNT(kExceptions); i++) {
                if (kExceptions[i].code == code) {
                    SkDebugf(" %s", kExceptions[i].name);
                }
            }
            SkDebugf("\n");

            // We need to run SymInitialize before doing any of the stack walking below.
            HANDLE hProcess = GetCurrentProcess();
            SymInitialize(hProcess, 0, true);

            STACKFRAME64 frame;
            sk_bzero(&frame, sizeof(frame));
            // Start frame off from the frame that triggered the exception.
            CONTEXT* c = e->ContextRecord;
            frame.AddrPC.Mode      = AddrModeFlat;
            frame.AddrStack.Mode   = AddrModeFlat;
            frame.AddrFrame.Mode   = AddrModeFlat;
        #if defined(_X86_)
            frame.AddrPC.Offset    = c->Eip;
            frame.AddrStack.Offset = c->Esp;
            frame.AddrFrame.Offset = c->Ebp;
            const DWORD machineType = IMAGE_FILE_MACHINE_I386;
        #elif defined(_AMD64_)
            frame.AddrPC.Offset    = c->Rip;
            frame.AddrStack.Offset = c->Rsp;
            frame.AddrFrame.Offset = c->Rbp;
            const DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
        #endif

            while (StackWalk64(machineType,
                               GetCurrentProcess(),
                               GetCurrentThread(),
                               &frame,
                               c,
                               nullptr,
                               SymFunctionTableAccess64,
                               SymGetModuleBase64,
                               nullptr)) {
                // Buffer to store symbol name in.
                static const int kMaxNameLength = 1024;
                uint8_t buffer[sizeof(IMAGEHLP_SYMBOL64) + kMaxNameLength];
                sk_bzero(buffer, sizeof(buffer));

                // We have to place IMAGEHLP_SYMBOL64 at the front, and fill in
                // how much space it can use.
                IMAGEHLP_SYMBOL64* symbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(&buffer);
                symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
                symbol->MaxNameLength = kMaxNameLength - 1;

                // Translate the current PC into a symbol and byte offset from the symbol.
                DWORD64 offset;
                SymGetSymFromAddr64(hProcess, frame.AddrPC.Offset, &offset, symbol);

                SkDebugf("%s +%x\n", symbol->Name, offset);
            }

            // Exit NOW.  Don't notify other threads, don't call anything registered with atexit().
            _exit(1);

            // The compiler wants us to return something.  This is what we'd do
            // if we didn't _exit().
            return EXCEPTION_EXECUTE_HANDLER;
        }

        void SetupCrashHandler() {
            SetUnhandledExceptionFilter(handler);
        }

    #else  // We asked for SK_CRASH_HANDLER, but it's not Mac, Linux, or Windows.  Sorry!

        void SetupCrashHandler() { }

    #endif
#endif // SK_CRASH_HANDLER
<|endoftext|>


<commit_before>#include "LotsOfLinesApp.h"
#include <QFileDialog>
#include <QCheckBox>
#include <QMessageBox>
#include <QTableView>
#include <QtConcurrent/qtconcurrentrun.h>
#include <qfuture.h>
#include "LoadDataDialog.h"
#include "PreferencesDialog.h"
#include "DataTableModel.h"
#include <LotsOfLines/RenderingSystem.hpp>
#include <LotsOfLines/IVisualizationMethod.hpp>

//Custom checkbox for selecting visualization methods.
class VisualizationTypeCheckbox : public QCheckBox
{
public:

	VisualizationTypeCheckbox(const QString& text, QWidget* parent, LotsOfLines::E_VISUALIZATION_TYPE type)
		:QCheckBox(text, parent),
		m_visualizationType(type)
	{}

	LotsOfLines::E_VISUALIZATION_TYPE getVisualizationType() { return m_visualizationType; }

private:

	LotsOfLines::E_VISUALIZATION_TYPE m_visualizationType;
};

LotsOfLinesApp::LotsOfLinesApp(QWidget *parent)
	:QMainWindow(parent),
	m_dataSet(nullptr)
{
	ui.setupUi(this);

	//Setup rendering window
	auto rendererWidget = new VisualizationRendererWidget(this);
	//m_renderingSystem = m_rendererWidget->getRenderingSystem();
	//ui.centralLayout->addWidget(m_rendererWidget);

	//Populate visualization type selection menu
	LotsOfLines::VisualizationMethodList visualizationMethods;
	rendererWidget->getRenderingSystem()->getVisualizationMethods(visualizationMethods);
	for (auto method : visualizationMethods)
	{
		VisualizationTypeCheckbox* methodCheckbox = new VisualizationTypeCheckbox(QString::fromStdString(method->getTypeName()), ui.visualizationTypeArea, method->getType());
		connect(methodCheckbox, SIGNAL(stateChanged(int)), this, SLOT(onVisualizationChecked(int)));
		ui.visualizationTypeLayout->addWidget(methodCheckbox);
	}

	delete rendererWidget;

	//Setup dock widgets
	ui.menuView->addAction(ui.sidebarDockWidget->toggleViewAction());
	ui.menuView->addAction(ui.dataTableDock->toggleViewAction());

	//Connect signals and slots
	connect(ui.actionLoad, SIGNAL(triggered()), this, SLOT(onLoadFile()));
	connect(ui.actionPreferences, SIGNAL(triggered()), this, SLOT(onOpenPreferences()));
}

void LotsOfLinesApp::loadFile(const QString& filename, const LotsOfLines::LoadOptions& options)
{
	//Load data set through DataModel module with QtConcurrent
	QFuture<std::shared_ptr<LotsOfLines::DataSet>> dataSet = QtConcurrent::run(this->m_dataModel, &LotsOfLines::DataModel::loadData, filename.toStdString(), options);
	//This will keep GUI active but does slow load down. Needs work
	while (!dataSet.isFinished()) {
		QCoreApplication::processEvents();
		//Potentially get progress here
	}
	//Set dataset to QtConcurrent run result
	m_dataSet = dataSet.result();

	if (m_dataSet == nullptr)
	{
		QMessageBox::warning(this, "Failed to load", "There was an error loading the data file.");
	}

	//Pass data along to rendering system
	for (auto rendererWidget : m_rendererWidgets)
	{
		auto renderingSystem = rendererWidget.second->getRenderingSystem();
		renderingSystem->setDataSet(m_dataSet);
		renderingSystem->redraw();
	}

	reloadDataTable();
}

void LotsOfLinesApp::reloadDataTable()
{
	//Delete all tabs
	for (unsigned int i = 0; i < ui.dataClassTabs->count(); ++i)
	{
		QWidget* tab = ui.dataClassTabs->widget(i);
		delete tab;
	}
	ui.dataClassTabs->clear();

	//Generate new tabs for each data class
	for (auto dataClass : m_dataSet->getClasses())
	{
		QTableView* dataTable = new QTableView(ui.dataClassTabs);
		dataTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
		dataTable->setModel(new DataTableModel(m_dataSet, dataClass));
		dataTable->setSelectionMode(QAbstractItemView::NoSelection);

		ui.dataClassTabs->addTab(dataTable, QString::fromStdString(dataClass));
	}
}

void LotsOfLinesApp::onLoadFile()
{
	//Get file path of data to load
	QString file = QFileDialog::getOpenFileName(this, "Select data file");
	if (file.isNull())
	{
		return;
	}

	//Show data loading options
	LoadDataDialog dlg(this, file);
	if (dlg.exec() == QDialog::Accepted)
	{
		LotsOfLines::LoadOptions options = dlg.getLoadOptions();
		loadFile(file, options);
	}
}

void LotsOfLinesApp::onOpenPreferences()
{
	PreferencesDialog dlg(this);
	dlg.exec();
}

void LotsOfLinesApp::onVisualizationChecked(int state)
{
	VisualizationTypeCheckbox* checkbox = (VisualizationTypeCheckbox*)sender();
	LotsOfLines::E_VISUALIZATION_TYPE visualizationType = checkbox->getVisualizationType();

	if (state)
	{
		//Init callback will be called by the rendering widget after OpenGL loads
		auto initCallback = [this, visualizationType](LotsOfLines::RenderingSystem* renderingSystem)
		{
			//Set visualization type and dataset now that OpenGL is initialized
			renderingSystem->setDataSet(m_dataSet);
			renderingSystem->setVisualizationType(visualizationType);
			renderingSystem->redraw();

			//Add options editor widget for visualization method
			OptionEditorWidget* editorWidget = new OptionEditorWidget(
				QString::fromStdString(renderingSystem->getCurrentVisualizationMethod()->getTypeName()),
				renderingSystem->getVisualizationOptions(),
				ui.optionsScrollArea
				);
			m_optionEditorWidgets[visualizationType] = editorWidget;
			ui.optionsScrollLayout->addWidget(editorWidget);

			//Connect option editing signal so that the visualization can be redrawn when options are changed
			connect(editorWidget, SIGNAL(optionChanged(const std::string&)), this, SLOT(onVisualizationOptionsChanged(const std::string&)));
		};

		//Create widget for screen section and use init callback to set parameters
		VisualizationRendererWidget* rendererWidget = new VisualizationRendererWidget(this, initCallback);
		m_rendererWidgets[checkbox->getVisualizationType()] = rendererWidget;
		reorderSplitScreens();
	}
	else
	{
		//Remove visualization type from splitscreen display
		m_rendererWidgets.erase(visualizationType);
		reorderSplitScreens();

		//Remove editor widget
		auto optionEditorWidget = m_optionEditorWidgets.find(visualizationType);
		if (optionEditorWidget != m_optionEditorWidgets.end())
		{
			ui.optionsScrollLayout->removeWidget(optionEditorWidget->second);
			delete optionEditorWidget->second;
			m_optionEditorWidgets.erase(optionEditorWidget);
		}
	}
}

void LotsOfLinesApp::onVisualizationOptionsChanged(const std::string& name)
{
	for (auto rendererWidget : m_rendererWidgets)
	{
		auto renderingSystem = rendererWidget.second->getRenderingSystem();
		renderingSystem->redraw();
	}
}

void LotsOfLinesApp::reorderSplitScreens()
{
	//Clear layout
	while (ui.centralLayout->count() > 0)
	{
		QLayoutItem* rendererLayoutItem = ui.centralLayout->itemAt(0);
		VisualizationRendererWidget* renderWidget = (VisualizationRendererWidget*)rendererLayoutItem->widget();
		LotsOfLines::E_VISUALIZATION_TYPE visualizationType = renderWidget->getRenderingSystem()->getCurrentVisualizationMethod()->getType();

		ui.centralLayout->removeItem(rendererLayoutItem);

		//If the visualization method has been disabled, then delete the rendering widget.
		if (m_rendererWidgets.find(visualizationType) == m_rendererWidgets.end())
		{
			delete renderWidget;
		}
	}

	//Assign based on index
	unsigned int idx = 0;
	for (auto widget : m_rendererWidgets)
	{
		unsigned int row = idx  / 2;
		unsigned int col = idx % 2;
		ui.centralLayout->addWidget(widget.second, row, col);

		idx++;
	}
}<commit_msg>Simple progressbar marquee style<commit_after>#include "LotsOfLinesApp.h"
#include <QFileDialog>
#include <QCheckBox>
#include <QMessageBox>
#include <QTableView>
#include <QtConcurrent/qtconcurrentrun.h>
#include <QtWidgets/qprogressdialog.h>
#include <qfuturewatcher.h>
#include <qfuture.h>
#include "LoadDataDialog.h"
#include "PreferencesDialog.h"
#include "DataTableModel.h"
#include <LotsOfLines/RenderingSystem.hpp>
#include <LotsOfLines/IVisualizationMethod.hpp>

//Custom checkbox for selecting visualization methods.
class VisualizationTypeCheckbox : public QCheckBox
{
public:

	VisualizationTypeCheckbox(const QString& text, QWidget* parent, LotsOfLines::E_VISUALIZATION_TYPE type)
		:QCheckBox(text, parent),
		m_visualizationType(type)
	{}

	LotsOfLines::E_VISUALIZATION_TYPE getVisualizationType() { return m_visualizationType; }

private:

	LotsOfLines::E_VISUALIZATION_TYPE m_visualizationType;
};

LotsOfLinesApp::LotsOfLinesApp(QWidget *parent)
	:QMainWindow(parent),
	m_dataSet(nullptr)
{
	ui.setupUi(this);

	//Setup rendering window
	auto rendererWidget = new VisualizationRendererWidget(this);
	//m_renderingSystem = m_rendererWidget->getRenderingSystem();
	//ui.centralLayout->addWidget(m_rendererWidget);

	//Populate visualization type selection menu
	LotsOfLines::VisualizationMethodList visualizationMethods;
	rendererWidget->getRenderingSystem()->getVisualizationMethods(visualizationMethods);
	for (auto method : visualizationMethods)
	{
		VisualizationTypeCheckbox* methodCheckbox = new VisualizationTypeCheckbox(QString::fromStdString(method->getTypeName()), ui.visualizationTypeArea, method->getType());
		connect(methodCheckbox, SIGNAL(stateChanged(int)), this, SLOT(onVisualizationChecked(int)));
		ui.visualizationTypeLayout->addWidget(methodCheckbox);
	}

	delete rendererWidget;

	//Setup dock widgets
	ui.menuView->addAction(ui.sidebarDockWidget->toggleViewAction());
	ui.menuView->addAction(ui.dataTableDock->toggleViewAction());

	//Connect signals and slots
	connect(ui.actionLoad, SIGNAL(triggered()), this, SLOT(onLoadFile()));
	connect(ui.actionPreferences, SIGNAL(triggered()), this, SLOT(onOpenPreferences()));
}

void LotsOfLinesApp::loadFile(const QString& filename, const LotsOfLines::LoadOptions& options)
{
	QProgressDialog dialog;
	dialog.setLabelText("Please wait while loading file...");
	dialog.setMaximum(0); // Marquee style
	QFutureWatcher<std::shared_ptr<LotsOfLines::DataSet>> future;
	QObject::connect(&future, SIGNAL(finished()), &dialog, SLOT(reset()));
	QObject::connect(&dialog, SIGNAL(canceled()), &future, SLOT(cancel()));
	//Load data set through DataModel module with QtConcurrent
	future.setFuture(QtConcurrent::run(this->m_dataModel, &LotsOfLines::DataModel::loadData, filename.toStdString(), options));
	dialog.exec();
	while (!future.future().isFinished()) {
		QCoreApplication::processEvents();
		if (future.future().isCanceled()) return;
	}
	//Set dataset to QtConcurrent run result
	m_dataSet = future.future().result();

	if (m_dataSet == nullptr)
	{
		QMessageBox::warning(this, "Failed to load", "There was an error loading the data file.");
	}

	//Pass data along to rendering system
	for (auto rendererWidget : m_rendererWidgets)
	{
		auto renderingSystem = rendererWidget.second->getRenderingSystem();
		renderingSystem->setDataSet(m_dataSet);
		renderingSystem->redraw();
	}

	reloadDataTable();
}

void LotsOfLinesApp::reloadDataTable()
{
	//Delete all tabs
	for (unsigned int i = 0; i < ui.dataClassTabs->count(); ++i)
	{
		QWidget* tab = ui.dataClassTabs->widget(i);
		delete tab;
	}
	ui.dataClassTabs->clear();

	//Generate new tabs for each data class
	for (auto dataClass : m_dataSet->getClasses())
	{
		QTableView* dataTable = new QTableView(ui.dataClassTabs);
		dataTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
		dataTable->setModel(new DataTableModel(m_dataSet, dataClass));
		dataTable->setSelectionMode(QAbstractItemView::NoSelection);

		ui.dataClassTabs->addTab(dataTable, QString::fromStdString(dataClass));
	}
}

void LotsOfLinesApp::onLoadFile()
{
	//Get file path of data to load
	QString file = QFileDialog::getOpenFileName(this, "Select data file");
	if (file.isNull())
	{
		return;
	}

	//Show data loading options
	LoadDataDialog dlg(this, file);
	if (dlg.exec() == QDialog::Accepted)
	{
		LotsOfLines::LoadOptions options = dlg.getLoadOptions();
		loadFile(file, options);
	}
}

void LotsOfLinesApp::onOpenPreferences()
{
	PreferencesDialog dlg(this);
	dlg.exec();
}

void LotsOfLinesApp::onVisualizationChecked(int state)
{
	VisualizationTypeCheckbox* checkbox = (VisualizationTypeCheckbox*)sender();
	LotsOfLines::E_VISUALIZATION_TYPE visualizationType = checkbox->getVisualizationType();

	if (state)
	{
		//Init callback will be called by the rendering widget after OpenGL loads
		auto initCallback = [this, visualizationType](LotsOfLines::RenderingSystem* renderingSystem)
		{
			//Set visualization type and dataset now that OpenGL is initialized
			renderingSystem->setDataSet(m_dataSet);
			renderingSystem->setVisualizationType(visualizationType);
			renderingSystem->redraw();

			//Add options editor widget for visualization method
			OptionEditorWidget* editorWidget = new OptionEditorWidget(
				QString::fromStdString(renderingSystem->getCurrentVisualizationMethod()->getTypeName()),
				renderingSystem->getVisualizationOptions(),
				ui.optionsScrollArea
				);
			m_optionEditorWidgets[visualizationType] = editorWidget;
			ui.optionsScrollLayout->addWidget(editorWidget);

			//Connect option editing signal so that the visualization can be redrawn when options are changed
			connect(editorWidget, SIGNAL(optionChanged(const std::string&)), this, SLOT(onVisualizationOptionsChanged(const std::string&)));
		};

		//Create widget for screen section and use init callback to set parameters
		VisualizationRendererWidget* rendererWidget = new VisualizationRendererWidget(this, initCallback);
		m_rendererWidgets[checkbox->getVisualizationType()] = rendererWidget;
		reorderSplitScreens();
	}
	else
	{
		//Remove visualization type from splitscreen display
		m_rendererWidgets.erase(visualizationType);
		reorderSplitScreens();

		//Remove editor widget
		auto optionEditorWidget = m_optionEditorWidgets.find(visualizationType);
		if (optionEditorWidget != m_optionEditorWidgets.end())
		{
			ui.optionsScrollLayout->removeWidget(optionEditorWidget->second);
			delete optionEditorWidget->second;
			m_optionEditorWidgets.erase(optionEditorWidget);
		}
	}
}

void LotsOfLinesApp::onVisualizationOptionsChanged(const std::string& name)
{
	for (auto rendererWidget : m_rendererWidgets)
	{
		auto renderingSystem = rendererWidget.second->getRenderingSystem();
		renderingSystem->redraw();
	}
}

void LotsOfLinesApp::reorderSplitScreens()
{
	//Clear layout
	while (ui.centralLayout->count() > 0)
	{
		QLayoutItem* rendererLayoutItem = ui.centralLayout->itemAt(0);
		VisualizationRendererWidget* renderWidget = (VisualizationRendererWidget*)rendererLayoutItem->widget();
		LotsOfLines::E_VISUALIZATION_TYPE visualizationType = renderWidget->getRenderingSystem()->getCurrentVisualizationMethod()->getType();

		ui.centralLayout->removeItem(rendererLayoutItem);

		//If the visualization method has been disabled, then delete the rendering widget.
		if (m_rendererWidgets.find(visualizationType) == m_rendererWidgets.end())
		{
			delete renderWidget;
		}
	}

	//Assign based on index
	unsigned int idx = 0;
	for (auto widget : m_rendererWidgets)
	{
		unsigned int row = idx  / 2;
		unsigned int col = idx % 2;
		ui.centralLayout->addWidget(widget.second, row, col);

		idx++;
	}
}<|endoftext|>