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

 Program:   Medical Imaging & Interaction Toolkit
 Language:  C++
 Date:      $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $
 Version:   $Revision: 21975 $

 Copyright (c) German Cancer Research Center, Division of Medical and
 Biological Informatics. All rights reserved.
 See MITKCopyright.txt or http://www.mitk.org/copyright.html 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.

 =========================================================================*/

// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>

// Qmitk
#include "QmitkFiberBundleDeveloperView.h"
#include <QmitkStdMultiWidget.h>

// Qt

// VTK
#include <vtkPointSource.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>

const std::string QmitkFiberBundleDeveloperView::VIEW_ID = "org.mitk.views.fiberbundledeveloper";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;

QmitkFiberBundleDeveloperView::QmitkFiberBundleDeveloperView()
: QmitkFunctionality()
, m_Controls( 0 )
, m_MultiWidget( NULL )
{

}

// Destructor
QmitkFiberBundleDeveloperView::~QmitkFiberBundleDeveloperView()
{

}

void QmitkFiberBundleDeveloperView::CreateQtPartControl( QWidget *parent )
{
  // build up qt view, unless already done in QtDesigner, etc.
  if ( !m_Controls )
  {
    // create GUI widgets from the Qt Designer's .ui file
    m_Controls = new Ui::QmitkFiberBundleDeveloperViewControls;
    m_Controls->setupUi( parent );

    connect( m_Controls->buttonGenerateFibers, SIGNAL(clicked()), this, SLOT(DoGenerateFibers()) );
    connect( m_Controls->radioButton_directionRandom, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) );
    connect( m_Controls->radioButton_directionX, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) );
    connect( m_Controls->radioButton_directionY, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) );
    connect( m_Controls->radioButton_directionZ, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) );

  }

  //  Checkpoint for fiber ORIENTATION
  if ( m_DirectionRadios.empty() )
  {
    m_DirectionRadios.insert(0, m_Controls->radioButton_directionRandom);
    m_DirectionRadios.insert(1, m_Controls->radioButton_directionX);
    m_DirectionRadios.insert(2, m_Controls->radioButton_directionY);
    m_DirectionRadios.insert(3, m_Controls->radioButton_directionZ);
  }

}

void QmitkFiberBundleDeveloperView::DoUpdateGenerateFibersWidget()
{
  MITK_INFO << "DO_UPDATE_GENERATE_FIBERS_WIDGET :-) ";
  //get selected radioButton
  QString fibDirection; //stores the object_name of selected radiobutton
  QVector<QRadioButton*>::const_iterator i;
  for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i)
  {
    QRadioButton* rdbtn = *i;
    if (rdbtn->isChecked())
      fibDirection = rdbtn->objectName();
  }

  if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) {
    // disable radiobuttons
    if (m_Controls->boxFiberMinLength->isEnabled())
      m_Controls->boxFiberMinLength->setEnabled(false);

    if (m_Controls->labelFiberMinLength->isEnabled())
      m_Controls->labelFiberMinLength->setEnabled(false);

    if (m_Controls->boxFiberMaxLength->isEnabled())
      m_Controls->boxFiberMaxLength->setEnabled(false);

    if (m_Controls->labelFiberMaxLength->isEnabled())
      m_Controls->labelFiberMaxLength->setEnabled(false);

    //enable radiobuttons
    if (!m_Controls->labelFibersTotal->isEnabled())
      m_Controls->labelFibersTotal->setEnabled(true);

    if (!m_Controls->boxFiberNumbers->isEnabled())
      m_Controls->boxFiberNumbers->setEnabled(true);

    if (!m_Controls->labelDistrRadius->isEnabled())
      m_Controls->labelDistrRadius->setEnabled(true);

    if (!m_Controls->boxDistributionRadius->isEnabled())
      m_Controls->boxDistributionRadius->setEnabled(true);

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_X ) {
    // disable radiobuttons

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Y ) {
     // disable radiobuttons

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Z ) {
     // disable radiobuttons
  }

}

void QmitkFiberBundleDeveloperView::DoGenerateFibers()
{

  // GET SELECTED FIBER DIRECTION
  QString fibDirection; //stores the object_name of selected radiobutton
  QVector<QRadioButton*>::const_iterator i;
  for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i)
  {
    QRadioButton* rdbtn = *i;
    if (rdbtn->isChecked())
      fibDirection = rdbtn->objectName();
  }

  vtkSmartPointer<vtkPolyData> output; // FiberPD stores the generated PolyData
  if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) {
    //    build polydata with random lines and fibers
    output = GenerateVtkFibersRandom();

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_X ) {
    //    build polydata with XDirection fibers
    output = GenerateVtkFibersDirectionX();

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Y ) {
    //    build polydata with YDirection fibers
    output = GenerateVtkFibersDirectionY();

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Z ) {
    //    build polydata with ZDirection fibers
    output = GenerateVtkFibersDirectionZ();

  }

  //mitkFiberBundleX::New()
  //write to dataStorage

}

/*
 * Generate polydata of random fibers
 */
vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersRandom()
{
  int numOfFibers = m_Controls->boxFiberNumbers->value();
  int distrRadius = m_Controls->boxDistributionRadius->value();
  int numOfPoints = numOfFibers * distrRadius;

  std::vector< std::vector<int> > fiberStorage;
  for (int i=0; i<numOfFibers; ++i) {
    std::vector<int> a;
    fiberStorage.push_back( a );

  }

  //get number of items in fiberStorage
  MITK_INFO << "Fibers in fiberstorage: " << fiberStorage.size();

  for (unsigned long i=0; i<fiberStorage.size(); ++i)
  {
    //add dummy points to storageentries
    fiberStorage.at(i).push_back(222);
    fiberStorage.at(i).push_back((int)i);

  }

  for (unsigned long i=0; i<fiberStorage.size(); ++i)
  {
    std::vector<int> singleFiber = fiberStorage.at(i);
    MITK_INFO << "====FIBER_" << i << "_=====";

    for (unsigned long si=0; si<singleFiber.size(); ++si) {
      MITK_INFO << singleFiber.at(si);
    }

  }

  vtkSmartPointer<vtkPointSource> randomPoints = vtkSmartPointer<vtkPointSource>::New();
  randomPoints->SetCenter(0.0, 0.0, 0.0);
  randomPoints->SetNumberOfPoints(numOfPoints);
  randomPoints->SetRadius(distrRadius);
  randomPoints->Update();

  vtkPolyData* pntHost = randomPoints->GetOutput();
  vtkPoints* pnts = pntHost->GetPoints();

  //===================================
  //checkpoint if requested amount of points equals generated amount
  if (numOfPoints != pnts->GetNumberOfPoints()) {
    MITK_INFO << "VTK POINT ERROR, WRONG AMOUNT OF GENRERATED POINTS";
    return 0;
  }// =================================

  // Set Fibers
  vtkSmartPointer<vtkCellArray> linesCell = vtkSmartPointer<vtkCellArray>::New();

  // iterate through points
  vtkSmartPointer<vtkPolyData> PDRandom = vtkSmartPointer<vtkPolyData>::New();
  PDRandom->SetPoints(pnts);
  PDRandom->SetLines(linesCell);

  return PDRandom;
}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionX()
{
  int numOfFibers = m_Controls->boxFiberNumbers->value();
  vtkSmartPointer<vtkCellArray> linesCell = vtkSmartPointer<vtkCellArray>::New();
  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();

  //insert Origin point, this point has index 0 in point array
  double originX = 0.0;
  double originY = 0.0;
  double originZ = 0.0;

  //after each iteration the origin of the new fiber increases
  //here you set which direction is affected.
  double increaseX = 0.0;
  double increaseY = 1.0;
  double increaseZ = 0.0;

  //walk along X axis
  //length of fibers increases in each iteration
  for (int i=0; i<numOfFibers; ++i) {

    vtkSmartPointer<vtkPolyLine> newFiber = vtkSmartPointer<vtkPolyLine>::New();
    newFiber->GetPointIds()->SetNumberOfIds(i+2);

    //create starting point and add it to pointset
    points->InsertNextPoint(originX + (double)i * increaseX , originY + (double)i * increaseY, originZ + (double)i * increaseZ);

    //add starting point to fiber
    newFiber->GetPointIds()->SetId(0,points->GetNumberOfPoints()-1);

    //insert remaining points for fiber
    for (int pj=0; pj<=i ; ++pj)
    { //generate next point on X axis
      points->InsertNextPoint( originX + (double)pj+1 , originY + (double)i * increaseY, originZ + (double)i * increaseZ );
      newFiber->GetPointIds()->SetId(pj+1,points->GetNumberOfPoints()-1);
    }

    linesCell->InsertNextCell(newFiber);
  }

  vtkSmartPointer<vtkPolyData> PDX = vtkSmartPointer<vtkPolyData>::New();
  PDX->SetPoints(points);
  PDX->SetLines(linesCell);
  return PDX;
}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionY()
{
  vtkSmartPointer<vtkPolyData> PDY = vtkSmartPointer<vtkPolyData>::New();
  //todo

  return PDY;
}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionZ()
{
  vtkSmartPointer<vtkPolyData> PDZ = vtkSmartPointer<vtkPolyData>::New();
  //todo

  return PDZ;
}

void QmitkFiberBundleDeveloperView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
  m_MultiWidget = &stdMultiWidget;
}

void QmitkFiberBundleDeveloperView::StdMultiWidgetNotAvailable()
{
  m_MultiWidget = NULL;
}

/* OnSelectionChanged is registered to SelectionService, therefore no need to
 implement SelectionService Listener explicitly */

void QmitkFiberBundleDeveloperView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{

}

void QmitkFiberBundleDeveloperView::Activated()
{

  MITK_INFO << "FB OPerations ACTIVATED()";

}

<commit_msg>gui element logic [cOK]<commit_after>/*=========================================================================

 Program:   Medical Imaging & Interaction Toolkit
 Language:  C++
 Date:      $Date: 2010-03-31 16:40:27 +0200 (Mi, 31 Mrz 2010) $
 Version:   $Revision: 21975 $

 Copyright (c) German Cancer Research Center, Division of Medical and
 Biological Informatics. All rights reserved.
 See MITKCopyright.txt or http://www.mitk.org/copyright.html 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.

 =========================================================================*/

// Blueberry
#include <berryISelectionService.h>
#include <berryIWorkbenchWindow.h>

// Qmitk
#include "QmitkFiberBundleDeveloperView.h"
#include <QmitkStdMultiWidget.h>

// Qt

// VTK
#include <vtkPointSource.h>
#include <vtkPolyLine.h>
#include <vtkCellArray.h>

const std::string QmitkFiberBundleDeveloperView::VIEW_ID = "org.mitk.views.fiberbundledeveloper";
const std::string id_DataManager = "org.mitk.views.datamanager";
using namespace berry;

QmitkFiberBundleDeveloperView::QmitkFiberBundleDeveloperView()
: QmitkFunctionality()
, m_Controls( 0 )
, m_MultiWidget( NULL )
{

}

// Destructor
QmitkFiberBundleDeveloperView::~QmitkFiberBundleDeveloperView()
{

}

