<commit_before>/*
 * CandidateHeap.cpp
 *
 *  Created on: Mar 27, 2016
 *      Author: michel
 */

#include "CandidateHeap.hpp"

CandidateHeap::CandidateHeap(std::string dir, int* activeIJs, int kPrime, TreeBuilderExtMem *tb, long sizeExp) : ArrayHeapExtMem(dir,activeIJs,sizeExp){
	initialize( kPrime, tb);
}

CandidateHeap::CandidateHeap(std::string dir, int* activeIJs, int kPrime, TreeBuilderExtMem *tb) : ArrayHeapExtMem(dir,activeIJs){
	initialize( kPrime, tb);
}
CandidateHeap::~CandidateHeap(){
	clear();
}

void CandidateHeap::initialize (int kPrime, TreeBuilderExtMem *tb) {

	this->firstActiveNode = -1;
	this->origSize = 0;
	this->expired = false;
	this->representedRowCount = 0;

	this->tb = tb;
	this->kPrime = kPrime;
	rowCounts = new int[tb->nextInternalNode+1]();
	rDeltas = new float[tb->nextInternalNode+1];
	nextActiveNode = new int[tb->nextInternalNode+1];
	prevActiveNode = new int[tb->nextInternalNode+1];

	rPrimes = new float[tb->RSize];
	for (int i=0; i< tb->RSize; i++ ) {
		rPrimes[i] = tb->R[i];
	}
}

void CandidateHeap::insert(int i, int j, float key){
	ArrayHeapExtMem::insert(i, j, key);

	rowCounts[i]++;
	rowCounts[j]++;
}

void CandidateHeap::buildNodeList () {
	origSize = ArrayHeapExtMem::size();

	int prev=-1;
	for (int i=0; i<tb->nextInternalNode+1; i++) {
		if (rowCounts[i] > 0) {
			representedRowCount++;
			if (firstActiveNode==-1) {
				firstActiveNode = i;
			} else {
				prevActiveNode[i] = prev;
				nextActiveNode[prev] = i;
			}
			prev = i;
		}
	}
	prevActiveNode[0] = -1;
	nextActiveNode[prev] = -1;
}

void CandidateHeap::removeMin(){
	HeapReturn x = ArrayHeapExtMem::getBinaryHeapWithMin();
	int i,j;
	if(x.which){
		BinaryHeap_FourInts* H = (BinaryHeap_FourInts*)x.h;
		i = H->heap->front().first;
		j = H->heap->front().second;
	}else{
		BinaryHeap_TwoInts* H = (BinaryHeap_TwoInts*)x.h;
		i = H->heap->front().first;
		j = H->heap->front().second;
	}

	int prev, next;
	if (--rowCounts[i] == 0) { // compact list
		representedRowCount--;
		prev = prevActiveNode[i];
		next = nextActiveNode[i];
		if (next != -1) prevActiveNode[next] = prev;
		if (prev != -1) nextActiveNode[prev] = next;
	}

	if (--rowCounts[j] == 0) { // compact list
		representedRowCount--;
		prev = prevActiveNode[j];
		next = nextActiveNode[j];
		if (next != -1) prevActiveNode[next] = prev;
		if (prev != -1) nextActiveNode[prev] = next;
	}

	ArrayHeapExtMem::removeMin();
}

void CandidateHeap::calcDeltaValues (int newK) {
	//prevActiveNode[0] = -1;
	//nextActiveNode[0] = -1;
	int x=firstActiveNode;

	float minRdelt1, minRdelt2;
	minRdelt1 = FLT_MAX;
	minRdelt2 = FLT_MAX;

	k_over_kprime = (float)(newK-2)/(kPrime-2);

	int rx, prev, next;
	while (x != -1) {
		rx = tb->redirect[x];

		if (rx == -1) {
			prev = prevActiveNode[x];
			next = nextActiveNode[x];
			if (next != -1) prevActiveNode[next] = prev;
			if (prev != -1) nextActiveNode[prev] = next;
			x = next;
		} else {
			rDeltas[x] = k_over_kprime * rPrimes[rx]  - tb->R[rx];

			if (rDeltas[x] < minRdelt1) {
				minRdelt2 = minRdelt1;
				minRdelt1 = rDeltas[x];
			} else if (rDeltas[x] < minRdelt2) {
				minRdelt2 = rDeltas[x];
			}

			x = nextActiveNode[x];
		}
	}
	minDeltaSum =  minRdelt1 + minRdelt2;

}
void CandidateHeap::clear(){

	//TODO: fix
	ArrayHeapExtMem::deleteAll();
	if (rPrimes!=NULL){
		delete[] rPrimes;
		rPrimes = NULL;
	}
	if (rDeltas!=NULL){
		delete[] rDeltas;
		rDeltas = NULL;
	}
	if (rowCounts!=NULL){
		delete[] rowCounts;
		rowCounts = NULL;
	}
	if (nextActiveNode!=NULL){
		delete[] nextActiveNode;
		nextActiveNode = NULL;
	}
	if (prevActiveNode!=NULL){
		delete[] prevActiveNode;
		prevActiveNode = NULL;
	}
	if (this->tb!=NULL){
		delete this->tb;
		tb = NULL;
	}
}
<commit_msg>fixed infinite recursion bug<commit_after>/*
 * CandidateHeap.cpp
 *
 *  Created on: Mar 27, 2016
 *      Author: michel
 */

#include "CandidateHeap.hpp"

CandidateHeap::CandidateHeap(std::string dir, int* activeIJs, int kPrime, TreeBuilderExtMem *tb, long sizeExp) : ArrayHeapExtMem(dir,activeIJs,sizeExp){
	initialize( kPrime, tb);
}

CandidateHeap::CandidateHeap(std::string dir, int* activeIJs, int kPrime, TreeBuilderExtMem *tb) : ArrayHeapExtMem(dir,activeIJs){
	initialize( kPrime, tb);
}
CandidateHeap::~CandidateHeap(){
	clear();
}

void CandidateHeap::initialize (int kPrime, TreeBuilderExtMem *tb) {

	this->firstActiveNode = -1;
	this->origSize = 0;
	this->expired = false;
	this->representedRowCount = 0;

	this->tb = tb;
	this->kPrime = kPrime;
	rowCounts = new int[tb->nextInternalNode+1]();
	rDeltas = new float[tb->nextInternalNode+1];
	nextActiveNode = new int[tb->nextInternalNode+1];
	prevActiveNode = new int[tb->nextInternalNode+1];

	rPrimes = new float[tb->RSize];
	for (int i=0; i< tb->RSize; i++ ) {
		rPrimes[i] = tb->R[i];
	}
}

void CandidateHeap::insert(int i, int j, float key){
	ArrayHeapExtMem::insert(i, j, key);

	rowCounts[i]++;
	rowCounts[j]++;
}

void CandidateHeap::buildNodeList () {
	origSize = ArrayHeapExtMem::size();

	int prev=-1;
	for (int i=0; i<tb->nextInternalNode+1; i++) {
		if (rowCounts[i] > 0) {
			representedRowCount++;
			if (firstActiveNode==-1) {
				firstActiveNode = i;
			} else {
				prevActiveNode[i] = prev;
				nextActiveNode[prev] = i;
			}
			prev = i;
		}
	}
	prevActiveNode[0] = -1;
	nextActiveNode[prev] = -1;
}

void CandidateHeap::removeMin(){
	HeapReturn x = ArrayHeapExtMem::getBinaryHeapWithMin();
	int i,j;
	if(x.which){
		BinaryHeap_FourInts* H = (BinaryHeap_FourInts*)x.h;
		i = H->heap->front().first;
		j = H->heap->front().second;
	}else{
		BinaryHeap_TwoInts* H = (BinaryHeap_TwoInts*)x.h;
		i = H->heap->front().first;
		j = H->heap->front().second;
	}

	int prev, next;
	if (--rowCounts[i] == 0) { // compact list
		representedRowCount--;
		prev = prevActiveNode[i];
		next = nextActiveNode[i];
		if (next != -1) prevActiveNode[next] = prev;
		if (prev != -1) nextActiveNode[prev] = next;
	}

	if (--rowCounts[j] == 0) { // compact list
		representedRowCount--;
		prev = prevActiveNode[j];
		next = nextActiveNode[j];
		if (next != -1) prevActiveNode[next] = prev;
		if (prev != -1) nextActiveNode[prev] = next;
	}

	ArrayHeapExtMem::removeMin();
}

void CandidateHeap::calcDeltaValues (int newK) {
	//prevActiveNode[0] = -1;
	//nextActiveNode[0] = -1;
	int x=firstActiveNode;

	float minRdelt1, minRdelt2;
	minRdelt1 = FLT_MAX;
	minRdelt2 = FLT_MAX;

	k_over_kprime = (float)(newK-2)/(kPrime-2);

	int rx, prev, next;
	while (x != -1) {
		rx = tb->redirect[x];

		if (rx == -1) {
			prev = prevActiveNode[x];
			next = nextActiveNode[x];
			if (next != -1) prevActiveNode[next] = prev;
			if (prev != -1) nextActiveNode[prev] = next;
			x = next;
		} else {
			rDeltas[x] = k_over_kprime * rPrimes[rx]  - tb->R[rx];

			if (rDeltas[x] < minRdelt1) {
				minRdelt2 = minRdelt1;
				minRdelt1 = rDeltas[x];
			} else if (rDeltas[x] < minRdelt2) {
				minRdelt2 = rDeltas[x];
			}

			x = nextActiveNode[x];
		}
	}
	minDeltaSum =  minRdelt1 + minRdelt2;

}
void CandidateHeap::clear(){

	//TODO: fix
	ArrayHeapExtMem::deleteAll();
	if (rPrimes!=NULL){
		delete[] rPrimes;
		rPrimes = NULL;
	}
	if (rDeltas!=NULL){
		delete[] rDeltas;
		rDeltas = NULL;
	}
	if (rowCounts!=NULL){
		delete[] rowCounts;
		rowCounts = NULL;
	}
	if (nextActiveNode!=NULL){
		delete[] nextActiveNode;
		nextActiveNode = NULL;
	}
	if (prevActiveNode!=NULL){
		delete[] prevActiveNode;
		prevActiveNode = NULL;
	}
	/*
	if (this->tb!=NULL){
		delete this->tb;
		tb = NULL;
	}*/
}
<|endoftext|>


<commit_before>/////
#include "Precompiled.h"
#include "GetOptInc.h"
#include "resource.h"
#include <Shellapi.h>
#include <Shlobj.h>
#include <Shlwapi.h>
#include <commctrl.h>
#if defined(_WIN32_WINNT_WIN8) && defined(_WIN32_WINNT) &&                     \
    _WIN32_WINNT >= _WIN32_WINNT_WIN8
#include <Processthreadsapi.h>
#endif
#include <strsafe.h>

#ifndef ASSERT
#ifdef _DEBUG
#include <assert.h>
#define ASSERT(x) assert(x)
#define ASSERT_HERE assert(FALSE)
#else // _DEBUG
#define ASSERT(x)
#endif //_DEBUG
#endif // ASSERT

#ifndef _tsizeof
#define _tsizeof(s) (sizeof(s) / sizeof(s[0]))
#endif //_tsizeof

#include <comdef.h>
#include <taskschd.h>

#define UNC_MAX_PATH (32 * 1024 - 1)

int OutErrorMessage(const wchar_t *errorMsg, const wchar_t *errorTitle);

void PrintVersion() {
  int nButtonPressed = 0;
  TaskDialog(NULL, GetModuleHandle(nullptr), L"Clangbuilder launcher",
             L"Version Info: ", LAUNCHER_APP_VERSION, TDCBF_OK_BUTTON,
             TD_INFORMATION_ICON, &nButtonPressed);
}

