<commit_before>//
//  CartridgePitfall2.h
//  Clock Signal
//
//  Created by Thomas Harte on 18/03/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#ifndef Atari2600_CartridgePitfall2_hpp
#define Atari2600_CartridgePitfall2_hpp

namespace Atari2600 {

class CartridgePitfall2: public Cartridge<CartridgePitfall2> {
	public:
		CartridgePitfall2(const std::vector<uint8_t> &rom) :
			Cartridge(rom),
			random_number_generator_(0),
			featcher_address_{0, 0, 0, 0, 0, 0, 0, 0},
			mask_{0, 0, 0, 0, 0, 0, 0, 0} {
			rom_ptr_ = rom_.data();
		}

		void perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value) {
			address &= 0x1fff;
			if(!(address & 0x1000)) return;

			switch(address) {

#pragma mark - Reads

				// The random number generator
				case 0x1000: case 0x1001: case 0x1002: case 0x1003: case 0x1004:
					if(isReadOperation(operation)) {
						*value = random_number_generator_;
					}
					random_number_generator_ = (uint8_t)(
						(random_number_generator_ << 1) |
						(~(	(random_number_generator_ >> 7) ^
							(random_number_generator_ >> 5) ^
							(random_number_generator_ >> 4) ^
							(random_number_generator_ >> 3)
						) & 1));
				break;

				// Music fetcher
				case 0x1005: case 0x1006: case 0x1007:
					*value = 0x00;
				break;

				case 0x1008: case 0x1009: case 0x100a: case 0x100b: case 0x100c: case 0x100d: case 0x100e: case 0x100f:
					*value = rom_[8192 + address_for_counter(address & 7)];
				break;

				case 0x1010: case 0x1011: case 0x1012: case 0x1013: case 0x1014: case 0x1015: case 0x1016: case 0x1017:
					*value = rom_[8192 + address_for_counter(address & 7)] & mask_[address & 7];
				break;

#pragma mark - Writes

				case 0x1040: case 0x1041: case 0x1042: case 0x1043: case 0x1044: case 0x1045: case 0x1046: case 0x1047:
					top_[address & 7] = *value;
				break;
				case 0x1048: case 0x1049: case 0x104a: case 0x104b: case 0x104c: case 0x104d: case 0x104e: case 0x104f:
					bottom_[address & 7] = *value;
				break;
				case 0x1050: case 0x1051: case 0x1052: case 0x1053: case 0x1054: case 0x1055: case 0x1056: case 0x1057:
					featcher_address_[address & 7] = (featcher_address_[address & 7] & 0xff00) | *value;
					mask_[address & 7] = 0x00;
				break;
				case 0x1058: case 0x1059: case 0x105a: case 0x105b: case 0x105c: case 0x105d: case 0x105e: case 0x105f:
					featcher_address_[address & 7] = (featcher_address_[address & 7] & 0x00ff) | (uint16_t)(*value << 8);
				break;
				case 0x1070: case 0x1071: case 0x1072: case 0x1073: case 0x1074: case 0x1075: case 0x1076: case 0x1077:
					random_number_generator_ = 0;
				break;

#pragma mark - Paging

				case 0x1ff8: rom_ptr_ = rom_.data();		break;
				case 0x1ff9: rom_ptr_ = rom_.data() + 4096;	break;

#pragma mark - Business as usual

				default:
					if(isReadOperation(operation)) {
						*value = rom_ptr_[address & 4095];
					}
				break;
			}
		}

	private:
		inline uint16_t address_for_counter(int counter) {
			uint16_t fetch_address = (featcher_address_[counter] & 2047) ^ 2047;
			if((featcher_address_[counter] & 0xff) == top_[counter]) mask_[counter] = 0xff;
			if((featcher_address_[counter] & 0xff) == bottom_[counter]) mask_[counter] = 0x00;
			featcher_address_[counter]--;
			return fetch_address;
		}

		uint16_t featcher_address_[8];
		uint8_t top_[8], bottom_[8], mask_[8];
		uint8_t music_mode_[3];
		uint8_t random_number_generator_;
		uint8_t *rom_ptr_;
};

}

#endif /* Atari2600_CartridgePitfall2_hpp */
<commit_msg>Made a first, hacky, attempt at audio.<commit_after>//
//  CartridgePitfall2.h
//  Clock Signal
//
//  Created by Thomas Harte on 18/03/2017.
//  Copyright © 2017 Thomas Harte. All rights reserved.
//

#ifndef Atari2600_CartridgePitfall2_hpp
#define Atari2600_CartridgePitfall2_hpp

namespace Atari2600 {

class CartridgePitfall2: public Cartridge<CartridgePitfall2> {
	public:
		CartridgePitfall2(const std::vector<uint8_t> &rom) :
			Cartridge(rom),
			random_number_generator_(0),
			featcher_address_{0, 0, 0, 0, 0, 0, 0, 0},
			mask_{0, 0, 0, 0, 0, 0, 0, 0},
			cycles_since_audio_update_(0) {
			rom_ptr_ = rom_.data();
		}

		void perform_bus_operation(CPU6502::BusOperation operation, uint16_t address, uint8_t *value) {
			cycles_since_audio_update_++;
			address &= 0x1fff;
			if(!(address & 0x1000)) return;

			switch(address) {

#pragma mark - Reads

				// The random number generator
				case 0x1000: case 0x1001: case 0x1002: case 0x1003: case 0x1004:
					if(isReadOperation(operation)) {
						*value = random_number_generator_;
					}
					random_number_generator_ = (uint8_t)(
						(random_number_generator_ << 1) |
						(~(	(random_number_generator_ >> 7) ^
							(random_number_generator_ >> 5) ^
							(random_number_generator_ >> 4) ^
							(random_number_generator_ >> 3)
						) & 1));
				break;

				case 0x1005: case 0x1006: case 0x1007:
					*value = update_audio();
					printf("%01x ", *value);
				break;

				case 0x1008: case 0x1009: case 0x100a: case 0x100b: case 0x100c: case 0x100d: case 0x100e: case 0x100f:
					*value = rom_[8192 + address_for_counter(address & 7)];
				break;

				case 0x1010: case 0x1011: case 0x1012: case 0x1013: case 0x1014: case 0x1015: case 0x1016: case 0x1017:
					*value = rom_[8192 + address_for_counter(address & 7)] & mask_[address & 7];
				break;

#pragma mark - Writes

				case 0x1040: case 0x1041: case 0x1042: case 0x1043: case 0x1044: case 0x1045: case 0x1046: case 0x1047:
					top_[address & 7] = *value;
				break;
				case 0x1048: case 0x1049: case 0x104a: case 0x104b: case 0x104c: case 0x104d: case 0x104e: case 0x104f:
					bottom_[address & 7] = *value;
				break;
				case 0x1050: case 0x1051: case 0x1052: case 0x1053: case 0x1054: case 0x1055: case 0x1056: case 0x1057:
					featcher_address_[address & 7] = (featcher_address_[address & 7] & 0xff00) | *value;
					mask_[address & 7] = 0x00;
				break;
				case 0x1058: case 0x1059: case 0x105a: case 0x105b: case 0x105c: case 0x105d: case 0x105e: case 0x105f:
					featcher_address_[address & 7] = (featcher_address_[address & 7] & 0x00ff) | (uint16_t)(*value << 8);
				break;
				case 0x1070: case 0x1071: case 0x1072: case 0x1073: case 0x1074: case 0x1075: case 0x1076: case 0x1077:
					random_number_generator_ = 0;
				break;

#pragma mark - Paging

				case 0x1ff8: rom_ptr_ = rom_.data();		break;
				case 0x1ff9: rom_ptr_ = rom_.data() + 4096;	break;

#pragma mark - Business as usual

				default:
					if(isReadOperation(operation)) {
						*value = rom_ptr_[address & 4095];
					}
				break;
			}
		}

	private:
		inline uint16_t address_for_counter(int counter) {
			uint16_t fetch_address = (featcher_address_[counter] & 2047) ^ 2047;
			if((featcher_address_[counter] & 0xff) == top_[counter]) mask_[counter] = 0xff;
			if((featcher_address_[counter] & 0xff) == bottom_[counter]) mask_[counter] = 0x00;
			featcher_address_[counter]--;
			return fetch_address;
		}

		inline uint8_t update_audio() {
			unsigned int cycles_to_run_for = cycles_since_audio_update_ / 57;
			cycles_since_audio_update_ %= 57;

			int table_position = 0;
			for(int c = 0; c < 3; c++) {
				audio_channel_[c] = (audio_channel_[c] + cycles_to_run_for) % (top_[5 + c] ^ 0xff);
				if((featcher_address_[5 + c] & 0x1000) && ((audio_channel_[c] ^ 0xff) > bottom_[5 + c])) {
					table_position |= 0x4 >> c;
				}
			}

			static uint8_t level_table[8] = { 0x0, 0x4, 0x5, 0x9, 0x6, 0xa, 0xb, 0xf };
			return level_table[table_position];
		}

		uint16_t featcher_address_[8];
		uint8_t top_[8], bottom_[8], mask_[8];
		uint8_t music_mode_[3];
		uint8_t random_number_generator_;
		uint8_t *rom_ptr_;
		uint8_t audio_channel_[3];
		unsigned int cycles_since_audio_update_;
};

}

#endif /* Atari2600_CartridgePitfall2_hpp */
<|endoftext|>


<commit_before>// Copyright ***********************************************************
//
// File ecmdDllCapi.C
//
// IBM Confidential
// OCO Source Materials
// 9400 Licensed Internal Code
// (C) COPYRIGHT IBM CORP. 1996
//
// The source code for this program is not published or otherwise
// divested of its trade secrets, irrespective of what has been
// deposited with the U.S. Copyright Office.
//
// End Copyright *******************************************************

// Module Description **************************************************
//
// Description:
//
// End Module Description **********************************************

//----------------------------------------------------------------------
//  Includes
//----------------------------------------------------------------------
#define ecmdDllCapi_C
#include <stdio.h>
#include <list>

#include "ecmdDllCapi.H"

#undef ecmdDllCapi_C
//----------------------------------------------------------------------
//  User Types
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Constants
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Macros
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Internal Function Prototypes
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Global Variables
//----------------------------------------------------------------------
list<ecmdError> ecmdErrorList;

//---------------------------------------------------------------------
// Member Function Specifications
//---------------------------------------------------------------------

int dllLoadDll (const char* i_clientVersion) {

  /* First off let's check our version */
  if (strcmp(i_clientVersion,ECMD_CAPI_VERSION)) {
    fprintf(stderr,"**** FATAL : eCMD DLL and your client are not compatible\n");
    fprintf(stderr,"**** FATAL : Client Version : %s   : DLL Version : %s\n",i_clientVersion, ECMD_CAPI_VERSION);
/*
    if (version < DLL_VERSION)
      fprintf(stderr,"**** FATAL : You must rebuild your client to continue\n");
    else
      fprintf(stderr,"**** FATAL : Contact the Cronus team to have the DLL rebuilt to match your client to continue\n");
*/
    exit(999);
  }

  return dllInitDll();

}

int dllUnloadDll() {
  int rc = 0;

  rc = dllFreeDll();

  return rc;
}

std::string dllGetErrorMsg(int i_errorCode) {
  std::string ret = "UNKNOWN";
  list<ecmdError>::iterator cur;

  for (cur = ecmdErrorList.begin(); cur != ecmdErrorList.end(); cur++) {
    if ( (*cur).errorCode == i_errorCode ) {
      ret = (*cur).whom + ": " + (*cur).message;
      break;
    }
  }

  return ret;
}