void QmitkFiberBundleDeveloperView::CreateQtPartControl( QWidget *parent )
{
  // build up qt view, unless already done in QtDesigner, etc.
  if ( !m_Controls )
  {
    // create GUI widgets from the Qt Designer's .ui file
    m_Controls = new Ui::QmitkFiberBundleDeveloperViewControls;
    m_Controls->setupUi( parent );

    connect( m_Controls->buttonGenerateFibers, SIGNAL(clicked()), this, SLOT(DoGenerateFibers()) );
    connect( m_Controls->radioButton_directionRandom, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) );
    connect( m_Controls->radioButton_directionX, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) );
    connect( m_Controls->radioButton_directionY, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) );
    connect( m_Controls->radioButton_directionZ, SIGNAL(clicked()), this, SLOT(DoUpdateGenerateFibersWidget()) );

  }

  //  Checkpoint for fiber ORIENTATION
  if ( m_DirectionRadios.empty() )
  {
    m_DirectionRadios.insert(0, m_Controls->radioButton_directionRandom);
    m_DirectionRadios.insert(1, m_Controls->radioButton_directionX);
    m_DirectionRadios.insert(2, m_Controls->radioButton_directionY);
    m_DirectionRadios.insert(3, m_Controls->radioButton_directionZ);
  }

  // set GUI elements of FiberGenerator to according configuration
  DoUpdateGenerateFibersWidget();

}

void QmitkFiberBundleDeveloperView::DoUpdateGenerateFibersWidget()
{
  //get selected radioButton
  QString fibDirection; //stores the object_name of selected radiobutton
  QVector<QRadioButton*>::const_iterator i;
  for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i)
  {
    QRadioButton* rdbtn = *i;
    if (rdbtn->isChecked())
      fibDirection = rdbtn->objectName();
  }

  if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) {
    // disable radiobuttons
    if (m_Controls->boxFiberMinLength->isEnabled())
      m_Controls->boxFiberMinLength->setEnabled(false);

    if (m_Controls->labelFiberMinLength->isEnabled())
      m_Controls->labelFiberMinLength->setEnabled(false);

    if (m_Controls->boxFiberMaxLength->isEnabled())
      m_Controls->boxFiberMaxLength->setEnabled(false);

    if (m_Controls->labelFiberMaxLength->isEnabled())
      m_Controls->labelFiberMaxLength->setEnabled(false);

    //enable radiobuttons
    if (!m_Controls->labelFibersTotal->isEnabled())
      m_Controls->labelFibersTotal->setEnabled(true);

    if (!m_Controls->boxFiberNumbers->isEnabled())
      m_Controls->boxFiberNumbers->setEnabled(true);

    if (!m_Controls->labelDistrRadius->isEnabled())
      m_Controls->labelDistrRadius->setEnabled(true);

    if (!m_Controls->boxDistributionRadius->isEnabled())
      m_Controls->boxDistributionRadius->setEnabled(true);

  } else {
    // disable radiobuttons
    if (m_Controls->labelDistrRadius->isEnabled())
      m_Controls->labelDistrRadius->setEnabled(false);

    if (m_Controls->boxDistributionRadius->isEnabled())
      m_Controls->boxDistributionRadius->setEnabled(false);

    //enable radiobuttons
    if (!m_Controls->labelFibersTotal->isEnabled())
      m_Controls->labelFibersTotal->setEnabled(true);

    if (!m_Controls->boxFiberNumbers->isEnabled())
      m_Controls->boxFiberNumbers->setEnabled(true);

    if (!m_Controls->boxFiberMinLength->isEnabled())
      m_Controls->boxFiberMinLength->setEnabled(true);

    if (!m_Controls->labelFiberMinLength->isEnabled())
      m_Controls->labelFiberMinLength->setEnabled(true);

    if (!m_Controls->boxFiberMaxLength->isEnabled())
      m_Controls->boxFiberMaxLength->setEnabled(true);

    if (!m_Controls->labelFiberMaxLength->isEnabled())
      m_Controls->labelFiberMaxLength->setEnabled(true);

  }

}

void QmitkFiberBundleDeveloperView::DoGenerateFibers()
{

  // GET SELECTED FIBER DIRECTION
  QString fibDirection; //stores the object_name of selected radiobutton
  QVector<QRadioButton*>::const_iterator i;
  for (i = m_DirectionRadios.begin(); i != m_DirectionRadios.end(); ++i)
  {
    QRadioButton* rdbtn = *i;
    if (rdbtn->isChecked())
      fibDirection = rdbtn->objectName();
  }

  vtkSmartPointer<vtkPolyData> output; // FiberPD stores the generated PolyData
  if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_RANDOM ) {
    //    build polydata with random lines and fibers
    output = GenerateVtkFibersRandom();

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_X ) {
    //    build polydata with XDirection fibers
    output = GenerateVtkFibersDirectionX();

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Y ) {
    //    build polydata with YDirection fibers
    output = GenerateVtkFibersDirectionY();

  } else if ( fibDirection == FIB_RADIOBUTTON_DIRECTION_Z ) {
    //    build polydata with ZDirection fibers
    output = GenerateVtkFibersDirectionZ();

  }

  //mitkFiberBundleX::New()
  //write to dataStorage

}

/*
 * Generate polydata of random fibers
 */
vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersRandom()
{
  int numOfFibers = m_Controls->boxFiberNumbers->value();
  int distrRadius = m_Controls->boxDistributionRadius->value();
  int numOfPoints = numOfFibers * distrRadius;

  std::vector< std::vector<int> > fiberStorage;
  for (int i=0; i<numOfFibers; ++i) {
    std::vector<int> a;
    fiberStorage.push_back( a );

  }

  //get number of items in fiberStorage
  MITK_INFO << "Fibers in fiberstorage: " << fiberStorage.size();

  for (unsigned long i=0; i<fiberStorage.size(); ++i)
  {
    //add dummy points to storageentries
    fiberStorage.at(i).push_back(222);
    fiberStorage.at(i).push_back((int)i);

  }

  for (unsigned long i=0; i<fiberStorage.size(); ++i)
  {
    std::vector<int> singleFiber = fiberStorage.at(i);
    MITK_INFO << "====FIBER_" << i << "_=====";

    for (unsigned long si=0; si<singleFiber.size(); ++si) {
      MITK_INFO << singleFiber.at(si);
    }

  }

  /* Generate Point Cloud */

  vtkSmartPointer<vtkPointSource> randomPoints = vtkSmartPointer<vtkPointSource>::New();
  randomPoints->SetCenter(0.0, 0.0, 0.0);
  randomPoints->SetNumberOfPoints(numOfPoints);
  randomPoints->SetRadius(distrRadius);
  randomPoints->Update();

  vtkPolyData* pntHost = randomPoints->GetOutput();
  vtkPoints* pnts = pntHost->GetPoints();

  //===================================
  //checkpoint if requested amount of points equals generated amount
  if (numOfPoints != pnts->GetNumberOfPoints()) {
    MITK_INFO << "VTK POINT ERROR, WRONG AMOUNT OF GENRERATED POINTS";
    return 0;
  }// =================================

  // Set Fibers
  vtkSmartPointer<vtkCellArray> linesCell = vtkSmartPointer<vtkCellArray>::New();

  // iterate through points
  vtkSmartPointer<vtkPolyData> PDRandom = vtkSmartPointer<vtkPolyData>::New();
  PDRandom->SetPoints(pnts);
  PDRandom->SetLines(linesCell);

  return PDRandom;
}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionX()
{
  int numOfFibers = m_Controls->boxFiberNumbers->value();
  vtkSmartPointer<vtkCellArray> linesCell = vtkSmartPointer<vtkCellArray>::New();
  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();

  //insert Origin point, this point has index 0 in point array
  double originX = 0.0;
  double originY = 0.0;
  double originZ = 0.0;

  //after each iteration the origin of the new fiber increases
  //here you set which direction is affected.
  double increaseX = 0.0;
  double increaseY = 1.0;
  double increaseZ = 0.0;

  //walk along X axis
  //length of fibers increases in each iteration
  for (int i=0; i<numOfFibers; ++i) {

    vtkSmartPointer<vtkPolyLine> newFiber = vtkSmartPointer<vtkPolyLine>::New();
    newFiber->GetPointIds()->SetNumberOfIds(i+2);

    //create starting point and add it to pointset
    points->InsertNextPoint(originX + (double)i * increaseX , originY + (double)i * increaseY, originZ + (double)i * increaseZ);

    //add starting point to fiber
    newFiber->GetPointIds()->SetId(0,points->GetNumberOfPoints()-1);

    //insert remaining points for fiber
    for (int pj=0; pj<=i ; ++pj)
    { //generate next point on X axis
      points->InsertNextPoint( originX + (double)pj+1 , originY + (double)i * increaseY, originZ + (double)i * increaseZ );
      newFiber->GetPointIds()->SetId(pj+1,points->GetNumberOfPoints()-1);
    }

    linesCell->InsertNextCell(newFiber);
  }

  vtkSmartPointer<vtkPolyData> PDX = vtkSmartPointer<vtkPolyData>::New();
  PDX->SetPoints(points);
  PDX->SetLines(linesCell);
  return PDX;
}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionY()
{
  vtkSmartPointer<vtkPolyData> PDY = vtkSmartPointer<vtkPolyData>::New();
  //todo

  return PDY;
}

vtkSmartPointer<vtkPolyData> QmitkFiberBundleDeveloperView::GenerateVtkFibersDirectionZ()
{
  vtkSmartPointer<vtkPolyData> PDZ = vtkSmartPointer<vtkPolyData>::New();
  //todo

  return PDZ;
}

void QmitkFiberBundleDeveloperView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget)
{
  m_MultiWidget = &stdMultiWidget;
}

void QmitkFiberBundleDeveloperView::StdMultiWidgetNotAvailable()
{
  m_MultiWidget = NULL;
}

/* OnSelectionChanged is registered to SelectionService, therefore no need to
 implement SelectionService Listener explicitly */

void QmitkFiberBundleDeveloperView::OnSelectionChanged( std::vector<mitk::DataNode*> nodes )
{

}

void QmitkFiberBundleDeveloperView::Activated()
{

  MITK_INFO << "FB OPerations ACTIVATED()";

}

<|endoftext|>


<commit_before>/*
 * kernel.cpp
 *
 *  Created on: Feb 20, 2017
 *      Author: garrett
 */
#include "Kernel.h"

#include "drivers/ProgrammableInterruptController.h"
#include "memory/alloc/PageFrameAllocator.h"
#include "drivers/Keyboard.h"
#include "interrupts/InterruptDescriptorTable.h"
#include "drivers/TTY/Console.h"
//#include "memory/alloc/malloc.h"
#include "memory/structures/GlobalDescriptorTable.h"
#include "memory/structures/PageTable.h"
#include "drivers/PCI/PCI.h"
#include "drivers/PCI/PCIDeviceList.h"
#include "multiboot_spec/Multiboot.h"
#include "memory/Mem.h"
#include "utils/printf/Printf.h"

InterruptDescriptorTable idt;
GlobalDescriptorTable gdt;
PageTable pageTable;
Keyboard KB;
PageFrameAllocator frameAlloc;

