<commit_before>#include "./i_ast_node.h"
#include <v8.h>
#include <node_object_wrap.h>
#include <tree_sitter/runtime.h>
#include "./ast_node.h"
#include "./ast_node_array.h"

namespace node_tree_sitter {

using namespace v8;

void IASTNode::SetUp(Local<FunctionTemplate> tpl) {
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  // Properties
  tpl->InstanceTemplate()->SetAccessor(
      NanNew<String>("children"),
      Children);
  tpl->InstanceTemplate()->SetAccessor(
      NanNew<String>("position"),
      Position);
  tpl->InstanceTemplate()->SetAccessor(
      NanNew<String>("size"),
      Size);
  tpl->InstanceTemplate()->SetAccessor(
      NanNew<String>("name"),
      Name);

  // Prototype
  tpl->PrototypeTemplate()->Set(
      NanNew<String>("toString"),
      NanNew<FunctionTemplate>(ToString)->GetFunction());
  tpl->PrototypeTemplate()->Set(
      NanNew("parent"),
      NanNew<FunctionTemplate>(Parent)->GetFunction());
  tpl->PrototypeTemplate()->Set(
      NanNew("next"),
      NanNew<FunctionTemplate>(Next)->GetFunction());
  tpl->PrototypeTemplate()->Set(
      NanNew("prev"),
      NanNew<FunctionTemplate>(Prev)->GetFunction());
  tpl->PrototypeTemplate()->Set(
      NanNew("nodeAt"),
      NanNew<FunctionTemplate>(NodeAt)->GetFunction());
}

static inline TSNode * unwrap(const Local<Object> &object) {
  return node::ObjectWrap::Unwrap<IASTNode>(object->ToObject())->node();
}

NAN_METHOD(IASTNode::ToString) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    NanReturnValue(NanNew<String>(ts_node_string(node)));
  }
  NanReturnValue(NanNew<String>("(NULL)"));
}

NAN_METHOD(IASTNode::Parent) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    TSNode *parent = ts_node_parent(node);
    if (parent)
      NanReturnValue(ASTNode::NewInstance(parent));
  }
  NanReturnNull();
}

NAN_METHOD(IASTNode::Next) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    TSNode *sibling = ts_node_next_sibling(node);
    if (sibling) {
      NanReturnValue(ASTNode::NewInstance(sibling));
    }
  }
  NanReturnNull();
}

NAN_METHOD(IASTNode::Prev) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    TSNode *sibling = ts_node_prev_sibling(node);
    if (sibling)
      NanReturnValue(ASTNode::NewInstance(sibling));
  }
  NanReturnNull();
}

NAN_METHOD(IASTNode::NodeAt) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    switch (args.Length()) {
      case 2: {
        Handle<Integer> min = Handle<Integer>::Cast(args[0]);
        Handle<Integer> max = Handle<Integer>::Cast(args[1]);
        TSNode *result = ts_node_find_for_range(node, min->Int32Value(), max->Int32Value());
        NanReturnValue(ASTNode::NewInstance(result));
      }
      case 1: {
        Handle<Integer> pos = Handle<Integer>::Cast(args[0]);
        TSNode *result = ts_node_find_for_pos(node, pos->Int32Value());
        NanReturnValue(ASTNode::NewInstance(result));
      }
      default:
        NanThrowTypeError("Must provide 1 or 2 numeric arguments");
        NanReturnUndefined();
    }
  }
  NanReturnNull();
}

NAN_GETTER(IASTNode::Name) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    NanReturnValue(NanNew<String>(ts_node_name(node)));
  }
  NanReturnNull();
}

NAN_GETTER(IASTNode::Size) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    NanReturnValue(NanNew<Integer>(ts_node_size(node).chars));
  }
  NanReturnNull();
}

NAN_GETTER(IASTNode::Position) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    NanReturnValue(NanNew<Integer>(ts_node_pos(node).chars));
  }
  NanReturnNull();
}

NAN_GETTER(IASTNode::Children) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    NanReturnValue(ASTNodeArray::NewInstance(node));
  }
  NanReturnNull();
}

}  // namespace node_tree_sitter
<commit_msg>Remove unnecessary braces<commit_after>#include "./i_ast_node.h"
#include <v8.h>
#include <node_object_wrap.h>
#include <tree_sitter/runtime.h>
#include "./ast_node.h"
#include "./ast_node_array.h"

namespace node_tree_sitter {

using namespace v8;

void IASTNode::SetUp(Local<FunctionTemplate> tpl) {
  tpl->InstanceTemplate()->SetInternalFieldCount(1);

  // Properties
  tpl->InstanceTemplate()->SetAccessor(
      NanNew<String>("children"),
      Children);
  tpl->InstanceTemplate()->SetAccessor(
      NanNew<String>("position"),
      Position);
  tpl->InstanceTemplate()->SetAccessor(
      NanNew<String>("size"),
      Size);
  tpl->InstanceTemplate()->SetAccessor(
      NanNew<String>("name"),
      Name);

  // Prototype
  tpl->PrototypeTemplate()->Set(
      NanNew<String>("toString"),
      NanNew<FunctionTemplate>(ToString)->GetFunction());
  tpl->PrototypeTemplate()->Set(
      NanNew("parent"),
      NanNew<FunctionTemplate>(Parent)->GetFunction());
  tpl->PrototypeTemplate()->Set(
      NanNew("next"),
      NanNew<FunctionTemplate>(Next)->GetFunction());
  tpl->PrototypeTemplate()->Set(
      NanNew("prev"),
      NanNew<FunctionTemplate>(Prev)->GetFunction());
  tpl->PrototypeTemplate()->Set(
      NanNew("nodeAt"),
      NanNew<FunctionTemplate>(NodeAt)->GetFunction());
}

static inline TSNode * unwrap(const Local<Object> &object) {
  return node::ObjectWrap::Unwrap<IASTNode>(object->ToObject())->node();
}

NAN_METHOD(IASTNode::ToString) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    NanReturnValue(NanNew<String>(ts_node_string(node)));
  }
  NanReturnValue(NanNew<String>("(NULL)"));
}

NAN_METHOD(IASTNode::Parent) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    TSNode *parent = ts_node_parent(node);
    if (parent)
      NanReturnValue(ASTNode::NewInstance(parent));
  }
  NanReturnNull();
}

NAN_METHOD(IASTNode::Next) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    TSNode *sibling = ts_node_next_sibling(node);
    if (sibling)
      NanReturnValue(ASTNode::NewInstance(sibling));
  }
  NanReturnNull();
}

NAN_METHOD(IASTNode::Prev) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    TSNode *sibling = ts_node_prev_sibling(node);
    if (sibling)
      NanReturnValue(ASTNode::NewInstance(sibling));
  }
  NanReturnNull();
}

NAN_METHOD(IASTNode::NodeAt) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node) {
    switch (args.Length()) {
      case 2: {
        Handle<Integer> min = Handle<Integer>::Cast(args[0]);
        Handle<Integer> max = Handle<Integer>::Cast(args[1]);
        TSNode *result = ts_node_find_for_range(node, min->Int32Value(), max->Int32Value());
        NanReturnValue(ASTNode::NewInstance(result));
      }
      case 1: {
        Handle<Integer> pos = Handle<Integer>::Cast(args[0]);
        TSNode *result = ts_node_find_for_pos(node, pos->Int32Value());
        NanReturnValue(ASTNode::NewInstance(result));
      }
      default:
        NanThrowTypeError("Must provide 1 or 2 numeric arguments");
    }
  }
  NanReturnNull();
}

NAN_GETTER(IASTNode::Name) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node)
    NanReturnValue(NanNew<String>(ts_node_name(node)));
  NanReturnNull();
}

NAN_GETTER(IASTNode::Size) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node)
    NanReturnValue(NanNew<Integer>(ts_node_size(node).chars));
  NanReturnNull();
}

NAN_GETTER(IASTNode::Position) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node)
    NanReturnValue(NanNew<Integer>(ts_node_pos(node).chars));
  NanReturnNull();
}

NAN_GETTER(IASTNode::Children) {
  NanScope();
  TSNode *node = unwrap(args.This());
  if (node)
    NanReturnValue(ASTNodeArray::NewInstance(node));
  NanReturnNull();
}

}  // namespace node_tree_sitter
<|endoftext|>


<commit_before>/***************************************************************************
*   Copyright © 2004 Jason Kivlighn <jkivlighn@gmail.com>                 *
*                                                                         *
*   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.                                   *
***************************************************************************/

#include "kretextedit.h"

//Added by qt3to4:
#include <QKeyEvent>
#include <KStandardShortcut>

#include <kaction.h>
#include <kdebug.h>

#include <sonnet/highlighter.h>

KreTextEdit::KreTextEdit( QWidget *parent ):
	KTextEdit( parent )//, KCompletionBase()
{
	KCompletion * comp = completionObject(); //creates the completion object
	comp->setIgnoreCase( true );

	completing = false;

	//connect( this, SIGNAL( clicked( int, int ) ), SLOT( haltCompletion() ) );
}

void KreTextEdit::createHighlighter()
{
	KTextEdit::createHighlighter();
	Sonnet::Highlighter * current_highlighter = highlighter();
	if (current_highlighter)
		current_highlighter->setAutomatic( false );
}

void KreTextEdit::haltCompletion()
{
	completing = false;
}
void KreTextEdit::keyPressEvent( QKeyEvent *e )
{
	// Filter key-events if completion mode is not set to CompletionNone

	KeyBindingMap keys = getKeyBindings();
	KShortcut cut;
	bool noModifier = ( e->modifiers() == Qt::NoModifier || e->modifiers() == Qt::ShiftModifier );

	if ( noModifier ) {
		QString keycode = e->text();
		if ( !keycode.isEmpty() && keycode.unicode() ->isPrint() ) {
			KTextEdit::keyPressEvent ( e );
			tryCompletion();
			e->accept();
			return ;
		}
	}

	// Handles completion
	if ( keys[ TextCompletion ].isEmpty() )
		cut = KStandardShortcut::shortcut( KStandardShortcut::TextCompletion );
	else
		cut = keys[ TextCompletion ];

	//using just the standard Ctrl+E isn't user-friendly enough for Grandma...
	if ( completing && ( cut.contains( e->key() ) || e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return ) ) {
#if 0
		int paraFrom, indexFrom, paraTo, indexTo;
		getSelection ( &paraFrom, &indexFrom, &paraTo, &indexTo );

		removeSelection();
		setCursorPosition( paraTo, indexTo );

		completing = false;
		return ;
#endif
	}

	// handle rotation

	// Handles previous match
	if ( keys[ PrevCompletionMatch ].isEmpty() )
		cut = KStandardShortcut::shortcut( KStandardShortcut::PrevCompletion );
	else
		cut = keys[ PrevCompletionMatch ];

	if ( cut.contains( e->key() ) ) {
		rotateText( KCompletionBase::PrevCompletionMatch );
		return ;
	}

	// Handles next match
	if ( keys[ NextCompletionMatch ].isEmpty() )
		cut = KStandardShortcut::shortcut( KStandardShortcut::NextCompletion );
	else
		cut = keys[ NextCompletionMatch ];

	if ( cut.contains( e->key() ) ) {
		rotateText( KCompletionBase::NextCompletionMatch );
		return ;
	}

	//any other key events will end any text completion execpt for modifiers
	switch ( e->key() ) {
	case Qt::Key_Shift:
	case Qt::Key_Control:
	case Qt::Key_Alt:
	case Qt::Key_Meta:
		break;
	default:
		completing = false;
		break;
	}

	// Let KTextEdit handle any other keys events.
	KTextEdit::keyPressEvent ( e );
}

