<commit_before>//===- TableGen.cpp - Top-Level TableGen implementation for Clang ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the main function for Clang's TableGen.
//
//===----------------------------------------------------------------------===//

#include "TableGenBackends.h" // Declares all backends.
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Main.h"
#include "llvm/TableGen/Record.h"

using namespace llvm;
using namespace clang;

enum ActionType {
  GenClangAttrClasses,
  GenClangAttrIdentifierArgList,
  GenClangAttrArgContextList,
  GenClangAttrTypeArgList,
  GenClangAttrImpl,
  GenClangAttrList,
  GenClangAttrPCHRead,
  GenClangAttrPCHWrite,
  GenClangAttrSpellingList,
  GenClangAttrSpellingListIndex,
  GenClangAttrASTVisitor,
  GenClangAttrLateParsedList,
  GenClangAttrTemplateInstantiate,
  GenClangAttrParsedAttrList,
  GenClangAttrParsedAttrImpl,
  GenClangAttrParsedAttrKinds,
  GenClangAttrDump,
  GenClangDiagsDefs,
  GenClangDiagGroups,
  GenClangDiagsIndexName,
  GenClangCommentNodes,
  GenClangDeclNodes,
  GenClangStmtNodes,
  GenClangSACheckers,
  GenClangCommentHTMLTags,
  GenClangCommentHTMLTagsProperties,
  GenClangCommentHTMLNamedCharacterReferences,
  GenClangCommentCommandInfo,
  GenClangCommentCommandList,
  GenArmNeon,
  GenArmNeonSema,
  GenArmNeonTest
};

namespace {
cl::opt<ActionType> Action(
    cl::desc("Action to perform:"),
    cl::values(
        clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes",
                   "Generate clang attribute clases"),
        clEnumValN(GenClangAttrIdentifierArgList,
                   "gen-clang-attr-identifier-arg-list",
                   "Generate a list of attributes that take an "
                   "identifier as their first argument"),
        clEnumValN(GenClangAttrArgContextList,
                   "gen-clang-attr-arg-context-list",
                   "Generate a list of attributes that parse their arguments "
                   "in an unevaluated context"),
        clEnumValN(GenClangAttrTypeArgList,
                   "gen-clang-attr-type-arg-list",
                   "Generate a list of attributes that take a type as their "
                   "first argument"),
        clEnumValN(GenClangAttrImpl, "gen-clang-attr-impl",
                   "Generate clang attribute implementations"),
        clEnumValN(GenClangAttrList, "gen-clang-attr-list",
                   "Generate a clang attribute list"),
        clEnumValN(GenClangAttrPCHRead, "gen-clang-attr-pch-read",
                   "Generate clang PCH attribute reader"),
        clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write",
                   "Generate clang PCH attribute writer"),
        clEnumValN(GenClangAttrSpellingList, "gen-clang-attr-spelling-list",
                   "Generate a clang attribute spelling list"),
        clEnumValN(GenClangAttrSpellingListIndex,
                   "gen-clang-attr-spelling-index",
                   "Generate a clang attribute spelling index"),
        clEnumValN(GenClangAttrASTVisitor,
                   "gen-clang-attr-ast-visitor",
                   "Generate a recursive AST visitor for clang attributes"),
        clEnumValN(GenClangAttrLateParsedList,
                   "gen-clang-attr-late-parsed-list",
                   "Generate a clang attribute LateParsed list"),
        clEnumValN(GenClangAttrTemplateInstantiate,
                   "gen-clang-attr-template-instantiate",
                   "Generate a clang template instantiate code"),
        clEnumValN(GenClangAttrParsedAttrList,
                   "gen-clang-attr-parsed-attr-list",
                   "Generate a clang parsed attribute list"),
        clEnumValN(GenClangAttrParsedAttrImpl,
                   "gen-clang-attr-parsed-attr-impl",
                   "Generate the clang parsed attribute helpers"),
        clEnumValN(GenClangAttrParsedAttrKinds,
                   "gen-clang-attr-parsed-attr-kinds",
                   "Generate a clang parsed attribute kinds"),
        clEnumValN(GenClangAttrDump, "gen-clang-attr-dump",
                   "Generate clang attribute dumper"),
        clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
                   "Generate Clang diagnostics definitions"),
        clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
                   "Generate Clang diagnostic groups"),
        clEnumValN(GenClangDiagsIndexName, "gen-clang-diags-index-name",
                   "Generate Clang diagnostic name index"),
        clEnumValN(GenClangCommentNodes, "gen-clang-comment-nodes",
                   "Generate Clang AST comment nodes"),
        clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes",
                   "Generate Clang AST declaration nodes"),
        clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
                   "Generate Clang AST statement nodes"),
        clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
                   "Generate Clang Static Analyzer checkers"),
        clEnumValN(GenClangCommentHTMLTags, "gen-clang-comment-html-tags",
                   "Generate efficient matchers for HTML tag "
                   "names that are used in documentation comments"),
        clEnumValN(GenClangCommentHTMLTagsProperties,
                   "gen-clang-comment-html-tags-properties",
                   "Generate efficient matchers for HTML tag "
                   "properties"),
        clEnumValN(GenClangCommentHTMLNamedCharacterReferences,
                   "gen-clang-comment-html-named-character-references",
                   "Generate function to translate named character "
                   "references to UTF-8 sequences"),
        clEnumValN(GenClangCommentCommandInfo, "gen-clang-comment-command-info",
                   "Generate command properties for commands that "
                   "are used in documentation comments"),
        clEnumValN(GenClangCommentCommandList, "gen-clang-comment-command-list",
                   "Generate list of commands that are used in "
                   "documentation comments"),
        clEnumValN(GenArmNeon, "gen-arm-neon", "Generate arm_neon.h for clang"),
        clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
                   "Generate ARM NEON sema support for clang"),
        clEnumValN(GenArmNeonTest, "gen-arm-neon-test",
                   "Generate ARM NEON tests for clang"),
        clEnumValEnd));

cl::opt<std::string>
ClangComponent("clang-component",
               cl::desc("Only use warnings from specified component"),
               cl::value_desc("component"), cl::Hidden);

bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
  switch (Action) {
  case GenClangAttrClasses:
    EmitClangAttrClass(Records, OS);
    break;
  case GenClangAttrIdentifierArgList:
    EmitClangAttrIdentifierArgList(Records, OS);
    break;
  case GenClangAttrArgContextList:
    EmitClangAttrArgContextList(Records, OS);
    break;
  case GenClangAttrTypeArgList:
    EmitClangAttrTypeArgList(Records, OS);
    break;
  case GenClangAttrImpl:
    EmitClangAttrImpl(Records, OS);
    break;
  case GenClangAttrList:
    EmitClangAttrList(Records, OS);
    break;
  case GenClangAttrPCHRead:
    EmitClangAttrPCHRead(Records, OS);
    break;
  case GenClangAttrPCHWrite:
    EmitClangAttrPCHWrite(Records, OS);
    break;
  case GenClangAttrSpellingList:
    EmitClangAttrSpellingList(Records, OS);
    break;
  case GenClangAttrSpellingListIndex:
    EmitClangAttrSpellingListIndex(Records, OS);
    break;
  case GenClangAttrASTVisitor:
    EmitClangAttrASTVisitor(Records, OS);
    break;
  case GenClangAttrLateParsedList:
    EmitClangAttrLateParsedList(Records, OS);
    break;
  case GenClangAttrTemplateInstantiate:
    EmitClangAttrTemplateInstantiate(Records, OS);
    break;
  case GenClangAttrParsedAttrList:
    EmitClangAttrParsedAttrList(Records, OS);
    break;
  case GenClangAttrParsedAttrImpl:
    EmitClangAttrParsedAttrImpl(Records, OS);
    break;
  case GenClangAttrParsedAttrKinds:
    EmitClangAttrParsedAttrKinds(Records, OS);
    break;
  case GenClangAttrDump:
    EmitClangAttrDump(Records, OS);
    break;
  case GenClangDiagsDefs:
    EmitClangDiagsDefs(Records, OS, ClangComponent);
    break;
  case GenClangDiagGroups:
    EmitClangDiagGroups(Records, OS);
    break;
  case GenClangDiagsIndexName:
    EmitClangDiagsIndexName(Records, OS);
    break;
  case GenClangCommentNodes:
    EmitClangASTNodes(Records, OS, "Comment", "");
    break;
  case GenClangDeclNodes:
    EmitClangASTNodes(Records, OS, "Decl", "Decl");
    EmitClangDeclContext(Records, OS);
    break;
  case GenClangStmtNodes:
    EmitClangASTNodes(Records, OS, "Stmt", "");
    break;
  case GenClangSACheckers:
    EmitClangSACheckers(Records, OS);
    break;
  case GenClangCommentHTMLTags:
    EmitClangCommentHTMLTags(Records, OS);
    break;
  case GenClangCommentHTMLTagsProperties:
    EmitClangCommentHTMLTagsProperties(Records, OS);
    break;
  case GenClangCommentHTMLNamedCharacterReferences:
    EmitClangCommentHTMLNamedCharacterReferences(Records, OS);
    break;
  case GenClangCommentCommandInfo:
    EmitClangCommentCommandInfo(Records, OS);
    break;
  case GenClangCommentCommandList:
    EmitClangCommentCommandList(Records, OS);
    break;
  case GenArmNeon:
    EmitNeon(Records, OS);
    break;
  case GenArmNeonSema:
    EmitNeonSema(Records, OS);
    break;
  case GenArmNeonTest:
    EmitNeonTest(Records, OS);
    break;
  }

  return false;
}
}

int main(int argc, char **argv) {
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(argc, argv);
  cl::ParseCommandLineOptions(argc, argv);

  return TableGenMain(argv[0], &ClangTableGenMain);
}
<commit_msg>reapply r198858: Disable LeakSanitizer in TableGen binaries, see PR18325; this time LeakSanitizerIsTurnedOffForTheCurrentProcess is used instead of __lsan_is_turned_off<commit_after>//===- TableGen.cpp - Top-Level TableGen implementation for Clang ---------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the main function for Clang's TableGen.
//
//===----------------------------------------------------------------------===//

#include "TableGenBackends.h" // Declares all backends.
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Signals.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Main.h"
#include "llvm/TableGen/Record.h"