#if defined(__cplusplus)
extern "C" {/* Use C linkage for kernel_main. */
#endif
	void kernelMain(multiboot_info_t* mbd) {
		//turn off interrupts before configed
		asm("cli");
		//clear screen, set the pointer to the start of the VGA buffer.
		terminalInit((uint16_t*) 0xC00B8000);
		// Green on black!
		terminalSetColor(vgaEntryColor(VGA_COLOR_GREEN, VGA_COLOR_BLACK));
        terminalWriteLine("Terminal active, Welcome to ExOS!");
        terminalWriteLine("Preparing your system:");
        terminalWriteString("  Preparing GDT...");
		//build and replce grub's GDT with a custom writable one.
		gdt.build( );
		gdt.load( );
        terminalWriteLine(" Done!");
        terminalWriteString("  Preparing the page table...");
		//rebuild page table. replaces the one built in boot.s
		pageTable.build( );
        terminalWriteLine(" Done!");
        terminalWriteString("  Setting up interrupts...");
		//sets up interrups and enables them
		interruptSetUp( );
        terminalWriteLine(" Done!");
        terminalWriteString("  Preparing the memory allocator...");
		//get the memory map from grub
		getMemMap(mbd);
		//build the page frame allocator (allocate physical memory)
		frameAlloc.build( );
		//set malloc's support vars
		mallocInit( );
        terminalWriteLine(" Done!");
        terminalWriteString("  Finding PCI buses...");
		//find the valid PCI buses
		PCIInit();
        terminalWriteLine(" Done!");
        terminalWriteString("  Finding USB host controllers...");
		//find the (3 or less) USB host controllers. all have the same class/subclass code.
		PCIDeviceList usbHostControllers(0x0C, 0x03, false);
        terminalWriteLine(" Done!");
        terminalWriteLine("!!!!ExOS fully booted!!!!");
        printf("Test printf %d %c\n", 42, 'B');
        printf("Newline is 0x%x%c", '\n', '\n');
        for (int cx = 0; cx < 10; cx++) {
            printf("%d", cx);
        }
		//dont return.
		while (true) {
			asm("hlt");
		}
	}

#if defined(__cplusplus)
}
#endif

void interruptSetUp( ) {
	//build the IDT.
	idt.build( );
	//set the interrupt lines for the PIC
	PICRemap(0x20, 0x28);
	//mask the timer line
	IRQSetMask(0);
	//load it to the CPU
	idt.load( );
	//enable interupts
	asm("sti");
}

<commit_msg>test code<commit_after>/*
 * kernel.cpp
 *
 *  Created on: Feb 20, 2017
 *      Author: garrett
 */
#include "Kernel.h"

#include "drivers/ProgrammableInterruptController.h"
#include "memory/alloc/PageFrameAllocator.h"
#include "drivers/Keyboard.h"
#include "interrupts/InterruptDescriptorTable.h"
#include "drivers/TTY/Console.h"
//#include "memory/alloc/malloc.h"
#include "memory/structures/GlobalDescriptorTable.h"
#include "memory/structures/PageTable.h"
#include "drivers/PCI/PCI.h"
#include "drivers/PCI/PCIDeviceList.h"
#include "multiboot_spec/Multiboot.h"
#include "memory/Mem.h"
#include "utils/printf/Printf.h"

InterruptDescriptorTable idt;
GlobalDescriptorTable gdt;
PageTable pageTable;
Keyboard KB;
PageFrameAllocator frameAlloc;

#if defined(__cplusplus)
extern "C" {/* Use C linkage for kernel_main. */
#endif

void kernelMain(multiboot_info_t *mbd)
{
	//turn off interrupts before configed
	asm("cli");
	//clear screen, set the pointer to the start of the VGA buffer.
	terminalInit((uint16_t *) 0xC00B8000);
	// Green on black!
	terminalSetColor(vgaEntryColor(VGA_COLOR_GREEN, VGA_COLOR_BLACK));
	terminalWriteLine("Terminal active, Welcome to ExOS!");
	terminalWriteLine("Preparing your system:");
	terminalWriteString("  Preparing GDT...");
	//build and replce grub's GDT with a custom writable one.
	gdt.build();
	gdt.load();
	terminalWriteLine(" Done!");
	terminalWriteString("  Preparing the page table...");
	//rebuild page table. replaces the one built in boot.s
	pageTable.build();
	terminalWriteLine(" Done!");
	terminalWriteString("  Setting up interrupts...");
	//sets up interrups and enables them
	interruptSetUp();
	terminalWriteLine(" Done!");
	terminalWriteString("  Preparing the memory allocator...");
	//get the memory map from grub
	getMemMap(mbd);
	//build the page frame allocator (allocate physical memory)
	frameAlloc.build();
	//set malloc's support vars
	mallocInit();
	terminalWriteLine(" Done!");
	terminalWriteString("  Finding PCI buses...");
	//find the valid PCI buses
	PCIInit();
	terminalWriteLine(" Done!");
	terminalWriteString("  Finding USB host controllers...");
	//find the (3 or less) USB host controllers. all have the same class/subclass code.
	PCIDeviceList usbHostControllers(0x0C, 0x03, false);
	terminalWriteLine(" Done!");
	terminalWriteLine("!!!!ExOS fully booted!!!!");
	printf("Test printf %d %c\n", 42, 'B');
	printf("Newline is 0x%x%c", '\n', '\n');
	uint32_t i = (uint32_t) malloc(10);
	printf("malloc returned 0x%x\n", i);
	i = (uint32_t)malloc(100);
	printf("malloc returned 0x%x\n", i);
	 i =(uint32_t) malloc(50);
	printf("malloc returned 0x%x\n", i);
	 i = (uint32_t)malloc(1);
	printf("malloc returned 0x%x\n", i);
	printf("freeing 1 byte");
	free((void*)i);
	 i = (uint32_t)malloc(1);
	printf("malloc returned 0x%x\n", i);
/*
	for (int cx = 0; cx < 10; cx++) {
		printf("%d", cx);
	}*/
	//dont return.
	while (true) {
		asm("hlt");
	}
}

#if defined(__cplusplus)
}
#endif

void interruptSetUp()
{
	//build the IDT.
	idt.build();
	//set the interrupt lines for the PIC
	PICRemap(0x20, 0x28);
	//mask the timer line
	IRQSetMask(0);
	//load it to the CPU
	idt.load();
	//enable interupts
	asm("sti");
}

<|endoftext|>


<commit_before>// SciTE - Scintilla based Text Editor
// LexCPP.cxx - lexer for C++, C, Java, and Javascript
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static bool classifyWordCpp(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
	char s[100];
	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
	}
	bool wordIsUUID = false;
	char chAttr = SCE_C_IDENTIFIER;
	if (isdigit(s[0]) || (s[0] == '.'))
		chAttr = SCE_C_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_C_WORD;
			wordIsUUID = strcmp(s, "uuid") == 0;
		}
	}
	styler.ColourTo(end, chAttr);
	return wordIsUUID;
}

static bool isOKBeforeRE(char ch) {
	return (ch == '(') || (ch == '=') || (ch == ',');
}

