<commit_before>#include "FusionEKF.h"
#include "tools.h"
#include "Eigen/Dense"
#include <iostream>

using namespace std;
using Eigen::MatrixXd;
using Eigen::VectorXd;
using std::vector;

/*
 * Constructor.
 */
FusionEKF::FusionEKF() {

  is_initialized_ = false;
  long long previous_timestamp_ = 0;

  // initializing matrices
  R_laser_ = MatrixXd(2, 2);
  R_radar_ = MatrixXd(3, 3);

  H_laser_ = MatrixXd(2, 4);
  H_laser_ << 1, 0, 0, 0,
              0, 1, 0, 0;

  // Hj_ = MatrixXd(3, 4);

  //measurement covariance matrix - laser
  R_laser_ << 0.0225, 0,
              0,      0.0225;

  //measurement covariance matrix - radar
  R_radar_ << 0.09, 0,      0,
              0,    0.0009, 0,
              0,    0,      0.09;

  ekf_.P_ = MatrixXd(4, 4);
  ekf_.P_ <<  .5,    0,    0,      0,
              0,    .5,    0,      0,
              0,    0,    1000,   0,
              0,    0,    0,    1000;

  // state transistion matrix
  // will change with time
  ekf_.F_ = MatrixXd(4, 4);
  ekf_.F_ << 1, 0, 0, 0,
             0, 1, 0, 0,
             0, 0, 1, 0,
             0, 0, 0, 1;

  ekf_.Q_ = MatrixXd(4, 4);
  // appears to need this to run otherwise get nan(ind) error
  ekf_.Q_ << 0, 0, 0, 0,
             0, 0, 0, 0,
             0, 0, 0, 0,
             0, 0, 0, 0;

}

/**
* Destructor.
*/
FusionEKF::~FusionEKF() {}

void FusionEKF::ProcessMeasurement(const MeasurementPackage &measurement_pack) {

  /*****************************************************************************
   *  Initialization
   ****************************************************************************/
  if (!is_initialized_) {

    // first measurement
    // cout << "EKF: " << endl;
    ekf_.x_ = VectorXd(4);
    ekf_.x_ << 1, 1, 1, 1;

    if (measurement_pack.sensor_type_ == MeasurementPackage::RADAR) {
      // Convert radar from polar to cartesian coordinates and initialize state.
      /* Where
       *  rho == distance from origin to point p
       *  phi == angle between px and py
       *  rhodot == estimated distance from point p ?
       */
      double rho = measurement_pack.raw_measurements_[0];
      double phi = measurement_pack.raw_measurements_[1];
      double rhodot = measurement_pack.raw_measurements_[2];

      double px = rho * cos(phi);
      double py = rho * sin(phi);

      double vx = rhodot * cos(phi);
      double vy = rhodot * sin(phi);

      ekf_.x_ << px, py, vx, vy;
    }

    else if (measurement_pack.sensor_type_ == MeasurementPackage::LASER) {
      // set state with initial llocation and zero velocity
      ekf_.x_ << measurement_pack.raw_measurements_[0], measurement_pack.raw_measurements_[1], 0, 0;
    }

    // functions valid for both laser and radar
    long long previous_timestamp_ = measurement_pack.timestamp_;
    // done initializing, no need to predict or update
    is_initialized_ = true;

    return;
  }

  /*****************************************************************************
   *  Prediction
   ****************************************************************************/

  // 1) compute elapsed time where delta time (dt) == difference_time, expresssed in seconds
  double secondsDivisor = 1000000.0; // 1,000,000
  double dt = (measurement_pack.timestamp_ - previous_timestamp_) / secondsDivisor;

  // Pre computer time difference power terms
  // where dt_x == "_x" == power term ie dt_3 == dt to the third power
  double dt_2 = dt * dt;
  double dt_3 = dt_2 * dt;
  double dt_4 = dt_3 * dt;
  // end precomputation of dt terms

  // 2) use Delta t to compute new EKF F, Q

  // modfy F matrix to integrate time
  ekf_.F_(0, 2) = dt;
  ekf_.F_(1, 3) = dt;

  // acceleration noise components for Q matrix.
  const int noise_ax = 9;
  const int noise_ay = 9;

    // set covariance matrix Q
  ekf_.Q_ = MatrixXd(4, 4);
  ekf_.Q_ <<  dt_4/4*noise_ax, 0,               dt_3/2*noise_ax, 0,
              0,               dt_4/4*noise_ay, 0,               dt_3/2*noise_ay,
              dt_3/2*noise_ax, 0,               dt_2*noise_ax,   0,
              0,               dt_3/2*noise_ay, 0,               dt_2*noise_ay;

  // If time difference is acceptable do prediction step.
  if (dt > .001) {
    ekf_.Predict();
  }

  /*****************************************************************************
   *  Update
   ****************************************************************************/

  // Setup matrices
  if (measurement_pack.sensor_type_ == MeasurementPackage::RADAR) {

    // Lineraize measurement function
    ekf_.H_ = tools.CalculateJacobian(ekf_.x_);

    // Radar updates
    ekf_.R_ = R_radar_;

    // State update with new measurements
    ekf_.UpdateEKF(measurement_pack.raw_measurements_);

  } else {  // Laser updates
    ekf_.R_ = R_laser_;
    ekf_.H_ = H_laser_;
    // State update with new measurements
    ekf_.Update(measurement_pack.raw_measurements_);
  }

  // print the output
  // cout << "x_ = " << ekf_.x_ << endl;
  // cout << "P_ = " << ekf_.P_ << endl;
}
<commit_msg>add timestamp update and improve efficiency<commit_after>#include "FusionEKF.h"
#include "tools.h"
#include "Eigen/Dense"
#include <iostream>

using namespace std;
using Eigen::MatrixXd;
using Eigen::VectorXd;
using std::vector;

/*
 * Constructor.
 */
FusionEKF::FusionEKF() {

  is_initialized_ = false;
  long long previous_timestamp_ = 0;

  // initializing matrices
  R_laser_ = MatrixXd(2, 2);
  R_radar_ = MatrixXd(3, 3);

  H_laser_ = MatrixXd(2, 4);
  H_laser_ << 1, 0, 0, 0,
              0, 1, 0, 0;

  //measurement covariance matrix - laser
  R_laser_ << 0.0225, 0,
              0,      0.0225;

  //measurement covariance matrix - radar
  R_radar_ << 0.09, 0,      0,
              0,    0.0009, 0,
              0,    0,      0.09;

  ekf_.P_ = MatrixXd(4, 4);
  ekf_.P_ <<  .5,    0,    0,      0,
              0,    .5,    0,      0,
              0,    0,    1000,   0,
              0,    0,    0,    1000;

  // state transistion matrix will change with time
  ekf_.F_ = MatrixXd(4, 4);
  ekf_.F_ << 1, 0, 0, 0,
             0, 1, 0, 0,
             0, 0, 1, 0,
             0, 0, 0, 1;

  ekf_.Q_ = MatrixXd(4, 4);
  ekf_.Q_ << 0, 0, 0, 0,
             0, 0, 0, 0,
             0, 0, 0, 0,
             0, 0, 0, 0;

}

/**
* Destructor.
*/
FusionEKF::~FusionEKF() {}

void FusionEKF::ProcessMeasurement(const MeasurementPackage &measurement_pack) {

  /*****************************************************************************
   *  Initialization
   ****************************************************************************/
  if (!is_initialized_) {

    // first measurement
    // cout << "EKF: " << endl;
    ekf_.x_ = VectorXd(4);
    ekf_.x_ << 1, 1, 1, 1;

    if (measurement_pack.sensor_type_ == MeasurementPackage::RADAR) {
      // Convert radar from polar to cartesian coordinates and initialize state.
      /* Where
       *  rho == distance from origin to point p
       *  phi == angle between px and py
       *  rhodot == estimated distance from point p ?
       */
      double rho = measurement_pack.raw_measurements_[0];
      double phi = measurement_pack.raw_measurements_[1];
      double rhodot = measurement_pack.raw_measurements_[2];

      double px = rho * cos(phi);
      double py = rho * sin(phi);

      double vx = rhodot * cos(phi);
      double vy = rhodot * sin(phi);

      ekf_.x_ << px, py, vx, vy;
    }

    else if (measurement_pack.sensor_type_ == MeasurementPackage::LASER) {
      // set state with initial llocation and zero velocity
      ekf_.x_ << measurement_pack.raw_measurements_[0], measurement_pack.raw_measurements_[1], 0, 0;
    }

    // functions valid for both laser and radar
    long long previous_timestamp_ = measurement_pack.timestamp_;
    // done initializing, no need to predict or update
    is_initialized_ = true;

    return;
  }

  /*****************************************************************************
   *  Prediction
   ****************************************************************************/

  // 1) compute elapsed time where delta time (dt) == difference_time, expresssed in seconds
  double secondsDivisor = 1000000.0; // 1,000,000
  double dt = (measurement_pack.timestamp_ - previous_timestamp_) / secondsDivisor;
  long long previous_timestamp_ = measurement_pack.timestamp_;

  // If time difference is acceptable do prediction step.
  if (dt > .001) {

    // Pre computer time difference power terms
    // where dt_x == "_x" == power term ie dt_3 == dt to the third power
    double dt_2 = dt * dt;
    double dt_3 = dt_2 * dt;
    double dt_4 = dt_3 * dt;
    // end precomputation of dt terms

    // 2) use Delta t to compute new EKF F, Q

    // modfy F matrix to integrate time
    ekf_.F_(0, 2) = dt;
    ekf_.F_(1, 3) = dt;

    // acceleration noise components for Q matrix.
    const int noise_ax = 9;
    const int noise_ay = 9;

      // set covariance matrix Q
    ekf_.Q_ = MatrixXd(4, 4);
    ekf_.Q_ <<  dt_4/4*noise_ax, 0,               dt_3/2*noise_ax, 0,
                0,               dt_4/4*noise_ay, 0,               dt_3/2*noise_ay,
                dt_3/2*noise_ax, 0,               dt_2*noise_ax,   0,
                0,               dt_3/2*noise_ay, 0,               dt_2*noise_ay;

    ekf_.Predict();
  }

  /*****************************************************************************
   *  Update
   ****************************************************************************/

  // Setup matrices
  if (measurement_pack.sensor_type_ == MeasurementPackage::RADAR) {

    // Radar updates
    ekf_.R_ = R_radar_;

    // Lineraize measurement function
    ekf_.H_ = tools.CalculateJacobian(ekf_.x_);

    // State update with new measurements
    ekf_.UpdateEKF(measurement_pack.raw_measurements_);

  } else {  // Laser updates
    ekf_.R_ = R_laser_;
    ekf_.H_ = H_laser_;
    // State update with new measurements
    ekf_.Update(measurement_pack.raw_measurements_);
  }

  // print the output
  // cout << "x_ = " << ekf_.x_ << endl;
  // cout << "P_ = " << ekf_.P_ << endl;
}
<|endoftext|>


<commit_before>// taken from http://www.alexfedotov.com/articles/killproc.asp
//

#include "stdafx.h"
#include "winp.h"