using namespace llvm;
using namespace clang;

enum ActionType {
  GenClangAttrClasses,
  GenClangAttrIdentifierArgList,
  GenClangAttrArgContextList,
  GenClangAttrTypeArgList,
  GenClangAttrImpl,
  GenClangAttrList,
  GenClangAttrPCHRead,
  GenClangAttrPCHWrite,
  GenClangAttrSpellingList,
  GenClangAttrSpellingListIndex,
  GenClangAttrASTVisitor,
  GenClangAttrLateParsedList,
  GenClangAttrTemplateInstantiate,
  GenClangAttrParsedAttrList,
  GenClangAttrParsedAttrImpl,
  GenClangAttrParsedAttrKinds,
  GenClangAttrDump,
  GenClangDiagsDefs,
  GenClangDiagGroups,
  GenClangDiagsIndexName,
  GenClangCommentNodes,
  GenClangDeclNodes,
  GenClangStmtNodes,
  GenClangSACheckers,
  GenClangCommentHTMLTags,
  GenClangCommentHTMLTagsProperties,
  GenClangCommentHTMLNamedCharacterReferences,
  GenClangCommentCommandInfo,
  GenClangCommentCommandList,
  GenArmNeon,
  GenArmNeonSema,
  GenArmNeonTest
};

namespace {
cl::opt<ActionType> Action(
    cl::desc("Action to perform:"),
    cl::values(
        clEnumValN(GenClangAttrClasses, "gen-clang-attr-classes",
                   "Generate clang attribute clases"),
        clEnumValN(GenClangAttrIdentifierArgList,
                   "gen-clang-attr-identifier-arg-list",
                   "Generate a list of attributes that take an "
                   "identifier as their first argument"),
        clEnumValN(GenClangAttrArgContextList,
                   "gen-clang-attr-arg-context-list",
                   "Generate a list of attributes that parse their arguments "
                   "in an unevaluated context"),
        clEnumValN(GenClangAttrTypeArgList,
                   "gen-clang-attr-type-arg-list",
                   "Generate a list of attributes that take a type as their "
                   "first argument"),
        clEnumValN(GenClangAttrImpl, "gen-clang-attr-impl",
                   "Generate clang attribute implementations"),
        clEnumValN(GenClangAttrList, "gen-clang-attr-list",
                   "Generate a clang attribute list"),
        clEnumValN(GenClangAttrPCHRead, "gen-clang-attr-pch-read",
                   "Generate clang PCH attribute reader"),
        clEnumValN(GenClangAttrPCHWrite, "gen-clang-attr-pch-write",
                   "Generate clang PCH attribute writer"),
        clEnumValN(GenClangAttrSpellingList, "gen-clang-attr-spelling-list",
                   "Generate a clang attribute spelling list"),
        clEnumValN(GenClangAttrSpellingListIndex,
                   "gen-clang-attr-spelling-index",
                   "Generate a clang attribute spelling index"),
        clEnumValN(GenClangAttrASTVisitor,
                   "gen-clang-attr-ast-visitor",
                   "Generate a recursive AST visitor for clang attributes"),
        clEnumValN(GenClangAttrLateParsedList,
                   "gen-clang-attr-late-parsed-list",
                   "Generate a clang attribute LateParsed list"),
        clEnumValN(GenClangAttrTemplateInstantiate,
                   "gen-clang-attr-template-instantiate",
                   "Generate a clang template instantiate code"),
        clEnumValN(GenClangAttrParsedAttrList,
                   "gen-clang-attr-parsed-attr-list",
                   "Generate a clang parsed attribute list"),
        clEnumValN(GenClangAttrParsedAttrImpl,
                   "gen-clang-attr-parsed-attr-impl",
                   "Generate the clang parsed attribute helpers"),
        clEnumValN(GenClangAttrParsedAttrKinds,
                   "gen-clang-attr-parsed-attr-kinds",
                   "Generate a clang parsed attribute kinds"),
        clEnumValN(GenClangAttrDump, "gen-clang-attr-dump",
                   "Generate clang attribute dumper"),
        clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
                   "Generate Clang diagnostics definitions"),
        clEnumValN(GenClangDiagGroups, "gen-clang-diag-groups",
                   "Generate Clang diagnostic groups"),
        clEnumValN(GenClangDiagsIndexName, "gen-clang-diags-index-name",
                   "Generate Clang diagnostic name index"),
        clEnumValN(GenClangCommentNodes, "gen-clang-comment-nodes",
                   "Generate Clang AST comment nodes"),
        clEnumValN(GenClangDeclNodes, "gen-clang-decl-nodes",
                   "Generate Clang AST declaration nodes"),
        clEnumValN(GenClangStmtNodes, "gen-clang-stmt-nodes",
                   "Generate Clang AST statement nodes"),
        clEnumValN(GenClangSACheckers, "gen-clang-sa-checkers",
                   "Generate Clang Static Analyzer checkers"),
        clEnumValN(GenClangCommentHTMLTags, "gen-clang-comment-html-tags",
                   "Generate efficient matchers for HTML tag "
                   "names that are used in documentation comments"),
        clEnumValN(GenClangCommentHTMLTagsProperties,
                   "gen-clang-comment-html-tags-properties",
                   "Generate efficient matchers for HTML tag "
                   "properties"),
        clEnumValN(GenClangCommentHTMLNamedCharacterReferences,
                   "gen-clang-comment-html-named-character-references",
                   "Generate function to translate named character "
                   "references to UTF-8 sequences"),
        clEnumValN(GenClangCommentCommandInfo, "gen-clang-comment-command-info",
                   "Generate command properties for commands that "
                   "are used in documentation comments"),
        clEnumValN(GenClangCommentCommandList, "gen-clang-comment-command-list",
                   "Generate list of commands that are used in "
                   "documentation comments"),
        clEnumValN(GenArmNeon, "gen-arm-neon", "Generate arm_neon.h for clang"),
        clEnumValN(GenArmNeonSema, "gen-arm-neon-sema",
                   "Generate ARM NEON sema support for clang"),
        clEnumValN(GenArmNeonTest, "gen-arm-neon-test",
                   "Generate ARM NEON tests for clang"),
        clEnumValEnd));

cl::opt<std::string>
ClangComponent("clang-component",
               cl::desc("Only use warnings from specified component"),
               cl::value_desc("component"), cl::Hidden);

bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
  switch (Action) {
  case GenClangAttrClasses:
    EmitClangAttrClass(Records, OS);
    break;
  case GenClangAttrIdentifierArgList:
    EmitClangAttrIdentifierArgList(Records, OS);
    break;
  case GenClangAttrArgContextList:
    EmitClangAttrArgContextList(Records, OS);
    break;
  case GenClangAttrTypeArgList:
    EmitClangAttrTypeArgList(Records, OS);
    break;
  case GenClangAttrImpl:
    EmitClangAttrImpl(Records, OS);
    break;
  case GenClangAttrList:
    EmitClangAttrList(Records, OS);
    break;
  case GenClangAttrPCHRead:
    EmitClangAttrPCHRead(Records, OS);
    break;
  case GenClangAttrPCHWrite:
    EmitClangAttrPCHWrite(Records, OS);
    break;
  case GenClangAttrSpellingList:
    EmitClangAttrSpellingList(Records, OS);
    break;
  case GenClangAttrSpellingListIndex:
    EmitClangAttrSpellingListIndex(Records, OS);
    break;
  case GenClangAttrASTVisitor:
    EmitClangAttrASTVisitor(Records, OS);
    break;
  case GenClangAttrLateParsedList:
    EmitClangAttrLateParsedList(Records, OS);
    break;
  case GenClangAttrTemplateInstantiate:
    EmitClangAttrTemplateInstantiate(Records, OS);
    break;
  case GenClangAttrParsedAttrList:
    EmitClangAttrParsedAttrList(Records, OS);
    break;
  case GenClangAttrParsedAttrImpl:
    EmitClangAttrParsedAttrImpl(Records, OS);
    break;
  case GenClangAttrParsedAttrKinds:
    EmitClangAttrParsedAttrKinds(Records, OS);
    break;
  case GenClangAttrDump:
    EmitClangAttrDump(Records, OS);
    break;
  case GenClangDiagsDefs:
    EmitClangDiagsDefs(Records, OS, ClangComponent);
    break;
  case GenClangDiagGroups:
    EmitClangDiagGroups(Records, OS);
    break;
  case GenClangDiagsIndexName:
    EmitClangDiagsIndexName(Records, OS);
    break;
  case GenClangCommentNodes:
    EmitClangASTNodes(Records, OS, "Comment", "");
    break;
  case GenClangDeclNodes:
    EmitClangASTNodes(Records, OS, "Decl", "Decl");
    EmitClangDeclContext(Records, OS);
    break;
  case GenClangStmtNodes:
    EmitClangASTNodes(Records, OS, "Stmt", "");
    break;
  case GenClangSACheckers:
    EmitClangSACheckers(Records, OS);
    break;
  case GenClangCommentHTMLTags:
    EmitClangCommentHTMLTags(Records, OS);
    break;
  case GenClangCommentHTMLTagsProperties:
    EmitClangCommentHTMLTagsProperties(Records, OS);
    break;
  case GenClangCommentHTMLNamedCharacterReferences:
    EmitClangCommentHTMLNamedCharacterReferences(Records, OS);
    break;
  case GenClangCommentCommandInfo:
    EmitClangCommentCommandInfo(Records, OS);
    break;
  case GenClangCommentCommandList:
    EmitClangCommentCommandList(Records, OS);
    break;
  case GenArmNeon:
    EmitNeon(Records, OS);
    break;
  case GenArmNeonSema:
    EmitNeonSema(Records, OS);
    break;
  case GenArmNeonTest:
    EmitNeonTest(Records, OS);
    break;
  }

  return false;
}
}

int main(int argc, char **argv) {
  sys::PrintStackTraceOnErrorSignal();
  PrettyStackTraceProgram X(argc, argv);
  cl::ParseCommandLineOptions(argc, argv);

  return TableGenMain(argv[0], &ClangTableGenMain);
}