HRESULT CALLBACK TaskDialogCallbackProc(__in HWND hwnd, __in UINT msg,
                                        __in WPARAM wParam, __in LPARAM lParam,
                                        __in LONG_PTR lpRefData) {
  UNREFERENCED_PARAMETER(lpRefData);
  UNREFERENCED_PARAMETER(wParam);
  switch (msg) {
  case TDN_CREATED:
    ::SetForegroundWindow(hwnd);
    break;
  case TDN_RADIO_BUTTON_CLICKED:
    break;
  case TDN_BUTTON_CLICKED:
    break;
  case TDN_HYPERLINK_CLICKED:
    ShellExecute(hwnd, NULL, (LPCTSTR)lParam, NULL, NULL, SW_SHOWNORMAL);
    break;
  }
  return S_OK;
}

const wchar_t usageInfo[] =
    L"OVERVIEW: Clangbuilder launcher utility\n"
    L"\nOPTIONS:\n"
    L"Usage: launcher [options| V:A:F:BEICRSLNH ] <input>\n"
    L"  -V\t[--vs] Visual Studio version \n\tAllow:  110| 120| 140| 141| "
    L"150\n\n"
    L"  -A\t[--arch] LLVM Arch \n\tAllow: x86| x64| ARM| ARM64\n\n"
    L"  -F\t[--flavor] Flavor \n\tAllow: Debug| Release| MinSizeRel| "
    L"RelWithDebInfo\n\n"
    L"  -B\t[--bootstrap] Bootstrap llvm\n"
    L"  -E\t[--env] Startup Environment not run builder\n"
    L"  -I\t[--install] Create Install Package\n"
    L"  -C\t[--clear] Clear Environment\n"
    L"  -R\t[--released] Build Last Released Revision\n"
    L"  -S\t[--static] Use Static C Runtime Library\n"
    L"  -L\t[--lldb] Build LLDB\n"
    L"  -N\t[--nmake] nmake\n"
    L"  -H\t[--help] Print Help Message";

void Usage() {
  MessageBoxW(nullptr, usageInfo, L"Clangbuilder launcher Usage", MB_OK);
}

enum ClangBuilderChannel : int {
  kOpenEnvironment = 0, ///
  kUseMSBuild = 1,
  kNinjaBootstrap
};

int LauncherStartup(const wchar_t *args, int channel) {
  wchar_t pwszPath[UNC_MAX_PATH];
  GetModuleFileNameW(nullptr, pwszPath, UNC_MAX_PATH);
  PathRemoveFileSpecW(pwszPath);
  PathRemoveFileSpecW(pwszPath);
  PathRemoveFileSpecW(pwszPath);
  std::wstring psfile = pwszPath;
  switch (channel) {
  case kOpenEnvironment:
    psfile += L"\\bin\\ClangBuilderEnvironment.ps1";
    break;
  case kUseMSBuild:
    psfile += L"\\bin\\ClangBuilderManager.ps1";
    break;
  case kNinjaBootstrap:
    psfile += L"\\bin\\ClangBuilderBootstrap.ps1";
    break;
  default:
    psfile = L"Not support channel value: " + std::to_wstring(channel);
    OutErrorMessage(psfile.c_str(), L"Not support clangbuilder channel !");
    return -2;
  }
  if (!PathFileExistsW(psfile.c_str())) {
    OutErrorMessage(psfile.c_str(), L"PathFileExists return false");
    return -1;
  }

  if (SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pwszPath) != S_OK) {
    return -1;
  }
  auto length = wcslen(pwszPath);
  StringCchCatW(pwszPath, UNC_MAX_PATH - length,
                L"\\WindowsPowerShell\\v1.0\\powershell.exe ");
  length = wcslen(pwszPath);
  auto offsetPtr = pwszPath + length;
  StringCchPrintfW(offsetPtr, UNC_MAX_PATH - length,
                   L" -NoLogo -NoExit   -File \"%s\" %s", psfile.c_str(), args);
  PROCESS_INFORMATION pi;
  STARTUPINFO si;
  ZeroMemory(&si, sizeof(si));
  ZeroMemory(&pi, sizeof(pi));
  si.cb = sizeof(si);
  si.dwFlags = STARTF_USESHOWWINDOW;
  si.wShowWindow = SW_SHOW;
  if (CreateProcessW(nullptr, pwszPath, NULL, NULL, FALSE,
                     CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS, NULL, NULL,
                     &si, &pi)) {
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    return 0;
  }
  return GetLastError();
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPWSTR lpCmdLine, int nCmdShow) {
  UNREFERENCED_PARAMETER(hInstance);
  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpCmdLine);
  UNREFERENCED_PARAMETER(nCmdShow);
  const wchar_t *vs = nullptr;
  const wchar_t *target = nullptr;
  const wchar_t *flavor = nullptr;
  bool createInstallPkg = false;
  bool clearEnv = false;
  bool useNmake = false;
  bool buildReleasedRevision = false;
  bool useStaticCRT = false;
  bool buildLLDB = false;
  int channel = kUseMSBuild;
  int Argc = 0;
  auto Argv_ = CommandLineToArgvW(GetCommandLineW(), &Argc);
  wchar_t *const *Argv = Argv_;
  int ch;
  const wchar_t *short_opts = L"V:A:F:BEICRSLNH"; // L"V:T:C:BIERSLNH";
  const option option_long_opt[] = {
      ///
      {L"vs", required_argument, NULL, 'V'},
      {L"arch", required_argument, NULL, 'A'},
      {L"flavor", required_argument, NULL, 'F'},
      {L"bootstrap", no_argument, NULL, 'B'},
      {L"env", no_argument, NULL, 'E'},
      {L"install", no_argument, NULL, 'I'},
      {L"clear", no_argument, NULL, 'C'},
      {L"released", no_argument, NULL, 'R'},
      {L"static", no_argument, NULL, 'S'},
      {L"lldb", no_argument, NULL, 'L'},
      {L"nmake", no_argument, NULL, 'N'},
      {L"help", no_argument, NULL, 'H'},
      {0, 0, 0, 0}
      ///
  };
  while ((ch = getopt_long(Argc, Argv, short_opts, option_long_opt, NULL)) !=
         -1) {
    switch (ch) {
    case 'V':
      vs = optarg;
      break;
    case 'A':
      target = optarg;
      break;
    case 'F':
      flavor = optarg;
      break;
    case 'B':
      channel = kNinjaBootstrap;
      break;
    case 'E':
      channel = kOpenEnvironment;
      break;
    case 'I':
      createInstallPkg = true;
      break;
    case 'C':
      clearEnv = true;
      break;
    case 'R':
      buildReleasedRevision = true;
      break;
    case 'S':
      useStaticCRT = true;
      break;
    case 'L':
      buildLLDB = true;
      break;
    case 'N':
      useNmake = true;
      break;
    case 'H':
      Usage();
      LocalFree(Argv_);
      return 0;
    default:
      break;
    }
  }
  if (vs == nullptr || target == nullptr || flavor == nullptr) {
    Usage();
    return 0;
  }
  WCHAR szBuffer[UNC_MAX_PATH] = {0};
  StringCbPrintfW(szBuffer, UNC_MAX_PATH, L" -VisualStudio %s -Arch %s", vs,
                  target);
  if (channel != kOpenEnvironment) {
    StringCbCatW(szBuffer, UNC_MAX_PATH, L" -Flavor ");
    StringCbCatW(szBuffer, UNC_MAX_PATH, flavor);
    if (createInstallPkg) {
      StringCbCatW(szBuffer, UNC_MAX_PATH, L" -Install");
    }
    if (buildReleasedRevision) {
      StringCbCatW(szBuffer, UNC_MAX_PATH, L" -Released");
    }
    if (useStaticCRT) {
      StringCbCatW(szBuffer, UNC_MAX_PATH, L" -Static");
    }
    if (useNmake && channel == kUseMSBuild) {
      StringCbCatW(szBuffer, UNC_MAX_PATH, L" -NMake");
    }
    if (buildLLDB && channel == kUseMSBuild) {
      StringCbCatW(szBuffer, UNC_MAX_PATH, L" -LLDB");
    }
  }
  if (clearEnv) {
    StringCbCatW(szBuffer, UNC_MAX_PATH, L" -Clear");
  }
  auto result = LauncherStartup(szBuffer, channel);
  LocalFree(Argv_);
  return result;
}

int OutErrorMessage(const wchar_t *errorMsg, const wchar_t *errorTitle) {
  int nButton = 0;
  int nRadioButton = 0;
  TASKDIALOGCONFIG tdConfig;
  memset(&tdConfig, 0, sizeof(tdConfig));
  tdConfig.cbSize = sizeof(tdConfig);
  tdConfig.hwndParent = nullptr;
  tdConfig.hInstance = GetModuleHandle(nullptr);
  tdConfig.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION | TDF_EXPAND_FOOTER_AREA |
                     TDF_POSITION_RELATIVE_TO_WINDOW | TDF_SIZE_TO_CONTENT |
                     TDF_ENABLE_HYPERLINKS;
  tdConfig.nDefaultRadioButton = nRadioButton;
  tdConfig.pszWindowTitle = L"Clangbuilder launcher Error";
  tdConfig.pszMainInstruction = errorTitle;
  tdConfig.hMainIcon = static_cast<HICON>(
      LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_ICON_LAUNCHER)));
  tdConfig.dwFlags |= TDF_USE_HICON_MAIN;
  tdConfig.pszContent = errorMsg;
  tdConfig.pszExpandedInformation =
      _T("For more information about this tool, ")
      _T("Visit: Force ")
      _T("Charlie");
  tdConfig.pszCollapsedControlText = _T("More information");
  tdConfig.pszExpandedControlText = _T("Less information");
  tdConfig.pfCallback = TaskDialogCallbackProc;
  HRESULT hr = TaskDialogIndirect(&tdConfig, &nButton, &nRadioButton, NULL);
  return hr;
}
<commit_msg>Update launcher.cpp<commit_after>/////
#include "Precompiled.h"
#include "GetOptInc.h"
#include "resource.h"
#include <Shellapi.h>
#include <Shlobj.h>
#include <Shlwapi.h>
#include <commctrl.h>
#if defined(_WIN32_WINNT_WIN8) && defined(_WIN32_WINNT) &&                     \
    _WIN32_WINNT >= _WIN32_WINNT_WIN8
#include <Processthreadsapi.h>
#endif
#include <strsafe.h>

#ifndef ASSERT
#ifdef _DEBUG
#include <assert.h>
#define ASSERT(x) assert(x)
#define ASSERT_HERE assert(FALSE)
#else // _DEBUG
#define ASSERT(x)
#endif //_DEBUG
#endif // ASSERT

#ifndef _tsizeof
#define _tsizeof(s) (sizeof(s) / sizeof(s[0]))
#endif //_tsizeof

#include <comdef.h>
#include <taskschd.h>

#define UNC_MAX_PATH (32 * 1024 - 1)

int OutErrorMessage(const wchar_t *errorMsg, const wchar_t *errorTitle);

void PrintVersion() {
  int nButtonPressed = 0;
  TaskDialog(NULL, GetModuleHandle(nullptr), L"Clangbuilder launcher",
             L"Version Info: ", LAUNCHER_APP_VERSION, TDCBF_OK_BUTTON,
             TD_INFORMATION_ICON, &nButtonPressed);
}

HRESULT CALLBACK TaskDialogCallbackProc(__in HWND hwnd, __in UINT msg,
                                        __in WPARAM wParam, __in LPARAM lParam,
                                        __in LONG_PTR lpRefData) {
  UNREFERENCED_PARAMETER(lpRefData);
  UNREFERENCED_PARAMETER(wParam);
  switch (msg) {
  case TDN_CREATED:
    ::SetForegroundWindow(hwnd);
    break;
  case TDN_RADIO_BUTTON_CLICKED:
    break;
  case TDN_BUTTON_CLICKED:
    break;
  case TDN_HYPERLINK_CLICKED:
    ShellExecute(hwnd, NULL, (LPCTSTR)lParam, NULL, NULL, SW_SHOWNORMAL);
    break;
  }
  return S_OK;
}