//---------------------------------------------------------------------------
// KillProcess
//
//  Terminates the specified process.
//
//  Parameters:
//	  dwProcessId - identifier of the process to terminate
//
//  Returns:
//	  TRUE, if successful, FALSE - otherwise.
//
BOOL WINAPI KillProcess(DWORD dwProcessId) {
	DWORD dwError;

	// first try to obtain handle to the process without the use of any
	// additional privileges
	HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId);
	if (hProcess == NULL)
		return FALSE;

	// terminate the process
	if (!TerminateProcess(hProcess, (UINT)-1)) {
		dwError = GetLastError();
		CloseHandle(hProcess);
		return SetLastError(dwError), FALSE;
	}

	CloseHandle(hProcess);

	// completed successfully
	return TRUE;
}

typedef LONG	KPRIORITY;

typedef struct _CLIENT_ID {
    DWORD	    UniqueProcess;
    DWORD	    UniqueThread;
} CLIENT_ID;

typedef struct _UNICODE_STRING {
    USHORT	    Length;
    USHORT	    MaximumLength;
    PWSTR	    Buffer;
} UNICODE_STRING;

typedef struct _VM_COUNTERS {
    SIZE_T	    PeakVirtualSize;
    SIZE_T	    VirtualSize;
    ULONG	    PageFaultCount;
    SIZE_T	    PeakWorkingSetSize;
    SIZE_T	    WorkingSetSize;
    SIZE_T	    QuotaPeakPagedPoolUsage;
    SIZE_T	    QuotaPagedPoolUsage;
    SIZE_T	    QuotaPeakNonPagedPoolUsage;
    SIZE_T	    QuotaNonPagedPoolUsage;
    SIZE_T	    PagefileUsage;
    SIZE_T	    PeakPagefileUsage;
} VM_COUNTERS;

typedef struct _SYSTEM_THREADS {
    LARGE_INTEGER   KernelTime;
    LARGE_INTEGER   UserTime;
    LARGE_INTEGER   CreateTime;
    ULONG			WaitTime;
    PVOID			StartAddress;
    CLIENT_ID	    ClientId;
    KPRIORITY	    Priority;
    KPRIORITY	    BasePriority;
    ULONG			ContextSwitchCount;
    LONG			State;
    LONG			WaitReason;
} SYSTEM_THREADS, * PSYSTEM_THREADS;

// Note that the size of the SYSTEM_PROCESSES structure is different on
// NT 4 and Win2K, but we don't care about it, since we don't access neither
// IoCounters member nor Threads array

typedef struct _SYSTEM_PROCESSES {
    ULONG			NextEntryDelta;
    ULONG			ThreadCount;
    ULONG			Reserved1[6];
    LARGE_INTEGER   CreateTime;
    LARGE_INTEGER   UserTime;
    LARGE_INTEGER   KernelTime;
    UNICODE_STRING  ProcessName;
    KPRIORITY	    BasePriority;
    ULONG			ProcessId;
    ULONG			InheritedFromProcessId;
    ULONG			HandleCount;
    ULONG			Reserved2[2];
    VM_COUNTERS	    VmCounters;
#if _WIN32_WINNT >= 0x500
    IO_COUNTERS	    IoCounters;
#endif
    SYSTEM_THREADS  Threads[1];
} SYSTEM_PROCESSES, * PSYSTEM_PROCESSES;

//---------------------------------------------------------------------------
// KillProcessTreeNtHelper
//
//  This is a recursive helper function that terminates all the processes
//  started by the specified process and them terminates the process itself
//
//  Parameters:
//	  pInfo       - processes information
//	  dwProcessId - identifier of the process to terminate
//
//  Returns:
//	  Win32 error code.
//
static BOOL WINAPI KillProcessTreeNtHelper(PSYSTEM_PROCESSES pInfo, DWORD dwProcessId) {
	_ASSERTE(pInfo != NULL);

    PSYSTEM_PROCESSES p = pInfo;

    // kill all children first
    for (;;)
    {
		if (p->InheritedFromProcessId == dwProcessId)
			KillProcessTreeNtHelper(pInfo, p->ProcessId);

		if (p->NextEntryDelta == 0)
			break;

		// find the address of the next process structure
		p = (PSYSTEM_PROCESSES)(((LPBYTE)p) + p->NextEntryDelta);
    }

	// kill the process itself
    if (!KillProcess(dwProcessId))
		return GetLastError();

	return ERROR_SUCCESS;
}

//---------------------------------------------------------------------------
// KillProcessTreeWinHelper
//
//  This is a recursive helper function that terminates all the processes
//  started by the specified process and them terminates the process itself
//
//  Parameters:
//	  dwProcessId - identifier of the process to terminate
//
//  Returns:
//	  Win32 error code.
//
static BOOL WINAPI KillProcessTreeWinHelper(DWORD dwProcessId) {
	// create a snapshot
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hSnapshot == INVALID_HANDLE_VALUE)
		return GetLastError();

	PROCESSENTRY32 Entry;
	Entry.dwSize = sizeof(Entry);
	if (!Process32First(hSnapshot, &Entry))
	{
		DWORD dwError = GetLastError();
		CloseHandle(hSnapshot);
		return dwError;
	}

	// kill all children first
	do
	{
		if (Entry.th32ParentProcessID == dwProcessId)
			KillProcessTreeWinHelper(Entry.th32ProcessID);

		Entry.dwSize = sizeof(Entry);
	}
	while (Process32Next(hSnapshot, &Entry));

	CloseHandle(hSnapshot);

	// kill the process itself
    if (!KillProcess(dwProcessId))
		return GetLastError();

	return ERROR_SUCCESS;
}

//---------------------------------------------------------------------------
// KillProcessEx
//
//  Terminates the specified process and, optionally, all processes started
//	from the specified process (the so-called process tree).
//
//  Parameters:
//	  dwProcessId - identifier of the process to terminate
//	  bTree		  - specifies whether the entire process tree should be
//					terminated
//
//  Returns:
//	  TRUE, if successful, FALSE - otherwise.
//
BOOL WINAPI KillProcessEx(DWORD dwProcessId, BOOL bTree) {
	if (!bTree)
		return KillProcess(dwProcessId);

	OSVERSIONINFO osvi;
	DWORD dwError;

	// determine operating system version
	osvi.dwOSVersionInfoSize = sizeof(osvi);
	GetVersionEx(&osvi);

	if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
		osvi.dwMajorVersion < 5)
	{
		// obtain a handle to the default process heap
		HANDLE hHeap = GetProcessHeap();

		NTSTATUS Status;
		ULONG cbBuffer = 0x8000;
		PVOID pBuffer = NULL;

		// it is difficult to say a priory which size of the buffer
		// will be enough to retrieve all information, so we start
		// with 32K buffer and increase its size until we get the
		// information successfully
		do
		{
			pBuffer = HeapAlloc(hHeap, 0, cbBuffer);
			if (pBuffer == NULL)
				return SetLastError(ERROR_NOT_ENOUGH_MEMORY), FALSE;

			Status = ZwQuerySystemInformation(
							SystemProcessesAndThreadsInformation,
							pBuffer, cbBuffer, NULL);

			if (Status == STATUS_INFO_LENGTH_MISMATCH)
			{
				HeapFree(hHeap, 0, pBuffer);
				cbBuffer *= 2;
			}
			else if (!NT_SUCCESS(Status))
			{
				HeapFree(hHeap, 0, pBuffer);
				return SetLastError(Status), NULL;
			}
		}
		while (Status == STATUS_INFO_LENGTH_MISMATCH);

		// call the helper function
		dwError = KillProcessTreeNtHelper((PSYSTEM_PROCESSES)pBuffer,
										  dwProcessId);

		HeapFree(hHeap, 0, pBuffer);
	}
	else
	{
		// call the helper function
		dwError = KillProcessTreeWinHelper(dwProcessId);
	}

	SetLastError(dwError);
	return dwError == ERROR_SUCCESS;
}
<commit_msg>https://hudson.dev.java.net/issues/show_bug.cgi?id=2842 reported an infinite recursion, so first, reducing the stack usage per recursion so that the hotspot dump would show arguments, and second, checking for obvious loop<commit_after>// taken from http://www.alexfedotov.com/articles/killproc.asp
//

#include "stdafx.h"
#include "winp.h"

//---------------------------------------------------------------------------
// KillProcess
//
//  Terminates the specified process.
//
//  Parameters:
//	  dwProcessId - identifier of the process to terminate
//
//  Returns:
//	  TRUE, if successful, FALSE - otherwise.
//
BOOL WINAPI KillProcess(DWORD dwProcessId) {
	DWORD dwError;

	// first try to obtain handle to the process without the use of any
	// additional privileges
	HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessId);
	if (hProcess == NULL)
		return FALSE;

	// terminate the process
	if (!TerminateProcess(hProcess, (UINT)-1)) {
		dwError = GetLastError();
		CloseHandle(hProcess);
		return SetLastError(dwError), FALSE;
	}

	CloseHandle(hProcess);

	// completed successfully
	return TRUE;
}

typedef LONG	KPRIORITY;

typedef struct _CLIENT_ID {
    DWORD	    UniqueProcess;
    DWORD	    UniqueThread;
} CLIENT_ID;

typedef struct _UNICODE_STRING {
    USHORT	    Length;
    USHORT	    MaximumLength;
    PWSTR	    Buffer;
} UNICODE_STRING;

typedef struct _VM_COUNTERS {
    SIZE_T	    PeakVirtualSize;
    SIZE_T	    VirtualSize;
    ULONG	    PageFaultCount;
    SIZE_T	    PeakWorkingSetSize;
    SIZE_T	    WorkingSetSize;
    SIZE_T	    QuotaPeakPagedPoolUsage;
    SIZE_T	    QuotaPagedPoolUsage;
    SIZE_T	    QuotaPeakNonPagedPoolUsage;
    SIZE_T	    QuotaNonPagedPoolUsage;
    SIZE_T	    PagefileUsage;
    SIZE_T	    PeakPagefileUsage;
} VM_COUNTERS;

typedef struct _SYSTEM_THREADS {
    LARGE_INTEGER   KernelTime;
    LARGE_INTEGER   UserTime;
    LARGE_INTEGER   CreateTime;
    ULONG			WaitTime;
    PVOID			StartAddress;
    CLIENT_ID	    ClientId;
    KPRIORITY	    Priority;
    KPRIORITY	    BasePriority;
    ULONG			ContextSwitchCount;
    LONG			State;
    LONG			WaitReason;
} SYSTEM_THREADS, * PSYSTEM_THREADS;

// Note that the size of the SYSTEM_PROCESSES structure is different on
// NT 4 and Win2K, but we don't care about it, since we don't access neither
// IoCounters member nor Threads array

typedef struct _SYSTEM_PROCESSES {
    ULONG			NextEntryDelta;
    ULONG			ThreadCount;
    ULONG			Reserved1[6];
    LARGE_INTEGER   CreateTime;
    LARGE_INTEGER   UserTime;
    LARGE_INTEGER   KernelTime;
    UNICODE_STRING  ProcessName;
    KPRIORITY	    BasePriority;
    ULONG			ProcessId;
    ULONG			InheritedFromProcessId;
    ULONG			HandleCount;
    ULONG			Reserved2[2];
    VM_COUNTERS	    VmCounters;
#if _WIN32_WINNT >= 0x500
    IO_COUNTERS	    IoCounters;
#endif
    SYSTEM_THREADS  Threads[1];
} SYSTEM_PROCESSES, * PSYSTEM_PROCESSES;