void KreTextEdit::setCompletedText( const QString &txt )
{
#if 0
	int para, index;
	getCursorPosition( &para, &index );

	QString para_text = text( para );
	int word_length = index - completion_begin;

	insert( txt.right( txt.length() - word_length ) );
	setSelection( para, index, para, completion_begin + txt.length() );
	setCursorPosition( para, index );

	completing = true;
#endif
}

void KreTextEdit::setCompletedItems( const QStringList &/*items*/ , bool)
{}

void KreTextEdit::tryCompletion()
{
#if 0
	int para, index;
	getCursorPosition( &para, &index );

	QString para_text = text( para );
	if ( para_text.at( index ).isSpace() || completing ) {
		if ( !completing )
			completion_begin = para_text.lastIndexOf( ' ', index - 1 ) + 1;

		QString completing_word = para_text.mid( completion_begin, index - completion_begin );

		QString match = compObj() ->makeCompletion( completing_word );

		if ( !match.isNull() && match != completing_word )
			setCompletedText( match );
		else
			completing = false;
	}
#endif
}

void KreTextEdit::rotateText( KCompletionBase::KeyBindingType type )
{
	KCompletion * comp = compObj();
	if ( comp && completing &&
	( type == KCompletionBase::PrevCompletionMatch ||
	type == KCompletionBase::NextCompletionMatch ) ) {
#if 0
		QString input = ( type == KCompletionBase::PrevCompletionMatch ) ? comp->previousMatch() : comp->nextMatch();

		// Skip rotation if previous/next match is null or the same text
		int para, index;
		getCursorPosition( &para, &index );
		QString para_text = text( para );
		QString complete_word = para_text.mid( completion_begin, index - completion_begin );
		if ( input.isNull() || input == complete_word )
			return ;
		setCompletedText( input );
#endif
	}
}

void KreTextEdit::addCompletionItem( const QString &name )
{
	compObj() ->addItem( name );
}

void KreTextEdit::removeCompletionItem( const QString &name )
{
	compObj() ->removeItem( name );
}

void KreTextEdit::clearCompletionItems()
{
	compObj() ->clear();
}

#include "kretextedit.moc"
<commit_msg>Use our own local configuration for spell checking.<commit_after>/***************************************************************************
*   Copyright © 2004 Jason Kivlighn <jkivlighn@gmail.com>                 *
*                                                                         *
*   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.                                   *
***************************************************************************/

#include "kretextedit.h"

#include <KStandardDirs>
//Added by qt3to4:
#include <QKeyEvent>
#include <KStandardShortcut>

#include <kaction.h>
#include <kdebug.h>

#include <sonnet/highlighter.h>

KreTextEdit::KreTextEdit( QWidget *parent ):
	KTextEdit( parent )//, KCompletionBase()
{
	KCompletion * comp = completionObject(); //creates the completion object
	comp->setIgnoreCase( true );

	completing = false;

	setSpellCheckingConfigFileName( KStandardDirs::locateLocal( "config", "krecipesrc"  ) );

	//connect( this, SIGNAL( clicked( int, int ) ), SLOT( haltCompletion() ) );
}

void KreTextEdit::createHighlighter()
{
	KTextEdit::createHighlighter();
	Sonnet::Highlighter * current_highlighter = highlighter();
	if (current_highlighter)
		current_highlighter->setAutomatic( false );
}

void KreTextEdit::haltCompletion()
{
	completing = false;
}
void KreTextEdit::keyPressEvent( QKeyEvent *e )
{
	// Filter key-events if completion mode is not set to CompletionNone

	KeyBindingMap keys = getKeyBindings();
	KShortcut cut;
	bool noModifier = ( e->modifiers() == Qt::NoModifier || e->modifiers() == Qt::ShiftModifier );

	if ( noModifier ) {
		QString keycode = e->text();
		if ( !keycode.isEmpty() && keycode.unicode() ->isPrint() ) {
			KTextEdit::keyPressEvent ( e );
			tryCompletion();
			e->accept();
			return ;
		}
	}

	// Handles completion
	if ( keys[ TextCompletion ].isEmpty() )
		cut = KStandardShortcut::shortcut( KStandardShortcut::TextCompletion );
	else
		cut = keys[ TextCompletion ];

	//using just the standard Ctrl+E isn't user-friendly enough for Grandma...
	if ( completing && ( cut.contains( e->key() ) || e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return ) ) {
#if 0
		int paraFrom, indexFrom, paraTo, indexTo;
		getSelection ( &paraFrom, &indexFrom, &paraTo, &indexTo );

		removeSelection();
		setCursorPosition( paraTo, indexTo );

		completing = false;
		return ;
#endif
	}

	// handle rotation

	// Handles previous match
	if ( keys[ PrevCompletionMatch ].isEmpty() )
		cut = KStandardShortcut::shortcut( KStandardShortcut::PrevCompletion );
	else
		cut = keys[ PrevCompletionMatch ];

	if ( cut.contains( e->key() ) ) {
		rotateText( KCompletionBase::PrevCompletionMatch );
		return ;
	}

	// Handles next match
	if ( keys[ NextCompletionMatch ].isEmpty() )
		cut = KStandardShortcut::shortcut( KStandardShortcut::NextCompletion );
	else
		cut = keys[ NextCompletionMatch ];

	if ( cut.contains( e->key() ) ) {
		rotateText( KCompletionBase::NextCompletionMatch );
		return ;
	}

	//any other key events will end any text completion execpt for modifiers
	switch ( e->key() ) {
	case Qt::Key_Shift:
	case Qt::Key_Control:
	case Qt::Key_Alt:
	case Qt::Key_Meta:
		break;
	default:
		completing = false;
		break;
	}

	// Let KTextEdit handle any other keys events.
	KTextEdit::keyPressEvent ( e );
}

void KreTextEdit::setCompletedText( const QString &txt )
{
#if 0
	int para, index;
	getCursorPosition( &para, &index );

	QString para_text = text( para );
	int word_length = index - completion_begin;

	insert( txt.right( txt.length() - word_length ) );
	setSelection( para, index, para, completion_begin + txt.length() );
	setCursorPosition( para, index );

	completing = true;
#endif
}

void KreTextEdit::setCompletedItems( const QStringList &/*items*/ , bool)
{}

void KreTextEdit::tryCompletion()
{
#if 0
	int para, index;
	getCursorPosition( &para, &index );

	QString para_text = text( para );
	if ( para_text.at( index ).isSpace() || completing ) {
		if ( !completing )
			completion_begin = para_text.lastIndexOf( ' ', index - 1 ) + 1;

		QString completing_word = para_text.mid( completion_begin, index - completion_begin );

		QString match = compObj() ->makeCompletion( completing_word );

		if ( !match.isNull() && match != completing_word )
			setCompletedText( match );
		else
			completing = false;
	}
#endif
}

void KreTextEdit::rotateText( KCompletionBase::KeyBindingType type )
{
	KCompletion * comp = compObj();
	if ( comp && completing &&
	( type == KCompletionBase::PrevCompletionMatch ||
	type == KCompletionBase::NextCompletionMatch ) ) {
#if 0
		QString input = ( type == KCompletionBase::PrevCompletionMatch ) ? comp->previousMatch() : comp->nextMatch();

		// Skip rotation if previous/next match is null or the same text
		int para, index;
		getCursorPosition( &para, &index );
		QString para_text = text( para );
		QString complete_word = para_text.mid( completion_begin, index - completion_begin );
		if ( input.isNull() || input == complete_word )
			return ;
		setCompletedText( input );
#endif
	}
}

void KreTextEdit::addCompletionItem( const QString &name )
{
	compObj() ->addItem( name );
}

void KreTextEdit::removeCompletionItem( const QString &name )
{
	compObj() ->removeItem( name );
}

void KreTextEdit::clearCompletionItems()
{
	compObj() ->clear();
}

#include "kretextedit.moc"
<|endoftext|>