int dllRegisterErrorMsg(int i_errorCode, const char* i_whom, const char* i_message) {
  int rc = ECMD_SUCCESS;

  ecmdError curError;
  curError.errorCode = i_errorCode;
  curError.whom = i_whom;
  curError.message = i_message;

  ecmdErrorList.push_back(curError);

  return rc;
}

int dllQuerySelected(ecmdChipTarget & i_target, std::vector<ecmdCageData> & o_queryData) {
  int rc = ECMD_SUCCESS;

  return rc;
}

int dllCommonCommandArgs(int*  io_argc, char** io_argv[]) {
  int rc = ECMD_SUCCESS;

  /* We need to pull out the targeting options here */

  /* Call the dllSpecificFunction */
  rc = dllSpecificCommandArgs(io_argc,io_argv);

  return rc;
}

// Change Log *********************************************************
//
//  Flag Reason   Vers Date     Coder    Description
//  ---- -------- ---- -------- -------- ------------------------------
//                              CENGEL   Initial Creation
//
// End Change Log *****************************************************
<commit_msg>added error code lookup stuff to ecmdGetErrorMsg<commit_after>// Copyright ***********************************************************
//
// File ecmdDllCapi.C
//
// IBM Confidential
// OCO Source Materials
// 9400 Licensed Internal Code
// (C) COPYRIGHT IBM CORP. 1996
//
// The source code for this program is not published or otherwise
// divested of its trade secrets, irrespective of what has been
// deposited with the U.S. Copyright Office.
//
// End Copyright *******************************************************

// Module Description **************************************************
//
// Description:
//
// End Module Description **********************************************

//----------------------------------------------------------------------
//  Includes
//----------------------------------------------------------------------
#define ecmdDllCapi_C
#include <stdio.h>
#include <list>
#include <fstream>
#include <string.h>
#include <stdlib.h>

#include "ecmdDllCapi.H"

#undef ecmdDllCapi_C
//----------------------------------------------------------------------
//  User Types
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Constants
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Macros
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Internal Function Prototypes
//----------------------------------------------------------------------

//----------------------------------------------------------------------
//  Global Variables
//----------------------------------------------------------------------
list<ecmdError> ecmdErrorList;

//---------------------------------------------------------------------
// Member Function Specifications
//---------------------------------------------------------------------

int dllLoadDll (const char* i_clientVersion) {

  /* First off let's check our version */
  if (strcmp(i_clientVersion,ECMD_CAPI_VERSION)) {
    fprintf(stderr,"**** FATAL : eCMD DLL and your client are not compatible\n");
    fprintf(stderr,"**** FATAL : Client Version : %s   : DLL Version : %s\n",i_clientVersion, ECMD_CAPI_VERSION);
/*
    if (version < DLL_VERSION)
      fprintf(stderr,"**** FATAL : You must rebuild your client to continue\n");
    else
      fprintf(stderr,"**** FATAL : Contact the Cronus team to have the DLL rebuilt to match your client to continue\n");
*/
    exit(999);
  }

  return dllInitDll();

}

int dllUnloadDll() {
  int rc = 0;

  rc = dllFreeDll();

  return rc;
}

std::string dllGetErrorMsg(int i_errorCode) {
  std::string ret;
  list<ecmdError>::iterator cur;

  for (cur = ecmdErrorList.begin(); cur != ecmdErrorList.end(); cur++) {
    if ( (*cur).errorCode == i_errorCode ) {
      ret = (*cur).whom + ": " + (*cur).message + " ";
      break;
    }
  }

  ecmdChipTarget dummy;
  std::string filePath;
  int rc = ecmdQueryFileLocation(dummy, ECMD_FILE_HELPTEXT, filePath);

  if (rc) {
    ret = "ERROR FINDING DECODE FILE";
    return ret;
  }

  /* jtw 10/6/03 - code below largely copied from cronusrc.c */
  char str[800];
  char num[30];
  char name[200];
  int found = 0;
  char* tempstr = NULL;

  ifstream ins(filePath.c_str());

  if (ins.fail()) {
    ret = "ERROR OPENING DECODE FILE";
    return ret;
  }

  while (!ins.eof()) { /*  && (strlen(str) != 0) */
    ins.getline(str,799,'\n');
    if (!strncmp(str,"#define",7)) {
      strtok(str," \t");        /* get rid of the #define */
      tempstr = strtok(NULL," \t");
      if (tempstr == NULL) continue;
      strcpy(name,tempstr);
      tempstr = strtok(NULL," \t");
      if (tempstr == NULL) continue;
      strcpy(num,tempstr);
      if (atol(num) == rc) {
        ret += name;
        found = 1;
        break;
      }
    }
  }

  ins.close();

  if (!found) {
    ret += "UNDEFINED";
  }

  return ret;
}

int dllRegisterErrorMsg(int i_errorCode, const char* i_whom, const char* i_message) {
  int rc = ECMD_SUCCESS;

  ecmdError curError;
  curError.errorCode = i_errorCode;
  curError.whom = i_whom;
  curError.message = i_message;

  ecmdErrorList.push_back(curError);

  return rc;
}

int dllQuerySelected(ecmdChipTarget & i_target, std::vector<ecmdCageData> & o_queryData) {
  int rc = ECMD_SUCCESS;

  return rc;
}

int dllCommonCommandArgs(int*  io_argc, char** io_argv[]) {
  int rc = ECMD_SUCCESS;

  /* We need to pull out the targeting options here */

  /* Call the dllSpecificFunction */
  rc = dllSpecificCommandArgs(io_argc,io_argv);

  return rc;
}

// Change Log *********************************************************
//
//  Flag Reason   Vers Date     Coder    Description
//  ---- -------- ---- -------- -------- ------------------------------
//                              CENGEL   Initial Creation
//
// End Change Log *****************************************************
<|endoftext|>


<commit_before>#include "ROOMLOAD.H"

#include "CD.H"
#include "DRAW.H"
#include "FILE.H"
#include "GPU.H"
#include "LOAD_LEV.H"
#include "SETUP.H"
#include "TYPEDEFS.H"

#include <stdio.h>

#if !DISC_VERSION
	#include <LIBSN.H>
#endif

long AnimFilePos;
long AnimFileLen;
short* floor_data;
unsigned long* SetupPtr;
unsigned short ClutStartY;
struct SVECTOR* RoomBBoxes;
short* mesh_base;
struct PSXSPRITESTRUCT* GLOBAL_default_sprites_ptr;
struct PSXTEXTI* AnimatingWaterfalls[6];
int AnimatingWaterfallsV[6];
unsigned long envmap_data[6];
unsigned long* RelocPtr[128];

void ReloadAnims(int name, long len)//600E4(<), 60D20(<) (*) (?)
{
#if DISC_VERSION
	cdCurrentSector = AnimFilePos;
	DEL_CDFS_Read((char*) frames, len);
#else
	int file;
	char buf[80];

	strcpy(buf, &gfFilenameWad[gfFilenameOffset[name]]);
	strcat(buf, ".PSX");
	file = PCopen(buf, 0, 0);

	PClseek(file, AnimFilePos, 0);
	FILE_Read((char*) frames, 1, len, file);

	PCclose(file);
#endif

	return;
}

void S_LoadLevelFile(int Name)//60188(<), 60D54(<) (F)
{
	char buf[80];
	unsigned long* mod;
	int len;
	int file;

#if DISC_VERSION
	//TITLE is the base file entry index for levels, simply as a result, we must add gameflow level id to this.
	DEL_CDFS_OpenFile(Name + TITLE);
#endif

	DrawSync(0);

	init_game_malloc();

	LOAD_Start(Name + TITLE);

	SetupPtr = &db.poly_buffer[0][1026];
	mod = &db.poly_buffer[0][1024];

#if DISC_VERSION
	DEL_CDFS_Read((char*) mod, gwHeader.entries[NONE].fileSize);//jal 5E414
#else
	len = FILE_Length("DATA\\SETUP.MOD");
	file = PCopen("DATA\\SETUP.MOD", 0, 0);
	FILE_Read((char*)mod, 1, len, file);

	PCclose(file);
#endif
	/*
	 *  SETUP.MOD
	 * Layout is:
	 * [SETUP.BIN]
	 * [SETUP.REL]
	 */
	RelocateModule((unsigned long)SetupPtr, (unsigned long*)(db.poly_buffer[0][1024] + (unsigned long)SetupPtr));

#if DISC_VERSION
	#if RELOC
		((VOIDFUNCVOID*)SetupPtr[5])();
	#else
		RelocateLevel();
	#endif
#else
	strcpy(&buf[0], &gfFilenameWad[gfFilenameOffset[Name]]);
	strcat(&buf[0], ".PSX");

	FILE_Length(buf);

	#if RELOC
		((VOIDFUNCINT*)SetupPtr[5])(PCopen(&buf[0], 0, 0));
	#else
	RelocateLevel(PCopen(buf, 0, 0));
	#endif
#endif

	LOAD_Stop();

	return;
}<commit_msg>Fix tab<commit_after>#include "ROOMLOAD.H"

#include "CD.H"
#include "DRAW.H"
#include "FILE.H"
#include "GPU.H"
#include "LOAD_LEV.H"
#include "SETUP.H"
#include "TYPEDEFS.H"

#include <stdio.h>

#if !DISC_VERSION
	#include <LIBSN.H>
#endif

long AnimFilePos;
long AnimFileLen;
short* floor_data;
unsigned long* SetupPtr;
unsigned short ClutStartY;
struct SVECTOR* RoomBBoxes;
short* mesh_base;
struct PSXSPRITESTRUCT* GLOBAL_default_sprites_ptr;
struct PSXTEXTI* AnimatingWaterfalls[6];
int AnimatingWaterfallsV[6];
unsigned long envmap_data[6];
unsigned long* RelocPtr[128];

void ReloadAnims(int name, long len)//600E4(<), 60D20(<) (*) (?)
{
#if DISC_VERSION
	cdCurrentSector = AnimFilePos;
	DEL_CDFS_Read((char*) frames, len);
#else
	int file;
	char buf[80];

	strcpy(buf, &gfFilenameWad[gfFilenameOffset[name]]);
	strcat(buf, ".PSX");
	file = PCopen(buf, 0, 0);

	PClseek(file, AnimFilePos, 0);
	FILE_Read((char*) frames, 1, len, file);

	PCclose(file);
#endif

	return;
}

void S_LoadLevelFile(int Name)//60188(<), 60D54(<) (F)
{
	char buf[80];
	unsigned long* mod;
	int len;
	int file;

#if DISC_VERSION
	//TITLE is the base file entry index for levels, simply as a result, we must add gameflow level id to this.
	DEL_CDFS_OpenFile(Name + TITLE);
#endif

	DrawSync(0);

	init_game_malloc();

	LOAD_Start(Name + TITLE);

	SetupPtr = &db.poly_buffer[0][1026];
	mod = &db.poly_buffer[0][1024];

#if DISC_VERSION
	DEL_CDFS_Read((char*) mod, gwHeader.entries[NONE].fileSize);//jal 5E414
#else
	len = FILE_Length("DATA\\SETUP.MOD");
	file = PCopen("DATA\\SETUP.MOD", 0, 0);
	FILE_Read((char*)mod, 1, len, file);

	PCclose(file);
#endif
	/*
	 *  SETUP.MOD
	 * Layout is:
	 * [SETUP.BIN]
	 * [SETUP.REL]
	 */
	RelocateModule((unsigned long)SetupPtr, (unsigned long*)(db.poly_buffer[0][1024] + (unsigned long)SetupPtr));

#if DISC_VERSION
	#if RELOC
		((VOIDFUNCVOID*)SetupPtr[5])();
	#else
		RelocateLevel();
	#endif
#else
	strcpy(&buf[0], &gfFilenameWad[gfFilenameOffset[Name]]);
	strcat(&buf[0], ".PSX");

	FILE_Length(buf);

	#if RELOC
		((VOIDFUNCINT*)SetupPtr[5])(PCopen(&buf[0], 0, 0));
	#else
		RelocateLevel(PCopen(buf, 0, 0));
	#endif
#endif

	LOAD_Stop();

	return;
}<|endoftext|>