//---------------------------------------------------------------------------
// KillProcessTreeNtHelper
//
//  This is a recursive helper function that terminates all the processes
//  started by the specified process and them terminates the process itself
//
//  Parameters:
//	  pInfo       - processes information
//	  dwProcessId - identifier of the process to terminate
//
//  Returns:
//	  Win32 error code.
//
BOOL WINAPI KillProcessTreeNtHelper(PSYSTEM_PROCESSES pInfo, DWORD dwProcessId) {
	_ASSERTE(pInfo != NULL);

    PSYSTEM_PROCESSES p = pInfo;

    // kill all children first
    for (;;)
    {
		if (p->InheritedFromProcessId == dwProcessId)
			KillProcessTreeNtHelper(pInfo, p->ProcessId);

		if (p->NextEntryDelta == 0)
			break;

		// find the address of the next process structure
		p = (PSYSTEM_PROCESSES)(((LPBYTE)p) + p->NextEntryDelta);
    }

	// kill the process itself
    if (!KillProcess(dwProcessId))
		return GetLastError();

	return ERROR_SUCCESS;
}

//---------------------------------------------------------------------------
// KillProcessTreeWinHelper
//
//  This is a recursive helper function that terminates all the processes
//  started by the specified process and them terminates the process itself
//
//  Parameters:
//	  dwProcessId - identifier of the process to terminate
//
//  Returns:
//	  Win32 error code.
//
BOOL WINAPI KillProcessTreeWinHelper(DWORD dwProcessId) {
	// create a snapshot
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hSnapshot == INVALID_HANDLE_VALUE)
		return GetLastError();

	PROCESSENTRY32* pEntry = (PROCESSENTRY32*)::LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT,sizeof(PROCESSENTRY32));

	pEntry->dwSize = sizeof(PROCESSENTRY32);
	if (!Process32First(hSnapshot, pEntry))
	{
		DWORD dwError = GetLastError();
		CloseHandle(hSnapshot);
		::LocalFree(pEntry);
		return dwError;
	}

	// kill all children first
	do
	{
		// there was a report of infinite recursion, so watching out for the obvious self-loop possibility
		DWORD pid = pEntry->th32ProcessID;
		if (pEntry->th32ParentProcessID == dwProcessId && dwProcessId!=pid)
			KillProcessTreeWinHelper(pid);
	}
	while (Process32Next(hSnapshot, pEntry));

	CloseHandle(hSnapshot);
	::LocalFree(pEntry);

	// kill the process itself
    if (!KillProcess(dwProcessId))
		return GetLastError();

	return ERROR_SUCCESS;
}

//---------------------------------------------------------------------------
// KillProcessEx
//
//  Terminates the specified process and, optionally, all processes started
//	from the specified process (the so-called process tree).
//
//  Parameters:
//	  dwProcessId - identifier of the process to terminate
//	  bTree		  - specifies whether the entire process tree should be
//					terminated
//
//  Returns:
//	  TRUE, if successful, FALSE - otherwise.
//
BOOL WINAPI KillProcessEx(DWORD dwProcessId, BOOL bTree) {
	if (!bTree)
		return KillProcess(dwProcessId);

	OSVERSIONINFO osvi;
	DWORD dwError;

	// determine operating system version
	osvi.dwOSVersionInfoSize = sizeof(osvi);
	GetVersionEx(&osvi);

	if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
		osvi.dwMajorVersion < 5)
	{
		// obtain a handle to the default process heap
		HANDLE hHeap = GetProcessHeap();

		NTSTATUS Status;
		ULONG cbBuffer = 0x8000;
		PVOID pBuffer = NULL;

		// it is difficult to say a priory which size of the buffer
		// will be enough to retrieve all information, so we start
		// with 32K buffer and increase its size until we get the
		// information successfully
		do
		{
			pBuffer = HeapAlloc(hHeap, 0, cbBuffer);
			if (pBuffer == NULL)
				return SetLastError(ERROR_NOT_ENOUGH_MEMORY), FALSE;

			Status = ZwQuerySystemInformation(
							SystemProcessesAndThreadsInformation,
							pBuffer, cbBuffer, NULL);

			if (Status == STATUS_INFO_LENGTH_MISMATCH)
			{
				HeapFree(hHeap, 0, pBuffer);
				cbBuffer *= 2;
			}
			else if (!NT_SUCCESS(Status))
			{
				HeapFree(hHeap, 0, pBuffer);
				return SetLastError(Status), NULL;
			}
		}
		while (Status == STATUS_INFO_LENGTH_MISMATCH);

		// call the helper function
		dwError = KillProcessTreeNtHelper((PSYSTEM_PROCESSES)pBuffer,
										  dwProcessId);

		HeapFree(hHeap, 0, pBuffer);
	}
	else
	{
		// call the helper function
		dwError = KillProcessTreeWinHelper(dwProcessId);
	}

	SetLastError(dwError);
	return dwError == ERROR_SUCCESS;
}
<|endoftext|>


<commit_before>/*
 * ====================================================================
 * Copyright (c) 2002-2005 The RapidSvn Group.  All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library (in the file LGPL.txt); if not,
 * write to the Free Software Foundation, Inc., 51 Franklin St,
 * Fifth Floor, Boston, MA  02110-1301  USA
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://rapidsvn.tigris.org/.
 * ====================================================================
 */

// svncpp
#include "status.hpp"

//#include <assert.h>

namespace svn
{
  class Status_private
  {
  public:
    Status_private();
    virtual ~Status_private();
    /**
     * Initialize structures
     *
     * @param path
     * @param status if NULL isVersioned will be false
     */
    void
    init (const QString&path, const svn_wc_status2_t * status);
    void
    init (const QString&path,const Status_private&src);
    void
    init(const QString&url,const DirEntry&src);
    void
    init(const QString&url,const InfoEntry&src);

    QString m_Path;
    bool m_isVersioned;
    bool m_hasReal;
    LockEntry m_Lock;
    Entry m_entry;

    svn_wc_status_kind _text_status,_prop_status,_repos_text_status,_repos_prop_status;
    bool _copied,_switched;
  };

  Status_private::Status_private()
    :m_Path(),m_isVersioned(false),m_hasReal(false)
  {
  }

  Status_private::~ Status_private()
  {
  }

  void Status_private::init (const QString&path, const svn_wc_status2_t * status)
  {
    m_Path = path;

    if (!status)
    {
      m_isVersioned = false;
      m_hasReal = false;
      m_entry=Entry();
      m_Lock = LockEntry();
    }
    else
    {
      m_isVersioned = status->text_status > svn_wc_status_unversioned;
      m_hasReal = m_isVersioned &&
                          status->text_status!=svn_wc_status_ignored;
      // now duplicate the contents
      if (status->entry)
      {
        m_entry = Entry(status->entry);
      } else {
        m_entry=Entry();
      }
      _text_status = status->text_status;
      _prop_status = status->prop_status;
      _copied = status->copied!=0;
      _switched = status->switched!=0;
      _repos_text_status = status->repos_text_status;
      _repos_prop_status = status->repos_prop_status;
      if (status->repos_lock) {
        m_Lock.init(status->repos_lock->creation_date,
                    status->repos_lock->expiration_date,
                    status->repos_lock->owner,
                    status->repos_lock->comment,
                    status->repos_lock->comment);
      } else {
        m_Lock=LockEntry();
      }
    }
  }

  void
  Status_private::init (const QString&path,const Status_private&src)
  {
    m_Path=path;
    m_Lock=src.m_Lock;
    m_entry=src.m_entry;
    m_isVersioned=src.m_isVersioned;
    m_hasReal=src.m_hasReal;
    _text_status=src._text_status;
    _prop_status=src._prop_status;
    _repos_text_status=src._repos_text_status;
    _repos_prop_status=src._repos_prop_status;
    _copied=src._copied;
    _switched=src._switched;
  }

  void Status_private::init(const QString&url,const DirEntry&src)
  {
    m_entry=Entry(url,src);
    m_Path=url;
    _text_status = svn_wc_status_normal;
    _prop_status = svn_wc_status_normal;
    m_Lock=src.lockEntry();
    _switched = false;
    _repos_text_status = svn_wc_status_normal;
    _repos_prop_status = svn_wc_status_normal;
    m_isVersioned=true;
    m_hasReal=true;
  }

  void Status_private::init(const QString&url,const InfoEntry&src)
  {
    m_entry=Entry(url,src);
    m_Path=url;
    m_Lock=src.lockEntry();
    _text_status = svn_wc_status_normal;
    _prop_status = svn_wc_status_normal;
    _repos_text_status = svn_wc_status_normal;
    _repos_prop_status = svn_wc_status_normal;
    m_isVersioned=true;
    m_hasReal=true;
  }

  Status::Status (const Status & src)
    : m_Data(new Status_private())
  {
    if( &src != this )
    {
        if (src.m_Data) {
             m_Data->init (src.m_Data->m_Path, *(src.m_Data));
        } else {
            m_Data->init(src.m_Data->m_Path,0);
        }
    }
  }

  Status::Status (const QString&path, svn_wc_status2_t * status)
    : m_Data(new Status_private())
  {
    m_Data->init(path, status);
  }

  Status::Status (const char*path, svn_wc_status2_t * status)
    : m_Data(new Status_private())
  {
    m_Data->init(QString::fromUtf8(path),status);
  }

  Status::Status(const QString&url,const DirEntry&src)
    : m_Data(new Status_private())
  {
    m_Data->init(url,src);
  }

  Status::Status(const QString&url,const InfoEntry&src)
    : m_Data(new Status_private())
  {
    m_Data->init(url,src);
  }

  Status::~Status ()
  {
    delete m_Data;
  }

  Status &
  Status::operator=(const Status & status)
  {
    if (this == &status)
      return *this;
    if (status.m_Data) {
        m_Data->init (status.m_Data->m_Path, *(status.m_Data));
    } else {
        m_Data->init(status.m_Data->m_Path,0);
    }
    return *this;
  }

  const LockEntry&
  Status::lockEntry () const
  {
      return m_Data->m_Lock;
  }
    const svn_wc_status_kind
    Status::reposPropStatus () const
    {
      return m_Data->_repos_prop_status;
    }
    const svn_wc_status_kind
    Status::reposTextStatus () const
    {
      return m_Data->_repos_text_status;
    }
    const bool
    Status::isSwitched () const
    {
      return m_Data->_switched != 0;
    }
    const bool
    Status::isCopied () const
    {
      return m_Data->_copied;
    }

    const bool
    Status::isLocked () const
    {
      return m_Data->m_Lock.Locked();
    }

    const bool
    Status::isRealVersioned()const
    {
      return m_Data->m_hasReal;
    }

    const bool
    Status::isVersioned () const
    {
      return m_Data->m_isVersioned;
    }

    const svn_wc_status_kind
    Status::propStatus () const
    {
      return m_Data->_prop_status;
    }

