<commit_before>#include <stdlib.h>
#include <stdio.h>

#ifdef _WIN32
#include <conio.h>
#endif

#ifdef _WIN32
#include <crtdbg.h>
#endif

#include <unistd.h>
#include <sstream>

#include "NGM.h"

#include "CS.h"
#include "Version.h"

#include "Timing.h"

#include "Debug.h"

#undef module_name
#define module_name "MAIN"

// Get current date/time, format is YYYY-MM-DD.HH:mm:ss
const std::string currentDateTime() {
	time_t now = time(0);
	struct tm tstruct;
	char buf[80];
	tstruct = *localtime(&now);
	// Visit http://www.cplusplus.com/reference/clibrary/ctime/strftime/
	// for more information about date/time format
	strftime(buf, sizeof(buf), "%Y-%m-%d.%X", &tstruct);

	return buf;
}

bool CheckOutput() {
	if (Config.Exists("output")) {
		if (!(Config.Exists("overwrite") && (Config.GetInt("overwrite") == 1))) {
			if (FileExists(Config.GetString("output"))) {
				Log.Error("Output file already exists and overwrite set to false.");
				return false;
			}
		}
	} else {
		Log.Error("No output file (-o) specified.");
		Help();
		return false;
	}
	if((Config.Exists("qry1") && Config.Exists("qry2"))) {
		if (!FileExists(Config.GetString("qry1"))) {
			Log.Error("Query file (%s) does not exist.", Config.GetString("qry1"));
			Help();
			return false;
		}
		if (!FileExists(Config.GetString("qry2"))) {
			Log.Error("Query file (%s) does not exist.", Config.GetString("qry2"));
			Help();
			return false;
		}
	} else {
		if (Config.Exists("qry")) {
			if (!FileExists(Config.GetString("qry"))) {
				Log.Error("Query file (%s) does not exist.", Config.GetString("qry"));
				Help();
				return false;
			}
		}
	}
	return true;
}

#ifdef NDEBUG
bool cDebug = false;
#else
bool cDebug = true;
#endif

ILog const * _log = 0;
IConfig * _config = 0;

int main(int argc, char * argv[]) {

	std::stringstream version;
	version << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_BUILD;

	char const * arch[] = { "x86", "x64" };
	char const * build = (cDebug) ? " (DEBUG)" : "";
	Log.Message("NextGenMap %s", version.str().c_str());
	Log.Message("Startup : %s%s (build %s %s)", arch[sizeof(void*) / 4 - 1], build, __DATE__, __TIME__);

	Log.Message("Starting time: %s", currentDateTime().c_str());

	//try {
	Timer tmr;
	tmr.ST();

	_NGM::AppName = argv[0];

	InitPlatform();

	// Initialization:
	_config = new _Config(argc, argv); // Parses command line & parameter file
	_log = &Log;
	_Log::Init(); // Inits logging to file

	Log.setColor(Config.Exists("color"));

	if (Config.Exists("master_cpu"))
		NGMSetThreadAffinity(0, Config.GetInt("master_cpu"));

	if (!Config.Exists("qry") || CheckOutput()) {
		NGM; // Init Core

		NGM.InitProviders();

		if (!Config.Exists("qry") && !(Config.Exists("qry1") && Config.Exists("qry2"))) {
			Log.Message("Finished building hash table.");
			Log.Message("No qry file specified. If you want to map single-end data use -q/--qry. If you want to map paired-end data, either use -q/--qry and -p or --qry1 and --qry2.");
		} else {
			try {
				Log.Message("Core initialization complete");
				NGM.StartThreads();

				NGM.MainLoop();

				bool const isPaired = Config.GetInt("paired") > 0;
				if (isPaired) {
					Log.Message("Valid pairs found: %.2f%%", NGM.Stats->validPairs);
					Log.Message("Estimated insert size: %d bp", (int)NGM.Stats->insertSize);
				}
				Log.Message("Alignments computed: %ld", AlignmentBuffer::alignmentCount);
#ifdef INSTANCE_COUNTING
				Log.Green("Counts:");
				Log.Message("MappedRead count = %i (max %i)", MappedRead::sInstanceCount, MappedRead::maxSeqCount);
				Log.Message("LocationScore count = %i", LocationScore::sInstanceCount);
#endif
				int discarded = NGM.GetReadReadCount() - (NGM.GetMappedReadCount()+NGM.GetUnmappedReadCount());
				if (discarded != 0) {
					Log.Warning("Reads discarded: %d", discarded);
				}

				Log.Message("Done (%i reads mapped (%.2f%%), %i reads not mapped, %i lines written)(elapsed: %fs)", NGM.GetMappedReadCount(), (float)NGM.GetMappedReadCount() * 100.0f / (float)(std::max(1, NGM.GetMappedReadCount()+NGM.GetUnmappedReadCount())),NGM.GetUnmappedReadCount(), NGM.GetWrittenReadCount(), tmr.ET());
			} catch (...) {
				Log.Error("Unhandled exception in control thread");
			}
		}
	}
	CS::Cleanup();
	_SequenceProvider::Cleanup();
	delete _config;
	delete _NGM::pInstance;
	_Log::Cleanup();

	CleanupPlatform();

	return 0;
}

void Help() {
	char const * const help_msg =
			"\
\
Usage:\
  ngm [-c <path>] {-q <reads> [-p] | -1 <mates 1> -2 <mates 2>} -r <reference> -o <output> [parameter]\n\
\n\
Input:\n\
\n\
 -c/--config <path>            Path to the config file. The config file contains\n\
                               all advanced options. If this parameter is\n\
                               omitted, default values will be used.\n\
 -r/--reference <path>         Path to the reference genome\n\
                               (format: FASTA, can be gzipped).\n\
 -q/--qry  <path>              Path to the read file. If the file contains\n\
                               interleaved mates use -p/--paired.\n\
 -1/--qry1 <path>              Path to the read file containing mates 1.\n\
 -2/--qry2 <path>              Path to the read file containing mates 2.\n\
                               Valid input formats are: FASTA/Q (gzipped),\n\
                               SAM/BAM. If the query file(s) is/are omitted,\n\
                               NGM will only pre-process the reference.\n\
 -p/--paired                   Input data is paired end.\n\
                               NOT required if -1/-2 are used. (default: off)\n\
 -I/--min-insert-size          The min insert size for paired end alignments\n\
                               (default: 0)\n\
 -X/--max-insert-size          The max insert size for paired end alignments\n\
                               (default: 1000)\n\
\n\
Output:\n\
\n\
 -o/--output <path>            Path to output file.\n\
 -n/--topn                     Prints the <n> best alignments sorted by\n\
                               alignment score (default: 1)\n\
 --strata                      Only  output  the  highest  scoring  mappings\n\
                               for any  given  read,  up  to <n> mappings per\n\
                               read. If a read has more than <n> mappings with\n\
                               the same score, it is discarded and reported\n\
                               as unmapped.\n\
 -b/--bam                      Output BAM instead of SAM.\n\
 --keep-tags                   Copy BAM/SAM tags present in input file to\n\
                               output file (default: off)\n\
 --no-unal                     Don't print unaligned reads to output file.\n\
 --hard-clip                   Hard instead of soft clipping in SAM output\n\
 --silent-clip                 Hard clip reads but don't add clipping\n\
                               information to CIGAR string\n\
 --rg-id <ID>                  Adds RG:Z:<ID> to all alignments in SAM/BAM \n\
 --rg-sm                       RG header: Sample\n\
 --rg-lb                       RG header: Library\n\
 --rg-pl                       RG header: Platform\n\
 --rg-ds                       RG header: Description\n\
 --rg-dt                       RG header: Date\n\
 --rg-pu                       RG header: Platform unit\n\
 --rg-pi                       RG header: Median insert size\n\
 --rg-pg                       RG header: Programs\n\
 --rg-cn                       RG header: sequencing center\n\
 --rg-fo                       RG header: Flow order\n\
 --rg-ks                       RG header: Key sequence\n\
 -d/--pe-delimiter <char>      Character used in suffix that identifies mate 1\n\
                               and 2. E.g. /1 and /2. This suffixes will be\n\
                               removed to ensure proper SAM output\n\
                               (default: /)\n\
\n\
General:\n\n\
 -t/--threads <int>            Number of candidate search threads\n\
 -s/--sensitivity <float>      A value between 0 and 1 that determines the\n\
                               number of candidate mapping regions that will\n\
                               be evaluated with an sequence alignment.\n\
                                 0: all CMR(s) will be evaluated\n\
                                 1: only the best CMR(s) will be evaluated\n\
                               Higher values will reduce the runtime but also\n\
                               have a negative effect on mapping sensitivity.\n\
                               (default: estimated from input data)\n\
 -i/--min-identity <0-1>       All reads mapped with an identity lower than\n\
                               this threshold will be reported as unmapped\n\
                               (default: 0.65)\n\
 -R/--min-residues <int/float> All reads mapped with lower than\n\
                               <int> or <float> * read length residues\n\
                               will be reported as unmapped. (default: 0.5)\n\
 -Q/--min-mq <int>             All reads mapped with lower than <int>\n\
                               mapping quality will be reported as unmapped.\n\
                               (default: 0)\n\
 -g/--gpu [int,...]            Use GPU(s) for alignment computation\n\
                               NOTE: GPU Ids are zero-based!\n\
                                  -g or --gpu to use GPU\n\
                                  -g 1 or --gpu 1 to use GPU 1\n\
                                  -g 0,1 or --gpu 0,1 to use GPU 0 and 1\n\
                               If -g/--gpu is omitted, alignments will be\n\
                               computed on the CPU (default)\n\
 --bs-mapping                  Enables bisulfite mapping.\n\
                               For bs-mapping, kmer-skip will be applied to\n\
                               the reads instead of the reference sequence.\n\
 --bs-cutoff <int>             Max. number of Ts in a k-mer. All k-mers were\n\
                               the number of Ts is higher than <int> are\n\
                               ignored (default: 8)\n\
 -h/--help                     Prints help and aborts program\n\n\
\n\
Advanced settings:\n\
\n\
 -k/--kmer [10-14]             Kmer length in bases. (default: 13)\n\
 --kmer-skip <int>             Number of k-mers to skip when building the\n\
                               lookup table from the reference(default: 2)\n\
 --kmer-min <int>              Minimal number of k-mer hits required to\n\
                               consider a region a CMR. (default: 0)\n\
 --max-cmrs <int>              Reads that have more than <int> CMRs are\n\
                               ignored. (default: infinite)\n\
 --skip-save                   Don't save index to disk. Saves disk space but\n\
                               increases runtime for larger genomes.\n\
 -l/--local                    Perform local alignment. Ends might get clipped.\n\
                               (default: on)\n\
 -e/--end-to-end               Perform local alignment. Ends might get clipped.\n\
			                   (default: off)\n\
 --affine                      Use alignment algorithms that support affine gap\n\
                               costs. This will give you better alignments for\n\
                               longer indels but will also increase the runtime.\n\
                               (default: off)\n\
 -C/--max-consec-indels <int>  Maximum number of consecutive indels allowed.\n\
                               (default: computed based on avg. read length)\n\
 --fast-pairing                Mates are mapped individually. If the best\n\
                               alignments for the mates give a proper pair\n\
                               they are marked as paired in the output.\n\
                               If not they are reported as broken pair.\n\
 --pair-score-cutoff <0-1>     To find the best pairing all alignments of a\n\
                               read that have a score in the range of: \n\
                                 [top score * pair-score-cutoff; top score]\n\
                               are taken into account.\n\
 --skip-mate-check             Don't check that both mates have the same name\n\
                               (default: off)\n\
 --match-bonus <int>           Match score\n\
                               (default: 10, affine: 10, bs-mapping: 4)\n\
 --mismatch penalty <int>      Mismatch penalty\n\
                               (default: 15, affine: 15, bs-mapping: 2)\n\
 --gap-read-penalty <int>      Penalty for a gap in the read\n\
                               (default: 20, affine: 33, bs-mapping: 10)\n\
 --gap-ref-penalty <int>       Penalty for a gap in the reference\n\
                               (default: 20, affine: 33, bs-mapping: 10)\n\
 --gap-extend-penalty <int>    Penalty for extending a gap\n\
			                   (default: 20, affine: 3, bs-mapping: 10)\n\
 --match-bonus-tt <int>        Only for bs-mapping (default: 4)\n\
 --match-bonus-tc <int>        Only for bs-mapping (default: 4)\n\
 --color                       Colored text output (default: off)\n\
 --no-progress                 Don't print progress info while mapping\n\
                               (default: off)\n\
\n\
\n";
	printf(help_msg);
	exit(0);
}