<commit_before>#include "rpcconsole.h"
#include "ui_rpcconsole.h"

#include "clientmodel.h"
#include "bitcoinrpc.h"
#include "guiutil.h"

#include <QTime>
#include <QThread>
#include <QKeyEvent>
#if QT_VERSION < 0x050000
#include <QUrl>
#endif
#include <QScrollBar>

#include <openssl/crypto.h>

// TODO: add a scrollback limit, as there is currently none
// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel

const int CONSOLE_HISTORY = 50;
const QSize ICON_SIZE(24, 24);

const struct {
    const char *url;
    const char *source;
} ICON_MAPPING[] = {
    {"cmd-request", ":/icons/tx_input"},
    {"cmd-reply", ":/icons/tx_output"},
    {"cmd-error", ":/icons/tx_output"},
    {"misc", ":/icons/tx_inout"},
    {NULL, NULL}
};

/* Object for executing console RPC commands in a separate thread.
*/
class RPCExecutor : public QObject
{
    Q_OBJECT

public slots:
    void request(const QString &command);

signals:
    void reply(int category, const QString &command);
};

#include "rpcconsole.moc"

/**
 * Split shell command line into a list of arguments. Aims to emulate \c bash and friends.
 *
 * - Arguments are delimited with whitespace
 * - Extra whitespace at the beginning and end and between arguments will be ignored
 * - Text can be "double" or 'single' quoted
 * - The backslash \c \ is used as escape character
 *   - Outside quotes, any character can be escaped
 *   - Within double quotes, only escape \c " and backslashes before a \c " or another backslash
 *   - Within single quotes, no escaping is possible and no special interpretation takes place
 *
 * @param[out]   args        Parsed arguments will be appended to this list
 * @param[in]    strCommand  Command line to split
 */
bool parseCommandLine(std::vector<std::string> &args, const std::string &strCommand)
{
    enum CmdParseState
    {
        STATE_EATING_SPACES,
        STATE_ARGUMENT,
        STATE_SINGLEQUOTED,
        STATE_DOUBLEQUOTED,
        STATE_ESCAPE_OUTER,
        STATE_ESCAPE_DOUBLEQUOTED
    } state = STATE_EATING_SPACES;
    std::string curarg;
    foreach(char ch, strCommand)
    {
        switch(state)
        {
        case STATE_ARGUMENT: // In or after argument
        case STATE_EATING_SPACES: // Handle runs of whitespace
            switch(ch)
            {
            case '"': state = STATE_DOUBLEQUOTED; break;
            case '\'': state = STATE_SINGLEQUOTED; break;
            case '\\': state = STATE_ESCAPE_OUTER; break;
            case ' ': case '\n': case '\t':
                if(state == STATE_ARGUMENT) // Space ends argument
                {
                    args.push_back(curarg);
                    curarg.clear();
                }
                state = STATE_EATING_SPACES;
                break;
            default: curarg += ch; state = STATE_ARGUMENT;
            }
            break;
        case STATE_SINGLEQUOTED: // Single-quoted string
            switch(ch)
            {
            case '\'': state = STATE_ARGUMENT; break;
            default: curarg += ch;
            }
            break;
        case STATE_DOUBLEQUOTED: // Double-quoted string
            switch(ch)
            {
            case '"': state = STATE_ARGUMENT; break;
            case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
            default: curarg += ch;
            }
            break;
        case STATE_ESCAPE_OUTER: // '\' outside quotes
            curarg += ch; state = STATE_ARGUMENT;
            break;
        case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
            if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
            curarg += ch; state = STATE_DOUBLEQUOTED;
            break;
        }
    }
    switch(state) // final state
    {
    case STATE_EATING_SPACES:
        return true;
    case STATE_ARGUMENT:
        args.push_back(curarg);
        return true;
    default: // ERROR to end in one of the other states
        return false;
    }
}

void RPCExecutor::request(const QString &command)
{
    std::vector<std::string> args;
    if(!parseCommandLine(args, command.toStdString()))
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
        return;
    }
    if(args.empty())
        return; // Nothing to do
    try
    {
        std::string strPrint;
        // Convert argument list to JSON objects in method-dependent way,
        // and pass it along with the method name to the dispatcher.
        json_spirit::Value result = tableRPC.execute(
            args[0],
            RPCConvertValues(args[0], std::vector<std::string>(args.begin() + 1, args.end())));

        // Format result reply
        if (result.type() == json_spirit::null_type)
            strPrint = "";
        else if (result.type() == json_spirit::str_type)
            strPrint = result.get_str();
        else
            strPrint = write_string(result, true);

        emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
    }
    catch (json_spirit::Object& objError)
    {
        try // Nice formatting for standard-format error
        {
            int code = find_value(objError, "code").get_int();
            std::string message = find_value(objError, "message").get_str();
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
        }
        catch(std::runtime_error &) // raised when converting to invalid type, i.e. missing code or message
        {   // Show raw JSON object
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
        }
    }
    catch (std::exception& e)
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

RPCConsole::RPCConsole(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RPCConsole),
    clientModel(0),
    historyPtr(0)
{
    ui->setupUi(this);

#ifndef Q_OS_MAC
    ui->openDebugLogfileButton->setIcon(QIcon(":/icons/export"));
    ui->showCLOptionsButton->setIcon(QIcon(":/icons/options"));
#endif

    // Install event filter for up and down arrow
    ui->lineEdit->installEventFilter(this);
    ui->messagesWidget->installEventFilter(this);

    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));

    // set OpenSSL version label
    ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));

    startExecutor();

    clear();
}

RPCConsole::~RPCConsole()
{
    emit stopExecutor();
    delete ui;
}

bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
{
    if(event->type() == QEvent::KeyPress) // Special key handling
    {
        QKeyEvent *keyevt = static_cast<QKeyEvent*>(event);
        int key = keyevt->key();
        Qt::KeyboardModifiers mod = keyevt->modifiers();
        switch(key)
        {
        case Qt::Key_Up: if(obj == ui->lineEdit) { browseHistory(-1); return true; } break;
        case Qt::Key_Down: if(obj == ui->lineEdit) { browseHistory(1); return true; } break;
        case Qt::Key_PageUp: /* pass paging keys to messages widget */
        case Qt::Key_PageDown:
            if(obj == ui->lineEdit)
            {
                QApplication::postEvent(ui->messagesWidget, new QKeyEvent(*keyevt));
                return true;
            }
            break;
        default:
            // Typing in messages widget brings focus to line edit, and redirects key there
            // Exclude most combinations and keys that emit no text, except paste shortcuts
            if(obj == ui->messagesWidget && (
                  (!mod && !keyevt->text().isEmpty() && key != Qt::Key_Tab) ||
                  ((mod & Qt::ControlModifier) && key == Qt::Key_V) ||
                  ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert)))
            {
                ui->lineEdit->setFocus();
                QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
                return true;
            }
        }
    }
    return QDialog::eventFilter(obj, event);
}

void RPCConsole::setClientModel(ClientModel *model)
{
    this->clientModel = model;
    if(model)
    {
        // Subscribe to information, replies, messages, errors
        connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
        connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));

        // Provide initial values
        ui->clientVersion->setText(model->formatFullVersion());
        ui->clientName->setText(model->clientName());
        ui->buildDate->setText(model->formatBuildDate());
        ui->startupTime->setText(model->formatClientStartupTime());

        setNumConnections(model->getNumConnections());
        ui->isTestNet->setChecked(model->isTestNet());
    }
}

static QString categoryClass(int category)
{
    switch(category)
    {
    case RPCConsole::CMD_REQUEST:  return "cmd-request"; break;
    case RPCConsole::CMD_REPLY:    return "cmd-reply"; break;
    case RPCConsole::CMD_ERROR:    return "cmd-error"; break;
    default:                       return "misc";
    }
}

void RPCConsole::clear()
{
    ui->messagesWidget->clear();
    history.clear();
    historyPtr = 0;
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();

    // Add smoothly scaled icon images.
    // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
    for(int i=0; ICON_MAPPING[i].url; ++i)
    {
        ui->messagesWidget->document()->addResource(
                    QTextDocument::ImageResource,
                    QUrl(ICON_MAPPING[i].url),
                    QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    }

    // Set default style sheet
    ui->messagesWidget->document()->setDefaultStyleSheet(
                "table { }"
                "td.time { color: #808080; padding-top: 3px; } "
                "td.message { font-family: Monospace; font-size: 12px; } "
                "td.cmd-request { color: #006060; } "
                "td.cmd-error { color: red; } "
                "b { color: #006060; } "
                );

    message(CMD_REPLY, (tr("Welcome to the Bitcoin RPC console.") + "
" +
                        tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.") + "
" +
                        tr("Type help for an overview of available commands.")), true);
}

void RPCConsole::message(int category, const QString &message, bool html)
{
    QTime time = QTime::currentTime();
    QString timeString = time.toString();
    QString out;
    out += "

" + timeString + "	";
    out += "	";
    out += "";
    if(html)
        out += message;
    else
        out += GUIUtil::HtmlEscape(message, true);
    out += "

";
    ui->messagesWidget->append(out);
}

void RPCConsole::setNumConnections(int count)
{
    ui->numberOfConnections->setText(QString::number(count));
}

void RPCConsole::setNumBlocks(int count, int countOfPeers)
{
    ui->numberOfBlocks->setText(QString::number(count));
    // If there is no current countOfPeers available display N/A instead of 0, which can't ever be true
    ui->totalBlocks->setText(countOfPeers == 0 ? tr("N/A") : QString::number(countOfPeers));
    if(clientModel)
        ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
}

void RPCConsole::on_lineEdit_returnPressed()
{
    QString cmd = ui->lineEdit->text();
    ui->lineEdit->clear();

    if(!cmd.isEmpty())
    {
        message(CMD_REQUEST, cmd);
        emit cmdRequest(cmd);
        // Truncate history from current position
        history.erase(history.begin() + historyPtr, history.end());
        // Append command to history
        history.append(cmd);
        // Enforce maximum history size
        while(history.size() > CONSOLE_HISTORY)
            history.removeFirst();
        // Set pointer to end of history
        historyPtr = history.size();
        // Scroll console view to end
        scrollToEnd();
    }
}

void RPCConsole::browseHistory(int offset)
{
    historyPtr += offset;
    if(historyPtr < 0)
        historyPtr = 0;
    if(historyPtr > history.size())
        historyPtr = history.size();
    QString cmd;
    if(historyPtr < history.size())
        cmd = history.at(historyPtr);
    ui->lineEdit->setText(cmd);
}

void RPCConsole::startExecutor()
{
    QThread *thread = new QThread;
    RPCExecutor *executor = new RPCExecutor();
    executor->moveToThread(thread);

    // Replies from executor object must go to this object
    connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
    // Requests from this object must go to executor
    connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));

    // On stopExecutor signal
    // - queue executor for deletion (in execution thread)
    // - quit the Qt event loop in the execution thread
    connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
    // Queue the thread for deletion (in this thread) when it is finished
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    // Default implementation of QThread::run() simply spins up an event loop in the thread,
    // which is what we want.
    thread->start();
}