static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];

	styler.StartAt(startPos);

	bool fold = styler.GetPropertyInt("fold");
	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor");
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;

	int state = initStyle;
	if (state == SCE_C_STRINGEOL)	// Does not leak onto next line
		state = SCE_C_DEFAULT;
	char chPrev = ' ';
	char chNext = styler[startPos];
	char chPrevNonWhite = ' ';
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	styler.StartSegment(startPos);
	bool lastWordWasUUID = false;
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
			// Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
			// Avoid triggering two times on Dos/Win
			// End of line
			if (state == SCE_C_STRINGEOL) {
				styler.ColourTo(i, state);
				state = SCE_C_DEFAULT;
			}
			if (fold) {
				int lev = levelPrev;
				if (visibleChars == 0)
					lev |= SC_FOLDLEVELWHITEFLAG;
				if ((levelCurrent > levelPrev) && (visibleChars > 0))
					lev |= SC_FOLDLEVELHEADERFLAG;
				styler.SetLevel(lineCurrent, lev);
				lineCurrent++;
				levelPrev = levelCurrent;
			}
			visibleChars = 0;
		}
		if (!isspace(ch))
			visibleChars++;

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_C_DEFAULT) {
			if (ch == '@' && chNext == '\"') {
				styler.ColourTo(i-1, state);
				state = SCE_C_VERBATIM;
				i++;
				ch = chNext;
				chNext = styler.SafeGetCharAt(i + 1);
			} else if (iswordstart(ch) || (ch == '@')) {
				styler.ColourTo(i-1, state);
				if (lastWordWasUUID) {
					state = SCE_C_UUID;
					lastWordWasUUID = false;
				} else {
					state = SCE_C_IDENTIFIER;
				}
			} else if (ch == '/' && chNext == '*') {
				styler.ColourTo(i-1, state);
				if (styler.SafeGetCharAt(i + 2) == '*')
					state = SCE_C_COMMENTDOC;
				else
					state = SCE_C_COMMENT;
			} else if (ch == '/' && chNext == '/') {
				styler.ColourTo(i-1, state);
				state = SCE_C_COMMENTLINE;
			} else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) {
				styler.ColourTo(i-1, state);
				state = SCE_C_REGEX;
			} else if (ch == '\"') {
				styler.ColourTo(i-1, state);
				state = SCE_C_STRING;
			} else if (ch == '\'') {
				styler.ColourTo(i-1, state);
				state = SCE_C_CHARACTER;
			} else if (ch == '#' && visibleChars == 1) {
				// Preprocessor commands are alone on their line
				styler.ColourTo(i-1, state);
				state = SCE_C_PREPROCESSOR;
				// Skip whitespace between # and preprocessor word
				do {
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				} while (isspace(ch) && (i < lengthDoc));
			} else if (isoperator(ch)) {
				styler.ColourTo(i-1, state);
				styler.ColourTo(i, SCE_C_OPERATOR);
				if ((ch == '{') || (ch == '}')) {
					levelCurrent += (ch == '{') ? 1 : -1;
				}
			}
		} else if (state == SCE_C_IDENTIFIER) {
			if (!iswordchar(ch)) {
				lastWordWasUUID = classifyWordCpp(styler.GetStartSegment(), i - 1, keywords, styler);
				state = SCE_C_DEFAULT;
				if (ch == '/' && chNext == '*') {
					if (styler.SafeGetCharAt(i + 2) == '*')
						state = SCE_C_COMMENTDOC;
					else
						state = SCE_C_COMMENT;
				} else if (ch == '/' && chNext == '/') {
					state = SCE_C_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_C_STRING;
				} else if (ch == '\'') {
					state = SCE_C_CHARACTER;
				} else if (isoperator(ch)) {
					styler.ColourTo(i, SCE_C_OPERATOR);
					if ((ch == '{') || (ch == '}')) {
						levelCurrent += (ch == '{') ? 1 : -1;
					}
				}
			}
		} else {
			if (state == SCE_C_PREPROCESSOR) {
				if (stylingWithinPreprocessor) {
					if (isspace(ch)) {
						styler.ColourTo(i-1, state);
						state = SCE_C_DEFAULT;
					}
				} else {
					if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
						styler.ColourTo(i-1, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENT) {
				if (ch == '/' && chPrev == '*') {
					if (((i > styler.GetStartSegment() + 2) || (
						(initStyle == SCE_C_COMMENT) &&
						(styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENTDOC) {
				if (ch == '/' && chPrev == '*') {
					if (((i > styler.GetStartSegment() + 2) || (
						(initStyle == SCE_C_COMMENTDOC) &&
						(styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENTLINE) {
				if (ch == '\r' || ch == '\n') {
					styler.ColourTo(i-1, state);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_STRING) {
				if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_C_DEFAULT;
				} else if ((chNext == '\r' || chNext == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i-1, SCE_C_STRINGEOL);
					state = SCE_C_STRINGEOL;
				}
			} else if (state == SCE_C_CHARACTER) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i-1, SCE_C_STRINGEOL);
					state = SCE_C_STRINGEOL;
				} else if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\'') {
					styler.ColourTo(i, state);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_REGEX) {
				if (ch == '\r' || ch == '\n' || ch == '/') {
					styler.ColourTo(i, state);
					state = SCE_C_DEFAULT;
				} else if (ch == '\\') {
					// Gobble up the quoted character
					if (chNext == '\\' || chNext == '/') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				}
			} else if (state == SCE_C_VERBATIM) {
				if (ch == '\"') {
					if (chNext == '\"') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					} else {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_UUID) {
				if (ch == '\r' || ch == '\n' || ch == ')') {
					styler.ColourTo(i-1, state);
					if (ch == ')')
						styler.ColourTo(i, SCE_C_OPERATOR);
					state = SCE_C_DEFAULT;
				}
			}
		}
		chPrev = ch;
		if (ch != ' ' && ch != '\t')
			chPrevNonWhite = ch;
	}
	styler.ColourTo(lengthDoc - 1, state);

	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	if (fold) {
		int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
		//styler.SetLevel(lineCurrent, levelCurrent | flagsNext);
		styler.SetLevel(lineCurrent, levelPrev | flagsNext);

	}
}

LexerModule lmCPP(SCLEX_CPP, ColouriseCppDoc);
<commit_msg>Addition of SCE_C_COMMENTLINEDOC by Philippe.<commit_after>// SciTE - Scintilla based Text Editor
// LexCPP.cxx - lexer for C++, C, Java, and Javascript
// Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static bool classifyWordCpp(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
	char s[100];
	for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
		s[i] = styler[start + i];
		s[i + 1] = '\0';
	}
	bool wordIsUUID = false;
	char chAttr = SCE_C_IDENTIFIER;
	if (isdigit(s[0]) || (s[0] == '.'))
		chAttr = SCE_C_NUMBER;
	else {
		if (keywords.InList(s)) {
			chAttr = SCE_C_WORD;
			wordIsUUID = strcmp(s, "uuid") == 0;
		}
	}
	styler.ColourTo(end, chAttr);
	return wordIsUUID;
}

static bool isOKBeforeRE(char ch) {
	return (ch == '(') || (ch == '=') || (ch == ',');
}

static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];

	styler.StartAt(startPos);

	bool fold = styler.GetPropertyInt("fold");
	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor");
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;

	int state = initStyle;
	if (state == SCE_C_STRINGEOL)	// Does not leak onto next line
		state = SCE_C_DEFAULT;
	char chPrev = ' ';
	char chNext = styler[startPos];
	char chPrevNonWhite = ' ';
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	styler.StartSegment(startPos);
	bool lastWordWasUUID = false;
	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);

		if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
			// Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix)
			// Avoid triggering two times on Dos/Win
			// End of line
			if (state == SCE_C_STRINGEOL) {
				styler.ColourTo(i, state);
				state = SCE_C_DEFAULT;
			}
			if (fold) {
				int lev = levelPrev;
				if (visibleChars == 0)
					lev |= SC_FOLDLEVELWHITEFLAG;
				if ((levelCurrent > levelPrev) && (visibleChars > 0))
					lev |= SC_FOLDLEVELHEADERFLAG;
				styler.SetLevel(lineCurrent, lev);
				lineCurrent++;
				levelPrev = levelCurrent;
			}
			visibleChars = 0;
		}
		if (!isspace(ch))
			visibleChars++;

		if (styler.IsLeadByte(ch)) {
			chNext = styler.SafeGetCharAt(i + 2);
			chPrev = ' ';
			i += 1;
			continue;
		}

		if (state == SCE_C_DEFAULT) {
			if (ch == '@' && chNext == '\"') {
				styler.ColourTo(i-1, state);
				state = SCE_C_VERBATIM;
				i++;
				ch = chNext;
				chNext = styler.SafeGetCharAt(i + 1);
			} else if (iswordstart(ch) || (ch == '@')) {
				styler.ColourTo(i-1, state);
				if (lastWordWasUUID) {
					state = SCE_C_UUID;
					lastWordWasUUID = false;
				} else {
					state = SCE_C_IDENTIFIER;
				}
			} else if (ch == '/' && chNext == '*') {
				styler.ColourTo(i-1, state);
				if (styler.SafeGetCharAt(i + 2) == '*' ||
					styler.SafeGetCharAt(i + 2) == '!')	// Support of Qt/Doxygen doc. style
					state = SCE_C_COMMENTDOC;
				else
					state = SCE_C_COMMENT;
			} else if (ch == '/' && chNext == '/') {
				styler.ColourTo(i-1, state);
				if (styler.SafeGetCharAt(i + 2) == '/' ||
					styler.SafeGetCharAt(i + 2) == '!')	// Support of Qt/Doxygen doc. style
					state = SCE_C_COMMENTLINEDOC;
				else
				state = SCE_C_COMMENTLINE;
			} else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) {
				styler.ColourTo(i-1, state);
				state = SCE_C_REGEX;
			} else if (ch == '\"') {
				styler.ColourTo(i-1, state);
				state = SCE_C_STRING;
			} else if (ch == '\'') {
				styler.ColourTo(i-1, state);
				state = SCE_C_CHARACTER;
			} else if (ch == '#' && visibleChars == 1) {
				// Preprocessor commands are alone on their line
				styler.ColourTo(i-1, state);
				state = SCE_C_PREPROCESSOR;
				// Skip whitespace between # and preprocessor word
				do {
					i++;
					ch = chNext;
					chNext = styler.SafeGetCharAt(i + 1);
				} while (isspace(ch) && (i < lengthDoc));
			} else if (isoperator(ch)) {
				styler.ColourTo(i-1, state);
				styler.ColourTo(i, SCE_C_OPERATOR);
				if ((ch == '{') || (ch == '}')) {
					levelCurrent += (ch == '{') ? 1 : -1;
				}
			}
		} else if (state == SCE_C_IDENTIFIER) {
			if (!iswordchar(ch)) {
				lastWordWasUUID = classifyWordCpp(styler.GetStartSegment(), i - 1, keywords, styler);
				state = SCE_C_DEFAULT;
				if (ch == '/' && chNext == '*') {
					if (styler.SafeGetCharAt(i + 2) == '*')
						state = SCE_C_COMMENTDOC;
					else
						state = SCE_C_COMMENT;
				} else if (ch == '/' && chNext == '/') {
					state = SCE_C_COMMENTLINE;
				} else if (ch == '\"') {
					state = SCE_C_STRING;
				} else if (ch == '\'') {
					state = SCE_C_CHARACTER;
				} else if (isoperator(ch)) {
					styler.ColourTo(i, SCE_C_OPERATOR);
					if ((ch == '{') || (ch == '}')) {
						levelCurrent += (ch == '{') ? 1 : -1;
					}
				}
			}
		} else {
			if (state == SCE_C_PREPROCESSOR) {
				if (stylingWithinPreprocessor) {
					if (isspace(ch)) {
						styler.ColourTo(i-1, state);
						state = SCE_C_DEFAULT;
					}
				} else {
					if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) {
						styler.ColourTo(i-1, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENT) {
				if (ch == '/' && chPrev == '*') {
					if (((i > styler.GetStartSegment() + 2) || (
						(initStyle == SCE_C_COMMENT) &&
						(styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENTDOC) {
				if (ch == '/' && chPrev == '*') {
					if (((i > styler.GetStartSegment() + 2) || (
						(initStyle == SCE_C_COMMENTDOC) &&
						(styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_COMMENTLINE || state == SCE_C_COMMENTLINEDOC) {
				if (ch == '\r' || ch == '\n') {
					styler.ColourTo(i-1, state);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_STRING) {
				if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\"') {
					styler.ColourTo(i, state);
					state = SCE_C_DEFAULT;
				} else if ((chNext == '\r' || chNext == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i-1, SCE_C_STRINGEOL);
					state = SCE_C_STRINGEOL;
				}
			} else if (state == SCE_C_CHARACTER) {
				if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
					styler.ColourTo(i-1, SCE_C_STRINGEOL);
					state = SCE_C_STRINGEOL;
				} else if (ch == '\\') {
					if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				} else if (ch == '\'') {
					styler.ColourTo(i, state);
					state = SCE_C_DEFAULT;
				}
			} else if (state == SCE_C_REGEX) {
				if (ch == '\r' || ch == '\n' || ch == '/') {
					styler.ColourTo(i, state);
					state = SCE_C_DEFAULT;
				} else if (ch == '\\') {
					// Gobble up the quoted character
					if (chNext == '\\' || chNext == '/') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					}
				}
			} else if (state == SCE_C_VERBATIM) {
				if (ch == '\"') {
					if (chNext == '\"') {
						i++;
						ch = chNext;
						chNext = styler.SafeGetCharAt(i + 1);
					} else {
						styler.ColourTo(i, state);
						state = SCE_C_DEFAULT;
					}
				}
			} else if (state == SCE_C_UUID) {
				if (ch == '\r' || ch == '\n' || ch == ')') {
					styler.ColourTo(i-1, state);
					if (ch == ')')
						styler.ColourTo(i, SCE_C_OPERATOR);
					state = SCE_C_DEFAULT;
				}
			}
		}
		chPrev = ch;
		if (ch != ' ' && ch != '\t')
			chPrevNonWhite = ch;
	}
	styler.ColourTo(lengthDoc - 1, state);

	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	if (fold) {
		int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
		//styler.SetLevel(lineCurrent, levelCurrent | flagsNext);
		styler.SetLevel(lineCurrent, levelPrev | flagsNext);

	}
}

LexerModule lmCPP(SCLEX_CPP, ColouriseCppDoc);
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexLua.cxx
 ** Lexer for Lua language.
 **
 ** Written by Paul Winwood.
 ** Folder by Alexey Yutkin.
 ** Modified by Marcos E. Wurzius & Philippe Lhoste
 **/

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {
	return ch >= 0x80 ||
	       (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(int ch) {
	return ch >= 0x80 ||
	       (isalpha(ch) || ch == '_');
}

static inline bool IsANumberChar(int ch) {
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases.
	return (ch < 0x80) &&
	        (isdigit(ch) || toupper(ch) == 'E' ||
	        ch == '.' || ch == '-' || ch == '+' ||
	        (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'));
}

static inline bool IsLuaOperator(int ch) {
	if (ch >= 0x80 || isalnum(ch)) {
		return false;
	}
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' ||
		ch == '{' || ch == '}' || ch == '~' ||
		ch == '[' || ch == ']' || ch == ';' ||
		ch == '<' || ch == '>' || ch == ',' ||
		ch == '.' || ch == '^' || ch == '%' || ch == ':' ||
		ch == '#') {
		return true;
	}
	return false;
}

// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ],
// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on.
// The maximum number of '=' characters allowed is 254.
static int LongDelimCheck(StyleContext &sc) {
	int sep = 1;
	while (sc.GetRelative(sep) == '=' && sep < 0xFF)
		sep++;
	if (sc.GetRelative(sep) == sc.ch)
		return sep;
	return 0;
}

static void ColouriseLuaDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];
	WordList &keywords7 = *keywordlists[6];
	WordList &keywords8 = *keywordlists[7];

	int currentLine = styler.GetLine(startPos);
	// Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level,
	// if we are inside such a string. Block comment was introduced in Lua 5.0,
	// blocks with separators [=[ ... ]=] in Lua 5.1.
	int nestLevel = 0;
	int sepCount = 0;
	if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT) {
		int lineState = styler.GetLineState(currentLine - 1);
		nestLevel = lineState >> 8;
		sepCount = lineState & 0xFF;
	}

	// Do not leak onto next line
	if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) {
		initStyle = SCE_LUA_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);
	if (startPos == 0 && sc.ch == '#') {
		// shbang line: # is a comment only if first char of the script
		sc.SetState(SCE_LUA_COMMENTLINE);
	}
	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			currentLine = styler.GetLine(sc.currentPos);
			switch (sc.state) {
			case SCE_LUA_LITERALSTRING:
			case SCE_LUA_COMMENT:
				// Inside a literal string or block comment, we set the line state
				styler.SetLineState(currentLine, (nestLevel << 8) | sepCount);
				break;
			default:
				// Reset the line state
				styler.SetLineState(currentLine, 0);
				break;
			}
		}
		if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) {
			// Prevent SCE_LUA_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_LUA_STRING);
		}

		// Handle string line continuation
		if ((sc.state == SCE_LUA_STRING || sc.state == SCE_LUA_CHARACTER) &&
		        sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_LUA_OPERATOR) {
			sc.SetState(SCE_LUA_DEFAULT);
		} else if (sc.state == SCE_LUA_NUMBER) {
			// We stop the number definition on non-numerical non-dot non-eE non-sign non-hexdigit char
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || sc.Match('.', '.')) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD3);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD4);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD5);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords7.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD7);
				} else if (keywords8.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD8);
				}
				sc.SetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) {
			if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_CHARACTER) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) {
			if (sc.ch == '[') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // [[-only allowed to nest
					nestLevel++;
					sc.Forward();
				}
			} else if (sc.ch == ']') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // un-nest with ]]-only
					nestLevel--;
					sc.Forward();
					if (nestLevel == 0) {
						sc.ForwardSetState(SCE_LUA_DEFAULT);
					}
				} else if (sep > 1 && sep == sepCount) {   // ]=]-style delim
					sc.Forward(sep);
					sc.ForwardSetState(SCE_LUA_DEFAULT);
				}
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_LUA_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_LUA_NUMBER);
				if (sc.ch == '0' && toupper(sc.chNext) == 'X') {
					sc.Forward(1);
				}
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_LUA_IDENTIFIER);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_LUA_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_LUA_CHARACTER);
			} else if (sc.ch == '[') {
				sepCount = LongDelimCheck(sc);
				if (sepCount == 0) {
					sc.SetState(SCE_LUA_OPERATOR);
				} else {
					nestLevel = 1;
					sc.SetState(SCE_LUA_LITERALSTRING);
					sc.Forward(sepCount);
				}
			} else if (sc.Match('-', '-')) {
				sc.SetState(SCE_LUA_COMMENTLINE);
				if (sc.Match("--[")) {
					sc.Forward(2);
					sepCount = LongDelimCheck(sc);
					if (sepCount > 0) {
						nestLevel = 1;
						sc.ChangeState(SCE_LUA_COMMENT);
						sc.Forward(sepCount);
					}
				} else {
					sc.Forward();
				}
			} else if (sc.atLineStart && sc.Match('$')) {
				sc.SetState(SCE_LUA_PREPROCESSOR);	// Obsolete since Lua 4.0, but still in old code
			} else if (IsLuaOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_LUA_OPERATOR);
			}
		}
	}
	sc.Complete();
}