    const svn_wc_status_kind
    Status::textStatus () const
    {
      return m_Data->_text_status;
    }

    const Entry&
    Status::entry () const
    {
      return m_Data->m_entry;
    }

    const QString&
    Status::path () const
    {
      return m_Data->m_Path;
    }

    bool
    Status::validReposStatus()const
    {
        return reposTextStatus()!=svn_wc_status_none||reposPropStatus()!=svn_wc_status_none;
    }

    bool
    Status::validLocalStatus()const
    {
        return textStatus()!=svn_wc_status_none||propStatus()!=svn_wc_status_none;
    }
}
<commit_msg>better check if item is versioned.<commit_after>/*
 * ====================================================================
 * Copyright (c) 2002-2005 The RapidSvn Group.  All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library (in the file LGPL.txt); if not,
 * write to the Free Software Foundation, Inc., 51 Franklin St,
 * Fifth Floor, Boston, MA  02110-1301  USA
 *
 * This software consists of voluntary contributions made by many
 * individuals.  For exact contribution history, see the revision
 * history and logs, available at http://rapidsvn.tigris.org/.
 * ====================================================================
 */

// svncpp
#include "status.hpp"

//#include <assert.h>

namespace svn
{
  class Status_private
  {
  public:
    Status_private();
    virtual ~Status_private();
    /**
     * Initialize structures
     *
     * @param path
     * @param status if NULL isVersioned will be false
     */
    void
    init (const QString&path, const svn_wc_status2_t * status);
    void
    init (const QString&path,const Status_private&src);
    void
    init(const QString&url,const DirEntry&src);
    void
    init(const QString&url,const InfoEntry&src);

    QString m_Path;
    bool m_isVersioned;
    bool m_hasReal;
    LockEntry m_Lock;
    Entry m_entry;

    svn_wc_status_kind _text_status,_prop_status,_repos_text_status,_repos_prop_status;
    bool _copied,_switched;
  };

  Status_private::Status_private()
    :m_Path(),m_isVersioned(false),m_hasReal(false)
  {
  }

  Status_private::~ Status_private()
  {
  }

  void Status_private::init (const QString&path, const svn_wc_status2_t * status)
  {
    m_Path = path;

    if (!status)
    {
      m_isVersioned = false;
      m_hasReal = false;
      m_entry=Entry();
      m_Lock = LockEntry();
    }
    else
    {
      m_isVersioned = status->text_status > svn_wc_status_unversioned||status->repos_text_status>svn_wc_status_unversioned;
      m_hasReal = m_isVersioned &&
                          status->text_status!=svn_wc_status_ignored;
      // now duplicate the contents
      if (status->entry)
      {
        m_entry = Entry(status->entry);
      } else {
        m_entry=Entry();
      }
      _text_status = status->text_status;
      _prop_status = status->prop_status;
      _copied = status->copied!=0;
      _switched = status->switched!=0;
      _repos_text_status = status->repos_text_status;
      _repos_prop_status = status->repos_prop_status;
      if (status->repos_lock) {
        m_Lock.init(status->repos_lock->creation_date,
                    status->repos_lock->expiration_date,
                    status->repos_lock->owner,
                    status->repos_lock->comment,
                    status->repos_lock->comment);
      } else {
        m_Lock=LockEntry();
      }
    }
  }

  void
  Status_private::init (const QString&path,const Status_private&src)
  {
    m_Path=path;
    m_Lock=src.m_Lock;
    m_entry=src.m_entry;
    m_isVersioned=src.m_isVersioned;
    m_hasReal=src.m_hasReal;
    _text_status=src._text_status;
    _prop_status=src._prop_status;
    _repos_text_status=src._repos_text_status;
    _repos_prop_status=src._repos_prop_status;
    _copied=src._copied;
    _switched=src._switched;
  }

  void Status_private::init(const QString&url,const DirEntry&src)
  {
    m_entry=Entry(url,src);
    m_Path=url;
    _text_status = svn_wc_status_normal;
    _prop_status = svn_wc_status_normal;
    m_Lock=src.lockEntry();
    _switched = false;
    _repos_text_status = svn_wc_status_normal;
    _repos_prop_status = svn_wc_status_normal;
    m_isVersioned=true;
    m_hasReal=true;
  }

  void Status_private::init(const QString&url,const InfoEntry&src)
  {
    m_entry=Entry(url,src);
    m_Path=url;
    m_Lock=src.lockEntry();
    _text_status = svn_wc_status_normal;
    _prop_status = svn_wc_status_normal;
    _repos_text_status = svn_wc_status_normal;
    _repos_prop_status = svn_wc_status_normal;
    m_isVersioned=true;
    m_hasReal=true;
  }

  Status::Status (const Status & src)
    : m_Data(new Status_private())
  {
    if( &src != this )
    {
        if (src.m_Data) {
             m_Data->init (src.m_Data->m_Path, *(src.m_Data));
        } else {
            m_Data->init(src.m_Data->m_Path,0);
        }
    }
  }

  Status::Status (const QString&path, svn_wc_status2_t * status)
    : m_Data(new Status_private())
  {
    m_Data->init(path, status);
  }

  Status::Status (const char*path, svn_wc_status2_t * status)
    : m_Data(new Status_private())
  {
    m_Data->init(QString::fromUtf8(path),status);
  }

  Status::Status(const QString&url,const DirEntry&src)
    : m_Data(new Status_private())
  {
    m_Data->init(url,src);
  }

  Status::Status(const QString&url,const InfoEntry&src)
    : m_Data(new Status_private())
  {
    m_Data->init(url,src);
  }

  Status::~Status ()
  {
    delete m_Data;
  }

  Status &
  Status::operator=(const Status & status)
  {
    if (this == &status)
      return *this;
    if (status.m_Data) {
        m_Data->init (status.m_Data->m_Path, *(status.m_Data));
    } else {
        m_Data->init(status.m_Data->m_Path,0);
    }
    return *this;
  }

  const LockEntry&
  Status::lockEntry () const
  {
      return m_Data->m_Lock;
  }
    const svn_wc_status_kind
    Status::reposPropStatus () const
    {
      return m_Data->_repos_prop_status;
    }
    const svn_wc_status_kind
    Status::reposTextStatus () const
    {
      return m_Data->_repos_text_status;
    }
    const bool
    Status::isSwitched () const
    {
      return m_Data->_switched != 0;
    }
    const bool
    Status::isCopied () const
    {
      return m_Data->_copied;
    }

    const bool
    Status::isLocked () const
    {
      return m_Data->m_Lock.Locked();
    }

    const bool
    Status::isRealVersioned()const
    {
      return m_Data->m_hasReal;
    }

    const bool
    Status::isVersioned () const
    {
      return m_Data->m_isVersioned;
    }

    const svn_wc_status_kind
    Status::propStatus () const
    {
      return m_Data->_prop_status;
    }

    const svn_wc_status_kind
    Status::textStatus () const
    {
      return m_Data->_text_status;
    }

    const Entry&
    Status::entry () const
    {
      return m_Data->m_entry;
    }

    const QString&
    Status::path () const
    {
      return m_Data->m_Path;
    }

    bool
    Status::validReposStatus()const
    {
        return reposTextStatus()!=svn_wc_status_none||reposPropStatus()!=svn_wc_status_none;
    }

    bool
    Status::validLocalStatus()const
    {
        return textStatus()!=svn_wc_status_none||propStatus()!=svn_wc_status_none;
    }
}
<|endoftext|>