void RPCConsole::on_tabWidget_currentChanged(int index)
{
    if(ui->tabWidget->widget(index) == ui->tab_console)
    {
        ui->lineEdit->setFocus();
    }
}

void RPCConsole::on_openDebugLogfileButton_clicked()
{
    GUIUtil::openDebugLogfile();
}

void RPCConsole::scrollToEnd()
{
    QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
    scrollbar->setValue(scrollbar->maximum());
}

void RPCConsole::on_showCLOptionsButton_clicked()
{
    GUIUtil::HelpMessageBox help;
    help.exec();
}
<commit_msg>Bitcoin-Qt: harmonize 2 setClientModel() functions<commit_after>#include "rpcconsole.h"
#include "ui_rpcconsole.h"

#include "clientmodel.h"
#include "bitcoinrpc.h"
#include "guiutil.h"

#include <QTime>
#include <QThread>
#include <QKeyEvent>
#if QT_VERSION < 0x050000
#include <QUrl>
#endif
#include <QScrollBar>

#include <openssl/crypto.h>

// TODO: add a scrollback limit, as there is currently none
// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel

const int CONSOLE_HISTORY = 50;
const QSize ICON_SIZE(24, 24);

const struct {
    const char *url;
    const char *source;
} ICON_MAPPING[] = {
    {"cmd-request", ":/icons/tx_input"},
    {"cmd-reply", ":/icons/tx_output"},
    {"cmd-error", ":/icons/tx_output"},
    {"misc", ":/icons/tx_inout"},
    {NULL, NULL}
};

/* Object for executing console RPC commands in a separate thread.
*/
class RPCExecutor : public QObject
{
    Q_OBJECT

public slots:
    void request(const QString &command);

signals:
    void reply(int category, const QString &command);
};

#include "rpcconsole.moc"

/**
 * Split shell command line into a list of arguments. Aims to emulate \c bash and friends.
 *
 * - Arguments are delimited with whitespace
 * - Extra whitespace at the beginning and end and between arguments will be ignored
 * - Text can be "double" or 'single' quoted
 * - The backslash \c \ is used as escape character
 *   - Outside quotes, any character can be escaped
 *   - Within double quotes, only escape \c " and backslashes before a \c " or another backslash
 *   - Within single quotes, no escaping is possible and no special interpretation takes place
 *
 * @param[out]   args        Parsed arguments will be appended to this list
 * @param[in]    strCommand  Command line to split
 */
bool parseCommandLine(std::vector<std::string> &args, const std::string &strCommand)
{
    enum CmdParseState
    {
        STATE_EATING_SPACES,
        STATE_ARGUMENT,
        STATE_SINGLEQUOTED,
        STATE_DOUBLEQUOTED,
        STATE_ESCAPE_OUTER,
        STATE_ESCAPE_DOUBLEQUOTED
    } state = STATE_EATING_SPACES;
    std::string curarg;
    foreach(char ch, strCommand)
    {
        switch(state)
        {
        case STATE_ARGUMENT: // In or after argument
        case STATE_EATING_SPACES: // Handle runs of whitespace
            switch(ch)
            {
            case '"': state = STATE_DOUBLEQUOTED; break;
            case '\'': state = STATE_SINGLEQUOTED; break;
            case '\\': state = STATE_ESCAPE_OUTER; break;
            case ' ': case '\n': case '\t':
                if(state == STATE_ARGUMENT) // Space ends argument
                {
                    args.push_back(curarg);
                    curarg.clear();
                }
                state = STATE_EATING_SPACES;
                break;
            default: curarg += ch; state = STATE_ARGUMENT;
            }
            break;
        case STATE_SINGLEQUOTED: // Single-quoted string
            switch(ch)
            {
            case '\'': state = STATE_ARGUMENT; break;
            default: curarg += ch;
            }
            break;
        case STATE_DOUBLEQUOTED: // Double-quoted string
            switch(ch)
            {
            case '"': state = STATE_ARGUMENT; break;
            case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
            default: curarg += ch;
            }
            break;
        case STATE_ESCAPE_OUTER: // '\' outside quotes
            curarg += ch; state = STATE_ARGUMENT;
            break;
        case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
            if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
            curarg += ch; state = STATE_DOUBLEQUOTED;
            break;
        }
    }
    switch(state) // final state
    {
    case STATE_EATING_SPACES:
        return true;
    case STATE_ARGUMENT:
        args.push_back(curarg);
        return true;
    default: // ERROR to end in one of the other states
        return false;
    }
}

void RPCExecutor::request(const QString &command)
{
    std::vector<std::string> args;
    if(!parseCommandLine(args, command.toStdString()))
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
        return;
    }
    if(args.empty())
        return; // Nothing to do
    try
    {
        std::string strPrint;
        // Convert argument list to JSON objects in method-dependent way,
        // and pass it along with the method name to the dispatcher.
        json_spirit::Value result = tableRPC.execute(
            args[0],
            RPCConvertValues(args[0], std::vector<std::string>(args.begin() + 1, args.end())));

        // Format result reply
        if (result.type() == json_spirit::null_type)
            strPrint = "";
        else if (result.type() == json_spirit::str_type)
            strPrint = result.get_str();
        else
            strPrint = write_string(result, true);

        emit reply(RPCConsole::CMD_REPLY, QString::fromStdString(strPrint));
    }
    catch (json_spirit::Object& objError)
    {
        try // Nice formatting for standard-format error
        {
            int code = find_value(objError, "code").get_int();
            std::string message = find_value(objError, "message").get_str();
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
        }
        catch(std::runtime_error &) // raised when converting to invalid type, i.e. missing code or message
        {   // Show raw JSON object
            emit reply(RPCConsole::CMD_ERROR, QString::fromStdString(write_string(json_spirit::Value(objError), false)));
        }
    }
    catch (std::exception& e)
    {
        emit reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
    }
}

RPCConsole::RPCConsole(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RPCConsole),
    clientModel(0),
    historyPtr(0)
{
    ui->setupUi(this);

#ifndef Q_OS_MAC
    ui->openDebugLogfileButton->setIcon(QIcon(":/icons/export"));
    ui->showCLOptionsButton->setIcon(QIcon(":/icons/options"));
#endif

    // Install event filter for up and down arrow
    ui->lineEdit->installEventFilter(this);
    ui->messagesWidget->installEventFilter(this);

    connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));

    // set OpenSSL version label
    ui->openSSLVersion->setText(SSLeay_version(SSLEAY_VERSION));

    startExecutor();

    clear();
}

RPCConsole::~RPCConsole()
{
    emit stopExecutor();
    delete ui;
}

bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
{
    if(event->type() == QEvent::KeyPress) // Special key handling
    {
        QKeyEvent *keyevt = static_cast<QKeyEvent*>(event);
        int key = keyevt->key();
        Qt::KeyboardModifiers mod = keyevt->modifiers();
        switch(key)
        {
        case Qt::Key_Up: if(obj == ui->lineEdit) { browseHistory(-1); return true; } break;
        case Qt::Key_Down: if(obj == ui->lineEdit) { browseHistory(1); return true; } break;
        case Qt::Key_PageUp: /* pass paging keys to messages widget */
        case Qt::Key_PageDown:
            if(obj == ui->lineEdit)
            {
                QApplication::postEvent(ui->messagesWidget, new QKeyEvent(*keyevt));
                return true;
            }
            break;
        default:
            // Typing in messages widget brings focus to line edit, and redirects key there
            // Exclude most combinations and keys that emit no text, except paste shortcuts
            if(obj == ui->messagesWidget && (
                  (!mod && !keyevt->text().isEmpty() && key != Qt::Key_Tab) ||
                  ((mod & Qt::ControlModifier) && key == Qt::Key_V) ||
                  ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert)))
            {
                ui->lineEdit->setFocus();
                QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
                return true;
            }
        }
    }
    return QDialog::eventFilter(obj, event);
}

void RPCConsole::setClientModel(ClientModel *model)
{
    this->clientModel = model;
    if(model)
    {
        // Keep up to date with client
        setNumConnections(model->getNumConnections());
        connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));

        setNumBlocks(model->getNumBlocks(), model->getNumBlocksOfPeers());
        connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));

        // Provide initial values
        ui->clientVersion->setText(model->formatFullVersion());
        ui->clientName->setText(model->clientName());
        ui->buildDate->setText(model->formatBuildDate());
        ui->startupTime->setText(model->formatClientStartupTime());

        ui->isTestNet->setChecked(model->isTestNet());
    }
}

static QString categoryClass(int category)
{
    switch(category)
    {
    case RPCConsole::CMD_REQUEST:  return "cmd-request"; break;
    case RPCConsole::CMD_REPLY:    return "cmd-reply"; break;
    case RPCConsole::CMD_ERROR:    return "cmd-error"; break;
    default:                       return "misc";
    }
}

void RPCConsole::clear()
{
    ui->messagesWidget->clear();
    history.clear();
    historyPtr = 0;
    ui->lineEdit->clear();
    ui->lineEdit->setFocus();

    // Add smoothly scaled icon images.
    // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
    for(int i=0; ICON_MAPPING[i].url; ++i)
    {
        ui->messagesWidget->document()->addResource(
                    QTextDocument::ImageResource,
                    QUrl(ICON_MAPPING[i].url),
                    QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
    }

    // Set default style sheet
    ui->messagesWidget->document()->setDefaultStyleSheet(
                "table { }"
                "td.time { color: #808080; padding-top: 3px; } "
                "td.message { font-family: Monospace; font-size: 12px; } "
                "td.cmd-request { color: #006060; } "
                "td.cmd-error { color: red; } "
                "b { color: #006060; } "
                );

    message(CMD_REPLY, (tr("Welcome to the Bitcoin RPC console.") + "
" +
                        tr("Use up and down arrows to navigate history, and Ctrl-L to clear screen.") + "
" +
                        tr("Type help for an overview of available commands.")), true);
}

void RPCConsole::message(int category, const QString &message, bool html)
{
    QTime time = QTime::currentTime();
    QString timeString = time.toString();
    QString out;
    out += "

" + timeString + "	";
    out += "	";
    out += "";
    if(html)
        out += message;
    else
        out += GUIUtil::HtmlEscape(message, true);
    out += "

";
    ui->messagesWidget->append(out);
}

void RPCConsole::setNumConnections(int count)
{
    ui->numberOfConnections->setText(QString::number(count));
}

void RPCConsole::setNumBlocks(int count, int countOfPeers)
{
    ui->numberOfBlocks->setText(QString::number(count));
    // If there is no current countOfPeers available display N/A instead of 0, which can't ever be true
    ui->totalBlocks->setText(countOfPeers == 0 ? tr("N/A") : QString::number(countOfPeers));
    if(clientModel)
        ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
}

void RPCConsole::on_lineEdit_returnPressed()
{
    QString cmd = ui->lineEdit->text();
    ui->lineEdit->clear();

    if(!cmd.isEmpty())
    {
        message(CMD_REQUEST, cmd);
        emit cmdRequest(cmd);
        // Truncate history from current position
        history.erase(history.begin() + historyPtr, history.end());
        // Append command to history
        history.append(cmd);
        // Enforce maximum history size
        while(history.size() > CONSOLE_HISTORY)
            history.removeFirst();
        // Set pointer to end of history
        historyPtr = history.size();
        // Scroll console view to end
        scrollToEnd();
    }
}

void RPCConsole::browseHistory(int offset)
{
    historyPtr += offset;
    if(historyPtr < 0)
        historyPtr = 0;
    if(historyPtr > history.size())
        historyPtr = history.size();
    QString cmd;
    if(historyPtr < history.size())
        cmd = history.at(historyPtr);
    ui->lineEdit->setText(cmd);
}

void RPCConsole::startExecutor()
{
    QThread *thread = new QThread;
    RPCExecutor *executor = new RPCExecutor();
    executor->moveToThread(thread);

    // Replies from executor object must go to this object
    connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
    // Requests from this object must go to executor
    connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));

    // On stopExecutor signal
    // - queue executor for deletion (in execution thread)
    // - quit the Qt event loop in the execution thread
    connect(this, SIGNAL(stopExecutor()), executor, SLOT(deleteLater()));
    connect(this, SIGNAL(stopExecutor()), thread, SLOT(quit()));
    // Queue the thread for deletion (in this thread) when it is finished
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    // Default implementation of QThread::run() simply spins up an event loop in the thread,
    // which is what we want.
    thread->start();
}