extern "C" {
// Disable LeakSanitizer for this binary as it has too many leaks that are not
// very interesting to fix. LeakSanitizerIsTurnedOffForTheCurrentProcess is
// explained in compiler-rt/include/sanitizer/lsan_interface.h
int LeakSanitizerIsTurnedOffForTheCurrentProcess() { return 1; }
} // extern "C"
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2019 Tuukka Norri
 * This code is licensed under MIT license (see LICENSE for details).
 */

#include <cereal/archives/portable_binary.hpp>
#include <cstdlib>
#include <iostream>
#include <libbio/assert.hh>
#include <libbio/dispatch.hh>
#include <range/v3/view/sliding.hpp>
#include <unistd.h>
#include <vcf2multialign/preprocess/variant_graph.hh>
#include <vcf2multialign/utility/read_single_fasta_seq.hh>
#include "cmdline.h"

namespace lb	= libbio;
namespace v2m	= vcf2multialign;

namespace {
	void output_for_gv(
		char const *reference_path,
		char const *input_graph_path,
		char const *output_graph_path,
		char const *reference_seq_name,
		bool const should_overwrite_files,
		bool const output_ref_labels
	)
	{
		v2m::vector_type reference;
		v2m::variant_graph graph;
		lb::file_ostream output_graph_stream;

		{
			lb::file_istream input_graph_stream;

			// Open the files.
			{
				auto const mode(lb::make_writing_open_mode({
					lb::writing_open_mode::CREATE,
					(should_overwrite_files ? lb::writing_open_mode::OVERWRITE : lb::writing_open_mode::NONE)
				}));
				lb::open_file_for_writing(output_graph_path, output_graph_stream, mode);
			}

			lb::open_file_for_reading(input_graph_path, input_graph_stream);

			lb::mmap_handle <char> ref_handle;
			ref_handle.open(reference_path);

			// Read the input FASTA.
			v2m::read_single_fasta_seq(ref_handle, reference, reference_seq_name);

			// Read the intermediate graph.
			cereal::PortableBinaryInputArchive iarchive(input_graph_stream);
			iarchive(graph);
		}

		// Output.
		auto const &ref_positions(graph.ref_positions());
		auto const &aligned_ref_positions(graph.aligned_ref_positions());
		auto const &subgraph_start_positions(graph.subgraph_start_positions());
		auto const &alt_edge_count_csum(graph.alt_edge_count_csum());
		auto const &alt_edge_targets(graph.alt_edge_targets());
		auto const &alt_edge_labels(graph.alt_edge_labels());
		output_graph_stream << "digraph variants {\n";
		output_graph_stream << "\trankdir = LR;\n";
		output_graph_stream << "\trank = same;\n";

		// Labels if needed, otherwise use node ID as the label.
		if (output_ref_labels)
		{
			// Since background colours are needed at subgraph start positions, handle them, too.
			auto sg_it(subgraph_start_positions.begin());
			auto const sg_end(subgraph_start_positions.end());
			std::size_t next_subgraph_start_idx(sg_it == sg_end ? SIZE_MAX : *sg_it++);
			auto const rsv(ranges::view::zip(ranges::view::ints(0), ref_positions | ranges::view::drop(1), aligned_ref_positions | ranges::view::drop(1)));
			for (auto const &[i, ref_pos, aligned_ref_pos] : rsv)
			{
				if (i == next_subgraph_start_idx)
				{
					next_subgraph_start_idx = (sg_it == sg_end ? SIZE_MAX : *sg_it++);
					output_graph_stream << '\t' << aligned_ref_pos << " [label = " << ref_pos << ", style = filled, fillcolor = grey95];\n";
				}
				else
				{
					output_graph_stream << '\t' << aligned_ref_pos << " [label = " << ref_pos << "];\n";
				}
			}
		}
		else
		{
			// Only subgraph start positions.
			for (auto const idx : subgraph_start_positions)
			{
				auto const aligned_ref_pos(aligned_ref_positions[1 + idx]);
				output_graph_stream << '\t' << aligned_ref_pos << " [style = filled, fillcolor = grey95];\n";
			}
		}
		output_graph_stream << '\n';

		// REF edges.
		{
			auto const rsv(ranges::view::zip(
				ref_positions | ranges::view::drop(1) | ranges::view::sliding(2),
				aligned_ref_positions | ranges::view::drop(1) | ranges::view::sliding(2)
			));
			for (auto const &[ref_pair, aligned_ref_pair] : rsv)
			{
				auto const aligned_lhs(aligned_ref_pair[0]);
				auto const aligned_rhs(aligned_ref_pair[1]);
				auto const ref_lhs(ref_pair[0]);
				auto const ref_rhs(ref_pair[1]);
				std::string_view const ref_sub(reference.data() + ref_lhs, ref_rhs - ref_lhs);

				output_graph_stream << '\t' << aligned_lhs << " -> " << aligned_rhs << " [label = \"";
				// If the text is longer than 20 characters, truncate and add an ellipsis.
				// FIXME: handle special characters?
				if (20 < ref_sub.size())
				{
					output_graph_stream << ref_sub.substr(0, 10);
					output_graph_stream << "…";
					output_graph_stream << ref_sub.substr(ref_sub.size() - 10, 10);
				}
				else
				{
					output_graph_stream << ref_sub;
				}
				output_graph_stream << "\", penwidth = 2.0];\n";
			}
			output_graph_stream << '\n';
		}

		// ALT edges.
		{
			std::size_t i(0);
			for (auto const &pair : alt_edge_count_csum | ranges::view::sliding(2))
			{
				auto const start(pair[0]);
				auto const end(pair[1]);
				for (auto const &[target, label] : ranges::view::slice(ranges::view::zip(alt_edge_targets, alt_edge_labels), start, end))
				{
					auto const src(aligned_ref_positions[1 + i]);
					auto const dst(aligned_ref_positions[1 + target]);
					output_graph_stream << '\t' << src << " -> " << dst << " [label = \"" << label << "\"];\n"; // FIXME: handle special characters?
				}

				++i;
			}
		}
		output_graph_stream << "}\n";
	}
}

int main(int argc, char **argv)
{
#ifndef NDEBUG
	std::cerr << "Assertions have been enabled." << std::endl;
#endif

	gengetopt_args_info args_info;
	if (0 != cmdline_parser(argc, argv, &args_info))
		exit(EXIT_FAILURE);

	std::ios_base::sync_with_stdio(false);	// Don't use C style IO after calling cmdline_parser.
	std::cin.tie(nullptr);					// We don't require any input from the user.

	try
	{
		output_for_gv(
			args_info.reference_arg,
			args_info.variants_arg,
			args_info.output_arg,
			args_info.reference_sequence_given ? args_info.reference_sequence_arg : nullptr,
			args_info.overwrite_flag,
			args_info.node_labels_arg == node_labels_arg_REF
		);
	}
	catch (lb::assertion_failure_exception const &exc)
	{
		std::cerr << "Assertion failure: " << exc.what() << '\n';
		boost::stacktrace::stacktrace const *st(boost::get_error_info <lb::traced>(exc));
		if (st)
			std::cerr << "Stack trace:\n" << *st << '\n';
		throw exc;
	}

	return EXIT_SUCCESS;
}
<commit_msg>Use ranges::view::tail instead of drop(1)<commit_after>/*
 * Copyright (c) 2019 Tuukka Norri
 * This code is licensed under MIT license (see LICENSE for details).
 */

#include <cereal/archives/portable_binary.hpp>
#include <cstdlib>
#include <iostream>
#include <libbio/assert.hh>
#include <libbio/dispatch.hh>
#include <range/v3/view/sliding.hpp>
#include <unistd.h>
#include <vcf2multialign/preprocess/variant_graph.hh>
#include <vcf2multialign/utility/read_single_fasta_seq.hh>
#include "cmdline.h"

namespace lb	= libbio;
namespace v2m	= vcf2multialign;

namespace {
	void output_for_gv(
		char const *reference_path,
		char const *input_graph_path,
		char const *output_graph_path,
		char const *reference_seq_name,
		bool const should_overwrite_files,
		bool const output_ref_labels
	)
	{
		v2m::vector_type reference;
		v2m::variant_graph graph;
		lb::file_ostream output_graph_stream;

		{
			lb::file_istream input_graph_stream;

			// Open the files.
			{
				auto const mode(lb::make_writing_open_mode({
					lb::writing_open_mode::CREATE,
					(should_overwrite_files ? lb::writing_open_mode::OVERWRITE : lb::writing_open_mode::NONE)
				}));
				lb::open_file_for_writing(output_graph_path, output_graph_stream, mode);
			}

			lb::open_file_for_reading(input_graph_path, input_graph_stream);

			lb::mmap_handle <char> ref_handle;
			ref_handle.open(reference_path);

			// Read the input FASTA.
			v2m::read_single_fasta_seq(ref_handle, reference, reference_seq_name);

			// Read the intermediate graph.
			cereal::PortableBinaryInputArchive iarchive(input_graph_stream);
			iarchive(graph);
		}

		// Output.
		auto const &ref_positions(graph.ref_positions());
		auto const &aligned_ref_positions(graph.aligned_ref_positions());
		auto const &subgraph_start_positions(graph.subgraph_start_positions());
		auto const &alt_edge_count_csum(graph.alt_edge_count_csum());
		auto const &alt_edge_targets(graph.alt_edge_targets());
		auto const &alt_edge_labels(graph.alt_edge_labels());
		output_graph_stream << "digraph variants {\n";
		output_graph_stream << "\trankdir = LR;\n";
		output_graph_stream << "\trank = same;\n";

		// Labels if needed, otherwise use node ID as the label.
		if (output_ref_labels)
		{
			// Since background colours are needed at subgraph start positions, handle them, too.
			auto sg_it(subgraph_start_positions.begin());
			auto const sg_end(subgraph_start_positions.end());
			std::size_t next_subgraph_start_idx(sg_it == sg_end ? SIZE_MAX : *sg_it++);
			auto const rsv(ranges::view::zip(ranges::view::ints(0), ref_positions | ranges::view::tail, aligned_ref_positions | ranges::view::tail));
			for (auto const &[i, ref_pos, aligned_ref_pos] : rsv)
			{
				if (i == next_subgraph_start_idx)
				{
					next_subgraph_start_idx = (sg_it == sg_end ? SIZE_MAX : *sg_it++);
					output_graph_stream << '\t' << aligned_ref_pos << " [label = " << ref_pos << ", style = filled, fillcolor = grey95];\n";
				}
				else
				{
					output_graph_stream << '\t' << aligned_ref_pos << " [label = " << ref_pos << "];\n";
				}
			}
		}
		else
		{
			// Only subgraph start positions.
			for (auto const idx : subgraph_start_positions)
			{
				auto const aligned_ref_pos(aligned_ref_positions[1 + idx]);
				output_graph_stream << '\t' << aligned_ref_pos << " [style = filled, fillcolor = grey95];\n";
			}
		}
		output_graph_stream << '\n';

		// REF edges.
		{
			auto const rsv(ranges::view::zip(
				ref_positions | ranges::view::tail | ranges::view::sliding(2),
				aligned_ref_positions | ranges::view::tail | ranges::view::sliding(2)
			));
			for (auto const &[ref_pair, aligned_ref_pair] : rsv)
			{
				auto const aligned_lhs(aligned_ref_pair[0]);
				auto const aligned_rhs(aligned_ref_pair[1]);
				auto const ref_lhs(ref_pair[0]);
				auto const ref_rhs(ref_pair[1]);
				std::string_view const ref_sub(reference.data() + ref_lhs, ref_rhs - ref_lhs);

				output_graph_stream << '\t' << aligned_lhs << " -> " << aligned_rhs << " [label = \"";
				// If the text is longer than 20 characters, truncate and add an ellipsis.
				// FIXME: handle special characters?
				if (20 < ref_sub.size())
				{
					output_graph_stream << ref_sub.substr(0, 10);
					output_graph_stream << "…";
					output_graph_stream << ref_sub.substr(ref_sub.size() - 10, 10);
				}
				else
				{
					output_graph_stream << ref_sub;
				}
				output_graph_stream << "\", penwidth = 2.0];\n";
			}
			output_graph_stream << '\n';
		}

		// ALT edges.
		{
			std::size_t i(0);
			for (auto const &pair : alt_edge_count_csum | ranges::view::sliding(2))
			{
				auto const start(pair[0]);
				auto const end(pair[1]);
				for (auto const &[target, label] : ranges::view::slice(ranges::view::zip(alt_edge_targets, alt_edge_labels), start, end))
				{
					auto const src(aligned_ref_positions[1 + i]);
					auto const dst(aligned_ref_positions[1 + target]);
					output_graph_stream << '\t' << src << " -> " << dst << " [label = \"" << label << "\"];\n"; // FIXME: handle special characters?
				}

				++i;
			}
		}
		output_graph_stream << "}\n";
	}
}