<commit_before>#include<iterator>
#include<iostream>
#include<sstream>
namespace hmLib{
	template<class Elem = char, class Traits = std::char_traits<Elem> >
	class ocsv_iterator : public std::iterator<std::output_iterator_tag, void, void, void, void>{
	private:
		using my_type = icsv_iterator <Elem, Traits>;
		using my_ostream = std::basic_ostream< Elem, Traits >;
		using my_pos = my_ostream::pos_type;
		using my_string = std::basic_string < Elem, Traits >;
	private:
		my_ostream* pstream;
		my_pos Pos;
		Elem Sep;
		Elem End;
		bool IsLineHead;
	public:
		ocsv_iterator(my_ostream& s, const CharT* delimiter = ',') :out_ptr(&s), del(delimiter){}
		ocsv_iterator(const my_type& x) = default;
	public:
		my_string& operator*();
		my_string* operator->();
		my_type& operator++();
		my_type operator++(int){
			ocell_iterator ans(*this);
			operator++();
			return ans;
		}
		bool eol()const;
		void endl();
	};
	template<class Elem = char, class Traits = std::char_traits<Elem> >
	class icsv_iterator : public std::iterator<std::input_iterator_tag, void, void, void, void>{
	private:
		using my_type = icsv_iterator <Elem, Traits>;
		using my_istream = std::basic_istream< Elem, Traits > ;
		using my_pos = my_istream::pos_type;
		using my_string = std::basic_string < Elem, Traits > ;
	private:
		my_istream* pstream;
		my_pos Pos;
		Elem Sep;
		Elem End;
		my_string ReadStr;
		bool HasRead;
		bool IsLineHead;
	private:
		void read();
	public:
		icsv_iterator() :pstream(nullptr){}
		icsv_iterator(my_istream& in_, Elem Sep_ = ',', Elem End_ = '\n')
			: pstream(&in_)
			, Sep(Sep_)
			, End(End_){
		}
		icsv_iterator(const my_type& x) = default;
		const my_string& operator*(){
			read();
			return ReadStr;
		}
		const my_string* operator->(){
			read();
			return &ReadStr;
		}
		my_type& operator++();
		my_type operator++(int){
			icell_iterator ans(*this);
			operator++();
			return ans;
		}
		bool eol()const{ return IsLineHead; }
		template<typename T>
		T get()const{
			std::stringstream StrStream(operator*());
			T Ans;
			StrStream >> Ans;
			return Ans;
		}
		friend bool operator==(const my_type& my1, const my_type& my2){
			if(&my1 == &my2)return true;

			if(my1.pstream != my2.pstream) return false;

			return my1.Pos == my2.Pos;
		}
		friend bool operator!=(const my_type& my1, const my_type& my2){return !(my1 == my2);}
	};
	template<class Elem = char, class Traits = std::char_traits<Elem> >
	void advance_line(icsv_iterator<Elem,Traits>& itr, unsigned int num = 1);
}
<commit_msg>Add ocsv_iterator functions.<commit_after>#include<iterator>
#include<iostream>
#include<sstream>
namespace hmLib{
	template<class Elem = char, class Traits = std::char_traits<Elem> >
	class ocsv_iterator : public std::iterator < std::output_iterator_tag, void, void, void, void > {
	private:
		using my_type = ocsv_iterator < Elem, Traits > ;
		using my_ostream = std::basic_ostream < Elem, Traits > ;
		using my_string = std::basic_string < Elem, Traits > ;
	private:
		struct output_proxy{
		private:
			my_type& My;
		public:
			output_proxy(my_type& My_) :My(My_){}
			void operator=(const my_string& Str){
				if(My.IsCellHead && !My.IsLineHead){
					*(My.pstream) << My.Sep;
					My.IsCellHead = false;
				}

				*(My.pstream) << Str;
			}
			template<typename T>
			output_proxy& operator<<(T Val){
				if(My.IsCellHead && !My.IsLineHead){
					*(My.pstream) << My.Sep;
					My.IsCellHead = false;
				}

				*(My.pstream) << Str;
				return *this;
			}
		};
	private:
		my_ostream* pstream;
		Elem Sep;
		Elem End;
		bool IsCellHead;
		bool IsLineHead;
	public:
		ocsv_iterator()
			: pstream(nullptr){
		}
		ocsv_iterator(my_ostream& Stream_, Elem Sep_ = ',', Elem End_ = '\n')
			: pstream(&Stream_)
			, Sep(Sep_)
			, End(End_)
			, IsCellHead(false)
			, IsLineHead(true){
		}
		ocsv_iterator(const my_type& x) = default;
	public:
		operator bool()const{ return pstream; }
		output_proxy operator*(){ return output_proxy(*this); }
		my_type& operator++(){
			IsCellHead = true;
			IsLineHead = false;
			return *this;
		}
		my_type operator++(int){
			my_type ans(*this);
			operator++();
			return ans;
		}
		bool eol()const{ return IsLineHead; }
		void endl(){
			(*pstream) << End;
			IsLineHead = true;
		}
	};
	template<class Elem = char, class Traits = std::char_traits<Elem> >
	class icsv_iterator : public std::iterator < std::input_iterator_tag, void, void, void, void > {
	private:
		using my_type = icsv_iterator < Elem, Traits > ;
		using my_istream = std::basic_istream < Elem, Traits > ;
		using my_pos = my_istream::pos_type;
		using my_string = std::basic_string < Elem, Traits > ;
		using my_sstream = std::basic_stringstream < Elem, Traits > ;
	private:
		my_istream* pstream;
		Elem Sep;
		Elem End;
		my_pos Pos;
		my_sstream sstream;
		bool HasRead;
		bool IsLineHead;
	private:
		void skip();
		void read(){
			Elem c;
			sstream.str(my_string());
			sstream.clear();

			if(pstream->tellg() != Pos) pstream->seekg(Pos);

			while(true){
				c = pstream->get();
				++Pos;

				if(c == Sep){
					IsLineHead = false;
					break;
				}
				if(c == End){
					IsLineHead = true;
					break;
				}

				sstream << c;
			}

			HasRead = true;
		}
	private:
		struct input_proxy{
		private:
			my_type& My;
		public:
			input_proxy(my_type& My_) :My(My_){}
			friend void operator=(my_string& Str, input_proxy& Proxy_){
				Str = Proxy_.My.sstream.str();
			}
			template<typename T>
			input_proxy& operator>>(T& Val){
				Proxy_.My.sstream >> Val;
				return *this;
			}
		};
	public:
		icsv_iterator() :pstream(nullptr){}
		icsv_iterator(my_istream& Stream_, Elem Sep_ = ',', Elem End_ = '\n')
			: pstream(&in_)
			, Sep(Sep_)
			, End(End_)
			, Pos(in.tellg()){
		}
		icsv_iterator(const my_type& My_) = default;
		my_type& operator=(const my_type& My_) = default;
		input_proxy operator*(){return input_proxy(*this);}
		my_type& operator++(){
			read();
			return *this;
		}
		my_type operator++(int){
			icsv_iterator ans(*this);
			operator++();
			return ans;
		}
		bool eol()const{ return IsLineHead; }
		friend bool operator==(const my_type& my1, const my_type& my2){
			if(&my1 == &my2)return true;

			if(my1.pstream != my2.pstream) return false;

			return my1.Pos == my2.Pos;
		}
		friend bool operator!=(const my_type& my1, const my_type& my2){ return !(my1 == my2); }
	public:
		static my_type line_end(const my_type& My_){
			my_type ans = My_;

			my_type End = file_end();

			while(End){
				if(ans.pstream->get() == ans.End)break;
			}

			ans.Pos = ans.pstream->tellg();
		}
		static my_type file_end(const my_type& My_){
			my_type ans = My_;
			ans.pstream->seekg(0, std::ios_base::end);
			ans.Pos = ans.pstream->tellg();
		}
	};
	template<class Elem = char, class Traits = std::char_traits<Elem> >
	void file_end(const icsv_iterator<Elem, Traits>& itr){
		unsigned int no = 0;
		do{
			++itr;
			if(itr.eol())++no;
		} while(no < num);
	}
	template<class Elem = char, class Traits = std::char_traits<Elem> >
	void advance_line(icsv_iterator<Elem, Traits>& itr, unsigned int num = 1){
		unsigned int no = 0;
		do{
			++itr;
			if(itr.eol())++no;
		} while(no < num);
	}
}
<|endoftext|>


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

#include <iostream>

#include "ros/include/ros/ros.h"
#include "std_msgs/String.h"

#include "modules/canbus/proto/chassis.pb.h"
#include "modules/control/proto/pad_msg.pb.h"

#include "modules/common/adapters/adapter_manager.h"
#include "modules/common/log.h"
#include "modules/common/time/time.h"
#include "modules/control/common/control_gflags.h"

namespace {

using ::apollo::common::adapter::AdapterManager;
using ::apollo::common::time::Clock;

const int ROS_QUEUE_SIZE = 1;
const int RESET_COMMAND = 1;
const int AUTO_DRIVE_COMMAND = 2;

const int EMERGENCY_MODE_HOLD_TIME = 4 * 1000000;

ros::Publisher g_pad_msg_pub;

void help() {
  AINFO << "COMMAND:\n";
  AINFO << "\t0: reset to manual drive mode.";
  AINFO << "\t1: auto drive mode.";
  AINFO << "\tctrl + c: exit.";
  AINFO << "\tother: print help.";
}

void send(int cmd_type) {
  ::apollo::control::PadMessage pb;
  if (cmd_type == RESET_COMMAND) {
    pb.set_action(apollo::control::DrivingAction::RESET);
    AINFO << "sending reset action command.";
  } else if (cmd_type == AUTO_DRIVE_COMMAND) {
    pb.set_action(apollo::control::DrivingAction::START);
    AINFO << "sending start action command.";
  }
  AdapterManager::FillPadHeader("terminal", pb.mutable_header());
  AdapterManager::PublishPad(pb);
  AINFO << "send pad_message OK";
}

void on_chassis(const apollo::canbus::Chassis& chassis) {
  static bool is_first_emergency_mode = true;
  static int64_t count_start = 0;
  static bool waiting_reset = false;

  // check if chassis enter security mode, if enter, after 10s should reset to
  // manual
  if (chassis.driving_mode() == apollo::canbus::Chassis::EMERGENCY_MODE) {
    if (is_first_emergency_mode == true) {
      count_start = apollo::common::time::AsInt64<std::chrono::microseconds>(
          Clock::Now());
      is_first_emergency_mode = false;
      AINFO << "detect emergency mode.";
    } else {
      int64_t diff = apollo::common::time::AsInt64<std::chrono::microseconds>(
                         Clock::Now()) -
                     count_start;
      if (diff > EMERGENCY_MODE_HOLD_TIME) {
        count_start = apollo::common::time::AsInt64<std::chrono::microseconds>(
            Clock::Now());
        waiting_reset = true;
        // send a reset command to control
        send(RESET_COMMAND);
        AINFO << "trigger to reset emergency mode to manual mode.";
      } else {
        // nothing to do
      }
    }
  } else if (chassis.driving_mode() ==
             apollo::canbus::Chassis::COMPLETE_MANUAL) {
    if (waiting_reset) {
      is_first_emergency_mode = true;
      waiting_reset = false;
      AINFO << "emergency mode reset to manual ok.";
    }
  }
}

void* terminal_thread(void* arg) {
  int mode = 0;
  bool should_exit = false;
  while (std::cin >> mode) {
    switch (mode) {
      case 0:
        send(RESET_COMMAND);
        break;
      case 1:
        send(AUTO_DRIVE_COMMAND);
        break;
      case 9:
        should_exit = true;
        break;
      default:
        help();
        break;
    }
    if (should_exit) {
      break;
    }
  }
  return NULL;
}

}  // end of namespace