static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	int styleNext = styler.StyleAt(startPos);
	char s[10];

	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LUA_WORD) {
			if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') {
				for (unsigned int j = 0; j < 8; j++) {
					if (!iswordchar(styler[i + j])) {
						break;
					}
					s[j] = styler[i + j];
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) {
					levelCurrent++;
				}
				if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0) || (strcmp(s, "until") == 0)) {
					levelCurrent--;
				}
			}
		} else if (style == SCE_LUA_OPERATOR) {
			if (ch == '{' || ch == '(') {
				levelCurrent++;
			} else if (ch == '}' || ch == ')') {
				levelCurrent--;
			}
		} else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) {
			if (ch == '[') {
				levelCurrent++;
			} else if (ch == ']') {
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact) {
				lev |= SC_FOLDLEVELWHITEFLAG;
			}
			if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch)) {
			visibleChars++;
		}
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const luaWordListDesc[] = {
	"Keywords",
	"Basic functions",
	"String, (table) & math functions",
	"(coroutines), I/O & system facilities",
	"user1",
	"user2",
	"user3",
	"user4",
	0
};

LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc);
<commit_msg>Patch from Kein-Hong Man properly handles + or - as operators in numbers like 1+2.<commit_after>// Scintilla source code edit control
/** @file LexLua.cxx
 ** Lexer for Lua language.
 **
 ** Written by Paul Winwood.
 ** Folder by Alexey Yutkin.
 ** Modified by Marcos E. Wurzius & Philippe Lhoste
 **/

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {
	return ch >= 0x80 ||
	       (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(int ch) {
	return ch >= 0x80 ||
	       (isalpha(ch) || ch == '_');
}

static inline bool IsANumberChar(int ch) {
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases.
	return (ch < 0x80) &&
	        (isdigit(ch) || toupper(ch) == 'E' ||
	        ch == '.' || ch == '-' || ch == '+' ||
	        (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'));
}

static inline bool IsLuaOperator(int ch) {
	if (ch >= 0x80 || isalnum(ch)) {
		return false;
	}
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' ||
		ch == '{' || ch == '}' || ch == '~' ||
		ch == '[' || ch == ']' || ch == ';' ||
		ch == '<' || ch == '>' || ch == ',' ||
		ch == '.' || ch == '^' || ch == '%' || ch == ':' ||
		ch == '#') {
		return true;
	}
	return false;
}

// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ],
// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on.
// The maximum number of '=' characters allowed is 254.
static int LongDelimCheck(StyleContext &sc) {
	int sep = 1;
	while (sc.GetRelative(sep) == '=' && sep < 0xFF)
		sep++;
	if (sc.GetRelative(sep) == sc.ch)
		return sep;
	return 0;
}

static void ColouriseLuaDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];
	WordList &keywords7 = *keywordlists[6];
	WordList &keywords8 = *keywordlists[7];

	int currentLine = styler.GetLine(startPos);
	// Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level,
	// if we are inside such a string. Block comment was introduced in Lua 5.0,
	// blocks with separators [=[ ... ]=] in Lua 5.1.
	int nestLevel = 0;
	int sepCount = 0;
	if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT) {
		int lineState = styler.GetLineState(currentLine - 1);
		nestLevel = lineState >> 8;
		sepCount = lineState & 0xFF;
	}

	// Do not leak onto next line
	if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) {
		initStyle = SCE_LUA_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);
	if (startPos == 0 && sc.ch == '#') {
		// shbang line: # is a comment only if first char of the script
		sc.SetState(SCE_LUA_COMMENTLINE);
	}
	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			currentLine = styler.GetLine(sc.currentPos);
			switch (sc.state) {
			case SCE_LUA_LITERALSTRING:
			case SCE_LUA_COMMENT:
				// Inside a literal string or block comment, we set the line state
				styler.SetLineState(currentLine, (nestLevel << 8) | sepCount);
				break;
			default:
				// Reset the line state
				styler.SetLineState(currentLine, 0);
				break;
			}
		}
		if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) {
			// Prevent SCE_LUA_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_LUA_STRING);
		}

		// Handle string line continuation
		if ((sc.state == SCE_LUA_STRING || sc.state == SCE_LUA_CHARACTER) &&
		        sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_LUA_OPERATOR) {
			sc.SetState(SCE_LUA_DEFAULT);
		} else if (sc.state == SCE_LUA_NUMBER) {
			// We stop the number definition on non-numerical non-dot non-eE non-sign non-hexdigit char
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_LUA_DEFAULT);
			} else if (sc.ch == '-' || sc.ch == '+') {
                                if (sc.chPrev != 'E' && sc.chPrev != 'e')
                                        sc.SetState(SCE_LUA_DEFAULT);
                        }
		} else if (sc.state == SCE_LUA_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || sc.Match('.', '.')) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD3);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD4);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD5);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords7.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD7);
				} else if (keywords8.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD8);
				}
				sc.SetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) {
			if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_CHARACTER) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) {
			if (sc.ch == '[') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // [[-only allowed to nest
					nestLevel++;
					sc.Forward();
				}
			} else if (sc.ch == ']') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // un-nest with ]]-only
					nestLevel--;
					sc.Forward();
					if (nestLevel == 0) {
						sc.ForwardSetState(SCE_LUA_DEFAULT);
					}
				} else if (sep > 1 && sep == sepCount) {   // ]=]-style delim
					sc.Forward(sep);
					sc.ForwardSetState(SCE_LUA_DEFAULT);
				}
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_LUA_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_LUA_NUMBER);
				if (sc.ch == '0' && toupper(sc.chNext) == 'X') {
					sc.Forward(1);
				}
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_LUA_IDENTIFIER);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_LUA_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_LUA_CHARACTER);
			} else if (sc.ch == '[') {
				sepCount = LongDelimCheck(sc);
				if (sepCount == 0) {
					sc.SetState(SCE_LUA_OPERATOR);
				} else {
					nestLevel = 1;
					sc.SetState(SCE_LUA_LITERALSTRING);
					sc.Forward(sepCount);
				}
			} else if (sc.Match('-', '-')) {
				sc.SetState(SCE_LUA_COMMENTLINE);
				if (sc.Match("--[")) {
					sc.Forward(2);
					sepCount = LongDelimCheck(sc);
					if (sepCount > 0) {
						nestLevel = 1;
						sc.ChangeState(SCE_LUA_COMMENT);
						sc.Forward(sepCount);
					}
				} else {
					sc.Forward();
				}
			} else if (sc.atLineStart && sc.Match('$')) {
				sc.SetState(SCE_LUA_PREPROCESSOR);	// Obsolete since Lua 4.0, but still in old code
			} else if (IsLuaOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_LUA_OPERATOR);
			}
		}
	}
	sc.Complete();
}

static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	int styleNext = styler.StyleAt(startPos);
	char s[10];

	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LUA_WORD) {
			if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') {
				for (unsigned int j = 0; j < 8; j++) {
					if (!iswordchar(styler[i + j])) {
						break;
					}
					s[j] = styler[i + j];
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) {
					levelCurrent++;
				}
				if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0) || (strcmp(s, "until") == 0)) {
					levelCurrent--;
				}
			}
		} else if (style == SCE_LUA_OPERATOR) {
			if (ch == '{' || ch == '(') {
				levelCurrent++;
			} else if (ch == '}' || ch == ')') {
				levelCurrent--;
			}
		} else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) {
			if (ch == '[') {
				levelCurrent++;
			} else if (ch == ']') {
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact) {
				lev |= SC_FOLDLEVELWHITEFLAG;
			}
			if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch)) {
			visibleChars++;
		}
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const luaWordListDesc[] = {
	"Keywords",
	"Basic functions",
	"String, (table) & math functions",
	"(coroutines), I/O & system facilities",
	"user1",
	"user2",
	"user3",
	"user4",
	0
};

LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc);
<|endoftext|>


<commit_before>#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <stddef.h>
#include <linux/inotify.h>

using namespace std;

#include "debug.h"
#include "config.h"

Config::Config(int count, char** values) :
	m_all(false),
	m_verbose(2),
	m_pidfile_path("/var/run"),
	m_logfile_path(""),
	m_no_demon(false),
	m_path_to_scripts("/etc/rnotifyd"),
	m_exclude(),
	m_heartbeat(250),
	m_skip_zero_file(false),
	m_enable_supressor(false),
	m_mask(0),
	m_catch_rename(false),
	m_need_help(false),
	m_my_name(values[0])
{
	readOpts(count, values);
	readMask();
}