const wchar_t usageInfo[] =
    L"OVERVIEW: Clangbuilder launcher utility\n"
    L"\nOPTIONS:\n"
    L"Usage: launcher [options| V:A:F:BEICRSLNH ] <input>\n"
    L"  -V\t[--vs] Visual Studio version \n\tAllow:  110| 120| 140| 141| "
    L"150\n\n"
    L"  -A\t[--arch] LLVM Arch \n\tAllow: x86| x64| ARM| ARM64\n\n"
    L"  -F\t[--flavor] Flavor \n\tAllow: Debug| Release| MinSizeRel| "
    L"RelWithDebInfo\n\n"
    L"  -B\t[--bootstrap] Bootstrap llvm\n"
    L"  -E\t[--env] Startup Environment not run builder\n"
    L"  -I\t[--install] Create Install Package\n"
    L"  -C\t[--clear] Clear Environment\n"
    L"  -R\t[--released] Build Last Released Revision\n"
    L"  -S\t[--static] Use Static C Runtime Library\n"
    L"  -L\t[--lldb] Build LLDB\n"
    L"  -N\t[--nmake] nmake\n"
    L"  -H\t[--help] Print Help Message";

void Usage() {
  MessageBoxW(nullptr, usageInfo, L"Clangbuilder launcher Usage", MB_OK);
}

enum ClangBuilderChannel : int {
  kOpenEnvironment = 0, ///
  kBaseBuilder = 1,
  kNinjaBootstrap
};

int LauncherStartup(const wchar_t *args, int channel) {
  wchar_t pwszPath[UNC_MAX_PATH];
  GetModuleFileNameW(nullptr, pwszPath, UNC_MAX_PATH);
  PathRemoveFileSpecW(pwszPath);
  PathRemoveFileSpecW(pwszPath);
  PathRemoveFileSpecW(pwszPath);
  std::wstring psfile = pwszPath;
  switch (channel) {
  case kOpenEnvironment:
    psfile += L"\\bin\\ClangBuilderEnvironment.ps1";
    break;
  case kBaseBuilder:
    psfile += L"\\bin\\ClangBuilderManager.ps1";
    break;
  case kNinjaBootstrap:
    psfile += L"\\bin\\ClangBuilderBootstrap.ps1";
    break;
  default:
    psfile = L"Not support channel value: " + std::to_wstring(channel);
    OutErrorMessage(psfile.c_str(), L"Not support clangbuilder channel !");
    return -2;
  }
  if (!PathFileExistsW(psfile.c_str())) {
    OutErrorMessage(psfile.c_str(), L"PathFileExists return false");
    return -1;
  }

  if (SHGetFolderPathW(NULL, CSIDL_SYSTEM, NULL, 0, pwszPath) != S_OK) {
    return -1;
  }
  auto length = wcslen(pwszPath);
  StringCchCatW(pwszPath, UNC_MAX_PATH - length,
                L"\\WindowsPowerShell\\v1.0\\powershell.exe ");
  length = wcslen(pwszPath);
  auto offsetPtr = pwszPath + length;
  StringCchPrintfW(offsetPtr, UNC_MAX_PATH - length,
                   L" -NoLogo -NoExit   -File \"%s\" %s", psfile.c_str(), args);
  PROCESS_INFORMATION pi;
  STARTUPINFO si;
  ZeroMemory(&si, sizeof(si));
  ZeroMemory(&pi, sizeof(pi));
  si.cb = sizeof(si);
  si.dwFlags = STARTF_USESHOWWINDOW;
  si.wShowWindow = SW_SHOW;
  if (CreateProcessW(nullptr, pwszPath, NULL, NULL, FALSE,
                     CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS, NULL, NULL,
                     &si, &pi)) {
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    return 0;
  }
  return GetLastError();
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPWSTR lpCmdLine, int nCmdShow) {
  UNREFERENCED_PARAMETER(hInstance);
  UNREFERENCED_PARAMETER(hPrevInstance);
  UNREFERENCED_PARAMETER(lpCmdLine);
  UNREFERENCED_PARAMETER(nCmdShow);
  const wchar_t *vs = nullptr;
  const wchar_t *target = nullptr;
  const wchar_t *flavor = nullptr;
  bool createInstallPkg = false;
  bool clearEnv = false;
  bool useNmake = false;
  bool buildReleasedRevision = false;
  bool useStaticCRT = false;
  bool buildLLDB = false;
  int channel = kBaseBuilder;
  int Argc = 0;
  auto Argv_ = CommandLineToArgvW(GetCommandLineW(), &Argc);
  wchar_t *const *Argv = Argv_;
  int ch;
  const wchar_t *short_opts = L"V:A:F:BEICRSLNH"; // L"V:T:C:BIERSLNH";
  const option option_long_opt[] = {
      ///
      {L"vs", required_argument, NULL, 'V'},
      {L"arch", required_argument, NULL, 'A'},
      {L"flavor", required_argument, NULL, 'F'},
      {L"bootstrap", no_argument, NULL, 'B'},
      {L"env", no_argument, NULL, 'E'},
      {L"install", no_argument, NULL, 'I'},
      {L"clear", no_argument, NULL, 'C'},
      {L"released", no_argument, NULL, 'R'},
      {L"static", no_argument, NULL, 'S'},
      {L"lldb", no_argument, NULL, 'L'},
      {L"nmake", no_argument, NULL, 'N'},
      {L"help", no_argument, NULL, 'H'},
      {0, 0, 0, 0}
      ///
  };
  while ((ch = getopt_long(Argc, Argv, short_opts, option_long_opt, NULL)) !=
         -1) {
    switch (ch) {
    case 'V':
      vs = optarg;
      break;
    case 'A':
      target = optarg;
      break;
    case 'F':
      flavor = optarg;
      break;
    case 'B':
      channel = kNinjaBootstrap;
      break;
    case 'E':
      channel = kOpenEnvironment;
      break;
    case 'I':
      createInstallPkg = true;
      break;
    case 'C':
      clearEnv = true;
      break;
    case 'R':
      buildReleasedRevision = true;
      break;
    case 'S':
      useStaticCRT = true;
      break;
    case 'L':
      buildLLDB = true;
      break;
    case 'N':
      useNmake = true;
      break;
    case 'H':
      Usage();
      LocalFree(Argv_);
      return 0;
    default:
      break;
    }
  }
  if (vs == nullptr || target == nullptr || flavor == nullptr) {
    Usage();
    return 0;
  }
  WCHAR szBuffer[UNC_MAX_PATH] = {0};
  StringCbPrintfW(szBuffer, UNC_MAX_PATH, L" -VisualStudio %s -Arch %s", vs,
                  target);
  if (channel != kOpenEnvironment) {
    StringCbCatW(szBuffer, UNC_MAX_PATH, L" -Flavor ");
    StringCbCatW(szBuffer, UNC_MAX_PATH, flavor);
    if (createInstallPkg) {
      StringCbCatW(szBuffer, UNC_MAX_PATH, L" -Install");
    }
    if (buildReleasedRevision) {
      StringCbCatW(szBuffer, UNC_MAX_PATH, L" -Released");
    }
    if (useStaticCRT) {
      StringCbCatW(szBuffer, UNC_MAX_PATH, L" -Static");
    }
    if (useNmake && channel == kBaseBuilder) {
      StringCbCatW(szBuffer, UNC_MAX_PATH, L" -NMake");
    }
    if (buildLLDB && channel == kBaseBuilder) {
      StringCbCatW(szBuffer, UNC_MAX_PATH, L" -LLDB");
    }
  }
  if (clearEnv) {
    StringCbCatW(szBuffer, UNC_MAX_PATH, L" -Clear");
  }
  auto result = LauncherStartup(szBuffer, channel);
  LocalFree(Argv_);
  return result;
}

int OutErrorMessage(const wchar_t *errorMsg, const wchar_t *errorTitle) {
  int nButton = 0;
  int nRadioButton = 0;
  TASKDIALOGCONFIG tdConfig;
  memset(&tdConfig, 0, sizeof(tdConfig));
  tdConfig.cbSize = sizeof(tdConfig);
  tdConfig.hwndParent = nullptr;
  tdConfig.hInstance = GetModuleHandle(nullptr);
  tdConfig.dwFlags = TDF_ALLOW_DIALOG_CANCELLATION | TDF_EXPAND_FOOTER_AREA |
                     TDF_POSITION_RELATIVE_TO_WINDOW | TDF_SIZE_TO_CONTENT |
                     TDF_ENABLE_HYPERLINKS;
  tdConfig.nDefaultRadioButton = nRadioButton;
  tdConfig.pszWindowTitle = L"Clangbuilder launcher Error";
  tdConfig.pszMainInstruction = errorTitle;
  tdConfig.hMainIcon = static_cast<HICON>(
      LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_ICON_LAUNCHER)));
  tdConfig.dwFlags |= TDF_USE_HICON_MAIN;
  tdConfig.pszContent = errorMsg;
  tdConfig.pszExpandedInformation =
      _T("For more information about this tool, ")
      _T("Visit: Force ")
      _T("Charlie");
  tdConfig.pszCollapsedControlText = _T("More information");
  tdConfig.pszExpandedControlText = _T("Less information");
  tdConfig.pfCallback = TaskDialogCallbackProc;
  HRESULT hr = TaskDialogIndirect(&tdConfig, &nButton, &nRadioButton, NULL);
  return hr;
}
<|endoftext|>


<commit_before>//===--- clang.cpp - C-Language Front-end ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This utility may be invoked in the following manner:
//   clang-cc --help                - Output help info.
//   clang-cc [options]             - Read from stdin.
//   clang-cc [options] file        - Read from "file".
//   clang-cc [options] file1 file2 - Read these files.
//
//===----------------------------------------------------------------------===//

#include "Options.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/VerifyDiagnosticsClient.h"
#include "llvm/LLVMContext.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
#include "llvm/System/Signals.h"
#include "llvm/Target/TargetSelect.h"
using namespace clang;

//===----------------------------------------------------------------------===//
// Main driver
//===----------------------------------------------------------------------===//

std::string GetBuiltinIncludePath(const char *Argv0) {
  llvm::sys::Path P =
    llvm::sys::Path::GetMainExecutable(Argv0,
                                       (void*)(intptr_t) GetBuiltinIncludePath);

  if (!P.isEmpty()) {
    P.eraseComponent();  // Remove /clang from foo/bin/clang
    P.eraseComponent();  // Remove /bin   from foo/bin

    // Get foo/lib/clang/<version>/include
    P.appendComponent("lib");
    P.appendComponent("clang");
    P.appendComponent(CLANG_VERSION_STRING);
    P.appendComponent("include");
  }

  return P.str();
}

static void LLVMErrorHandler(void *UserData, const std::string &Message) {
  Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);

  Diags.Report(diag::err_fe_error_backend) << Message;

  // We cannot recover from llvm errors.
  exit(1);
}

/// ClangFrontendTimer - The front-end activities should charge time to it with
/// TimeRegion.  The -ftime-report option controls whether this will do
/// anything.
llvm::Timer *ClangFrontendTimer = 0;