int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);
  FLAGS_alsologtostderr = true;
  FLAGS_v = 3;

  google::ParseCommandLineFlags(&argc, &argv, true);

  ros::init(argc, argv, "terminal");

  apollo::common::adapter::AdapterManagerConfig config;
  config.set_is_ros(true);
  {
    auto* sub_config = config.add_config();
    sub_config->set_mode(apollo::common::adapter::AdapterConfig::PUBLISH_ONLY);
    sub_config->set_type(apollo::common::adapter::AdapterConfig::PAD);
  }

  {
    auto* sub_config = config.add_config();
    sub_config->set_mode(apollo::common::adapter::AdapterConfig::RECEIVE_ONLY);
    sub_config->set_type(apollo::common::adapter::AdapterConfig::CHASSIS);
  }

  {
    auto* sub_config = config.add_config();
    sub_config->set_mode(apollo::common::adapter::AdapterConfig::RECEIVE_ONLY);
    sub_config->set_type(apollo::common::adapter::AdapterConfig::LOCALIZATION);
  }

  AdapterManager::Init(config);
  AdapterManager::SetChassisCallback(on_chassis);

  help();
  pthread_t pid;
  if (pthread_create(&pid, NULL, terminal_thread, NULL) != 0) {
    AINFO << "create terminal thread failed.";
    exit(0);
  }
  ros::spin();
  return 0;
}
<commit_msg>Use std::thread instead of pthread.<commit_after>/******************************************************************************
 * Copyright 2017 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

#include <iostream>
#include <thread>

#include "ros/include/ros/ros.h"
#include "std_msgs/String.h"

#include "modules/canbus/proto/chassis.pb.h"
#include "modules/control/proto/pad_msg.pb.h"

#include "modules/common/adapters/adapter_manager.h"
#include "modules/common/log.h"
#include "modules/common/time/time.h"
#include "modules/control/common/control_gflags.h"

namespace {

using ::apollo::common::adapter::AdapterManager;
using ::apollo::common::time::Clock;

const int ROS_QUEUE_SIZE = 1;
const int RESET_COMMAND = 1;
const int AUTO_DRIVE_COMMAND = 2;

const int EMERGENCY_MODE_HOLD_TIME = 4 * 1000000;

ros::Publisher g_pad_msg_pub;

void help() {
  AINFO << "COMMAND:\n";
  AINFO << "\t0: reset to manual drive mode.";
  AINFO << "\t1: auto drive mode.";
  AINFO << "\tctrl + c: exit.";
  AINFO << "\tother: print help.";
}

void send(int cmd_type) {
  ::apollo::control::PadMessage pb;
  if (cmd_type == RESET_COMMAND) {
    pb.set_action(apollo::control::DrivingAction::RESET);
    AINFO << "sending reset action command.";
  } else if (cmd_type == AUTO_DRIVE_COMMAND) {
    pb.set_action(apollo::control::DrivingAction::START);
    AINFO << "sending start action command.";
  }
  AdapterManager::FillPadHeader("terminal", pb.mutable_header());
  AdapterManager::PublishPad(pb);
  AINFO << "send pad_message OK";
}

void on_chassis(const apollo::canbus::Chassis& chassis) {
  static bool is_first_emergency_mode = true;
  static int64_t count_start = 0;
  static bool waiting_reset = false;

  // check if chassis enter security mode, if enter, after 10s should reset to
  // manual
  if (chassis.driving_mode() == apollo::canbus::Chassis::EMERGENCY_MODE) {
    if (is_first_emergency_mode == true) {
      count_start = apollo::common::time::AsInt64<std::chrono::microseconds>(
          Clock::Now());
      is_first_emergency_mode = false;
      AINFO << "detect emergency mode.";
    } else {
      int64_t diff = apollo::common::time::AsInt64<std::chrono::microseconds>(
                         Clock::Now()) -
                     count_start;
      if (diff > EMERGENCY_MODE_HOLD_TIME) {
        count_start = apollo::common::time::AsInt64<std::chrono::microseconds>(
            Clock::Now());
        waiting_reset = true;
        // send a reset command to control
        send(RESET_COMMAND);
        AINFO << "trigger to reset emergency mode to manual mode.";
      } else {
        // nothing to do
      }
    }
  } else if (chassis.driving_mode() ==
             apollo::canbus::Chassis::COMPLETE_MANUAL) {
    if (waiting_reset) {
      is_first_emergency_mode = true;
      waiting_reset = false;
      AINFO << "emergency mode reset to manual ok.";
    }
  }
}

void terminal_thread_func() {
  int mode = 0;
  bool should_exit = false;
  while (std::cin >> mode) {
    switch (mode) {
      case 0:
        send(RESET_COMMAND);
        break;
      case 1:
        send(AUTO_DRIVE_COMMAND);
        break;
      case 9:
        should_exit = true;
        break;
      default:
        help();
        break;
    }
    if (should_exit) {
      break;
    }
  }
}

}  // end of namespace

int main(int argc, char** argv) {
  google::InitGoogleLogging(argv[0]);
  FLAGS_alsologtostderr = true;
  FLAGS_v = 3;

  google::ParseCommandLineFlags(&argc, &argv, true);

  ros::init(argc, argv, "terminal");

  apollo::common::adapter::AdapterManagerConfig config;
  config.set_is_ros(true);
  {
    auto* sub_config = config.add_config();
    sub_config->set_mode(apollo::common::adapter::AdapterConfig::PUBLISH_ONLY);
    sub_config->set_type(apollo::common::adapter::AdapterConfig::PAD);
  }

  {
    auto* sub_config = config.add_config();
    sub_config->set_mode(apollo::common::adapter::AdapterConfig::RECEIVE_ONLY);
    sub_config->set_type(apollo::common::adapter::AdapterConfig::CHASSIS);
  }

  {
    auto* sub_config = config.add_config();
    sub_config->set_mode(apollo::common::adapter::AdapterConfig::RECEIVE_ONLY);
    sub_config->set_type(apollo::common::adapter::AdapterConfig::LOCALIZATION);
  }

  AdapterManager::Init(config);
  AdapterManager::SetChassisCallback(on_chassis);

  help();
  std::thread terminal_thread(terminal_thread_func);
  ros::spin();
  terminal_thread.join();
  return 0;
}
<|endoftext|>


<commit_before>// 7.exercise.11.ch05.05.cpp
//
//  Revisit two programs you wrote for the exercises in Chapter 4 or 5. Clean
//  up that code according to the rules outlined in this chapter. See if you
//  find any bugs in the process.
//
// ORIGINAL STATEMENT
//
//  5.exercise.05.cpp
//
//   Add to the program so that it can also convert from Kelvin to Celsius.
//
// COMMENTS
//
//  In summary the chapter tell us to:
//
//      - Review pregram presentation to the user.
//      - Do testing trying to break the program and solve bugs found.
//      - Clean up the code:
//          - get rid of symbolic constants
//          - divide the code into functions that do just one single logical
//          action
//          - review code layout to improve code reading
//      - Evaluate if we can recover from errors
//      - Evaluate and implement improvements to the program

#include "std_lib_facilities.h"

class Below_abszero{};
class Bad_input{};

double ctok(double c)
{
    if (c < -273.15) throw Below_abszero();
    return c + 273.15;
}

double ktoc(double k)
{
    if (k < 0) throw Below_abszero();
    return k - 273.15;
}

int main()
try
{
    double deg = 0;
    char unit = ' ';

    cout << "Insert a temperature in Celsius or Kelvin to convert.\n"
         << "(Magnitude and unit separated by an space; e.g. 30 C or 300 K)\n"
         << ": ";

    cin >> deg >> unit;
    if (cin) {
        switch (unit) {
            case 'C':
                cout << ctok(deg) << "K\n";
                break;
            case 'K':
                cout << ktoc(deg) << " ºC\n";
                break;
            default:
                throw runtime_error("Given temperature unit isn't a known one.");
        }
    } else {
        throw Bad_input();
    }

    return 0;
}
// Exception style a bit mixed, I know. Just testing with those provided
// by C++ and the personalized ones in the same program.
catch (Bad_input)
{
    cerr << "Bad input, sorry!\n";
    return 1;
}
catch (runtime_error& e)
{
    cerr << e.what() << '\n';
    return 2;
}
catch (Below_abszero)
{
    cerr << "You tried to trick me with a temperature below absolute zero ...\n"
        << "Please, don't do that to me.\n";
    return 3;
}
<commit_msg>First steps on second part of exercise 11 from chapter 7.<commit_after>// 7.exercise.11.ch05.05.cpp
//
//  Revisit two programs you wrote for the exercises in Chapter 4 or 5. Clean
//  up that code according to the rules outlined in this chapter. See if you
//  find any bugs in the process.
//
// ORIGINAL STATEMENT
//
//  5.exercise.05.cpp
//
//   Add to the program so that it can also convert from Kelvin to Celsius.
//
// STATEMENT
//
//  This program converts a temperature from Kelvin to Celsius and vice versa.
//
// COMMENTS
//
//  In summary the chapter tell us to:
//
//      1. Review program presentation to the user.
//      2. Do testing trying to break the program and solve bugs found.
//      3. Clean up the code:
//          a) get rid of symbolic constants
//          b) divide the code into functions that do just one single logical
//          action
//          c) review code layout to improve code reading
//      4. Evaluate if we can recover from errors
//      5. Evaluate and implement improvements to the program
//
// 3.c
//  I include the statement of the exercise, but since it's an improvement
//  of a previous one, information about the objective is missing. So we
//  include STATEMENT.

#include "std_lib_facilities.h"

class Below_abszero{};
class Bad_input{};

double ctok(double c)
{
    if (c < -273.15) throw Below_abszero();
    return c + 273.15;
}

double ktoc(double k)
{
    if (k < 0) throw Below_abszero();
    return k - 273.15;
}

int main()
try
{
    double deg = 0;
    char unit = ' ';

    cout << "Insert a temperature in Celsius or Kelvin to convert.\n"
         << "(Magnitude and unit separated by an space; e.g. 30 C or 300 K)\n"
         << ": ";

    cin >> deg >> unit;
    if (cin) {
        switch (unit) {
            case 'C':
                cout << ctok(deg) << "K\n";
                break;
            case 'K':
                cout << ktoc(deg) << " ºC\n";
                break;
            default:
                throw runtime_error("Given temperature unit isn't a known one.");
        }
    } else {
        throw Bad_input();
    }

    return 0;
}
// Exception style a bit mixed, I know. Just testing with those provided
// by C++ and the personalized ones in the same program.
catch (Bad_input)
{
    cerr << "Bad input, sorry!\n";
    return 1;
}
catch (runtime_error& e)
{
    cerr << e.what() << '\n';
    return 2;
}
catch (Below_abszero)
{
    cerr << "You tried to trick me with a temperature below absolute zero ...\n"
        << "Please, don't do that to me.\n";
    return 3;
}
<|endoftext|>


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

// verilog_format is a command-line utility to format verilog source code
// for a given file.
//
// Example usage:
// verilog_format original-file > new-file
//
// Exit code:
//   0: stdout output can be used to replace original file
//   nonzero: stdout output (if any) should be discarded

#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>  // IWYU pragma: keep  // for ostringstream
#include <string>   // for string, allocator, etc
#include <vector>

#include "absl/flags/flag.h"
#include "absl/flags/usage.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "common/formatting/align.h"
#include "common/strings/position.h"
#include "common/util/file_util.h"
#include "common/util/init_command_line.h"
#include "common/util/interval_set.h"
#include "common/util/logging.h"  // for operator<<, LOG, LogMessage, etc
#include "verilog/formatting/format_style.h"
#include "verilog/formatting/formatter.h"

using absl::StatusCode;
using verible::AlignmentPolicy;
using verible::IndentationStyle;
using verible::LineNumberSet;
using verilog::formatter::ExecutionControl;
using verilog::formatter::FormatStyle;
using verilog::formatter::FormatVerilog;

// Pseudo-singleton, so that repeated flag occurrences accumulate values.
//   --flag x --flag y yields [x, y]
struct LineRanges {
  // need to copy string, cannot just use string_view
  typedef std::vector<std::string> storage_type;
  static storage_type values;
};

LineRanges::storage_type LineRanges::values;  // global initializer

bool AbslParseFlag(absl::string_view flag_arg, LineRanges* /* unused */,
                   std::string* error) {
  auto& values = LineRanges::values;
  // Pre-split strings, so that "--flag v1,v2" and "--flag v1 --flag v2" are
  // equivalent.
  const std::vector<absl::string_view> tokens = absl::StrSplit(flag_arg, ',');
  values.reserve(values.size() + tokens.size());
  for (const auto& token : tokens) {
    // need to copy string, cannot just use string_view
    values.push_back(std::string(token.begin(), token.end()));
  }
  // Range validation done later.
  return true;
}

std::string AbslUnparseFlag(LineRanges /* unused */) {
  const auto& values = LineRanges::values;
  return absl::StrJoin(values.begin(), values.end(), ",",
                       absl::StreamFormatter());
}

// TODO(fangism): Provide -i alias, as it is canonical to many formatters
ABSL_FLAG(bool, inplace, false,
          "If true, overwrite the input file on successful conditions.");
ABSL_FLAG(std::string, stdin_name, "<stdin>",
          "When using '-' to read from stdin, this gives an alternate name for "
          "diagnostic purposes.  Otherwise this is ignored.");
ABSL_FLAG(LineRanges, lines, {},
          "Specific lines to format, 1-based, comma-separated, inclusive N-M "
          "ranges, N is short for N-N.  By default, left unspecified, "
          "all lines are enabled for formatting.  (repeatable, cumulative)");
ABSL_FLAG(bool, failsafe_success, true,
          "If true, always exit with 0 status, even if there were input errors "
          "or internal errors.  In all error conditions, the original text is "
          "always preserved.  This is useful in deploying services where "
          "fail-safe behaviors should be considered a success.");
ABSL_FLAG(bool, verify_convergence, true,
          "If true, and not incrementally formatting with --lines, "
          "verify that re-formatting the formatted output yields "
          "no further changes, i.e. formatting is convergent.");

ABSL_FLAG(int, show_largest_token_partitions, 0,
          "If > 0, print token partitioning and then "
          "exit without formatting output.");