int main(int argc, char **argv)
{
#ifndef NDEBUG
	std::cerr << "Assertions have been enabled." << std::endl;
#endif

	gengetopt_args_info args_info;
	if (0 != cmdline_parser(argc, argv, &args_info))
		exit(EXIT_FAILURE);

	std::ios_base::sync_with_stdio(false);	// Don't use C style IO after calling cmdline_parser.
	std::cin.tie(nullptr);					// We don't require any input from the user.

	try
	{
		output_for_gv(
			args_info.reference_arg,
			args_info.variants_arg,
			args_info.output_arg,
			args_info.reference_sequence_given ? args_info.reference_sequence_arg : nullptr,
			args_info.overwrite_flag,
			args_info.node_labels_arg == node_labels_arg_REF
		);
	}
	catch (lb::assertion_failure_exception const &exc)
	{
		std::cerr << "Assertion failure: " << exc.what() << '\n';
		boost::stacktrace::stacktrace const *st(boost::get_error_info <lb::traced>(exc));
		if (st)
			std::cerr << "Stack trace:\n" << *st << '\n';
		throw exc;
	}

	return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: i18nhelp.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: mt $ $Date: 2001-08-08 10:31:49 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

#include <i18nhelp.hxx>

/*
#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#endif

#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif
*/

// #include <cppuhelper/servicefactory.hxx>

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#ifndef _COM_SUN_STAR_I18N_TRANSLITERATIONMODULES_HPP_
#include <com/sun/star/i18n/TransliterationModules.hpp>
#endif

#ifndef _UNOTOOLS_LOCALEDATAWRAPPER_HXX
#include <unotools/localedatawrapper.hxx>
#endif

#ifndef _UNOTOOLS_TRANSLITERATIONWRAPPER_HXX
#include <unotools/transliterationwrapper.hxx>
#endif

#ifndef _ISOLANG_HXX
#include <tools/isolang.hxx>
#endif

using namespace ::com::sun::star;

vcl::I18nHelper::I18nHelper(  ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxMSF, const ::com::sun::star::lang::Locale& rLocale )
{
    mxMSF = rxMSF;
    maLocale = rLocale;
    mpLocaleDataWrapper = NULL;
    mpTransliterationWrapper= NULL;
    mbTransliterateIgnoreCase = sal_False;
}

vcl::I18nHelper::~I18nHelper()
{
    ImplDestroyWrappers();
}

void vcl::I18nHelper::ImplDestroyWrappers()
{
    delete mpLocaleDataWrapper;
    mpLocaleDataWrapper = NULL;

    delete mpTransliterationWrapper;
    mpTransliterationWrapper= NULL;
}

utl::TransliterationWrapper& vcl::I18nHelper::ImplGetTransliterationWrapper() const
{
    if ( !mpTransliterationWrapper )
    {
        sal_Int32 nModules = i18n::TransliterationModules_IGNORE_WIDTH;
        if ( mbTransliterateIgnoreCase )
            nModules |= i18n::TransliterationModules_IGNORE_CASE;

        ((vcl::I18nHelper*)this)->mpTransliterationWrapper = new utl::TransliterationWrapper( mxMSF, (i18n::TransliterationModules)nModules );
        ((vcl::I18nHelper*)this)->mpTransliterationWrapper->loadModuleIfNeeded( ConvertIsoNamesToLanguage( maLocale.Language, maLocale.Country ) );
    }
    return *mpTransliterationWrapper;
}

const ::com::sun::star::lang::Locale& vcl::I18nHelper::getLocale() const
{
    return maLocale;
}

sal_Bool vcl::I18nHelper::MatchString( const String& rStr1, const String& rStr2 ) const
{
    ::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );

    if ( !mbTransliterateIgnoreCase )
    {
        // Change mbTransliterateIgnoreCase and destroy the warpper, next call to
        // ImplGetTransliterationWrapper() will create a wrapper with the correct bIgnoreCase
        ((vcl::I18nHelper*)this)->mbTransliterateIgnoreCase = TRUE;
        delete ((vcl::I18nHelper*)this)->mpTransliterationWrapper;
        ((vcl::I18nHelper*)this)->mpTransliterationWrapper = NULL;
    }

    return ImplGetTransliterationWrapper().isMatch( rStr1, rStr2 );
}

sal_Bool vcl::I18nHelper::MatchMnemonic( const String& rString, sal_Unicode cMnemonicChar ) const
{
    ::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );

    BOOL bEqual = FALSE;
    USHORT n = rString.Search( '~' );
    if ( n != STRING_NOTFOUND )
    {
        String aMatchStr( rString, n+1, STRING_LEN );   // not only one char, because of transliteration...
        sal_Int32 nMatch1, nMatch2;
        bEqual = MatchString( cMnemonicChar, aMatchStr );
    }
    return bEqual;
}

String vcl::I18nHelper::GetDate( const Date& rDate, sal_Bool bLongFormat ) const
{
    ::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );

    // !!!!!!!!!!!!!!!!!!!!!!!!!!!!
    return String();
}
<commit_msg>#89855# More helper functions<commit_after>/*************************************************************************
 *
 *  $RCSfile: i18nhelp.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: mt $ $Date: 2001-08-23 12:03:17 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#pragma hdrstop

#include <i18nhelp.hxx>

/*
#ifndef _COM_SUN_STAR_LANG_XSINGLESERVICEFACTORY_HPP_
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#endif

#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif
*/

// #include <cppuhelper/servicefactory.hxx>

#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#ifndef _COM_SUN_STAR_I18N_TRANSLITERATIONMODULES_HPP_
#include <com/sun/star/i18n/TransliterationModules.hpp>
#endif

#ifndef _UNOTOOLS_LOCALEDATAWRAPPER_HXX
#include <unotools/localedatawrapper.hxx>
#endif

#ifndef _UNOTOOLS_TRANSLITERATIONWRAPPER_HXX
#include <unotools/transliterationwrapper.hxx>
#endif

#ifndef _ISOLANG_HXX
#include <tools/isolang.hxx>
#endif

using namespace ::com::sun::star;

vcl::I18nHelper::I18nHelper(  ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& rxMSF, const ::com::sun::star::lang::Locale& rLocale )
{
    mxMSF = rxMSF;
    maLocale = rLocale;
    mpLocaleDataWrapper = NULL;
    mpTransliterationWrapper= NULL;
    mbTransliterateIgnoreCase = sal_False;
}

vcl::I18nHelper::~I18nHelper()
{
    ImplDestroyWrappers();
}

void vcl::I18nHelper::ImplDestroyWrappers()
{
    delete mpLocaleDataWrapper;
    mpLocaleDataWrapper = NULL;

    delete mpTransliterationWrapper;
    mpTransliterationWrapper= NULL;
}

utl::TransliterationWrapper& vcl::I18nHelper::ImplGetTransliterationWrapper() const
{
    if ( !mpTransliterationWrapper )
    {
        sal_Int32 nModules = i18n::TransliterationModules_IGNORE_WIDTH;
        if ( mbTransliterateIgnoreCase )
            nModules |= i18n::TransliterationModules_IGNORE_CASE;

        ((vcl::I18nHelper*)this)->mpTransliterationWrapper = new utl::TransliterationWrapper( mxMSF, (i18n::TransliterationModules)nModules );
        ((vcl::I18nHelper*)this)->mpTransliterationWrapper->loadModuleIfNeeded( ConvertIsoNamesToLanguage( maLocale.Language, maLocale.Country ) );
    }
    return *mpTransliterationWrapper;
}

LocaleDataWrapper& vcl::I18nHelper::ImplGetLocaleDataWrapper() const
{
    if ( !mpLocaleDataWrapper )
    {
        ((vcl::I18nHelper*)this)->mpLocaleDataWrapper = new LocaleDataWrapper( mxMSF, maLocale );
    }
    return *mpLocaleDataWrapper;
}