static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
  using namespace clang::frontend;

  switch (CI.getFrontendOpts().ProgramAction) {
  default:
    llvm::llvm_unreachable("Invalid program action!");

  case ASTDump:                return new ASTDumpAction();
  case ASTPrint:               return new ASTPrintAction();
  case ASTPrintXML:            return new ASTPrintXMLAction();
  case ASTView:                return new ASTViewAction();
  case DumpRawTokens:          return new DumpRawTokensAction();
  case DumpRecordLayouts:      return new DumpRecordAction();
  case DumpTokens:             return new DumpTokensAction();
  case EmitAssembly:           return new EmitAssemblyAction();
  case EmitBC:                 return new EmitBCAction();
  case EmitHTML:               return new HTMLPrintAction();
  case EmitLLVM:               return new EmitLLVMAction();
  case EmitLLVMOnly:           return new EmitLLVMOnlyAction();
  case FixIt:                  return new FixItAction();
  case GeneratePCH:            return new GeneratePCHAction();
  case GeneratePTH:            return new GeneratePTHAction();
  case InheritanceView:        return new InheritanceViewAction();
  case ParseNoop:              return new ParseOnlyAction();
  case ParsePrintCallbacks:    return new PrintParseAction();
  case ParseSyntaxOnly:        return new SyntaxOnlyAction();

  case PluginAction: {
    if (CI.getFrontendOpts().ActionName == "help") {
      llvm::errs() << "clang-cc plugins:\n";
      for (FrontendPluginRegistry::iterator it =
             FrontendPluginRegistry::begin(),
             ie = FrontendPluginRegistry::end();
           it != ie; ++it)
        llvm::errs() << "  " << it->getName() << " - " << it->getDesc() << "\n";
      exit(1);
    }

    for (FrontendPluginRegistry::iterator it =
           FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
         it != ie; ++it) {
      if (it->getName() == CI.getFrontendOpts().ActionName)
        return it->instantiate();
    }

    CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
      << CI.getFrontendOpts().ActionName;
    return 0;
  }

  case PrintDeclContext:       return new DeclContextPrintAction();
  case PrintPreprocessedInput: return new PrintPreprocessedAction();
  case RewriteBlocks:          return new RewriteBlocksAction();
  case RewriteMacros:          return new RewriteMacrosAction();
  case RewriteObjC:            return new RewriteObjCAction();
  case RewriteTest:            return new RewriteTestAction();
  case RunAnalysis:            return new AnalysisAction();
  case RunPreprocessorOnly:    return new PreprocessOnlyAction();
  }
}

static TargetInfo *
ConstructCompilerInvocation(CompilerInvocation &Opts, Diagnostic &Diags,
                            const char *Argv0, bool &IsAST) {
  // Initialize target options.
  InitializeTargetOptions(Opts.getTargetOpts());

  // Get information about the target being compiled for.
  llvm::OwningPtr<TargetInfo> Target(
    TargetInfo::CreateTargetInfo(Diags, Opts.getTargetOpts()));
  if (!Target)
    return 0;

  // Initialize frontend options.
  InitializeFrontendOptions(Opts.getFrontendOpts());

  // Determine the input language, we currently require all files to match.
  FrontendOptions::InputKind IK = Opts.getFrontendOpts().Inputs[0].first;
  for (unsigned i = 1, e = Opts.getFrontendOpts().Inputs.size(); i != e; ++i) {
    if (Opts.getFrontendOpts().Inputs[i].first != IK) {
      llvm::errs() << "error: cannot have multiple input files of distinct "
                   << "language kinds without -x\n";
      return 0;
    }
  }

  // Initialize language options.
  //
  // FIXME: These aren't used during operations on ASTs. Split onto a separate
  // code path to make this obvious.
  IsAST = (IK == FrontendOptions::IK_AST);
  if (!IsAST)
    InitializeLangOptions(Opts.getLangOpts(), IK, *Target);

  // Initialize the static analyzer options.
  InitializeAnalyzerOptions(Opts.getAnalyzerOpts());

  // Initialize the dependency output options (-M...).
  InitializeDependencyOutputOptions(Opts.getDependencyOutputOpts());

  // Initialize the header search options.
  InitializeHeaderSearchOptions(Opts.getHeaderSearchOpts(),
                                GetBuiltinIncludePath(Argv0));

  // Initialize the other preprocessor options.
  InitializePreprocessorOptions(Opts.getPreprocessorOpts());

  // Initialize the preprocessed output options.
  InitializePreprocessorOutputOptions(Opts.getPreprocessorOutputOpts());

  // Initialize backend options, which may also be used to key some language
  // options.
  InitializeCodeGenOptions(Opts.getCodeGenOpts(), Opts.getLangOpts(),
                           Opts.getFrontendOpts().ShowTimers);

  return Target.take();
}

int main(int argc, char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal();
  llvm::PrettyStackTraceProgram X(argc, argv);
  CompilerInstance Clang(&llvm::getGlobalContext(), false);

  // Initialize targets first, so that --version shows registered targets.
  llvm::InitializeAllTargets();
  llvm::InitializeAllAsmPrinters();

  llvm::cl::ParseCommandLineOptions(argc, argv,
                              "LLVM 'Clang' Compiler: http://clang.llvm.org\n");

  // Construct the diagnostic engine first, so that we can build a diagnostic
  // client to use for any errors during option handling.
  InitializeDiagnosticOptions(Clang.getDiagnosticOpts());
  Clang.createDiagnostics(argc, argv);
  if (!Clang.hasDiagnostics())
    return 1;

  // Set an error handler, so that any LLVM backend diagnostics go through our
  // error handler.
  llvm::llvm_install_error_handler(LLVMErrorHandler,
                                   static_cast<void*>(&Clang.getDiagnostics()));

  // Now that we have initialized the diagnostics engine, create the target and
  // the compiler invocation object.
  //
  // FIXME: We should move .ast inputs to taking a separate path, they are
  // really quite different.
  bool IsAST;
  Clang.setTarget(
    ConstructCompilerInvocation(Clang.getInvocation(), Clang.getDiagnostics(),
                                argv[0], IsAST));
  if (!Clang.hasTarget())
    return 1;

  // Validate/process some options
  if (Clang.getHeaderSearchOpts().Verbose)
    llvm::errs() << "clang-cc version " CLANG_VERSION_STRING
                 << " based upon " << PACKAGE_STRING
                 << " hosted on " << llvm::sys::getHostTriple() << "\n";

  if (Clang.getFrontendOpts().ShowTimers)
    ClangFrontendTimer = new llvm::Timer("Clang front-end time");

  // Enforce certain implications.
  if (!Clang.getFrontendOpts().ViewClassInheritance.empty())
    Clang.getFrontendOpts().ProgramAction = frontend::InheritanceView;
  if (!Clang.getFrontendOpts().FixItLocations.empty())
    Clang.getFrontendOpts().ProgramAction = frontend::FixIt;

  for (unsigned i = 0, e = Clang.getFrontendOpts().Inputs.size(); i != e; ++i) {
    const std::string &InFile = Clang.getFrontendOpts().Inputs[i].second;

    // If we aren't using an AST file, setup the file and source managers and
    // the preprocessor.
    if (!IsAST) {
      if (!i) {
        // Create a file manager object to provide access to and cache the
        // filesystem.
        Clang.createFileManager();

        // Create the source manager.
        Clang.createSourceManager();
      } else {
        // Reset the ID tables if we are reusing the SourceManager.
        Clang.getSourceManager().clearIDTables();
      }

      // Create the preprocessor.
      Clang.createPreprocessor();
    }

    llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
    if (!Act)
      break;

    Act->setCurrentTimer(ClangFrontendTimer);
    if (Act->BeginSourceFile(Clang, InFile, IsAST)) {
      Act->Execute();
      Act->EndSourceFile();
    }
  }

  if (Clang.getDiagnosticOpts().ShowCarets)
    if (unsigned NumDiagnostics = Clang.getDiagnostics().getNumDiagnostics())
      fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics,
              (NumDiagnostics == 1 ? "" : "s"));

  if (Clang.getFrontendOpts().ShowStats) {
    Clang.getFileManager().PrintStats();
    fprintf(stderr, "\n");
  }

  delete ClangFrontendTimer;

  // Return the appropriate status when verifying diagnostics.
  //
  // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
  // this.
  if (Clang.getDiagnosticOpts().VerifyDiagnostics)
    return static_cast<VerifyDiagnosticsClient&>(
      Clang.getDiagnosticClient()).HadErrors();

  // Managed static deconstruction. Useful for making things like
  // -time-passes usable.
  llvm::llvm_shutdown();

  return (Clang.getDiagnostics().getNumErrors() != 0);
}

<commit_msg>Fix -Asserts warning.<commit_after>//===--- clang.cpp - C-Language Front-end ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This utility may be invoked in the following manner:
//   clang-cc --help                - Output help info.
//   clang-cc [options]             - Read from stdin.
//   clang-cc [options] file        - Read from "file".
//   clang-cc [options] file1 file2 - Read these files.
//
//===----------------------------------------------------------------------===//

#include "Options.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Frontend/VerifyDiagnosticsClient.h"
#include "llvm/LLVMContext.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Host.h"
#include "llvm/System/Path.h"
#include "llvm/System/Signals.h"
#include "llvm/Target/TargetSelect.h"
using namespace clang;

//===----------------------------------------------------------------------===//
// Main driver
//===----------------------------------------------------------------------===//

std::string GetBuiltinIncludePath(const char *Argv0) {
  llvm::sys::Path P =
    llvm::sys::Path::GetMainExecutable(Argv0,
                                       (void*)(intptr_t) GetBuiltinIncludePath);

  if (!P.isEmpty()) {
    P.eraseComponent();  // Remove /clang from foo/bin/clang
    P.eraseComponent();  // Remove /bin   from foo/bin

    // Get foo/lib/clang/<version>/include
    P.appendComponent("lib");
    P.appendComponent("clang");
    P.appendComponent(CLANG_VERSION_STRING);
    P.appendComponent("include");
  }

  return P.str();
}

static void LLVMErrorHandler(void *UserData, const std::string &Message) {
  Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);

  Diags.Report(diag::err_fe_error_backend) << Message;

  // We cannot recover from llvm errors.
  exit(1);
}

/// ClangFrontendTimer - The front-end activities should charge time to it with
/// TimeRegion.  The -ftime-report option controls whether this will do
/// anything.
llvm::Timer *ClangFrontendTimer = 0;

static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
  using namespace clang::frontend;

  switch (CI.getFrontendOpts().ProgramAction) {
  default:
    llvm::llvm_unreachable("Invalid program action!");

  case ASTDump:                return new ASTDumpAction();
  case ASTPrint:               return new ASTPrintAction();
  case ASTPrintXML:            return new ASTPrintXMLAction();
  case ASTView:                return new ASTViewAction();
  case DumpRawTokens:          return new DumpRawTokensAction();
  case DumpRecordLayouts:      return new DumpRecordAction();
  case DumpTokens:             return new DumpTokensAction();
  case EmitAssembly:           return new EmitAssemblyAction();
  case EmitBC:                 return new EmitBCAction();
  case EmitHTML:               return new HTMLPrintAction();
  case EmitLLVM:               return new EmitLLVMAction();
  case EmitLLVMOnly:           return new EmitLLVMOnlyAction();
  case FixIt:                  return new FixItAction();
  case GeneratePCH:            return new GeneratePCHAction();
  case GeneratePTH:            return new GeneratePTHAction();
  case InheritanceView:        return new InheritanceViewAction();
  case ParseNoop:              return new ParseOnlyAction();
  case ParsePrintCallbacks:    return new PrintParseAction();
  case ParseSyntaxOnly:        return new SyntaxOnlyAction();

  case PluginAction: {
    if (CI.getFrontendOpts().ActionName == "help") {
      llvm::errs() << "clang-cc plugins:\n";
      for (FrontendPluginRegistry::iterator it =
             FrontendPluginRegistry::begin(),
             ie = FrontendPluginRegistry::end();
           it != ie; ++it)
        llvm::errs() << "  " << it->getName() << " - " << it->getDesc() << "\n";
      exit(1);
    }

    for (FrontendPluginRegistry::iterator it =
           FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
         it != ie; ++it) {
      if (it->getName() == CI.getFrontendOpts().ActionName)
        return it->instantiate();
    }

    CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
      << CI.getFrontendOpts().ActionName;
    return 0;
  }

  case PrintDeclContext:       return new DeclContextPrintAction();
  case PrintPreprocessedInput: return new PrintPreprocessedAction();
  case RewriteBlocks:          return new RewriteBlocksAction();
  case RewriteMacros:          return new RewriteMacrosAction();
  case RewriteObjC:            return new RewriteObjCAction();
  case RewriteTest:            return new RewriteTestAction();
  case RunAnalysis:            return new AnalysisAction();
  case RunPreprocessorOnly:    return new PreprocessOnlyAction();
  }
}