// actually platform specific.../care
ulong const FileSize(char const * const filename) {
	FILE * fp = fopen(filename, "rb");
	if (fp == 0) {
		Log.Warning("Tried to get size of nonexistent file %s", filename);
		return 0;
	}

	if (fseek(fp, 0, SEEK_END) != 0)
		return 0;

	ulong end = ftell(fp);
	fclose(fp);
	return end;
}
<commit_msg>Help message<commit_after>#include <stdlib.h>
#include <stdio.h>

#ifdef _WIN32
#include <conio.h>
#endif

#ifdef _WIN32
#include <crtdbg.h>
#endif

#include <unistd.h>
#include <sstream>

#include "NGM.h"

#include "CS.h"
#include "Version.h"

#include "Timing.h"

#include "Debug.h"

#undef module_name
#define module_name "MAIN"

// Get current date/time, format is YYYY-MM-DD.HH:mm:ss
const std::string currentDateTime() {
	time_t now = time(0);
	struct tm tstruct;
	char buf[80];
	tstruct = *localtime(&now);
	// Visit http://www.cplusplus.com/reference/clibrary/ctime/strftime/
	// for more information about date/time format
	strftime(buf, sizeof(buf), "%Y-%m-%d.%X", &tstruct);

	return buf;
}

bool CheckOutput() {
	if (Config.Exists("output")) {
		if (!(Config.Exists("overwrite") && (Config.GetInt("overwrite") == 1))) {
			if (FileExists(Config.GetString("output"))) {
				Log.Error("Output file already exists and overwrite set to false.");
				return false;
			}
		}
	} else {
		Log.Error("No output file (-o) specified.");
		Help();
		return false;
	}
	if((Config.Exists("qry1") && Config.Exists("qry2"))) {
		if (!FileExists(Config.GetString("qry1"))) {
			Log.Error("Query file (%s) does not exist.", Config.GetString("qry1"));
			Help();
			return false;
		}
		if (!FileExists(Config.GetString("qry2"))) {
			Log.Error("Query file (%s) does not exist.", Config.GetString("qry2"));
			Help();
			return false;
		}
	} else {
		if (Config.Exists("qry")) {
			if (!FileExists(Config.GetString("qry"))) {
				Log.Error("Query file (%s) does not exist.", Config.GetString("qry"));
				Help();
				return false;
			}
		}
	}
	return true;
}

#ifdef NDEBUG
bool cDebug = false;
#else
bool cDebug = true;
#endif

ILog const * _log = 0;
IConfig * _config = 0;

int main(int argc, char * argv[]) {

	std::stringstream version;
	version << VERSION_MAJOR << "." << VERSION_MINOR << "." << VERSION_BUILD;

	char const * arch[] = { "x86", "x64" };
	char const * build = (cDebug) ? " (DEBUG)" : "";
	Log.Message("NextGenMap %s", version.str().c_str());
	Log.Message("Startup : %s%s (build %s %s)", arch[sizeof(void*) / 4 - 1], build, __DATE__, __TIME__);

	Log.Message("Starting time: %s", currentDateTime().c_str());

	//try {
	Timer tmr;
	tmr.ST();

	_NGM::AppName = argv[0];

	InitPlatform();

	// Initialization:
	_config = new _Config(argc, argv); // Parses command line & parameter file
	_log = &Log;
	_Log::Init(); // Inits logging to file

	Log.setColor(Config.Exists("color"));

	if (Config.Exists("master_cpu"))
		NGMSetThreadAffinity(0, Config.GetInt("master_cpu"));

	if (!Config.Exists("qry") || CheckOutput()) {
		NGM; // Init Core

		NGM.InitProviders();

		if (!Config.Exists("qry") && !(Config.Exists("qry1") && Config.Exists("qry2"))) {
			Log.Message("Finished building hash table.");
			Log.Message("No qry file specified. If you want to map single-end data use -q/--qry. If you want to map paired-end data, either use -q/--qry and -p or --qry1 and --qry2.");
		} else {
			try {
				Log.Message("Core initialization complete");
				NGM.StartThreads();

				NGM.MainLoop();

				bool const isPaired = Config.GetInt("paired") > 0;
				if (isPaired) {
					Log.Message("Valid pairs found: %.2f%%", NGM.Stats->validPairs);
					Log.Message("Estimated insert size: %d bp", (int)NGM.Stats->insertSize);
				}
				Log.Message("Alignments computed: %ld", AlignmentBuffer::alignmentCount);
#ifdef INSTANCE_COUNTING
				Log.Green("Counts:");
				Log.Message("MappedRead count = %i (max %i)", MappedRead::sInstanceCount, MappedRead::maxSeqCount);
				Log.Message("LocationScore count = %i", LocationScore::sInstanceCount);
#endif
				int discarded = NGM.GetReadReadCount() - (NGM.GetMappedReadCount()+NGM.GetUnmappedReadCount());
				if (discarded != 0) {
					Log.Warning("Reads discarded: %d", discarded);
				}

				Log.Message("Done (%i reads mapped (%.2f%%), %i reads not mapped, %i lines written)(elapsed: %fs)", NGM.GetMappedReadCount(), (float)NGM.GetMappedReadCount() * 100.0f / (float)(std::max(1, NGM.GetMappedReadCount()+NGM.GetUnmappedReadCount())),NGM.GetUnmappedReadCount(), NGM.GetWrittenReadCount(), tmr.ET());
			} catch (...) {
				Log.Error("Unhandled exception in control thread");
			}
		}
	}
	CS::Cleanup();
	_SequenceProvider::Cleanup();
	delete _config;
	delete _NGM::pInstance;
	_Log::Cleanup();

	CleanupPlatform();

	return 0;
}

void Help() {
	char const * const help_msg =
			"\
\
Usage:\
  ngm [-c <path>] {-q <reads> [-p] | -1 <mates 1> -2 <mates 2>} -r <reference> -o <output> [parameter]\n\
\n\
Input:\n\
\n\
 -c/--config <path>            Path to the config file. The config file contains\n\
                               all advanced options. If this parameter is\n\
                               omitted, default values will be used.\n\
 -r/--reference <path>         Path to the reference genome\n\
                               (format: FASTA, can be gzipped).\n\
 -q/--qry  <path>              Path to the read file. If the file contains\n\
                               interleaved mates use -p/--paired.\n\
 -1/--qry1 <path>              Path to the read file containing mates 1.\n\
 -2/--qry2 <path>              Path to the read file containing mates 2.\n\
                               Valid input formats are: FASTA/Q (gzipped),\n\
                               SAM/BAM. If the query file(s) is/are omitted,\n\
                               NGM will only pre-process the reference.\n\
 -p/--paired                   Input data is paired end.\n\
                               NOT required if -1/-2 are used. (default: off)\n\
 -I/--min-insert-size          The min insert size for paired end alignments\n\
                               (default: 0)\n\
 -X/--max-insert-size          The max insert size for paired end alignments\n\
                               (default: 1000)\n\
\n\
Output:\n\
\n\
 -o/--output <path>            Path to output file.\n\
 -n/--topn                     Prints the <n> best alignments sorted by\n\
                               alignment score (default: 1)\n\
 --strata                      Only  output  the  highest  scoring  mappings\n\
                               for any  given  read,  up  to <n> mappings per\n\
                               read. If a read has more than <n> mappings with\n\
                               the same score, it is discarded and reported\n\
                               as unmapped.\n\
 -b/--bam                      Output BAM instead of SAM.\n\
 --keep-tags                   Copy BAM/SAM tags present in input file to\n\
                               output file (default: off)\n\
 --no-unal                     Don't print unaligned reads to output file.\n\
 --hard-clip                   Hard instead of soft clipping in SAM output\n\
 --silent-clip                 Hard clip reads but don't add clipping\n\
                               information to CIGAR string\n\
 --rg-id <string>              Adds RG:Z:<string> to all alignments in SAM/BAM \n\
 --rg-sm <string>              RG header: Sample\n\
 --rg-lb <string>              RG header: Library\n\
 --rg-pl <string>              RG header: Platform\n\
 --rg-ds <string>              RG header: Description\n\
 --rg-dt <string>              RG header: Date\n\
 --rg-pu <string>              RG header: Platform unit\n\
 --rg-pi <string>              RG header: Median insert size\n\
 --rg-pg <string>              RG header: Programs\n\
 --rg-cn <string>              RG header: sequencing center\n\
 --rg-fo <string>              RG header: Flow order\n\
 --rg-ks <string>              RG header: Key sequence\n\
 -d/--pe-delimiter <char>      Character used in suffix that identifies mate 1\n\
                               and 2. E.g. /1 and /2. This suffixes will be\n\
                               removed to ensure proper SAM output\n\
                               (default: /)\n\
\n\
General:\n\n\
 -t/--threads <int>            Number of candidate search threads\n\
 -s/--sensitivity <float>      A value between 0 and 1 that determines the\n\
                               number of candidate mapping regions that will\n\
                               be evaluated with an sequence alignment.\n\
                                 0: all CMR(s) will be evaluated\n\
                                 1: only the best CMR(s) will be evaluated\n\
                               Higher values will reduce the runtime but also\n\
                               have a negative effect on mapping sensitivity.\n\
                               (default: estimated from input data)\n\
 -i/--min-identity <0-1>       All reads mapped with an identity lower than\n\
                               this threshold will be reported as unmapped\n\
                               (default: 0.65)\n\
 -R/--min-residues <int/float> All reads mapped with lower than\n\
                               <int> or <float> * read length residues\n\
                               will be reported as unmapped. (default: 0.5)\n\
 -Q/--min-mq <int>             All reads mapped with lower than <int>\n\
                               mapping quality will be reported as unmapped.\n\
                               (default: 0)\n\
 -g/--gpu [int,...]            Use GPU(s) for alignment computation\n\
                               NOTE: GPU Ids are zero-based!\n\
                                  -g or --gpu to use GPU\n\
                                  -g 1 or --gpu 1 to use GPU 1\n\
                                  -g 0,1 or --gpu 0,1 to use GPU 0 and 1\n\
                               If -g/--gpu is omitted, alignments will be\n\
                               computed on the CPU (default)\n\
 --bs-mapping                  Enables bisulfite mapping.\n\
                               For bs-mapping, kmer-skip will be applied to\n\
                               the reads instead of the reference sequence.\n\
 --bs-cutoff <int>             Max. number of Ts in a k-mer. All k-mers were\n\
                               the number of Ts is higher than <int> are\n\
                               ignored (default: 8)\n\
 -h/--help                     Prints help and aborts program\n\n\
\n\
Advanced settings:\n\
\n\
 -k/--kmer [10-14]             Kmer length in bases. (default: 13)\n\
 --kmer-skip <int>             Number of k-mers to skip when building the\n\
                               lookup table from the reference(default: 2)\n\
 --kmer-min <int>              Minimal number of k-mer hits required to\n\
                               consider a region a CMR. (default: 0)\n\
 --max-cmrs <int>              Reads that have more than <int> CMRs are\n\
                               ignored. (default: infinite)\n\
 --skip-save                   Don't save index to disk. Saves disk space but\n\
                               increases runtime for larger genomes.\n\
 -l/--local                    Perform local alignment. Ends might get clipped.\n\
                               (default: on)\n\
 -e/--end-to-end               Perform local alignment. Ends might get clipped.\n\
			                   (default: off)\n\
 --affine                      Use alignment algorithms that support affine gap\n\
                               costs. This will give you better alignments for\n\
                               longer indels but will also increase the runtime.\n\
                               (default: off)\n\
 -C/--max-consec-indels <int>  Maximum number of consecutive indels allowed.\n\
                               (default: computed based on avg. read length)\n\
 --fast-pairing                Mates are mapped individually. If the best\n\
                               alignments for the mates give a proper pair\n\
                               they are marked as paired in the output.\n\
                               If not they are reported as broken pair.\n\
 --pair-score-cutoff <0-1>     To find the best pairing all alignments of a\n\
                               read that have a score in the range of: \n\
                                 [top score * pair-score-cutoff; top score]\n\
                               are taken into account.\n\
 --skip-mate-check             Don't check that both mates have the same name\n\
                               (default: off)\n\
 --match-bonus <int>           Match score\n\
                               (default: 10, affine: 10, bs-mapping: 4)\n\
 --mismatch penalty <int>      Mismatch penalty\n\
                               (default: 15, affine: 15, bs-mapping: 2)\n\
 --gap-read-penalty <int>      Penalty for a gap in the read\n\
                               (default: 20, affine: 33, bs-mapping: 10)\n\
 --gap-ref-penalty <int>       Penalty for a gap in the reference\n\
                               (default: 20, affine: 33, bs-mapping: 10)\n\
 --gap-extend-penalty <int>    Penalty for extending a gap\n\
			                   (default: 20, affine: 3, bs-mapping: 10)\n\
 --match-bonus-tt <int>        Only for bs-mapping (default: 4)\n\
 --match-bonus-tc <int>        Only for bs-mapping (default: 4)\n\
 --color                       Colored text output (default: off)\n\
 --no-progress                 Don't print progress info while mapping\n\
                               (default: off)\n\
\n\
\n";
	printf(help_msg);
	exit(0);
}