ABSL_FLAG(bool, show_token_partition_tree, false,
          "If true, print diagnostics after token partitioning and then "
          "exit without formatting output.");
ABSL_FLAG(bool, show_inter_token_info, false,
          "If true, along with show_token_partition_tree, include inter-token "
          "information such as spacing and break penalties.");
ABSL_FLAG(bool, show_equally_optimal_wrappings, false,
          "If true, print when multiple optimal solutions are found (stderr), "
          "but continue to operate normally.");
ABSL_FLAG(int, max_search_states, 100000,
          "Limits the number of search states explored during "
          "line wrap optimization.");

// These flags exist in the short term to disable formatting of some regions.
// Do not expect to be able to use these in the long term, once they find
// a better home in a configuration struct.

// "indent" means 2 spaces, "wrap" means 4 spaces.
ABSL_FLAG(IndentationStyle, port_declarations_indentation,
          IndentationStyle::kWrap, "Indent port declarations: {indent,wrap}");
ABSL_FLAG(IndentationStyle, formal_parameters_indentation,
          IndentationStyle::kWrap, "Indent formal parameters: {indent,wrap}");
ABSL_FLAG(IndentationStyle, named_parameter_indentation,
          IndentationStyle::kWrap,
          "Indent named parameter assignments: {indent,wrap}");
ABSL_FLAG(IndentationStyle, named_port_indentation, IndentationStyle::kWrap,
          "Indent named port connections: {indent,wrap}");