static TargetInfo *
ConstructCompilerInvocation(CompilerInvocation &Opts, Diagnostic &Diags,
                            const char *Argv0, bool &IsAST) {
  // Initialize target options.
  InitializeTargetOptions(Opts.getTargetOpts());

  // Get information about the target being compiled for.
  llvm::OwningPtr<TargetInfo> Target(
    TargetInfo::CreateTargetInfo(Diags, Opts.getTargetOpts()));
  if (!Target)
    return 0;

  // Initialize frontend options.
  InitializeFrontendOptions(Opts.getFrontendOpts());

  // Determine the input language, we currently require all files to match.
  FrontendOptions::InputKind IK = Opts.getFrontendOpts().Inputs[0].first;
  for (unsigned i = 1, e = Opts.getFrontendOpts().Inputs.size(); i != e; ++i) {
    if (Opts.getFrontendOpts().Inputs[i].first != IK) {
      llvm::errs() << "error: cannot have multiple input files of distinct "
                   << "language kinds without -x\n";
      return 0;
    }
  }

  // Initialize language options.
  //
  // FIXME: These aren't used during operations on ASTs. Split onto a separate
  // code path to make this obvious.
  IsAST = (IK == FrontendOptions::IK_AST);
  if (!IsAST)
    InitializeLangOptions(Opts.getLangOpts(), IK, *Target);

  // Initialize the static analyzer options.
  InitializeAnalyzerOptions(Opts.getAnalyzerOpts());

  // Initialize the dependency output options (-M...).
  InitializeDependencyOutputOptions(Opts.getDependencyOutputOpts());

  // Initialize the header search options.
  InitializeHeaderSearchOptions(Opts.getHeaderSearchOpts(),
                                GetBuiltinIncludePath(Argv0));

  // Initialize the other preprocessor options.
  InitializePreprocessorOptions(Opts.getPreprocessorOpts());

  // Initialize the preprocessed output options.
  InitializePreprocessorOutputOptions(Opts.getPreprocessorOutputOpts());

  // Initialize backend options, which may also be used to key some language
  // options.
  InitializeCodeGenOptions(Opts.getCodeGenOpts(), Opts.getLangOpts(),
                           Opts.getFrontendOpts().ShowTimers);

  return Target.take();
}

int main(int argc, char **argv) {
  llvm::sys::PrintStackTraceOnErrorSignal();
  llvm::PrettyStackTraceProgram X(argc, argv);
  CompilerInstance Clang(&llvm::getGlobalContext(), false);

  // Initialize targets first, so that --version shows registered targets.
  llvm::InitializeAllTargets();
  llvm::InitializeAllAsmPrinters();

  llvm::cl::ParseCommandLineOptions(argc, argv,
                              "LLVM 'Clang' Compiler: http://clang.llvm.org\n");

  // Construct the diagnostic engine first, so that we can build a diagnostic
  // client to use for any errors during option handling.
  InitializeDiagnosticOptions(Clang.getDiagnosticOpts());
  Clang.createDiagnostics(argc, argv);
  if (!Clang.hasDiagnostics())
    return 1;

  // Set an error handler, so that any LLVM backend diagnostics go through our
  // error handler.
  llvm::llvm_install_error_handler(LLVMErrorHandler,
                                   static_cast<void*>(&Clang.getDiagnostics()));

  // Now that we have initialized the diagnostics engine, create the target and
  // the compiler invocation object.
  //
  // FIXME: We should move .ast inputs to taking a separate path, they are
  // really quite different.
  bool IsAST = false;
  Clang.setTarget(
    ConstructCompilerInvocation(Clang.getInvocation(), Clang.getDiagnostics(),
                                argv[0], IsAST));
  if (!Clang.hasTarget())
    return 1;

  // Validate/process some options
  if (Clang.getHeaderSearchOpts().Verbose)
    llvm::errs() << "clang-cc version " CLANG_VERSION_STRING
                 << " based upon " << PACKAGE_STRING
                 << " hosted on " << llvm::sys::getHostTriple() << "\n";

  if (Clang.getFrontendOpts().ShowTimers)
    ClangFrontendTimer = new llvm::Timer("Clang front-end time");

  // Enforce certain implications.
  if (!Clang.getFrontendOpts().ViewClassInheritance.empty())
    Clang.getFrontendOpts().ProgramAction = frontend::InheritanceView;
  if (!Clang.getFrontendOpts().FixItLocations.empty())
    Clang.getFrontendOpts().ProgramAction = frontend::FixIt;

  for (unsigned i = 0, e = Clang.getFrontendOpts().Inputs.size(); i != e; ++i) {
    const std::string &InFile = Clang.getFrontendOpts().Inputs[i].second;

    // If we aren't using an AST file, setup the file and source managers and
    // the preprocessor.
    if (!IsAST) {
      if (!i) {
        // Create a file manager object to provide access to and cache the
        // filesystem.
        Clang.createFileManager();

        // Create the source manager.
        Clang.createSourceManager();
      } else {
        // Reset the ID tables if we are reusing the SourceManager.
        Clang.getSourceManager().clearIDTables();
      }

      // Create the preprocessor.
      Clang.createPreprocessor();
    }

    llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
    if (!Act)
      break;

    Act->setCurrentTimer(ClangFrontendTimer);
    if (Act->BeginSourceFile(Clang, InFile, IsAST)) {
      Act->Execute();
      Act->EndSourceFile();
    }
  }

  if (Clang.getDiagnosticOpts().ShowCarets)
    if (unsigned NumDiagnostics = Clang.getDiagnostics().getNumDiagnostics())
      fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics,
              (NumDiagnostics == 1 ? "" : "s"));

  if (Clang.getFrontendOpts().ShowStats) {
    Clang.getFileManager().PrintStats();
    fprintf(stderr, "\n");
  }

  delete ClangFrontendTimer;

  // Return the appropriate status when verifying diagnostics.
  //
  // FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
  // this.
  if (Clang.getDiagnosticOpts().VerifyDiagnostics)
    return static_cast<VerifyDiagnosticsClient&>(
      Clang.getDiagnosticClient()).HadErrors();

  // Managed static deconstruction. Useful for making things like
  // -time-passes usable.
  llvm::llvm_shutdown();

  return (Clang.getDiagnostics().getNumErrors() != 0);
}

<|endoftext|>


<commit_before>//  Copyright 2010 Gregory Szorc
//
//  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 <zippylog/zippylog.hpp>
#include <zippylog/device/server.hpp>

#include <iostream>
#include <string>

using ::zippylog::device::Server;
using ::std::cout;
using ::std::endl;
using ::std::string;
using ::std::vector;

#ifdef LINUX
static volatile sig_atomic_t active = 1;

void signal_handler(int signo)
{
    active = 0;

    signal(signo, SIG_DFL);
}
#endif

int main(int argc, const char * const argv[])
{
#ifdef LINUX
    // TODO this signal handling is horribly naive
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
#endif

    try {
        ::zippylog::initialize_library();

        Server server(argv[1]);

#ifdef LINUX
        server.RunAsync();
        while (active) pause();
#elif WINDOWS
        server.Run();
#else
#error "not implemented on this platform"
#endif
    }
    catch (string s) {
        cout << "Exception:" << endl;
        cout << s;
        return 1;
    }
    catch (char * s) {
        cout << "Exception: " << s << endl;
        return 1;
    }
    catch (...) {
        cout << "received an exception" << endl;
        return 1;
    }

    ::zippylog::shutdown_library();

    return 0;
}
<commit_msg>catch exceptions better<commit_after>//  Copyright 2010 Gregory Szorc
//
//  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 <zippylog/zippylog.hpp>
#include <zippylog/device/server.hpp>

#include <iostream>
#include <string>

using ::zippylog::device::Server;
using ::std::cout;
using ::std::endl;
using ::std::string;
using ::std::vector;

#ifdef LINUX
static volatile sig_atomic_t active = 1;

void signal_handler(int signo)
{
    active = 0;

    signal(signo, SIG_DFL);
}
#endif

int main(int argc, const char * const argv[])
{
#ifdef LINUX
    // TODO this signal handling is horribly naive
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
#endif

    try {
        ::zippylog::initialize_library();

        Server server(argv[1]);

#ifdef LINUX
        server.RunAsync();
        while (active) pause();
#elif WINDOWS
        server.Run();
#else
#error "not implemented on this platform"
#endif
    }
    catch (::std::exception e) {
        cout << "Exception: " << e.what() << endl;
        return 1;
    }

    ::zippylog::shutdown_library();

    return 0;
}
<|endoftext|>


<commit_before>#include "qcsvtoxml.h"

#include <algorithm>

#include <QFileDialog>
#include <QTextStream>
#include <QXmlStreamWriter>

QCSVToXML::QCSVToXML(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	connect(this->ui.actionLoad, &QAction::triggered, this, &QCSVToXML::loadAction);
	connect(this->ui.actionExport, &QAction::triggered, this, &QCSVToXML::saveAction);

	connect(this->ui.lineEditElement, &QLineEdit::textChanged, this, &QCSVToXML::refreshXmlPreview);
	connect(this->ui.lineEditNamespace, &QLineEdit::textChanged, this, &QCSVToXML::refreshXmlPreview);
	connect(this->ui.lineEditNamespaceUri, &QLineEdit::textChanged, this, &QCSVToXML::refreshXmlPreview);
	connect(this->ui.lineEditRoot, &QLineEdit::textChanged, this, &QCSVToXML::refreshXmlPreview);

	connect(this->ui.checkBoxAttributeAsElement, &QCheckBox::toggled, this, &QCSVToXML::refreshXmlPreview);
	connect(this->ui.checkBoxFirstRowAsAttributes, &QCheckBox::toggled, this, &QCSVToXML::refreshXmlPreview);
}

QCSVToXML::~QCSVToXML()
{

}

void QCSVToXML::loadAction()
{
	this->load(
		QFileDialog::getOpenFileName(
			this,
			tr("Load File"),
			this->settings.value(
				"workingDirectory",
				QApplication::applicationDirPath()).toString(),
			tr("CSV files (*.csv)")));
}

void QCSVToXML::saveAction()
{
	this->save(
		QFileDialog::getSaveFileName(
			this,
			tr("Save File"),
			this->settings.value(
				"workingDirectory",
				QApplication::applicationDirPath()).toString(),
			tr("XML files (*.xml)")));
}

void QCSVToXML::load(const QString &filename)
{
	if (filename.isEmpty()) {
		return;
	}

	QFile file(filename);
	QFileInfo fileInfo(file);

	this->settings.setValue("workingDirectory", fileInfo.absolutePath());

	if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
		return;
	}

	this->csvContents.clear();

	this->ui.lineEditElement->setText(fileInfo.baseName());
	this->ui.lineEditRoot->setText(fileInfo.baseName() + "s");

	QTextStream in(&file);

	while (!in.atEnd()) {
		QString line = in.readLine();
		while (line.count('"') % 2 != 0 && !in.atEnd()) {
			// If we have an odd number of quotes there must be a newline in
			//  one of the fields. (or RFC 4180 is not being followed, in which
			//  case we don't care about handling the file properly.)
			line += '\n' + in.readLine();
		}

		bool quoted = false;
		int start = 0;

		std::vector<QString> elements;

		for (int i = 0; i <= line.length(); ++i) {
			if (i == line.length()) {
				elements.push_back(line.mid(start));
			} else if (line[i] == '"') {
				quoted = !quoted;
			} else if (line[i] == ',' && !quoted) {
				elements.push_back(line.mid(start, i - start));
				start = i + 1;
			}
		}

		for (int i = 0; i < elements.size(); ++i) {
			// remove quotes surrounding quoted fields.
			elements[i].replace(
				QRegularExpression(
					"^\\s*\"(.*)\"\\s*$",
					QRegularExpression::DotMatchesEverythingOption),
				"\\1");

			// unescape quotes.
			elements[i].replace("\"\"", "\"");
		}

		this->csvContents.push_back(elements);
	}

	this->populateAttributeGroupBox();
	this->refreshXmlPreview();
}