const ::com::sun::star::lang::Locale& vcl::I18nHelper::getLocale() const
{
    return maLocale;
}

sal_Int32 vcl::I18nHelper::CompareString( const String& rStr1, const String& rStr2 ) const
{
    ::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );

    if ( mbTransliterateIgnoreCase )
    {
        // Change mbTransliterateIgnoreCase and destroy the warpper, next call to
        // ImplGetTransliterationWrapper() will create a wrapper with the correct bIgnoreCase
        ((vcl::I18nHelper*)this)->mbTransliterateIgnoreCase = FALSE;
        delete ((vcl::I18nHelper*)this)->mpTransliterationWrapper;
        ((vcl::I18nHelper*)this)->mpTransliterationWrapper = NULL;
    }

    return ImplGetTransliterationWrapper().compareString( rStr1, rStr2 );
}

sal_Bool vcl::I18nHelper::MatchString( const String& rStr1, const String& rStr2 ) const
{
    ::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );

    if ( !mbTransliterateIgnoreCase )
    {
        // Change mbTransliterateIgnoreCase and destroy the warpper, next call to
        // ImplGetTransliterationWrapper() will create a wrapper with the correct bIgnoreCase
        ((vcl::I18nHelper*)this)->mbTransliterateIgnoreCase = TRUE;
        delete ((vcl::I18nHelper*)this)->mpTransliterationWrapper;
        ((vcl::I18nHelper*)this)->mpTransliterationWrapper = NULL;
    }

    return ImplGetTransliterationWrapper().isMatch( rStr1, rStr2 );
}

sal_Bool vcl::I18nHelper::MatchMnemonic( const String& rString, sal_Unicode cMnemonicChar ) const
{
    ::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );

    BOOL bEqual = FALSE;
    USHORT n = rString.Search( '~' );
    if ( n != STRING_NOTFOUND )
    {
        String aMatchStr( rString, n+1, STRING_LEN );   // not only one char, because of transliteration...
        bEqual = MatchString( cMnemonicChar, aMatchStr );
    }
    return bEqual;
}

String vcl::I18nHelper::GetDate( const Date& rDate ) const
{
    ::osl::Guard< ::osl::Mutex > aGuard( ((vcl::I18nHelper*)this)->maMutex );

    return ImplGetLocaleDataWrapper().getDate( rDate );
}

String vcl::I18nHelper::GetNum( long nNumber, USHORT nDecimals, BOOL bUseThousandSep, BOOL bTrailingZeros ) const
{
    return ImplGetLocaleDataWrapper().getNum( nNumber, nDecimals, bUseThousandSep, bTrailingZeros );
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: gtkinst.cxx,v $
 *
 *  $Revision: 1.14 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 19:44:33 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <osl/module.h>
#include <plugins/gtk/gtkdata.hxx>
#include <plugins/gtk/gtkinst.hxx>
#include <salframe.h>
#include <salobj.h>
#include <plugins/gtk/gtkframe.hxx>
#include <plugins/gtk/gtkobject.hxx>
#include <plugins/gtk/atkbridge.hxx>

#include <rtl/strbuf.hxx>

#if OSL_DEBUG_LEVEL > 1
#include <stdio.h>
#endif

#include <dlfcn.h>

GtkHookedYieldMutex::GtkHookedYieldMutex()
{
}

/*
 * These methods always occur in pairs
 * A ThreadsEnter is followed by a ThreadsLeave
 * We need to queue up the recursive lock count
 * for each pair, so we can accurately restore
 * it later.
 */
void GtkHookedYieldMutex::ThreadsEnter()
{
    acquire();
    if( !aYieldStack.empty() )
    { /* Previously called ThreadsLeave() */
        ULONG nCount = aYieldStack.front();
        aYieldStack.pop_front();
        while( nCount-- > 1 )
            acquire();
    }
}

void GtkHookedYieldMutex::ThreadsLeave()
{
    aYieldStack.push_front( mnCount );

#if OSL_DEBUG_LEVEL > 1
    if( mnThreadId &&
        mnThreadId != NAMESPACE_VOS(OThread)::getCurrentIdentifier())
        fprintf( stderr, "\n\n--- A different thread owns the mutex ...---\n\n\n");
#endif

    while( mnCount > 1 )
        release();
    release();
}

void GtkHookedYieldMutex::acquire()
{
    SalYieldMutex::acquire();
}

void GtkHookedYieldMutex::release()
{
    SalYieldMutex::release();
}

extern "C"
{
    #define GET_YIELD_MUTEX() static_cast<GtkHookedYieldMutex*>(GetSalData()->pInstance_->GetYieldMutex())
    static void GdkThreadsEnter( void )
    {
        GtkHookedYieldMutex *pYieldMutex = GET_YIELD_MUTEX();
        pYieldMutex->ThreadsEnter();
    }
    static void GdkThreadsLeave( void )
    {
        GtkHookedYieldMutex *pYieldMutex = GET_YIELD_MUTEX();
        pYieldMutex->ThreadsLeave();
    }
    static bool hookLocks( oslModule pModule )
    {
        typedef void (*GdkLockFn) (GCallback enter_fn, GCallback leave_fn);
        rtl::OUString aSymbolName( RTL_CONSTASCII_USTRINGPARAM( "gdk_threads_set_lock_functions") );

        GdkLockFn gdk_threads_set_lock_functions =
                (GdkLockFn) osl_getFunctionSymbol( pModule, aSymbolName.pData );
        if ( !gdk_threads_set_lock_functions )
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "Failed to hook gdk threads locks\n" );
#endif
            return false;
        }

        gdk_threads_set_lock_functions (GdkThreadsEnter, GdkThreadsLeave);
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "Hooked gdk threads locks\n" );
#endif
        return true;
    }

    VCL_DLLPUBLIC SalInstance* create_SalInstance( oslModule pModule )
    {
        const gchar* pVersion = gtk_check_version( 2, 2, 0 );
        if( pVersion )
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "gtk version conflict: %s\n", pVersion );
#endif
            return NULL;
        }

        GtkYieldMutex *pYieldMutex;

        // init gdk thread protection
        if ( !g_thread_supported() )
            g_thread_init( NULL );

        if ( hookLocks( pModule ) )
            pYieldMutex = new GtkHookedYieldMutex();
        else
            pYieldMutex = new GtkYieldMutex();

        gdk_threads_init();

        GtkInstance* pInstance = new GtkInstance( pYieldMutex );
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "creating GtkSalInstance 0x%p\n", pInstance );
#endif

        // initialize SalData
        SalData *pSalData = new GtkData();
        SetSalData( pSalData );
        pSalData->pInstance_ = pInstance;
        pSalData->Init();
        pSalData->initNWF();

        const char* pGtkModules = getenv( "GTK_MODULES" );
        if( pGtkModules )
        {
            rtl::OString aModules( pGtkModules );
            sal_Int32 nIndex = 0;
            while( nIndex >= 0 )
            {
                rtl::OString aToken = aModules.getToken( 0, ':', nIndex );
                if( aToken.equals( "gail" ) || aToken.equals( "atk-bridge" ) )
                {
                    InitAtkBridge();
                    break;
                }
            }
        }

        return pInstance;
    }
}

GtkInstance::~GtkInstance()
{
    DeInitAtkBridge();
}

SalFrame* GtkInstance::CreateFrame( SalFrame* pParent, ULONG nStyle )
{
    return new GtkSalFrame( pParent, nStyle );
}

SalFrame* GtkInstance::CreateChildFrame( SystemParentData* pParentData, ULONG )
{
    SalFrame* pFrame = new GtkSalFrame( pParentData );

    return pFrame;
}

SalObject* GtkInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData )
{
    // there is no method to set a visual for a GtkWidget
    // so we need the X11SalObject in that case
    if( pWindowData )
        return X11SalObject::CreateObject( pParent, pWindowData );

    return new GtkSalObject( static_cast<GtkSalFrame*>(pParent) );
}

GtkYieldMutex::GtkYieldMutex()
{
}

void GtkYieldMutex::acquire()
{
    vos::OThread::TThreadIdentifier aCurrentThread = vos::OThread::getCurrentIdentifier();
    // protect member manipulation
    OMutex::acquire();
    if( mnCount > 0 && mnThreadId == aCurrentThread )
    {
        mnCount++;
        OMutex::release();
        return;
    }
    OMutex::release();

    // obtain gdk mutex
    gdk_threads_enter();

    // obtained gdk mutex, now lock count is one by definition
    OMutex::acquire();
    mnCount = 1;
    mnThreadId = aCurrentThread;
    OMutex::release();
}

void GtkYieldMutex::release()
{
    vos::OThread::TThreadIdentifier aCurrentThread = vos::OThread::getCurrentIdentifier();
    // protect member manipulation
    OMutex::acquire();
    // strange things happen, do nothing if we don't own the mutex
    if( mnThreadId == aCurrentThread )
    {
        mnCount--;
        if( mnCount == 0 )
        {
            gdk_threads_leave();
            mnThreadId = 0;
        }
    }
    OMutex::release();
}

sal_Bool GtkYieldMutex::tryToAcquire()
{
    vos::OThread::TThreadIdentifier aCurrentThread = vos::OThread::getCurrentIdentifier();
    // protect member manipulation
    OMutex::acquire();
    if( mnCount > 0 )
    {
        if( mnThreadId == aCurrentThread )
        {
            mnCount++;
            OMutex::release();
            return sal_True;
        }
        else
        {
            OMutex::release();
            return sal_False;
        }
    }
    OMutex::release();

    // HACK: gdk_threads_mutex is private, we shouldn't use it.
    // how to we do a try_lock without having a gdk_threads_try_enter ?
    if( ! g_mutex_trylock( gdk_threads_mutex ) )
        return sal_False;

    // obtained gdk mutex, now lock count is one by definition
    OMutex::acquire();
    mnCount = 1;
    mnThreadId = aCurrentThread;
    OMutex::release();

    return sal_True;
}

