<commit_before>// @(#)root/tmva $Id$
// Author: Matt Jachowski

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : TActivationTanh                                                       *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Tanh activation function (sigmoid normalized in [-1,1] for an ANN.        *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Matt Jachowski  <jachowski@stanford.edu> - Stanford University, USA       *
 *                                                                                *
 * Copyright (c) 2005:                                                            *
 *      CERN, Switzerland                                                         *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without             *
 * modification, are permitted according to the terms listed in LICENSE           *
 * (http://tmva.sourceforge.net/LICENSE)                                          *
 **********************************************************************************/

//_______________________________________________________________________
//
//  Tanh activation function for ANN. This really simple implementation
//  uses TFormulas and should probably be replaced with something more
//  efficient later.
//
//_______________________________________________________________________

#include <iostream>

#include "TFormula.h"
#include "TString.h"
#include "TMath.h"

#ifndef ROOT_TMVA_TActivationTanh
#include "TMVA/TActivationTanh.h"
#endif

ClassImp(TMVA::TActivationTanh)

////////////////////////////////////////////////////////////////////////////////
/// constructor for tanh sigmoid (normalized in [-1,1])

TMVA::TActivationTanh::TActivationTanh()
{
   fFAST=kTRUE;
}

////////////////////////////////////////////////////////////////////////////////
/// destructor

TMVA::TActivationTanh::~TActivationTanh()
{
}

////////////////////////////////////////////////////////////////////////////////
/// a fast tanh approximation

Double_t TMVA::TActivationTanh::fast_tanh(Double_t arg){
   float arg2 = arg * arg;
   float a = arg * (135135.0f + arg2 * (17325.0f + arg2 * (378.0f + arg2)));
   float b = 135135.0f + arg2 * (62370.0f + arg2 * (3150.0f + arg2 * 28.0f));
   return a / b;
}

////////////////////////////////////////////////////////////////////////////////
/// evaluate the tanh

Double_t TMVA::TActivationTanh::Eval(Double_t arg)
{
   return fFAST ? fast_tanh(arg) : TMath::TanH(arg);
}

////////////////////////////////////////////////////////////////////////////////
/// evaluate the derivative

Double_t TMVA::TActivationTanh::EvalDerivative(Double_t arg)
{
   Double_t tmp=Eval(arg);
   return ( 1-tmp*tmp);
}

////////////////////////////////////////////////////////////////////////////////
/// get expressions for the tanh and its derivative
/// whatever that may be good for ...

TString TMVA::TActivationTanh::GetExpression()
{
   TString expr = "tanh(x)\t\t (1-tanh()^2)";
   return expr;
}

////////////////////////////////////////////////////////////////////////////////
/// writes the sigmoid activation function source code

void TMVA::TActivationTanh::MakeFunction( std::ostream& fout, const TString& fncName )
{
   fout << "double " << fncName << "(double x) const {" << std::endl;
   fout << "   // hyperbolic tan" << std::endl;
   fout << "   return tanh(x);" << std::endl;
   fout << "}" << std::endl;
}
<commit_msg>protect fast tanh approximation against floating point exception<commit_after>// @(#)root/tmva $Id$
// Author: Matt Jachowski

/**********************************************************************************
 * Project: TMVA - a Root-integrated toolkit for multivariate data analysis       *
 * Package: TMVA                                                                  *
 * Class  : TActivationTanh                                                       *
 * Web    : http://tmva.sourceforge.net                                           *
 *                                                                                *
 * Description:                                                                   *
 *      Tanh activation function (sigmoid normalized in [-1,1] for an ANN.        *
 *                                                                                *
 * Authors (alphabetical):                                                        *
 *      Matt Jachowski  <jachowski@stanford.edu> - Stanford University, USA       *
 *                                                                                *
 * Copyright (c) 2005:                                                            *
 *      CERN, Switzerland                                                         *
 *                                                                                *
 * Redistribution and use in source and binary forms, with or without             *
 * modification, are permitted according to the terms listed in LICENSE           *
 * (http://tmva.sourceforge.net/LICENSE)                                          *
 **********************************************************************************/

//_______________________________________________________________________
//
//  Tanh activation function for ANN. This really simple implementation
//  uses TFormulas and should probably be replaced with something more
//  efficient later.
//
//_______________________________________________________________________

#include <iostream>

#include "TFormula.h"
#include "TString.h"
#include "TMath.h"

#ifndef ROOT_TMVA_TActivationTanh
#include "TMVA/TActivationTanh.h"
#endif

ClassImp(TMVA::TActivationTanh)

////////////////////////////////////////////////////////////////////////////////
/// constructor for tanh sigmoid (normalized in [-1,1])

TMVA::TActivationTanh::TActivationTanh()
{
   fFAST=kTRUE;
}

////////////////////////////////////////////////////////////////////////////////
/// destructor

TMVA::TActivationTanh::~TActivationTanh()
{
}

////////////////////////////////////////////////////////////////////////////////
/// a fast tanh approximation

Double_t TMVA::TActivationTanh::fast_tanh(Double_t arg){
   if (arg > 4.97) return 1;
   if (arg < -4.97) return -1;
   float arg2 = arg * arg;
   float a = arg * (135135.0f + arg2 * (17325.0f + arg2 * (378.0f + arg2)));
   float b = 135135.0f + arg2 * (62370.0f + arg2 * (3150.0f + arg2 * 28.0f));
   return a/b;
}

////////////////////////////////////////////////////////////////////////////////
/// evaluate the tanh

Double_t TMVA::TActivationTanh::Eval(Double_t arg)
{
   return fFAST ? fast_tanh(arg) : TMath::TanH(arg);
}

////////////////////////////////////////////////////////////////////////////////
/// evaluate the derivative

Double_t TMVA::TActivationTanh::EvalDerivative(Double_t arg)
{
   Double_t tmp=Eval(arg);
   return ( 1-tmp*tmp);
}

////////////////////////////////////////////////////////////////////////////////
/// get expressions for the tanh and its derivative
/// whatever that may be good for ...

TString TMVA::TActivationTanh::GetExpression()
{
   TString expr = "tanh(x)\t\t (1-tanh()^2)";
   return expr;
}

////////////////////////////////////////////////////////////////////////////////
/// writes the sigmoid activation function source code

void TMVA::TActivationTanh::MakeFunction( std::ostream& fout, const TString& fncName )
{
   fout << "double " << fncName << "(double x) const {" << std::endl;
   fout << "   // hyperbolic tan" << std::endl;
   fout << "   return tanh(x);" << std::endl;
   fout << "}" << std::endl;
}
<|endoftext|>


<commit_before>/*************************************************************************/
/*  editor_sub_scene.cpp                                                 */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                    http://www.godotengine.org                         */
/*************************************************************************/
/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.                 */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/
#include "editor_sub_scene.h"
#include "scene/gui/margin_container.h"
#include "scene/resources/packed_scene.h"
void EditorSubScene::_path_selected(const String& p_path) {

	path->set_text(p_path);
	_path_changed(p_path);

}

void EditorSubScene::_path_changed(const String& p_path) {

	tree->clear();

	if (scene) {
		memdelete(scene);
		scene=NULL;
	}

	if (p_path=="")
		return;

	Ref<PackedScene> ps = ResourceLoader::load(p_path,"PackedScene");

	if (ps.is_null())
		return;

	scene = ps->instance();
	if (!scene)
		return;

	_fill_tree(scene,NULL);

}

void EditorSubScene::_path_browse() {

	file_dialog->popup_centered_ratio();
}

void EditorSubScene::_notification(int p_what) {

	if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {

		if (!is_visible()) {

		}
	}
}

void EditorSubScene::_fill_tree(Node* p_node,TreeItem *p_parent) {

	TreeItem *it = tree->create_item(p_parent);
	it->set_metadata(0,p_node);
	it->set_text(0,p_node->get_name());
	it->set_editable(0,false);
	it->set_selectable(0,true);
	if (has_icon(p_node->get_type(),"EditorIcons")) {
		it->set_icon(0,get_icon(p_node->get_type(),"EditorIcons"));

	}

	for(int i=0;i<p_node->get_child_count();i++) {

		Node *c = p_node->get_child(i);
		if (c->get_owner()!=scene)
			continue;
		_fill_tree(c,it);
	}

}

void EditorSubScene::ok_pressed() {

	TreeItem *s = tree->get_selected();
	if (!s)
		return;
	Node *selnode = s->get_metadata(0);
	if (!selnode)
		return;
	emit_signal("subscene_selected");
	hide();
	clear();

}

void EditorSubScene::_reown(Node* p_node,List<Node*> *p_to_reown) {

	if (p_node==scene) {

		scene->set_filename("");
		p_to_reown->push_back(p_node);
	} else if (p_node->get_owner()==scene){

		p_to_reown->push_back(p_node);
	}

	for(int i=0;i<p_node->get_child_count();i++) {
		Node *c=p_node->get_child(i);
		_reown(c,p_to_reown);
	}
}

void EditorSubScene::move(Node* p_new_parent, Node* p_new_owner) {

	if (!scene) {
		return;
	}
	TreeItem *s = tree->get_selected();
	if (!s) {
		return;
	}

	Node *selnode = s->get_metadata(0);
	if (!selnode) {
		return;
	}

	List<Node*> to_reown;
	_reown(selnode,&to_reown);

	if (selnode!=scene) {
		selnode->get_parent()->remove_child(selnode);
	}

	p_new_parent->add_child(selnode);
	for (List<Node*>::Element *E=to_reown.front();E;E=E->next()) {
		E->get()->set_owner(p_new_owner);
	}

	if (selnode!=scene) {
		memdelete(scene);
	}
	scene=NULL;

	//return selnode;

}

void EditorSubScene::clear() {

	path->set_text("");
	_path_changed("");
}

void EditorSubScene::_bind_methods() {

	ObjectTypeDB::bind_method(_MD("_path_selected"),&EditorSubScene::_path_selected);
	ObjectTypeDB::bind_method(_MD("_path_changed"),&EditorSubScene::_path_changed);
	ObjectTypeDB::bind_method(_MD("_path_browse"),&EditorSubScene::_path_browse);
	ADD_SIGNAL( MethodInfo("subscene_selected"));

}

EditorSubScene::EditorSubScene() {

	scene=NULL;

	set_title("Select Sub-Scene..");
	set_hide_on_ok(false);

	VBoxContainer *vb = memnew( VBoxContainer );
	add_child(vb);
	set_child_rect(vb);

	HBoxContainer *hb = memnew( HBoxContainer );
	path = memnew( LineEdit );
	path->connect("text_entered",this,"_path_changed");
	hb->add_child(path);
	path->set_h_size_flags(SIZE_EXPAND_FILL);
	Button *b = memnew( Button );
	b->set_text(" .. ");
	hb->add_child(b);
	b->connect("pressed",this,"_path_browse");
	vb->add_margin_child("Scene Path:",hb);

	tree = memnew( Tree );
	tree->set_v_size_flags(SIZE_EXPAND_FILL);
	vb->add_margin_child("Import From Node:",tree,true);
	tree->connect("item_activated",this,"_ok");

	file_dialog = memnew( EditorFileDialog );
	List<String> extensions;
	ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);

	for(List<String>::Element *E = extensions.front();E;E=E->next() ) {

		file_dialog->add_filter("*."+E->get());
	}

	file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
	add_child(file_dialog);
	file_dialog->connect("file_selected",this,"_path_selected");

}
<commit_msg>Fix crash when importing sub-scenes<commit_after>/*************************************************************************/
/*  editor_sub_scene.cpp                                                 */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                    http://www.godotengine.org                         */
/*************************************************************************/
/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur.                 */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/
#include "editor_sub_scene.h"
#include "scene/gui/margin_container.h"
#include "scene/resources/packed_scene.h"
void EditorSubScene::_path_selected(const String& p_path) {

	path->set_text(p_path);
	_path_changed(p_path);

}

void EditorSubScene::_path_changed(const String& p_path) {

	tree->clear();

	if (scene) {
		memdelete(scene);
		scene=NULL;
	}

	if (p_path=="")
		return;

	Ref<PackedScene> ps = ResourceLoader::load(p_path,"PackedScene");

	if (ps.is_null())
		return;

	scene = ps->instance();
	if (!scene)
		return;

	_fill_tree(scene,NULL);

}

void EditorSubScene::_path_browse() {

	file_dialog->popup_centered_ratio();
}

void EditorSubScene::_notification(int p_what) {

	if (p_what==NOTIFICATION_VISIBILITY_CHANGED) {

		if (!is_visible()) {

		}
	}
}

void EditorSubScene::_fill_tree(Node* p_node,TreeItem *p_parent) {

	TreeItem *it = tree->create_item(p_parent);
	it->set_metadata(0,p_node);
	it->set_text(0,p_node->get_name());
	it->set_editable(0,false);
	it->set_selectable(0,true);
	if (has_icon(p_node->get_type(),"EditorIcons")) {
		it->set_icon(0,get_icon(p_node->get_type(),"EditorIcons"));

	}

	for(int i=0;i<p_node->get_child_count();i++) {

		Node *c = p_node->get_child(i);
		if (c->get_owner()!=scene)
			continue;
		_fill_tree(c,it);
	}

}

void EditorSubScene::ok_pressed() {

	TreeItem *s = tree->get_selected();
	if (!s)
		return;
	Node *selnode = s->get_metadata(0);
	if (!selnode)
		return;
	emit_signal("subscene_selected");
	hide();
	clear();

}

void EditorSubScene::_reown(Node* p_node,List<Node*> *p_to_reown) {

	if (p_node==scene) {

		scene->set_filename("");
		p_to_reown->push_back(p_node);
	} else if (p_node->get_owner()==scene){

		p_to_reown->push_back(p_node);
	}

	for(int i=0;i<p_node->get_child_count();i++) {
		Node *c=p_node->get_child(i);
		_reown(c,p_to_reown);
	}
}

void EditorSubScene::move(Node* p_new_parent, Node* p_new_owner) {

	if (!scene) {
		return;
	}
	TreeItem *s = tree->get_selected();
	if (!s) {
		return;
	}

	Node *selnode = s->get_metadata(0);
	if (!selnode) {
		return;
	}

	List<Node*> to_reown;
	_reown(selnode,&to_reown);

	if (selnode!=scene) {
		selnode->get_parent()->remove_child(selnode);
	}

	p_new_parent->add_child(selnode);
	for (List<Node*>::Element *E=to_reown.front();E;E=E->next()) {
		E->get()->set_owner(p_new_owner);
	}

	if (selnode!=scene) {
		memdelete(scene);
	}
	scene=NULL;

	//return selnode;

}

void EditorSubScene::clear() {

	path->set_text("");
	_path_changed("");
}

void EditorSubScene::_bind_methods() {

	ObjectTypeDB::bind_method(_MD("_path_selected"),&EditorSubScene::_path_selected);
	ObjectTypeDB::bind_method(_MD("_path_changed"),&EditorSubScene::_path_changed);
	ObjectTypeDB::bind_method(_MD("_path_browse"),&EditorSubScene::_path_browse);
	ADD_SIGNAL( MethodInfo("subscene_selected"));

}

EditorSubScene::EditorSubScene() {

	scene=NULL;

	set_title("Select Sub-Scene..");
	set_hide_on_ok(false);

	VBoxContainer *vb = memnew( VBoxContainer );
	add_child(vb);
	set_child_rect(vb);

	HBoxContainer *hb = memnew( HBoxContainer );
	path = memnew( LineEdit );
	path->connect("text_entered",this,"_path_changed");
	hb->add_child(path);
	path->set_h_size_flags(SIZE_EXPAND_FILL);
	Button *b = memnew( Button );
	b->set_text(" .. ");
	hb->add_child(b);
	b->connect("pressed",this,"_path_browse");
	vb->add_margin_child("Scene Path:",hb);

	tree = memnew( Tree );
	tree->set_v_size_flags(SIZE_EXPAND_FILL);
	vb->add_margin_child("Import From Node:",tree,true);
	tree->connect("item_activated",this,"_ok",make_binds(),CONNECT_DEFERRED);

	file_dialog = memnew( EditorFileDialog );
	List<String> extensions;
	ResourceLoader::get_recognized_extensions_for_type("PackedScene",&extensions);

	for(List<String>::Element *E = extensions.front();E;E=E->next() ) {

		file_dialog->add_filter("*."+E->get());
	}

	file_dialog->set_mode(EditorFileDialog::MODE_OPEN_FILE);
	add_child(file_dialog);
	file_dialog->connect("file_selected",this,"_path_selected");

}
<|endoftext|>


<commit_before>//===-- llvm-config.cpp - LLVM project configuration utility --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tool encapsulates information about an LLVM project configuration for
// use by other project's build environments (to determine installed path,
// available features, required libraries, etc.).
//
// Note that although this tool *may* be used by some parts of LLVM's build
// itself (i.e., the Makefiles use it to compute required libraries when linking
// tools), this tool is primarily designed to support external projects.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <set>
#include <vector>

using namespace llvm;

// Include the build time variables we can report to the user. This is generated
// at build time from the BuildVariables.inc.in file by the build system.
#include "BuildVariables.inc"

// Include the component table. This creates an array of struct
// AvailableComponent entries, which record the component name, library name,
// and required components for all of the available libraries.
//
// Not all components define a library, we also use "library groups" as a way to
// create entries for pseudo groups like x86 or all-targets.
#include "LibraryDependencies.inc"

/// \brief Traverse a single component adding to the topological ordering in
/// \arg RequiredLibs.
///
/// \param Name - The component to traverse.
/// \param ComponentMap - A prebuilt map of component names to descriptors.
/// \param VisitedComponents [in] [out] - The set of already visited components.
/// \param RequiredLibs [out] - The ordered list of required libraries.
static void VisitComponent(StringRef Name,
                           const StringMap<AvailableComponent*> &ComponentMap,
                           std::set<AvailableComponent*> &VisitedComponents,
                           std::vector<StringRef> &RequiredLibs,
                           bool IncludeNonInstalled) {
  // Lookup the component.
  AvailableComponent *AC = ComponentMap.lookup(Name);
  assert(AC && "Invalid component name!");

  // Add to the visited table.
  if (!VisitedComponents.insert(AC).second) {
    // We are done if the component has already been visited.
    return;
  }

  // Only include non-installed components if requested.
  if (!AC->IsInstalled && !IncludeNonInstalled)
    return;

  // Otherwise, visit all the dependencies.
  for (unsigned i = 0; AC->RequiredLibraries[i]; ++i) {
    VisitComponent(AC->RequiredLibraries[i], ComponentMap, VisitedComponents,
                   RequiredLibs, IncludeNonInstalled);
  }

  // Add to the required library list.
  if (AC->Library)
    RequiredLibs.push_back(AC->Library);
}

/// \brief Compute the list of required libraries for a given list of
/// components, in an order suitable for passing to a linker (that is, libraries
/// appear prior to their dependencies).
///
/// \param Components - The names of the components to find libraries for.
/// \param RequiredLibs [out] - On return, the ordered list of libraries that
/// are required to link the given components.
/// \param IncludeNonInstalled - Whether non-installed components should be
/// reported.
void ComputeLibsForComponents(const std::vector<StringRef> &Components,
                              std::vector<StringRef> &RequiredLibs,
                              bool IncludeNonInstalled) {
  std::set<AvailableComponent*> VisitedComponents;

  // Build a map of component names to information.
  StringMap<AvailableComponent*> ComponentMap;
  for (unsigned i = 0; i != array_lengthof(AvailableComponents); ++i) {
    AvailableComponent *AC = &AvailableComponents[i];
    ComponentMap[AC->Name] = AC;
  }

  // Visit the components.
  for (unsigned i = 0, e = Components.size(); i != e; ++i) {
    // Users are allowed to provide mixed case component names.
    std::string ComponentLower = Components[i].lower();

    // Validate that the user supplied a valid component name.
    if (!ComponentMap.count(ComponentLower)) {
      llvm::errs() << "llvm-config: unknown component name: " << Components[i]
                   << "\n";
      exit(1);
    }

    VisitComponent(ComponentLower, ComponentMap, VisitedComponents,
                   RequiredLibs, IncludeNonInstalled);
  }

  // The list is now ordered with leafs first, we want the libraries to printed
  // in the reverse order of dependency.
  std::reverse(RequiredLibs.begin(), RequiredLibs.end());
}

/* *** */

void usage() {
  errs() << "\
usage: llvm-config <OPTION>... [<COMPONENT>...]\n\
\n\
Get various configuration information needed to compile programs which use\n\
LLVM.  Typically called from 'configure' scripts.  Examples:\n\
  llvm-config --cxxflags\n\
  llvm-config --ldflags\n\
  llvm-config --libs engine bcreader scalaropts\n\
\n\
Options:\n\
  --version         Print LLVM version.\n\
  --prefix          Print the installation prefix.\n\
  --src-root        Print the source root LLVM was built from.\n\
  --obj-root        Print the object root used to build LLVM.\n\
  --bindir          Directory containing LLVM executables.\n\
  --includedir      Directory containing LLVM headers.\n\
  --libdir          Directory containing LLVM libraries.\n\
  --cppflags        C preprocessor flags for files that include LLVM headers.\n\
  --cflags          C compiler flags for files that include LLVM headers.\n\
  --cxxflags        C++ compiler flags for files that include LLVM headers.\n\
  --ldflags         Print Linker flags.\n\
  --system-libs     Sytem Libraries needed to link against LLVM components.\n\
  --libs            Libraries needed to link against LLVM components.\n\
  --libnames        Bare library names for in-tree builds.\n\
  --libfiles        Fully qualified library filenames for makefile depends.\n\
  --components      List of all possible components.\n\
  --targets-built   List of all targets currently built.\n\
  --host-target     Target triple used to configure LLVM.\n\
  --build-mode      Print build mode of LLVM tree (e.g. Debug or Release).\n\
  --assertion-mode  Print assertion mode of LLVM tree (ON or OFF).\n\
Typical components:\n\
  all               All LLVM libraries (default).\n\
  engine            Either a native JIT or a bitcode interpreter.\n";
  exit(1);
}

/// \brief Compute the path to the main executable.
std::string GetExecutablePath(const char *Argv0) {
  // This just needs to be some symbol in the binary; C++ doesn't
  // allow taking the address of ::main however.
  void *P = (void*) (intptr_t) GetExecutablePath;
  return llvm::sys::fs::getMainExecutable(Argv0, P);
}

int main(int argc, char **argv) {
  std::vector<StringRef> Components;
  bool PrintLibs = false, PrintLibNames = false, PrintLibFiles = false;
  bool PrintSystemLibs = false;
  bool HasAnyOption = false;

  // llvm-config is designed to support being run both from a development tree
  // and from an installed path. We try and auto-detect which case we are in so
  // that we can report the correct information when run from a development
  // tree.
  bool IsInDevelopmentTree;
  enum { MakefileStyle, CMakeStyle, CMakeBuildModeStyle } DevelopmentTreeLayout;
  llvm::SmallString<256> CurrentPath(GetExecutablePath(argv[0]));
  std::string CurrentExecPrefix;
  std::string ActiveObjRoot;

  // If CMAKE_CFG_INTDIR is given, honor it as build mode.
  char const *build_mode = LLVM_BUILDMODE;
#if defined(CMAKE_CFG_INTDIR)
  if (!(CMAKE_CFG_INTDIR[0] == '.' && CMAKE_CFG_INTDIR[1] == '\0'))
    build_mode = CMAKE_CFG_INTDIR;
#endif

  // Create an absolute path, and pop up one directory (we expect to be inside a
  // bin dir).
  sys::fs::make_absolute(CurrentPath);
  CurrentExecPrefix = sys::path::parent_path(
    sys::path::parent_path(CurrentPath)).str();

  // Check to see if we are inside a development tree by comparing to possible
  // locations (prefix style or CMake style).
  if (sys::fs::equivalent(CurrentExecPrefix,
                          Twine(LLVM_OBJ_ROOT) + "/" + LLVM_BUILDMODE)) {
    IsInDevelopmentTree = true;
    DevelopmentTreeLayout = MakefileStyle;

    // If we are in a development tree, then check if we are in a BuildTools
    // directory. This indicates we are built for the build triple, but we
    // always want to provide information for the host triple.
    if (sys::path::filename(LLVM_OBJ_ROOT) == "BuildTools") {
      ActiveObjRoot = sys::path::parent_path(LLVM_OBJ_ROOT);
    } else {
      ActiveObjRoot = LLVM_OBJ_ROOT;
    }
  } else if (sys::fs::equivalent(CurrentExecPrefix, LLVM_OBJ_ROOT)) {
    IsInDevelopmentTree = true;
    DevelopmentTreeLayout = CMakeStyle;
    ActiveObjRoot = LLVM_OBJ_ROOT;
  } else if (sys::fs::equivalent(CurrentExecPrefix,
                                 Twine(LLVM_OBJ_ROOT) + "/bin")) {
    IsInDevelopmentTree = true;
    DevelopmentTreeLayout = CMakeBuildModeStyle;
    ActiveObjRoot = LLVM_OBJ_ROOT;
  } else {
    IsInDevelopmentTree = false;
    DevelopmentTreeLayout = MakefileStyle; // Initialized to avoid warnings.
  }

  // Compute various directory locations based on the derived location
  // information.
  std::string ActivePrefix, ActiveBinDir, ActiveIncludeDir, ActiveLibDir;
  std::string ActiveIncludeOption;
  if (IsInDevelopmentTree) {
    ActiveIncludeDir = std::string(LLVM_SRC_ROOT) + "/include";
    ActivePrefix = CurrentExecPrefix;

    // CMake organizes the products differently than a normal prefix style
    // layout.
    switch (DevelopmentTreeLayout) {
    case MakefileStyle:
      ActiveBinDir = ActiveObjRoot + "/" + LLVM_BUILDMODE + "/bin";
      ActiveLibDir = ActiveObjRoot + "/" + LLVM_BUILDMODE + "/lib";
      break;
    case CMakeStyle:
      ActiveBinDir = ActiveObjRoot + "/bin";
      ActiveLibDir = ActiveObjRoot + "/lib";
      break;
    case CMakeBuildModeStyle:
      ActivePrefix = ActiveObjRoot;
      ActiveBinDir = ActiveObjRoot + "/bin/" + build_mode;
      ActiveLibDir = ActiveObjRoot + "/lib/" + build_mode;
      break;
    }

    // We need to include files from both the source and object trees.
    ActiveIncludeOption = ("-I" + ActiveIncludeDir + " " +
                           "-I" + ActiveObjRoot + "/include");
  } else {
    ActivePrefix = CurrentExecPrefix;
    ActiveIncludeDir = ActivePrefix + "/include";
    ActiveBinDir = ActivePrefix + "/bin";
    ActiveLibDir = ActivePrefix + "/lib";
    ActiveIncludeOption = "-I" + ActiveIncludeDir;
  }

  raw_ostream &OS = outs();
  for (int i = 1; i != argc; ++i) {
    StringRef Arg = argv[i];

    if (Arg.startswith("-")) {
      HasAnyOption = true;
      if (Arg == "--version") {
        OS << PACKAGE_VERSION << '\n';
      } else if (Arg == "--prefix") {
        OS << ActivePrefix << '\n';
      } else if (Arg == "--bindir") {
        OS << ActiveBinDir << '\n';
      } else if (Arg == "--includedir") {
        OS << ActiveIncludeDir << '\n';
      } else if (Arg == "--libdir") {
        OS << ActiveLibDir << '\n';
      } else if (Arg == "--cppflags") {
        OS << ActiveIncludeOption << ' ' << LLVM_CPPFLAGS << '\n';
      } else if (Arg == "--cflags") {
        OS << ActiveIncludeOption << ' ' << LLVM_CFLAGS << '\n';
      } else if (Arg == "--cxxflags") {
        OS << ActiveIncludeOption << ' ' << LLVM_CXXFLAGS << '\n';
      } else if (Arg == "--ldflags") {
        OS << "-L" << ActiveLibDir << ' ' << LLVM_LDFLAGS << '\n';
      } else if (Arg == "--system-libs") {
        PrintSystemLibs = true;
      } else if (Arg == "--libs") {
        PrintLibs = true;
      } else if (Arg == "--libnames") {
        PrintLibNames = true;
      } else if (Arg == "--libfiles") {
        PrintLibFiles = true;
      } else if (Arg == "--components") {
        for (unsigned j = 0; j != array_lengthof(AvailableComponents); ++j) {
          // Only include non-installed components when in a development tree.
          if (!AvailableComponents[j].IsInstalled && !IsInDevelopmentTree)
            continue;

          OS << ' ';
          OS << AvailableComponents[j].Name;
        }
        OS << '\n';
      } else if (Arg == "--targets-built") {
        OS << LLVM_TARGETS_BUILT << '\n';
      } else if (Arg == "--host-target") {
        OS << LLVM_DEFAULT_TARGET_TRIPLE << '\n';
      } else if (Arg == "--build-mode") {
        OS << build_mode << '\n';
      } else if (Arg == "--assertion-mode") {
#if defined(NDEBUG)
        OS << "OFF\n";
#else
        OS << "ON\n";
#endif
      } else if (Arg == "--obj-root") {
        OS << LLVM_OBJ_ROOT << '\n';
      } else if (Arg == "--src-root") {
        OS << LLVM_SRC_ROOT << '\n';
      } else {
        usage();
      }
    } else {
      Components.push_back(Arg);
    }
  }

  if (!HasAnyOption)
    usage();

  if (PrintLibs || PrintLibNames || PrintLibFiles || PrintSystemLibs) {
    // If no components were specified, default to "all".
    if (Components.empty())
      Components.push_back("all");

    // Construct the list of all the required libraries.
    std::vector<StringRef> RequiredLibs;
    ComputeLibsForComponents(Components, RequiredLibs,
                             /*IncludeNonInstalled=*/IsInDevelopmentTree);

    for (unsigned i = 0, e = RequiredLibs.size(); i != e; ++i) {
      StringRef Lib = RequiredLibs[i];
      if (i)
        OS << ' ';

      if (PrintLibNames) {
        OS << Lib;
      } else if (PrintLibFiles) {
        OS << ActiveLibDir << '/' << Lib;
      } else if (PrintLibs) {
        // If this is a typical library name, include it using -l.
        if (Lib.startswith("lib") && Lib.endswith(".a")) {
          OS << "-l" << Lib.slice(3, Lib.size()-2);
          continue;
        }

        // Otherwise, print the full path.
        OS << ActiveLibDir << '/' << Lib;
      }
    }
    OS << '\n';

    // Print SYSTEM_LIBS after --libs.
    // FIXME: Each LLVM component may have its dependent system libs.
    if (PrintSystemLibs)
      OS << LLVM_SYSTEM_LIBS << '\n';
  } else if (!Components.empty()) {
    errs() << "llvm-config: error: components given, but unused\n\n";
    usage();
  }

  return 0;
}
<commit_msg>llvm-config: Don't show build tree with --obj-root for installed llvm-config. Show $(prefix) instead.<commit_after>//===-- llvm-config.cpp - LLVM project configuration utility --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tool encapsulates information about an LLVM project configuration for
// use by other project's build environments (to determine installed path,
// available features, required libraries, etc.).
//
// Note that although this tool *may* be used by some parts of LLVM's build
// itself (i.e., the Makefiles use it to compute required libraries when linking
// tools), this tool is primarily designed to support external projects.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
#include <set>
#include <vector>

using namespace llvm;

// Include the build time variables we can report to the user. This is generated
// at build time from the BuildVariables.inc.in file by the build system.
#include "BuildVariables.inc"

// Include the component table. This creates an array of struct
// AvailableComponent entries, which record the component name, library name,
// and required components for all of the available libraries.
//
// Not all components define a library, we also use "library groups" as a way to
// create entries for pseudo groups like x86 or all-targets.
#include "LibraryDependencies.inc"

/// \brief Traverse a single component adding to the topological ordering in
/// \arg RequiredLibs.
///
/// \param Name - The component to traverse.
/// \param ComponentMap - A prebuilt map of component names to descriptors.
/// \param VisitedComponents [in] [out] - The set of already visited components.
/// \param RequiredLibs [out] - The ordered list of required libraries.
static void VisitComponent(StringRef Name,
                           const StringMap<AvailableComponent*> &ComponentMap,
                           std::set<AvailableComponent*> &VisitedComponents,
                           std::vector<StringRef> &RequiredLibs,
                           bool IncludeNonInstalled) {
  // Lookup the component.
  AvailableComponent *AC = ComponentMap.lookup(Name);
  assert(AC && "Invalid component name!");

  // Add to the visited table.
  if (!VisitedComponents.insert(AC).second) {
    // We are done if the component has already been visited.
    return;
  }

  // Only include non-installed components if requested.
  if (!AC->IsInstalled && !IncludeNonInstalled)
    return;

  // Otherwise, visit all the dependencies.
  for (unsigned i = 0; AC->RequiredLibraries[i]; ++i) {
    VisitComponent(AC->RequiredLibraries[i], ComponentMap, VisitedComponents,
                   RequiredLibs, IncludeNonInstalled);
  }

  // Add to the required library list.
  if (AC->Library)
    RequiredLibs.push_back(AC->Library);
}

/// \brief Compute the list of required libraries for a given list of
/// components, in an order suitable for passing to a linker (that is, libraries
/// appear prior to their dependencies).
///
/// \param Components - The names of the components to find libraries for.
/// \param RequiredLibs [out] - On return, the ordered list of libraries that
/// are required to link the given components.
/// \param IncludeNonInstalled - Whether non-installed components should be
/// reported.
void ComputeLibsForComponents(const std::vector<StringRef> &Components,
                              std::vector<StringRef> &RequiredLibs,
                              bool IncludeNonInstalled) {
  std::set<AvailableComponent*> VisitedComponents;

  // Build a map of component names to information.
  StringMap<AvailableComponent*> ComponentMap;
  for (unsigned i = 0; i != array_lengthof(AvailableComponents); ++i) {
    AvailableComponent *AC = &AvailableComponents[i];
    ComponentMap[AC->Name] = AC;
  }

  // Visit the components.
  for (unsigned i = 0, e = Components.size(); i != e; ++i) {
    // Users are allowed to provide mixed case component names.
    std::string ComponentLower = Components[i].lower();

    // Validate that the user supplied a valid component name.
    if (!ComponentMap.count(ComponentLower)) {
      llvm::errs() << "llvm-config: unknown component name: " << Components[i]
                   << "\n";
      exit(1);
    }

    VisitComponent(ComponentLower, ComponentMap, VisitedComponents,
                   RequiredLibs, IncludeNonInstalled);
  }

  // The list is now ordered with leafs first, we want the libraries to printed
  // in the reverse order of dependency.
  std::reverse(RequiredLibs.begin(), RequiredLibs.end());
}

/* *** */

void usage() {
  errs() << "\
usage: llvm-config <OPTION>... [<COMPONENT>...]\n\
\n\
Get various configuration information needed to compile programs which use\n\
LLVM.  Typically called from 'configure' scripts.  Examples:\n\
  llvm-config --cxxflags\n\
  llvm-config --ldflags\n\
  llvm-config --libs engine bcreader scalaropts\n\
\n\
Options:\n\
  --version         Print LLVM version.\n\
  --prefix          Print the installation prefix.\n\
  --src-root        Print the source root LLVM was built from.\n\
  --obj-root        Print the object root used to build LLVM.\n\
  --bindir          Directory containing LLVM executables.\n\
  --includedir      Directory containing LLVM headers.\n\
  --libdir          Directory containing LLVM libraries.\n\
  --cppflags        C preprocessor flags for files that include LLVM headers.\n\
  --cflags          C compiler flags for files that include LLVM headers.\n\
  --cxxflags        C++ compiler flags for files that include LLVM headers.\n\
  --ldflags         Print Linker flags.\n\
  --system-libs     Sytem Libraries needed to link against LLVM components.\n\
  --libs            Libraries needed to link against LLVM components.\n\
  --libnames        Bare library names for in-tree builds.\n\
  --libfiles        Fully qualified library filenames for makefile depends.\n\
  --components      List of all possible components.\n\
  --targets-built   List of all targets currently built.\n\
  --host-target     Target triple used to configure LLVM.\n\
  --build-mode      Print build mode of LLVM tree (e.g. Debug or Release).\n\
  --assertion-mode  Print assertion mode of LLVM tree (ON or OFF).\n\
Typical components:\n\
  all               All LLVM libraries (default).\n\
  engine            Either a native JIT or a bitcode interpreter.\n";
  exit(1);
}

/// \brief Compute the path to the main executable.
std::string GetExecutablePath(const char *Argv0) {
  // This just needs to be some symbol in the binary; C++ doesn't
  // allow taking the address of ::main however.
  void *P = (void*) (intptr_t) GetExecutablePath;
  return llvm::sys::fs::getMainExecutable(Argv0, P);
}

int main(int argc, char **argv) {
  std::vector<StringRef> Components;
  bool PrintLibs = false, PrintLibNames = false, PrintLibFiles = false;
  bool PrintSystemLibs = false;
  bool HasAnyOption = false;

  // llvm-config is designed to support being run both from a development tree
  // and from an installed path. We try and auto-detect which case we are in so
  // that we can report the correct information when run from a development
  // tree.
  bool IsInDevelopmentTree;
  enum { MakefileStyle, CMakeStyle, CMakeBuildModeStyle } DevelopmentTreeLayout;
  llvm::SmallString<256> CurrentPath(GetExecutablePath(argv[0]));
  std::string CurrentExecPrefix;
  std::string ActiveObjRoot;

  // If CMAKE_CFG_INTDIR is given, honor it as build mode.
  char const *build_mode = LLVM_BUILDMODE;
#if defined(CMAKE_CFG_INTDIR)
  if (!(CMAKE_CFG_INTDIR[0] == '.' && CMAKE_CFG_INTDIR[1] == '\0'))
    build_mode = CMAKE_CFG_INTDIR;
#endif

  // Create an absolute path, and pop up one directory (we expect to be inside a
  // bin dir).
  sys::fs::make_absolute(CurrentPath);
  CurrentExecPrefix = sys::path::parent_path(
    sys::path::parent_path(CurrentPath)).str();

  // Check to see if we are inside a development tree by comparing to possible
  // locations (prefix style or CMake style).
  if (sys::fs::equivalent(CurrentExecPrefix,
                          Twine(LLVM_OBJ_ROOT) + "/" + LLVM_BUILDMODE)) {
    IsInDevelopmentTree = true;
    DevelopmentTreeLayout = MakefileStyle;

    // If we are in a development tree, then check if we are in a BuildTools
    // directory. This indicates we are built for the build triple, but we
    // always want to provide information for the host triple.
    if (sys::path::filename(LLVM_OBJ_ROOT) == "BuildTools") {
      ActiveObjRoot = sys::path::parent_path(LLVM_OBJ_ROOT);
    } else {
      ActiveObjRoot = LLVM_OBJ_ROOT;
    }
  } else if (sys::fs::equivalent(CurrentExecPrefix, LLVM_OBJ_ROOT)) {
    IsInDevelopmentTree = true;
    DevelopmentTreeLayout = CMakeStyle;
    ActiveObjRoot = LLVM_OBJ_ROOT;
  } else if (sys::fs::equivalent(CurrentExecPrefix,
                                 Twine(LLVM_OBJ_ROOT) + "/bin")) {
    IsInDevelopmentTree = true;
    DevelopmentTreeLayout = CMakeBuildModeStyle;
    ActiveObjRoot = LLVM_OBJ_ROOT;
  } else {
    IsInDevelopmentTree = false;
    DevelopmentTreeLayout = MakefileStyle; // Initialized to avoid warnings.
  }

  // Compute various directory locations based on the derived location
  // information.
  std::string ActivePrefix, ActiveBinDir, ActiveIncludeDir, ActiveLibDir;
  std::string ActiveIncludeOption;
  if (IsInDevelopmentTree) {
    ActiveIncludeDir = std::string(LLVM_SRC_ROOT) + "/include";
    ActivePrefix = CurrentExecPrefix;

    // CMake organizes the products differently than a normal prefix style
    // layout.
    switch (DevelopmentTreeLayout) {
    case MakefileStyle:
      ActiveBinDir = ActiveObjRoot + "/" + LLVM_BUILDMODE + "/bin";
      ActiveLibDir = ActiveObjRoot + "/" + LLVM_BUILDMODE + "/lib";
      break;
    case CMakeStyle:
      ActiveBinDir = ActiveObjRoot + "/bin";
      ActiveLibDir = ActiveObjRoot + "/lib";
      break;
    case CMakeBuildModeStyle:
      ActivePrefix = ActiveObjRoot;
      ActiveBinDir = ActiveObjRoot + "/bin/" + build_mode;
      ActiveLibDir = ActiveObjRoot + "/lib/" + build_mode;
      break;
    }

    // We need to include files from both the source and object trees.
    ActiveIncludeOption = ("-I" + ActiveIncludeDir + " " +
                           "-I" + ActiveObjRoot + "/include");
  } else {
    ActivePrefix = CurrentExecPrefix;
    ActiveIncludeDir = ActivePrefix + "/include";
    ActiveBinDir = ActivePrefix + "/bin";
    ActiveLibDir = ActivePrefix + "/lib";
    ActiveIncludeOption = "-I" + ActiveIncludeDir;
  }

  raw_ostream &OS = outs();
  for (int i = 1; i != argc; ++i) {
    StringRef Arg = argv[i];

    if (Arg.startswith("-")) {
      HasAnyOption = true;
      if (Arg == "--version") {
        OS << PACKAGE_VERSION << '\n';
      } else if (Arg == "--prefix") {
        OS << ActivePrefix << '\n';
      } else if (Arg == "--bindir") {
        OS << ActiveBinDir << '\n';
      } else if (Arg == "--includedir") {
        OS << ActiveIncludeDir << '\n';
      } else if (Arg == "--libdir") {
        OS << ActiveLibDir << '\n';
      } else if (Arg == "--cppflags") {
        OS << ActiveIncludeOption << ' ' << LLVM_CPPFLAGS << '\n';
      } else if (Arg == "--cflags") {
        OS << ActiveIncludeOption << ' ' << LLVM_CFLAGS << '\n';
      } else if (Arg == "--cxxflags") {
        OS << ActiveIncludeOption << ' ' << LLVM_CXXFLAGS << '\n';
      } else if (Arg == "--ldflags") {
        OS << "-L" << ActiveLibDir << ' ' << LLVM_LDFLAGS << '\n';
      } else if (Arg == "--system-libs") {
        PrintSystemLibs = true;
      } else if (Arg == "--libs") {
        PrintLibs = true;
      } else if (Arg == "--libnames") {
        PrintLibNames = true;
      } else if (Arg == "--libfiles") {
        PrintLibFiles = true;
      } else if (Arg == "--components") {
        for (unsigned j = 0; j != array_lengthof(AvailableComponents); ++j) {
          // Only include non-installed components when in a development tree.
          if (!AvailableComponents[j].IsInstalled && !IsInDevelopmentTree)
            continue;

          OS << ' ';
          OS << AvailableComponents[j].Name;
        }
        OS << '\n';
      } else if (Arg == "--targets-built") {
        OS << LLVM_TARGETS_BUILT << '\n';
      } else if (Arg == "--host-target") {
        OS << LLVM_DEFAULT_TARGET_TRIPLE << '\n';
      } else if (Arg == "--build-mode") {
        OS << build_mode << '\n';
      } else if (Arg == "--assertion-mode") {
#if defined(NDEBUG)
        OS << "OFF\n";
#else
        OS << "ON\n";
#endif
      } else if (Arg == "--obj-root") {
        OS << ActivePrefix << '\n';
      } else if (Arg == "--src-root") {
        OS << LLVM_SRC_ROOT << '\n';
      } else {
        usage();
      }
    } else {
      Components.push_back(Arg);
    }
  }

  if (!HasAnyOption)
    usage();

  if (PrintLibs || PrintLibNames || PrintLibFiles || PrintSystemLibs) {
    // If no components were specified, default to "all".
    if (Components.empty())
      Components.push_back("all");

    // Construct the list of all the required libraries.
    std::vector<StringRef> RequiredLibs;
    ComputeLibsForComponents(Components, RequiredLibs,
                             /*IncludeNonInstalled=*/IsInDevelopmentTree);

    for (unsigned i = 0, e = RequiredLibs.size(); i != e; ++i) {
      StringRef Lib = RequiredLibs[i];
      if (i)
        OS << ' ';

      if (PrintLibNames) {
        OS << Lib;
      } else if (PrintLibFiles) {
        OS << ActiveLibDir << '/' << Lib;
      } else if (PrintLibs) {
        // If this is a typical library name, include it using -l.
        if (Lib.startswith("lib") && Lib.endswith(".a")) {
          OS << "-l" << Lib.slice(3, Lib.size()-2);
          continue;
        }

        // Otherwise, print the full path.
        OS << ActiveLibDir << '/' << Lib;
      }
    }
    OS << '\n';

    // Print SYSTEM_LIBS after --libs.
    // FIXME: Each LLVM component may have its dependent system libs.
    if (PrintSystemLibs)
      OS << LLVM_SYSTEM_LIBS << '\n';
  } else if (!Components.empty()) {
    errs() << "llvm-config: error: components given, but unused\n\n";
    usage();
  }

  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: mempool.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2006-05-02 11:58:34 $
 *
 *  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 "mempool.hxx"

#ifndef _RTL_ALLOC_H_
#include "rtl/alloc.h"
#endif

#ifndef INCLUDED_STDIO_H
#include <stdio.h>
#endif

/*************************************************************************
|*
|*    FixedMemPool::FixedMemPool()
|*
*************************************************************************/

FixedMemPool::FixedMemPool (
    USHORT _nTypeSize, USHORT, USHORT)
{
    char name[RTL_CACHE_NAME_LENGTH + 1];
    snprintf (name, sizeof(name), "FixedMemPool_%d", (int)_nTypeSize);
    m_pImpl = (FixedMemPool_Impl*)rtl_cache_create (name, _nTypeSize, 0, NULL, NULL, NULL, 0, NULL, 0);
}

/*************************************************************************
|*
|*    FixedMemPool::~FixedMemPool()
|*
*************************************************************************/

FixedMemPool::~FixedMemPool()
{
    rtl_cache_destroy ((rtl_cache_type*)(m_pImpl));
}

/*************************************************************************
|*
|*    FixedMemPool::Alloc()
|*
*************************************************************************/

void* FixedMemPool::Alloc()
{
    return rtl_cache_alloc ((rtl_cache_type*)(m_pImpl));
}

/*************************************************************************
|*
|*    FixedMemPool::Free()
|*
*************************************************************************/

void FixedMemPool::Free( void* pFree )
{
    rtl_cache_free ((rtl_cache_type*)(m_pImpl), pFree);
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.6.58); FILE MERGED 2006/09/01 17:54:54 kaib 1.6.58.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: mempool.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 00:58:37 $
 *
 *  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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_tools.hxx"

#include "mempool.hxx"

#ifndef _RTL_ALLOC_H_
#include "rtl/alloc.h"
#endif

#ifndef INCLUDED_STDIO_H
#include <stdio.h>
#endif

/*************************************************************************
|*
|*    FixedMemPool::FixedMemPool()
|*
*************************************************************************/

FixedMemPool::FixedMemPool (
    USHORT _nTypeSize, USHORT, USHORT)
{
    char name[RTL_CACHE_NAME_LENGTH + 1];
    snprintf (name, sizeof(name), "FixedMemPool_%d", (int)_nTypeSize);
    m_pImpl = (FixedMemPool_Impl*)rtl_cache_create (name, _nTypeSize, 0, NULL, NULL, NULL, 0, NULL, 0);
}

/*************************************************************************
|*
|*    FixedMemPool::~FixedMemPool()
|*
*************************************************************************/

FixedMemPool::~FixedMemPool()
{
    rtl_cache_destroy ((rtl_cache_type*)(m_pImpl));
}

/*************************************************************************
|*
|*    FixedMemPool::Alloc()
|*
*************************************************************************/

void* FixedMemPool::Alloc()
{
    return rtl_cache_alloc ((rtl_cache_type*)(m_pImpl));
}

/*************************************************************************
|*
|*    FixedMemPool::Free()
|*
*************************************************************************/

void FixedMemPool::Free( void* pFree )
{
    rtl_cache_free ((rtl_cache_type*)(m_pImpl), pFree);
}
<|endoftext|>


<commit_before>// 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 "tink/config/tink_fips.h"

namespace crypto {
namespace tink {

#ifdef TINK_USE_ONLY_FIPS
const bool kUseOnlyFips = true;
#else
const bool kUseOnlyFips = false;
#endif

crypto::tink::util::Status ChecksFipsCompatibility(
    FipsCompatibility fips_status) {
  switch (fips_status) {
    case FipsCompatibility::kNotFips:
      if (kUseOnlyFips) {
        return util::Status(util::error::INTERNAL,
                            "Primitive not available in FIPS only mode");
      } else {
        return util::OkStatus();
      }
    case FipsCompatibility::kRequiresBoringCrypto:
      if (kUseOnlyFips && !FIPS_mode()) {
        return util::Status(
            util::error::INTERNAL,
            "BoringSSL not built with the BoringCrypto module. If you want to "
            "use "
            "FIPS only mode you have to build BoringSSL in FIPS Mode.");

      } else {
        return util::OkStatus();
      }
  }
}

}  // namespace tink
}  // namespace crypto
<commit_msg>Return error if FIPS status is in undefined state.<commit_after>// 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 "tink/config/tink_fips.h"

namespace crypto {
namespace tink {

#ifdef TINK_USE_ONLY_FIPS
const bool kUseOnlyFips = true;
#else
const bool kUseOnlyFips = false;
#endif

crypto::tink::util::Status ChecksFipsCompatibility(
    FipsCompatibility fips_status) {
  switch (fips_status) {
    case FipsCompatibility::kNotFips:
      if (kUseOnlyFips) {
        return util::Status(util::error::INTERNAL,
                            "Primitive not available in FIPS only mode.");
      } else {
        return util::OkStatus();
      }
    case FipsCompatibility::kRequiresBoringCrypto:
      if (kUseOnlyFips && !FIPS_mode()) {
        return util::Status(
            util::error::INTERNAL,
            "BoringSSL not built with the BoringCrypto module. If you want to "
            "use "
            "FIPS only mode you have to build BoringSSL in FIPS Mode.");

      } else {
        return util::OkStatus();
      }
    default:
      util::Status(util::error::INTERNAL,
                   "Could not determine FIPS status.");
  }
}

}  // namespace tink
}  // namespace crypto
<|endoftext|>


<commit_before>#include <common/buffer.h>
#include <common/endian.h>

#include <xcodec/xcbackref.h>
#include <xcodec/xcdb.h>
#include <xcodec/xchash.h>
#include <xcodec/xcodec.h>
#include <xcodec/xcodec_encoder.h>

struct xcodec_special_p {
	bool operator() (uint8_t ch) const
	{
		return (XCODEC_CHAR_SPECIAL(ch));
	}
};

XCodecEncoder::Data::Data(void)
: prefix_(),
  hash_(),
  seg_(NULL)
{ }

XCodecEncoder::Data::Data(const XCodecEncoder::Data& src)
: prefix_(src.prefix_),
  hash_(src.hash_),
  seg_(NULL)
{
	if (src.seg_ != NULL) {
		src.seg_->ref();
		seg_ = src.seg_;
	}
}

XCodecEncoder::Data::~Data()
{
	if (seg_ != NULL) {
		seg_->unref();
		seg_ = NULL;
	}
}

XCodecEncoder::XCodecEncoder(XCodec *codec)
: log_("/xcodec/encoder"),
  database_(codec->database_),
  backref_()
{ }

XCodecEncoder::~XCodecEncoder()
{ }

/*
 * This takes a view of a data stream and turns it into a series of references
 * to other data, declarations of data to be referenced, and data that needs
 * escaped.
 *
 * It's very simple and aggressive and performs worse than the original encoder
 * as a result.  The old encoder did a few important things differently.  First,
 * it would start declaring data as soon as we knew we hadn't found a hash for a
 * given chunk of data.  What I mean is that it would look at a segment and a
 * segment but one worth of data until it found either a match or something that
 * didn't collide, and then it would use that.
 *
 * Secondly, as a result of that, it didn't need to do two database lookups, and
 * those things get expensive.
 *
 * However, we have a few places where we can do better.  First, we can emulate
 * the aggressive declaration (which is better for data and for speed) by
 * looking at the first ohit and seeing when we're a segment length away from
 * it, and then scanning it then and there to find something we can use.  Then
 * we can just put it into the offset_seg_map and we can avoid using the
 * hash_map later on.
 *
 * Probably a lot of other things.
 */
void
XCodecEncoder::encode(Buffer *output, Buffer *input)
{
	if (input->length() < XCODEC_SEGMENT_LENGTH) {
		output->append(input);
		input->clear();
		return;
	}

	XCHash<XCODEC_SEGMENT_LENGTH> xcodec_hash;
	std::deque<std::pair<unsigned, uint64_t> > offset_hash_map;
	std::deque<std::pair<unsigned, BufferSegment *> > offset_seg_map;
	Buffer outq;
	unsigned o = 0;
	unsigned base = 0;

	while (!input->empty()) {
		BufferSegment *seg;
		input->moveout(&seg);

		outq.append(seg);

		const uint8_t *p;
		for (p = seg->data(); p < seg->end(); p++) {
			if (++o < base)
				continue;

			xcodec_hash.roll(*p);

			if (o - base < XCODEC_SEGMENT_LENGTH)
				continue;

			unsigned start = o - XCODEC_SEGMENT_LENGTH;
			uint64_t hash = xcodec_hash.mix();

			BufferSegment *oseg;
			oseg = database_->lookup(hash);
			if (oseg != NULL) {
				/*
				 * This segment already exists.  If it's
				 * identical to this chunk of data, then that's
				 * positively fantastic.
				 */
				uint8_t data[XCODEC_SEGMENT_LENGTH];
				outq.copyout(data, start, sizeof data);

				if (!oseg->match(data, sizeof data)) {
					DEBUG(log_) << "Collision in first pass.";
					continue;
				}

				/*
				 * The segment was identical, we can use it.
				 * We're giving our reference to the offset-seg
				 * map.
				 */
				std::pair<unsigned, BufferSegment *> osp;
				osp.first = start;
				osp.second = oseg;
				offset_seg_map.push_back(osp);

				/* Do not hash any data until after us.  */
				base = o;
			}

			/*
			 * No collision, remember this for later.
			 */
			std::pair<unsigned, uint64_t> ohp;
			ohp.first = start;
			ohp.second = hash;
			offset_hash_map.push_back(ohp);
		}
		seg->unref();
	}

	/*
	 * Now compile the offset-hash map into child data.
	 */

	std::deque<std::pair<unsigned, uint64_t> >::iterator ohit;
	BufferSegment *seg;
	unsigned soff = 0;
	while ((ohit = offset_hash_map.begin()) != offset_hash_map.end()) {
		unsigned start = ohit->first;
		uint64_t hash = ohit->second;
		unsigned end = start + XCODEC_SEGMENT_LENGTH;

		/*
		 * We only get one bite at the apple.
		 */
		offset_hash_map.erase(ohit);

		std::deque<std::pair<unsigned, BufferSegment *> >::iterator osit = offset_seg_map.begin();
		Data slice;

		/*
		 * If this offset-hash corresponds to this offset-segment, use
		 * it!
		 */
		if (osit != offset_seg_map.end()) {
			if (start == osit->first) {
				slice.hash_ = hash;
				/* The slice holds our reference.  */
				slice.seg_ = osit->second;

				/*
				 * Dispose of this entry.
				 */
				offset_seg_map.erase(osit);
			} else if (start < osit->first && end > osit->first) {
				/*
				 * This hash would overlap with a
				 * offset-segment.  Skip it.
				 */
				continue;
			} else {
				/*
				 * There is an offset-segment in our distant
				 * future, we can try this hash for now.
				 */
			}
		} else {
			/*
			 * There is no offset-segment after this, so we can just
			 * use this hash gleefully.
			 */
		}

		/*
		 * We have not yet set a seg_ in this Data, so it's time for us
		 * to declare this segment.
		 */
		if (slice.seg_ == NULL) {
			uint8_t data[XCODEC_SEGMENT_LENGTH];
			outq.copyout(data, start - soff, sizeof data);

			/*
			 * We can't assume that this isn't in the database.
			 * Since we're declaring things all the time in this
			 * stream, we may have introduced hits and collisions.
			 * So we, sadly, have to go back to the well.
			 */
			seg = database_->lookup(hash);
			if (seg != NULL) {
				if (!seg->match(data, sizeof data)) {
					seg->unref();
					DEBUG(log_) << "Collision in second pass.";
					continue;
				}

				/*
				 * A hit!  Well, that's fantastic.
				 */
				slice.hash_ = hash;
				/* The slice holds our reference.  */
				slice.seg_ = seg;
			} else {
				/*
				 * No hit is fantastic, too -- go ahead and
				 * declare this hash.
				 */
				seg = new BufferSegment();
				seg->append(data, sizeof data);

				database_->enter(hash, seg);

				slice.hash_ = hash;
				/* The slice holds our reference.  */
				slice.seg_ = seg;

				output->append(XCODEC_DECLARE_CHAR);
				uint64_t lehash = LittleEndian::encode(slice.hash_);
				output->append((const uint8_t *)&lehash, sizeof lehash);
				output->append(slice.seg_);

				backref_.declare(slice.hash_, slice.seg_);
			}

			/*
			 * Skip any successive overlapping hashes.
			 */
			while ((ohit = offset_hash_map.begin()) != offset_hash_map.end()) {
				if (ohit->first >= end)
					break;
				offset_hash_map.erase(ohit);
			}
		} else {
			/*
			 * There should not be any successive overlapping hashes
			 * if we found a hit in the first pass.  XXX We should
			 * ASSERT that this looks like we'd expect.
			 */
		}

		ASSERT(slice.seg_ != NULL);

		/*
		 * Copy out any prefixing data.
		 */
		if (soff != start) {
			outq.moveout(&slice.prefix_, 0, start - soff);
			soff = start;

			slice.prefix_.escape(XCODEC_ESCAPE_CHAR, xcodec_special_p());
			output->append(slice.prefix_);
			slice.prefix_.clear();
		}

		/*
		 * And skip this segment.
		 */
		outq.skip(XCODEC_SEGMENT_LENGTH);
		soff = end;

		/*
		 * And output a reference.
		 */
		uint8_t b;
		if (backref_.present(slice.hash_, &b)) {
			output->append(XCODEC_BACKREF_CHAR);
			output->append(b);
		} else {
			output->append(XCODEC_HASHREF_CHAR);
			uint64_t lehash = LittleEndian::encode(slice.hash_);
			output->append((const uint8_t *)&lehash, sizeof lehash);

			backref_.declare(slice.hash_, slice.seg_);
		}
	}

	/*
	 * The segment map should be empty, too.  It should only have entries
	 * that correspond to offset-hash entries.
	 */
	ASSERT(offset_seg_map.empty());

	if (!outq.empty()) {
		Buffer suffix(outq);
		outq.clear();

		suffix.escape(XCODEC_ESCAPE_CHAR, xcodec_special_p());

		output->append(suffix);
		outq.clear();
	}

	ASSERT(outq.empty());
	ASSERT(input->empty());
}
<commit_msg>Correctly escape short data.<commit_after>#include <common/buffer.h>
#include <common/endian.h>

#include <xcodec/xcbackref.h>
#include <xcodec/xcdb.h>
#include <xcodec/xchash.h>
#include <xcodec/xcodec.h>
#include <xcodec/xcodec_encoder.h>

struct xcodec_special_p {
	bool operator() (uint8_t ch) const
	{
		return (XCODEC_CHAR_SPECIAL(ch));
	}
};

XCodecEncoder::Data::Data(void)
: prefix_(),
  hash_(),
  seg_(NULL)
{ }

XCodecEncoder::Data::Data(const XCodecEncoder::Data& src)
: prefix_(src.prefix_),
  hash_(src.hash_),
  seg_(NULL)
{
	if (src.seg_ != NULL) {
		src.seg_->ref();
		seg_ = src.seg_;
	}
}

XCodecEncoder::Data::~Data()
{
	if (seg_ != NULL) {
		seg_->unref();
		seg_ = NULL;
	}
}

XCodecEncoder::XCodecEncoder(XCodec *codec)
: log_("/xcodec/encoder"),
  database_(codec->database_),
  backref_()
{ }

XCodecEncoder::~XCodecEncoder()
{ }

/*
 * This takes a view of a data stream and turns it into a series of references
 * to other data, declarations of data to be referenced, and data that needs
 * escaped.
 *
 * It's very simple and aggressive and performs worse than the original encoder
 * as a result.  The old encoder did a few important things differently.  First,
 * it would start declaring data as soon as we knew we hadn't found a hash for a
 * given chunk of data.  What I mean is that it would look at a segment and a
 * segment but one worth of data until it found either a match or something that
 * didn't collide, and then it would use that.
 *
 * Secondly, as a result of that, it didn't need to do two database lookups, and
 * those things get expensive.
 *
 * However, we have a few places where we can do better.  First, we can emulate
 * the aggressive declaration (which is better for data and for speed) by
 * looking at the first ohit and seeing when we're a segment length away from
 * it, and then scanning it then and there to find something we can use.  Then
 * we can just put it into the offset_seg_map and we can avoid using the
 * hash_map later on.
 *
 * Probably a lot of other things.
 */
void
XCodecEncoder::encode(Buffer *output, Buffer *input)
{
	if (input->length() < XCODEC_SEGMENT_LENGTH) {
		input->escape(XCODEC_ESCAPE_CHAR, xcodec_special_p());
		output->append(input);
		input->clear();
		return;
	}

	XCHash<XCODEC_SEGMENT_LENGTH> xcodec_hash;
	std::deque<std::pair<unsigned, uint64_t> > offset_hash_map;
	std::deque<std::pair<unsigned, BufferSegment *> > offset_seg_map;
	Buffer outq;
	unsigned o = 0;
	unsigned base = 0;

	while (!input->empty()) {
		BufferSegment *seg;
		input->moveout(&seg);

		outq.append(seg);

		const uint8_t *p;
		for (p = seg->data(); p < seg->end(); p++) {
			if (++o < base)
				continue;

			xcodec_hash.roll(*p);

			if (o - base < XCODEC_SEGMENT_LENGTH)
				continue;

			unsigned start = o - XCODEC_SEGMENT_LENGTH;
			uint64_t hash = xcodec_hash.mix();

			BufferSegment *oseg;
			oseg = database_->lookup(hash);
			if (oseg != NULL) {
				/*
				 * This segment already exists.  If it's
				 * identical to this chunk of data, then that's
				 * positively fantastic.
				 */
				uint8_t data[XCODEC_SEGMENT_LENGTH];
				outq.copyout(data, start, sizeof data);

				if (!oseg->match(data, sizeof data)) {
					DEBUG(log_) << "Collision in first pass.";
					continue;
				}

				/*
				 * The segment was identical, we can use it.
				 * We're giving our reference to the offset-seg
				 * map.
				 */
				std::pair<unsigned, BufferSegment *> osp;
				osp.first = start;
				osp.second = oseg;
				offset_seg_map.push_back(osp);

				/* Do not hash any data until after us.  */
				base = o;
			}

			/*
			 * No collision, remember this for later.
			 */
			std::pair<unsigned, uint64_t> ohp;
			ohp.first = start;
			ohp.second = hash;
			offset_hash_map.push_back(ohp);
		}
		seg->unref();
	}

	/*
	 * Now compile the offset-hash map into child data.
	 */

	std::deque<std::pair<unsigned, uint64_t> >::iterator ohit;
	BufferSegment *seg;
	unsigned soff = 0;
	while ((ohit = offset_hash_map.begin()) != offset_hash_map.end()) {
		unsigned start = ohit->first;
		uint64_t hash = ohit->second;
		unsigned end = start + XCODEC_SEGMENT_LENGTH;

		/*
		 * We only get one bite at the apple.
		 */
		offset_hash_map.erase(ohit);

		std::deque<std::pair<unsigned, BufferSegment *> >::iterator osit = offset_seg_map.begin();
		Data slice;

		/*
		 * If this offset-hash corresponds to this offset-segment, use
		 * it!
		 */
		if (osit != offset_seg_map.end()) {
			if (start == osit->first) {
				slice.hash_ = hash;
				/* The slice holds our reference.  */
				slice.seg_ = osit->second;

				/*
				 * Dispose of this entry.
				 */
				offset_seg_map.erase(osit);
			} else if (start < osit->first && end > osit->first) {
				/*
				 * This hash would overlap with a
				 * offset-segment.  Skip it.
				 */
				continue;
			} else {
				/*
				 * There is an offset-segment in our distant
				 * future, we can try this hash for now.
				 */
			}
		} else {
			/*
			 * There is no offset-segment after this, so we can just
			 * use this hash gleefully.
			 */
		}

		/*
		 * We have not yet set a seg_ in this Data, so it's time for us
		 * to declare this segment.
		 */
		if (slice.seg_ == NULL) {
			uint8_t data[XCODEC_SEGMENT_LENGTH];
			outq.copyout(data, start - soff, sizeof data);

			/*
			 * We can't assume that this isn't in the database.
			 * Since we're declaring things all the time in this
			 * stream, we may have introduced hits and collisions.
			 * So we, sadly, have to go back to the well.
			 */
			seg = database_->lookup(hash);
			if (seg != NULL) {
				if (!seg->match(data, sizeof data)) {
					seg->unref();
					DEBUG(log_) << "Collision in second pass.";
					continue;
				}

				/*
				 * A hit!  Well, that's fantastic.
				 */
				slice.hash_ = hash;
				/* The slice holds our reference.  */
				slice.seg_ = seg;
			} else {
				/*
				 * No hit is fantastic, too -- go ahead and
				 * declare this hash.
				 */
				seg = new BufferSegment();
				seg->append(data, sizeof data);

				database_->enter(hash, seg);

				slice.hash_ = hash;
				/* The slice holds our reference.  */
				slice.seg_ = seg;

				output->append(XCODEC_DECLARE_CHAR);
				uint64_t lehash = LittleEndian::encode(slice.hash_);
				output->append((const uint8_t *)&lehash, sizeof lehash);
				output->append(slice.seg_);

				backref_.declare(slice.hash_, slice.seg_);
			}

			/*
			 * Skip any successive overlapping hashes.
			 */
			while ((ohit = offset_hash_map.begin()) != offset_hash_map.end()) {
				if (ohit->first >= end)
					break;
				offset_hash_map.erase(ohit);
			}
		} else {
			/*
			 * There should not be any successive overlapping hashes
			 * if we found a hit in the first pass.  XXX We should
			 * ASSERT that this looks like we'd expect.
			 */
		}

		ASSERT(slice.seg_ != NULL);

		/*
		 * Copy out any prefixing data.
		 */
		if (soff != start) {
			outq.moveout(&slice.prefix_, 0, start - soff);
			soff = start;

			slice.prefix_.escape(XCODEC_ESCAPE_CHAR, xcodec_special_p());
			output->append(slice.prefix_);
			slice.prefix_.clear();
		}

		/*
		 * And skip this segment.
		 */
		outq.skip(XCODEC_SEGMENT_LENGTH);
		soff = end;

		/*
		 * And output a reference.
		 */
		uint8_t b;
		if (backref_.present(slice.hash_, &b)) {
			output->append(XCODEC_BACKREF_CHAR);
			output->append(b);
		} else {
			output->append(XCODEC_HASHREF_CHAR);
			uint64_t lehash = LittleEndian::encode(slice.hash_);
			output->append((const uint8_t *)&lehash, sizeof lehash);

			backref_.declare(slice.hash_, slice.seg_);
		}
	}

	/*
	 * The segment map should be empty, too.  It should only have entries
	 * that correspond to offset-hash entries.
	 */
	ASSERT(offset_seg_map.empty());

	if (!outq.empty()) {
		Buffer suffix(outq);
		outq.clear();

		suffix.escape(XCODEC_ESCAPE_CHAR, xcodec_special_p());

		output->append(suffix);
		outq.clear();
	}

	ASSERT(outq.empty());
	ASSERT(input->empty());
}
<|endoftext|>