Config::~Config()
{
	vector <char*> :: iterator itr;
	for (itr = m_watch.begin(); itr != m_watch.end(); ++itr)
	{
		delete *itr;
	}
}

bool Config::getAll()
{
	return m_all;
}

string Config::getMyName()
{
	return m_my_name;
}

bool Config::getNeedHelp()
{
	return m_need_help;
}

bool Config::getCatchRename()
{
	return m_catch_rename;
}

bool Config::getEnableSuppressor()
{
	return m_enable_supressor;
}

bool Config::getSkipZeroFile()
{
	return m_skip_zero_file;
}

bool Config::getNoDemon()
{
	return m_no_demon;
}

string Config::getExclude()
{
	return m_exclude;
}

string Config::getPathToScripts()
{
	return m_path_to_scripts;
}

string Config::getPidfile()
{
	return m_pidfile_path + "/" + m_my_name + ".pid";
}

string Config::getLogfilePath()
{
	return m_logfile_path;
}

uint32_t Config::getMask()
{
	return m_mask;
}

int Config::getHearbeat()
{
	return m_heartbeat;
}

int Config::getVerbose()
{
	return m_verbose;
}

char** Config::getWatch()
{
	return &m_watch[0];
}

void Config::readMask()
{
	if (m_all)
	{
		m_mask = IN_ALL_EVENTS;
		return;
	}

	if (m_path_to_scripts.empty())
	{
		m_mask = 0;
		return;
	}

	DIR* dp	= opendir(m_path_to_scripts.c_str());
	if (dp == NULL)
	{
		fatal << " Nothing to do in " << m_path_to_scripts.c_str() << "/. Please follow instructions for -s argument." << std::endl;
		m_need_help = true;
		return;
	}

	size_t dirent_sz = offsetof(struct dirent, d_name) + pathconf(m_path_to_scripts.c_str(), _PC_NAME_MAX);
	struct dirent* entry = new struct dirent[dirent_sz + 1];
	if (entry == NULL)
	{
		fatal << " Can't get entry from " << m_path_to_scripts.c_str() << "." << std::endl;
		m_need_help = true;
		closedir(dp);
		return;
	}

	char** lst = NULL;
	for (;;)
	{
		struct dirent* result = NULL;
		if (0 != readdir_r(dp, entry, &result)
			|| result == NULL)
		{
			break;
		}

		if (!strcmp(entry->d_name, ".")
			|| !strcmp(entry->d_name, ".."))
		{
                        continue;
		}

		string script = m_path_to_scripts + "/" + result->d_name;
		debug << "<<<<<<<< ++" << script << std::endl;

		if (!strcmp(result->d_name, "IN_ACCESS") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_ACCESS;
		}

		if (!strcmp(result->d_name, "IN_ATTRIB") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_ATTRIB;
		}

		if (!strcmp(result->d_name, "IN_CLOSE_WRITE") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_CLOSE_WRITE;
		}

		if (!strcmp(result->d_name, "IN_CLOSE_NOWRITE") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_CLOSE_NOWRITE;
		}

		if (!strcmp(result->d_name, "IN_CREATE") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_CREATE;
		}

		if (!strcmp(result->d_name, "IN_DELETE") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_DELETE;
		}

		if (!strcmp(result->d_name, "IN_DELETE_SELF") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_DELETE_SELF;
		}

		if (!strcmp(result->d_name, "IN_MODIFY") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_MODIFY;
		}

		if (!strcmp(result->d_name, "IN_MOVE_SELF") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_MOVE_SELF;
		}

		if (!strcmp(result->d_name, "IN_MOVED_FROM") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_MOVED_FROM;
		}

		if (!strcmp(result->d_name, "IN_MOVED_TO") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_MOVED_TO;
		}

		if (!strcmp(result->d_name, "IN_OPEN") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_OPEN;
		}

		if (!strcmp(result->d_name, "IN_RENAME") && !access(script.c_str(), X_OK))
		{
			m_catch_rename = true;
		}
	}

	if (!m_mask && !m_catch_rename)
	{
		m_need_help = true;
	}

	delete entry;
	closedir(dp);
}

void Config::readOpts(int count, char** values)
{
	const char* opts = "av:p:l:dhw:s:e:t:zu";
	char opt = 0;

	while (-1 != (opt = getopt(count, values, opts)))
	{
		switch (opt)
		{
			case 'a':
				m_all = true;
				m_no_demon = true;
				break;
			case 'v':
				m_verbose = atoi(optarg);
				break;
			case 'p':
				m_pidfile_path = optarg;
				break;
			case 'l':
				m_logfile_path = optarg;
				break;
			case 'd':
				m_no_demon = true;
				break;
			case 's':
				m_path_to_scripts = optarg;
				break;
			case 'e':
				m_exclude = optarg;
				break;
			case 't':
				m_heartbeat = atoi(optarg);
				break;
			case 'z':
				m_skip_zero_file = true;
				break;
			case 'u':
				m_enable_supressor = true;
				break;
			case 'w':
				m_watch.push_back(strdup(optarg));
				break;
			case 'h':
				m_need_help = true;
				break;
			default:
				break;
		}
	}
	m_watch.push_back(NULL);

	Debug::Init(m_verbose, m_no_demon, m_logfile_path);

	char** watch = getWatch();
	if (watch[0] == NULL)
	{
		fatal << " At least one watched directory should be present. Look at -w argument please." << std::endl;
		m_need_help = true;
	}
}

<commit_msg>clear code<commit_after>#include <iostream>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <stddef.h>
#include <linux/inotify.h>

using namespace std;

#include "debug.h"
#include "config.h"

Config::Config(int count, char** values) :
	m_all(false),
	m_verbose(2),
	m_pidfile_path("/var/run"),
	m_logfile_path(""),
	m_no_demon(false),
	m_path_to_scripts("/etc/rnotifyd"),
	m_exclude(),
	m_heartbeat(250),
	m_skip_zero_file(false),
	m_enable_supressor(false),
	m_mask(0),
	m_catch_rename(false),
	m_need_help(false),
	m_my_name(values[0])
{
	readOpts(count, values);
	readMask();
}

Config::~Config()
{
	vector <char*> :: iterator itr;
	for (itr = m_watch.begin(); itr != m_watch.end(); ++itr)
	{
		delete *itr;
	}
}

bool Config::getAll()
{
	return m_all;
}

string Config::getMyName()
{
	return m_my_name;
}

bool Config::getNeedHelp()
{
	return m_need_help;
}

bool Config::getCatchRename()
{
	return m_catch_rename;
}

bool Config::getEnableSuppressor()
{
	return m_enable_supressor;
}

bool Config::getSkipZeroFile()
{
	return m_skip_zero_file;
}

bool Config::getNoDemon()
{
	return m_no_demon;
}

string Config::getExclude()
{
	return m_exclude;
}

string Config::getPathToScripts()
{
	return m_path_to_scripts;
}

string Config::getPidfile()
{
	return m_pidfile_path + "/" + m_my_name + ".pid";
}

string Config::getLogfilePath()
{
	return m_logfile_path;
}

uint32_t Config::getMask()
{
	return m_mask;
}

int Config::getHearbeat()
{
	return m_heartbeat;
}

int Config::getVerbose()
{
	return m_verbose;
}

char** Config::getWatch()
{
	return &m_watch[0];
}

void Config::readMask()
{
	if (m_all)
	{
		m_mask = IN_ALL_EVENTS;
		return;
	}

	if (m_path_to_scripts.empty())
	{
		m_mask = 0;
		return;
	}

	DIR* dp	= opendir(m_path_to_scripts.c_str());
	if (dp == NULL)
	{
		fatal << " Nothing to do in " << m_path_to_scripts.c_str() << "/. Please follow instructions for -s argument." << std::endl;
		m_need_help = true;
		return;
	}

	size_t dirent_sz = offsetof(struct dirent, d_name) + pathconf(m_path_to_scripts.c_str(), _PC_NAME_MAX);
	struct dirent* entry = new struct dirent[dirent_sz + 1];
	if (entry == NULL)
	{
		fatal << " Can't get entry from " << m_path_to_scripts.c_str() << "." << std::endl;
		m_need_help = true;
		closedir(dp);
		return;
	}

	char** lst = NULL;
	for (;;)
	{
		struct dirent* result = NULL;
		if (0 != readdir_r(dp, entry, &result)
			|| result == NULL)
		{
			break;
		}

		if (!strcmp(entry->d_name, ".")
			|| !strcmp(entry->d_name, ".."))
		{
                        continue;
		}

		string script = m_path_to_scripts + "/" + result->d_name;

		if (!strcmp(result->d_name, "IN_ACCESS") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_ACCESS;
		}

		if (!strcmp(result->d_name, "IN_ATTRIB") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_ATTRIB;
		}

		if (!strcmp(result->d_name, "IN_CLOSE_WRITE") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_CLOSE_WRITE;
		}

		if (!strcmp(result->d_name, "IN_CLOSE_NOWRITE") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_CLOSE_NOWRITE;
		}

		if (!strcmp(result->d_name, "IN_CREATE") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_CREATE;
		}

		if (!strcmp(result->d_name, "IN_DELETE") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_DELETE;
		}

		if (!strcmp(result->d_name, "IN_DELETE_SELF") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_DELETE_SELF;
		}

		if (!strcmp(result->d_name, "IN_MODIFY") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_MODIFY;
		}

		if (!strcmp(result->d_name, "IN_MOVE_SELF") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_MOVE_SELF;
		}

		if (!strcmp(result->d_name, "IN_MOVED_FROM") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_MOVED_FROM;
		}

		if (!strcmp(result->d_name, "IN_MOVED_TO") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_MOVED_TO;
		}

		if (!strcmp(result->d_name, "IN_OPEN") && !access(script.c_str(), X_OK))
		{
			m_mask |= IN_OPEN;
		}

		if (!strcmp(result->d_name, "IN_RENAME") && !access(script.c_str(), X_OK))
		{
			m_catch_rename = true;
		}
	}

	if (!m_mask && !m_catch_rename)
	{
		m_need_help = true;
	}

	delete entry;
	closedir(dp);
}

void Config::readOpts(int count, char** values)
{
	const char* opts = "av:p:l:dhw:s:e:t:zu";
	char opt = 0;

	while (-1 != (opt = getopt(count, values, opts)))
	{
		switch (opt)
		{
			case 'a':
				m_all = true;
				m_no_demon = true;
				break;
			case 'v':
				m_verbose = atoi(optarg);
				break;
			case 'p':
				m_pidfile_path = optarg;
				break;
			case 'l':
				m_logfile_path = optarg;
				break;
			case 'd':
				m_no_demon = true;
				break;
			case 's':
				m_path_to_scripts = optarg;
				break;
			case 'e':
				m_exclude = optarg;
				break;
			case 't':
				m_heartbeat = atoi(optarg);
				break;
			case 'z':
				m_skip_zero_file = true;
				break;
			case 'u':
				m_enable_supressor = true;
				break;
			case 'w':
				m_watch.push_back(strdup(optarg));
				break;
			case 'h':
				m_need_help = true;
				break;
			default:
				break;
		}
	}
	m_watch.push_back(NULL);

	Debug::Init(m_verbose, m_no_demon, m_logfile_path);

	char** watch = getWatch();
	if (watch[0] == NULL)
	{
		fatal << " At least one watched directory should be present. Look at -w argument please." << std::endl;
		m_need_help = true;
	}
}