void QCSVToXML::save(const QString &filename)
{
	if (filename.isEmpty()) {
		return;
	}

	QFile file(filename);
	QFileInfo fileInfo(file);

	this->settings.setValue("workingDirectory", fileInfo.absolutePath());
}

void QCSVToXML::populateAttributeGroupBox()
{
	if (this->csvContents.empty() || this->csvContents[0].size() < this->ui.formLayoutWidgetAttributes->rowCount()) {
		this->fieldLineEdits.clear();
		this->ui.verticalLayoutGroupBoxAttributes->removeWidget(this->ui.widgetAttributes);
		delete this->ui.widgetAttributes;
		this->ui.widgetAttributes = new QWidget(this->ui.groupBoxAttributes);
		this->ui.formLayoutWidgetAttributes = new QFormLayout(this->ui.widgetAttributes);
		this->ui.verticalLayoutGroupBoxAttributes->addWidget(this->ui.widgetAttributes);
	}

	for (int i = this->ui.formLayoutWidgetAttributes->rowCount(); i < this->csvContents[0].size(); ++i) {
		QLineEdit *lineEdit = new QLineEdit(this->ui.widgetAttributes);

		if (this->ui.checkBoxFirstRowAsAttributes->isChecked()) {
			lineEdit->setText(this->csvContents[0][i]);
		} else {
			lineEdit->setText(QString("Attribute %1").arg(QString::number(i)));
		}

		this->fieldLineEdits.push_back(lineEdit);
		this->ui.formLayoutWidgetAttributes->addRow(QString("Field %1:").arg(QString::number(i)), lineEdit);
	}
}

void QCSVToXML::refreshXmlPreview()
{
	if (this->csvContents.empty()) {
		this->ui.textBrowserXmlOutput->clear();
		return;
	}

	QString xml;

	QXmlStreamWriter writer(&xml);

	writer.setAutoFormatting(true);

	writer.writeStartDocument();

	writer.writeStartElement(this->ui.lineEditRoot->text().replace(' ', '_'));

	writer.writeStartElement(this->ui.lineEditElement->text().replace(' ', '_'));

	int dataRow = (this->ui.checkBoxFirstRowAsAttributes->isChecked() && this->csvContents.size() > 1) ? 1 : 0;

	for (int i = 0; i < std::min(this->csvContents[dataRow].size(), this->csvContents[0].size()); ++i) {
		if (this->ui.checkBoxAttributeAsElement->isChecked()) {
			writer.writeTextElement(this->fieldLineEdits[i]->text().replace(' ', '_'), this->csvContents[dataRow][i]);
		} else {
			writer.writeAttribute(this->ui.lineEditNamespaceUri->text().replace(' ', '_'), this->fieldLineEdits[i]->text(), this->csvContents[dataRow][i]);
		}
	}

	writer.writeEndElement();

	writer.writeEndElement();

	writer.writeEndDocument();

	this->ui.textBrowserXmlOutput->setText(xml);
}
<commit_msg>Spaces replaced with underscores in attribute names too...<commit_after>#include "qcsvtoxml.h"

#include <algorithm>

#include <QFileDialog>
#include <QTextStream>
#include <QXmlStreamWriter>

QCSVToXML::QCSVToXML(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	connect(this->ui.actionLoad, &QAction::triggered, this, &QCSVToXML::loadAction);
	connect(this->ui.actionExport, &QAction::triggered, this, &QCSVToXML::saveAction);

	connect(this->ui.lineEditElement, &QLineEdit::textChanged, this, &QCSVToXML::refreshXmlPreview);
	connect(this->ui.lineEditNamespace, &QLineEdit::textChanged, this, &QCSVToXML::refreshXmlPreview);
	connect(this->ui.lineEditNamespaceUri, &QLineEdit::textChanged, this, &QCSVToXML::refreshXmlPreview);
	connect(this->ui.lineEditRoot, &QLineEdit::textChanged, this, &QCSVToXML::refreshXmlPreview);

	connect(this->ui.checkBoxAttributeAsElement, &QCheckBox::toggled, this, &QCSVToXML::refreshXmlPreview);
	connect(this->ui.checkBoxFirstRowAsAttributes, &QCheckBox::toggled, this, &QCSVToXML::refreshXmlPreview);
}

QCSVToXML::~QCSVToXML()
{

}

void QCSVToXML::loadAction()
{
	this->load(
		QFileDialog::getOpenFileName(
			this,
			tr("Load File"),
			this->settings.value(
				"workingDirectory",
				QApplication::applicationDirPath()).toString(),
			tr("CSV files (*.csv)")));
}

void QCSVToXML::saveAction()
{
	this->save(
		QFileDialog::getSaveFileName(
			this,
			tr("Save File"),
			this->settings.value(
				"workingDirectory",
				QApplication::applicationDirPath()).toString(),
			tr("XML files (*.xml)")));
}

void QCSVToXML::load(const QString &filename)
{
	if (filename.isEmpty()) {
		return;
	}

	QFile file(filename);
	QFileInfo fileInfo(file);

	this->settings.setValue("workingDirectory", fileInfo.absolutePath());

	if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
		return;
	}

	this->csvContents.clear();

	this->ui.lineEditElement->setText(fileInfo.baseName());
	this->ui.lineEditRoot->setText(fileInfo.baseName() + "s");

	QTextStream in(&file);

	while (!in.atEnd()) {
		QString line = in.readLine();
		while (line.count('"') % 2 != 0 && !in.atEnd()) {
			// If we have an odd number of quotes there must be a newline in
			//  one of the fields. (or RFC 4180 is not being followed, in which
			//  case we don't care about handling the file properly.)
			line += '\n' + in.readLine();
		}

		bool quoted = false;
		int start = 0;

		std::vector<QString> elements;

		for (int i = 0; i <= line.length(); ++i) {
			if (i == line.length()) {
				elements.push_back(line.mid(start));
			} else if (line[i] == '"') {
				quoted = !quoted;
			} else if (line[i] == ',' && !quoted) {
				elements.push_back(line.mid(start, i - start));
				start = i + 1;
			}
		}

		for (int i = 0; i < elements.size(); ++i) {
			// remove quotes surrounding quoted fields.
			elements[i].replace(
				QRegularExpression(
					"^\\s*\"(.*)\"\\s*$",
					QRegularExpression::DotMatchesEverythingOption),
				"\\1");

			// unescape quotes.
			elements[i].replace("\"\"", "\"");
		}

		this->csvContents.push_back(elements);
	}

	this->populateAttributeGroupBox();
	this->refreshXmlPreview();
}

void QCSVToXML::save(const QString &filename)
{
	if (filename.isEmpty()) {
		return;
	}

	QFile file(filename);
	QFileInfo fileInfo(file);

	this->settings.setValue("workingDirectory", fileInfo.absolutePath());
}

void QCSVToXML::populateAttributeGroupBox()
{
	if (this->csvContents.empty() || this->csvContents[0].size() < this->ui.formLayoutWidgetAttributes->rowCount()) {
		this->fieldLineEdits.clear();
		this->ui.verticalLayoutGroupBoxAttributes->removeWidget(this->ui.widgetAttributes);
		delete this->ui.widgetAttributes;
		this->ui.widgetAttributes = new QWidget(this->ui.groupBoxAttributes);
		this->ui.formLayoutWidgetAttributes = new QFormLayout(this->ui.widgetAttributes);
		this->ui.verticalLayoutGroupBoxAttributes->addWidget(this->ui.widgetAttributes);
	}

	for (int i = this->ui.formLayoutWidgetAttributes->rowCount(); i < this->csvContents[0].size(); ++i) {
		QLineEdit *lineEdit = new QLineEdit(this->ui.widgetAttributes);

		if (this->ui.checkBoxFirstRowAsAttributes->isChecked()) {
			lineEdit->setText(this->csvContents[0][i]);
		} else {
			lineEdit->setText(QString("Attribute %1").arg(QString::number(i)));
		}

		this->fieldLineEdits.push_back(lineEdit);
		this->ui.formLayoutWidgetAttributes->addRow(QString("Field %1:").arg(QString::number(i)), lineEdit);
	}
}