<commit_before>#pragma once
#include "../arglist.hpp"
static cov_basic::extension hash_map_ext;
namespace hash_map_cbs_ext {
	using namespace cov_basic;
	cov::any clear(array& args)
	{
		arglist::check<hash_map>(args);
		args.at(0).val<hash_map>(true).clear();
		return number(0);
	}
	cov::any insert(array& args)
	{
		if(args.size()!=3)
			throw syntax_error("Wrong size of arguments.");
		if(args.at(0).type()!=typeid(hash_map))
			throw syntax_error("Wrong type of arguments.(Request Hash Map)");
		hash_map& map=args.at(0).val<hash_map>(true);
		if(map.count(args.at(1))>0)
			map.at(args.at(1)).swap(copy(args.at(2)),true);
		else
			map.emplace(copy(args.at(1)),copy(args.at(2)));
		return number(0);
	}
	cov::any erase(array& args)
	{
		if(args.size()!=2)
			throw syntax_error("Wrong size of arguments.");
		if(args.at(0).type()!=typeid(hash_map))
			throw syntax_error("Wrong type of arguments.(Request Hash Map)");
		args.at(0).val<hash_map>(true).erase(args.at(1));
		return number(0);
	}
	cov::any exist(array& args)
	{
		if(args.size()!=2)
			throw syntax_error("Wrong size of arguments.");
		if(args.at(0).type()!=typeid(hash_map))
			throw syntax_error("Wrong type of arguments.(Request Hash Map)");
		return bool(args.at(0).val<hash_map>(true).count(args.at(1))>0);
	}
	cov::any at(array& args)
	{
		if(args.size()!=2)
			throw syntax_error("Wrong size of arguments.");
		if(args.at(0).type()!=typeid(hash_map))
			throw syntax_error("Wrong type of arguments.(Request Hash Map)");
		return args.at(0).val<hash_map>(true).at(args.at(1));
	}
	cov::any for_each(array& args)
	{
		arglist::check<hash_map,function>(args);
		const function& f=args.at(1).const_val<function>();
		for(auto& pair:args.at(0).val<hash_map>(true)) {
			array arr= {pair.first,pair.second};
			f.call(arr);
		}
		return number(0);
	}
	void init()
	{
		hash_map_ext.add_var("clear",cov::any::make_protect<native_interface>(clear,true));
		hash_map_ext.add_var("insert",cov::any::make_protect<native_interface>(insert,true));
		hash_map_ext.add_var("erase",cov::any::make_protect<native_interface>(erase,true));
		hash_map_ext.add_var("exist",cov::any::make_protect<native_interface>(exist,true));
		hash_map_ext.add_var("at",cov::any::make_protect<native_interface>(at,true));
		hash_map_ext.add_var("for_each",cov::any::make_protect<native_interface>(for_each));
	}
}
<commit_msg>移除旧的for_each<commit_after>#pragma once
#include "../arglist.hpp"
static cov_basic::extension hash_map_ext;
namespace hash_map_cbs_ext {
	using namespace cov_basic;
	cov::any clear(array& args)
	{
		arglist::check<hash_map>(args);
		args.at(0).val<hash_map>(true).clear();
		return number(0);
	}
	cov::any insert(array& args)
	{
		if(args.size()!=3)
			throw syntax_error("Wrong size of arguments.");
		if(args.at(0).type()!=typeid(hash_map))
			throw syntax_error("Wrong type of arguments.(Request Hash Map)");
		hash_map& map=args.at(0).val<hash_map>(true);
		if(map.count(args.at(1))>0)
			map.at(args.at(1)).swap(copy(args.at(2)),true);
		else
			map.emplace(copy(args.at(1)),copy(args.at(2)));
		return number(0);
	}
	cov::any erase(array& args)
	{
		if(args.size()!=2)
			throw syntax_error("Wrong size of arguments.");
		if(args.at(0).type()!=typeid(hash_map))
			throw syntax_error("Wrong type of arguments.(Request Hash Map)");
		args.at(0).val<hash_map>(true).erase(args.at(1));
		return number(0);
	}
	cov::any exist(array& args)
	{
		if(args.size()!=2)
			throw syntax_error("Wrong size of arguments.");
		if(args.at(0).type()!=typeid(hash_map))
			throw syntax_error("Wrong type of arguments.(Request Hash Map)");
		return bool(args.at(0).val<hash_map>(true).count(args.at(1))>0);
	}
	cov::any at(array& args)
	{
		if(args.size()!=2)
			throw syntax_error("Wrong size of arguments.");
		if(args.at(0).type()!=typeid(hash_map))
			throw syntax_error("Wrong type of arguments.(Request Hash Map)");
		return args.at(0).val<hash_map>(true).at(args.at(1));
	}
	void init()
	{
		hash_map_ext.add_var("clear",cov::any::make_protect<native_interface>(clear,true));
		hash_map_ext.add_var("insert",cov::any::make_protect<native_interface>(insert,true));
		hash_map_ext.add_var("erase",cov::any::make_protect<native_interface>(erase,true));
		hash_map_ext.add_var("exist",cov::any::make_protect<native_interface>(exist,true));
		hash_map_ext.add_var("at",cov::any::make_protect<native_interface>(at,true));
	}
}
<|endoftext|>


<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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.
==============================================================================*/

// This file contains the analysis and transformation to rewrite kernel
// functions such that information about alignment, aliasing and zero offsets
// steming from the tf_framework uses is propagated.

#include <memory>

#include "mlir/Dialect/GPU/GPUDialect.h"  // from @llvm-project
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"  // from @llvm-project
#include "mlir/Dialect/StandardOps/IR/Ops.h"  // from @llvm-project
#include "mlir/IR/MLIRContext.h"  // from @llvm-project
#include "mlir/IR/StandardTypes.h"  // from @llvm-project
#include "mlir/Support/LLVM.h"  // from @llvm-project
#include "tensorflow/compiler/mlir/hlo/include/mlir-hlo/Dialect/mhlo/IR/lhlo_ops.h"
#include "tensorflow/compiler/mlir/tools/kernel_gen/ir/tf_framework_ops.h"
#include "tensorflow/compiler/mlir/tools/kernel_gen/transforms/passes.h"

namespace mlir {
namespace kernel_gen {
namespace transforms {
namespace {

#define GEN_PASS_CLASSES
#include "tensorflow/compiler/mlir/tools/kernel_gen/transforms/kernel_gen_passes.h.inc"

// TODO(herhut): Move upstream to MLIR.
static constexpr StringRef kLLVMAlignAttrName = "llvm.align";
static constexpr StringRef kLLVMNoAliasAttrName = "llvm.noalias";

struct PropagateTfAbiKnowledgeToKernelsPass
    : public PropagateTfAbiKnowledgeToKernelsBase<
          PropagateTfAbiKnowledgeToKernelsPass> {
  void runOnFunction() override {
    FuncOp function = getFunction();
    // We currently only handle entry functions and do not propagate across
    // functions.
    if (function.getAttrOfType<mlir::UnitAttr>(
            tf_framework::TFFrameworkDialect::kTFEntryAttrName)) {
      // For all operands of this function, we know they are aligned. Also, by
      // construction of kernel generator, we know that there is no offset.
      // TODO(herhut): Insert asserts in debug mode to check this.
      for (auto argument : function.getArguments()) {
        if (argument.getType().isa<BaseMemRefType>()) {
          allocated_by_runtime.insert(argument);
        }
      }
    }

    // For locally allocated values, we know they are aligned and have offset
    // zero. Further, they also do not alias with other memrefs, except in
    // benign ways. This is ensured by the reuse analysis.
    function.walk([&](tf_framework::TFAllocOp op) {
      Value allocated = op.getResult();
      allocated_by_runtime.insert(allocated);
      no_alias.insert(allocated);
    });

    // Next, take what we have and propagate it through known operations.
    propagateThroughUses();

    // Now look at launches and make use of the knowledge we have.
    function.walk([&](gpu::LaunchFuncOp launch) {
      auto module = launch.getParentOfType<ModuleOp>();
      auto kernel = module.lookupSymbol<LLVM::LLVMFuncOp>(launch.kernel());

      if (!kernel || kernel.isExternal()) return;

      // Count the position of kernel operands independently, as they do not
      // coincide with laucnh operands as memref parameters get expanded when
      // lowered to llvm.
      int kernel_p = 0;
      OpBuilder b = OpBuilder::atBlockBegin(&kernel.body().front());
      Value zero;
      Value one;
      auto loc = kernel.getLoc();
      for (auto operand : launch.operands()) {
        auto memref = operand.getType().dyn_cast<MemRefType>();
        if (!memref) {
          // Scalar argument, advance kernel position by one.
          kernel_p++;
          continue;
        }
        if (allocated_by_runtime.contains(operand)) {
          // This was allocated by the tf runtime, so it is aligned, has no
          // offset, an inner stride of 1 and the two pointers in the descriptor
          // coincide. Rewrite the kernel accordingly.
          Value alloc_ptr = kernel.getArgument(kernel_p);
          Value align_ptr = kernel.getArgument(kernel_p + 1);
          alloc_ptr.replaceAllUsesWith(align_ptr);
          Value offset = kernel.getArgument(kernel_p + 2);
          if (!zero) {
            zero = b.create<LLVM::ConstantOp>(loc, offset.getType(),
                                              b.getIndexAttr(0));
          }
          offset.replaceAllUsesWith(zero);
          // The stride is the last argument belonging to this memref.
          Value inner_stride =
              kernel.getArgument(kernel_p + 2 + memref.getRank() * 2);
          if (!one) {
            one = b.create<LLVM::ConstantOp>(loc, offset.getType(),
                                             b.getIndexAttr(1));
          }
          inner_stride.replaceAllUsesWith(one);
          kernel.setArgAttr(
              kernel_p + 1, kLLVMAlignAttrName,
              b.getIndexAttr(
                  tf_framework::TFFrameworkDialect::kAllocationAlignment));
        }
        if (no_alias.contains(operand)) {
          // TODO(herhut): We also need to check whether any of the other args
          //     are aliases. This is currently never the case by construction
          //     but we could use the alias analysis from buffer placement here
          //     to make sure.
          // Add the no_alias attribute to the correspondign pointer.
          kernel.setArgAttr(kernel_p + 1, kLLVMNoAliasAttrName,
                            b.getBoolAttr(true));
        }
        // Advance base, aligned, offset, strides and sizes many arguments.
        kernel_p += memref.getRank() * 2 + 3;
      }
    });
  }

 private:
  void propagateThroughUses() {
    llvm::SmallVector<Value, 4> worklist(allocated_by_runtime.begin(),
                                         allocated_by_runtime.end());

    while (!worklist.empty()) {
      Value candidate = worklist.pop_back_val();
      for (auto user : candidate.getUsers()) {
        if (auto reshape = dyn_cast<MemRefReshapeOp>(user)) {
          // Reshape propagates alignment, offset and innermost stride.
          // TODO(herhut): This should be a trait.
          if (allocated_by_runtime.insert(reshape.result()).second) {
            worklist.push_back(reshape.result());
          }
        }
      }
    }
  }

  // Set of values that were allocated by the tf runtime and hence are aligned
  // and have no offset.
  llvm::DenseSet<Value> allocated_by_runtime;
  // Set of values we know do not alias other values.
  llvm::DenseSet<Value> no_alias;
};

}  // namespace

std::unique_ptr<FunctionPass> CreatePropagateTfAbiKnowledgeToKernels() {
  return std::make_unique<PropagateTfAbiKnowledgeToKernelsPass>();
}

}  // namespace transforms
}  // namespace kernel_gen
}  // namespace mlir
<commit_msg>Use align and aliasing attribute name getters form LLVMDialect now that they are available.<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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.
==============================================================================*/

// This file contains the analysis and transformation to rewrite kernel
// functions such that information about alignment, aliasing and zero offsets
// steming from the tf_framework uses is propagated.

#include <memory>

#include "mlir/Dialect/GPU/GPUDialect.h"  // from @llvm-project
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"  // from @llvm-project
#include "mlir/Dialect/StandardOps/IR/Ops.h"  // from @llvm-project
#include "mlir/IR/MLIRContext.h"  // from @llvm-project
#include "mlir/IR/StandardTypes.h"  // from @llvm-project
#include "mlir/Support/LLVM.h"  // from @llvm-project
#include "tensorflow/compiler/mlir/hlo/include/mlir-hlo/Dialect/mhlo/IR/lhlo_ops.h"
#include "tensorflow/compiler/mlir/tools/kernel_gen/ir/tf_framework_ops.h"
#include "tensorflow/compiler/mlir/tools/kernel_gen/transforms/passes.h"