// actually platform specific.../care
ulong const FileSize(char const * const filename) {
	FILE * fp = fopen(filename, "rb");
	if (fp == 0) {
		Log.Warning("Tried to get size of nonexistent file %s", filename);
		return 0;
	}

	if (fseek(fp, 0, SEEK_END) != 0)
		return 0;

	ulong end = ftell(fp);
	fclose(fp);
	return end;
}
<|endoftext|>


<commit_before>// use TGeo classes to draw a model of a nucleus
//
// Author: Otto Schaile

void nucleus(Int_t nProtons  = 40,Int_t  nNeutrons = 60)
{
   Double_t NeutronRadius = 60,
            ProtonRadius = 60,
            NucleusRadius,
            distance = 60;
   Double_t vol = nProtons + nNeutrons;
   vol = 3 * vol / (4 * TMath::Pi());

   NucleusRadius = distance * TMath::Power(vol, 1./3.);
//   cout << "NucleusRadius: " << NucleusRadius << endl;

   TGeoManager * geom = new TGeoManager("nucleus", "Model of a nucleus");
   geom->SetNsegments(40);
   TGeoMaterial *matEmptySpace = new TGeoMaterial("EmptySpace", 0, 0, 0);
   TGeoMaterial *matProton     = new TGeoMaterial("Proton"    , .938, 1., 10000.);
   TGeoMaterial *matNeutron    = new TGeoMaterial("Neutron"   , .935, 0., 10000.);

   TGeoMedium *EmptySpace = new TGeoMedium("Empty", 1, matEmptySpace);
   TGeoMedium *Proton     = new TGeoMedium("Proton", 1, matProton);
   TGeoMedium *Neutron    = new TGeoMedium("Neutron",1, matNeutron);

//  the space where the nucleus lives (top container volume)

   Double_t worldx = 200.;
   Double_t worldy = 200.;
   Double_t worldz = 200.;

   TGeoVolume *top = geom->MakeBox("WORLD", EmptySpace, worldx, worldy, worldz);
   geom->SetTopVolume(top);

   TGeoVolume * proton  = geom->MakeSphere("proton",  Proton,  0., ProtonRadius);
   TGeoVolume * neutron = geom->MakeSphere("neutron", Neutron, 0., NeutronRadius);
   proton->SetLineColor(kRed);
   neutron->SetLineColor(kBlue);

   Double_t x, y, z, dummy;
   Int_t i = 0;
   while ( i<  nProtons) {
      gRandom->Rannor(x, y);
      gRandom->Rannor(z,dummy);
      if ( TMath::Sqrt(x*x + y*y + z*z) < 1) {
         x = (2 * x - 1) * NucleusRadius;
         y = (2 * y - 1) * NucleusRadius;
         z = (2 * z - 1) * NucleusRadius;
         top->AddNode(proton, i, new TGeoTranslation(x, y, z));
         i++;
      }
   }
   i = 0;
   while ( i <  nNeutrons) {
      gRandom->Rannor(x, y);
      gRandom->Rannor(z,dummy);
      if ( TMath::Sqrt(x*x + y*y + z*z) < 1) {
         x = (2 * x - 1) * NucleusRadius;
         y = (2 * y - 1) * NucleusRadius;
         z = (2 * z - 1) * NucleusRadius;
         top->AddNode(neutron, i + nProtons, new TGeoTranslation(x, y, z));
         i++;
      }
   }
   geom->CloseGeometry();
   geom->SetVisLevel(4);
   top->Draw("ogl");
}
<commit_msg>Remove executable property.<commit_after>// use TGeo classes to draw a model of a nucleus
//
// Author: Otto Schaile

void nucleus(Int_t nProtons  = 40,Int_t  nNeutrons = 60)
{
   Double_t NeutronRadius = 60,
            ProtonRadius = 60,
            NucleusRadius,
            distance = 60;
   Double_t vol = nProtons + nNeutrons;
   vol = 3 * vol / (4 * TMath::Pi());

   NucleusRadius = distance * TMath::Power(vol, 1./3.);
//   cout << "NucleusRadius: " << NucleusRadius << endl;

   TGeoManager * geom = new TGeoManager("nucleus", "Model of a nucleus");
   geom->SetNsegments(40);
   TGeoMaterial *matEmptySpace = new TGeoMaterial("EmptySpace", 0, 0, 0);
   TGeoMaterial *matProton     = new TGeoMaterial("Proton"    , .938, 1., 10000.);
   TGeoMaterial *matNeutron    = new TGeoMaterial("Neutron"   , .935, 0., 10000.);

   TGeoMedium *EmptySpace = new TGeoMedium("Empty", 1, matEmptySpace);
   TGeoMedium *Proton     = new TGeoMedium("Proton", 1, matProton);
   TGeoMedium *Neutron    = new TGeoMedium("Neutron",1, matNeutron);

//  the space where the nucleus lives (top container volume)

   Double_t worldx = 200.;
   Double_t worldy = 200.;
   Double_t worldz = 200.;

   TGeoVolume *top = geom->MakeBox("WORLD", EmptySpace, worldx, worldy, worldz);
   geom->SetTopVolume(top);

   TGeoVolume * proton  = geom->MakeSphere("proton",  Proton,  0., ProtonRadius);
   TGeoVolume * neutron = geom->MakeSphere("neutron", Neutron, 0., NeutronRadius);
   proton->SetLineColor(kRed);
   neutron->SetLineColor(kBlue);

   Double_t x, y, z, dummy;
   Int_t i = 0;
   while ( i<  nProtons) {
      gRandom->Rannor(x, y);
      gRandom->Rannor(z,dummy);
      if ( TMath::Sqrt(x*x + y*y + z*z) < 1) {
         x = (2 * x - 1) * NucleusRadius;
         y = (2 * y - 1) * NucleusRadius;
         z = (2 * z - 1) * NucleusRadius;
         top->AddNode(proton, i, new TGeoTranslation(x, y, z));
         i++;
      }
   }
   i = 0;
   while ( i <  nNeutrons) {
      gRandom->Rannor(x, y);
      gRandom->Rannor(z,dummy);
      if ( TMath::Sqrt(x*x + y*y + z*z) < 1) {
         x = (2 * x - 1) * NucleusRadius;
         y = (2 * y - 1) * NucleusRadius;
         z = (2 * z - 1) * NucleusRadius;
         top->AddNode(neutron, i + nProtons, new TGeoTranslation(x, y, z));
         i++;
      }
   }
   geom->CloseGeometry();
   geom->SetVisLevel(4);
   top->Draw("ogl");
}
<|endoftext|>


<commit_before>/**
 * This file is part of Slideshow.
 * Copyright (C) 2008 David Sveningsson <ext@sidvind.com>
 *
 * Slideshow is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Slideshow is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Slideshow.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"
#include "OS.h"
#include "Log.h"
//#include <cstdio>
#include "Exceptions.h"
#include <X11/Xlib.h>
#include <X11/cursorfont.h>

#if HAVE_XRANDR
#	include <X11/extensions/Xrandr.h>
#endif /* HAVE_XRANDR */

#if HAVE_XF86VIDMODE
#	include <X11/extensions/xf86vmode.h>
#endif /* HAVE_XF86VIDMODE */

#include <GL/glx.h>

typedef struct __glx_state {
	Display* dpy;
	Window win;
	Window root;
	GLXContext ctx;
	GLXDrawable glx_drawable;
	int width;
	int height;
	bool in_fullscreen;
	bool fullscreen_available;
} glx_state;

/* @todo Remove usage of this global state */
static glx_state g;

#if HAVE_XRANDR
XRRScreenConfiguration* saved_screen_config = NULL;
Rotation saved_rotation;
int saved_size_id = -1;
#endif

#if HAVE_XF86VIDMODE
static XF86VidModeModeInfo **vidmodes;
#endif /* HAVE_XF86VIDMODE */

static Atom wm_delete_window;
static Atom wm_fullscreen;
static Atom wm_state;

Cursor default_cursor = 0;
Cursor no_cursor = 0;

enum {
	_NET_WM_STATE_REMOVE =0,
	_NET_WM_STATE_ADD = 1,
	_NET_WM_STATE_TOGGLE =2
};

/**
 * Generates X interal atoms.
 * @param dpy Specifies the connection to the X server.
 */
void generate_atoms(Display* dpy){
	wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
	wm_fullscreen = XInternAtom(dpy,"_NET_WM_STATE_FULLSCREEN", False);
	wm_state = XInternAtom(dpy, "_NET_WM_STATE", False);
}

void generate_cursors(Display* dpy, Window win){
	Pixmap blank;
	XColor dummy;
	char data[1] = {0};

	blank = XCreateBitmapFromData (dpy, win, data, 1, 1);
	no_cursor = XCreatePixmapCursor(dpy, blank, blank, &dummy, &dummy, 0, 0);
	XFreePixmap (dpy, blank);
	default_cursor = XCreateFontCursor(dpy, XC_left_ptr);
}

void set_cursor(glx_state* state, Cursor cursor){
	XDefineCursor(state->dpy, state->win, cursor);
}

int doubleBufferAttributes[] = {
	GLX_DRAWABLE_TYPE,	GLX_WINDOW_BIT,
	GLX_RENDER_TYPE,	GLX_RGBA_BIT,
	GLX_DOUBLEBUFFER,	True,
	None
};

/**
 * Return a glXVisualInfo from a FBConfig attribute list.
 * @param dpy Specifies the connection to the X server.
 * @param screen  Specifies the screen number.
 * @param attribList Specifies a list of boolean attributes and integer attribute/value pairs.  The last attribute must be None.
 */
XVisualInfo* glXVisualFromFBConfigAttributes(Display* dpy, int screen, int* attribList){
	int configs = 0;

	GLXFBConfig* fbConfigs = glXChooseFBConfig(dpy, screen, attribList, &configs);
	if ( !fbConfigs ) {
		throw XlibException( "No double buffered config available\n" );
	}

	XVisualInfo* visual = glXGetVisualFromFBConfig(dpy, fbConfigs[0]);
	if ( !visual ){
		throw XlibException("No appropriate visual found\n");
	}

	return visual;
}