// For most of the following in this group, kInferUserIntent is a reasonable
// default behavior because it allows for user-control with minimal invasiveness
// and burden on the user.
ABSL_FLAG(AlignmentPolicy, port_declarations_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format port declarations: {align,flush-left,preserve,infer}");
ABSL_FLAG(AlignmentPolicy, named_parameter_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format named actual parameters: {align,flush-left,preserve,infer}");
ABSL_FLAG(AlignmentPolicy, named_port_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format named port connections: {align,flush-left,preserve,infer}");
ABSL_FLAG(
    AlignmentPolicy, net_variable_alignment,  //
    AlignmentPolicy::kInferUserIntent,
    "Format net/variable declarations: {align,flush-left,preserve,infer}");
ABSL_FLAG(AlignmentPolicy, formal_parameters_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format formal parameters: {align,flush-left,preserve,infer}");
ABSL_FLAG(AlignmentPolicy, class_member_variables_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format class member variables: {align,flush-left,preserve,infer}");
ABSL_FLAG(AlignmentPolicy, case_items_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format case items: {align,flush-left,preserve,infer}");
ABSL_FLAG(AlignmentPolicy, assignment_statement_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format various assignments: {align,flush-left,preserve,infer}");

ABSL_FLAG(bool, try_wrap_long_lines, false,
          "If true, let the formatter attempt to optimize line wrapping "
          "decisions where wrapping is needed, else leave them unformatted.  "
          "This is a short-term measure to reduce risk-of-harm.");

static std::ostream& FileMsg(absl::string_view filename) {
  std::cerr << filename << ": ";
  return std::cerr;
}

static bool formatOneFile(absl::string_view filename,
                          const LineNumberSet& lines_to_format) {
  const bool inplace = absl::GetFlag(FLAGS_inplace);
  const bool is_stdin = filename == "-";
  const auto& stdin_name = absl::GetFlag(FLAGS_stdin_name);

  if (inplace && is_stdin) {
    FileMsg(filename)
        << "--inplace is incompatible with stdin.  Ignoring --inplace "
        << "and writing to stdout." << std::endl;
  }

  const auto diagnostic_filename = is_stdin ? stdin_name : filename;

  // Read contents into memory first.
  std::string content;
  absl::Status status = verible::file::GetContents(filename, &content);
  if (!status.ok()) {
    FileMsg(filename) << status << std::endl;
    return false;
  }

  // TODO(fangism): When requesting --inplace, verify that file
  // is write-able, and fail-early if it is not.

  // TODO(fangism): support style configuration from flags.
  FormatStyle format_style;

  // Handle special debugging modes.
  ExecutionControl formatter_control;
  {
    // execution control flags
    formatter_control.stream = &std::cout;  // for diagnostics only
    formatter_control.show_largest_token_partitions =
        absl::GetFlag(FLAGS_show_largest_token_partitions);
    formatter_control.show_token_partition_tree =
        absl::GetFlag(FLAGS_show_token_partition_tree);
    formatter_control.show_inter_token_info =
        absl::GetFlag(FLAGS_show_inter_token_info);
    formatter_control.show_equally_optimal_wrappings =
        absl::GetFlag(FLAGS_show_equally_optimal_wrappings);
    formatter_control.max_search_states =
        absl::GetFlag(FLAGS_max_search_states);
    formatter_control.verify_convergence =
        absl::GetFlag(FLAGS_verify_convergence);

    // formatting style flags
    format_style.try_wrap_long_lines = absl::GetFlag(FLAGS_try_wrap_long_lines);

    // various indentation control
    format_style.port_declarations_indentation =
        absl::GetFlag(FLAGS_port_declarations_indentation);
    format_style.formal_parameters_indentation =
        absl::GetFlag(FLAGS_formal_parameters_indentation);
    format_style.named_parameter_indentation =
        absl::GetFlag(FLAGS_named_parameter_indentation);
    format_style.named_port_indentation =
        absl::GetFlag(FLAGS_named_port_indentation);

    // various alignment control
    format_style.port_declarations_alignment =
        absl::GetFlag(FLAGS_port_declarations_alignment);
    format_style.named_parameter_alignment =
        absl::GetFlag(FLAGS_named_parameter_alignment);
    format_style.named_port_alignment =
        absl::GetFlag(FLAGS_named_port_alignment);
    format_style.module_net_variable_alignment =
        absl::GetFlag(FLAGS_net_variable_alignment);
    format_style.formal_parameters_alignment =
        absl::GetFlag(FLAGS_formal_parameters_alignment);
    format_style.class_member_variable_alignment =
        absl::GetFlag(FLAGS_class_member_variables_alignment);
    format_style.case_items_alignment =
        absl::GetFlag(FLAGS_case_items_alignment);
    format_style.assignment_statement_alignment =
        absl::GetFlag(FLAGS_assignment_statement_alignment);
  }

  std::ostringstream stream;
  const auto format_status =
      FormatVerilog(content, diagnostic_filename, format_style, stream,
                    lines_to_format, formatter_control);

  const std::string& formatted_output(stream.str());
  if (!format_status.ok()) {
    if (!inplace) {
      // Fall back to printing original content regardless of error condition.
      std::cout << content;
    }
    switch (format_status.code()) {
      case StatusCode::kCancelled:
      case StatusCode::kInvalidArgument:
        FileMsg(filename) << format_status.message() << std::endl;
        break;
      case StatusCode::kDataLoss:
        FileMsg(filename) << format_status.message()
                          << "; problematic formatter output is\n"
                          << formatted_output << "<<EOF>>" << std::endl;
        break;
      default:
        FileMsg(filename) << format_status.message() << "[other error status]"
                          << std::endl;
        break;
    }

    return absl::GetFlag(FLAGS_failsafe_success);
  }

  // Safe to write out result, having passed above verification.
  if (inplace && !is_stdin) {
    // Don't write if the output is exactly as the input, so that we don't mess
    // with tools that look for timestamp changes (such as make).
    if (content != formatted_output) {
      status = verible::file::SetContents(filename, formatted_output);
      if (!status.ok()) {
        FileMsg(filename) << "error writing result " << status << std::endl;
        return false;
      }
    } else {
      FileMsg(filename) << "Already formatted, no change." << std::endl;
    }
  } else {
    std::cout << formatted_output;
  }

  return true;
}

int main(int argc, char** argv) {
  const auto usage = absl::StrCat("usage: ", argv[0],
                                  " [options] <file> [<file...>]\n"
                                  "To pipe from stdin, use '-' as <file>.");
  const auto file_args = verible::InitCommandLine(usage, &argc, &argv);

  if (file_args.size() == 1) {
    std::cerr << absl::ProgramUsageMessage() << std::endl;
    // TODO(hzeller): how can we append the output of --help here ?
    return 1;
  }

  // Parse LineRanges into a line set, to validate the --lines flag(s)
  LineNumberSet lines_to_format;
  if (!verible::ParseInclusiveRanges(
          &lines_to_format, LineRanges::values.begin(),
          LineRanges::values.end(), &std::cerr, '-')) {
    std::cerr << "Error parsing --lines." << std::endl;
    std::cerr << "Got: --lines=" << AbslUnparseFlag(LineRanges()) << std::endl;
    return 1;
  }

  // Some sanity checks if multiple files are given.
  if (file_args.size() > 2) {
    if (!lines_to_format.empty()) {
      std::cerr << "--lines only works for single files." << std::endl;
      return 1;
    }

    if (!absl::GetFlag(FLAGS_inplace)) {
      // Dumping all to stdout doesn't really make sense.
      std::cerr << "--inplace required for multiple files." << std::endl;
      return 1;
    }
  }

  bool all_success = true;
  // All positional arguments are file names.  Exclude program name.
  for (const absl::string_view filename :
       verible::make_range(file_args.begin() + 1, file_args.end())) {
    all_success &= formatOneFile(filename, lines_to_format);
  }

  return all_success ? 0 : 1;
}
<commit_msg>Don't violate the 'no news are good news' principle.<commit_after>// Copyright 2017-2020 The Verible Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// verilog_format is a command-line utility to format verilog source code
// for a given file.
//
// Example usage:
// verilog_format original-file > new-file
//
// Exit code:
//   0: stdout output can be used to replace original file
//   nonzero: stdout output (if any) should be discarded

#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>  // IWYU pragma: keep  // for ostringstream
#include <string>   // for string, allocator, etc
#include <vector>

#include "absl/flags/flag.h"
#include "absl/flags/usage.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "common/formatting/align.h"
#include "common/strings/position.h"
#include "common/util/file_util.h"
#include "common/util/init_command_line.h"
#include "common/util/interval_set.h"
#include "common/util/logging.h"  // for operator<<, LOG, LogMessage, etc
#include "verilog/formatting/format_style.h"
#include "verilog/formatting/formatter.h"

using absl::StatusCode;
using verible::AlignmentPolicy;
using verible::IndentationStyle;
using verible::LineNumberSet;
using verilog::formatter::ExecutionControl;
using verilog::formatter::FormatStyle;
using verilog::formatter::FormatVerilog;

// Pseudo-singleton, so that repeated flag occurrences accumulate values.
//   --flag x --flag y yields [x, y]
struct LineRanges {
  // need to copy string, cannot just use string_view
  typedef std::vector<std::string> storage_type;
  static storage_type values;
};

LineRanges::storage_type LineRanges::values;  // global initializer

bool AbslParseFlag(absl::string_view flag_arg, LineRanges* /* unused */,
                   std::string* error) {
  auto& values = LineRanges::values;
  // Pre-split strings, so that "--flag v1,v2" and "--flag v1 --flag v2" are
  // equivalent.
  const std::vector<absl::string_view> tokens = absl::StrSplit(flag_arg, ',');
  values.reserve(values.size() + tokens.size());
  for (const auto& token : tokens) {
    // need to copy string, cannot just use string_view
    values.push_back(std::string(token.begin(), token.end()));
  }
  // Range validation done later.
  return true;
}

std::string AbslUnparseFlag(LineRanges /* unused */) {
  const auto& values = LineRanges::values;
  return absl::StrJoin(values.begin(), values.end(), ",",
                       absl::StreamFormatter());
}

// TODO(fangism): Provide -i alias, as it is canonical to many formatters
ABSL_FLAG(bool, inplace, false,
          "If true, overwrite the input file on successful conditions.");
ABSL_FLAG(std::string, stdin_name, "<stdin>",
          "When using '-' to read from stdin, this gives an alternate name for "
          "diagnostic purposes.  Otherwise this is ignored.");
ABSL_FLAG(LineRanges, lines, {},
          "Specific lines to format, 1-based, comma-separated, inclusive N-M "
          "ranges, N is short for N-N.  By default, left unspecified, "
          "all lines are enabled for formatting.  (repeatable, cumulative)");
ABSL_FLAG(bool, failsafe_success, true,
          "If true, always exit with 0 status, even if there were input errors "
          "or internal errors.  In all error conditions, the original text is "
          "always preserved.  This is useful in deploying services where "
          "fail-safe behaviors should be considered a success.");
ABSL_FLAG(bool, verify_convergence, true,
          "If true, and not incrementally formatting with --lines, "
          "verify that re-formatting the formatted output yields "
          "no further changes, i.e. formatting is convergent.");

ABSL_FLAG(bool, verbose, false, "Be more verbose.");

ABSL_FLAG(int, show_largest_token_partitions, 0,
          "If > 0, print token partitioning and then "
          "exit without formatting output.");
ABSL_FLAG(bool, show_token_partition_tree, false,
          "If true, print diagnostics after token partitioning and then "
          "exit without formatting output.");
ABSL_FLAG(bool, show_inter_token_info, false,
          "If true, along with show_token_partition_tree, include inter-token "
          "information such as spacing and break penalties.");
ABSL_FLAG(bool, show_equally_optimal_wrappings, false,
          "If true, print when multiple optimal solutions are found (stderr), "
          "but continue to operate normally.");
ABSL_FLAG(int, max_search_states, 100000,
          "Limits the number of search states explored during "
          "line wrap optimization.");

// These flags exist in the short term to disable formatting of some regions.
// Do not expect to be able to use these in the long term, once they find
// a better home in a configuration struct.

// "indent" means 2 spaces, "wrap" means 4 spaces.
ABSL_FLAG(IndentationStyle, port_declarations_indentation,
          IndentationStyle::kWrap, "Indent port declarations: {indent,wrap}");
ABSL_FLAG(IndentationStyle, formal_parameters_indentation,
          IndentationStyle::kWrap, "Indent formal parameters: {indent,wrap}");
ABSL_FLAG(IndentationStyle, named_parameter_indentation,
          IndentationStyle::kWrap,
          "Indent named parameter assignments: {indent,wrap}");
ABSL_FLAG(IndentationStyle, named_port_indentation, IndentationStyle::kWrap,
          "Indent named port connections: {indent,wrap}");

// For most of the following in this group, kInferUserIntent is a reasonable
// default behavior because it allows for user-control with minimal invasiveness
// and burden on the user.
ABSL_FLAG(AlignmentPolicy, port_declarations_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format port declarations: {align,flush-left,preserve,infer}");
ABSL_FLAG(AlignmentPolicy, named_parameter_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format named actual parameters: {align,flush-left,preserve,infer}");
ABSL_FLAG(AlignmentPolicy, named_port_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format named port connections: {align,flush-left,preserve,infer}");
ABSL_FLAG(
    AlignmentPolicy, net_variable_alignment,  //
    AlignmentPolicy::kInferUserIntent,
    "Format net/variable declarations: {align,flush-left,preserve,infer}");
ABSL_FLAG(AlignmentPolicy, formal_parameters_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format formal parameters: {align,flush-left,preserve,infer}");
ABSL_FLAG(AlignmentPolicy, class_member_variables_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format class member variables: {align,flush-left,preserve,infer}");
ABSL_FLAG(AlignmentPolicy, case_items_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format case items: {align,flush-left,preserve,infer}");
ABSL_FLAG(AlignmentPolicy, assignment_statement_alignment,
          AlignmentPolicy::kInferUserIntent,
          "Format various assignments: {align,flush-left,preserve,infer}");

ABSL_FLAG(bool, try_wrap_long_lines, false,
          "If true, let the formatter attempt to optimize line wrapping "
          "decisions where wrapping is needed, else leave them unformatted.  "
          "This is a short-term measure to reduce risk-of-harm.");

static std::ostream& FileMsg(absl::string_view filename) {
  std::cerr << filename << ": ";
  return std::cerr;
}

static bool formatOneFile(absl::string_view filename,
                          const LineNumberSet& lines_to_format) {
  const bool inplace = absl::GetFlag(FLAGS_inplace);
  const bool is_stdin = filename == "-";
  const auto& stdin_name = absl::GetFlag(FLAGS_stdin_name);

  if (inplace && is_stdin) {
    FileMsg(filename)
        << "--inplace is incompatible with stdin.  Ignoring --inplace "
        << "and writing to stdout." << std::endl;
  }

  const auto diagnostic_filename = is_stdin ? stdin_name : filename;

  // Read contents into memory first.
  std::string content;
  absl::Status status = verible::file::GetContents(filename, &content);
  if (!status.ok()) {
    FileMsg(filename) << status << std::endl;
    return false;
  }

  // TODO(fangism): When requesting --inplace, verify that file
  // is write-able, and fail-early if it is not.

  // TODO(fangism): support style configuration from flags.
  FormatStyle format_style;

  // Handle special debugging modes.
  ExecutionControl formatter_control;
  {
    // execution control flags
    formatter_control.stream = &std::cout;  // for diagnostics only
    formatter_control.show_largest_token_partitions =
        absl::GetFlag(FLAGS_show_largest_token_partitions);
    formatter_control.show_token_partition_tree =
        absl::GetFlag(FLAGS_show_token_partition_tree);
    formatter_control.show_inter_token_info =
        absl::GetFlag(FLAGS_show_inter_token_info);
    formatter_control.show_equally_optimal_wrappings =
        absl::GetFlag(FLAGS_show_equally_optimal_wrappings);
    formatter_control.max_search_states =
        absl::GetFlag(FLAGS_max_search_states);
    formatter_control.verify_convergence =
        absl::GetFlag(FLAGS_verify_convergence);

    // formatting style flags
    format_style.try_wrap_long_lines = absl::GetFlag(FLAGS_try_wrap_long_lines);

    // various indentation control
    format_style.port_declarations_indentation =
        absl::GetFlag(FLAGS_port_declarations_indentation);
    format_style.formal_parameters_indentation =
        absl::GetFlag(FLAGS_formal_parameters_indentation);
    format_style.named_parameter_indentation =
        absl::GetFlag(FLAGS_named_parameter_indentation);
    format_style.named_port_indentation =
        absl::GetFlag(FLAGS_named_port_indentation);

    // various alignment control
    format_style.port_declarations_alignment =
        absl::GetFlag(FLAGS_port_declarations_alignment);
    format_style.named_parameter_alignment =
        absl::GetFlag(FLAGS_named_parameter_alignment);
    format_style.named_port_alignment =
        absl::GetFlag(FLAGS_named_port_alignment);
    format_style.module_net_variable_alignment =
        absl::GetFlag(FLAGS_net_variable_alignment);
    format_style.formal_parameters_alignment =
        absl::GetFlag(FLAGS_formal_parameters_alignment);
    format_style.class_member_variable_alignment =
        absl::GetFlag(FLAGS_class_member_variables_alignment);
    format_style.case_items_alignment =
        absl::GetFlag(FLAGS_case_items_alignment);
    format_style.assignment_statement_alignment =
        absl::GetFlag(FLAGS_assignment_statement_alignment);
  }

  std::ostringstream stream;
  const auto format_status =
      FormatVerilog(content, diagnostic_filename, format_style, stream,
                    lines_to_format, formatter_control);

  const std::string& formatted_output(stream.str());
  if (!format_status.ok()) {
    if (!inplace) {
      // Fall back to printing original content regardless of error condition.
      std::cout << content;
    }
    switch (format_status.code()) {
      case StatusCode::kCancelled:
      case StatusCode::kInvalidArgument:
        FileMsg(filename) << format_status.message() << std::endl;
        break;
      case StatusCode::kDataLoss:
        FileMsg(filename) << format_status.message()
                          << "; problematic formatter output is\n"
                          << formatted_output << "<<EOF>>" << std::endl;
        break;
      default:
        FileMsg(filename) << format_status.message() << "[other error status]"
                          << std::endl;
        break;
    }

    return absl::GetFlag(FLAGS_failsafe_success);
  }

  // Safe to write out result, having passed above verification.
  if (inplace && !is_stdin) {
    // Don't write if the output is exactly as the input, so that we don't mess
    // with tools that look for timestamp changes (such as make).
    if (content != formatted_output) {
      status = verible::file::SetContents(filename, formatted_output);
      if (!status.ok()) {
        FileMsg(filename) << "error writing result " << status << std::endl;
        return false;
      }
    } else if (absl::GetFlag(FLAGS_verbose)) {
      FileMsg(filename) << "Already formatted, no change." << std::endl;
    }
  } else {
    std::cout << formatted_output;
  }

  return true;
}

int main(int argc, char** argv) {
  const auto usage = absl::StrCat("usage: ", argv[0],
                                  " [options] <file> [<file...>]\n"
                                  "To pipe from stdin, use '-' as <file>.");
  const auto file_args = verible::InitCommandLine(usage, &argc, &argv);

  if (file_args.size() == 1) {
    std::cerr << absl::ProgramUsageMessage() << std::endl;
    // TODO(hzeller): how can we append the output of --help here ?
    return 1;
  }

  // Parse LineRanges into a line set, to validate the --lines flag(s)
  LineNumberSet lines_to_format;
  if (!verible::ParseInclusiveRanges(
          &lines_to_format, LineRanges::values.begin(),
          LineRanges::values.end(), &std::cerr, '-')) {
    std::cerr << "Error parsing --lines." << std::endl;
    std::cerr << "Got: --lines=" << AbslUnparseFlag(LineRanges()) << std::endl;
    return 1;
  }

  // Some sanity checks if multiple files are given.
  if (file_args.size() > 2) {
    if (!lines_to_format.empty()) {
      std::cerr << "--lines only works for single files." << std::endl;
      return 1;
    }

    if (!absl::GetFlag(FLAGS_inplace)) {
      // Dumping all to stdout doesn't really make sense.
      std::cerr << "--inplace required for multiple files." << std::endl;
      return 1;
    }
  }

  bool all_success = true;
  // All positional arguments are file names.  Exclude program name.
  for (const absl::string_view filename :
       verible::make_range(file_args.begin() + 1, file_args.end())) {
    all_success &= formatOneFile(filename, lines_to_format);
  }

  return all_success ? 0 : 1;
}
<|endoftext|>