namespace mlir {
namespace kernel_gen {
namespace transforms {
namespace {

#define GEN_PASS_CLASSES
#include "tensorflow/compiler/mlir/tools/kernel_gen/transforms/kernel_gen_passes.h.inc"

struct PropagateTfAbiKnowledgeToKernelsPass
    : public PropagateTfAbiKnowledgeToKernelsBase<
          PropagateTfAbiKnowledgeToKernelsPass> {
  void runOnFunction() override {
    FuncOp function = getFunction();
    // We currently only handle entry functions and do not propagate across
    // functions.
    if (function.getAttrOfType<mlir::UnitAttr>(
            tf_framework::TFFrameworkDialect::kTFEntryAttrName)) {
      // For all operands of this function, we know they are aligned. Also, by
      // construction of kernel generator, we know that there is no offset.
      // TODO(herhut): Insert asserts in debug mode to check this.
      for (auto argument : function.getArguments()) {
        if (argument.getType().isa<BaseMemRefType>()) {
          allocated_by_runtime.insert(argument);
        }
      }
    }

    // For locally allocated values, we know they are aligned and have offset
    // zero. Further, they also do not alias with other memrefs, except in
    // benign ways. This is ensured by the reuse analysis.
    function.walk([&](tf_framework::TFAllocOp op) {
      Value allocated = op.getResult();
      allocated_by_runtime.insert(allocated);
      no_alias.insert(allocated);
    });

    // Next, take what we have and propagate it through known operations.
    propagateThroughUses();

    // Now look at launches and make use of the knowledge we have.
    function.walk([&](gpu::LaunchFuncOp launch) {
      auto module = launch.getParentOfType<ModuleOp>();
      auto kernel = module.lookupSymbol<LLVM::LLVMFuncOp>(launch.kernel());

      if (!kernel || kernel.isExternal()) return;

      // Count the position of kernel operands independently, as they do not
      // coincide with laucnh operands as memref parameters get expanded when
      // lowered to llvm.
      int kernel_p = 0;
      OpBuilder b = OpBuilder::atBlockBegin(&kernel.body().front());
      Value zero;
      Value one;
      auto loc = kernel.getLoc();
      for (auto operand : launch.operands()) {
        auto memref = operand.getType().dyn_cast<MemRefType>();
        if (!memref) {
          // Scalar argument, advance kernel position by one.
          kernel_p++;
          continue;
        }
        if (allocated_by_runtime.contains(operand)) {
          // This was allocated by the tf runtime, so it is aligned, has no
          // offset, an inner stride of 1 and the two pointers in the descriptor
          // coincide. Rewrite the kernel accordingly.
          Value alloc_ptr = kernel.getArgument(kernel_p);
          Value align_ptr = kernel.getArgument(kernel_p + 1);
          alloc_ptr.replaceAllUsesWith(align_ptr);
          Value offset = kernel.getArgument(kernel_p + 2);
          if (!zero) {
            zero = b.create<LLVM::ConstantOp>(loc, offset.getType(),
                                              b.getIndexAttr(0));
          }
          offset.replaceAllUsesWith(zero);
          // The stride is the last argument belonging to this memref.
          Value inner_stride =
              kernel.getArgument(kernel_p + 2 + memref.getRank() * 2);
          if (!one) {
            one = b.create<LLVM::ConstantOp>(loc, offset.getType(),
                                             b.getIndexAttr(1));
          }
          inner_stride.replaceAllUsesWith(one);
          kernel.setArgAttr(
              kernel_p + 1, LLVM::LLVMDialect::getAlignAttrName(),
              b.getIndexAttr(
                  tf_framework::TFFrameworkDialect::kAllocationAlignment));
        }
        if (no_alias.contains(operand)) {
          // TODO(herhut): We also need to check whether any of the other args
          //     are aliases. This is currently never the case by construction
          //     but we could use the alias analysis from buffer placement here
          //     to make sure.
          // Add the no_alias attribute to the correspondign pointer.
          kernel.setArgAttr(kernel_p + 1,
                            LLVM::LLVMDialect::getNoAliasAttrName(),
                            b.getBoolAttr(true));
        }
        // Advance base, aligned, offset, strides and sizes many arguments.
        kernel_p += memref.getRank() * 2 + 3;
      }
    });
  }

 private:
  void propagateThroughUses() {
    llvm::SmallVector<Value, 4> worklist(allocated_by_runtime.begin(),
                                         allocated_by_runtime.end());

    while (!worklist.empty()) {
      Value candidate = worklist.pop_back_val();
      for (auto user : candidate.getUsers()) {
        if (auto reshape = dyn_cast<MemRefReshapeOp>(user)) {
          // Reshape propagates alignment, offset and innermost stride.
          // TODO(herhut): This should be a trait.
          if (allocated_by_runtime.insert(reshape.result()).second) {
            worklist.push_back(reshape.result());
          }
        }
      }
    }
  }

  // Set of values that were allocated by the tf runtime and hence are aligned
  // and have no offset.
  llvm::DenseSet<Value> allocated_by_runtime;
  // Set of values we know do not alias other values.
  llvm::DenseSet<Value> no_alias;
};

}  // namespace

std::unique_ptr<FunctionPass> CreatePropagateTfAbiKnowledgeToKernels() {
  return std::make_unique<PropagateTfAbiKnowledgeToKernelsPass>();
}

}  // namespace transforms
}  // namespace kernel_gen
}  // namespace mlir
<|endoftext|>


<commit_before>/*
 * LootSchematicMenuComponent.cpp
 *
 *  Created on: 10/30/2011
 *      Author: kyle
 */

#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/objects/player/PlayerObject.h"
#include "LootSchematicMenuComponent.h"
#include "server/zone/objects/scene/components/ObjectMenuComponent.h"
#include "server/zone/objects/draftschematic/DraftSchematic.h"
#include "server/zone/packets/object/ObjectMenuResponse.h"

#include "server/zone/templates/tangible/LootSchematicTemplate.h"
#include "server/zone/managers/crafting/schematicmap/SchematicMap.h"

void LootSchematicMenuComponent::fillObjectMenuResponse(SceneObject* sceneObject, ObjectMenuResponse* menuResponse, CreatureObject* player) const {

	if (!sceneObject->isTangibleObject())
		return;

	TangibleObjectMenuComponent::fillObjectMenuResponse(sceneObject, menuResponse, player);

	uint32 gameObjectType = sceneObject->getGameObjectType();

	LootSchematicTemplate* schematicData = cast<LootSchematicTemplate*>(sceneObject->getObjectTemplate());

	if (schematicData == NULL) {
		error("No LootSchematicTemplate for: " + String::valueOf(sceneObject->getServerObjectCRC()));
		return;
	}

	String skillNeeded = schematicData->getRequiredSkill();

	if((skillNeeded.isEmpty() || player->hasSkill(skillNeeded))) {
		menuResponse->addRadialMenuItem(50, 3, "@loot_schematic:use_schematic"); //Learn Schematic
	}

}

int LootSchematicMenuComponent::handleObjectMenuSelect(SceneObject* sceneObject, CreatureObject* player, byte selectedID) const {
	if (!sceneObject->isTangibleObject())
		return 0;

	if (!player->isPlayerCreature())
		return 0;

	if(selectedID == 50) {
		if (!sceneObject->isASubChildOf(player)) {
			player->sendSystemMessage("@loot_schematic:must_be_holding"); // You must be holding that in order to use it.
			return 0;
		}

		Reference<PlayerObject*> ghost = player->getSlottedObject("ghost").castTo<PlayerObject*>();

		LootSchematicTemplate* schematicData = cast<LootSchematicTemplate*>(sceneObject->getObjectTemplate());

		if (schematicData == NULL) {
			error("No LootSchematicTemplate for: " + String::valueOf(sceneObject->getServerObjectCRC()));
			return 0;
		}

		String skillNeeded = schematicData->getRequiredSkill();

		if((!skillNeeded.isEmpty() && !player->hasSkill(skillNeeded))) {
			StringIdChatParameter* noSkill = NULL;
			noSkill = new StringIdChatParameter("@loot_schematic:not_enough_skill"); // You must have %TO skill in order to understand this.
			noSkill->setTO(skillNeeded);
			player->sendSystemMessage(*noSkill);
			return 0;
		}

		ManagedReference<DraftSchematic* > schematic = SchematicMap::instance()->get(schematicData->getTargetDraftSchematic().hashCode());

		if (schematic == NULL) {
			player->sendSystemMessage("Error learning schematic, try again later");
			error("Unable to create schematic: " + schematicData->getTargetDraftSchematic());
			return 0;
		}

		if(ghost->addRewardedSchematic(schematic, SchematicList::LOOT, schematicData->getTargetUseCount(), true)) {

			TangibleObject* tano = cast<TangibleObject*>(sceneObject);
			if(tano != NULL)
				tano->decreaseUseCount();
			player->sendSystemMessage("@loot_schematic:schematic_learned"); // You acquire a new crafting schematic!
		}

		return 0;
	} else
		return TangibleObjectMenuComponent::handleObjectMenuSelect(sceneObject, player, selectedID);

	return 0;
}

<commit_msg>[fixed] memory leak<commit_after>/*
 * LootSchematicMenuComponent.cpp
 *
 *  Created on: 10/30/2011
 *      Author: kyle
 */

#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/objects/player/PlayerObject.h"
#include "LootSchematicMenuComponent.h"
#include "server/zone/objects/scene/components/ObjectMenuComponent.h"
#include "server/zone/objects/draftschematic/DraftSchematic.h"
#include "server/zone/packets/object/ObjectMenuResponse.h"

#include "server/zone/templates/tangible/LootSchematicTemplate.h"
#include "server/zone/managers/crafting/schematicmap/SchematicMap.h"

void LootSchematicMenuComponent::fillObjectMenuResponse(SceneObject* sceneObject, ObjectMenuResponse* menuResponse, CreatureObject* player) const {

	if (!sceneObject->isTangibleObject())
		return;

	TangibleObjectMenuComponent::fillObjectMenuResponse(sceneObject, menuResponse, player);

	uint32 gameObjectType = sceneObject->getGameObjectType();

	LootSchematicTemplate* schematicData = cast<LootSchematicTemplate*>(sceneObject->getObjectTemplate());

	if (schematicData == NULL) {
		error("No LootSchematicTemplate for: " + String::valueOf(sceneObject->getServerObjectCRC()));
		return;
	}

	String skillNeeded = schematicData->getRequiredSkill();

	if((skillNeeded.isEmpty() || player->hasSkill(skillNeeded))) {
		menuResponse->addRadialMenuItem(50, 3, "@loot_schematic:use_schematic"); //Learn Schematic
	}

}