void store_display_config(Display* dpy, Window root){
#if HAVE_XRANDR
	saved_screen_config = XRRGetScreenInfo(dpy, root);
	saved_size_id = XRRConfigCurrentConfiguration(saved_screen_config, &saved_rotation);
#elif HAVE_XF86VIDMODE

#endif
}

enum fullscreen_state_t {
	ENABLE = _NET_WM_STATE_ADD,
	DISABLE = _NET_WM_STATE_REMOVE,
	TOGGLE = _NET_WM_STATE_TOGGLE
};

/**
 * Checks if the specified resolution is available. It is important that the
 * exact resolution requested is used since the slides has been created in that
 * resolution. No scaling must occur.
 *
 * @param dpy Specifies the connection to the X server.
 * @param root Specifies the X window.
 * @param width
 * @param height
 */
bool resolution_available(Display* dpy, Window root, int width, int height){
#if HAVE_XRANDR
	XRRScreenConfiguration* screen_config = XRRGetScreenInfo(dpy, root);

	int nsizes;
	XRRScreenSize *sizes = XRRConfigSizes(screen_config, &nsizes);

	for ( int i = 0; i < nsizes; i++ ){
		if ( width == sizes[i].width && height == sizes[i].height ){
			return true;
		}
	}
#elif HAVE_XF86VIDMODE
#	error NOT IMPLEMENTED
#endif
	return false;
}

void enter_fullscreen(glx_state* state){
#if HAVE_XRANDR
#elif HAVE_XF86VIDMODE
#	error NOT IMPLEMENTED
#endif
	state->in_fullscreen = true;
}

void exit_fullscreen(glx_state* state){
#if HAVE_XRANDR
#elif HAVE_XF86VIDMODE
#	error NOT IMPLEMENTED
#endif
	state->in_fullscreen = false;
}

/**
 * Enable, disable or toggle fullscreen mode.
 * @param dpy Specifies the connection to the X server.
 * @param win Specifies the X window.
 * @param status Action to perform.
 */