int GtkYieldMutex::Grab()
{
    // this MUST only be called by gdk/gtk callbacks:
    // they are entered with gdk mutex locked; the mutex
    // was unlocked by GtkYieldMutex befor yielding which
    // is now locked again by gtk implicitly

    // obtained gdk mutex, now lock count is one by definition
    OMutex::acquire();
    int nRet = mnCount;
    if( mnCount == 0 ) // recursive else
        mnThreadId = vos::OThread::getCurrentIdentifier();
#if OSL_DEBUG_LEVEL > 1
    else if( mnThreadId != vos::OThread::getCurrentIdentifier() )
    {
        fprintf( stderr, "Yield mutex grabbed in different thread !\n" );
        abort();
    }
#endif
    mnCount = 1;
    OMutex::release();
    return nRet;
}

void GtkYieldMutex::Ungrab( int nGrabs )
{
    // this MUST only be called when leaving the callback
    // that locked the mutex with Grab()
    OMutex::acquire();
    mnCount = nGrabs;
    if( mnCount == 0 )
        mnThreadId = 0;
    OMutex::release();
}
<commit_msg>INTEGRATION: CWS svp01 (1.13.18); FILE MERGED 2006/06/27 12:49:18 pl 1.13.18.2: RESYNC: (1.13-1.14); FILE MERGED 2006/05/22 16:35:26 pl 1.13.18.1: #135265# free plugin abstraction of dependency on X11 specific SalData<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: gtkinst.cxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: hr $ $Date: 2006-08-11 17:45:57 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <osl/module.h>
#include <plugins/gtk/gtkdata.hxx>
#include <plugins/gtk/gtkinst.hxx>
#include <salframe.h>
#include <salobj.h>
#include <plugins/gtk/gtkframe.hxx>
#include <plugins/gtk/gtkobject.hxx>
#include <plugins/gtk/atkbridge.hxx>

#include <rtl/strbuf.hxx>

#if OSL_DEBUG_LEVEL > 1
#include <stdio.h>
#endif

#include <dlfcn.h>

GtkHookedYieldMutex::GtkHookedYieldMutex()
{
}

/*
 * These methods always occur in pairs
 * A ThreadsEnter is followed by a ThreadsLeave
 * We need to queue up the recursive lock count
 * for each pair, so we can accurately restore
 * it later.
 */
void GtkHookedYieldMutex::ThreadsEnter()
{
    acquire();
    if( !aYieldStack.empty() )
    { /* Previously called ThreadsLeave() */
        ULONG nCount = aYieldStack.front();
        aYieldStack.pop_front();
        while( nCount-- > 1 )
            acquire();
    }
}

void GtkHookedYieldMutex::ThreadsLeave()
{
    aYieldStack.push_front( mnCount );

#if OSL_DEBUG_LEVEL > 1
    if( mnThreadId &&
        mnThreadId != NAMESPACE_VOS(OThread)::getCurrentIdentifier())
        fprintf( stderr, "\n\n--- A different thread owns the mutex ...---\n\n\n");
#endif

    while( mnCount > 1 )
        release();
    release();
}

void GtkHookedYieldMutex::acquire()
{
    SalYieldMutex::acquire();
}

void GtkHookedYieldMutex::release()
{
    SalYieldMutex::release();
}

extern "C"
{
    #define GET_YIELD_MUTEX() static_cast<GtkHookedYieldMutex*>(GetSalData()->m_pInstance->GetYieldMutex())
    static void GdkThreadsEnter( void )
    {
        GtkHookedYieldMutex *pYieldMutex = GET_YIELD_MUTEX();
        pYieldMutex->ThreadsEnter();
    }
    static void GdkThreadsLeave( void )
    {
        GtkHookedYieldMutex *pYieldMutex = GET_YIELD_MUTEX();
        pYieldMutex->ThreadsLeave();
    }
    static bool hookLocks( oslModule pModule )
    {
        typedef void (*GdkLockFn) (GCallback enter_fn, GCallback leave_fn);
        rtl::OUString aSymbolName( RTL_CONSTASCII_USTRINGPARAM( "gdk_threads_set_lock_functions") );

        GdkLockFn gdk_threads_set_lock_functions =
                (GdkLockFn) osl_getFunctionSymbol( pModule, aSymbolName.pData );
        if ( !gdk_threads_set_lock_functions )
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "Failed to hook gdk threads locks\n" );
#endif
            return false;
        }

        gdk_threads_set_lock_functions (GdkThreadsEnter, GdkThreadsLeave);
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "Hooked gdk threads locks\n" );
#endif
        return true;
    }

    VCL_DLLPUBLIC SalInstance* create_SalInstance( oslModule pModule )
    {
        const gchar* pVersion = gtk_check_version( 2, 2, 0 );
        if( pVersion )
        {
#if OSL_DEBUG_LEVEL > 1
            fprintf( stderr, "gtk version conflict: %s\n", pVersion );
#endif
            return NULL;
        }

        GtkYieldMutex *pYieldMutex;

        // init gdk thread protection
        if ( !g_thread_supported() )
            g_thread_init( NULL );

        if ( hookLocks( pModule ) )
            pYieldMutex = new GtkHookedYieldMutex();
        else
            pYieldMutex = new GtkYieldMutex();

        gdk_threads_init();

        GtkInstance* pInstance = new GtkInstance( pYieldMutex );
#if OSL_DEBUG_LEVEL > 1
        fprintf( stderr, "creating GtkSalInstance 0x%p\n", pInstance );
#endif

        // initialize SalData
        GtkData *pSalData = new GtkData();
        SetSalData( pSalData );
        pSalData->m_pInstance = pInstance;
        pSalData->Init();
        pSalData->initNWF();

        const char* pGtkModules = getenv( "GTK_MODULES" );
        if( pGtkModules )
        {
            rtl::OString aModules( pGtkModules );
            sal_Int32 nIndex = 0;
            while( nIndex >= 0 )
            {
                rtl::OString aToken = aModules.getToken( 0, ':', nIndex );
                if( aToken.equals( "gail" ) || aToken.equals( "atk-bridge" ) )
                {
                    InitAtkBridge();
                    break;
                }
            }
        }

        return pInstance;
    }
}

GtkInstance::~GtkInstance()
{
    DeInitAtkBridge();
}

SalFrame* GtkInstance::CreateFrame( SalFrame* pParent, ULONG nStyle )
{
    return new GtkSalFrame( pParent, nStyle );
}

SalFrame* GtkInstance::CreateChildFrame( SystemParentData* pParentData, ULONG )
{
    SalFrame* pFrame = new GtkSalFrame( pParentData );

    return pFrame;
}

SalObject* GtkInstance::CreateObject( SalFrame* pParent, SystemWindowData* pWindowData )
{
    // there is no method to set a visual for a GtkWidget
    // so we need the X11SalObject in that case
    if( pWindowData )
        return X11SalObject::CreateObject( pParent, pWindowData );

    return new GtkSalObject( static_cast<GtkSalFrame*>(pParent) );
}

GtkYieldMutex::GtkYieldMutex()
{
}

void GtkYieldMutex::acquire()
{
    vos::OThread::TThreadIdentifier aCurrentThread = vos::OThread::getCurrentIdentifier();
    // protect member manipulation
    OMutex::acquire();
    if( mnCount > 0 && mnThreadId == aCurrentThread )
    {
        mnCount++;
        OMutex::release();
        return;
    }
    OMutex::release();

    // obtain gdk mutex
    gdk_threads_enter();

    // obtained gdk mutex, now lock count is one by definition
    OMutex::acquire();
    mnCount = 1;
    mnThreadId = aCurrentThread;
    OMutex::release();
}

void GtkYieldMutex::release()
{
    vos::OThread::TThreadIdentifier aCurrentThread = vos::OThread::getCurrentIdentifier();
    // protect member manipulation
    OMutex::acquire();
    // strange things happen, do nothing if we don't own the mutex
    if( mnThreadId == aCurrentThread )
    {
        mnCount--;
        if( mnCount == 0 )
        {
            gdk_threads_leave();
            mnThreadId = 0;
        }
    }
    OMutex::release();
}

sal_Bool GtkYieldMutex::tryToAcquire()
{
    vos::OThread::TThreadIdentifier aCurrentThread = vos::OThread::getCurrentIdentifier();
    // protect member manipulation
    OMutex::acquire();
    if( mnCount > 0 )
    {
        if( mnThreadId == aCurrentThread )
        {
            mnCount++;
            OMutex::release();
            return sal_True;
        }
        else
        {
            OMutex::release();
            return sal_False;
        }
    }
    OMutex::release();

    // HACK: gdk_threads_mutex is private, we shouldn't use it.
    // how to we do a try_lock without having a gdk_threads_try_enter ?
    if( ! g_mutex_trylock( gdk_threads_mutex ) )
        return sal_False;

    // obtained gdk mutex, now lock count is one by definition
    OMutex::acquire();
    mnCount = 1;
    mnThreadId = aCurrentThread;
    OMutex::release();

    return sal_True;
}

int GtkYieldMutex::Grab()
{
    // this MUST only be called by gdk/gtk callbacks:
    // they are entered with gdk mutex locked; the mutex
    // was unlocked by GtkYieldMutex befor yielding which
    // is now locked again by gtk implicitly

    // obtained gdk mutex, now lock count is one by definition
    OMutex::acquire();
    int nRet = mnCount;
    if( mnCount == 0 ) // recursive else
        mnThreadId = vos::OThread::getCurrentIdentifier();
#if OSL_DEBUG_LEVEL > 1
    else if( mnThreadId != vos::OThread::getCurrentIdentifier() )
    {
        fprintf( stderr, "Yield mutex grabbed in different thread !\n" );
        abort();
    }
#endif
    mnCount = 1;
    OMutex::release();
    return nRet;
}

void GtkYieldMutex::Ungrab( int nGrabs )
{
    // this MUST only be called when leaving the callback
    // that locked the mutex with Grab()
    OMutex::acquire();
    mnCount = nGrabs;
    if( mnCount == 0 )
        mnThreadId = 0;
    OMutex::release();
}
<|endoftext|>


<commit_before>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Bohrium 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 General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __BH_VE_OPENCL_ENGINE_OPENCL_HPP
#define __BH_VE_OPENCL_ENGINE_OPENCL_HPP

#include <map>
#include <memory>
#include <vector>
#include <chrono>

#include <bh_config_parser.hpp>
#include <bh_view.hpp>
#include <jitk/statistics.hpp>
#include <jitk/kernel.hpp>
#include <jitk/codegen_util.hpp>