void QCSVToXML::refreshXmlPreview()
{
	if (this->csvContents.empty()) {
		this->ui.textBrowserXmlOutput->clear();
		return;
	}

	QString xml;

	QXmlStreamWriter writer(&xml);

	writer.setAutoFormatting(true);

	writer.writeStartDocument();

	writer.writeStartElement(this->ui.lineEditRoot->text().replace(' ', '_'));

	writer.writeStartElement(this->ui.lineEditElement->text().replace(' ', '_'));

	int dataRow = (this->ui.checkBoxFirstRowAsAttributes->isChecked() && this->csvContents.size() > 1) ? 1 : 0;

	for (int i = 0; i < std::min(this->csvContents[dataRow].size(), this->csvContents[0].size()); ++i) {
		if (this->ui.checkBoxAttributeAsElement->isChecked()) {
			writer.writeTextElement(this->fieldLineEdits[i]->text().replace(' ', '_'), this->csvContents[dataRow][i]);
		} else {
			writer.writeAttribute(this->ui.lineEditNamespaceUri->text().replace(' ', '_'), this->fieldLineEdits[i]->text().replace(' ', '_'), this->csvContents[dataRow][i]);
		}
	}

	writer.writeEndElement();

	writer.writeEndElement();

	writer.writeEndDocument();

	this->ui.textBrowserXmlOutput->setText(xml);
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include "caf/config.hpp"
#include "caf/detail/parser/add_ascii.hpp"
#include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/read_ipv6_address.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp"
#include "caf/uri.hpp"

CAF_PUSH_UNUSED_LABEL_WARNING

#include "caf/detail/parser/fsm.hpp"

namespace caf {
namespace detail {
namespace parser {

//   foo://example.com:8042/over/there?name=ferret#nose
//   \_/   \______________/\_________/ \_________/ \__/
//    |           |            |            |        |
// scheme     authority       path        query   fragment
//    |   _____________________|__
//   / \ /                        \.
//   urn:example:animal:ferret:nose

// Unlike our other parsers, the URI parsers only check for validity and
// generate ranges for the subcomponents. URIs can't have linebreaks, so we can
// safely keep track of the position by looking at the column.

template <class Iterator, class Sentinel>
void read_uri_percent_encoded(state<Iterator, Sentinel>& ps, std::string& str) {
  uint8_t char_code = 0;
  auto g = make_scope_guard([&] {
    if (ps.code <= pec::trailing_character)
      str += static_cast<char>(char_code);
  });
  start();
  state(init) {
    transition(read_nibble, hexadecimal_chars, add_ascii<16>(char_code, ch))
  }
  state(read_nibble) {
    transition(done, hexadecimal_chars, add_ascii<16>(char_code, ch))
  }
  term_state(done) {
    // nop
  }
  fin();
}

inline bool uri_unprotected_char(char c) {
  return in_whitelist(alphanumeric_chars, c) || in_whitelist("-._~", c);
}

#define read_next_char(next_state, dest)                                       \
  transition(next_state, uri_unprotected_char, dest += ch)                     \
  fsm_transition(read_uri_percent_encoded(ps, dest), next_state, '%')

template <class Iterator, class Sentinel, class Consumer>
void read_uri_query(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
  // Local variables.
  uri::query_map result;
  std::string key;
  std::string value;
  // Utility functions.
  auto take_str = [&](std::string& str) {
    using std::swap;
    std::string res;
    swap(str, res);
    return std::move(res);
  };
  auto push = [&] {
    result.emplace(take_str(key), take_str(value));
  };
  // Call consumer on exit.
  auto g = make_scope_guard([&] {
    if (ps.code <= pec::trailing_character)
      consumer.query(std::move(result));
  });
  // FSM declaration.
  start();
  // query may be empty
  term_state(init) {
    read_next_char(read_key, key)
  }
  state(read_key) {
    read_next_char(read_key, key)
    transition(read_value, '=')
  }
  term_state(read_value, push()) {
    read_next_char(read_value, value)
    transition(init, '&', push())
  }
  fin();
}

template <class Iterator, class Sentinel, class Consumer>
void read_uri(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
  // Local variables.
  std::string str;
  uint16_t port = 0;
  // Replaces `str` with a default constructed string to make sure we're never
  // operating on a moved-from string object.
  auto take_str = [&] {
    using std::swap;
    std::string res;
    swap(str, res);
    return std::move(res);
  };
  // Allowed character sets.
  auto path_char = [](char c) {
    return in_whitelist(alphanumeric_chars, c) || c == '/';
  };
  // Utility setters for avoiding code duplication.
  auto set_path = [&] {
    consumer.path(take_str());
  };
  auto set_host = [&] {
    consumer.host(take_str());
  };
  auto set_userinfo = [&] {
    consumer.userinfo(take_str());
  };
  // Consumer for reading IPv6 addresses.
  struct {
    Consumer& f;
    void value(ipv6_address addr) {
      f.host(addr);
    }
  } ip_consumer{consumer};
  // FSM declaration.
  start();
  state(init) {
    epsilon(read_scheme)
  }
  state(read_scheme) {
    read_next_char(read_scheme, str)
    transition(have_scheme, ':', consumer.scheme(take_str()))
  }
  state(have_scheme) {
    transition(disambiguate_path, '/')
    read_next_char(read_path, str)
    fsm_transition(read_uri_percent_encoded(ps, str), read_path, '%')
  }
  // This state is terminal, because "file:/" is a valid URI.
  term_state(disambiguate_path, consumer.path("/")) {
    transition(start_authority, '/')
    epsilon(read_path, any_char, str += '/')
  }
  state(start_authority) {
    read_next_char(read_authority, str)
    fsm_transition(read_ipv6_address(ps, ip_consumer), await_end_of_ipv6, '[')
  }
  state(await_end_of_ipv6) {
    transition(end_of_ipv6_host, ']')
  }
  term_state(end_of_ipv6_host) {
    transition(start_port, ':')
    epsilon(end_of_authority)
  }
  term_state(end_of_host) {
    transition(start_port, ':', set_host())
    epsilon(end_of_authority, "/?#", set_host())
  }
  term_state(read_authority, set_host()) {
    read_next_char(read_authority, str)
    transition(start_host, '@', set_userinfo())
    transition(start_port, ':', set_host())
    epsilon(end_of_authority, "/?#", set_host())
  }
  state(start_host) {
    read_next_char(read_host, str)
    fsm_transition(read_ipv6_address(ps, ip_consumer), await_end_of_ipv6, '[')
  }
  term_state(read_host, set_host()) {
    read_next_char(read_host, str)
    transition(start_port, ':', set_host())
    epsilon(end_of_authority, "/?#", set_host())
  }
  state(start_port) {
    transition(read_port, decimal_chars, add_ascii<10>(port, ch))
  }
  term_state(read_port, consumer.port(port)) {
    transition(read_port, decimal_chars, add_ascii<10>(port, ch),
               pec::integer_overflow)
    epsilon(end_of_authority, "/?#", consumer.port(port))
  }
  term_state(end_of_authority) {
    transition(read_path, '/')
    transition(start_query, '?')
    transition(read_fragment, '#')
  }
  term_state(read_path, set_path()) {
    transition(read_path, path_char, str += ch)
    fsm_transition(read_uri_percent_encoded(ps, str), read_path, '%')
    transition(start_query, '?', set_path())
    transition(read_fragment, '#', set_path())
  }
  term_state(start_query) {
    fsm_epsilon(read_uri_query(ps, consumer), end_of_query)
  }
  unstable_state(end_of_query) {
    transition(read_fragment, '#')
    epsilon(done)
  }
  term_state(read_fragment, consumer.fragment(take_str())) {
    read_next_char(read_fragment, str)
  }
  term_state(done) {
    // nop
  }
  fin();
}

} // namespace parser
} // namespace detail
} // namespace caf

#include "caf/detail/parser/fsm_undef.hpp"

CAF_POP_WARNINGS
<commit_msg>Fix commenting style<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright 2011-2018 Dominik Charousset                                     *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#pragma once

#include "caf/config.hpp"
#include "caf/detail/parser/add_ascii.hpp"
#include "caf/detail/parser/chars.hpp"
#include "caf/detail/parser/read_ipv6_address.hpp"
#include "caf/detail/parser/state.hpp"
#include "caf/detail/scope_guard.hpp"
#include "caf/pec.hpp"
#include "caf/uri.hpp"

CAF_PUSH_UNUSED_LABEL_WARNING

#include "caf/detail/parser/fsm.hpp"

namespace caf {
namespace detail {
namespace parser {

//   foo://example.com:8042/over/there?name=ferret#nose
//   \_/   \______________/\_________/ \_________/ \__/
//    |           |            |            |        |
// scheme     authority       path        query   fragment
//    |   _____________________|__
//   / \ /                        \.
//   urn:example:animal:ferret:nose

// Unlike our other parsers, the URI parsers only check for validity and
// generate ranges for the subcomponents. URIs can't have linebreaks, so we can
// safely keep track of the position by looking at the column.

template <class Iterator, class Sentinel>
void read_uri_percent_encoded(state<Iterator, Sentinel>& ps, std::string& str) {
  uint8_t char_code = 0;
  auto g = make_scope_guard([&] {
    if (ps.code <= pec::trailing_character)
      str += static_cast<char>(char_code);
  });
  start();
  state(init) {
    transition(read_nibble, hexadecimal_chars, add_ascii<16>(char_code, ch))
  }
  state(read_nibble) {
    transition(done, hexadecimal_chars, add_ascii<16>(char_code, ch))
  }
  term_state(done) {
    // nop
  }
  fin();
}

inline bool uri_unprotected_char(char c) {
  return in_whitelist(alphanumeric_chars, c) || in_whitelist("-._~", c);
}

#define read_next_char(next_state, dest)                                       \
  transition(next_state, uri_unprotected_char, dest += ch)                     \
  fsm_transition(read_uri_percent_encoded(ps, dest), next_state, '%')

template <class Iterator, class Sentinel, class Consumer>
void read_uri_query(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
  // Local variables.
  uri::query_map result;
  std::string key;
  std::string value;
  // Utility functions.
  auto take_str = [&](std::string& str) {
    using std::swap;
    std::string res;
    swap(str, res);
    return std::move(res);
  };
  auto push = [&] {
    result.emplace(take_str(key), take_str(value));
  };
  // Call consumer on exit.
  auto g = make_scope_guard([&] {
    if (ps.code <= pec::trailing_character)
      consumer.query(std::move(result));
  });
  // FSM declaration.
  start();
  // Query may be empty.
  term_state(init) {
    read_next_char(read_key, key)
  }
  state(read_key) {
    read_next_char(read_key, key)
    transition(read_value, '=')
  }
  term_state(read_value, push()) {
    read_next_char(read_value, value)
    transition(init, '&', push())
  }
  fin();
}

template <class Iterator, class Sentinel, class Consumer>
void read_uri(state<Iterator, Sentinel>& ps, Consumer&& consumer) {
  // Local variables.
  std::string str;
  uint16_t port = 0;
  // Replaces `str` with a default constructed string to make sure we're never
  // operating on a moved-from string object.
  auto take_str = [&] {
    using std::swap;
    std::string res;
    swap(str, res);
    return std::move(res);
  };
  // Allowed character sets.
  auto path_char = [](char c) {
    return in_whitelist(alphanumeric_chars, c) || c == '/';
  };
  // Utility setters for avoiding code duplication.
  auto set_path = [&] {
    consumer.path(take_str());
  };
  auto set_host = [&] {
    consumer.host(take_str());
  };
  auto set_userinfo = [&] {
    consumer.userinfo(take_str());
  };
  // Consumer for reading IPv6 addresses.
  struct {
    Consumer& f;
    void value(ipv6_address addr) {
      f.host(addr);
    }
  } ip_consumer{consumer};
  // FSM declaration.
  start();
  state(init) {
    epsilon(read_scheme)
  }
  state(read_scheme) {
    read_next_char(read_scheme, str)
    transition(have_scheme, ':', consumer.scheme(take_str()))
  }
  state(have_scheme) {
    transition(disambiguate_path, '/')
    read_next_char(read_path, str)
    fsm_transition(read_uri_percent_encoded(ps, str), read_path, '%')
  }
  // This state is terminal, because "file:/" is a valid URI.
  term_state(disambiguate_path, consumer.path("/")) {
    transition(start_authority, '/')
    epsilon(read_path, any_char, str += '/')
  }
  state(start_authority) {
    read_next_char(read_authority, str)
    fsm_transition(read_ipv6_address(ps, ip_consumer), await_end_of_ipv6, '[')
  }
  state(await_end_of_ipv6) {
    transition(end_of_ipv6_host, ']')
  }
  term_state(end_of_ipv6_host) {
    transition(start_port, ':')
    epsilon(end_of_authority)
  }
  term_state(end_of_host) {
    transition(start_port, ':', set_host())
    epsilon(end_of_authority, "/?#", set_host())
  }
  term_state(read_authority, set_host()) {
    read_next_char(read_authority, str)
    transition(start_host, '@', set_userinfo())
    transition(start_port, ':', set_host())
    epsilon(end_of_authority, "/?#", set_host())
  }
  state(start_host) {
    read_next_char(read_host, str)
    fsm_transition(read_ipv6_address(ps, ip_consumer), await_end_of_ipv6, '[')
  }
  term_state(read_host, set_host()) {
    read_next_char(read_host, str)
    transition(start_port, ':', set_host())
    epsilon(end_of_authority, "/?#", set_host())
  }
  state(start_port) {
    transition(read_port, decimal_chars, add_ascii<10>(port, ch))
  }
  term_state(read_port, consumer.port(port)) {
    transition(read_port, decimal_chars, add_ascii<10>(port, ch),
               pec::integer_overflow)
    epsilon(end_of_authority, "/?#", consumer.port(port))
  }
  term_state(end_of_authority) {
    transition(read_path, '/')
    transition(start_query, '?')
    transition(read_fragment, '#')
  }
  term_state(read_path, set_path()) {
    transition(read_path, path_char, str += ch)
    fsm_transition(read_uri_percent_encoded(ps, str), read_path, '%')
    transition(start_query, '?', set_path())
    transition(read_fragment, '#', set_path())
  }
  term_state(start_query) {
    fsm_epsilon(read_uri_query(ps, consumer), end_of_query)
  }
  unstable_state(end_of_query) {
    transition(read_fragment, '#')
    epsilon(done)
  }
  term_state(read_fragment, consumer.fragment(take_str())) {
    read_next_char(read_fragment, str)
  }
  term_state(done) {
    // nop
  }
  fin();
}

} // namespace parser
} // namespace detail
} // namespace caf

#include "caf/detail/parser/fsm_undef.hpp"

CAF_POP_WARNINGS
<|endoftext|>


<commit_before><commit_msg>add a copy method to the AST<commit_after><|endoftext|>


<commit_before>#include "qhotkey.h"
#include "qhotkey_p.h"
#include <QDebug>
#include <QX11Info>
#include <QThreadStorage>
#include <X11/Xlib.h>
#include <xcb/xcb.h>

//compability to pre Qt 5.8
#ifndef Q_FALLTHROUGH
#define Q_FALLTHROUGH() (void)0
#endif

class QHotkeyPrivateX11 : public QHotkeyPrivate
{
public:
	// QAbstractNativeEventFilter interface
	bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;

protected:
	// QHotkeyPrivate interface
	quint32 nativeKeycode(Qt::Key keycode, bool &ok) Q_DECL_OVERRIDE;
	quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) Q_DECL_OVERRIDE;
	bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;
	bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;

private:
	static const QVector<quint32> specialModifiers;
	static const quint32 validModsMask;

	static QString formatX11Error(Display *display, int errorCode);

	class HotkeyErrorHandler {
	public:
		HotkeyErrorHandler();
		~HotkeyErrorHandler();

		static bool hasError;
		static QString errorString;

	private:
		XErrorHandler prevHandler;

		static int handleError(Display *display, XErrorEvent *error);
	};
};
NATIVE_INSTANCE(QHotkeyPrivateX11)