<|endoftext|>


<commit_before>#include "pending_irob.h"
#include "debug.h"
#include "timeops.h"
#include <functional>
#include <vector>
using std::vector; using std::max;
using std::mem_fun_ref;
using std::bind1st;

#include "pthread_util.h"

static pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
ssize_t PendingIROB::obj_count = 0;

PendingIROB::PendingIROB(irob_id_t id_)
    : id(id_),
      anonymous(false),
      complete(false),
      placeholder(true)
{
    /* this placeholder PendingIROB will be replaced by
       the real one, when it arrives. */
}

PendingIROB::PendingIROB(irob_id_t id_, int numdeps, const irob_id_t *deps_array,
			 size_t datalen, char *data, u_long send_labels_)
    : id(id_),
      send_labels(send_labels_),
      anonymous(false),
      complete(false),
      placeholder(false)
{
    if (numdeps > 0) {
        assert(deps_array);
    }
    for (int i = 0; i < numdeps; i++) {
        deps.insert(deps_array[i]);
    }

    if (datalen > 0) {
        anonymous = true;
        assert(data);
        struct irob_chunk_data chunk;
        chunk.id = id;
        chunk.seqno = INVALID_IROB_SEQNO;
        chunk.datalen = datalen;
        chunk.data = data;

        (void)add_chunk(chunk);
        (void)finish();
    }

    PthreadScopedLock lock(&count_mutex);
    ++obj_count;
}

PendingIROB::~PendingIROB()
{
    while (!chunks.empty()) {
        struct irob_chunk_data chunk = chunks.front();
        chunks.pop_front();
        delete [] chunk.data;
    }

    PthreadScopedLock lock(&count_mutex);
    --obj_count;
}

ssize_t
PendingIROB::objs()
{
    PthreadScopedLock lock(&count_mutex);
    return obj_count;
}

bool
PendingIROB::add_chunk(struct irob_chunk_data& irob_chunk)
{
    if (is_complete()) {
        return false;
    }

    chunks.push_back(irob_chunk);
    return true;
}

bool
PendingIROB::finish(void)
{
    if (is_complete()) {
        return false;
    }
    complete = true;
    return true;
}

void
PendingIROB::add_dep(irob_id_t id)
{
    deps.insert(id);
}

void
PendingIROB::dep_satisfied(irob_id_t id)
{
    deps.erase(id);
}

void
PendingIROB::add_dependent(irob_id_t id)
{
    dependents.insert(id);
}

bool
PendingIROB::is_complete(void) const
{
    return complete;
}

bool
PendingIROB::is_anonymous(void) const
{
    return anonymous;
}

bool
PendingIROB::depends_on(irob_id_t that)
{
    return (deps.count(that) == 1);
}

PendingIROBLattice::PendingIROBLattice()
    : offset(0), last_anon_irob_id(-1), count(0)
{
    pthread_mutex_init(&membership_lock, NULL);
}

PendingIROBLattice::~PendingIROBLattice()
{
    {
        PthreadScopedLock lock(&membership_lock);
        for (size_t i = 0; i < pending_irobs.size(); i++) {
            delete pending_irobs[i];
        }
        pending_irobs.clear();
        offset = 0;
    }
    pthread_mutex_destroy(&membership_lock);
}

bool
PendingIROBLattice::insert(PendingIROB *pirob, bool infer_deps)
{
    PthreadScopedLock lock(&membership_lock);
    return insert_locked(pirob, infer_deps);
}

bool
PendingIROBLattice::insert_locked(PendingIROB *pirob, bool infer_deps)
{
    assert(pirob);
    if (past_irobs.contains(pirob->id)) {
        dbgprintf("Inserting IROB %d failed; it's in past_irobs\n", pirob->id);
        return false;
    }

    if (pending_irobs.empty()) {
        offset = pirob->id;
    }

    int index = pirob->id - offset;

    if (index >= 0 && index < (int)pending_irobs.size() &&
        (pending_irobs[index] != NULL &&
         !pending_irobs[index]->placeholder)) {
        dbgprintf("Inserting IROB %d failed; I have it already??\n", pirob->id);
        return false;
    }
    while (index < 0) {
        pending_irobs.push_front(NULL);
        --offset;
        index = pirob->id - offset;
    }
    if ((int)pending_irobs.size() <= index) {
        pending_irobs.resize(index+1, NULL);
    }
    if (pending_irobs[index]) {
        // grab the placeholder's dependents and replace it
        // with the real PendingIROB
        assert(!pirob->placeholder);
        assert(pending_irobs[index]->placeholder);
        assert(pending_irobs[index]->id == pirob->id);
        pirob->dependents.insert(pending_irobs[index]->dependents.begin(),
                                 pending_irobs[index]->dependents.end());
        delete pending_irobs[index];
        pending_irobs[index] = pirob;
    } else {
        pending_irobs[index] = pirob;
    }

    if (pirob->placeholder) {
        // pirob only exists to hold dependents until
        // its replacement arrives.
        return true;
    }

    correct_deps(pirob, infer_deps);

    dbgprintf("Adding IROB %d as dependent of: [ ", pirob->id);
    for (irob_id_set::iterator it = pirob->deps.begin();
         it != pirob->deps.end(); it++) {
        PendingIROB *dep = find_locked(*it);
        if (dep) {
            dbgprintf_plain("%ld ", dep->id);
            dep->add_dependent(pirob->id);
        } else {
            dbgprintf_plain("(%ld) ", *it);
            dep = new PendingIROB(*it);
            insert_locked(dep);
            dep->add_dependent(pirob->id);
        }
    }
    dbgprintf_plain("]\n");

    ++count;
    return true;
}

void
PendingIROBLattice::clear()
{
    PthreadScopedLock lock(&membership_lock);

    pending_irobs.clear();
    min_dominator_set.clear();
    last_anon_irob_id = -1;
    count = 0;
}

void
PendingIROBLattice::correct_deps(PendingIROB *pirob, bool infer_deps)
{
    /* 1) If pirob is anonymous, add deps on all pending IROBs. */
    /* 2) Otherwise, add deps on all pending anonymous IROBs. */
    /* we keep around a min-dominator set of IROBs; that is,
     * the minimal set of IROBs that the next anonymous IROB
     * must depend on. */

    if (!infer_deps) {
        pirob->remove_deps_if(bind1st(mem_fun_ref(&IntSet::contains),
                                      past_irobs));
    }

    if (infer_deps) {
        // skip this at the receiver. The sender infers and
        //  communicates deps; the receiver enforces them.

        if (pirob->is_anonymous()) {
            if (last_anon_irob_id >= 0 && min_dominator_set.empty()) {
                pirob->add_dep(last_anon_irob_id);
            } else {
                pirob->deps.insert(min_dominator_set.begin(),
                                   min_dominator_set.end());
                min_dominator_set.clear();
            }
            last_anon_irob_id = pirob->id;
        } else {
            // this IROB dominates its deps, so remove them from
            // the min_dominator_set before inserting it
            vector<irob_id_t> isect(max(pirob->deps.size(),
                                        min_dominator_set.size()));
            vector<irob_id_t>::iterator the_end =
                set_intersection(pirob->deps.begin(), pirob->deps.end(),
                                 min_dominator_set.begin(),
                                 min_dominator_set.end(),
                                 isect.begin());

            if (last_anon_irob_id >= 0 && isect.begin() == the_end) {
                pirob->add_dep(last_anon_irob_id);
            } // otherwise, it already depends on something
            // that depends on the last_anon_irob

            for (vector<irob_id_t>::iterator it = isect.begin();
                 it != the_end; ++it) {
                min_dominator_set.erase(*it);
            }

            min_dominator_set.insert(pirob->id);
        }
    }

    if (!infer_deps) {
        /* 3) Remove already-satisfied deps. */
        pirob->remove_deps_if(bind1st(mem_fun_ref(&IntSet::contains),
                                      past_irobs));
    }
}

PendingIROB *
PendingIROBLattice::find(irob_id_t id)
{
    PthreadScopedLock lock(&membership_lock);

    return find_locked(id);
}

PendingIROB *
PendingIROBLattice::find_locked(irob_id_t id)
{
    //TimeFunctionBody timer("pending_irobs.find(accessor)");
    int index = id - offset;
    if (index < 0 || index >= (int)pending_irobs.size()) {
        return NULL;
    }
    return pending_irobs[index];
}

bool
PendingIROBLattice::erase(irob_id_t id)
{
    PthreadScopedLock lock(&membership_lock);

    //TimeFunctionBody timer("pending_irobs.erase(const_accessor)");
    int index = id - offset;
    if (index < 0 || index >= (int)pending_irobs.size() ||
        pending_irobs[index] == NULL) {
        dbgprintf("WARNING: failed to remove IROB %d from lattice!\n", id);
        return false;
    }
    past_irobs.insert(id);
    min_dominator_set.erase(id);

    PendingIROB *victim = pending_irobs[index];
    pending_irobs[index] = NULL; // caller must free it
    while (!pending_irobs.empty() && pending_irobs[0] == NULL) {
        pending_irobs.pop_front();
        offset++;
    }

    dbgprintf("Notifying dependents of IROB %d's release: [ ", id);
    for (irob_id_set::iterator it = victim->dependents.begin();
         it != victim->dependents.end(); it++) {

        PendingIROB *dependent = this->find_locked(*it);
        if (dependent == NULL) {
            dbgprintf_plain("(%ld) ", *it);
            continue;
        }
        dbgprintf_plain("%ld ", dependent->id);
        dependent->dep_satisfied(id);
    }
    dbgprintf_plain("]\n");

    --count;
    return true;
}

bool
PendingIROBLattice::past_irob_exists(irob_id_t id)
{
    PthreadScopedLock lock(&membership_lock);
    return past_irobs.contains(id);
}

bool
PendingIROBLattice::empty()
{
    PthreadScopedLock lock(&membership_lock);
    return pending_irobs.empty();
}

size_t
PendingIROBLattice::size()
{
    PthreadScopedLock lock(&membership_lock);
    return count;
}

IROBSchedulingData::IROBSchedulingData(irob_id_t id_, u_long seqno_)
    : id(id_), seqno(seqno_)
{
    /* empty */
}

bool
IROBSchedulingData::operator<(const IROBSchedulingData& other) const
{
    // can implement priority here, based on
    //  any added scheduling hints
    return (id < other.id) || (seqno < other.seqno);
}
<commit_msg>Don't insert placeholders for IROBs that are in past_irobs.<commit_after>#include "pending_irob.h"
#include "debug.h"
#include "timeops.h"
#include <functional>
#include <vector>
using std::vector; using std::max;
using std::mem_fun_ref;
using std::bind1st;

#include "pthread_util.h"

static pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
ssize_t PendingIROB::obj_count = 0;

PendingIROB::PendingIROB(irob_id_t id_)
    : id(id_),
      anonymous(false),
      complete(false),
      placeholder(true)
{
    /* this placeholder PendingIROB will be replaced by
       the real one, when it arrives. */
}

PendingIROB::PendingIROB(irob_id_t id_, int numdeps, const irob_id_t *deps_array,
			 size_t datalen, char *data, u_long send_labels_)
    : id(id_),
      send_labels(send_labels_),
      anonymous(false),
      complete(false),
      placeholder(false)
{
    if (numdeps > 0) {
        assert(deps_array);
    }
    for (int i = 0; i < numdeps; i++) {
        deps.insert(deps_array[i]);
    }

    if (datalen > 0) {
        anonymous = true;
        assert(data);
        struct irob_chunk_data chunk;
        chunk.id = id;
        chunk.seqno = INVALID_IROB_SEQNO;
        chunk.datalen = datalen;
        chunk.data = data;

        (void)add_chunk(chunk);
        (void)finish();
    }

    PthreadScopedLock lock(&count_mutex);
    ++obj_count;
}