int LootSchematicMenuComponent::handleObjectMenuSelect(SceneObject* sceneObject, CreatureObject* player, byte selectedID) const {
	if (!sceneObject->isTangibleObject())
		return 0;

	if (!player->isPlayerCreature())
		return 0;

	if(selectedID == 50) {
		if (!sceneObject->isASubChildOf(player)) {
			player->sendSystemMessage("@loot_schematic:must_be_holding"); // You must be holding that in order to use it.
			return 0;
		}

		Reference<PlayerObject*> ghost = player->getSlottedObject("ghost").castTo<PlayerObject*>();

		LootSchematicTemplate* schematicData = cast<LootSchematicTemplate*>(sceneObject->getObjectTemplate());

		if (schematicData == NULL) {
			error("No LootSchematicTemplate for: " + String::valueOf(sceneObject->getServerObjectCRC()));
			return 0;
		}

		String skillNeeded = schematicData->getRequiredSkill();

		if((!skillNeeded.isEmpty() && !player->hasSkill(skillNeeded))) {
			StringIdChatParameter noSkill("@loot_schematic:not_enough_skill"); // You must have %TO skill in order to understand this.
			noSkill.setTO(skillNeeded);
			player->sendSystemMessage(noSkill);
			return 0;
		}

		ManagedReference<DraftSchematic* > schematic = SchematicMap::instance()->get(schematicData->getTargetDraftSchematic().hashCode());

		if (schematic == NULL) {
			player->sendSystemMessage("Error learning schematic, try again later");
			error("Unable to create schematic: " + schematicData->getTargetDraftSchematic());
			return 0;
		}

		if(ghost->addRewardedSchematic(schematic, SchematicList::LOOT, schematicData->getTargetUseCount(), true)) {

			TangibleObject* tano = cast<TangibleObject*>(sceneObject);
			if(tano != NULL)
				tano->decreaseUseCount();
			player->sendSystemMessage("@loot_schematic:schematic_learned"); // You acquire a new crafting schematic!
		}

		return 0;
	} else
		return TangibleObjectMenuComponent::handleObjectMenuSelect(sceneObject, player, selectedID);

	return 0;
}

<|endoftext|>