#include "cl.hpp"

namespace bohrium {

class EngineOpenCL {
private:
    // Map of all compiled OpenCL programs
    std::map<uint64_t, cl::Program> _programs;
    // The OpenCL context, device, and queue used throughout the execution
    cl::Context context;
    cl::Device device;
    cl::CommandQueue queue;
    // We save the OpenCL platform object for later information retrieval
    cl::Platform platform;
    // OpenCL work group sizes
    const cl_ulong work_group_size_1dx;
    const cl_ulong work_group_size_2dx;
    const cl_ulong work_group_size_2dy;
    const cl_ulong work_group_size_3dx;
    const cl_ulong work_group_size_3dy;
    const cl_ulong work_group_size_3dz;
    // OpenCL compile flags
    const std::string compile_flg;
    // Default device type
    const std::string default_device_type;
    // Default platform number
    const int platform_no;
    // Returns the global and local work OpenCL ranges based on the 'threaded_blocks'
    std::pair<cl::NDRange, cl::NDRange> NDRanges(const std::vector<const jitk::LoopB*> &threaded_blocks) const;
    // A map of allocated buffers on the device
    std::map<bh_base*, std::unique_ptr<cl::Buffer> > buffers;
    // Verbose flag
    const bool verbose;
    // Some statistics
    jitk::Statistics &stat;
    // Record profiling statistics
    const bool prof;
    // Path to the directory of the source files (only used in verbose mode)
    const boost::filesystem::path source_dir;
public:
    EngineOpenCL(const ConfigParser &config, jitk::Statistics &stat);

    // Execute the 'source'
    void execute(const std::string &source, const jitk::Kernel &kernel,
                 const std::vector<const jitk::LoopB*> &threaded_blocks,
                 const std::vector<const bh_view*> &offset_strides,
                 const std::vector<const bh_instruction*> &constants);

    // Copy 'bases' to the host (ignoring bases that isn't on the device)
    template <typename T>
    void copyToHost(T &bases) {
        auto tcopy = std::chrono::steady_clock::now();
        // Let's copy sync'ed arrays back to the host
        for(bh_base *base: bases) {
            if (buffers.find(base) != buffers.end()) {
                bh_data_malloc(base);
                if (verbose) {
                    std::cout << "Copy to host: " << *base << std::endl;
                }
                queue.enqueueReadBuffer(*buffers.at(base), CL_FALSE, 0, (cl_ulong) bh_base_size(base), base->data);
                // When syncing we assume that the host writes to the data and invalidate the device data thus
                // we have to remove its data buffer
                buffers.erase(base);
            }
        }
        queue.finish();
        stat.time_copy2host += std::chrono::steady_clock::now() - tcopy;
    }

    // Copy 'base_list' to the device (ignoring bases that is already on the device)
    template <typename T>
    void copyToDevice(T &base_list) {

        // Let's update the maximum memory usage on the device
        if (prof) {
            uint64_t sum = 0;
            for (const auto &b: buffers) {
                sum += bh_base_size(b.first);
            }
            stat.max_memory_usage = sum > stat.max_memory_usage?sum:stat.max_memory_usage;
        }

        auto tcopy = std::chrono::steady_clock::now();
        for(bh_base *base: base_list) {
            if (buffers.find(base) == buffers.end()) { // We shouldn't overwrite existing buffers
                cl::Buffer *buf = new cl::Buffer(context, CL_MEM_READ_WRITE, (cl_ulong) bh_base_size(base));
                buffers[base].reset(buf);

                // If the host data is non-null we should copy it to the device
                if (base->data != NULL) {
                    if (verbose) {
                        std::cout << "Copy to device: " << *base << std::endl;
                    }
                    queue.enqueueWriteBuffer(*buf, CL_FALSE, 0, (cl_ulong) bh_base_size(base), base->data);
                }
            }
        }
        queue.finish();
        stat.time_copy2dev += std::chrono::steady_clock::now() - tcopy;
    }

    // Copy all bases to the host (ignoring bases that isn't on the device)
    void allBasesToHost() {
        std::vector<bh_base*> bases_on_device;
        for(auto &buf_pair: buffers) {
            bases_on_device.push_back(buf_pair.first);
        }
        copyToHost(bases_on_device);
    }

    // Sets the constructor flag of each instruction in 'instr_list'
    void set_constructor_flag(std::vector<bh_instruction*> &instr_list);

    // Return a YAML string describing this component
    std::string info() const;

    // Retrieve a single buffer
    template <typename T>
    cl::Buffer* getBuffer(T &base) {
        if(buffers.find(base) == buffers.end()) {
            std::vector<T> vec = {base};
            copyToDevice(vec);
        }
        return &(*buffers[base]);
    }

    // Delete a buffer
    template <typename T>
    void delBuffer(T &base) {
        buffers.erase(base);
    }

    // Get C buffer from wrapped C++ object
    template <typename T>
    cl_mem getCBuffer(T &base) {
        return (*getBuffer(base))();
    }

    cl::CommandQueue* getQueue() {
        return &queue;
    }

    // Get C command queue from wrapped C++ object
    cl_command_queue getCQueue() {
        return queue();
    }
};

} // bohrium

#endif
<commit_msg>opencl: clean up<commit_after>/*
This file is part of Bohrium and copyright (c) 2012 the Bohrium
team <http://www.bh107.org>.

Bohrium is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3
of the License, or (at your option) any later version.

Bohrium 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 General Public License for more details.

You should have received a copy of the
GNU Lesser General Public License along with Bohrium.

If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __BH_VE_OPENCL_ENGINE_OPENCL_HPP
#define __BH_VE_OPENCL_ENGINE_OPENCL_HPP

#include <map>
#include <memory>
#include <vector>
#include <chrono>

#include <bh_config_parser.hpp>
#include <bh_view.hpp>
#include <jitk/statistics.hpp>
#include <jitk/kernel.hpp>
#include <jitk/codegen_util.hpp>

#include "cl.hpp"

namespace bohrium {

class EngineOpenCL {
private:
    // Map of all compiled OpenCL programs
    std::map<uint64_t, cl::Program> _programs;
    // The OpenCL context, device, and queue used throughout the execution
    cl::Context context;
    cl::Device device;
    cl::CommandQueue queue;
    // We save the OpenCL platform object for later information retrieval
    cl::Platform platform;
    // OpenCL work group sizes
    const cl_ulong work_group_size_1dx;
    const cl_ulong work_group_size_2dx;
    const cl_ulong work_group_size_2dy;
    const cl_ulong work_group_size_3dx;
    const cl_ulong work_group_size_3dy;
    const cl_ulong work_group_size_3dz;
    // OpenCL compile flags
    const std::string compile_flg;
    // Default device type
    const std::string default_device_type;
    // Default platform number
    const int platform_no;
    // Returns the global and local work OpenCL ranges based on the 'threaded_blocks'
    std::pair<cl::NDRange, cl::NDRange> NDRanges(const std::vector<const jitk::LoopB*> &threaded_blocks) const;
    // A map of allocated buffers on the device
    std::map<bh_base*, std::unique_ptr<cl::Buffer> > buffers;
    // Verbose flag
    const bool verbose;
    // Some statistics
    jitk::Statistics &stat;
    // Record profiling statistics
    const bool prof;
    // Path to the directory of the source files (only used in verbose mode)
    const boost::filesystem::path source_dir;
public:
    EngineOpenCL(const ConfigParser &config, jitk::Statistics &stat);

    // Execute the 'source'
    void execute(const std::string &source, const jitk::Kernel &kernel,
                 const std::vector<const jitk::LoopB*> &threaded_blocks,
                 const std::vector<const bh_view*> &offset_strides,
                 const std::vector<const bh_instruction*> &constants);

    // Copy 'bases' to the host (ignoring bases that isn't on the device)
    template <typename T>
    void copyToHost(T &bases) {
        auto tcopy = std::chrono::steady_clock::now();
        // Let's copy sync'ed arrays back to the host
        for(bh_base *base: bases) {
            if (buffers.find(base) != buffers.end()) {
                bh_data_malloc(base);
                if (verbose) {
                    std::cout << "Copy to host: " << *base << std::endl;
                }
                queue.enqueueReadBuffer(*buffers.at(base), CL_FALSE, 0, (cl_ulong) bh_base_size(base), base->data);
                // When syncing we assume that the host writes to the data and invalidate the device data thus
                // we have to remove its data buffer
                buffers.erase(base);
            }
        }
        queue.finish();
        stat.time_copy2host += std::chrono::steady_clock::now() - tcopy;
    }

    // Copy 'base_list' to the device (ignoring bases that is already on the device)
    template <typename T>
    void copyToDevice(T &base_list) {

        // Let's update the maximum memory usage on the device
        if (prof) {
            uint64_t sum = 0;
            for (const auto &b: buffers) {
                sum += bh_base_size(b.first);
            }
            stat.max_memory_usage = sum > stat.max_memory_usage?sum:stat.max_memory_usage;
        }

        auto tcopy = std::chrono::steady_clock::now();
        for(bh_base *base: base_list) {
            if (buffers.find(base) == buffers.end()) { // We shouldn't overwrite existing buffers
                cl::Buffer *buf = new cl::Buffer(context, CL_MEM_READ_WRITE, (cl_ulong) bh_base_size(base));
                buffers[base].reset(buf);

                // If the host data is non-null we should copy it to the device
                if (base->data != NULL) {
                    if (verbose) {
                        std::cout << "Copy to device: " << *base << std::endl;
                    }
                    queue.enqueueWriteBuffer(*buf, CL_FALSE, 0, (cl_ulong) bh_base_size(base), base->data);
                }
            }
        }
        queue.finish();
        stat.time_copy2dev += std::chrono::steady_clock::now() - tcopy;
    }

    // Copy all bases to the host (ignoring bases that isn't on the device)
    void allBasesToHost() {
        std::vector<bh_base*> bases_on_device;
        for(auto &buf_pair: buffers) {
            bases_on_device.push_back(buf_pair.first);
        }
        copyToHost(bases_on_device);
    }

    // Sets the constructor flag of each instruction in 'instr_list'
    void set_constructor_flag(std::vector<bh_instruction*> &instr_list);

    // Return a YAML string describing this component
    std::string info() const;

    // Retrieve a single buffer
    cl::Buffer* getBuffer(bh_base* base) {
        if(buffers.find(base) == buffers.end()) {
            std::vector<bh_base*> vec = {base};
            copyToDevice(vec);
        }
        return &(*buffers[base]);
    }

    // Delete a buffer
    void delBuffer(bh_base* base) {
        buffers.erase(base);
    }

    // Get C buffer from wrapped C++ object
    cl_mem getCBuffer(bh_base* base) {
        return (*getBuffer(base))();
    }

    // Get the OpenCL command queue object
    cl::CommandQueue* getQueue() {
        return &queue;
    }

    // Get C command queue from wrapped C++ object
    cl_command_queue getCQueue() {
        return queue();
    }
};

} // bohrium

#endif
<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gsl/gsl_assert>
#include <net/tcp/listener.hpp>
#include <net/tcp/tcp.hpp>

using namespace net;
using namespace tcp;

Listener::Listener(TCP& host, Socket local, ConnectCallback cb)
  : host_(host), local_(local), syn_queue_(),
    on_accept_({this, &Listener::default_on_accept}),
    on_connect_{std::move(cb)},
    _on_close_({host_, &TCP::close_listener})
{
}

bool Listener::default_on_accept(Socket) {
  return true;
}

bool Listener::syn_queue_full() const
{ return syn_queue_.size() >= host_.max_syn_backlog(); }

void Listener::segment_arrived(Packet_ptr packet) {
  debug2("<Listener::segment_arrived> Received packet: %s\n",
    packet->to_string().c_str());

  auto it = std::find_if(syn_queue_.begin(), syn_queue_.end(),
    [dest = packet->source()]
    (Connection_ptr conn) {
      return conn->remote() == dest;
    });

  // if it's an reply to any of our half-open connections
  if(it != syn_queue_.end())
  {
    auto conn = *it;
    debug("<Listener::segment_arrived> Found packet receiver: %s\n",
      conn->to_string().c_str());
    conn->segment_arrived(std::move(packet));
    debug2("<Listener::segment_arrived> Connection done handling segment\n");
    return;
  }
  // if it's a new attempt (SYN)
  else
  {
    // don't waste time if the packet does not have SYN
    if(UNLIKELY(not packet->isset(SYN) or packet->has_tcp_data()))
    {
      host_.send_reset(*packet);
      return;
    }

    // Stat increment number of connection attempts
    host_.connection_attempts_++;

    // if we don't like this client, do nothing
    if(UNLIKELY(on_accept_(packet->source()) == false))
      return;

    // remove oldest connection if queue is full
    debug2("<Listener::segment_arrived> SynQueue: %u\n", syn_queue_.size());
    // SYN queue is full
    if(syn_queue_.size() >= host_.max_syn_backlog())
    {
      debug2("<Listener::segment_arrived> Queue is full\n");
      Expects(not syn_queue_.empty());
      debug("<Listener::segment_arrived> Connection %s dropped to make room for new connection\n",
        syn_queue_.back()->to_string().c_str());

      syn_queue_.pop_back();
    }

    auto& conn = *(syn_queue_.emplace(
      syn_queue_.cbegin(),
      std::make_shared<Connection>(host_, packet->destination(), packet->source(), ConnectCallback{this, &Listener::connected})
      )
    );
    conn->_on_cleanup({this, &Listener::remove});
    // Open connection
    conn->open(false);
    Ensures(conn->is_listening());
    debug("<Listener::segment_arrived> Connection %s created\n",
      conn->to_string().c_str());
    conn->segment_arrived(std::move(packet));
    debug2("<Listener::segment_arrived> Connection done handling segment\n");
    return;
  }
  debug2("<Listener::segment_arrived> No receipent\n");
}

void Listener::remove(Connection_ptr conn) {
  debug2("<Listener::remove> Try remove %s\n", conn->to_string().c_str());
  auto it = syn_queue_.begin();
  while(it != syn_queue_.end())
  {
    if((*it) == conn)
    {
      syn_queue_.erase(it);
      debug("<Listener::remove> %s removed.\n", conn->to_string().c_str());
      return;
    }
    it++;
  }
}

void Listener::connected(Connection_ptr conn) {
  debug("<Listener::connected> %s connected\n", conn->to_string().c_str());
  remove(conn);
  Expects(conn->is_connected());
  host_.add_connection(conn);

  if(on_connect_ != nullptr)
    on_connect_(conn);
}

void Listener::close() {
  // Maybe abort() is too harsh, but connections are fully established yet so why not
  for(auto conn : syn_queue_)
    conn->abort();

  _on_close_(*this);
}

/**
 * [Port] (SynQueue size)
 *    <SynQueue entries>
 */