PendingIROB::~PendingIROB()
{
    while (!chunks.empty()) {
        struct irob_chunk_data chunk = chunks.front();
        chunks.pop_front();
        delete [] chunk.data;
    }

    PthreadScopedLock lock(&count_mutex);
    --obj_count;
}

ssize_t
PendingIROB::objs()
{
    PthreadScopedLock lock(&count_mutex);
    return obj_count;
}

bool
PendingIROB::add_chunk(struct irob_chunk_data& irob_chunk)
{
    if (is_complete()) {
        return false;
    }

    chunks.push_back(irob_chunk);
    return true;
}

bool
PendingIROB::finish(void)
{
    if (is_complete()) {
        return false;
    }
    complete = true;
    return true;
}

void
PendingIROB::add_dep(irob_id_t id)
{
    deps.insert(id);
}

void
PendingIROB::dep_satisfied(irob_id_t id)
{
    deps.erase(id);
}

void
PendingIROB::add_dependent(irob_id_t id)
{
    dependents.insert(id);
}

bool
PendingIROB::is_complete(void) const
{
    return complete;
}

bool
PendingIROB::is_anonymous(void) const
{
    return anonymous;
}

bool
PendingIROB::depends_on(irob_id_t that)
{
    return (deps.count(that) == 1);
}

PendingIROBLattice::PendingIROBLattice()
    : offset(0), last_anon_irob_id(-1), count(0)
{
    pthread_mutex_init(&membership_lock, NULL);
}

PendingIROBLattice::~PendingIROBLattice()
{
    {
        PthreadScopedLock lock(&membership_lock);
        for (size_t i = 0; i < pending_irobs.size(); i++) {
            delete pending_irobs[i];
        }
        pending_irobs.clear();
        offset = 0;
    }
    pthread_mutex_destroy(&membership_lock);
}

bool
PendingIROBLattice::insert(PendingIROB *pirob, bool infer_deps)
{
    PthreadScopedLock lock(&membership_lock);
    return insert_locked(pirob, infer_deps);
}

bool
PendingIROBLattice::insert_locked(PendingIROB *pirob, bool infer_deps)
{
    assert(pirob);
    if (past_irobs.contains(pirob->id)) {
        dbgprintf("Inserting IROB %d failed; it's in past_irobs\n", pirob->id);
        return false;
    }

    if (pending_irobs.empty()) {
        offset = pirob->id;
    }

    int index = pirob->id - offset;

    if (index >= 0 && index < (int)pending_irobs.size() &&
        (pending_irobs[index] != NULL &&
         !pending_irobs[index]->placeholder)) {
        dbgprintf("Inserting IROB %d failed; I have it already??\n", pirob->id);
        return false;
    }
    while (index < 0) {
        pending_irobs.push_front(NULL);
        --offset;
        index = pirob->id - offset;
    }
    if ((int)pending_irobs.size() <= index) {
        pending_irobs.resize(index+1, NULL);
    }
    if (pending_irobs[index]) {
        // grab the placeholder's dependents and replace it
        // with the real PendingIROB
        assert(!pirob->placeholder);
        assert(pending_irobs[index]->placeholder);
        assert(pending_irobs[index]->id == pirob->id);
        pirob->dependents.insert(pending_irobs[index]->dependents.begin(),
                                 pending_irobs[index]->dependents.end());
        delete pending_irobs[index];
        pending_irobs[index] = pirob;
    } else {
        pending_irobs[index] = pirob;
    }

    if (pirob->placeholder) {
        // pirob only exists to hold dependents until
        // its replacement arrives.
        return true;
    }

    correct_deps(pirob, infer_deps);

    dbgprintf("Adding IROB %d as dependent of: [ ", pirob->id);
    for (irob_id_set::iterator it = pirob->deps.begin();
         it != pirob->deps.end(); it++) {
        if (past_irobs.contains(*it)) {
            dbgprintf_plain("(%ld) ", *it);
            continue;
        }

        PendingIROB *dep = find_locked(*it);
        if (dep) {
            dbgprintf_plain("%ld ", dep->id);
            dep->add_dependent(pirob->id);
        } else {
            dbgprintf_plain("P%ld ", *it);
            dep = new PendingIROB(*it);
            bool ret = insert_locked(dep);
            assert(ret);
            dep->add_dependent(pirob->id);
        }
    }
    dbgprintf_plain("]\n");

    ++count;
    return true;
}

void
PendingIROBLattice::clear()
{
    PthreadScopedLock lock(&membership_lock);

    pending_irobs.clear();
    min_dominator_set.clear();
    last_anon_irob_id = -1;
    count = 0;
}

void
PendingIROBLattice::correct_deps(PendingIROB *pirob, bool infer_deps)
{
    /* 1) If pirob is anonymous, add deps on all pending IROBs. */
    /* 2) Otherwise, add deps on all pending anonymous IROBs. */
    /* we keep around a min-dominator set of IROBs; that is,
     * the minimal set of IROBs that the next anonymous IROB
     * must depend on. */

    if (!infer_deps) {
        pirob->remove_deps_if(bind1st(mem_fun_ref(&IntSet::contains),
                                      past_irobs));
    }

    if (infer_deps) {
        // skip this at the receiver. The sender infers and
        //  communicates deps; the receiver enforces them.

        if (pirob->is_anonymous()) {
            if (last_anon_irob_id >= 0 && min_dominator_set.empty()) {
                pirob->add_dep(last_anon_irob_id);
            } else {
                pirob->deps.insert(min_dominator_set.begin(),
                                   min_dominator_set.end());
                min_dominator_set.clear();
            }
            last_anon_irob_id = pirob->id;
        } else {
            // this IROB dominates its deps, so remove them from
            // the min_dominator_set before inserting it
            vector<irob_id_t> isect(max(pirob->deps.size(),
                                        min_dominator_set.size()));
            vector<irob_id_t>::iterator the_end =
                set_intersection(pirob->deps.begin(), pirob->deps.end(),
                                 min_dominator_set.begin(),
                                 min_dominator_set.end(),
                                 isect.begin());

            if (last_anon_irob_id >= 0 && isect.begin() == the_end) {
                pirob->add_dep(last_anon_irob_id);
            } // otherwise, it already depends on something
            // that depends on the last_anon_irob

            for (vector<irob_id_t>::iterator it = isect.begin();
                 it != the_end; ++it) {
                min_dominator_set.erase(*it);
            }

            min_dominator_set.insert(pirob->id);
        }
    }

    if (!infer_deps) {
        /* 3) Remove already-satisfied deps. */
        pirob->remove_deps_if(bind1st(mem_fun_ref(&IntSet::contains),
                                      past_irobs));
    }
}

PendingIROB *
PendingIROBLattice::find(irob_id_t id)
{
    PthreadScopedLock lock(&membership_lock);

    return find_locked(id);
}

PendingIROB *
PendingIROBLattice::find_locked(irob_id_t id)
{
    //TimeFunctionBody timer("pending_irobs.find(accessor)");
    int index = id - offset;
    if (index < 0 || index >= (int)pending_irobs.size()) {
        return NULL;
    }
    return pending_irobs[index];
}

bool
PendingIROBLattice::erase(irob_id_t id)
{
    PthreadScopedLock lock(&membership_lock);

    //TimeFunctionBody timer("pending_irobs.erase(const_accessor)");
    int index = id - offset;
    if (index < 0 || index >= (int)pending_irobs.size() ||
        pending_irobs[index] == NULL) {
        dbgprintf("WARNING: failed to remove IROB %d from lattice!\n", id);
        return false;
    }
    past_irobs.insert(id);
    min_dominator_set.erase(id);

    PendingIROB *victim = pending_irobs[index];
    pending_irobs[index] = NULL; // caller must free it
    while (!pending_irobs.empty() && pending_irobs[0] == NULL) {
        pending_irobs.pop_front();
        offset++;
    }

    dbgprintf("Notifying dependents of IROB %d's release: [ ", id);
    for (irob_id_set::iterator it = victim->dependents.begin();
         it != victim->dependents.end(); it++) {

        PendingIROB *dependent = this->find_locked(*it);
        if (dependent == NULL) {
            dbgprintf_plain("(%ld) ", *it);
            continue;
        }
        dbgprintf_plain("%ld ", dependent->id);
        dependent->dep_satisfied(id);
    }
    dbgprintf_plain("]\n");

    --count;
    return true;
}

bool
PendingIROBLattice::past_irob_exists(irob_id_t id)
{
    PthreadScopedLock lock(&membership_lock);
    return past_irobs.contains(id);
}

bool
PendingIROBLattice::empty()
{
    PthreadScopedLock lock(&membership_lock);
    return pending_irobs.empty();
}

size_t
PendingIROBLattice::size()
{
    PthreadScopedLock lock(&membership_lock);
    return count;
}

IROBSchedulingData::IROBSchedulingData(irob_id_t id_, u_long seqno_)
    : id(id_), seqno(seqno_)
{
    /* empty */
}

bool
IROBSchedulingData::operator<(const IROBSchedulingData& other) const
{
    // can implement priority here, based on
    //  any added scheduling hints
    return (id < other.id) || (seqno < other.seqno);
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Andrey Valyaev <dron.valyaev@gmail.com>
//
// This software may be modified and distributed under the terms
// of the MIT license.  See the LICENSE file for details.

#include <Result.h>
#include <Format.h>
#include <Report.h>

using namespace std;
using namespace oout;

Result::Result(
	const string &tag,
	const map<string, string> &attributes,
	const list<shared_ptr<const Result>> &nodes
)
	: tag(tag), attributes(attributes), nodes(nodes)
{
}

string Result::print(const Format &format) const
{
	// @todo #??:15min Use polymorphism instead if
	if (tag == "testcase") {
		return format.test(
			attributes.at("name"),
			attributes.at("failures") != "0",
			0
		);
	}

	if (tag == "testsuite") {
		return format.suite(
			attributes.at("name"),
			0,
			nodes
		);
	}

	throw runtime_error("Wrong node type");
}

size_t Result::failures() const
{
	return stoi(attributes.at("failures"));
}
<commit_msg>#68: fix todo<commit_after>// Copyright (c) 2017 Andrey Valyaev <dron.valyaev@gmail.com>
//
// This software may be modified and distributed under the terms
// of the MIT license.  See the LICENSE file for details.

#include <Result.h>
#include <Format.h>
#include <Report.h>

using namespace std;
using namespace oout;

Result::Result(
	const string &tag,
	const map<string, string> &attributes,
	const list<shared_ptr<const Result>> &nodes
)
	: tag(tag), attributes(attributes), nodes(nodes)
{
}

string Result::print(const Format &format) const
{
	// @todo #68:15min Use polymorphism instead if
	if (tag == "testcase") {
		return format.test(
			attributes.at("name"),
			attributes.at("failures") != "0",
			0
		);
	}

	if (tag == "testsuite") {
		return format.suite(
			attributes.at("name"),
			0,
			nodes
		);
	}

	throw runtime_error("Wrong node type");
}

size_t Result::failures() const
{
	return stoi(attributes.at("failures"));
}
<|endoftext|>