<commit_before>/*=========================================================================

Program:   openCherry Platform
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "cherryExtensionPointService.h"
#include "cherryConfigurationElement.h"
#include "cherryExtensionPoint.h"

#include "Poco/Exception.h"

#include "cherryBundle.h"

#include "Poco/StringTokenizer.h"
#include "Poco/DOM/Document.h"
#include "Poco/DOM/Node.h"
#include "Poco/DOM/Element.h"
#include "Poco/DOM/NodeList.h"
#include "Poco/DOM/NamedNodeMap.h"

#include <iostream>

namespace cherry {

bool
ExtensionPointService::IsA(const std::type_info& type)
{
  std::string name(GetType().name());
  return name == type.name() || Service::IsA(type);
}

const std::type_info&
ExtensionPointService::GetType() const
{
  return typeid(IExtensionPointService);
}

ExtensionPointService::ExtensionPointService(BundleLoader* loader)
  : m_BundleLoader(loader)
{

}

void
ExtensionPointService::AddContribution(std::istream& istr,
                                            const std::string& contributor)
{
  m_XMLInputSource.setByteStream(istr);
  Poco::XML::Document* document = m_DOMParser.parse(&m_XMLInputSource);

  Poco::XML::NodeList* nodes = document->getElementsByTagName("extension-point");
  for (unsigned long i = 0; i < nodes->length(); ++i)
  {
    Poco::XML::NamedNodeMap* attributes = nodes->item(i)->attributes();
    Poco::XML::Node* attr = attributes->getNamedItem("id");
    std::string simpleId = attr->nodeValue();
    attr = attributes->getNamedItem("name");
    std::string label = "";
    if (attr != 0) label = attr->nodeValue();

    ExtensionPoint::Pointer xp(new ExtensionPoint(contributor));
    xp->SetLabel(label);
    Poco::StringTokenizer tokenizer(simpleId, ".");
    if (tokenizer.count() == 1)
    {
      xp->SetSimpleId(simpleId);
      xp->SetParentId(contributor);
    }
    else
    {
      std::string parentId = "";
      for (std::size_t i = 0; i < tokenizer.count()-1; ++i)
      {
        if (i > 0) parentId += ".";
        parentId += tokenizer[i];
      }
      xp->SetSimpleId(tokenizer[tokenizer.count()-1]);
      xp->SetParentId(parentId);
    }

    m_ExtensionPointMap[xp->GetUniqueIdentifier()] = xp;

    std::cout << "Extension-Point found: " << xp->GetUniqueIdentifier() << " (from " << xp->GetContributor() << ")\n";

    attributes->release();
  }
  nodes->release();

  nodes = document->getElementsByTagName("extension");
  for (unsigned long i = 0; i < nodes->length(); ++i)
  {
    Poco::XML::NamedNodeMap* attributes = nodes->item(i)->attributes();
    Poco::XML::Node* attr = attributes->getNamedItem("point");
    if (attr == 0) continue;

    std::string xp = attr->nodeValue();
    std::cout << "Extension found for extension-point: " << xp << std::endl;
    if (m_ExtensionPointMap[xp].IsNull())
    {
      std::cout << "Extension-point unknown, extension skipped.\n";
      continue;
    }

    Extension::Pointer extension(new Extension(contributor));
    extension->SetExtensionPointIdentifier(xp);
    attr = attributes->getNamedItem("id");
    if (attr)
      extension->SetSimpleIdentifier(attr->nodeValue());

    std::vector<IConfigurationElement::Pointer> children;
    if (nodes->item(i)->hasChildNodes())
    {
      Poco::XML::NodeList* ch = nodes->item(i)->childNodes();
      for (unsigned long childIndex = 0; childIndex < ch->length(); ++childIndex)
      {
        Poco::XML::Node* child = ch->item(childIndex);
        if (dynamic_cast<Poco::XML::Element*>(child) == 0) continue;
        IConfigurationElement::Pointer elem(
            new ConfigurationElement(m_BundleLoader,
                                     child,
                                     contributor, extension, 0));
        children.push_back(elem);
      }
      ch->release();
    }

    extension->SetSubElements(children);

    m_ExtensionPointMap[xp]->AddExtension(extension);

    attributes->release();
  }
  //nodes->release();

  m_Contributors.insert(contributor);
}

bool
ExtensionPointService::HasContributionFrom(const std::string& name) const
{
  return m_Contributors.find(name) != m_Contributors.end();
}

const std::vector<IConfigurationElement::Pointer>
ExtensionPointService::GetConfigurationElementsFor(const std::string& extensionPointId) const
{
  std::cout << "Getting configuration elements for point: " << extensionPointId << std::endl;

  std::vector<IConfigurationElement::Pointer> configs;
  const IExtensionPoint* xp = this->GetExtensionPoint(extensionPointId);
  if (xp != 0)
  {
    std::vector<const IExtension*> extensions(xp->GetExtensions());
    for (std::vector<const IExtension*>::const_iterator extension = extensions.begin();
         extension != extensions.end(); ++extension)
    {
      std::vector<IConfigurationElement::Pointer> c((*extension)->GetConfigurationElements());
      configs.insert(configs.end(), c.begin(), c.end());
    }
  }

  return configs;
}

const IExtensionPoint*
ExtensionPointService::GetExtensionPoint(const std::string& id) const
{
  ExtensionPointMap::const_iterator iter;
  iter = m_ExtensionPointMap.find(id);
  if (iter != m_ExtensionPointMap.end()) return iter->second.GetPointer();
  return 0;
}

const IExtension*
ExtensionPointService::GetExtension(const std::string& extensionPointId, const std::string& extensionId) const
{
  const IExtensionPoint* xp = this->GetExtensionPoint(extensionPointId);
  if (xp != 0)
  {
    return xp->GetExtension(extensionId);
  }

  return 0;
}

const std::vector<const IExtension*>
ExtensionPointService::GetExtensions(const std::string& contributor) const
{
  std::vector<const IExtension*> extensions;
  for (std::map<std::string,ExtensionPoint::Pointer>::const_iterator iter = m_ExtensionPointMap.begin();
       iter != m_ExtensionPointMap.end(); ++iter)
  {
    const std::vector<const IExtension*> ext(iter->second->GetExtensions());
    for (std::vector<const IExtension*>::const_iterator extension = ext.begin();
         extension != ext.end(); ++extension)
    {
      if ((*extension)->GetNamespace() == contributor)
        extensions.push_back(*extension);
    }
  }

  return extensions;
}

const std::vector<const IExtensionPoint*>
ExtensionPointService::GetExtensionPoints() const
{
  std::vector<const IExtensionPoint*> xps;
  for (std::map<std::string,ExtensionPoint::Pointer>::const_iterator iter = m_ExtensionPointMap.begin();
       iter != m_ExtensionPointMap.end(); ++iter)
  {
    xps.push_back(iter->second.GetPointer());
  }

  return xps;
}

const std::vector<const IExtensionPoint*>
ExtensionPointService::GetExtensionPoints(const std::string& contributor) const
{
  std::vector<const IExtensionPoint*> xps;
  for (std::map<std::string,ExtensionPoint::Pointer>::const_iterator iter = m_ExtensionPointMap.begin();
       iter != m_ExtensionPointMap.end(); ++iter)
  {
    if (iter->second->GetContributor() == contributor)
      xps.push_back(iter->second.GetPointer());
  }

  return xps;
}

}
<commit_msg>add try/catch block around XML parsing code to enable further processing of plug-ins fixing type in multipleorgansegmentation/plugin.xml (missing ")<commit_after>/*=========================================================================

Program:   openCherry Platform
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "cherryExtensionPointService.h"
#include "cherryConfigurationElement.h"
#include "cherryExtensionPoint.h"

#include "Poco/Exception.h"

#include "cherryBundle.h"

#include "Poco/StringTokenizer.h"
#include "Poco/DOM/Document.h"
#include "Poco/DOM/Node.h"
#include "Poco/DOM/Element.h"
#include "Poco/DOM/NodeList.h"
#include "Poco/DOM/NamedNodeMap.h"

#include <iostream>

namespace cherry {

bool
ExtensionPointService::IsA(const std::type_info& type)
{
  std::string name(GetType().name());
  return name == type.name() || Service::IsA(type);
}

const std::type_info&
ExtensionPointService::GetType() const
{
  return typeid(IExtensionPointService);
}

ExtensionPointService::ExtensionPointService(BundleLoader* loader)
  : m_BundleLoader(loader)
{

}

void
ExtensionPointService::AddContribution(std::istream& istr,
                                            const std::string& contributor)
{
  m_XMLInputSource.setByteStream(istr);
  try
  {
  Poco::XML::Document* document = m_DOMParser.parse(&m_XMLInputSource);

  Poco::XML::NodeList* nodes = document->getElementsByTagName("extension-point");
  for (unsigned long i = 0; i < nodes->length(); ++i)
  {
    Poco::XML::NamedNodeMap* attributes = nodes->item(i)->attributes();
    Poco::XML::Node* attr = attributes->getNamedItem("id");
    std::string simpleId = attr->nodeValue();
    attr = attributes->getNamedItem("name");
    std::string label = "";
    if (attr != 0) label = attr->nodeValue();

    ExtensionPoint::Pointer xp(new ExtensionPoint(contributor));
    xp->SetLabel(label);
    Poco::StringTokenizer tokenizer(simpleId, ".");
    if (tokenizer.count() == 1)
    {
      xp->SetSimpleId(simpleId);
      xp->SetParentId(contributor);
    }
    else
    {
      std::string parentId = "";
      for (std::size_t i = 0; i < tokenizer.count()-1; ++i)
      {
        if (i > 0) parentId += ".";
        parentId += tokenizer[i];
      }
      xp->SetSimpleId(tokenizer[tokenizer.count()-1]);
      xp->SetParentId(parentId);
    }

    m_ExtensionPointMap[xp->GetUniqueIdentifier()] = xp;

    std::cout << "Extension-Point found: " << xp->GetUniqueIdentifier() << " (from " << xp->GetContributor() << ")\n";

    attributes->release();
  }
  nodes->release();

  nodes = document->getElementsByTagName("extension");
  for (unsigned long i = 0; i < nodes->length(); ++i)
  {
    Poco::XML::NamedNodeMap* attributes = nodes->item(i)->attributes();
    Poco::XML::Node* attr = attributes->getNamedItem("point");
    if (attr == 0) continue;

    std::string xp = attr->nodeValue();
    std::cout << "Extension found for extension-point: " << xp << " (from " << contributor << ")\n";
    if (m_ExtensionPointMap[xp].IsNull())
    {
      std::cout << "Extension-point unknown, extension skipped.\n";
      continue;
    }

    Extension::Pointer extension(new Extension(contributor));
    extension->SetExtensionPointIdentifier(xp);
    attr = attributes->getNamedItem("id");
    if (attr)
      extension->SetSimpleIdentifier(attr->nodeValue());

    std::vector<IConfigurationElement::Pointer> children;
    if (nodes->item(i)->hasChildNodes())
    {
      Poco::XML::NodeList* ch = nodes->item(i)->childNodes();
      for (unsigned long childIndex = 0; childIndex < ch->length(); ++childIndex)
      {
        Poco::XML::Node* child = ch->item(childIndex);
        if (dynamic_cast<Poco::XML::Element*>(child) == 0) continue;
        IConfigurationElement::Pointer elem(
            new ConfigurationElement(m_BundleLoader,
                                     child,
                                     contributor, extension, 0));
        children.push_back(elem);
      }
      ch->release();
    }

    extension->SetSubElements(children);

    m_ExtensionPointMap[xp]->AddExtension(extension);

    attributes->release();
  }
  //nodes->release();

  m_Contributors.insert(contributor);
  }
  catch(Poco::Exception* exc)
  {
    std::cerr << exc->displayText() << std::endl;
  }
  catch(...)
  {
    std::cerr << "Exception while parsing plugin.xml from " << contributor << std::endl;
  }
}

bool
ExtensionPointService::HasContributionFrom(const std::string& name) const
{
  return m_Contributors.find(name) != m_Contributors.end();
}

const std::vector<IConfigurationElement::Pointer>
ExtensionPointService::GetConfigurationElementsFor(const std::string& extensionPointId) const
{
  std::cout << "Getting configuration elements for point: " << extensionPointId << std::endl;

  std::vector<IConfigurationElement::Pointer> configs;
  const IExtensionPoint* xp = this->GetExtensionPoint(extensionPointId);
  if (xp != 0)
  {
    std::vector<const IExtension*> extensions(xp->GetExtensions());
    for (std::vector<const IExtension*>::const_iterator extension = extensions.begin();
         extension != extensions.end(); ++extension)
    {
      std::vector<IConfigurationElement::Pointer> c((*extension)->GetConfigurationElements());
      configs.insert(configs.end(), c.begin(), c.end());
    }
  }

  return configs;
}

const IExtensionPoint*
ExtensionPointService::GetExtensionPoint(const std::string& id) const
{
  ExtensionPointMap::const_iterator iter;
  iter = m_ExtensionPointMap.find(id);
  if (iter != m_ExtensionPointMap.end()) return iter->second.GetPointer();
  return 0;
}

const IExtension*
ExtensionPointService::GetExtension(const std::string& extensionPointId, const std::string& extensionId) const
{
  const IExtensionPoint* xp = this->GetExtensionPoint(extensionPointId);
  if (xp != 0)
  {
    return xp->GetExtension(extensionId);
  }

  return 0;
}

const std::vector<const IExtension*>
ExtensionPointService::GetExtensions(const std::string& contributor) const
{
  std::vector<const IExtension*> extensions;
  for (std::map<std::string,ExtensionPoint::Pointer>::const_iterator iter = m_ExtensionPointMap.begin();
       iter != m_ExtensionPointMap.end(); ++iter)
  {
    const std::vector<const IExtension*> ext(iter->second->GetExtensions());
    for (std::vector<const IExtension*>::const_iterator extension = ext.begin();
         extension != ext.end(); ++extension)
    {
      if ((*extension)->GetNamespace() == contributor)
        extensions.push_back(*extension);
    }
  }

  return extensions;
}

const std::vector<const IExtensionPoint*>
ExtensionPointService::GetExtensionPoints() const
{
  std::vector<const IExtensionPoint*> xps;
  for (std::map<std::string,ExtensionPoint::Pointer>::const_iterator iter = m_ExtensionPointMap.begin();
       iter != m_ExtensionPointMap.end(); ++iter)
  {
    xps.push_back(iter->second.GetPointer());
  }

  return xps;
}

const std::vector<const IExtensionPoint*>
ExtensionPointService::GetExtensionPoints(const std::string& contributor) const
{
  std::vector<const IExtensionPoint*> xps;
  for (std::map<std::string,ExtensionPoint::Pointer>::const_iterator iter = m_ExtensionPointMap.begin();
       iter != m_ExtensionPointMap.end(); ++iter)
  {
    if (iter->second->GetContributor() == contributor)
      xps.push_back(iter->second.GetPointer());
  }

  return xps;
}

}
<|endoftext|>


<commit_before>//===- Core/Resolver.cpp - Resolves Atom References -----------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lld/Core/Atom.h"
#include "lld/Core/File.h"
#include "lld/Core/InputFiles.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Resolver.h"
#include "lld/Core/SymbolTable.h"
#include "lld/Core/TargetInfo.h"
#include "lld/Core/UndefinedAtom.h"

#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"

#include <algorithm>
#include <cassert>
#include <vector>

namespace lld {

namespace {

/// This is used as a filter function to std::remove_if to dead strip atoms.
class NotLive {
public:
  explicit NotLive(const llvm::DenseSet<const Atom*>& la) : _liveAtoms(la) { }

  bool operator()(const Atom *atom) const {
    // don't remove if live
    if ( _liveAtoms.count(atom) )
      return false;
   // don't remove if marked never-dead-strip
    if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(atom)) {
      if ( defAtom->deadStrip() == DefinedAtom::deadStripNever )
        return false;
    }
    // do remove this atom
    return true;
  }

private:
  const llvm::DenseSet<const Atom*> _liveAtoms;
};

/// This is used as a filter function to std::remove_if to coalesced atoms.
class AtomCoalescedAway {
public:
  explicit AtomCoalescedAway(SymbolTable &sym) : _symbolTable(sym) {}

  bool operator()(const Atom *atom) const {
    const Atom *rep = _symbolTable.replacement(atom);
    return rep != atom;
  }

private:
  SymbolTable &_symbolTable;
};

} // namespace

// add all atoms from all initial .o files
void Resolver::buildInitialAtomList() {
 DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver initial atom list:\n");

  // each input files contributes initial atoms
  _atoms.reserve(1024);
  _inputFiles.forEachInitialAtom(*this);

  _completedInitialObjectFiles = true;
}

// called before the first atom in any file is added with doAtom()
void Resolver::doFile(const File &file) {
}

void Resolver::doUndefinedAtom(const class UndefinedAtom& atom) {
  DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                    << "       UndefinedAtom: "
                    << llvm::format("0x%09lX", &atom)
                    << ", name="
                    << atom.name()
                    << "\n");

 // add to list of known atoms
  _atoms.push_back(&atom);

  // tell symbol table
  _symbolTable.add(atom);
}

// called on each atom when a file is added
void Resolver::doDefinedAtom(const DefinedAtom &atom) {
  DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                    << "         DefinedAtom: "
                    << llvm::format("0x%09lX", &atom)
                    << ", file=#"
                    << atom.file().ordinal()
                    << ", atom=#"
                    << atom.ordinal()
                    << ", name="
                    << atom.name()
                    << "\n");

  // Verify on zero-size atoms are pinned to start or end of section.
  switch ( atom.sectionPosition() ) {
  case DefinedAtom::sectionPositionStart:
  case DefinedAtom::sectionPositionEnd:
    assert(atom.size() == 0);
    break;
  case DefinedAtom::sectionPositionEarly:
  case DefinedAtom::sectionPositionAny:
    break;
  }

  // add to list of known atoms
  _atoms.push_back(&atom);

  // tell symbol table
  _symbolTable.add(atom);

  if (_targetInfo.deadStrip()) {
    // add to set of dead-strip-roots, all symbols that
    // the compiler marks as don't strip
    if (atom.deadStrip() == DefinedAtom::deadStripNever)
      _deadStripRoots.insert(&atom);
  }
}

void Resolver::doSharedLibraryAtom(const SharedLibraryAtom& atom) {
   DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                    << "   SharedLibraryAtom: "
                    << llvm::format("0x%09lX", &atom)
                    << ", name="
                    << atom.name()
                    << "\n");

  // add to list of known atoms
  _atoms.push_back(&atom);

  // tell symbol table
  _symbolTable.add(atom);
}

void Resolver::doAbsoluteAtom(const AbsoluteAtom& atom) {
   DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                    << "       AbsoluteAtom: "
                    << llvm::format("0x%09lX", &atom)
                    << ", name="
                     << atom.name()
                    << "\n");

  // add to list of known atoms
  _atoms.push_back(&atom);

  // tell symbol table
  if (atom.scope() != Atom::scopeTranslationUnit) {
    _symbolTable.add(atom);
  }
}

// utility to add a vector of atoms
void Resolver::addAtoms(const std::vector<const DefinedAtom*>& newAtoms) {
  for (std::vector<const DefinedAtom *>::const_iterator it = newAtoms.begin();
       it != newAtoms.end(); ++it) {
    this->doDefinedAtom(**it);
  }
}

// ask symbol table if any definitionUndefined atoms still exist
// if so, keep searching libraries until no more atoms being added
void Resolver::resolveUndefines() {
  const bool searchArchives =
      _targetInfo.searchArchivesToOverrideTentativeDefinitions();
  const bool searchSharedLibs =
      _targetInfo.searchSharedLibrariesToOverrideTentativeDefinitions();

  // keep looping until no more undefines were added in last loop
  unsigned int undefineGenCount = 0xFFFFFFFF;
  while (undefineGenCount != _symbolTable.size()) {
    undefineGenCount = _symbolTable.size();
    std::vector<const UndefinedAtom *> undefines;
    _symbolTable.undefines(undefines);
    for ( const Atom *undefAtom : undefines ) {
      StringRef undefName = undefAtom->name();
      // load for previous undefine may also have loaded this undefine
      if (!_symbolTable.isDefined(undefName)) {
        _inputFiles.searchLibraries(undefName, true, true, false, *this);
      }
    }
    // search libraries for overrides of common symbols
    if (searchArchives || searchSharedLibs) {
      std::vector<StringRef> tentDefNames;
      _symbolTable.tentativeDefinitions(tentDefNames);
      for ( StringRef tentDefName : tentDefNames ) {
        // Load for previous tentative may also have loaded
        // something that overrode this tentative, so always check.
        const Atom *curAtom = _symbolTable.findByName(tentDefName);
        assert(curAtom != nullptr);
        if (const DefinedAtom* curDefAtom = dyn_cast<DefinedAtom>(curAtom)) {
          if (curDefAtom->merge() == DefinedAtom::mergeAsTentative ) {
            // Still tentative definition, so look for override.
            _inputFiles.searchLibraries(tentDefName, searchSharedLibs,
                                        searchArchives, true, *this);
          }
        }
      }
    }
  }
}

// switch all references to undefined or coalesced away atoms
// to the new defined atom
void Resolver::updateReferences() {
  for(const Atom *atom : _atoms) {
    if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(atom)) {
      for (const Reference *ref : *defAtom) {
        const Atom* newTarget = _symbolTable.replacement(ref->target());
        (const_cast<Reference*>(ref))->setTarget(newTarget);
      }
    }
  }
}

// for dead code stripping, recursively mark atoms "live"
void Resolver::markLive(const Atom &atom) {
  // if already marked live, then done (stop recursion)
  if ( _liveAtoms.count(&atom) )
    return;

  // mark this atom is live
  _liveAtoms.insert(&atom);

  // mark all atoms it references as live
  if ( const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
    for (const Reference *ref : *defAtom) {
      const Atom *target = ref->target();
      if ( target != nullptr )
        this->markLive(*target);
    }
  }
}

// remove all atoms not actually used
void Resolver::deadStripOptimize() {
  // only do this optimization with -dead_strip
  if (!_targetInfo.deadStrip())
    return;

  // clear liveness on all atoms
  _liveAtoms.clear();

  // By default, shared libraries are built with all globals as dead strip roots
  if (_targetInfo.globalsAreDeadStripRoots()) {
    for ( const Atom *atom : _atoms ) {
      const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom);
      if (defAtom == nullptr)
        continue;
      if ( defAtom->scope() == DefinedAtom::scopeGlobal )
        _deadStripRoots.insert(defAtom);
    }
  }

  // Or, use list of names that are dead stip roots.
  for (const StringRef &name : _targetInfo.deadStripRoots()) {
    const Atom *symAtom = _symbolTable.findByName(name);
    assert(symAtom->definition() != Atom::definitionUndefined);
    _deadStripRoots.insert(symAtom);
  }

  // mark all roots as live, and recursively all atoms they reference
  for ( const Atom *dsrAtom : _deadStripRoots) {
    this->markLive(*dsrAtom);
  }

  // now remove all non-live atoms from _atoms
  _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
                              NotLive(_liveAtoms)), _atoms.end());
}

// error out if some undefines remain
bool Resolver::checkUndefines(bool final) {
  // when using LTO, undefines are checked after bitcode is optimized
  if (_haveLLVMObjs && !final)
    return false;

  // build vector of remaining undefined symbols
  std::vector<const UndefinedAtom *> undefinedAtoms;
  _symbolTable.undefines(undefinedAtoms);
  if (_targetInfo.deadStrip()) {
    // When dead code stripping, we don't care if dead atoms are undefined.
    undefinedAtoms.erase(std::remove_if(
                           undefinedAtoms.begin(), undefinedAtoms.end(),
                           NotLive(_liveAtoms)), undefinedAtoms.end());
  }

  // error message about missing symbols
  if (!undefinedAtoms.empty()) {
    // FIXME: need diagnostics interface for writing error messages
    bool foundUndefines = false;
    for (const UndefinedAtom *undefAtom : undefinedAtoms) {
      const File &f = undefAtom->file();

      // Skip over a weak symbol.
      if (undefAtom->canBeNull() != UndefinedAtom::canBeNullNever)
        continue;

      // If this is a library and undefined symbols are allowed on the
      // target platform, skip over it.
      if (isa<SharedLibraryFile>(f) && _targetInfo.allowShlibUndefines())
        continue;

      // Seems like this symbol is undefined. Warn that.
      foundUndefines = true;
      if (_targetInfo.printRemainingUndefines()) {
        llvm::errs() << "Undefined Symbol: " << undefAtom->file().path()
                     << " : " << undefAtom->name() << "\n";
      }
    }
    if (foundUndefines) {
      if (_targetInfo.printRemainingUndefines())
        llvm::errs() << "symbol(s) not found\n";
      return true;
    }
  }
  return false;
}

// remove from _atoms all coaleseced away atoms
void Resolver::removeCoalescedAwayAtoms() {
  _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
                              AtomCoalescedAway(_symbolTable)), _atoms.end());
}

// check for interactions between symbols defined in this linkage unit
// and same symbol name in linked dynamic shared libraries
void Resolver::checkDylibSymbolCollisions() {
  for ( const Atom *atom : _atoms ) {
    const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(atom);
    if (defAtom == nullptr)
      continue;
    if ( defAtom->merge() != DefinedAtom::mergeAsTentative )
      continue;
    assert(defAtom->scope() != DefinedAtom::scopeTranslationUnit);
    // See if any shared library also has symbol which
    // collides with the tentative definition.
    // SymbolTable will warn if needed.
    _inputFiles.searchLibraries(defAtom->name(), true, false, false, *this);
  }
}

void Resolver::linkTimeOptimize() {
  // FIX ME
}

bool Resolver::resolve() {
  this->buildInitialAtomList();
  this->resolveUndefines();
  this->updateReferences();
  this->deadStripOptimize();
  if (this->checkUndefines(false)) {
    if (!_targetInfo.allowRemainingUndefines())
      return true;
  }
  this->removeCoalescedAwayAtoms();
  this->checkDylibSymbolCollisions();
  this->linkTimeOptimize();
  this->_result.addAtoms(_atoms);
  return false;
}

void Resolver::MergedFile::addAtom(const Atom& atom) {
  if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
    _definedAtoms._atoms.push_back(defAtom);
  } else if (const UndefinedAtom* undefAtom = dyn_cast<UndefinedAtom>(&atom)) {
    _undefinedAtoms._atoms.push_back(undefAtom);
  } else if (const SharedLibraryAtom* slAtom =
               dyn_cast<SharedLibraryAtom>(&atom)) {
    _sharedLibraryAtoms._atoms.push_back(slAtom);
  } else if (const AbsoluteAtom* abAtom = dyn_cast<AbsoluteAtom>(&atom)) {
    _absoluteAtoms._atoms.push_back(abAtom);
  } else {
    llvm_unreachable("atom has unknown definition kind");
  }
}

MutableFile::DefinedAtomRange Resolver::MergedFile::definedAtoms() {
  return range<std::vector<const DefinedAtom*>::iterator>(
                    _definedAtoms._atoms.begin(), _definedAtoms._atoms.end());
}

void Resolver::MergedFile::addAtoms(std::vector<const Atom*>& all) {
  DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
  for ( const Atom *atom : all ) {
    DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                    << llvm::format("    0x%09lX", atom)
                    << ", name="
                    << atom->name()
                    << "\n");
    this->addAtom(*atom);
  }
}

} // namespace lld
<commit_msg>[lld] Add comments to InputFiles::searchLibraries() arguments.<commit_after>//===- Core/Resolver.cpp - Resolves Atom References -----------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lld/Core/Atom.h"
#include "lld/Core/File.h"
#include "lld/Core/InputFiles.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/Resolver.h"
#include "lld/Core/SymbolTable.h"
#include "lld/Core/TargetInfo.h"
#include "lld/Core/UndefinedAtom.h"

#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"

#include <algorithm>
#include <cassert>
#include <vector>

namespace lld {

namespace {

/// This is used as a filter function to std::remove_if to dead strip atoms.
class NotLive {
public:
  explicit NotLive(const llvm::DenseSet<const Atom*>& la) : _liveAtoms(la) { }

  bool operator()(const Atom *atom) const {
    // don't remove if live
    if ( _liveAtoms.count(atom) )
      return false;
   // don't remove if marked never-dead-strip
    if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(atom)) {
      if ( defAtom->deadStrip() == DefinedAtom::deadStripNever )
        return false;
    }
    // do remove this atom
    return true;
  }

private:
  const llvm::DenseSet<const Atom*> _liveAtoms;
};

/// This is used as a filter function to std::remove_if to coalesced atoms.
class AtomCoalescedAway {
public:
  explicit AtomCoalescedAway(SymbolTable &sym) : _symbolTable(sym) {}

  bool operator()(const Atom *atom) const {
    const Atom *rep = _symbolTable.replacement(atom);
    return rep != atom;
  }

private:
  SymbolTable &_symbolTable;
};

} // namespace

// add all atoms from all initial .o files
void Resolver::buildInitialAtomList() {
 DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver initial atom list:\n");

  // each input files contributes initial atoms
  _atoms.reserve(1024);
  _inputFiles.forEachInitialAtom(*this);

  _completedInitialObjectFiles = true;
}

// called before the first atom in any file is added with doAtom()
void Resolver::doFile(const File &file) {
}

void Resolver::doUndefinedAtom(const class UndefinedAtom& atom) {
  DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                    << "       UndefinedAtom: "
                    << llvm::format("0x%09lX", &atom)
                    << ", name="
                    << atom.name()
                    << "\n");

 // add to list of known atoms
  _atoms.push_back(&atom);

  // tell symbol table
  _symbolTable.add(atom);
}

// called on each atom when a file is added
void Resolver::doDefinedAtom(const DefinedAtom &atom) {
  DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                    << "         DefinedAtom: "
                    << llvm::format("0x%09lX", &atom)
                    << ", file=#"
                    << atom.file().ordinal()
                    << ", atom=#"
                    << atom.ordinal()
                    << ", name="
                    << atom.name()
                    << "\n");

  // Verify on zero-size atoms are pinned to start or end of section.
  switch ( atom.sectionPosition() ) {
  case DefinedAtom::sectionPositionStart:
  case DefinedAtom::sectionPositionEnd:
    assert(atom.size() == 0);
    break;
  case DefinedAtom::sectionPositionEarly:
  case DefinedAtom::sectionPositionAny:
    break;
  }

  // add to list of known atoms
  _atoms.push_back(&atom);

  // tell symbol table
  _symbolTable.add(atom);

  if (_targetInfo.deadStrip()) {
    // add to set of dead-strip-roots, all symbols that
    // the compiler marks as don't strip
    if (atom.deadStrip() == DefinedAtom::deadStripNever)
      _deadStripRoots.insert(&atom);
  }
}

void Resolver::doSharedLibraryAtom(const SharedLibraryAtom& atom) {
   DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                    << "   SharedLibraryAtom: "
                    << llvm::format("0x%09lX", &atom)
                    << ", name="
                    << atom.name()
                    << "\n");

  // add to list of known atoms
  _atoms.push_back(&atom);

  // tell symbol table
  _symbolTable.add(atom);
}

void Resolver::doAbsoluteAtom(const AbsoluteAtom& atom) {
   DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                    << "       AbsoluteAtom: "
                    << llvm::format("0x%09lX", &atom)
                    << ", name="
                     << atom.name()
                    << "\n");

  // add to list of known atoms
  _atoms.push_back(&atom);

  // tell symbol table
  if (atom.scope() != Atom::scopeTranslationUnit) {
    _symbolTable.add(atom);
  }
}

// utility to add a vector of atoms
void Resolver::addAtoms(const std::vector<const DefinedAtom*>& newAtoms) {
  for (std::vector<const DefinedAtom *>::const_iterator it = newAtoms.begin();
       it != newAtoms.end(); ++it) {
    this->doDefinedAtom(**it);
  }
}

// ask symbol table if any definitionUndefined atoms still exist
// if so, keep searching libraries until no more atoms being added
void Resolver::resolveUndefines() {
  const bool searchArchives =
      _targetInfo.searchArchivesToOverrideTentativeDefinitions();
  const bool searchSharedLibs =
      _targetInfo.searchSharedLibrariesToOverrideTentativeDefinitions();

  // keep looping until no more undefines were added in last loop
  unsigned int undefineGenCount = 0xFFFFFFFF;
  while (undefineGenCount != _symbolTable.size()) {
    undefineGenCount = _symbolTable.size();
    std::vector<const UndefinedAtom *> undefines;
    _symbolTable.undefines(undefines);
    for ( const Atom *undefAtom : undefines ) {
      StringRef undefName = undefAtom->name();
      // load for previous undefine may also have loaded this undefine
      if (!_symbolTable.isDefined(undefName)) {
        _inputFiles.searchLibraries(undefName,
                                    true,   // searchSharedLibs
                                    true,   // searchArchives
                                    false,  // dataSymbolOnly
                                    *this);
      }
    }
    // search libraries for overrides of common symbols
    if (searchArchives || searchSharedLibs) {
      std::vector<StringRef> tentDefNames;
      _symbolTable.tentativeDefinitions(tentDefNames);
      for ( StringRef tentDefName : tentDefNames ) {
        // Load for previous tentative may also have loaded
        // something that overrode this tentative, so always check.
        const Atom *curAtom = _symbolTable.findByName(tentDefName);
        assert(curAtom != nullptr);
        if (const DefinedAtom* curDefAtom = dyn_cast<DefinedAtom>(curAtom)) {
          if (curDefAtom->merge() == DefinedAtom::mergeAsTentative) {
            // Still tentative definition, so look for override.
            _inputFiles.searchLibraries(tentDefName,
                                        searchSharedLibs,
                                        searchArchives,
                                        true,  // dataSymbolOnly
                                        *this);
          }
        }
      }
    }
  }
}

// switch all references to undefined or coalesced away atoms
// to the new defined atom
void Resolver::updateReferences() {
  for(const Atom *atom : _atoms) {
    if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(atom)) {
      for (const Reference *ref : *defAtom) {
        const Atom* newTarget = _symbolTable.replacement(ref->target());
        (const_cast<Reference*>(ref))->setTarget(newTarget);
      }
    }
  }
}

// for dead code stripping, recursively mark atoms "live"
void Resolver::markLive(const Atom &atom) {
  // if already marked live, then done (stop recursion)
  if ( _liveAtoms.count(&atom) )
    return;

  // mark this atom is live
  _liveAtoms.insert(&atom);

  // mark all atoms it references as live
  if ( const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
    for (const Reference *ref : *defAtom) {
      const Atom *target = ref->target();
      if ( target != nullptr )
        this->markLive(*target);
    }
  }
}

// remove all atoms not actually used
void Resolver::deadStripOptimize() {
  // only do this optimization with -dead_strip
  if (!_targetInfo.deadStrip())
    return;

  // clear liveness on all atoms
  _liveAtoms.clear();

  // By default, shared libraries are built with all globals as dead strip roots
  if (_targetInfo.globalsAreDeadStripRoots()) {
    for ( const Atom *atom : _atoms ) {
      const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(atom);
      if (defAtom == nullptr)
        continue;
      if ( defAtom->scope() == DefinedAtom::scopeGlobal )
        _deadStripRoots.insert(defAtom);
    }
  }

  // Or, use list of names that are dead stip roots.
  for (const StringRef &name : _targetInfo.deadStripRoots()) {
    const Atom *symAtom = _symbolTable.findByName(name);
    assert(symAtom->definition() != Atom::definitionUndefined);
    _deadStripRoots.insert(symAtom);
  }

  // mark all roots as live, and recursively all atoms they reference
  for ( const Atom *dsrAtom : _deadStripRoots) {
    this->markLive(*dsrAtom);
  }

  // now remove all non-live atoms from _atoms
  _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
                              NotLive(_liveAtoms)), _atoms.end());
}

// error out if some undefines remain
bool Resolver::checkUndefines(bool final) {
  // when using LTO, undefines are checked after bitcode is optimized
  if (_haveLLVMObjs && !final)
    return false;

  // build vector of remaining undefined symbols
  std::vector<const UndefinedAtom *> undefinedAtoms;
  _symbolTable.undefines(undefinedAtoms);
  if (_targetInfo.deadStrip()) {
    // When dead code stripping, we don't care if dead atoms are undefined.
    undefinedAtoms.erase(std::remove_if(
                           undefinedAtoms.begin(), undefinedAtoms.end(),
                           NotLive(_liveAtoms)), undefinedAtoms.end());
  }

  // error message about missing symbols
  if (!undefinedAtoms.empty()) {
    // FIXME: need diagnostics interface for writing error messages
    bool foundUndefines = false;
    for (const UndefinedAtom *undefAtom : undefinedAtoms) {
      const File &f = undefAtom->file();

      // Skip over a weak symbol.
      if (undefAtom->canBeNull() != UndefinedAtom::canBeNullNever)
        continue;

      // If this is a library and undefined symbols are allowed on the
      // target platform, skip over it.
      if (isa<SharedLibraryFile>(f) && _targetInfo.allowShlibUndefines())
        continue;

      // Seems like this symbol is undefined. Warn that.
      foundUndefines = true;
      if (_targetInfo.printRemainingUndefines()) {
        llvm::errs() << "Undefined Symbol: " << undefAtom->file().path()
                     << " : " << undefAtom->name() << "\n";
      }
    }
    if (foundUndefines) {
      if (_targetInfo.printRemainingUndefines())
        llvm::errs() << "symbol(s) not found\n";
      return true;
    }
  }
  return false;
}

// remove from _atoms all coaleseced away atoms
void Resolver::removeCoalescedAwayAtoms() {
  _atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(),
                              AtomCoalescedAway(_symbolTable)), _atoms.end());
}

// check for interactions between symbols defined in this linkage unit
// and same symbol name in linked dynamic shared libraries
void Resolver::checkDylibSymbolCollisions() {
  for ( const Atom *atom : _atoms ) {
    const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(atom);
    if (defAtom == nullptr)
      continue;
    if ( defAtom->merge() != DefinedAtom::mergeAsTentative )
      continue;
    assert(defAtom->scope() != DefinedAtom::scopeTranslationUnit);
    // See if any shared library also has symbol which
    // collides with the tentative definition.
    // SymbolTable will warn if needed.
    _inputFiles.searchLibraries(defAtom->name(), true, false, false, *this);
  }
}

void Resolver::linkTimeOptimize() {
  // FIX ME
}

bool Resolver::resolve() {
  this->buildInitialAtomList();
  this->resolveUndefines();
  this->updateReferences();
  this->deadStripOptimize();
  if (this->checkUndefines(false)) {
    if (!_targetInfo.allowRemainingUndefines())
      return true;
  }
  this->removeCoalescedAwayAtoms();
  this->checkDylibSymbolCollisions();
  this->linkTimeOptimize();
  this->_result.addAtoms(_atoms);
  return false;
}

void Resolver::MergedFile::addAtom(const Atom& atom) {
  if (const DefinedAtom* defAtom = dyn_cast<DefinedAtom>(&atom)) {
    _definedAtoms._atoms.push_back(defAtom);
  } else if (const UndefinedAtom* undefAtom = dyn_cast<UndefinedAtom>(&atom)) {
    _undefinedAtoms._atoms.push_back(undefAtom);
  } else if (const SharedLibraryAtom* slAtom =
               dyn_cast<SharedLibraryAtom>(&atom)) {
    _sharedLibraryAtoms._atoms.push_back(slAtom);
  } else if (const AbsoluteAtom* abAtom = dyn_cast<AbsoluteAtom>(&atom)) {
    _absoluteAtoms._atoms.push_back(abAtom);
  } else {
    llvm_unreachable("atom has unknown definition kind");
  }
}

MutableFile::DefinedAtomRange Resolver::MergedFile::definedAtoms() {
  return range<std::vector<const DefinedAtom*>::iterator>(
                    _definedAtoms._atoms.begin(), _definedAtoms._atoms.end());
}

void Resolver::MergedFile::addAtoms(std::vector<const Atom*>& all) {
  DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
  for ( const Atom *atom : all ) {
    DEBUG_WITH_TYPE("resolver", llvm::dbgs()
                    << llvm::format("    0x%09lX", atom)
                    << ", name="
                    << atom->name()
                    << "\n");
    this->addAtom(*atom);
  }
}

} // namespace lld
<|endoftext|>