std::string Listener::to_string() const {
  char buffer[256];
  int len = snprintf(buffer, sizeof(buffer),
          "[%s] SynQueue (%ld) ", local_.to_string().c_str(), syn_queue_.size());
  std::string str(buffer, len);
  // add syn queue
  for(auto& conn : syn_queue_)
      str += "\n\t" + conn->to_string();
  return str;
}
<commit_msg>net: Fix size print on Listener::to_string<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <gsl/gsl_assert>
#include <net/tcp/listener.hpp>
#include <net/tcp/tcp.hpp>

using namespace net;
using namespace tcp;

Listener::Listener(TCP& host, Socket local, ConnectCallback cb)
  : host_(host), local_(local), syn_queue_(),
    on_accept_({this, &Listener::default_on_accept}),
    on_connect_{std::move(cb)},
    _on_close_({host_, &TCP::close_listener})
{
}

bool Listener::default_on_accept(Socket) {
  return true;
}

bool Listener::syn_queue_full() const
{ return syn_queue_.size() >= host_.max_syn_backlog(); }

void Listener::segment_arrived(Packet_ptr packet) {
  debug2("<Listener::segment_arrived> Received packet: %s\n",
    packet->to_string().c_str());

  auto it = std::find_if(syn_queue_.begin(), syn_queue_.end(),
    [dest = packet->source()]
    (Connection_ptr conn) {
      return conn->remote() == dest;
    });

  // if it's an reply to any of our half-open connections
  if(it != syn_queue_.end())
  {
    auto conn = *it;
    debug("<Listener::segment_arrived> Found packet receiver: %s\n",
      conn->to_string().c_str());
    conn->segment_arrived(std::move(packet));
    debug2("<Listener::segment_arrived> Connection done handling segment\n");
    return;
  }
  // if it's a new attempt (SYN)
  else
  {
    // don't waste time if the packet does not have SYN
    if(UNLIKELY(not packet->isset(SYN) or packet->has_tcp_data()))
    {
      host_.send_reset(*packet);
      return;
    }

    // Stat increment number of connection attempts
    host_.connection_attempts_++;

    // if we don't like this client, do nothing
    if(UNLIKELY(on_accept_(packet->source()) == false))
      return;

    // remove oldest connection if queue is full
    debug2("<Listener::segment_arrived> SynQueue: %u\n", syn_queue_.size());
    // SYN queue is full
    if(syn_queue_.size() >= host_.max_syn_backlog())
    {
      debug2("<Listener::segment_arrived> Queue is full\n");
      Expects(not syn_queue_.empty());
      debug("<Listener::segment_arrived> Connection %s dropped to make room for new connection\n",
        syn_queue_.back()->to_string().c_str());

      syn_queue_.pop_back();
    }

    auto& conn = *(syn_queue_.emplace(
      syn_queue_.cbegin(),
      std::make_shared<Connection>(host_, packet->destination(), packet->source(), ConnectCallback{this, &Listener::connected})
      )
    );
    conn->_on_cleanup({this, &Listener::remove});
    // Open connection
    conn->open(false);
    Ensures(conn->is_listening());
    debug("<Listener::segment_arrived> Connection %s created\n",
      conn->to_string().c_str());
    conn->segment_arrived(std::move(packet));
    debug2("<Listener::segment_arrived> Connection done handling segment\n");
    return;
  }
  debug2("<Listener::segment_arrived> No receipent\n");
}

void Listener::remove(Connection_ptr conn) {
  debug2("<Listener::remove> Try remove %s\n", conn->to_string().c_str());
  auto it = syn_queue_.begin();
  while(it != syn_queue_.end())
  {
    if((*it) == conn)
    {
      syn_queue_.erase(it);
      debug("<Listener::remove> %s removed.\n", conn->to_string().c_str());
      return;
    }
    it++;
  }
}

void Listener::connected(Connection_ptr conn) {
  debug("<Listener::connected> %s connected\n", conn->to_string().c_str());
  remove(conn);
  Expects(conn->is_connected());
  host_.add_connection(conn);

  if(on_connect_ != nullptr)
    on_connect_(conn);
}

void Listener::close() {
  // Maybe abort() is too harsh, but connections are fully established yet so why not
  for(auto conn : syn_queue_)
    conn->abort();

  _on_close_(*this);
}

/**
 * [Port] (SynQueue size)
 *    <SynQueue entries>
 */

std::string Listener::to_string() const {
  char buffer[256];
  int len = snprintf(buffer, sizeof(buffer),
          "[%s] SynQueue (%zu) ", local_.to_string().c_str(), syn_queue_.size());
  std::string str(buffer, len);
  // add syn queue
  for(auto& conn : syn_queue_)
      str += "\n\t" + conn->to_string();
  return str;
}
<|endoftext|>


<commit_before>/*
KSync - Client-Server synchronization system using rsync.
Copyright (C) 2014  Matthew Scott Krafczyk

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "ksync/client.h"

int main(int argc __attribute__((unused)), char** argv __attribute__((unused))) {
	return 0;
}
<commit_msg>Argument parsing for client<commit_after>/*
KSync - Client-Server synchronization system using rsync.
Copyright (C) 2014  Matthew Scott Krafczyk

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "ksync/logging.h"
#include "ksync/optparse.h"
#include "ksync/client.h"

int main(int argc, char** argv) {
	KSync::ArgParser arg_parser("KSync Server - Server side of a Client-Server synchonization system using rsync.");

	int status;
	if((status = arg_parser.ParseArgs(argc, argv)) < 0) {
		Error("Problem parsing arguments\n");
		arg_parser.PrintHelp();
		return -1;
	}

	return 0;
}
<|endoftext|>