const QVector<quint32> QHotkeyPrivateX11::specialModifiers = {0, Mod2Mask, LockMask, (Mod2Mask | LockMask)};
const quint32 QHotkeyPrivateX11::validModsMask = ShiftMask | ControlMask | Mod1Mask | Mod4Mask;

bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
	Q_UNUSED(eventType);
	Q_UNUSED(result);

	xcb_generic_event_t *genericEvent = static_cast<xcb_generic_event_t *>(message);
	if (genericEvent->response_type == XCB_KEY_PRESS) {
		xcb_key_press_event_t *keyEvent = static_cast<xcb_key_press_event_t *>(message);
		this->activateShortcut({keyEvent->detail, keyEvent->state & QHotkeyPrivateX11::validModsMask});
	}

	return false;
}

quint32 QHotkeyPrivateX11::nativeKeycode(Qt::Key keycode, bool &ok)
{
	KeySym keysym = XStringToKeysym(QKeySequence(keycode).toString(QKeySequence::NativeText).toLatin1().constData());
	if (keysym == NoSymbol) {
		//not found -> just use the key
		if(keycode <= 0xFFFF)
			keysym = keycode;
		else
			return 0;
	}

	Display *display = QX11Info::display();
	if(display) {
		auto res = XKeysymToKeycode(QX11Info::display(), keysym);
		if(res != 0)
			ok = true;
		return res;
	} else
		return 0;
}

quint32 QHotkeyPrivateX11::nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok)
{
	quint32 nMods = 0;
	if (modifiers & Qt::ShiftModifier)
		nMods |= ShiftMask;
	if (modifiers & Qt::ControlModifier)
		nMods |= ControlMask;
	if (modifiers & Qt::AltModifier)
		nMods |= Mod1Mask;
	if (modifiers & Qt::MetaModifier)
		nMods |= Mod4Mask;
	ok = true;
	return nMods;
}

bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut)
{
	Display *display = QX11Info::display();
	if(!display)
		return false;

	HotkeyErrorHandler errorHandler;
	for(quint32 specialMod : QHotkeyPrivateX11::specialModifiers) {
		XGrabKey(display,
				 shortcut.key,
				 shortcut.modifier | specialMod,
				 DefaultRootWindow(display),
				 True,
				 GrabModeAsync,
				 GrabModeAsync);
	}
	XSync(display, False);

	if(errorHandler.hasError) {
		qCWarning(logQHotkey) << "Failed to register hotkey. Error:"
							  << qPrintable(errorHandler.errorString);
		this->unregisterShortcut(shortcut);
		return false;
	} else
		return true;
}

bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut)
{
	Display *display = QX11Info::display();
	if(!display)
		return false;

	HotkeyErrorHandler errorHandler;
	for(quint32 specialMod : QHotkeyPrivateX11::specialModifiers) {
		XUngrabKey(display,
				   shortcut.key,
				   shortcut.modifier | specialMod,
				   DefaultRootWindow(display));
	}
	XSync(display, False);

	if(errorHandler.hasError) {
		qCWarning(logQHotkey) << "Failed to unregister hotkey. Error:"
							  << qPrintable(errorHandler.errorString);
		return false;
	} else
		return true;
}

QString QHotkeyPrivateX11::formatX11Error(Display *display, int errorCode)
{
	char errStr[256];
	XGetErrorText(display, errorCode, errStr, 256);
	return QString::fromLatin1(errStr);
}

// ---------- QHotkeyPrivateX11::HotkeyErrorHandler implementation ----------

bool QHotkeyPrivateX11::HotkeyErrorHandler::hasError = false;
QString QHotkeyPrivateX11::HotkeyErrorHandler::errorString;

QHotkeyPrivateX11::HotkeyErrorHandler::HotkeyErrorHandler()
{
	prevHandler = XSetErrorHandler(&HotkeyErrorHandler::handleError);
}

QHotkeyPrivateX11::HotkeyErrorHandler::~HotkeyErrorHandler()
{
	XSetErrorHandler(prevHandler);
	hasError = false;
	errorString.clear();
}

int QHotkeyPrivateX11::HotkeyErrorHandler::handleError(Display *display, XErrorEvent *error)
{
	switch (error->error_code) {
	case BadAccess:
	case BadValue:
	case BadWindow:
		if (error->request_code == 33 || //grab key
			error->request_code == 34) {// ungrab key
			hasError = true;
			errorString = QHotkeyPrivateX11::formatX11Error(display, error->error_code);
			return 1;
		}
		Q_FALLTHROUGH();
		// fall through
	default:
		return 0;
	}
}
<commit_msg>X11 Media Key Support<commit_after>#include "qhotkey.h"
#include "qhotkey_p.h"
#include <QDebug>
#include <QX11Info>
#include <QThreadStorage>
#include <X11/Xlib.h>
#include <xcb/xcb.h>

//compability to pre Qt 5.8
#ifndef Q_FALLTHROUGH
#define Q_FALLTHROUGH() (void)0
#endif

class QHotkeyPrivateX11 : public QHotkeyPrivate
{
public:
	// QAbstractNativeEventFilter interface
	bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) Q_DECL_OVERRIDE;

protected:
	// QHotkeyPrivate interface
	quint32 nativeKeycode(Qt::Key keycode, bool &ok) Q_DECL_OVERRIDE;
	quint32 nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok) Q_DECL_OVERRIDE;
	QString getX11String(Qt::Key keycode);
	bool registerShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;
	bool unregisterShortcut(QHotkey::NativeShortcut shortcut) Q_DECL_OVERRIDE;

private:
	static const QVector<quint32> specialModifiers;
	static const quint32 validModsMask;

	static QString formatX11Error(Display *display, int errorCode);

	class HotkeyErrorHandler {
	public:
		HotkeyErrorHandler();
		~HotkeyErrorHandler();

		static bool hasError;
		static QString errorString;

	private:
		XErrorHandler prevHandler;

		static int handleError(Display *display, XErrorEvent *error);
	};
};
NATIVE_INSTANCE(QHotkeyPrivateX11)

const QVector<quint32> QHotkeyPrivateX11::specialModifiers = {0, Mod2Mask, LockMask, (Mod2Mask | LockMask)};
const quint32 QHotkeyPrivateX11::validModsMask = ShiftMask | ControlMask | Mod1Mask | Mod4Mask;

bool QHotkeyPrivateX11::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
	Q_UNUSED(eventType);
	Q_UNUSED(result);

	xcb_generic_event_t *genericEvent = static_cast<xcb_generic_event_t *>(message);
	if (genericEvent->response_type == XCB_KEY_PRESS) {
		xcb_key_press_event_t *keyEvent = static_cast<xcb_key_press_event_t *>(message);
		this->activateShortcut({keyEvent->detail, keyEvent->state & QHotkeyPrivateX11::validModsMask});
	}

	return false;
}

QString QHotkeyPrivateX11::getX11String(Qt::Key keycode)
{
	switch(keycode){

		case Qt::Key_MediaLast :
		case Qt::Key_MediaPrevious :
			return "XF86AudioPrev";
		case Qt::Key_MediaNext :
			return "XF86AudioNext";
		case Qt::Key_MediaPause :
		case Qt::Key_MediaPlay :
		case Qt::Key_MediaTogglePlayPause :
			return "XF86AudioPlay";
		case Qt::Key_MediaRecord :
			return "XF86AudioRecord";
		case Qt::Key_MediaStop :
			return "XF86AudioStop";
		default :
			return QKeySequence(keycode).toString(QKeySequence::NativeText);
	}
}

quint32 QHotkeyPrivateX11::nativeKeycode(Qt::Key keycode, bool &ok)
{
	QString keyString = getX11String(keycode);

	KeySym keysym = XStringToKeysym(keyString.toLatin1().constData());
	if (keysym == NoSymbol) {
		//not found -> just use the key
		if(keycode <= 0xFFFF)
			keysym = keycode;
		else
			return 0;
	}

	Display *display = QX11Info::display();
	if(display) {
		auto res = XKeysymToKeycode(QX11Info::display(), keysym);
		if(res != 0)
			ok = true;
		return res;
	} else
		return 0;
}

quint32 QHotkeyPrivateX11::nativeModifiers(Qt::KeyboardModifiers modifiers, bool &ok)
{
	quint32 nMods = 0;
	if (modifiers & Qt::ShiftModifier)
		nMods |= ShiftMask;
	if (modifiers & Qt::ControlModifier)
		nMods |= ControlMask;
	if (modifiers & Qt::AltModifier)
		nMods |= Mod1Mask;
	if (modifiers & Qt::MetaModifier)
		nMods |= Mod4Mask;
	ok = true;
	return nMods;
}

bool QHotkeyPrivateX11::registerShortcut(QHotkey::NativeShortcut shortcut)
{
	Display *display = QX11Info::display();
	if(!display)
		return false;

	HotkeyErrorHandler errorHandler;
	for(quint32 specialMod : QHotkeyPrivateX11::specialModifiers) {
		XGrabKey(display,
				 shortcut.key,
				 shortcut.modifier | specialMod,
				 DefaultRootWindow(display),
				 True,
				 GrabModeAsync,
				 GrabModeAsync);
	}
	XSync(display, False);

	if(errorHandler.hasError) {
		qCWarning(logQHotkey) << "Failed to register hotkey. Error:"
							  << qPrintable(errorHandler.errorString);
		this->unregisterShortcut(shortcut);
		return false;
	} else
		return true;
}

bool QHotkeyPrivateX11::unregisterShortcut(QHotkey::NativeShortcut shortcut)
{
	Display *display = QX11Info::display();
	if(!display)
		return false;

	HotkeyErrorHandler errorHandler;
	for(quint32 specialMod : QHotkeyPrivateX11::specialModifiers) {
		XUngrabKey(display,
				   shortcut.key,
				   shortcut.modifier | specialMod,
				   DefaultRootWindow(display));
	}
	XSync(display, False);

	if(errorHandler.hasError) {
		qCWarning(logQHotkey) << "Failed to unregister hotkey. Error:"
							  << qPrintable(errorHandler.errorString);
		return false;
	} else
		return true;
}

QString QHotkeyPrivateX11::formatX11Error(Display *display, int errorCode)
{
	char errStr[256];
	XGetErrorText(display, errorCode, errStr, 256);
	return QString::fromLatin1(errStr);
}

// ---------- QHotkeyPrivateX11::HotkeyErrorHandler implementation ----------

bool QHotkeyPrivateX11::HotkeyErrorHandler::hasError = false;
QString QHotkeyPrivateX11::HotkeyErrorHandler::errorString;

QHotkeyPrivateX11::HotkeyErrorHandler::HotkeyErrorHandler()
{
	prevHandler = XSetErrorHandler(&HotkeyErrorHandler::handleError);
}

QHotkeyPrivateX11::HotkeyErrorHandler::~HotkeyErrorHandler()
{
	XSetErrorHandler(prevHandler);
	hasError = false;
	errorString.clear();
}

int QHotkeyPrivateX11::HotkeyErrorHandler::handleError(Display *display, XErrorEvent *error)
{
	switch (error->error_code) {
	case BadAccess:
	case BadValue:
	case BadWindow:
		if (error->request_code == 33 || //grab key
			error->request_code == 34) {// ungrab key
			hasError = true;
			errorString = QHotkeyPrivateX11::formatX11Error(display, error->error_code);
			return 1;
		}
		Q_FALLTHROUGH();
		// fall through
	default:
		return 0;
	}
}
<|endoftext|>