void set_fullscreen(glx_state* state, fullscreen_state_t status){
	if ( !state->fullscreen_available ){
		Log::message(Log::Warning, "Graphics: Cannot enter fullscreen mode as the requested resolution %dx%d isn't available.\n", state->width, state->height);
		return;
	}

	switch ( status ) {
		case ENABLE: enter_fullscreen(state); break;
		case DISABLE: exit_fullscreen(state); break;
		case TOGGLE:
			if ( state->in_fullscreen ){
				exit_fullscreen(state);
			} else {
				enter_fullscreen(state);
			}
			break;
	}

	/* Notify the window manager to enable/disable the window decorations */
	XEvent xev;

	xev.xclient.type =         ClientMessage;
	xev.xclient.serial =       0;
	xev.xclient.send_event =   True;
	xev.xclient.window =       state->win;
	xev.xclient.message_type = wm_state;
	xev.xclient.format =       32;

	xev.xclient.data.l[0] = status;
	xev.xclient.data.l[1] = wm_fullscreen;
	xev.xclient.data.l[2] = 0;

	XSendEvent(state->dpy, state->root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
}

bool is_window_delete_event(XEvent* event){
	return (unsigned int)event->xclient.data.l[0] == wm_delete_window;
}

void OS::init_view(int width, int height, bool fullscreen){
	Display* dpy = XOpenDisplay(NULL);

	if( !dpy ) {
		throw XlibException("Could not connect to an X server");
	}

	Window root = DefaultRootWindow(dpy);
	XVisualInfo* vi = glXVisualFromFBConfigAttributes(dpy, DefaultScreen(dpy), doubleBufferAttributes);

	bool fullscreen_available = resolution_available(dpy, root, width, height);
	if ( fullscreen && !fullscreen_available ){
		throw XlibException("The specified resolution %dx%d is not available in fullscreen mode", width, height);
	}

	store_display_config(dpy, root);

	unsigned long mask = CWColormap | CWEventMask;
	Colormap cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
	XSetWindowAttributes swa;
	swa.colormap = cmap;
	swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask ;

	Window win = XCreateWindow(dpy, root, 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, mask, &swa);

	XStoreName(dpy, win, "Slideshow");

	XMapWindow(dpy, win);

	GLXContext ctx = glXCreateContext(dpy, vi, NULL, GL_TRUE);
	glXMakeCurrent(dpy, win, ctx);
	GLXDrawable glx_drawable = glXGetCurrentDrawable();

	g.dpy = dpy;
	g.win = win;
	g.root = root;
	g.ctx = ctx;
	g.glx_drawable = glx_drawable;
	g.width = width;
	g.height = height;
	g.in_fullscreen = false;
	g.fullscreen_available = fullscreen_available;

	generate_atoms(dpy);

	XSetWMProtocols(dpy, win, &wm_delete_window, 1);

	/* make a blank cursor */
	generate_cursors(dpy, win);
	set_cursor(&g, no_cursor);

	if ( fullscreen ){
		Log::message(Log::Verbose, "Graphics: Going fullscreen\n");
		set_fullscreen(&g, ENABLE);
	}
}

void OS::swap_gl_buffers(){
	glXSwapBuffers(g.dpy, g.glx_drawable);
}

void OS::cleanup(){
	if ( g.in_fullscreen ){
		exit_fullscreen(&g);
	}

	set_cursor(&g, default_cursor);
  glXDestroyContext(g.dpy, g.ctx);

  if( g.win && g.dpy ){
	XDestroyWindow(g.dpy, g.win );
	g.win = (Window) 0;
  }

  if ( g.dpy ){
	XCloseDisplay( g.dpy );
	g.dpy = 0;
  }
}

void OS::poll_events(bool& running){
	XEvent event;

	while ( XPending(g.dpy) > 0 ){
		XNextEvent(g.dpy, &event);
		switch (event.type){
			case KeyPress:
				if ( event.xkey.state == 24 && event.xkey.keycode == 36 ){
					set_fullscreen(&g, TOGGLE);
					continue;
				}

				if ( event.xkey.keycode == 9 ){
					running = false;

					continue;
				}

				break;

			case ClientMessage:
				if( is_window_delete_event(&event) ){
					running = false;
					continue;
				}
				break;
		}
	}
}
<commit_msg>Set fullscreen resolution<commit_after>/**
 * This file is part of Slideshow.
 * Copyright (C) 2008 David Sveningsson <ext@sidvind.com>
 *
 * Slideshow is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Slideshow is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Slideshow.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"
#include "OS.h"
#include "Log.h"
//#include <cstdio>
#include "Exceptions.h"
#include <X11/Xlib.h>
#include <X11/cursorfont.h>

#if HAVE_XRANDR
#	include <X11/extensions/Xrandr.h>
#endif /* HAVE_XRANDR */

#if HAVE_XF86VIDMODE
#	include <X11/extensions/xf86vmode.h>
#endif /* HAVE_XF86VIDMODE */

#include <GL/glx.h>

typedef struct __glx_state {
	Display* dpy;
	Window win;
	Window root;
	GLXContext ctx;
	GLXDrawable glx_drawable;
	int width;
	int height;
	bool in_fullscreen;
	bool fullscreen_available;
#if HAVE_XRANDR
	XRRScreenConfiguration* screen_config;
	int size_id;
#endif
} glx_state;

/* @todo Remove usage of this global state */
static glx_state g;

#if HAVE_XRANDR
XRRScreenConfiguration* saved_screen_config = NULL;
Rotation saved_rotation;
int saved_size_id = -1;
#endif

#if HAVE_XF86VIDMODE
static XF86VidModeModeInfo **vidmodes;
#endif /* HAVE_XF86VIDMODE */

static Atom wm_delete_window;
static Atom wm_fullscreen;
static Atom wm_state;

Cursor default_cursor = 0;
Cursor no_cursor = 0;

enum {
	_NET_WM_STATE_REMOVE =0,
	_NET_WM_STATE_ADD = 1,
	_NET_WM_STATE_TOGGLE =2
};

/**
 * Generates X interal atoms.
 * @param dpy Specifies the connection to the X server.
 */
void generate_atoms(Display* dpy){
	wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
	wm_fullscreen = XInternAtom(dpy,"_NET_WM_STATE_FULLSCREEN", False);
	wm_state = XInternAtom(dpy, "_NET_WM_STATE", False);
}

void generate_cursors(Display* dpy, Window win){
	Pixmap blank;
	XColor dummy;
	char data[1] = {0};

	blank = XCreateBitmapFromData (dpy, win, data, 1, 1);
	no_cursor = XCreatePixmapCursor(dpy, blank, blank, &dummy, &dummy, 0, 0);
	XFreePixmap (dpy, blank);
	default_cursor = XCreateFontCursor(dpy, XC_left_ptr);
}

void set_cursor(glx_state* state, Cursor cursor){
	XDefineCursor(state->dpy, state->win, cursor);
}

int doubleBufferAttributes[] = {
	GLX_DRAWABLE_TYPE,	GLX_WINDOW_BIT,
	GLX_RENDER_TYPE,	GLX_RGBA_BIT,
	GLX_DOUBLEBUFFER,	True,
	None
};

/**
 * Return a glXVisualInfo from a FBConfig attribute list.
 * @param dpy Specifies the connection to the X server.
 * @param screen  Specifies the screen number.
 * @param attribList Specifies a list of boolean attributes and integer attribute/value pairs.  The last attribute must be None.
 */
XVisualInfo* glXVisualFromFBConfigAttributes(Display* dpy, int screen, int* attribList){
	int configs = 0;

	GLXFBConfig* fbConfigs = glXChooseFBConfig(dpy, screen, attribList, &configs);
	if ( !fbConfigs ) {
		throw XlibException( "No double buffered config available\n" );
	}

	XVisualInfo* visual = glXGetVisualFromFBConfig(dpy, fbConfigs[0]);
	if ( !visual ){
		throw XlibException("No appropriate visual found\n");
	}

	return visual;
}

void store_display_config(Display* dpy, Window root){
#if HAVE_XRANDR
	saved_screen_config = XRRGetScreenInfo(dpy, root);
	saved_size_id = XRRConfigCurrentConfiguration(saved_screen_config, &saved_rotation);
#elif HAVE_XF86VIDMODE

#endif
}

enum fullscreen_state_t {
	ENABLE = _NET_WM_STATE_ADD,
	DISABLE = _NET_WM_STATE_REMOVE,
	TOGGLE = _NET_WM_STATE_TOGGLE
};

/**
 * Checks if the specified resolution is available. It is important that the
 * exact resolution requested is used since the slides has been created in that
 * resolution. No scaling must occur.
 *
 * @param dpy Specifies the connection to the X server.
 * @param root Specifies the X window.
 * @param width
 * @param height
 */
bool resolution_available(Display* dpy, Window root, int width, int height){
#if HAVE_XRANDR
	XRRScreenConfiguration* screen_config = XRRGetScreenInfo(dpy, root);
	g.screen_config = screen_config;

	int nsizes;
	XRRScreenSize *sizes = XRRConfigSizes(screen_config, &nsizes);

	for ( int i = 0; i < nsizes; i++ ){
		if ( width == sizes[i].width && height == sizes[i].height ){
			g.size_id = i;
			return true;
		}
	}
#elif HAVE_XF86VIDMODE
#	error NOT IMPLEMENTED
#endif
	return false;
}

void enter_fullscreen(glx_state* state){
#if HAVE_XRANDR
	XRRSetScreenConfig(state->dpy, state->screen_config, state->root, state->size_id, saved_rotation, CurrentTime);
#elif HAVE_XF86VIDMODE
#	error NOT IMPLEMENTED
#endif
	state->in_fullscreen = true;
}

void exit_fullscreen(glx_state* state){
#if HAVE_XRANDR
	XRRSetScreenConfig(state->dpy, saved_screen_config, state->root, saved_size_id, saved_rotation, CurrentTime);
#elif HAVE_XF86VIDMODE
#	error NOT IMPLEMENTED
#endif
	state->in_fullscreen = false;
}

/**
 * Enable, disable or toggle fullscreen mode.
 * @param dpy Specifies the connection to the X server.
 * @param win Specifies the X window.
 * @param status Action to perform.
 */
void set_fullscreen(glx_state* state, fullscreen_state_t status){
	if ( !state->fullscreen_available ){
		Log::message(Log::Warning, "Graphics: Cannot enter fullscreen mode as the requested resolution %dx%d isn't available.\n", state->width, state->height);
		return;
	}

	switch ( status ) {
		case ENABLE: enter_fullscreen(state); break;
		case DISABLE: exit_fullscreen(state); break;
		case TOGGLE:
			if ( state->in_fullscreen ){
				exit_fullscreen(state);
			} else {
				enter_fullscreen(state);
			}
			break;
	}

	/* Notify the window manager to enable/disable the window decorations */
	XEvent xev;

	xev.xclient.type =         ClientMessage;
	xev.xclient.serial =       0;
	xev.xclient.send_event =   True;
	xev.xclient.window =       state->win;
	xev.xclient.message_type = wm_state;
	xev.xclient.format =       32;

	xev.xclient.data.l[0] = status;
	xev.xclient.data.l[1] = wm_fullscreen;
	xev.xclient.data.l[2] = 0;

	XSendEvent(state->dpy, state->root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);
}

bool is_window_delete_event(XEvent* event){
	return (unsigned int)event->xclient.data.l[0] == wm_delete_window;
}

void OS::init_view(int width, int height, bool fullscreen){
	Display* dpy = XOpenDisplay(NULL);

	if( !dpy ) {
		throw XlibException("Could not connect to an X server");
	}

	Window root = DefaultRootWindow(dpy);
	XVisualInfo* vi = glXVisualFromFBConfigAttributes(dpy, DefaultScreen(dpy), doubleBufferAttributes);

	bool fullscreen_available = resolution_available(dpy, root, width, height);
	if ( fullscreen && !fullscreen_available ){
		throw XlibException("The specified resolution %dx%d is not available in fullscreen mode", width, height);
	}

	store_display_config(dpy, root);

	unsigned long mask = CWColormap | CWEventMask;
	Colormap cmap = XCreateColormap(dpy, root, vi->visual, AllocNone);
	XSetWindowAttributes swa;
	swa.colormap = cmap;
	swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask ;

	if ( fullscreen ){
		swa.override_redirect = True;
		swa.backing_store = NotUseful;
		swa.save_under = False;
	}

	Window win = XCreateWindow(dpy, root, 0, 0, width, height, 0, vi->depth, InputOutput, vi->visual, mask, &swa);

	XStoreName(dpy, win, "Slideshow");

	XMapWindow(dpy, win);

	GLXContext ctx = glXCreateContext(dpy, vi, NULL, GL_TRUE);
	glXMakeCurrent(dpy, win, ctx);
	GLXDrawable glx_drawable = glXGetCurrentDrawable();

	g.dpy = dpy;
	g.win = win;
	g.root = root;
	g.ctx = ctx;
	g.glx_drawable = glx_drawable;
	g.width = width;
	g.height = height;
	g.in_fullscreen = false;
	g.fullscreen_available = fullscreen_available;

	generate_atoms(dpy);

	XSetWMProtocols(dpy, win, &wm_delete_window, 1);

	/* make a blank cursor */
	generate_cursors(dpy, win);
	set_cursor(&g, no_cursor);

	if ( fullscreen ){
		Log::message(Log::Verbose, "Graphics: Going fullscreen\n");
		set_fullscreen(&g, ENABLE);
	}
}

void OS::swap_gl_buffers(){
	glXSwapBuffers(g.dpy, g.glx_drawable);
}

void OS::cleanup(){
	if ( g.in_fullscreen ){
		exit_fullscreen(&g);
	}

	set_cursor(&g, default_cursor);
  glXDestroyContext(g.dpy, g.ctx);

  if( g.win && g.dpy ){
	XDestroyWindow(g.dpy, g.win );
	g.win = (Window) 0;
  }

  if ( g.dpy ){
	XCloseDisplay( g.dpy );
	g.dpy = 0;
  }
}

void OS::poll_events(bool& running){
	XEvent event;

	while ( XPending(g.dpy) > 0 ){
		XNextEvent(g.dpy, &event);
		switch (event.type){
			case KeyPress:
				if ( event.xkey.state == 24 && event.xkey.keycode == 36 ){
					set_fullscreen(&g, TOGGLE);
					continue;
				}

				if ( event.xkey.keycode == 9 ){
					running = false;

					continue;
				}

				break;

			case ClientMessage:
				if( is_window_delete_event(&event) ){
					running = false;
					continue;
				}
				break;
		}
	}
}
<|endoftext|>


<commit_before>#ifndef COLOR_HPP_
#define COLOR_HPP_

#include "FAST/Data/DataTypes.hpp"

namespace fast {

class Color : public Vector3f {
    public:
        Color() : Vector3f(0,0,0) {};
        Color(float red, float green, float blue) : Vector3f(red, green, blue) {};
        float getRedValue() const {
            return x();
        }
        float getGreenValue() const {
            return y();
        }
        float getBlueValue() const {
            return z();
        }
        static Color Red() {
            return Color(1,0,0);
        }
        static Color Green() {
            return Color(0,1,0);
        }
        static Color Blue() {
            return Color(0,0,1);
        }
        static Color White() {
            return Color(1,1,1);
        }
        static Color Black() {
            return Color(0,0,0);
        }
        static Color Yellow() {
            return Color(1, 1, 0);
        }
        static Color Purple() {
            return Color(1, 0, 1);
        }

};

}

#endif
<commit_msg>added cyan color<commit_after>#ifndef COLOR_HPP_
#define COLOR_HPP_

#include "FAST/Data/DataTypes.hpp"

namespace fast {

class Color : public Vector3f {
    public:
        Color() : Vector3f(0,0,0) {};
        Color(float red, float green, float blue) : Vector3f(red, green, blue) {};
        float getRedValue() const {
            return x();
        }
        float getGreenValue() const {
            return y();
        }
        float getBlueValue() const {
            return z();
        }
        static Color Red() {
            return Color(1,0,0);
        }
        static Color Green() {
            return Color(0,1,0);
        }
        static Color Blue() {
            return Color(0,0,1);
        }
        static Color White() {
            return Color(1,1,1);
        }
        static Color Black() {
            return Color(0,0,0);
        }
        static Color Yellow() {
            return Color(1, 1, 0);
        }
        static Color Purple() {
            return Color(1, 0, 1);
        }
        static Color Cyan() {
            return Color(0, 1, 1);
        }

};

}

#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * TIGHTDB CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2012] TightDB Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of TightDB Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to TightDB Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from TightDB Incorporated.
 *
 **************************************************************************/
#ifndef TIGHTDB_TEST_UTIL_UNIT_TEST_HPP
#define TIGHTDB_TEST_UTIL_UNIT_TEST_HPP

#include <cstring>
#include <string>
#include <sstream>
#include <ostream>

#include <tightdb/util/type_traits.hpp>
#include <tightdb/util/safe_int_ops.hpp>

#define CHECK(cond) \
    tightdb::test_util::unit_test::test(bool(cond), __FILE__, __LINE__, #cond)

#define CHECK_EQUAL(a,b) \
    tightdb::test_util::unit_test::test_equal((a), (b), __FILE__, __LINE__, #a, #b)

#define CHECK_NOT_EQUAL(a,b) \
    tightdb::test_util::unit_test::test_not_equal((a), (b), __FILE__, __LINE__, #a, #b)

#define CHECK_LESS(a,b) \
    tightdb::test_util::unit_test::test_less((a), (b), __FILE__, __LINE__, #a, #b)

#define CHECK_LESS_EQUAL(a,b) \
    tightdb::test_util::unit_test::test_less_equal((a), (b), __FILE__, __LINE__, #a, #b)

#define CHECK_GREATER(a,b) \
    tightdb::test_util::unit_test::test_greater((a), (b), __FILE__, __LINE__, #a, #b)

#define CHECK_GREATER_EQUAL(a,b) \
    tightdb::test_util::unit_test::test_greater_equal((a), (b), __FILE__, __LINE__, #a, #b)

#define CHECK_THROW(expr, exception) \
    do { \
        try { \
            (expr); \
            tightdb::test_util::unit_test::throw_failed(__FILE__, __LINE__, #expr, #exception); \
        } \
        catch (exception&) { \
            tightdb::test_util::unit_test::check_succeeded(); \
        } \
    } while(false)

#define TEST(name) \
    void Tightdb_UnitTest__##name();            \
    tightdb::test_util::unit_test::RegisterTest \
    tightdb_unit_test__##name(__FILE__, __LINE__, #name, &Tightdb_UnitTest__##name); \
    void Tightdb_UnitTest__##name()

namespace tightdb {
namespace test_util {
namespace unit_test {

struct RegisterTest {
    RegisterTest(const char* file, long line, const char* name, void (*func)());
};

void cond_failed(const char* file, long line, const char* cond_text);
void comp_failed(const char* file, long line, const char* macro_name,
                 const char* a_text, const char* b_text,
                 const std::string& a_val, const std::string& b_val);
void throw_failed(const char* file, long line, const char* expr_text, const char* exception);

void check_succeeded();

template<class A, class B, bool both_are_integral> struct Compare {
    static bool equal(const A& a, const B& b)
    {
        return a == b;
    }
    static bool less(const A& a, const B& b)
    {
        return a < b;
    }
};
template<class A, class B> struct Compare<A, B, true> {
    static bool equal(const A& a, const B& b)
    {
        return util::int_equal_to(a,b);
    }
    static bool less(const A& a, const B& b)
    {
        return util::int_less_than(a,b);
    }
};

template<class A, class B> inline bool equal(const A& a, const B& b)
{
    const bool both_are_integral = util::IsIntegral<A>::value && util::IsIntegral<B>::value;
    return Compare<A, B, both_are_integral>::equal(a,b);
}
template<class A, class B> inline bool less(const A& a, const B& b)
{
    const bool both_are_integral = util::IsIntegral<A>::value && util::IsIntegral<B>::value;
    return Compare<A, B, both_are_integral>::less(a,b);
}

// Special hooks for comparing zero terminated strings
inline bool equal(const char* a, const char* b)
{
    return std::strcmp(a,b) == 0;
}
inline bool less(const char* a, const char* b)
{
    return std::strcmp(a,b) < 0;
}

inline void test(bool cond, const char* file, long line, const char* cond_text)
{
    if (TIGHTDB_LIKELY(cond)) {
        check_succeeded();
    }
    else {
        cond_failed(file, line, cond_text);
    }
}

template<class A, class B>
inline void test_compare(bool cond, const A& a, const B& b, const char* file, long line,
                         const char* macro_name, const char* a_text, const char* b_text)
{
    if (TIGHTDB_LIKELY(cond)) {
        check_succeeded();
    }
    else {
        std::string a_val, b_val;
        {
            std::ostringstream out;
            out << a;
            a_val = out.str();
        }
        {
            std::ostringstream out;
            out << b;
            b_val = out.str();
        }
        comp_failed(file, line, macro_name, a_text, b_text, a_val, b_val);
    }
}

template<class A, class B>
inline void test_equal(const A& a, const B& b, const char* file, long line,
                       const char* a_text, const char* b_text)
{
    bool cond = equal(a,b);
    test_compare(cond, a, b, file, line, "TEST_EQUAL", a_text, b_text);
}

template<class A, class B>
inline void test_not_equal(const A& a, const B& b, const char* file, long line,
                           const char* a_text, const char* b_text)
{
    bool cond = !equal(a,b);
    test_compare(cond, a, b, file, line, "TEST_NOT_EQUAL", a_text, b_text);
}

template<class A, class B>
inline void test_less(const A& a, const B& b, const char* file, long line,
                      const char* a_text, const char* b_text)
{
    bool cond = less(a,b);
    test_compare(cond, a, b, file, line, "TEST_LESS", a_text, b_text);
}

template<class A, class B>
inline void test_less_equal(const A& a, const B& b, const char* file, long line,
                            const char* a_text, const char* b_text)
{
    bool cond = !less(b,a);
    test_compare(cond, a, b, file, line, "TEST_LESS_EQUAL", a_text, b_text);
}

template<class A, class B>
inline void test_greater(const A& a, const B& b, const char* file, long line,
                         const char* a_text, const char* b_text)
{
    bool cond = less(b,a);
    test_compare(cond, a, b, file, line, "TEST_GREATER", a_text, b_text);
}

template<class A, class B>
inline void test_greater_equal(const A& a, const B& b, const char* file, long line,
                               const char* a_text, const char* b_text)
{
    bool cond = !less(a,b);
    test_compare(cond, a, b, file, line, "TEST_GREATER_EQUAL", a_text, b_text);
}

struct Location {
    const char* test_name;
    const char* file_name;
    long line_number;
};

struct Summary {
    long num_included_tests;
    long num_failed_tests;
    long num_excluded_tests;
    long num_tests;
    long num_checks;
    long num_failed_checks;
    double elapsed_seconds;
};

class Reporter {
public:
    virtual void begin(const Location&);
    virtual void fail(const Location&, const std::string& message);
    virtual void end(const Location&, double elapsed_seconds);
    virtual void summary(const Summary&);
    virtual ~Reporter() TIGHTDB_NOEXCEPT {}
};

class Filter {
public:
    virtual bool include(const Location&) = 0;
    virtual ~Filter() TIGHTDB_NOEXCEPT {}
};

bool run(Reporter* = 0, Filter* = 0);

class SimpleReporter: public Reporter {
public:
    explicit SimpleReporter(bool report_progress = false);

    void begin(const Location&) TIGHTDB_OVERRIDE;
    void fail(const Location&, const std::string&) TIGHTDB_OVERRIDE;
    void summary(const Summary&) TIGHTDB_OVERRIDE;

protected:
    bool m_report_progress;
};

/// Generates output that is compatible with the XML output of
/// UnitTest++. Caller receives ownership of the reporter.
Reporter* create_xml_reporter(std::ostream&);

/// Run only those tests whose name is both included and not excluded.
///
/// EBNF:
///
///     filter = { include-pattern }, [ '-', { exclude-pattern } ]
///     include-pattern = pattern
///     exclude-pattern = pattern
///
/// Each pattern is a string containing no white-space, and optionally
/// containg `*` wild cards. Each `*` matches zero or more arbitrary
/// characters.
///
/// An empty filter is functionally equivalent to "*" and a filter on
/// the form "- ..." is equivalent to "* - ...".
///
/// Examples:
///
///     ""                 everything
///     "*"                everything
///     "* -"              everything
///     "-"                everything
///     "- *"              nothing
///     "* - *"            nothing
///     "Array_Count"      only "Array_Count"
///     "- Array_*"        all except those that match "Array_*"
///     "Array_* Column_* - *_Count"
Filter* create_wildcard_filter(const std::string&);

} // namespace unit_test
} // namespace test_util
} // namespace tightdb

#endif // TIGHTDB_TEST_UTIL_UNIT_TEST_HPP
<commit_msg>Add note about the possibility of producing JUnit XML output<commit_after>/*************************************************************************
 *
 * TIGHTDB CONFIDENTIAL
 * __________________
 *
 *  [2011] - [2012] TightDB Inc
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of TightDB Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to TightDB Incorporated
 * and its suppliers and may be covered by U.S. and Foreign Patents,
 * patents in process, and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from TightDB Incorporated.
 *
 **************************************************************************/
#ifndef TIGHTDB_TEST_UTIL_UNIT_TEST_HPP
#define TIGHTDB_TEST_UTIL_UNIT_TEST_HPP

#include <cstring>
#include <string>
#include <sstream>
#include <ostream>

#include <tightdb/util/type_traits.hpp>
#include <tightdb/util/safe_int_ops.hpp>

#define CHECK(cond) \
    tightdb::test_util::unit_test::test(bool(cond), __FILE__, __LINE__, #cond)

#define CHECK_EQUAL(a,b) \
    tightdb::test_util::unit_test::test_equal((a), (b), __FILE__, __LINE__, #a, #b)

#define CHECK_NOT_EQUAL(a,b) \
    tightdb::test_util::unit_test::test_not_equal((a), (b), __FILE__, __LINE__, #a, #b)

#define CHECK_LESS(a,b) \
    tightdb::test_util::unit_test::test_less((a), (b), __FILE__, __LINE__, #a, #b)

#define CHECK_LESS_EQUAL(a,b) \
    tightdb::test_util::unit_test::test_less_equal((a), (b), __FILE__, __LINE__, #a, #b)

#define CHECK_GREATER(a,b) \
    tightdb::test_util::unit_test::test_greater((a), (b), __FILE__, __LINE__, #a, #b)

#define CHECK_GREATER_EQUAL(a,b) \
    tightdb::test_util::unit_test::test_greater_equal((a), (b), __FILE__, __LINE__, #a, #b)

#define CHECK_THROW(expr, exception) \
    do { \
        try { \
            (expr); \
            tightdb::test_util::unit_test::throw_failed(__FILE__, __LINE__, #expr, #exception); \
        } \
        catch (exception&) { \
            tightdb::test_util::unit_test::check_succeeded(); \
        } \
    } while(false)

#define TEST(name) \
    void Tightdb_UnitTest__##name();            \
    tightdb::test_util::unit_test::RegisterTest \
    tightdb_unit_test__##name(__FILE__, __LINE__, #name, &Tightdb_UnitTest__##name); \
    void Tightdb_UnitTest__##name()

namespace tightdb {
namespace test_util {
namespace unit_test {

struct RegisterTest {
    RegisterTest(const char* file, long line, const char* name, void (*func)());
};

void cond_failed(const char* file, long line, const char* cond_text);
void comp_failed(const char* file, long line, const char* macro_name,
                 const char* a_text, const char* b_text,
                 const std::string& a_val, const std::string& b_val);
void throw_failed(const char* file, long line, const char* expr_text, const char* exception);

void check_succeeded();

template<class A, class B, bool both_are_integral> struct Compare {
    static bool equal(const A& a, const B& b)
    {
        return a == b;
    }
    static bool less(const A& a, const B& b)
    {
        return a < b;
    }
};
template<class A, class B> struct Compare<A, B, true> {
    static bool equal(const A& a, const B& b)
    {
        return util::int_equal_to(a,b);
    }
    static bool less(const A& a, const B& b)
    {
        return util::int_less_than(a,b);
    }
};

template<class A, class B> inline bool equal(const A& a, const B& b)
{
    const bool both_are_integral = util::IsIntegral<A>::value && util::IsIntegral<B>::value;
    return Compare<A, B, both_are_integral>::equal(a,b);
}
template<class A, class B> inline bool less(const A& a, const B& b)
{
    const bool both_are_integral = util::IsIntegral<A>::value && util::IsIntegral<B>::value;
    return Compare<A, B, both_are_integral>::less(a,b);
}

// Special hooks for comparing zero terminated strings
inline bool equal(const char* a, const char* b)
{
    return std::strcmp(a,b) == 0;
}
inline bool less(const char* a, const char* b)
{
    return std::strcmp(a,b) < 0;
}

inline void test(bool cond, const char* file, long line, const char* cond_text)
{
    if (TIGHTDB_LIKELY(cond)) {
        check_succeeded();
    }
    else {
        cond_failed(file, line, cond_text);
    }
}

template<class A, class B>
inline void test_compare(bool cond, const A& a, const B& b, const char* file, long line,
                         const char* macro_name, const char* a_text, const char* b_text)
{
    if (TIGHTDB_LIKELY(cond)) {
        check_succeeded();
    }
    else {
        std::string a_val, b_val;
        {
            std::ostringstream out;
            out << a;
            a_val = out.str();
        }
        {
            std::ostringstream out;
            out << b;
            b_val = out.str();
        }
        comp_failed(file, line, macro_name, a_text, b_text, a_val, b_val);
    }
}

template<class A, class B>
inline void test_equal(const A& a, const B& b, const char* file, long line,
                       const char* a_text, const char* b_text)
{
    bool cond = equal(a,b);
    test_compare(cond, a, b, file, line, "TEST_EQUAL", a_text, b_text);
}

template<class A, class B>
inline void test_not_equal(const A& a, const B& b, const char* file, long line,
                           const char* a_text, const char* b_text)
{
    bool cond = !equal(a,b);
    test_compare(cond, a, b, file, line, "TEST_NOT_EQUAL", a_text, b_text);
}

template<class A, class B>
inline void test_less(const A& a, const B& b, const char* file, long line,
                      const char* a_text, const char* b_text)
{
    bool cond = less(a,b);
    test_compare(cond, a, b, file, line, "TEST_LESS", a_text, b_text);
}

template<class A, class B>
inline void test_less_equal(const A& a, const B& b, const char* file, long line,
                            const char* a_text, const char* b_text)
{
    bool cond = !less(b,a);
    test_compare(cond, a, b, file, line, "TEST_LESS_EQUAL", a_text, b_text);
}

template<class A, class B>
inline void test_greater(const A& a, const B& b, const char* file, long line,
                         const char* a_text, const char* b_text)
{
    bool cond = less(b,a);
    test_compare(cond, a, b, file, line, "TEST_GREATER", a_text, b_text);
}

template<class A, class B>
inline void test_greater_equal(const A& a, const B& b, const char* file, long line,
                               const char* a_text, const char* b_text)
{
    bool cond = !less(a,b);
    test_compare(cond, a, b, file, line, "TEST_GREATER_EQUAL", a_text, b_text);
}

struct Location {
    const char* test_name;
    const char* file_name;
    long line_number;
};

struct Summary {
    long num_included_tests;
    long num_failed_tests;
    long num_excluded_tests;
    long num_tests;
    long num_checks;
    long num_failed_checks;
    double elapsed_seconds;
};

class Reporter {
public:
    virtual void begin(const Location&);
    virtual void fail(const Location&, const std::string& message);
    virtual void end(const Location&, double elapsed_seconds);
    virtual void summary(const Summary&);
    virtual ~Reporter() TIGHTDB_NOEXCEPT {}
};

class Filter {
public:
    virtual bool include(const Location&) = 0;
    virtual ~Filter() TIGHTDB_NOEXCEPT {}
};

bool run(Reporter* = 0, Filter* = 0);

class SimpleReporter: public Reporter {
public:
    explicit SimpleReporter(bool report_progress = false);

    void begin(const Location&) TIGHTDB_OVERRIDE;
    void fail(const Location&, const std::string&) TIGHTDB_OVERRIDE;
    void summary(const Summary&) TIGHTDB_OVERRIDE;

protected:
    bool m_report_progress;
};

/// Generates output that is compatible with the XML output of
/// UnitTest++. Caller receives ownership of the reporter.
///
/// FIXME: Consider producing output that conforms to
/// http://windyroad.com.au/dl/Open%20Source/JUnit.xsd.
Reporter* create_xml_reporter(std::ostream&);

/// Run only those tests whose name is both included and not excluded.
///
/// EBNF:
///
///     filter = { include-pattern }, [ '-', { exclude-pattern } ]
///     include-pattern = pattern
///     exclude-pattern = pattern
///
/// Each pattern is a string containing no white-space, and optionally
/// containg `*` wild cards. Each `*` matches zero or more arbitrary
/// characters.
///
/// An empty filter is functionally equivalent to "*" and a filter on
/// the form "- ..." is equivalent to "* - ...".
///
/// Examples:
///
///     ""                 everything
///     "*"                everything
///     "* -"              everything
///     "-"                everything
///     "- *"              nothing
///     "* - *"            nothing
///     "Array_Count"      only "Array_Count"
///     "- Array_*"        all except those that match "Array_*"
///     "Array_* Column_* - *_Count"
Filter* create_wildcard_filter(const std::string&);

} // namespace unit_test
} // namespace test_util
} // namespace tightdb

#endif // TIGHTDB_TEST_UTIL_UNIT_TEST_HPP
<|endoftext|>


<commit_before>//===-- source/Host/linux/Host.cpp ------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
#include <stdio.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>

// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Target/Process.h"

#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#ifdef __ANDROID_NDK__
#include "lldb/Host/android/Android.h"
#endif
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"

#include "lldb/Core/ModuleSpec.h"
#include "lldb/Symbol/ObjectFile.h"
#include "Plugins/Process/Linux/ProcFileReader.h"

using namespace lldb;
using namespace lldb_private;

typedef enum ProcessStateFlags
{
    eProcessStateRunning           = (1u << 0), // Running
    eProcessStateSleeping          = (1u << 1), // Sleeping in an interruptible wait
    eProcessStateWaiting           = (1u << 2), // Waiting in an uninterruptible disk sleep
    eProcessStateZombie            = (1u << 3), // Zombie
    eProcessStateTracedOrStopped   = (1u << 4), // Traced or stopped (on a signal)
    eProcessStatePaging            = (1u << 5)  // Paging
} ProcessStateFlags;

typedef struct ProcessStatInfo
{
    lldb::pid_t ppid;           // Parent Process ID
    uint32_t fProcessState;     // ProcessStateFlags
} ProcessStatInfo;

// Get the process info with additional information from /proc/$PID/stat (like process state, and tracer pid).
static bool GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid);

static bool
ReadProcPseudoFileStat (lldb::pid_t pid, ProcessStatInfo& stat_info)
{
    // Read the /proc/$PID/stat file.
    lldb::DataBufferSP buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer (pid, "stat");

    // The filename of the executable is stored in parenthesis right after the pid. We look for the closing
    // parenthesis for the filename and work from there in case the name has something funky like ')' in it.
    const char *filename_end = strrchr ((const char *)buf_sp->GetBytes(), ')');
    if (filename_end)
    {
        char state = '\0';
        int ppid = LLDB_INVALID_PROCESS_ID;

        // Read state and ppid.
        sscanf (filename_end + 1, " %c %d", &state, &ppid);

        stat_info.ppid = ppid;

        switch (state)
        {
            case 'R':
                stat_info.fProcessState |= eProcessStateRunning;
                break;
            case 'S':
                stat_info.fProcessState |= eProcessStateSleeping;
                break;
            case 'D':
                stat_info.fProcessState |= eProcessStateWaiting;
                break;
            case 'Z':
                stat_info.fProcessState |= eProcessStateZombie;
                break;
            case 'T':
                stat_info.fProcessState |= eProcessStateTracedOrStopped;
                break;
            case 'W':
                stat_info.fProcessState |= eProcessStatePaging;
                break;
        }

        return true;
    }

    return false;
}

static void
GetLinuxProcessUserAndGroup (lldb::pid_t pid, ProcessInstanceInfo &process_info, lldb::pid_t &tracerpid)
{
    tracerpid = 0;
    uint32_t rUid = UINT32_MAX;     // Real User ID
    uint32_t eUid = UINT32_MAX;     // Effective User ID
    uint32_t rGid = UINT32_MAX;     // Real Group ID
    uint32_t eGid = UINT32_MAX;     // Effective Group ID

    // Read the /proc/$PID/status file and parse the Uid:, Gid:, and TracerPid: fields.
    lldb::DataBufferSP buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer (pid, "status");

    static const char uid_token[] = "Uid:";
    char *buf_uid = strstr ((char *)buf_sp->GetBytes(), uid_token);
    if (buf_uid)
    {
        // Real, effective, saved set, and file system UIDs. Read the first two.
        buf_uid += sizeof(uid_token);
        rUid = strtol (buf_uid, &buf_uid, 10);
        eUid = strtol (buf_uid, &buf_uid, 10);
    }

    static const char gid_token[] = "Gid:";
    char *buf_gid = strstr ((char *)buf_sp->GetBytes(), gid_token);
    if (buf_gid)
    {
        // Real, effective, saved set, and file system GIDs. Read the first two.
        buf_gid += sizeof(gid_token);
        rGid = strtol (buf_gid, &buf_gid, 10);
        eGid = strtol (buf_gid, &buf_gid, 10);
    }

    static const char tracerpid_token[] = "TracerPid:";
    char *buf_tracerpid = strstr((char *)buf_sp->GetBytes(), tracerpid_token);
    if (buf_tracerpid)
    {
        // Tracer PID. 0 if we're not being debugged.
        buf_tracerpid += sizeof(tracerpid_token);
        tracerpid = strtol (buf_tracerpid, &buf_tracerpid, 10);
    }

    process_info.SetUserID (rUid);
    process_info.SetEffectiveUserID (eUid);
    process_info.SetGroupID (rGid);
    process_info.SetEffectiveGroupID (eGid);
}

lldb::DataBufferSP
Host::GetAuxvData(lldb_private::Process *process)
{
    return process_linux::ProcFileReader::ReadIntoDataBuffer (process->GetID(), "auxv");
}

lldb::DataBufferSP
Host::GetAuxvData (lldb::pid_t pid)
{
    return process_linux::ProcFileReader::ReadIntoDataBuffer (pid, "auxv");
}

static bool
IsDirNumeric(const char *dname)
{
    for (; *dname; dname++)
    {
        if (!isdigit (*dname))
            return false;
    }
    return true;
}

uint32_t
Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
{
    static const char procdir[] = "/proc/";

    DIR *dirproc = opendir (procdir);
    if (dirproc)
    {
        struct dirent *direntry = NULL;
        const uid_t our_uid = getuid();
        const lldb::pid_t our_pid = getpid();
        bool all_users = match_info.GetMatchAllUsers();

        while ((direntry = readdir (dirproc)) != NULL)
        {
            if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name))
                continue;

            lldb::pid_t pid = atoi (direntry->d_name);

            // Skip this process.
            if (pid == our_pid)
                continue;

            lldb::pid_t tracerpid;
            ProcessStatInfo stat_info;
            ProcessInstanceInfo process_info;

            if (!GetProcessAndStatInfo (pid, process_info, stat_info, tracerpid))
                continue;

            // Skip if process is being debugged.
            if (tracerpid != 0)
                continue;

            // Skip zombies.
            if (stat_info.fProcessState & eProcessStateZombie)
                continue;

            // Check for user match if we're not matching all users and not running as root.
            if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid))
                continue;

            if (match_info.Matches (process_info))
            {
                process_infos.Append (process_info);
            }
        }

        closedir (dirproc);
    }

    return process_infos.GetSize();
}

bool
Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach)
{
    bool tids_changed = false;
    static const char procdir[] = "/proc/";
    static const char taskdir[] = "/task/";
    std::string process_task_dir = procdir + std::to_string(pid) + taskdir;
    DIR *dirproc = opendir (process_task_dir.c_str());

    if (dirproc)
    {
        struct dirent *direntry = NULL;
        while ((direntry = readdir (dirproc)) != NULL)
        {
            if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name))
                continue;

            lldb::tid_t tid = atoi(direntry->d_name);
            TidMap::iterator it = tids_to_attach.find(tid);
            if (it == tids_to_attach.end())
            {
                tids_to_attach.insert(TidPair(tid, false));
                tids_changed = true;
            }
        }
        closedir (dirproc);
    }

    return tids_changed;
}

static bool
GetELFProcessCPUType (const char *exe_path, ProcessInstanceInfo &process_info)
{
    // Clear the architecture.
    process_info.GetArchitecture().Clear();

    ModuleSpecList specs;
    FileSpec filespec (exe_path, false);
    const size_t num_specs = ObjectFile::GetModuleSpecifications (filespec, 0, 0, specs);
    // GetModuleSpecifications() could fail if the executable has been deleted or is locked.
    // But it shouldn't return more than 1 architecture.
    assert(num_specs <= 1 && "Linux plugin supports only a single architecture");
    if (num_specs == 1)
    {
        ModuleSpec module_spec;
        if (specs.GetModuleSpecAtIndex (0, module_spec) && module_spec.GetArchitecture().IsValid())
        {
            process_info.GetArchitecture () = module_spec.GetArchitecture();
            return true;
        }
    }
    return false;
}

static bool
GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid)
{
    tracerpid = 0;
    process_info.Clear();
    ::memset (&stat_info, 0, sizeof(stat_info));
    stat_info.ppid = LLDB_INVALID_PROCESS_ID;

    // Use special code here because proc/[pid]/exe is a symbolic link.
    char link_path[PATH_MAX];
    char exe_path[PATH_MAX] = "";
    if (snprintf (link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) <= 0)
        return false;

    ssize_t len = readlink (link_path, exe_path, sizeof(exe_path) - 1);
    if (len <= 0)
        return false;

    // readlink does not append a null byte.
    exe_path[len] = 0;

    // If the binary has been deleted, the link name has " (deleted)" appended.
    //  Remove if there.
    static const ssize_t deleted_len = strlen(" (deleted)");
    if (len > deleted_len &&
        !strcmp(exe_path + len - deleted_len, " (deleted)"))
    {
        exe_path[len - deleted_len] = 0;
    }
    else
    {
        GetELFProcessCPUType (exe_path, process_info);
    }

    process_info.SetProcessID(pid);
    process_info.GetExecutableFile().SetFile(exe_path, false);
    process_info.GetArchitecture().MergeFrom(HostInfo::GetArchitecture());

    lldb::DataBufferSP buf_sp;

    // Get the process environment.
    buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "environ");
    Args &info_env = process_info.GetEnvironmentEntries();
    char *next_var = (char *)buf_sp->GetBytes();
    char *end_buf = next_var + buf_sp->GetByteSize();
    while (next_var < end_buf && 0 != *next_var)
    {
        info_env.AppendArgument(next_var);
        next_var += strlen(next_var) + 1;
    }

    // Get the command line used to start the process.
    buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "cmdline");

    // Grab Arg0 first, if there is one.
    char *cmd = (char *)buf_sp->GetBytes();
    if (cmd)
    {
        process_info.SetArg0(cmd);

        // Now process any remaining arguments.
        Args &info_args = process_info.GetArguments();
        char *next_arg = cmd + strlen(cmd) + 1;
        end_buf = cmd + buf_sp->GetByteSize();
        while (next_arg < end_buf && 0 != *next_arg)
        {
            info_args.AppendArgument(next_arg);
            next_arg += strlen(next_arg) + 1;
        }
    }

    // Read /proc/$PID/stat to get our parent pid.
    if (ReadProcPseudoFileStat (pid, stat_info))
    {
        process_info.SetParentProcessID (stat_info.ppid);
    }

    // Get User and Group IDs and get tracer pid.
    GetLinuxProcessUserAndGroup (pid, process_info, tracerpid);

    return true;
}

bool
Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
    lldb::pid_t tracerpid;
    ProcessStatInfo stat_info;

    return GetProcessAndStatInfo (pid, process_info, stat_info, tracerpid);
}

size_t
Host::GetEnvironment (StringList &env)
{
    char **host_env = environ;
    char *env_entry;
    size_t i;
    for (i=0; (env_entry = host_env[i]) != NULL; ++i)
        env.AppendString(env_entry);
    return i;
}

Error
Host::ShellExpandArguments (ProcessLaunchInfo &launch_info)
{
    return Error("unimplemented");
}
<commit_msg>Add logging to Linux Host::GetProcessAndStatInfo.<commit_after>//===-- source/Host/linux/Host.cpp ------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>

// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Target/Process.h"

#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#ifdef __ANDROID_NDK__
#include "lldb/Host/android/Android.h"
#endif
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"

#include "lldb/Core/ModuleSpec.h"
#include "lldb/Symbol/ObjectFile.h"
#include "Plugins/Process/Linux/ProcFileReader.h"

using namespace lldb;
using namespace lldb_private;

typedef enum ProcessStateFlags
{
    eProcessStateRunning           = (1u << 0), // Running
    eProcessStateSleeping          = (1u << 1), // Sleeping in an interruptible wait
    eProcessStateWaiting           = (1u << 2), // Waiting in an uninterruptible disk sleep
    eProcessStateZombie            = (1u << 3), // Zombie
    eProcessStateTracedOrStopped   = (1u << 4), // Traced or stopped (on a signal)
    eProcessStatePaging            = (1u << 5)  // Paging
} ProcessStateFlags;

typedef struct ProcessStatInfo
{
    lldb::pid_t ppid;           // Parent Process ID
    uint32_t fProcessState;     // ProcessStateFlags
} ProcessStatInfo;

// Get the process info with additional information from /proc/$PID/stat (like process state, and tracer pid).
static bool GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid);

static bool
ReadProcPseudoFileStat (lldb::pid_t pid, ProcessStatInfo& stat_info)
{
    // Read the /proc/$PID/stat file.
    lldb::DataBufferSP buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer (pid, "stat");

    // The filename of the executable is stored in parenthesis right after the pid. We look for the closing
    // parenthesis for the filename and work from there in case the name has something funky like ')' in it.
    const char *filename_end = strrchr ((const char *)buf_sp->GetBytes(), ')');
    if (filename_end)
    {
        char state = '\0';
        int ppid = LLDB_INVALID_PROCESS_ID;

        // Read state and ppid.
        sscanf (filename_end + 1, " %c %d", &state, &ppid);

        stat_info.ppid = ppid;

        switch (state)
        {
            case 'R':
                stat_info.fProcessState |= eProcessStateRunning;
                break;
            case 'S':
                stat_info.fProcessState |= eProcessStateSleeping;
                break;
            case 'D':
                stat_info.fProcessState |= eProcessStateWaiting;
                break;
            case 'Z':
                stat_info.fProcessState |= eProcessStateZombie;
                break;
            case 'T':
                stat_info.fProcessState |= eProcessStateTracedOrStopped;
                break;
            case 'W':
                stat_info.fProcessState |= eProcessStatePaging;
                break;
        }

        return true;
    }

    return false;
}

static void
GetLinuxProcessUserAndGroup (lldb::pid_t pid, ProcessInstanceInfo &process_info, lldb::pid_t &tracerpid)
{
    tracerpid = 0;
    uint32_t rUid = UINT32_MAX;     // Real User ID
    uint32_t eUid = UINT32_MAX;     // Effective User ID
    uint32_t rGid = UINT32_MAX;     // Real Group ID
    uint32_t eGid = UINT32_MAX;     // Effective Group ID

    // Read the /proc/$PID/status file and parse the Uid:, Gid:, and TracerPid: fields.
    lldb::DataBufferSP buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer (pid, "status");

    static const char uid_token[] = "Uid:";
    char *buf_uid = strstr ((char *)buf_sp->GetBytes(), uid_token);
    if (buf_uid)
    {
        // Real, effective, saved set, and file system UIDs. Read the first two.
        buf_uid += sizeof(uid_token);
        rUid = strtol (buf_uid, &buf_uid, 10);
        eUid = strtol (buf_uid, &buf_uid, 10);
    }

    static const char gid_token[] = "Gid:";
    char *buf_gid = strstr ((char *)buf_sp->GetBytes(), gid_token);
    if (buf_gid)
    {
        // Real, effective, saved set, and file system GIDs. Read the first two.
        buf_gid += sizeof(gid_token);
        rGid = strtol (buf_gid, &buf_gid, 10);
        eGid = strtol (buf_gid, &buf_gid, 10);
    }

    static const char tracerpid_token[] = "TracerPid:";
    char *buf_tracerpid = strstr((char *)buf_sp->GetBytes(), tracerpid_token);
    if (buf_tracerpid)
    {
        // Tracer PID. 0 if we're not being debugged.
        buf_tracerpid += sizeof(tracerpid_token);
        tracerpid = strtol (buf_tracerpid, &buf_tracerpid, 10);
    }

    process_info.SetUserID (rUid);
    process_info.SetEffectiveUserID (eUid);
    process_info.SetGroupID (rGid);
    process_info.SetEffectiveGroupID (eGid);
}

lldb::DataBufferSP
Host::GetAuxvData(lldb_private::Process *process)
{
    return process_linux::ProcFileReader::ReadIntoDataBuffer (process->GetID(), "auxv");
}

lldb::DataBufferSP
Host::GetAuxvData (lldb::pid_t pid)
{
    return process_linux::ProcFileReader::ReadIntoDataBuffer (pid, "auxv");
}

static bool
IsDirNumeric(const char *dname)
{
    for (; *dname; dname++)
    {
        if (!isdigit (*dname))
            return false;
    }
    return true;
}

uint32_t
Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
{
    static const char procdir[] = "/proc/";

    DIR *dirproc = opendir (procdir);
    if (dirproc)
    {
        struct dirent *direntry = NULL;
        const uid_t our_uid = getuid();
        const lldb::pid_t our_pid = getpid();
        bool all_users = match_info.GetMatchAllUsers();

        while ((direntry = readdir (dirproc)) != NULL)
        {
            if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name))
                continue;

            lldb::pid_t pid = atoi (direntry->d_name);

            // Skip this process.
            if (pid == our_pid)
                continue;

            lldb::pid_t tracerpid;
            ProcessStatInfo stat_info;
            ProcessInstanceInfo process_info;

            if (!GetProcessAndStatInfo (pid, process_info, stat_info, tracerpid))
                continue;

            // Skip if process is being debugged.
            if (tracerpid != 0)
                continue;

            // Skip zombies.
            if (stat_info.fProcessState & eProcessStateZombie)
                continue;

            // Check for user match if we're not matching all users and not running as root.
            if (!all_users && (our_uid != 0) && (process_info.GetUserID() != our_uid))
                continue;

            if (match_info.Matches (process_info))
            {
                process_infos.Append (process_info);
            }
        }

        closedir (dirproc);
    }

    return process_infos.GetSize();
}

bool
Host::FindProcessThreads (const lldb::pid_t pid, TidMap &tids_to_attach)
{
    bool tids_changed = false;
    static const char procdir[] = "/proc/";
    static const char taskdir[] = "/task/";
    std::string process_task_dir = procdir + std::to_string(pid) + taskdir;
    DIR *dirproc = opendir (process_task_dir.c_str());

    if (dirproc)
    {
        struct dirent *direntry = NULL;
        while ((direntry = readdir (dirproc)) != NULL)
        {
            if (direntry->d_type != DT_DIR || !IsDirNumeric (direntry->d_name))
                continue;

            lldb::tid_t tid = atoi(direntry->d_name);
            TidMap::iterator it = tids_to_attach.find(tid);
            if (it == tids_to_attach.end())
            {
                tids_to_attach.insert(TidPair(tid, false));
                tids_changed = true;
            }
        }
        closedir (dirproc);
    }

    return tids_changed;
}

static bool
GetELFProcessCPUType (const char *exe_path, ProcessInstanceInfo &process_info)
{
    // Clear the architecture.
    process_info.GetArchitecture().Clear();

    ModuleSpecList specs;
    FileSpec filespec (exe_path, false);
    const size_t num_specs = ObjectFile::GetModuleSpecifications (filespec, 0, 0, specs);
    // GetModuleSpecifications() could fail if the executable has been deleted or is locked.
    // But it shouldn't return more than 1 architecture.
    assert(num_specs <= 1 && "Linux plugin supports only a single architecture");
    if (num_specs == 1)
    {
        ModuleSpec module_spec;
        if (specs.GetModuleSpecAtIndex (0, module_spec) && module_spec.GetArchitecture().IsValid())
        {
            process_info.GetArchitecture () = module_spec.GetArchitecture();
            return true;
        }
    }
    return false;
}

static bool
GetProcessAndStatInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info, ProcessStatInfo &stat_info, lldb::pid_t &tracerpid)
{
    tracerpid = 0;
    process_info.Clear();
    ::memset (&stat_info, 0, sizeof(stat_info));
    stat_info.ppid = LLDB_INVALID_PROCESS_ID;

    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

    // Use special code here because proc/[pid]/exe is a symbolic link.
    char link_path[PATH_MAX];
    char exe_path[PATH_MAX] = "";
    if (snprintf (link_path, PATH_MAX, "/proc/%" PRIu64 "/exe", pid) <= 0)
    {
        if (log)
            log->Printf("%s: failed to sprintf pid %" PRIu64, __FUNCTION__, pid);
        return false;
    }

    ssize_t len = readlink (link_path, exe_path, sizeof(exe_path) - 1);
    if (len <= 0)
    {
        if (log)
            log->Printf("%s: failed to read link %s: %s", __FUNCTION__, link_path, strerror(errno));
        return false;
    }

    // readlink does not append a null byte.
    exe_path[len] = 0;

    // If the binary has been deleted, the link name has " (deleted)" appended.
    //  Remove if there.
    static const ssize_t deleted_len = strlen(" (deleted)");
    if (len > deleted_len &&
        !strcmp(exe_path + len - deleted_len, " (deleted)"))
    {
        exe_path[len - deleted_len] = 0;
    }
    else
    {
        GetELFProcessCPUType (exe_path, process_info);
    }

    process_info.SetProcessID(pid);
    process_info.GetExecutableFile().SetFile(exe_path, false);
    process_info.GetArchitecture().MergeFrom(HostInfo::GetArchitecture());

    lldb::DataBufferSP buf_sp;

    // Get the process environment.
    buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "environ");
    Args &info_env = process_info.GetEnvironmentEntries();
    char *next_var = (char *)buf_sp->GetBytes();
    char *end_buf = next_var + buf_sp->GetByteSize();
    while (next_var < end_buf && 0 != *next_var)
    {
        info_env.AppendArgument(next_var);
        next_var += strlen(next_var) + 1;
    }

    // Get the command line used to start the process.
    buf_sp = process_linux::ProcFileReader::ReadIntoDataBuffer(pid, "cmdline");

    // Grab Arg0 first, if there is one.
    char *cmd = (char *)buf_sp->GetBytes();
    if (cmd)
    {
        process_info.SetArg0(cmd);

        // Now process any remaining arguments.
        Args &info_args = process_info.GetArguments();
        char *next_arg = cmd + strlen(cmd) + 1;
        end_buf = cmd + buf_sp->GetByteSize();
        while (next_arg < end_buf && 0 != *next_arg)
        {
            info_args.AppendArgument(next_arg);
            next_arg += strlen(next_arg) + 1;
        }
    }

    // Read /proc/$PID/stat to get our parent pid.
    if (ReadProcPseudoFileStat (pid, stat_info))
    {
        process_info.SetParentProcessID (stat_info.ppid);
    }

    // Get User and Group IDs and get tracer pid.
    GetLinuxProcessUserAndGroup (pid, process_info, tracerpid);

    return true;
}

bool
Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
    lldb::pid_t tracerpid;
    ProcessStatInfo stat_info;

    return GetProcessAndStatInfo (pid, process_info, stat_info, tracerpid);
}

size_t
Host::GetEnvironment (StringList &env)
{
    char **host_env = environ;
    char *env_entry;
    size_t i;
    for (i=0; (env_entry = host_env[i]) != NULL; ++i)
        env.AppendString(env_entry);
    return i;
}

Error
Host::ShellExpandArguments (ProcessLaunchInfo &launch_info)
{
    return Error("unimplemented");
}
<|endoftext|>