void RPCConsole::on_tabWidget_currentChanged(int index)
{
    if(ui->tabWidget->widget(index) == ui->tab_console)
    {
        ui->lineEdit->setFocus();
    }
}

void RPCConsole::on_openDebugLogfileButton_clicked()
{
    GUIUtil::openDebugLogfile();
}

void RPCConsole::scrollToEnd()
{
    QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
    scrollbar->setValue(scrollbar->maximum());
}

void RPCConsole::on_showCLOptionsButton_clicked()
{
    GUIUtil::HelpMessageBox help;
    help.exec();
}
<|endoftext|>


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

#include "mem/cache/replacement_policies/ship_rp.hh"

#include "base/logging.hh"
#include "params/SHiPMemRP.hh"
#include "params/SHiPPCRP.hh"
#include "params/SHiPRP.hh"

namespace gem5
{

namespace replacement_policy
{

SHiP::SHiPReplData::SHiPReplData(int num_bits)
  : BRRIPReplData(num_bits), signature(0), outcome(false)
{
}

SHiP::SignatureType
SHiP::SHiPReplData::getSignature() const
{
    return signature;
}

void
SHiP::SHiPReplData::setSignature(SignatureType new_signature)
{
    signature = new_signature;
    outcome = false;
}

void
SHiP::SHiPReplData::setReReferenced()
{
    outcome = true;
}

bool
SHiP::SHiPReplData::wasReReferenced() const
{
    return outcome;
}

SHiP::SHiP(const Params &p)
  : BRRIP(p), insertionThreshold(p.insertion_threshold / 100.0),
    SHCT(p.shct_size, SatCounter(numRRPVBits))
{
}

void
SHiP::invalidate(const std::shared_ptr<ReplacementData>& replacement_data)
{
    std::shared_ptr<SHiPReplData> casted_replacement_data =
        std::static_pointer_cast<SHiPReplData>(replacement_data);

    // The predictor is detrained when an entry that has not been re-
    // referenced since insertion is invalidated
    if (casted_replacement_data->wasReReferenced()) {
        SHCT[casted_replacement_data->getSignature()]--;
    }

    BRRIP::invalidate(replacement_data);
}

void
SHiP::touch(const std::shared_ptr<ReplacementData>& replacement_data,
    const PacketPtr pkt)
{
    std::shared_ptr<SHiPReplData> casted_replacement_data =
        std::static_pointer_cast<SHiPReplData>(replacement_data);

    // When a hit happens the SHCT entry indexed by the signature is
    // incremented
    SHCT[getSignature(pkt)]++;
    casted_replacement_data->setReReferenced();

    // This was a hit; update replacement data accordingly
    BRRIP::touch(replacement_data);
}

void
SHiP::touch(const std::shared_ptr<ReplacementData>& replacement_data)
    const
{
    panic("Cant train SHiP's predictor without access information.");
}

void
SHiP::reset(const std::shared_ptr<ReplacementData>& replacement_data,
    const PacketPtr pkt)
{
    std::shared_ptr<SHiPReplData> casted_replacement_data =
        std::static_pointer_cast<SHiPReplData>(replacement_data);

    // Get signature
    const SignatureType signature = getSignature(pkt);

    // Store signature
    casted_replacement_data->setSignature(signature);

    // If SHCT for signature is set, predict intermediate re-reference.
    // Predict distant re-reference otherwise
    BRRIP::reset(replacement_data);
    if (SHCT[signature].calcSaturation() >= insertionThreshold) {
        casted_replacement_data->rrpv--;
    }
}

void
SHiP::reset(const std::shared_ptr<ReplacementData>& replacement_data)
    const
{
    panic("Cant train SHiP's predictor without access information.");
}

std::shared_ptr<ReplacementData>
SHiP::instantiateEntry()
{
    return std::shared_ptr<ReplacementData>(new SHiPReplData(numRRPVBits));
}

SHiPMem::SHiPMem(const SHiPMemRPParams &p) : SHiP(p) {}

SHiP::SignatureType
SHiPMem::getSignature(const PacketPtr pkt) const
{
    return static_cast<SignatureType>(pkt->getAddr() % SHCT.size());
}

SHiPPC::SHiPPC(const SHiPPCRPParams &p) : SHiP(p) {}

SHiP::SignatureType
SHiPPC::getSignature(const PacketPtr pkt) const
{
    SignatureType signature;

    if (pkt->req->hasPC()) {
        signature = static_cast<SignatureType>(pkt->req->getPC());
    } else {
        signature = NO_PC_SIGNATURE;
    }

    return signature % SHCT.size();
}

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

#include "mem/cache/replacement_policies/ship_rp.hh"

#include "base/logging.hh"
#include "params/SHiPMemRP.hh"
#include "params/SHiPPCRP.hh"
#include "params/SHiPRP.hh"

namespace gem5
{

namespace replacement_policy
{

SHiP::SHiPReplData::SHiPReplData(int num_bits)
  : BRRIPReplData(num_bits), signature(0), outcome(false)
{
}

SHiP::SignatureType
SHiP::SHiPReplData::getSignature() const
{
    return signature;
}

void
SHiP::SHiPReplData::setSignature(SignatureType new_signature)
{
    signature = new_signature;
    outcome = false;
}

void
SHiP::SHiPReplData::setReReferenced()
{
    outcome = true;
}

bool
SHiP::SHiPReplData::wasReReferenced() const
{
    return outcome;
}

SHiP::SHiP(const Params &p)
  : BRRIP(p), insertionThreshold(p.insertion_threshold / 100.0),
    SHCT(p.shct_size, SatCounter8(numRRPVBits))
{
}

void
SHiP::invalidate(const std::shared_ptr<ReplacementData>& replacement_data)
{
    std::shared_ptr<SHiPReplData> casted_replacement_data =
        std::static_pointer_cast<SHiPReplData>(replacement_data);

    // The predictor is detrained when an entry that has not been re-
    // referenced since insertion is invalidated
    if (casted_replacement_data->wasReReferenced()) {
        SHCT[casted_replacement_data->getSignature()]--;
    }

    BRRIP::invalidate(replacement_data);
}

void
SHiP::touch(const std::shared_ptr<ReplacementData>& replacement_data,
    const PacketPtr pkt)
{
    std::shared_ptr<SHiPReplData> casted_replacement_data =
        std::static_pointer_cast<SHiPReplData>(replacement_data);

    // When a hit happens the SHCT entry indexed by the signature is
    // incremented
    SHCT[getSignature(pkt)]++;
    casted_replacement_data->setReReferenced();

    // This was a hit; update replacement data accordingly
    BRRIP::touch(replacement_data);
}

void
SHiP::touch(const std::shared_ptr<ReplacementData>& replacement_data)
    const
{
    panic("Cant train SHiP's predictor without access information.");
}

void
SHiP::reset(const std::shared_ptr<ReplacementData>& replacement_data,
    const PacketPtr pkt)
{
    std::shared_ptr<SHiPReplData> casted_replacement_data =
        std::static_pointer_cast<SHiPReplData>(replacement_data);

    // Get signature
    const SignatureType signature = getSignature(pkt);

    // Store signature
    casted_replacement_data->setSignature(signature);

    // If SHCT for signature is set, predict intermediate re-reference.
    // Predict distant re-reference otherwise
    BRRIP::reset(replacement_data);
    if (SHCT[signature].calcSaturation() >= insertionThreshold) {
        casted_replacement_data->rrpv--;
    }
}

void
SHiP::reset(const std::shared_ptr<ReplacementData>& replacement_data)
    const
{
    panic("Cant train SHiP's predictor without access information.");
}

std::shared_ptr<ReplacementData>
SHiP::instantiateEntry()
{
    return std::shared_ptr<ReplacementData>(new SHiPReplData(numRRPVBits));
}

SHiPMem::SHiPMem(const SHiPMemRPParams &p) : SHiP(p) {}

SHiP::SignatureType
SHiPMem::getSignature(const PacketPtr pkt) const
{
    return static_cast<SignatureType>(pkt->getAddr() % SHCT.size());
}

SHiPPC::SHiPPC(const SHiPPCRPParams &p) : SHiP(p) {}

SHiP::SignatureType
SHiPPC::getSignature(const PacketPtr pkt) const
{
    SignatureType signature;

    if (pkt->req->hasPC()) {
        signature = static_cast<SignatureType>(pkt->req->getPC());
    } else {
        signature = NO_PC_SIGNATURE;
    }

    return signature % SHCT.size();
}

} // namespace replacement_policy
} // namespace gem5
<|endoftext|>


<commit_before>/* $Id: alara.C,v 1.17 2002-09-09 19:57:12 varuttam Exp $ */
#include "alara.h"

#include "Input/Input.h"
#include "Chains/Root.h"
#include "Util/Statistics.h"
#include "Output/Result.h"

/* See why Paul is using these silly STL things? */

int chainCode = 0;

/*!
 This list of elemental symbols is specially formatted to be used for
 looking up the atomic number of a given element.  For each element
 with atomic number, Z, and symbol, CC, the string " CC " exists at
 index Z-1.
*/
const char *SYMBOLS=" h  he li be b  c  n  o  f  ne na mg al si p  s  cl ar \
k  ca sc ti v  cr mn fe co ni cu zn ga ge as se br kr rb sr y  zr nb mo tc ru \
rh pd ag cd in sn sb te i  xe cs ba la ce pr nd pm sm eu gd tb dy ho er tm \
yb lu hf ta w  re os ir pt au hg tl pb bi po at rn fr ra ac th pa u  np \
pu am cm bk cf es fm md no lr ";

/// This is derived from a CVS variable to determine the version string
static char *id="$Name: not supported by cvs2svn $";

/*!
 This is the standard help/usage message that is printed when an incorrect
 command-line option is used, or when -h is used.
*/
static char *helpmsg="\
usage: %s [-h] [-r] [-t <tree_filename>] [-V] [-v <n>] [<input_filename>] \n\
\t -h                 Show this message\n\
\t -c                 Option to only calculate chains and skip post-processing\n\
\t -r                 \"Restart\" option to skip chain calculation and only post-process\n\
\t -t <tree_filename> Create tree file with given name\n\
\t -V                 Show version\n\
\t -v <n>             Set verbosity level\n\
\t <input_filename>   Name of input file\n\
See Users' Guide for more info.\n\
(http://www.cae.wisc.edu/~wilsonp/projects/ALARA/users.guide.html/)\n";

int main(int argc, char *argv[])
{
  int argNum = 1;
  int solved = FALSE;
  int doOutput = TRUE;
  char *inFname = NULL;
  Root* rootList = new Root;
  topSchedule* schedule;

  verbose(-1,"ALARA %s",id);

  while (argNum<argc)
    {
      if (argv[argNum][0] != '-')
	if (inFname == NULL)
	  {
	    inFname = new char[strlen(argv[argNum])+1];
	    strcpy(inFname,argv[argNum]);
	    argNum++;
	    /* get next argument */
	    continue;
	  }
	else
	  error(1,"Only one input filename can be specified: %s.",inFname);

      while (argv[argNum][0] == '-')
	argv[argNum]++;
      switch (argv[argNum][0])
	{
#ifdef DVLPR
	case 'd':
	  if (argv[argNum][1] == '\0')
	    {
	      debug_level = atoi(argv[argNum+1]);
	      argNum+=2;
	    }
	  else
	    {
	      debug_level = atoi(argv[argNum]+1);
	      argNum++;
	    }
	  debug(0,"Set debug level to %d.",debug_level);
	  break;
#endif
/*	case 'v':
	  if (argv[argNum][1] == '\0')
	    {
	      verb_level = atoi(argv[argNum+1]);
	      argNum+=2;
	    }
	  else
	    {
	      verb_level = atoi(argv[argNum]+1);
	      argNum++;
	    }
	  verbose(0,"Set verbose level to %d.",verb_level);
	  break;	*/

	case 'v':
	  if (argv[argNum][1] == '\0')
	    {
	      if (argNum<argc-1)
              {
		verb_level = atoi(argv[argNum+1]);
	        argNum+=2;
	      }
	     else
		error(2,"-v requires parameter.");
	    }
	  else
	    {
	      verb_level = atoi(argv[argNum]+1);
	      argNum++;
	    }
	  verbose(0,"Set verbose level to %d.",verb_level);
	  break;

 	case 'c':
	  verbose(0,"Calculating chains ONLY.");
	  doOutput=FALSE;
	  argNum+=1;
	  break;
	case 'r':
          verbose(0,"Reusing binary dump data.");
	  solved=TRUE;
	  argNum+=1;
	  break;
	case 't':
	  if (argv[argNum][1] == '\0')
	    {
	      if (argNum<argc-1)
              {
                 Statistics::initTree(argv[argNum+1]);
	         verbose(0,"Openned tree file %s.",argv[argNum+1]);
	         argNum+=2;
	      }
	      else
		 error(2,"-t requires parameter.");
	    }
	  else
	    {
	      Statistics::initTree(argv[argNum]+1);
	      verbose(0,"Openned tree file %s.",argv[argNum]+1);
	      argNum++;
	    }
	  break;
	case 'h':
	  verbose(-1,helpmsg,argv[0]);
	case 'V':
	  exit(0);
	  break;
	default:
	  {
	    verbose(-1,helpmsg,argv[0]);
	    error(0,"Invalid option: %s.",argv[argNum]);
	  }
	}
    }

  Input problemInput(inFname);

  /* INPUT */
  verbose(0,"Starting problem input processing.");
  verbose(1,"Reading input.");
  problemInput.read();
  verbose(1,"Cross-checking input for completeness and self-consistency.");
  problemInput.xCheck();
  verbose(1,"Preprocessing input.");
  problemInput.preProc(rootList,schedule);

  if (!solved)
    {
      verbose(0,"Starting problem solution.");

      rootList->solve(schedule);

      verbose(1,"Solved problem.");
    }

  if (doOutput)
    {
      Result::resetBinDump();
      problemInput.postProc(rootList);

      verbose(0,"Output.");
    }

  Result::closeBinDump();

  delete rootList;
  delete inFname;

}
<commit_msg>Using config.h variables for identifying version.<commit_after>/* $Id: alara.C,v 1.18 2003-09-04 13:31:02 wilsonp Exp $ */
#include "alara.h"

#include "Input/Input.h"
#include "Chains/Root.h"
#include "Util/Statistics.h"
#include "Output/Result.h"

/* See why Paul is using these silly STL things? */

int chainCode = 0;

/*!
 This list of elemental symbols is specially formatted to be used for
 looking up the atomic number of a given element.  For each element
 with atomic number, Z, and symbol, CC, the string " CC " exists at
 index Z-1.
*/
const char *SYMBOLS=" h  he li be b  c  n  o  f  ne na mg al si p  s  cl ar \
k  ca sc ti v  cr mn fe co ni cu zn ga ge as se br kr rb sr y  zr nb mo tc ru \
rh pd ag cd in sn sb te i  xe cs ba la ce pr nd pm sm eu gd tb dy ho er tm \
yb lu hf ta w  re os ir pt au hg tl pb bi po at rn fr ra ac th pa u  np \
pu am cm bk cf es fm md no lr ";

/// This is derived from a CVS variable to determine the version string
static char *id="$Name: not supported by cvs2svn $";

/*!
 This is the standard help/usage message that is printed when an incorrect
 command-line option is used, or when -h is used.
*/
static char *helpmsg="\
usage: %s [-h] [-r] [-t <tree_filename>] [-V] [-v <n>] [<input_filename>] \n\
\t -h                 Show this message\n\
\t -c                 Option to only calculate chains and skip post-processing\n\
\t -r                 \"Restart\" option to skip chain calculation and only post-process\n\
\t -t <tree_filename> Create tree file with given name\n\
\t -V                 Show version\n\
\t -v <n>             Set verbosity level\n\
\t <input_filename>   Name of input file\n\
See Users' Guide for more info.\n\
(http://www.cae.wisc.edu/~wilsonp/research/ALARA/users.guide.html/)\n";

int main(int argc, char *argv[])
{
  int argNum = 1;
  int solved = FALSE;
  int doOutput = TRUE;
  char *inFname = NULL;
  Root* rootList = new Root;
  topSchedule* schedule;

  verbose(-1,"%s",PACKAGE_STRING);

  while (argNum<argc)
    {
      if (argv[argNum][0] != '-')
	if (inFname == NULL)
	  {
	    inFname = new char[strlen(argv[argNum])+1];
	    strcpy(inFname,argv[argNum]);
	    argNum++;
	    /* get next argument */
	    continue;
	  }
	else
	  error(1,"Only one input filename can be specified: %s.",inFname);

      while (argv[argNum][0] == '-')
	argv[argNum]++;
      switch (argv[argNum][0])
	{
#ifdef DVLPR
	case 'd':
	  if (argv[argNum][1] == '\0')
	    {
	      debug_level = atoi(argv[argNum+1]);
	      argNum+=2;
	    }
	  else
	    {
	      debug_level = atoi(argv[argNum]+1);
	      argNum++;
	    }
	  debug(0,"Set debug level to %d.",debug_level);
	  break;
#endif
/*	case 'v':
	  if (argv[argNum][1] == '\0')
	    {
	      verb_level = atoi(argv[argNum+1]);
	      argNum+=2;
	    }
	  else
	    {
	      verb_level = atoi(argv[argNum]+1);
	      argNum++;
	    }
	  verbose(0,"Set verbose level to %d.",verb_level);
	  break;	*/

	case 'v':
	  if (argv[argNum][1] == '\0')
	    {
	      if (argNum<argc-1)
              {
		verb_level = atoi(argv[argNum+1]);
	        argNum+=2;
	      }
	     else
		error(2,"-v requires parameter.");
	    }
	  else
	    {
	      verb_level = atoi(argv[argNum]+1);
	      argNum++;
	    }
	  verbose(0,"Set verbose level to %d.",verb_level);
	  break;

 	case 'c':
	  verbose(0,"Calculating chains ONLY.");
	  doOutput=FALSE;
	  argNum+=1;
	  break;
	case 'r':
          verbose(0,"Reusing binary dump data.");
	  solved=TRUE;
	  argNum+=1;
	  break;
	case 't':
	  if (argv[argNum][1] == '\0')
	    {
	      if (argNum<argc-1)
              {
                 Statistics::initTree(argv[argNum+1]);
	         verbose(0,"Openned tree file %s.",argv[argNum+1]);
	         argNum+=2;
	      }
	      else
		 error(2,"-t requires parameter.");
	    }
	  else
	    {
	      Statistics::initTree(argv[argNum]+1);
	      verbose(0,"Openned tree file %s.",argv[argNum]+1);
	      argNum++;
	    }
	  break;
	case 'h':
	  verbose(-1,helpmsg,argv[0]);
	case 'V':
	  exit(0);
	  break;
	default:
	  {
	    verbose(-1,helpmsg,argv[0]);
	    error(0,"Invalid option: %s.",argv[argNum]);
	  }
	}
    }

  Input problemInput(inFname);

  /* INPUT */
  verbose(0,"Starting problem input processing.");
  verbose(1,"Reading input.");
  problemInput.read();
  verbose(1,"Cross-checking input for completeness and self-consistency.");
  problemInput.xCheck();
  verbose(1,"Preprocessing input.");
  problemInput.preProc(rootList,schedule);

  if (!solved)
    {
      verbose(0,"Starting problem solution.");

      rootList->solve(schedule);

      verbose(1,"Solved problem.");
    }

  if (doOutput)
    {
      Result::resetBinDump();
      problemInput.postProc(rootList);

      verbose(0,"Output.");
    }

  Result::closeBinDump();

  delete rootList;
  delete inFname;

}
<|endoftext|>


<commit_before>// check each bit

int print_each_bit(int flag) {
    while (flag) {
        int index = __builtin_ctz(flag);
        //printf("%d\n", index);
        flag &= flag - 1;
    }
}

// lexicographically next bit permutation
unsigned int next(unsigned int) {
    unsigned int t = v | (v - 1); // t gets v's least significant 0 bits set to 1
    // Next set to 1 the most significant bit to change,
    // set to 0 the least significant ones, and add the necessary 1 bits.
    w = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
    return w;
}

// lexicographically next bit permutation
unsigned int next(unsigned int) {
    unsigned int t = (v | (v - 1)) + 1;
    w = t | ((((t & -t) / (v & -v)) >> 1) - 1);
    return w;
}
<commit_msg>add print_bit()<commit_after>// check each bit

int print_each_bit(int flag) {
    while (flag) {
        int index = __builtin_ctz(flag);
        //printf("%d\n", index);
        flag &= flag - 1;
    }
}

// lexicographically next bit permutation
unsigned int next(unsigned int) {
    unsigned int t = v | (v - 1); // t gets v's least significant 0 bits set to 1
    // Next set to 1 the most significant bit to change,
    // set to 0 the least significant ones, and add the necessary 1 bits.
    w = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
    return w;
}

// lexicographically next bit permutation
unsigned int next(unsigned int) {
    unsigned int t = (v | (v - 1)) + 1;
    w = t | ((((t & -t) / (v & -v)) >> 1) - 1);
    return w;
}

// print binary
void print_bit(unsigned int x) {
    int i = 31;
    while (0 <= i) {
        cout << ((x & (1<<i)) ? 1 : 0);
        if (i%4 == 0) cout << " ";
        i--;
    }
    cout << endl;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 1992-2009 Nokia. All rights reserved.
**
** This file is part of Qt Jambi.
**
** ** $BEGIN_LICENSE$
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $END_LICENSE$
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

#include "metadylan.h"

bool MetaDylanFunction::needsCallThrough() const {
    if (ownerClass()->isInterface())
        return false;
    return AbstractMetaFunction::needsCallThrough();
}

QString MetaDylanFunction::dylanName() const {
  // convert from camelCase to dylan-style
  static QRegExp re1("(.)([A-Z][a-z]+)");
  static QRegExp re2("([a-z0-9])([A-Z])");
  QString function_name = name();
  const MetaDylanClass *owner_class = (const MetaDylanClass *)ownerClass();

  function_name.replace(re1, "\\1-\\2");
  function_name.replace(re2, "\\1-\\2");
  function_name = function_name.toLower();

  // prefix with class name
  function_name = owner_class->name().toLower() + "-" + function_name;
  return function_name;
}

QString MetaDylanFunction::dylanConstructorName() const {
  QString function_name = name();
  return function_name;
}

QString MetaDylanFunction::package() const {
  MetaDylanClass *owner = (MetaDylanClass *)ownerClass();
  return owner->package();
}

QString MetaDylanEnumValue::dylanName() const {
  return "$" + name();
}

QString MetaDylanEnum::dylanName() const {
  if (enclosingClass())
    return "<" + enclosingClass()->name() + name() + ">";
  else
    return "<" + name() + ">";
}

QString MetaDylanClass::dylanName() const {
  return "<" + name() + ">";
}

// TODO: return the real module name
QString MetaDylanClass::package() const {
  return "qt-core";
}
<commit_msg>Generate unique function names<commit_after>/****************************************************************************
**
** Copyright (C) 1992-2009 Nokia. All rights reserved.
**
** This file is part of Qt Jambi.
**
** ** $BEGIN_LICENSE$
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** $END_LICENSE$
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

#include "metadylan.h"

bool MetaDylanFunction::needsCallThrough() const {
    if (ownerClass()->isInterface())
        return false;
    return AbstractMetaFunction::needsCallThrough();
}

QString MetaDylanFunction::dylanName() const {
  // convert from camelCase to dylan-style
  static QRegExp re1("(.)([A-Z][a-z]+)");
  static QRegExp re2("([a-z0-9])([A-Z])");
  QString function_name = name();
  const MetaDylanClass *owner_class = (const MetaDylanClass *)ownerClass();

  function_name.replace(re1, "\\1-\\2");
  function_name.replace(re2, "\\1-\\2");
  function_name = function_name.toLower();

  // prefix with class name
  function_name = owner_class->name() + "-" + function_name;
  for (int i = 0; i < arguments().count(); ++i) {
    if (!argumentRemoved(i + 1)) {
      AbstractMetaArgument *arg = arguments().at(i);
      function_name += "-" + arg->type()->name();
    }
  }
  return function_name.toLower();
}

QString MetaDylanFunction::dylanConstructorName() const {
  QString function_name = name();
  for (int i = 0; i < arguments().count(); ++i) {
    if (!argumentRemoved(i + 1)) {
      AbstractMetaArgument *arg = arguments().at(i);
      function_name += "-" + arg->type()->name();
    }
  }
  return function_name.toLower();
}

QString MetaDylanFunction::package() const {
  MetaDylanClass *owner = (MetaDylanClass *)ownerClass();
  return owner->package();
}

QString MetaDylanEnumValue::dylanName() const {
  return "$" + name();
}

QString MetaDylanEnum::dylanName() const {
  if (enclosingClass())
    return "<" + enclosingClass()->name() + name() + ">";
  else
    return "<" + name() + ">";
}

QString MetaDylanClass::dylanName() const {
  return "<" + name() + ">";
}

// TODO: return the real module name
QString MetaDylanClass::package() const {
  return "qt-core";
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//  Geom.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "Geom.h"

using namespace Oryol;

//------------------------------------------------------------------------------
void
Geom::Setup(const GfxSetup& gfxSetup, Id indexMesh, const Shaders::Voxel::VSParams& params) {

    // static shader params
    // FIXME: better move those into a separate uniform block?
    this->VSParams = params;

    // create Gfx resources
    // NOTE: currently geoms are replaced each frame, so use Usage::Stream
    auto meshSetup = MeshSetup::Empty(MaxNumVertices, Usage::Stream);
    meshSetup.Layout
        .Add(VertexAttr::Position, VertexFormat::UByte4)
        .Add(VertexAttr::Normal, VertexFormat::UByte4);
    this->Mesh = Gfx::CreateResource(meshSetup);
    Id shd = Gfx::CreateResource(Shaders::Voxel::Setup());
    auto dss = DrawStateSetup::FromMeshAndShader(indexMesh, shd);
    dss.Meshes[1] = this->Mesh;
    dss.DepthStencilState.DepthCmpFunc = CompareFunc::LessEqual;
    dss.DepthStencilState.DepthWriteEnabled = true;
    dss.RasterizerState.CullFaceEnabled = true;
    dss.RasterizerState.CullFace = Face::Front;
    dss.RasterizerState.SampleCount = gfxSetup.SampleCount;
    this->DrawState = Gfx::CreateResource(dss);
}

//------------------------------------------------------------------------------
void
Geom::Discard() {
    this->Mesh.Invalidate();
    this->DrawState.Invalidate();
}
<commit_msg>Changed vertex buffer usage to Dynamic from Stream<commit_after>//------------------------------------------------------------------------------
//  Geom.cc
//------------------------------------------------------------------------------
#include "Pre.h"
#include "Geom.h"

using namespace Oryol;

//------------------------------------------------------------------------------
void
Geom::Setup(const GfxSetup& gfxSetup, Id indexMesh, const Shaders::Voxel::VSParams& params) {

    // static shader params
    // FIXME: better move those into a separate uniform block?
    this->VSParams = params;

    // create Gfx resources
    auto meshSetup = MeshSetup::Empty(MaxNumVertices, Usage::Dynamic);
    meshSetup.Layout
        .Add(VertexAttr::Position, VertexFormat::UByte4)
        .Add(VertexAttr::Normal, VertexFormat::UByte4);
    this->Mesh = Gfx::CreateResource(meshSetup);
    Id shd = Gfx::CreateResource(Shaders::Voxel::Setup());
    auto dss = DrawStateSetup::FromMeshAndShader(indexMesh, shd);
    dss.Meshes[1] = this->Mesh;
    dss.DepthStencilState.DepthCmpFunc = CompareFunc::LessEqual;
    dss.DepthStencilState.DepthWriteEnabled = true;
    dss.RasterizerState.CullFaceEnabled = true;
    dss.RasterizerState.CullFace = Face::Front;
    dss.RasterizerState.SampleCount = gfxSetup.SampleCount;
    this->DrawState = Gfx::CreateResource(dss);
}

//------------------------------------------------------------------------------
void
Geom::Discard() {
    this->Mesh.Invalidate();
    this->DrawState.Invalidate();
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
All Rights Reserved.

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

#include <iostream>
#include <cmath>

#include "oslexec_pvt.h"
#include "genclosure.h"

OSL_NAMESPACE_ENTER
namespace pvt {

// This symbol is strictly to force linkage of this file when building
// static library.
int opclosure_cpp_dummy = 1;

OSL_SHADEOP const ClosureColor *
osl_add_closure_closure (ShaderGlobals *sg,
                         const ClosureColor *a, const ClosureColor *b)
{
    if (a == NULL) return b;
    if (b == NULL) return a;
    return sg->context->closure_add_allot (a, b);
}

OSL_SHADEOP const ClosureColor *
osl_mul_closure_color (ShaderGlobals *sg, ClosureColor *a, const Color3 *w)
{
    if (a == NULL) return NULL;
    return sg->context->closure_mul_allot (*w, a);
}

OSL_SHADEOP const ClosureColor *
osl_mul_closure_float (ShaderGlobals *sg, ClosureColor *a, float w)
{
    if (a == NULL) return NULL;
    return sg->context->closure_mul_allot (w, a);
}

OSL_SHADEOP ClosureComponent *
osl_allocate_closure_component (ShaderGlobals *sg, int id, int size, int nattrs)
{
    return sg->context->closure_component_allot(id, size, nattrs);
}

OSL_SHADEOP const char *
osl_closure_to_string (ShaderGlobals *sg, ClosureColor *c)
{
    // Special case for printing closures
    std::stringstream stream;
    print_closure(stream, c, &sg->context->shadingsys());
    return ustring(stream.str ()).c_str();
}

} // namespace pvt
OSL_NAMESPACE_EXIT
<commit_msg>Make sure multiplying by a closure by 0 produces NULL<commit_after>/*
Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
All Rights Reserved.

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

#include <iostream>
#include <cmath>

#include "oslexec_pvt.h"
#include "genclosure.h"

OSL_NAMESPACE_ENTER
namespace pvt {

// This symbol is strictly to force linkage of this file when building
// static library.
int opclosure_cpp_dummy = 1;

OSL_SHADEOP const ClosureColor *
osl_add_closure_closure (ShaderGlobals *sg,
                         const ClosureColor *a, const ClosureColor *b)
{
    if (a == NULL) return b;
    if (b == NULL) return a;
    return sg->context->closure_add_allot (a, b);
}

OSL_SHADEOP const ClosureColor *
osl_mul_closure_color (ShaderGlobals *sg, ClosureColor *a, const Color3 *w)
{
    if (a == NULL) return NULL;
    if (w->x == 0.0f &&
        w->y == 0.0f &&
        w->z == 0.0f) return NULL;
    return sg->context->closure_mul_allot (*w, a);
}

OSL_SHADEOP const ClosureColor *
osl_mul_closure_float (ShaderGlobals *sg, ClosureColor *a, float w)
{
    if (a == NULL) return NULL;
    if (w == 0.0f) return NULL;
    return sg->context->closure_mul_allot (w, a);
}

OSL_SHADEOP ClosureComponent *
osl_allocate_closure_component (ShaderGlobals *sg, int id, int size, int nattrs)
{
    return sg->context->closure_component_allot(id, size, nattrs);
}

OSL_SHADEOP const char *
osl_closure_to_string (ShaderGlobals *sg, ClosureColor *c)
{
    // Special case for printing closures
    std::stringstream stream;
    print_closure(stream, c, &sg->context->shadingsys());
    return ustring(stream.str ()).c_str();
}

} // namespace pvt
OSL_NAMESPACE_EXIT
<|endoftext|>


<commit_before><commit_msg>Add comment to clarify why replace() is used<commit_after><|endoftext|>


<commit_before><commit_msg>Add information about Linux GFX environnement in FC info<commit_after><|endoftext|>


<commit_before>#include "app.hpp"
#include "config.h"
#include <windows.h>
#include <iostream>
#include <stdexcept>
#include <memory>
#include <getopt.h>
#include "cmd/register.hpp"
#include "cmd/exec.hpp"
#include "cmd/list.hpp"
#include "util/winerror.hpp"
#include "util/elevated.hpp"
#include "util/strconv.hpp"
#include "util/message.hpp"

namespace cygregext {

/* type of native WinApi GetCommandLineW */
typedef LPWSTR (__stdcall* native_GetCommandLineW)(void);

App::App(const int argc, char* const argv[]) :
	_argc(argc),
	_argv(argv),
	_cmd(Command::NONE),
	_regType(RegisterType::USER),
	_extension(".sh"),
	_iconPath(std::string()),
	_force(false) {
	static const char *opts = "ruaflhV";
	static const struct option longopts[] = {
		{ "register", no_argument, NULL, 'r' },
		{ "unregister", no_argument, NULL, 'u' },
		{ "ext", required_argument, NULL, 'e' },
		{ "icon", required_argument, NULL, 'i' },
		{ "all", no_argument, NULL, 'a' },
		{ "force", no_argument, NULL, 'f' },
		{ "list", no_argument, NULL, 'l' },
		{ "exec", no_argument, NULL, 'E' },
		{ "version", no_argument, NULL, 'V' },
		{ "help", no_argument, NULL, 'h' },
		{ 0, 0, 0, 0 }
	};
	while (1) {
		int opt_index = 0;
		int c = 0;
		c = getopt_long(argc, argv, opts, longopts, &opt_index);
		if (-1 == c) {
			break;
		}
		switch (c) {
		/* --register */
		case 'r':
			_cmd = Command::REGISTER;
			break;
		/* --unregister */
		case 'u':
			_cmd = Command::UNREGISTER;
			break;
		/* --ext */
		case 'e':
			_extension = optarg;
			break;
		/* --icon */
		case 'i':
			_iconPath = optarg;
			break;
		/* --all */
		case 'a':
			_regType = RegisterType::EVERYONE;
			break;
		/* --force */
		case 'f':
			_force = true;
			break;
		/* --list */
		case 'l':
			_cmd = Command::LIST;
			break;
		/* --exec */
		case 'E':
			_cmd = Command::EXEC;
			break;
		/* --version */
		case 'V':
			_printVersion();
			exit(EXIT_SUCCESS);
		/* --help */
		case '?':
		case 'h':
		default:
			_printUsage(argv[0]);
			exit(EXIT_FAILURE);
		}
	}
	if (Command::NONE == _cmd) {
		_printUsage(argv[0]);
		exit(EXIT_FAILURE);
	}
	if ('.' != _extension[0]) {
		_extension.insert(0, ".");
	}
}

int App::run() {
	std::unique_ptr<ICommand> cmd;
	switch (_cmd) {
	/* execute command */
	case Command::EXEC:
		cmd = std::unique_ptr<ExecCommand>(new ExecCommand(_wideArgs()));
		break;
	/* register extension */
	case Command::REGISTER:
		if (_regType == RegisterType::EVERYONE) {
			_checkElevated();
		}
		cmd = std::unique_ptr<RegisterCommand>(
			new RegisterCommand(_extension, _iconPath,
			                    _regType == RegisterType::EVERYONE, _force));
		break;
	/* unregister extension */
	case Command::UNREGISTER:
		if (_regType == RegisterType::EVERYONE) {
			_checkElevated();
		}
		cmd = std::unique_ptr<UnregisterCommand>(
			new UnregisterCommand(_extension,
			                      _regType == RegisterType::EVERYONE));
		break;
	/* list registered extensions */
	case Command::LIST:
		cmd = std::unique_ptr<ListCommand>(new ListCommand());
		break;
	case Command::NONE:
		return 1;
	}
	return cmd->run();
}

WinPathW App::getPath() {
	wchar_t buf[MAX_PATH + 1];
	DWORD ret = GetModuleFileName(NULL, buf, sizeof(buf) / sizeof(buf[0]));
	if (0 == ret) {
		THROW_LAST_ERROR("Failed to get executable path.");
	}
	if (sizeof(buf) / sizeof(buf[0]) == ret &&
	    ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
		throw std::runtime_error("Failed to get executable path.");
	}
	return WinPathW(std::wstring(buf, ret));
}

static char help[] =
	""
	"Options:\n"
	"  -r, --register     Add extension to Windows registry.\n"
	"  -u, --unregister   Remove extension from Windows registry.\n"
	"      --ext=EXT      Register or unregister files of the given extension,\n"
	"                       default to .sh\n"
	"      --icon=PATH,N  Path and index of the icon to register for the extension,\n"
	"                       default to icon of this application.\n"
	"  -a, --all          Register or unregister extension for all users,\n"
	"                       default to current user.\n"
	"  -f, --force        Overwrite if already registered for another application.\n"
	"  -l, --list         List registered extensions.\n"
	"  -h, --help         Display this help and exit.\n"
	"  -V, --version      Print version and exit.\n";

void App::_printUsage(char *progname) {
	std::stringstream ss;
	ss << "Usage: " << progname << " [OPTION]..." << std::endl;
	ss << "Register script file type (.sh) to Windows File Explorer."
	   << std::endl << std::endl;
	ss << help;
	show_message(ss.str());
}

void App::_printVersion() {
	std::cout << "cygregext " << VERSION << std::endl;
	std::cout << "Copyright (C) 2017 Joni Eskelinen" << std::endl;
	std::cout << "License MIT: The MIT License" << std::endl;
	std::cout << "Icons: Tango Desktop Project" << std::endl;
}

std::vector<std::wstring> App::_wideArgs() {
	std::vector<std::wstring> args;
	LPWSTR* argv;
	int argc;
	/* use native WinApi GetCommandLineW since Cygwin hooks it */
	native_GetCommandLineW fn = (native_GetCommandLineW)GetProcAddress(
		GetModuleHandle(L"kernel32.dll"), "GetCommandLineW");
	if (NULL == fn) {
		THROW_LAST_ERROR("Failed to import GetCommandLineW");
	}
	argv = CommandLineToArgvW(fn(), &argc);
	/* if Windows command line has less arguments than what was
	   passed to the main(), then application was invoked from Cygwin shell. */
	if (argc < _argc) {
		for (int i = 0; i < _argc; ++i) {
			/* assume utf-8 */
			args.push_back(mb_to_wide(_argv[i], CP_UTF8));
		}
	} else {
		for (int i = 0; i < argc; ++i) {
			args.push_back(argv[i]);
		}
	}
	LocalFree(argv);
	return args;
}

void App::_checkElevated() {
	ElevatedProcess proc;
	if (proc.isAdmin()) {
		return;
	}
	proc.startElevated(_argc, _argv);
	exit(EXIT_SUCCESS);
}

}
<commit_msg>Edit wording<commit_after>#include "app.hpp"
#include "config.h"
#include <windows.h>
#include <iostream>
#include <stdexcept>
#include <memory>
#include <getopt.h>
#include "cmd/register.hpp"
#include "cmd/exec.hpp"
#include "cmd/list.hpp"
#include "util/winerror.hpp"
#include "util/elevated.hpp"
#include "util/strconv.hpp"
#include "util/message.hpp"

namespace cygregext {

/* type of native WinApi GetCommandLineW */
typedef LPWSTR (__stdcall* native_GetCommandLineW)(void);

App::App(const int argc, char* const argv[]) :
	_argc(argc),
	_argv(argv),
	_cmd(Command::NONE),
	_regType(RegisterType::USER),
	_extension(".sh"),
	_iconPath(std::string()),
	_force(false) {
	static const char *opts = "ruaflhV";
	static const struct option longopts[] = {
		{ "register", no_argument, NULL, 'r' },
		{ "unregister", no_argument, NULL, 'u' },
		{ "ext", required_argument, NULL, 'e' },
		{ "icon", required_argument, NULL, 'i' },
		{ "all", no_argument, NULL, 'a' },
		{ "force", no_argument, NULL, 'f' },
		{ "list", no_argument, NULL, 'l' },
		{ "exec", no_argument, NULL, 'E' },
		{ "version", no_argument, NULL, 'V' },
		{ "help", no_argument, NULL, 'h' },
		{ 0, 0, 0, 0 }
	};
	while (1) {
		int opt_index = 0;
		int c = 0;
		c = getopt_long(argc, argv, opts, longopts, &opt_index);
		if (-1 == c) {
			break;
		}
		switch (c) {
		/* --register */
		case 'r':
			_cmd = Command::REGISTER;
			break;
		/* --unregister */
		case 'u':
			_cmd = Command::UNREGISTER;
			break;
		/* --ext */
		case 'e':
			_extension = optarg;
			break;
		/* --icon */
		case 'i':
			_iconPath = optarg;
			break;
		/* --all */
		case 'a':
			_regType = RegisterType::EVERYONE;
			break;
		/* --force */
		case 'f':
			_force = true;
			break;
		/* --list */
		case 'l':
			_cmd = Command::LIST;
			break;
		/* --exec */
		case 'E':
			_cmd = Command::EXEC;
			break;
		/* --version */
		case 'V':
			_printVersion();
			exit(EXIT_SUCCESS);
		/* --help */
		case '?':
		case 'h':
		default:
			_printUsage(argv[0]);
			exit(EXIT_FAILURE);
		}
	}
	if (Command::NONE == _cmd) {
		_printUsage(argv[0]);
		exit(EXIT_FAILURE);
	}
	if ('.' != _extension[0]) {
		_extension.insert(0, ".");
	}
}

int App::run() {
	std::unique_ptr<ICommand> cmd;
	switch (_cmd) {
	/* execute command */
	case Command::EXEC:
		cmd = std::unique_ptr<ExecCommand>(new ExecCommand(_wideArgs()));
		break;
	/* register extension */
	case Command::REGISTER:
		if (_regType == RegisterType::EVERYONE) {
			_checkElevated();
		}
		cmd = std::unique_ptr<RegisterCommand>(
			new RegisterCommand(_extension, _iconPath,
			                    _regType == RegisterType::EVERYONE, _force));
		break;
	/* unregister extension */
	case Command::UNREGISTER:
		if (_regType == RegisterType::EVERYONE) {
			_checkElevated();
		}
		cmd = std::unique_ptr<UnregisterCommand>(
			new UnregisterCommand(_extension,
			                      _regType == RegisterType::EVERYONE));
		break;
	/* list registered extensions */
	case Command::LIST:
		cmd = std::unique_ptr<ListCommand>(new ListCommand());
		break;
	case Command::NONE:
		return 1;
	}
	return cmd->run();
}

WinPathW App::getPath() {
	wchar_t buf[MAX_PATH + 1];
	DWORD ret = GetModuleFileName(NULL, buf, sizeof(buf) / sizeof(buf[0]));
	if (0 == ret) {
		THROW_LAST_ERROR("Failed to get executable path.");
	}
	if (sizeof(buf) / sizeof(buf[0]) == ret &&
	    ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
		throw std::runtime_error("Failed to get executable path.");
	}
	return WinPathW(std::wstring(buf, ret));
}

static char help[] =
	""
	"Options:\n"
	"  -r, --register     Add a file type to the Windows registry.\n"
	"  -u, --unregister   Remove a file type from the Windows registry.\n"
	"      --ext=EXT      Register or unregister files of the given extension.\n"
	"                       Default to .sh.\n"
	"      --icon=PATH,N  Path and index of the icon to register for an extension.\n"
	"                       Default to the icon of this application.\n"
	"  -a, --all          Register or unregister extension for all users.\n"
	"                       Default to current user only.\n"
	"  -f, --force        Overwrite if already registered for another application.\n"
	"  -l, --list         List registered extensions.\n"
	"  -h, --help         Display this help and exit.\n"
	"  -V, --version      Print version and exit.\n";

void App::_printUsage(char *progname) {
	std::stringstream ss;
	ss << "Usage: " << progname << " [OPTION]..." << std::endl;
	ss << "Register a script file type (.sh) to Windows File Explorer."
	   << std::endl << std::endl;
	ss << help;
	show_message(ss.str());
}

void App::_printVersion() {
	std::cout << "cygregext " << VERSION << std::endl;
	std::cout << "Copyright (C) 2017 Joni Eskelinen" << std::endl;
	std::cout << "License MIT: The MIT License" << std::endl;
	std::cout << "Icons: Tango Desktop Project" << std::endl;
}

std::vector<std::wstring> App::_wideArgs() {
	std::vector<std::wstring> args;
	LPWSTR* argv;
	int argc;
	/* use native WinApi GetCommandLineW since Cygwin hooks it */
	native_GetCommandLineW fn = (native_GetCommandLineW)GetProcAddress(
		GetModuleHandle(L"kernel32.dll"), "GetCommandLineW");
	if (NULL == fn) {
		THROW_LAST_ERROR("Failed to import GetCommandLineW");
	}
	argv = CommandLineToArgvW(fn(), &argc);
	/* if Windows command line has less arguments than what was
	   passed to the main(), then application was invoked from Cygwin shell. */
	if (argc < _argc) {
		for (int i = 0; i < _argc; ++i) {
			/* assume utf-8 */
			args.push_back(mb_to_wide(_argv[i], CP_UTF8));
		}
	} else {
		for (int i = 0; i < argc; ++i) {
			args.push_back(argv[i]);
		}
	}
	LocalFree(argv);
	return args;
}

void App::_checkElevated() {
	ElevatedProcess proc;
	if (proc.isAdmin()) {
		return;
	}
	proc.startElevated(_argc, _argv);
	exit(EXIT_SUCCESS);
}

}
<|endoftext|>