<commit_before>/*
 *  ImageJFind
 *  A Diamond application for interoperating with ImageJ
 *  Version 1
 *
 *  Copyright (c) 2002-2005 Intel Corporation
 *  Copyright (c) 2008 Carnegie Mellon University
 *  All Rights Reserved.
 *
 *  This software is distributed under the terms of the Eclipse Public
 *  License, Version 1.0 which can be found in the file named LICENSE.
 *  ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS SOFTWARE CONSTITUTES
 *  RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT
 */

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <sys/queue.h>
#include "lib_results.h"
#include "rgb.h"
#include "imagej_search.h"
#include "factory.h"
#include "quick_tar.h"

#define	MAX_DISPLAY_NAME	64

/* config file tokens that we write out */
#define SEARCH_NAME     "imagej_search"
#define EVAL_FUNCTION_ID    "EVAL_FUNCTION"
#define THRESHOLD_ID "THRESHOLD"
#define SOURCE_FOLDER_ID 	"SOURCE_FOLDER"

extern "C" {
void search_init();
}

/*
 * Initialization function that creates the factory and registers
 * it with the rest of the UI.
 */
void
search_init()
{
	imagej_factory *fac;
	fac = new imagej_factory;
	imagej_codec_factory *fac2;
	fac2 = new imagej_codec_factory;
	factory_register(fac);
	//	factory_register_codec(fac2);  // also does codec
}

imagej_search::imagej_search(const char *name, char *descr)
		: img_search(name, descr)
{
	eval_function = NULL;
	threshold = NULL;
	source_folder = NULL;

	edit_window = NULL;

	return;
}

imagej_search::~imagej_search()
{
	if (eval_function) {
		free(eval_function);
	}
	if (threshold) {
		free(threshold);
	}
	if (source_folder) {
		free(source_folder);
	}

	free(get_auxiliary_data());
	return;
}

int
imagej_search::handle_config(int nconf, char **data)
{
	int	err;

	if (strcmp(EVAL_FUNCTION_ID, data[0]) == 0) {
		assert(nconf > 1);
		eval_function = strdup(data[1]);
		assert(eval_function != NULL);
		err = 0;
	} else if (strcmp(THRESHOLD_ID, data[0]) == 0) {
		assert(nconf > 1);
		threshold = strdup(data[1]);
		assert(threshold != NULL);
		err = 0;
	} else if (strcmp(SOURCE_FOLDER_ID, data[0]) == 0) {
		assert(nconf > 1);
		source_folder = strdup(data[1]);
		assert(source_folder != NULL);
		err = 0;
	} else {
		err = img_search::handle_config(nconf, data);
	}

	return(err);
}

static void
cb_edit_done(GtkButton *item, gpointer data)
{
	GtkWidget * widget = (GtkWidget *)data;
	gtk_widget_destroy(widget);
}

static void
cb_close_edit_window(GtkWidget* item, gpointer data)
{
	imagej_search *    search;
	search = (imagej_search *)data;
	search->close_edit_win();
}

void
imagej_search::edit_search()
{
	GtkWidget *     widget;
	GtkWidget *     box;
	GtkWidget *     hbox;
	GtkWidget *     table;
	char        name[MAX_DISPLAY_NAME];

	/* see if it already exists */
	if (edit_window != NULL) {
		/* raise to top ??? */
		gdk_window_raise(GTK_WIDGET(edit_window)->window);
		return;
	}

	edit_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	snprintf(name, MAX_DISPLAY_NAME - 1, "Edit %s", get_name());
	name[MAX_DISPLAY_NAME -1] = '\0';
	gtk_window_set_title(GTK_WINDOW(edit_window), name);
	g_signal_connect(G_OBJECT(edit_window), "destroy",
	                 G_CALLBACK(cb_close_edit_window), this);

	box = gtk_vbox_new(FALSE, 10);
	gtk_container_add(GTK_CONTAINER(edit_window), box);

	hbox = gtk_hbox_new(FALSE, 10);
	gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, TRUE, 0);

	widget = gtk_button_new_with_label("Close");
	g_signal_connect(G_OBJECT(widget), "clicked",
	                 G_CALLBACK(cb_edit_done), edit_window);
	GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_DEFAULT);
	gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0);

	/*
	 * Get the controls from the img_search.
	 */
	widget = img_search_display();
	gtk_box_pack_start(GTK_BOX(box), widget, FALSE, TRUE, 0);

	/*
 	 * To make the layout look a little cleaner we use a table
	 * to place all the fields.  This will make them be nicely
	 * aligned.
	 */
	table = gtk_table_new(4, 2, FALSE);
        gtk_table_set_row_spacings(GTK_TABLE(table), 2);
        gtk_table_set_col_spacings(GTK_TABLE(table), 4);
        gtk_container_set_border_width(GTK_CONTAINER(table), 10);
	gtk_box_pack_start(GTK_BOX(box), table, FALSE, TRUE, 0);

	/* set the first row label and text entry for the eval function */
	widget = gtk_label_new("Macro name");
	gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_LEFT);
	gtk_table_attach_defaults(GTK_TABLE(table), widget, 0, 1, 0, 1);
	eval_function_entry = gtk_entry_new();
	gtk_table_attach_defaults(GTK_TABLE(table), eval_function_entry, 1, 2, 0, 1);
	if (eval_function != NULL) {
		char *s = strdup(eval_function);

		// convert '_' to ' '
		for (int i = 0; i < strlen(s); i++) {
			if (s[i] == '_') {
				s[i] = ' ';
			}
		}
		gtk_entry_set_text(GTK_ENTRY(eval_function_entry), s);
		free(s);
	}

	/* set the third row label and text entry for the threshold */
	widget = gtk_label_new("Threshold");
	gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_LEFT);
	gtk_table_attach_defaults(GTK_TABLE(table), widget, 0, 1, 2, 3);
	threshold_entry = gtk_entry_new();
	gtk_table_attach_defaults(GTK_TABLE(table), threshold_entry, 1, 2, 2, 3);
	if (threshold != NULL) {
		gtk_entry_set_text(GTK_ENTRY(threshold_entry), threshold);
	}

	/* set the fourth row label and file chooser button for the source directory */
        widget = gtk_label_new("Source folder");
	gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_LEFT);
	gtk_table_attach_defaults(GTK_TABLE(table), widget, 0, 1, 3, 4);
	source_folder_button = gtk_file_chooser_button_new("Select a Folder",
							   GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
	gtk_table_attach_defaults(GTK_TABLE(table), source_folder_button, 1, 2, 3, 4);
	if (source_folder != NULL) {
		gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(source_folder_button), source_folder);
	}

	/* make everything visible */
	gtk_widget_show_all(edit_window);

	return;
}

/*
 * This method reads the values from the current edit
 * window if there is an active one.
 */

void
imagej_search::save_edits()
{
	int fd;
	int blob_len;
	gchar *name_used;
	gboolean success;
	gchar *blob_data;

	if (edit_window == NULL) {
		return;
	}

	if (eval_function != NULL) {
		free(eval_function);
	}
	if (threshold != NULL) {
		free(threshold);
	}
	if (source_folder != NULL) {
		free(source_folder);
	}

	eval_function = strdup(gtk_entry_get_text(GTK_ENTRY(eval_function_entry)));
	assert(eval_function != NULL);

	// convert ' ' to '_'
	for (int i = 0; i < strlen(eval_function); i++) {
	  if (eval_function[i] == ' ') {
	    eval_function[i] = '_';
	  }
	}

	threshold = strdup(gtk_entry_get_text(GTK_ENTRY(threshold_entry)));
	assert(threshold != NULL);
	source_folder = strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(source_folder_button)));
	assert(source_folder != NULL);

	/* blob */
	free(get_auxiliary_data());

	fd = g_file_open_tmp(NULL, &name_used, NULL);
	g_assert(fd >= 0);

	printf("quick tar: %s\n", source_folder);
	blob_len = tar_blob(source_folder, fd);
	g_assert(blob_len >= 0);

	success = g_file_get_contents(name_used, &blob_data, NULL, NULL);
	g_assert(success);

	set_auxiliary_data(blob_data);
	set_auxiliary_data_length(blob_len);
	printf(" blob length: %d\n", blob_len);

	return;
}

void
imagej_search::close_edit_win()
{
	save_edits();

	/* call parent to give them a chance to cleanup */
	img_search::close_edit_win();

	edit_window = NULL;
}

/*
 * This write the relevant section of the filter specification file
 * for this search.
 */

void
imagej_search::write_fspec(FILE *ostream)
{
	if (strcmp("RGB", get_name()) == 0) {
		fprintf(ostream, "FILTER  RGB\n");
	} else {
		fprintf(ostream, "FILTER  %s  # dependencies \n", get_name());
		fprintf(ostream, "REQUIRES RGB\n");
	}

	fprintf(ostream, "\n");
	fprintf(ostream, "THRESHOLD  %s\n", threshold);
	fprintf(ostream, "MERIT  10000\n");
	fprintf(ostream, "EVAL_FUNCTION  f_eval_imagej_exec  # eval function \n");
	fprintf(ostream, "INIT_FUNCTION  f_init_imagej_exec  # init function \n");
	fprintf(ostream, "FINI_FUNCTION  f_fini_imagej_exec  # fini function \n");
	fprintf(ostream, "ARG  %s\n", eval_function );
	fprintf(ostream, "\n");
	fprintf(ostream, "\n");
}

void
imagej_search::write_config(FILE *ostream, const char *dirname)
{
 	fprintf(ostream, "SEARCH %s %s\n", SEARCH_NAME, get_name());
 	fprintf(ostream, "%s %s\n", EVAL_FUNCTION_ID, eval_function);
 	fprintf(ostream, "%s %d \n", THRESHOLD_ID, threshold);
 	fprintf(ostream, "%s %d \n", SOURCE_FOLDER_ID, source_folder);
}

/* Region match isn't meaningful for this search */
void
imagej_search::region_match(RGBImage *img, bbox_list_t *blist)
{
	return;
}

bool
imagej_search::is_editable(void)
{
	return true;
}
<commit_msg>Fix bugs to work with plugin runner<commit_after>/*
 *  ImageJFind
 *  A Diamond application for interoperating with ImageJ
 *  Version 1
 *
 *  Copyright (c) 2002-2005 Intel Corporation
 *  Copyright (c) 2008 Carnegie Mellon University
 *  All Rights Reserved.
 *
 *  This software is distributed under the terms of the Eclipse Public
 *  License, Version 1.0 which can be found in the file named LICENSE.
 *  ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS SOFTWARE CONSTITUTES
 *  RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT
 */

#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <sys/queue.h>
#include "lib_results.h"
#include "rgb.h"
#include "imagej_search.h"
#include "factory.h"
#include "quick_tar.h"

#define	MAX_DISPLAY_NAME	64

/* config file tokens that we write out */
#define SEARCH_NAME     "imagej_search"
#define EVAL_FUNCTION_ID    "EVAL_FUNCTION"
#define THRESHOLD_ID "THRESHOLD"
#define SOURCE_FOLDER_ID 	"SOURCE_FOLDER"

extern "C" {
void search_init();
}

/*
 * Initialization function that creates the factory and registers
 * it with the rest of the UI.
 */
void
search_init()
{
	imagej_factory *fac;
	fac = new imagej_factory;
	imagej_codec_factory *fac2;
	fac2 = new imagej_codec_factory;
	factory_register(fac);
	//	factory_register_codec(fac2);  // also does codec
}

imagej_search::imagej_search(const char *name, char *descr)
		: img_search(name, descr)
{
	eval_function = strdup("eval");
	threshold = strdup("0");
	source_folder = strdup(".");

	edit_window = NULL;

	return;
}

imagej_search::~imagej_search()
{
	if (eval_function) {
		free(eval_function);
	}
	if (threshold) {
		free(threshold);
	}
	if (source_folder) {
		free(source_folder);
	}

	free(get_auxiliary_data());
	return;
}

int
imagej_search::handle_config(int nconf, char **data)
{
	int	err;

	if (strcmp(EVAL_FUNCTION_ID, data[0]) == 0) {
		assert(nconf > 1);
		eval_function = strdup(data[1]);
		assert(eval_function != NULL);
		err = 0;
	} else if (strcmp(THRESHOLD_ID, data[0]) == 0) {
		assert(nconf > 1);
		threshold = strdup(data[1]);
		assert(threshold != NULL);
		err = 0;
	} else if (strcmp(SOURCE_FOLDER_ID, data[0]) == 0) {
		assert(nconf > 1);
		source_folder = strdup(data[1]);
		assert(source_folder != NULL);
		err = 0;
	} else {
		err = img_search::handle_config(nconf, data);
	}

	return(err);
}

static void
cb_edit_done(GtkButton *item, gpointer data)
{
	GtkWidget * widget = (GtkWidget *)data;
	gtk_widget_destroy(widget);
}

static void
cb_close_edit_window(GtkWidget* item, gpointer data)
{
	imagej_search *    search;
	search = (imagej_search *)data;
	search->close_edit_win();
}

void
imagej_search::edit_search()
{
	GtkWidget *     widget;
	GtkWidget *     box;
	GtkWidget *     hbox;
	GtkWidget *     table;
	char        name[MAX_DISPLAY_NAME];

	/* see if it already exists */
	if (edit_window != NULL) {
		/* raise to top ??? */
		gdk_window_raise(GTK_WIDGET(edit_window)->window);
		return;
	}

	edit_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	snprintf(name, MAX_DISPLAY_NAME - 1, "Edit %s", get_name());
	name[MAX_DISPLAY_NAME -1] = '\0';
	gtk_window_set_title(GTK_WINDOW(edit_window), name);
	g_signal_connect(G_OBJECT(edit_window), "destroy",
	                 G_CALLBACK(cb_close_edit_window), this);

	box = gtk_vbox_new(FALSE, 10);
	gtk_container_add(GTK_CONTAINER(edit_window), box);

	hbox = gtk_hbox_new(FALSE, 10);
	gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, TRUE, 0);

	widget = gtk_button_new_with_label("Close");
	g_signal_connect(G_OBJECT(widget), "clicked",
	                 G_CALLBACK(cb_edit_done), edit_window);
	GTK_WIDGET_SET_FLAGS(widget, GTK_CAN_DEFAULT);
	gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, TRUE, 0);

	/*
	 * Get the controls from the img_search.
	 */
	widget = img_search_display();
	gtk_box_pack_start(GTK_BOX(box), widget, FALSE, TRUE, 0);

	/*
 	 * To make the layout look a little cleaner we use a table
	 * to place all the fields.  This will make them be nicely
	 * aligned.
	 */
	table = gtk_table_new(4, 2, FALSE);
        gtk_table_set_row_spacings(GTK_TABLE(table), 2);
        gtk_table_set_col_spacings(GTK_TABLE(table), 4);
        gtk_container_set_border_width(GTK_CONTAINER(table), 10);
	gtk_box_pack_start(GTK_BOX(box), table, FALSE, TRUE, 0);

	/* set the first row label and text entry for the eval function */
	widget = gtk_label_new("Macro name");
	gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_LEFT);
	gtk_table_attach_defaults(GTK_TABLE(table), widget, 0, 1, 0, 1);
	eval_function_entry = gtk_entry_new();
	gtk_table_attach_defaults(GTK_TABLE(table), eval_function_entry, 1, 2, 0, 1);
	if (eval_function != NULL) {
		char *s = strdup(eval_function);

		// convert '_' to ' '
		for (int i = 0; i < strlen(s); i++) {
			if (s[i] == '_') {
				s[i] = ' ';
			}
		}
		gtk_entry_set_text(GTK_ENTRY(eval_function_entry), s);
		free(s);
	}

	/* set the third row label and text entry for the threshold */
	widget = gtk_label_new("Threshold");
	gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_LEFT);
	gtk_table_attach_defaults(GTK_TABLE(table), widget, 0, 1, 2, 3);
	threshold_entry = gtk_entry_new();
	gtk_table_attach_defaults(GTK_TABLE(table), threshold_entry, 1, 2, 2, 3);
	if (threshold != NULL) {
		gtk_entry_set_text(GTK_ENTRY(threshold_entry), threshold);
	}

	/* set the fourth row label and file chooser button for the source directory */
        widget = gtk_label_new("Source folder");
	gtk_label_set_justify(GTK_LABEL(widget), GTK_JUSTIFY_LEFT);
	gtk_table_attach_defaults(GTK_TABLE(table), widget, 0, 1, 3, 4);
	source_folder_button = gtk_file_chooser_button_new("Select a Folder",
							   GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
	gtk_table_attach_defaults(GTK_TABLE(table), source_folder_button, 1, 2, 3, 4);
	if (source_folder != NULL) {
		gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(source_folder_button), source_folder);
	}

	/* make everything visible */
	gtk_widget_show_all(edit_window);

	return;
}

/*
 * This method reads the values from the current edit
 * window if there is an active one.
 */

void
imagej_search::save_edits()
{
	int fd;
	int blob_len;
	gchar *name_used;
	gboolean success;
	gchar *blob_data;

	if (edit_window == NULL) {
		return;
	}

	if (eval_function != NULL) {
		free(eval_function);
	}
	if (threshold != NULL) {
		free(threshold);
	}
	if (source_folder != NULL) {
		free(source_folder);
	}

	eval_function = strdup(gtk_entry_get_text(GTK_ENTRY(eval_function_entry)));
	assert(eval_function != NULL);

	// convert ' ' to '_'
	for (int i = 0; i < strlen(eval_function); i++) {
	  if (eval_function[i] == ' ') {
	    eval_function[i] = '_';
	  }
	}

	threshold = strdup(gtk_entry_get_text(GTK_ENTRY(threshold_entry)));
	assert(threshold != NULL);
	source_folder = strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(source_folder_button)));
	assert(source_folder != NULL);

	/* blob */
	free(get_auxiliary_data());

	fd = g_file_open_tmp(NULL, &name_used, NULL);
	g_assert(fd >= 0);

	//	printf("quick tar: %s\n", source_folder);
	blob_len = tar_blob(source_folder, fd);
	g_assert(blob_len >= 0);

	success = g_file_get_contents(name_used, &blob_data, NULL, NULL);
	g_assert(success);

	set_auxiliary_data(blob_data);
	set_auxiliary_data_length(blob_len);
	//	printf(" blob length: %d\n", blob_len);

	return;
}

void
imagej_search::close_edit_win()
{
	save_edits();

	/* call parent to give them a chance to cleanup */
	img_search::close_edit_win();

	edit_window = NULL;
}

/*
 * This write the relevant section of the filter specification file
 * for this search.
 */

void
imagej_search::write_fspec(FILE *ostream)
{
	if (strcmp("RGB", get_name()) == 0) {
		fprintf(ostream, "FILTER  RGB\n");
	} else {
		fprintf(ostream, "FILTER  %s  # dependencies \n", get_name());
		fprintf(ostream, "REQUIRES RGB\n");
	}

	fprintf(ostream, "\n");
	fprintf(ostream, "THRESHOLD  %s\n", threshold);
	fprintf(ostream, "MERIT  10000\n");
	fprintf(ostream, "EVAL_FUNCTION  f_eval_imagej_exec  # eval function \n");
	fprintf(ostream, "INIT_FUNCTION  f_init_imagej_exec  # init function \n");
	fprintf(ostream, "FINI_FUNCTION  f_fini_imagej_exec  # fini function \n");
	fprintf(ostream, "ARG  %s\n", eval_function );
	fprintf(ostream, "\n");
	fprintf(ostream, "\n");
}

void
imagej_search::write_config(FILE *ostream, const char *dirname)
{
 	fprintf(ostream, "SEARCH %s %s\n", SEARCH_NAME, get_name());
 	fprintf(ostream, "%s %s\n", EVAL_FUNCTION_ID, eval_function);
 	fprintf(ostream, "%s %s \n", THRESHOLD_ID, threshold);
 	fprintf(ostream, "%s %s \n", SOURCE_FOLDER_ID, source_folder);
}

/* Region match isn't meaningful for this search */
void
imagej_search::region_match(RGBImage *img, bbox_list_t *blist)
{
	return;
}

bool
imagej_search::is_editable(void)
{
	return true;
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vvasielv@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/Transaction.h"

#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;

namespace cling {

  Transaction::Transaction() {
    Initialize();
  }

  Transaction::Transaction(const CompilationOptions& Opts) {
    Initialize();
    m_Opts = Opts; // intentional copy.
  }

  void Transaction::Initialize() {
    m_NestedTransactions.reset(0);
    m_Parent = 0;
    m_State = kCollecting;
    m_IssuedDiags = kNone;
    m_Opts = CompilationOptions();
    m_Module = 0;
    m_WrapperFD = 0;
    m_Next = 0;
  }

  Transaction::~Transaction() {
    if (hasNestedTransactions())
      for (size_t i = 0; i < m_NestedTransactions->size(); ++i) {
        assert((*m_NestedTransactions)[i]->getState() == kCommitted
               && "All nested transactions must be committed!");
        delete (*m_NestedTransactions)[i];
      }
  }

  void Transaction::addNestedTransaction(Transaction* nested) {
    // Create lazily the list
    if (!m_NestedTransactions)
      m_NestedTransactions.reset(new NestedTransactions());

    nested->setParent(this);
    // Leave a marker in the parent transaction, where the nested transaction
    // started.
    DelayCallInfo marker(clang::DeclGroupRef(), Transaction::kCCINone);
    m_DeclQueue.push_back(marker);
    m_NestedTransactions->push_back(nested);
  }

  void Transaction::removeNestedTransaction(Transaction* nested) {
    assert(hasNestedTransactions() && "Does not contain nested transactions");
    int nestedPos = -1;
    for (size_t i = 0; i < m_NestedTransactions->size(); ++i)
      if ((*m_NestedTransactions)[i] == nested) {
        nestedPos = i;
        break;
      }
    assert(nestedPos > -1 && "Not found!?");
    m_NestedTransactions->erase(m_NestedTransactions->begin() + nestedPos);
    // We need to remove the marker too.
    int markerPos = -1;
    for (size_t i = 0; i < size(); ++i) {
      if ((*this)[i].m_DGR.isNull() && (*this)[i].m_Call == kCCINone) {
        ++markerPos;
        if (nestedPos == markerPos) {
          erase(i);
          break;
        }
      }
    }
    if (!m_NestedTransactions->size())
      m_NestedTransactions.reset(0);
  }

  void Transaction::reset() {
    assert(empty() && "The transaction must be empty.");
    if (Transaction* parent = getParent())
      parent->removeNestedTransaction(this);
    m_Parent = 0;
    m_State = kCollecting;
    m_IssuedDiags = kNone;
    m_Opts = CompilationOptions();
    m_NestedTransactions.reset(0); // FIXME: leaks the nested transactions.
    m_Module = 0;
    m_WrapperFD = 0;
    m_Next = 0;
  }

  void Transaction::append(DelayCallInfo DCI) {
    assert(!DCI.m_DGR.isNull() && "Appending null DGR?!");
#ifdef TEMPORARILY_DISABLED
    assert(getState() == kCollecting
           && "Cannot append declarations in current state.");
#endif
    forceAppend(DCI);
  }

  void Transaction::forceAppend(DelayCallInfo DCI) {
    assert(!DCI.m_DGR.isNull() && "Appending null DGR?!");
    assert((getState() == kCollecting || getState() == kCompleted)
           && "Must not be");

#ifdef TEMPORARILY_DISABLED
#ifndef NDEBUG
    // Check for duplicates
    for (size_t i = 0, e = m_DeclQueue.size(); i < e; ++i) {
      DelayCallInfo &oldDCI (m_DeclQueue[i]);
      // It is possible to have duplicate calls to HandleVTable with the same
      // declaration, because each time Sema believes a vtable is used it emits
      // that callback.
      // For reference (clang::CodeGen::CodeGenModule::EmitVTable).
      if (oldDCI.m_Call != kCCIHandleVTable)
        assert(oldDCI != DCI && "Duplicates?!");
    }
#endif
#endif

    bool checkForWrapper = !m_WrapperFD;
    assert(checkForWrapper = true && "Check for wrappers with asserts");
    // register the wrapper if any.
    if (checkForWrapper && !DCI.m_DGR.isNull() && DCI.m_DGR.isSingleDecl()) {
      if (FunctionDecl* FD = dyn_cast<FunctionDecl>(DCI.m_DGR.getSingleDecl()))
        if (utils::Analyze::IsWrapper(FD)) {
          assert(!m_WrapperFD && "Two wrappers in one transaction?");
          m_WrapperFD = FD;
        }
    }

    if (comesFromASTReader(DCI.m_DGR))
      m_DeserializedDeclQueue.push_back(DCI);
    else
      m_DeclQueue.push_back(DCI);
  }

  void Transaction::append(clang::DeclGroupRef DGR) {
    append(DelayCallInfo(DGR, kCCIHandleTopLevelDecl));
  }

  void Transaction::append(Decl* D) {
    append(DeclGroupRef(D));
  }

  void Transaction::forceAppend(Decl* D) {
    forceAppend(DelayCallInfo(DeclGroupRef(D), kCCIHandleTopLevelDecl));
  }

  void Transaction::erase(size_t pos) {
    assert(!empty() && "Erasing from an empty transaction.");
    m_DeclQueue.erase(decls_begin() + pos);
  }

  void Transaction::dump() const {
    if (!size())
      return;

    ASTContext& C = getFirstDecl().getSingleDecl()->getASTContext();
    PrintingPolicy Policy = C.getPrintingPolicy();
    print(llvm::errs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::dumpPretty() const {
    if (!size())
      return;
    ASTContext* C = 0;
    if (m_WrapperFD)
      C = &(m_WrapperFD->getASTContext());
    if (!getFirstDecl().isNull())
      C = &(getFirstDecl().getSingleDecl()->getASTContext());

    PrintingPolicy Policy(C->getLangOpts());
    print(llvm::errs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::print(llvm::raw_ostream& Out, const PrintingPolicy& Policy,
                          unsigned Indent, bool PrintInstantiation) const {
    int nestedT = 0;
    for (const_iterator I = decls_begin(), E = decls_end(); I != E; ++I) {
      if (I->m_DGR.isNull()) {
        assert(hasNestedTransactions() && "DGR is null even if no nesting?");
        // print the nested decl
        Out<< "\n";
        Out<<"+====================================================+\n";
        Out<<"        Nested Transaction" << nestedT << "           \n";
        Out<<"+====================================================+\n";
        (*m_NestedTransactions)[nestedT++]->print(Out, Policy, Indent,
                                                  PrintInstantiation);
        Out<< "\n";
        Out<<"+====================================================+\n";
        Out<<"          End Transaction" << nestedT << "            \n";
        Out<<"+====================================================+\n";
      }
      for (DeclGroupRef::const_iterator J = I->m_DGR.begin(),
             L = I->m_DGR.end(); J != L; ++J)
        if (*J)
          (*J)->print(Out, Policy, Indent, PrintInstantiation);
        else
          Out << "<<NULL DECL>>";
    }
  }

  void Transaction::printStructure(size_t nindent) const {
    static const char* const stateNames[kNumStates] = {
      "Collecting",
      "kCompleted",
      "RolledBack",
      "RolledBackWithErrors",
      "Committed"
    };
    std::string indent(nindent, ' ');
    llvm::errs() << indent << "Transaction @" << this << ": \n";
    for (const_nested_iterator I = nested_begin(), E = nested_end();
         I != E; ++I) {
      (*I)->printStructure(nindent + 3);
    }
    llvm::errs() << indent << " state: " << stateNames[getState()] << ", "
                 << size() << " decl groups, ";
    if (hasNestedTransactions())
      llvm::errs() << m_NestedTransactions->size();
    else
      llvm::errs() << "0";

    llvm::errs() << " nested transactions\n"
                 << indent << " wrapper: " << m_WrapperFD
                 << ", parent: " << m_Parent
                 << ", next: " << m_Next << "\n";
  }

  void cling::Transaction::printStructureBrief(size_t nindent /*=0*/) const {
    std::string indent(nindent, ' ');
    llvm::errs() << indent << "<T @" << this << " isEmpty=" << empty();
    llvm::errs() << " isCommitted=" << (getState() == kCommitted);
    llvm::errs() <<"> \n";

    for (const_nested_iterator I = nested_begin(), E = nested_end();
         I != E; ++I) {
      llvm::errs() << indent << "`";
      (*I)->printStructureBrief(nindent + 3);
    }
  }

  bool Transaction::comesFromASTReader(DeclGroupRef DGR) const {
    assert(!DGR.isNull() && "DeclGroupRef is Null!");
    if (getCompilationOpts().CodeGenerationForModule)
      return true;

    // Take the first/only decl in the group.
    Decl* D = *DGR.begin();
    return D->isFromASTFile();
  }

} // end namespace cling
<commit_msg>Enhance debug printout.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vvasielv@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/Transaction.h"

#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;

namespace cling {

  Transaction::Transaction() {
    Initialize();
  }

  Transaction::Transaction(const CompilationOptions& Opts) {
    Initialize();
    m_Opts = Opts; // intentional copy.
  }

  void Transaction::Initialize() {
    m_NestedTransactions.reset(0);
    m_Parent = 0;
    m_State = kCollecting;
    m_IssuedDiags = kNone;
    m_Opts = CompilationOptions();
    m_Module = 0;
    m_WrapperFD = 0;
    m_Next = 0;
  }

  Transaction::~Transaction() {
    if (hasNestedTransactions())
      for (size_t i = 0; i < m_NestedTransactions->size(); ++i) {
        assert((*m_NestedTransactions)[i]->getState() == kCommitted
               && "All nested transactions must be committed!");
        delete (*m_NestedTransactions)[i];
      }
  }

  void Transaction::addNestedTransaction(Transaction* nested) {
    // Create lazily the list
    if (!m_NestedTransactions)
      m_NestedTransactions.reset(new NestedTransactions());

    nested->setParent(this);
    // Leave a marker in the parent transaction, where the nested transaction
    // started.
    DelayCallInfo marker(clang::DeclGroupRef(), Transaction::kCCINone);
    m_DeclQueue.push_back(marker);
    m_NestedTransactions->push_back(nested);
  }

  void Transaction::removeNestedTransaction(Transaction* nested) {
    assert(hasNestedTransactions() && "Does not contain nested transactions");
    int nestedPos = -1;
    for (size_t i = 0; i < m_NestedTransactions->size(); ++i)
      if ((*m_NestedTransactions)[i] == nested) {
        nestedPos = i;
        break;
      }
    assert(nestedPos > -1 && "Not found!?");
    m_NestedTransactions->erase(m_NestedTransactions->begin() + nestedPos);
    // We need to remove the marker too.
    int markerPos = -1;
    for (size_t i = 0; i < size(); ++i) {
      if ((*this)[i].m_DGR.isNull() && (*this)[i].m_Call == kCCINone) {
        ++markerPos;
        if (nestedPos == markerPos) {
          erase(i);
          break;
        }
      }
    }
    if (!m_NestedTransactions->size())
      m_NestedTransactions.reset(0);
  }

  void Transaction::reset() {
    assert(empty() && "The transaction must be empty.");
    if (Transaction* parent = getParent())
      parent->removeNestedTransaction(this);
    m_Parent = 0;
    m_State = kCollecting;
    m_IssuedDiags = kNone;
    m_Opts = CompilationOptions();
    m_NestedTransactions.reset(0); // FIXME: leaks the nested transactions.
    m_Module = 0;
    m_WrapperFD = 0;
    m_Next = 0;
  }

  void Transaction::append(DelayCallInfo DCI) {
    assert(!DCI.m_DGR.isNull() && "Appending null DGR?!");
#ifdef TEMPORARILY_DISABLED
    assert(getState() == kCollecting
           && "Cannot append declarations in current state.");
#endif
    forceAppend(DCI);
  }

  void Transaction::forceAppend(DelayCallInfo DCI) {
    assert(!DCI.m_DGR.isNull() && "Appending null DGR?!");
    assert((getState() == kCollecting || getState() == kCompleted)
           && "Must not be");

#ifdef TEMPORARILY_DISABLED
#ifndef NDEBUG
    // Check for duplicates
    for (size_t i = 0, e = m_DeclQueue.size(); i < e; ++i) {
      DelayCallInfo &oldDCI (m_DeclQueue[i]);
      // It is possible to have duplicate calls to HandleVTable with the same
      // declaration, because each time Sema believes a vtable is used it emits
      // that callback.
      // For reference (clang::CodeGen::CodeGenModule::EmitVTable).
      if (oldDCI.m_Call != kCCIHandleVTable)
        assert(oldDCI != DCI && "Duplicates?!");
    }
#endif
#endif

    bool checkForWrapper = !m_WrapperFD;
    assert(checkForWrapper = true && "Check for wrappers with asserts");
    // register the wrapper if any.
    if (checkForWrapper && !DCI.m_DGR.isNull() && DCI.m_DGR.isSingleDecl()) {
      if (FunctionDecl* FD = dyn_cast<FunctionDecl>(DCI.m_DGR.getSingleDecl()))
        if (utils::Analyze::IsWrapper(FD)) {
          assert(!m_WrapperFD && "Two wrappers in one transaction?");
          m_WrapperFD = FD;
        }
    }

    if (comesFromASTReader(DCI.m_DGR))
      m_DeserializedDeclQueue.push_back(DCI);
    else
      m_DeclQueue.push_back(DCI);
  }

  void Transaction::append(clang::DeclGroupRef DGR) {
    append(DelayCallInfo(DGR, kCCIHandleTopLevelDecl));
  }

  void Transaction::append(Decl* D) {
    append(DeclGroupRef(D));
  }

  void Transaction::forceAppend(Decl* D) {
    forceAppend(DelayCallInfo(DeclGroupRef(D), kCCIHandleTopLevelDecl));
  }

  void Transaction::erase(size_t pos) {
    assert(!empty() && "Erasing from an empty transaction.");
    m_DeclQueue.erase(decls_begin() + pos);
  }

  void Transaction::dump() const {
    if (!size())
      return;

    ASTContext& C = getFirstDecl().getSingleDecl()->getASTContext();
    PrintingPolicy Policy = C.getPrintingPolicy();
    print(llvm::errs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::dumpPretty() const {
    if (!size())
      return;
    ASTContext* C = 0;
    if (m_WrapperFD)
      C = &(m_WrapperFD->getASTContext());
    if (!getFirstDecl().isNull())
      C = &(getFirstDecl().getSingleDecl()->getASTContext());

    PrintingPolicy Policy(C->getLangOpts());
    print(llvm::errs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::print(llvm::raw_ostream& Out, const PrintingPolicy& Policy,
                          unsigned Indent, bool PrintInstantiation) const {
    int nestedT = 0;
    for (const_iterator I = decls_begin(), E = decls_end(); I != E; ++I) {
      if (I->m_DGR.isNull()) {
        assert(hasNestedTransactions() && "DGR is null even if no nesting?");
        // print the nested decl
        Out<< "\n";
        Out<<"+====================================================+\n";
        Out<<"        Nested Transaction" << nestedT << "           \n";
        Out<<"+====================================================+\n";
        (*m_NestedTransactions)[nestedT++]->print(Out, Policy, Indent,
                                                  PrintInstantiation);
        Out<< "\n";
        Out<<"+====================================================+\n";
        Out<<"          End Transaction" << nestedT << "            \n";
        Out<<"+====================================================+\n";
      }
      for (DeclGroupRef::const_iterator J = I->m_DGR.begin(),
             L = I->m_DGR.end(); J != L; ++J)
        if (*J)
          (*J)->print(Out, Policy, Indent, PrintInstantiation);
        else
          Out << "<<NULL DECL>>";
    }
  }

  void Transaction::printStructure(size_t nindent) const {
    static const char* const stateNames[kNumStates] = {
      "Collecting",
      "kCompleted",
      "RolledBack",
      "RolledBackWithErrors",
      "Committed"
    };
    std::string indent(nindent, ' ');
    llvm::errs() << indent << "Transaction @" << this << ": \n";
    for (const_nested_iterator I = nested_begin(), E = nested_end();
         I != E; ++I) {
      (*I)->printStructure(nindent + 3);
    }
    llvm::errs() << indent << " state: " << stateNames[getState()] << ", "
                 << size() << " decl groups, ";
    if (hasNestedTransactions())
      llvm::errs() << m_NestedTransactions->size();
    else
      llvm::errs() << "0";

    llvm::errs() << " nested transactions\n"
                 << indent << " wrapper: " << m_WrapperFD
                 << ", parent: " << m_Parent
                 << ", next: " << m_Next << "\n";
  }

  void Transaction::printStructureBrief(size_t nindent /*=0*/) const {
    std::string indent(nindent, ' ');
    llvm::errs() << indent << "<cling::Transaction* " << this
                 << " isEmpty=" << empty();
    llvm::errs() << " isCommitted=" << (getState() == kCommitted);
    llvm::errs() <<"> \n";

    for (const_nested_iterator I = nested_begin(), E = nested_end();
         I != E; ++I) {
      llvm::errs() << indent << "`";
      (*I)->printStructureBrief(nindent + 3);
    }
  }

  bool Transaction::comesFromASTReader(DeclGroupRef DGR) const {
    assert(!DGR.isNull() && "DeclGroupRef is Null!");
    if (getCompilationOpts().CodeGenerationForModule)
      return true;

    // Take the first/only decl in the group.
    Decl* D = *DGR.begin();
    return D->isFromASTFile();
  }

} // end namespace cling
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vvasielv@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/Transaction.h"

#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;

namespace cling {

  Transaction::~Transaction() {
    if (hasNestedTransactions())
      for (size_t i = 0; i < m_NestedTransactions->size(); ++i) {
        assert((*m_NestedTransactions)[i]->getState() == kCommitted
               && "All nested transactions must be committed!");
        delete (*m_NestedTransactions)[i];
      }
  }

  void Transaction::removeNestedTransaction(Transaction* nested) {
    assert(hasNestedTransactions() && "Does not contain nested transactions");
    int nestedPos = -1;
    for (size_t i = 0; i < m_NestedTransactions->size(); ++i)
      if ((*m_NestedTransactions)[i] == nested) {
        nestedPos = i;
        break;
      }
    assert(nestedPos > -1 && "Not found!?");
    m_NestedTransactions->erase(m_NestedTransactions->begin() + nestedPos);
    // We need to remove the marker too.
    for (size_t i = 0; i < size(); ++i) {
      if ((*this)[i].m_DGR.isNull())
        --nestedPos;
      if (!nestedPos) {
        erase(i);
        break;
      }
    }
  }

  void Transaction::reset() {
    assert(empty() && "The transaction must be empty.");
    if (Transaction* parent = getParent())
      parent->removeNestedTransaction(this);
    m_Parent = 0;
    m_State = kCollecting;
    m_IssuedDiags = kNone;
    m_Opts = CompilationOptions();
    //m_Module = 0; <- NOTE: we want to reuse the empty module
    m_WrapperFD = 0;
    m_Next = 0;
  }

  void Transaction::append(DelayCallInfo DCI) {
    assert(!DCI.m_DGR.isNull() && "Appending null DGR?!");
    assert(getState() == kCollecting
           && "Cannot append declarations in current state.");
    forceAppend(DCI);
  }

  void Transaction::forceAppend(DelayCallInfo DCI) {
    assert(!DCI.m_DGR.isNull() && "Appending null DGR?!");
    if (!DCI.m_DGR.isNull() && getState() == kCommitting) {
      // We are committing and getting new decls in.
      // Move them into a sub transaction that will be processed
      // recursively at the end of of commitTransaction.
      Transaction* subTransactionWhileCommitting = 0;
      if (hasNestedTransactions()
          && m_NestedTransactions->back()->getState() == kCollecting)
        subTransactionWhileCommitting = m_NestedTransactions->back();
      else {
        // FIXME: is this correct (Axel says "yes")
        CompilationOptions Opts(getCompilationOpts());
        Opts.DeclarationExtraction = 0;
        Opts.ValuePrinting = CompilationOptions::VPDisabled;
        Opts.ResultEvaluation = 0;
        Opts.DynamicScoping = 0;
        subTransactionWhileCommitting = new Transaction(Opts);
        addNestedTransaction(subTransactionWhileCommitting);
      }
      subTransactionWhileCommitting->append(DCI);
      return;
    }
    bool checkForWrapper = !m_WrapperFD;
    assert(checkForWrapper = true && "Check for wrappers with asserts");
    // register the wrapper if any.
    if (checkForWrapper && !DCI.m_DGR.isNull() && DCI.m_DGR.isSingleDecl()) {
      if (FunctionDecl* FD = dyn_cast<FunctionDecl>(DCI.m_DGR.getSingleDecl()))
        if (utils::Analyze::IsWrapper(FD)) {
          assert(!m_WrapperFD && "Two wrappers in one transaction?");
          m_WrapperFD = FD;
        }
    }

    // Lazy create the container on first append.
    if (!m_DeclQueue)
      m_DeclQueue.reset(new DeclQueue());
    m_DeclQueue->push_back(DCI);
  }

  void Transaction::append(clang::DeclGroupRef DGR) {
    append(DelayCallInfo(DGR, kCCIHandleTopLevelDecl));
  }

  void Transaction::append(Decl* D) {
    append(DeclGroupRef(D));
  }

  void Transaction::forceAppend(Decl* D) {
    forceAppend(DelayCallInfo(DeclGroupRef(D), kCCIHandleTopLevelDecl));
  }

  void Transaction::erase(size_t pos) {
    assert(!empty() && "Erasing from an empty transaction.");
    m_DeclQueue->erase(decls_begin() + pos);
  }

  void Transaction::dump() const {
    if (!size())
      return;

    ASTContext& C = getFirstDecl().getSingleDecl()->getASTContext();
    PrintingPolicy Policy = C.getPrintingPolicy();
    print(llvm::errs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::dumpPretty() const {
    if (!size())
      return;
    ASTContext* C = 0;
    if (m_WrapperFD)
      C = &(m_WrapperFD->getASTContext());
    if (!getFirstDecl().isNull())
      C = &(getFirstDecl().getSingleDecl()->getASTContext());

    PrintingPolicy Policy(C->getLangOpts());
    print(llvm::errs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::print(llvm::raw_ostream& Out, const PrintingPolicy& Policy,
                          unsigned Indent, bool PrintInstantiation) const {
    int nestedT = 0;
    for (const_iterator I = decls_begin(), E = decls_end(); I != E; ++I) {
      if (I->m_DGR.isNull()) {
        assert(hasNestedTransactions() && "DGR is null even if no nesting?");
        // print the nested decl
        Out<< "\n";
        Out<<"+====================================================+\n";
        Out<<"        Nested Transaction" << nestedT << "           \n";
        Out<<"+====================================================+\n";
        (*m_NestedTransactions)[nestedT++]->print(Out, Policy, Indent,
                                                  PrintInstantiation);
        Out<< "\n";
        Out<<"+====================================================+\n";
        Out<<"          End Transaction" << nestedT << "            \n";
        Out<<"+====================================================+\n";
      }
      for (DeclGroupRef::const_iterator J = I->m_DGR.begin(),
             L = I->m_DGR.end(); J != L; ++J)
        if (*J)
          (*J)->print(Out, Policy, Indent, PrintInstantiation);
        else
          Out << "<<NULL DECL>>";
    }
  }

  void Transaction::printStructure(size_t nindent) const {
    static const char* const stateNames[kNumStates] = {
      "Collecting",
      "kCompleted",
      "Committing",
      "RolledBack",
      "RolledBackWithErrors",
      "Committed"
    };
    std::string indent(nindent, ' ');
    llvm::errs() << indent << "Transaction @" << this << ": \n";
    for (const_nested_iterator I = nested_begin(), E = nested_end();
         I != E; ++I) {
      (*I)->printStructure(nindent + 3);
    }
    llvm::errs() << indent << " state: " << stateNames[getState()] << ", "
                 << size() << " decl groups, ";
    if (hasNestedTransactions())
      llvm::errs() << m_NestedTransactions->size();
    else
      llvm::errs() << "0";

    llvm::errs() << " nested transactions\n"
                 << indent << " wrapper: " << m_WrapperFD
                 << ", parent: " << m_Parent
                 << ", next: " << m_Next << "\n";
  }

} // end namespace cling
<commit_msg>Move the late creation of the container up. Implement sanity check for decl uniqueness when in debug mode.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vvasielv@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/Transaction.h"

#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/PrettyPrinter.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;

namespace cling {

  Transaction::~Transaction() {
    if (hasNestedTransactions())
      for (size_t i = 0; i < m_NestedTransactions->size(); ++i) {
        assert((*m_NestedTransactions)[i]->getState() == kCommitted
               && "All nested transactions must be committed!");
        delete (*m_NestedTransactions)[i];
      }
  }

  void Transaction::removeNestedTransaction(Transaction* nested) {
    assert(hasNestedTransactions() && "Does not contain nested transactions");
    int nestedPos = -1;
    for (size_t i = 0; i < m_NestedTransactions->size(); ++i)
      if ((*m_NestedTransactions)[i] == nested) {
        nestedPos = i;
        break;
      }
    assert(nestedPos > -1 && "Not found!?");
    m_NestedTransactions->erase(m_NestedTransactions->begin() + nestedPos);
    // We need to remove the marker too.
    for (size_t i = 0; i < size(); ++i) {
      if ((*this)[i].m_DGR.isNull())
        --nestedPos;
      if (!nestedPos) {
        erase(i);
        break;
      }
    }
  }

  void Transaction::reset() {
    assert(empty() && "The transaction must be empty.");
    if (Transaction* parent = getParent())
      parent->removeNestedTransaction(this);
    m_Parent = 0;
    m_State = kCollecting;
    m_IssuedDiags = kNone;
    m_Opts = CompilationOptions();
    //m_Module = 0; <- NOTE: we want to reuse the empty module
    m_WrapperFD = 0;
    m_Next = 0;
  }

  void Transaction::append(DelayCallInfo DCI) {
    assert(!DCI.m_DGR.isNull() && "Appending null DGR?!");
    assert(getState() == kCollecting
           && "Cannot append declarations in current state.");
    forceAppend(DCI);
  }

  void Transaction::forceAppend(DelayCallInfo DCI) {
    assert(!DCI.m_DGR.isNull() && "Appending null DGR?!");

    // Lazy create the container on first append.
    if (!m_DeclQueue)
      m_DeclQueue.reset(new DeclQueue());

#ifdef NDEBUG
    // Check for duplicates
    for (size_t i = 0, e = m_DeclQueue->size(); i < e; ++i)
      assert((*m_DeclsQueue)[i] != DCI && "Duplicates?!");
#endif

    if (!DCI.m_DGR.isNull() && getState() == kCommitting) {
      // We are committing and getting new decls in.
      // Move them into a sub transaction that will be processed
      // recursively at the end of of commitTransaction.
      Transaction* subTransactionWhileCommitting = 0;
      if (hasNestedTransactions()
          && m_NestedTransactions->back()->getState() == kCollecting)
        subTransactionWhileCommitting = m_NestedTransactions->back();
      else {
        // FIXME: is this correct (Axel says "yes")
        CompilationOptions Opts(getCompilationOpts());
        Opts.DeclarationExtraction = 0;
        Opts.ValuePrinting = CompilationOptions::VPDisabled;
        Opts.ResultEvaluation = 0;
        Opts.DynamicScoping = 0;
        subTransactionWhileCommitting = new Transaction(Opts);
        addNestedTransaction(subTransactionWhileCommitting);
      }
      subTransactionWhileCommitting->append(DCI);
      return;
    }
    bool checkForWrapper = !m_WrapperFD;
    assert(checkForWrapper = true && "Check for wrappers with asserts");
    // register the wrapper if any.
    if (checkForWrapper && !DCI.m_DGR.isNull() && DCI.m_DGR.isSingleDecl()) {
      if (FunctionDecl* FD = dyn_cast<FunctionDecl>(DCI.m_DGR.getSingleDecl()))
        if (utils::Analyze::IsWrapper(FD)) {
          assert(!m_WrapperFD && "Two wrappers in one transaction?");
          m_WrapperFD = FD;
        }
    }
    m_DeclQueue->push_back(DCI);
  }

  void Transaction::append(clang::DeclGroupRef DGR) {
    append(DelayCallInfo(DGR, kCCIHandleTopLevelDecl));
  }

  void Transaction::append(Decl* D) {
    append(DeclGroupRef(D));
  }

  void Transaction::forceAppend(Decl* D) {
    forceAppend(DelayCallInfo(DeclGroupRef(D), kCCIHandleTopLevelDecl));
  }

  void Transaction::erase(size_t pos) {
    assert(!empty() && "Erasing from an empty transaction.");
    m_DeclQueue->erase(decls_begin() + pos);
  }

  void Transaction::dump() const {
    if (!size())
      return;

    ASTContext& C = getFirstDecl().getSingleDecl()->getASTContext();
    PrintingPolicy Policy = C.getPrintingPolicy();
    print(llvm::errs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::dumpPretty() const {
    if (!size())
      return;
    ASTContext* C = 0;
    if (m_WrapperFD)
      C = &(m_WrapperFD->getASTContext());
    if (!getFirstDecl().isNull())
      C = &(getFirstDecl().getSingleDecl()->getASTContext());

    PrintingPolicy Policy(C->getLangOpts());
    print(llvm::errs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::print(llvm::raw_ostream& Out, const PrintingPolicy& Policy,
                          unsigned Indent, bool PrintInstantiation) const {
    int nestedT = 0;
    for (const_iterator I = decls_begin(), E = decls_end(); I != E; ++I) {
      if (I->m_DGR.isNull()) {
        assert(hasNestedTransactions() && "DGR is null even if no nesting?");
        // print the nested decl
        Out<< "\n";
        Out<<"+====================================================+\n";
        Out<<"        Nested Transaction" << nestedT << "           \n";
        Out<<"+====================================================+\n";
        (*m_NestedTransactions)[nestedT++]->print(Out, Policy, Indent,
                                                  PrintInstantiation);
        Out<< "\n";
        Out<<"+====================================================+\n";
        Out<<"          End Transaction" << nestedT << "            \n";
        Out<<"+====================================================+\n";
      }
      for (DeclGroupRef::const_iterator J = I->m_DGR.begin(),
             L = I->m_DGR.end(); J != L; ++J)
        if (*J)
          (*J)->print(Out, Policy, Indent, PrintInstantiation);
        else
          Out << "<<NULL DECL>>";
    }
  }

  void Transaction::printStructure(size_t nindent) const {
    static const char* const stateNames[kNumStates] = {
      "Collecting",
      "kCompleted",
      "Committing",
      "RolledBack",
      "RolledBackWithErrors",
      "Committed"
    };
    std::string indent(nindent, ' ');
    llvm::errs() << indent << "Transaction @" << this << ": \n";
    for (const_nested_iterator I = nested_begin(), E = nested_end();
         I != E; ++I) {
      (*I)->printStructure(nindent + 3);
    }
    llvm::errs() << indent << " state: " << stateNames[getState()] << ", "
                 << size() << " decl groups, ";
    if (hasNestedTransactions())
      llvm::errs() << m_NestedTransactions->size();
    else
      llvm::errs() << "0";

    llvm::errs() << " nested transactions\n"
                 << indent << " wrapper: " << m_WrapperFD
                 << ", parent: " << m_Parent
                 << ", next: " << m_Next << "\n";
  }

} // end namespace cling
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vvasielv@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/Transaction.h"

#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/PrettyPrinter.h"

using namespace clang;

namespace cling {

  Transaction::~Transaction() {
    for (size_t i = 0; i < m_NestedTransactions.size(); ++i)
      delete m_NestedTransactions[i];
  }

  void Transaction::appendUnique(DeclGroupRef DGR) {
    for (const_iterator I = decls_begin(), E = decls_end(); I != E; ++I) {
      if (DGR.isNull() || (*I).getAsOpaquePtr() == DGR.getAsOpaquePtr())
        return;
    }
    // register the wrapper if any.
    if (DGR.isSingleDecl()) {
      if (FunctionDecl* FD = dyn_cast<FunctionDecl>(DGR.getSingleDecl()))
        if (utils::Analyze::IsWrapper(FD)) {
          assert(!m_WrapperFD && "Two wrappers in one transaction?");
          m_WrapperFD = FD;
        }
    }
    m_DeclQueue.push_back(DGR);
  }

  void Transaction::dump() const {
    if (!size())
      return;

    ASTContext& C = getFirstDecl().getSingleDecl()->getASTContext();
    PrintingPolicy Policy = C.getPrintingPolicy();
    Policy.DumpSourceManager = &C.getSourceManager();
    print(llvm::outs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::dumpPretty() const {
    if (!size())
      return;

    ASTContext& C = getFirstDecl().getSingleDecl()->getASTContext();
    PrintingPolicy Policy(C.getLangOpts());
    print(llvm::outs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::print(llvm::raw_ostream& Out, const PrintingPolicy& Policy,
                          unsigned Indent, bool PrintInstantiation) const {
    int nestedT = 0;
    for (const_iterator I = decls_begin(), E = decls_end(); I != E; ++I) {
      if (I->isNull()) {
        assert(hasNestedTransactions() && "DGR is null even if no nesting?");
        // print the nested decl
        Out<<"+====================================================+\n";
        Out<<"|       Nested Transaction" << nestedT << "          |\n";
        Out<<"+====================================================+\n";
        m_NestedTransactions[nestedT++]->print(Out, Policy, Indent,
                                               PrintInstantiation);
        Out<<"+====================================================+\n";
        Out<<"|         End Transaction" << nestedT << "           |\n";
        Out<<"+====================================================+\n";
      }
      for (DeclGroupRef::const_iterator J = I->begin(), L = I->end();J != L;++J)
        if (*J)
          (*J)->print(Out, Policy, Indent, PrintInstantiation);
        else
          Out << "<<NULL DECL>>";
    }
  }

} // end namespace cling
<commit_msg>If the first decl happens to be null ask the wrapper function for the ASTContext.<commit_after>//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author:  Vassil Vassilev <vvasielv@cern.ch>
//------------------------------------------------------------------------------

#include "cling/Interpreter/Transaction.h"

#include "cling/Utils/AST.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/PrettyPrinter.h"

using namespace clang;

namespace cling {

  Transaction::~Transaction() {
    for (size_t i = 0; i < m_NestedTransactions.size(); ++i)
      delete m_NestedTransactions[i];
  }

  void Transaction::appendUnique(DeclGroupRef DGR) {
    for (const_iterator I = decls_begin(), E = decls_end(); I != E; ++I) {
      if (DGR.isNull() || (*I).getAsOpaquePtr() == DGR.getAsOpaquePtr())
        return;
    }
    // register the wrapper if any.
    if (DGR.isSingleDecl()) {
      if (FunctionDecl* FD = dyn_cast<FunctionDecl>(DGR.getSingleDecl()))
        if (utils::Analyze::IsWrapper(FD)) {
          assert(!m_WrapperFD && "Two wrappers in one transaction?");
          m_WrapperFD = FD;
        }
    }
    m_DeclQueue.push_back(DGR);
  }

  void Transaction::dump() const {
    if (!size())
      return;

    ASTContext& C = getFirstDecl().getSingleDecl()->getASTContext();
    PrintingPolicy Policy = C.getPrintingPolicy();
    Policy.DumpSourceManager = &C.getSourceManager();
    print(llvm::outs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::dumpPretty() const {
    if (!size())
      return;
    ASTContext* C;
    if (m_WrapperFD)
      C = &(m_WrapperFD->getASTContext());
    if (!getFirstDecl().isNull())
      C = &(getFirstDecl().getSingleDecl()->getASTContext());

    PrintingPolicy Policy(C->getLangOpts());
    print(llvm::outs(), Policy, /*Indent*/0, /*PrintInstantiation*/true);
  }

  void Transaction::print(llvm::raw_ostream& Out, const PrintingPolicy& Policy,
                          unsigned Indent, bool PrintInstantiation) const {
    int nestedT = 0;
    for (const_iterator I = decls_begin(), E = decls_end(); I != E; ++I) {
      if (I->isNull()) {
        assert(hasNestedTransactions() && "DGR is null even if no nesting?");
        // print the nested decl
        Out<< "\n";
        Out<<"+====================================================+\n";
        Out<<"        Nested Transaction" << nestedT << "           \n";
        Out<<"+====================================================+\n";
        m_NestedTransactions[nestedT++]->print(Out, Policy, Indent,
                                               PrintInstantiation);
        Out<< "\n";
        Out<<"+====================================================+\n";
        Out<<"          End Transaction" << nestedT << "            \n";
        Out<<"+====================================================+\n";
      }
      for (DeclGroupRef::const_iterator J = I->begin(), L = I->end();J != L;++J)
        if (*J)
          (*J)->print(Out, Policy, Indent, PrintInstantiation);
        else
          Out << "<<NULL DECL>>";
    }
  }

} // end namespace cling
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include <config_folders.h>

#include <pyuno/pyuno.hxx>

#include <osl/process.h>
#include <osl/file.hxx>
#include <osl/thread.h>

#include <rtl/ustrbuf.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/bootstrap.hxx>

#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/factory.hxx>

// apparently PATH_MAX is not standard and not defined by MSVC
#ifndef PATH_MAX
#ifdef _MAX_PATH
#define PATH_MAX _MAX_PATH
#else
#ifdef MAX_PATH
#define PATH_MAX MAX_PATH
#else
#error no PATH_MAX
#endif
#endif
#endif

using pyuno::PyRef;
using pyuno::Runtime;
using pyuno::PyThreadAttach;

using com::sun::star::registry::XRegistryKey;
using com::sun::star::uno::Reference;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::XComponentContext;
using com::sun::star::uno::RuntimeException;

namespace pyuno_loader
{

static void raiseRuntimeExceptionWhenNeeded() throw ( RuntimeException )
{
    if( PyErr_Occurred() )
    {
        PyRef excType, excValue, excTraceback;
        PyErr_Fetch( (PyObject **)&excType, (PyObject**)&excValue,(PyObject**)&excTraceback);
        Runtime runtime;
        com::sun::star::uno::Any a = runtime.extractUnoException( excType, excValue, excTraceback );
        OUStringBuffer buf;
        buf.appendAscii( "python-loader:" );
        if( a.hasValue() )
            buf.append( ((com::sun::star::uno::Exception *)a.getValue())->Message );
        throw RuntimeException( buf.makeStringAndClear() );
    }
}

static PyRef getLoaderModule() throw( RuntimeException )
{
    PyRef module(
        PyImport_ImportModule( "pythonloader" ),
        SAL_NO_ACQUIRE );
    raiseRuntimeExceptionWhenNeeded();
    if( !module.is() )
    {
        throw RuntimeException( "pythonloader: Couldn't load pythonloader module" );
    }
    return PyRef( PyModule_GetDict( module.get() ));
}

static PyRef getObjectFromLoaderModule( const char * func )
    throw ( RuntimeException )
{
    PyRef object( PyDict_GetItemString(getLoaderModule().get(), (char*)func ) );
    if( !object.is() )
    {
        OUStringBuffer buf;
        buf.appendAscii( "pythonloader: couldn't find core element pythonloader." );
        buf.appendAscii( func );
        throw RuntimeException(buf.makeStringAndClear());
    }
    return object;
}

OUString getImplementationName()
{
    return OUString( "org.openoffice.comp.pyuno.Loader" );
}

Sequence< OUString > getSupportedServiceNames()
{
    OUString serviceName( "com.sun.star.loader.Python" );
    return Sequence< OUString > ( &serviceName, 1 );
}

static void setPythonHome ( const OUString & pythonHome )
{
    OUString systemPythonHome;
    osl_getSystemPathFromFileURL( pythonHome.pData, &(systemPythonHome.pData) );
    OString o = OUStringToOString( systemPythonHome, osl_getThreadTextEncoding() );
#if PY_MAJOR_VERSION >= 3
    // static because Py_SetPythonHome just copies the "wide" pointer
    static wchar_t wide[PATH_MAX + 1];
    size_t len = mbstowcs(wide, o.pData->buffer, PATH_MAX + 1);
    if(len == (size_t)-1)
    {
        PyErr_SetString(PyExc_SystemError, "invalid multibyte sequence in python home path");
        return;
    }
    if(len == PATH_MAX + 1)
    {
        PyErr_SetString(PyExc_SystemError, "python home path is too long");
        return;
    }
    Py_SetPythonHome(wide);
#else
    rtl_string_acquire(o.pData); // increase reference count
    Py_SetPythonHome(o.pData->buffer);
#endif
}

static void prependPythonPath( const OUString & pythonPathBootstrap )
{
    OUStringBuffer bufPYTHONPATH( 256 );
    sal_Int32 nIndex = 0;
    while( true )
    {
        sal_Int32 nNew = pythonPathBootstrap.indexOf( ' ', nIndex );
        OUString fileUrl;
        if( nNew == -1 )
        {
            fileUrl = pythonPathBootstrap.copy(nIndex);
        }
        else
        {
            fileUrl = pythonPathBootstrap.copy(nIndex, nNew - nIndex);
        }
        OUString systemPath;
        osl_getSystemPathFromFileURL( fileUrl.pData, &(systemPath.pData) );
        bufPYTHONPATH.append( systemPath );
        bufPYTHONPATH.append( static_cast<sal_Unicode>(SAL_PATHSEPARATOR) );
        if( nNew == -1 )
            break;
        nIndex = nNew + 1;
    }
    const char * oldEnv = getenv( "PYTHONPATH");
    if( oldEnv )
        bufPYTHONPATH.append( OUString(oldEnv, strlen(oldEnv), osl_getThreadTextEncoding()) );

    OUString envVar("PYTHONPATH");
    OUString envValue(bufPYTHONPATH.makeStringAndClear());
    osl_setEnvironment(envVar.pData, envValue.pData);
}

Reference< XInterface > CreateInstance( const Reference< XComponentContext > & ctx )
{
    Reference< XInterface > ret;

    if( ! Py_IsInitialized() )
    {
        OUString pythonPath;
        OUString pythonHome;
        OUString path( "$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("pythonloader.uno" ));
        rtl::Bootstrap::expandMacros(path); //TODO: detect failure
        rtl::Bootstrap bootstrap(path);

        // look for pythonhome
        bootstrap.getFrom( OUString( "PYUNO_LOADER_PYTHONHOME"), pythonHome );
        bootstrap.getFrom( OUString( "PYUNO_LOADER_PYTHONPATH" ) , pythonPath );

        // pythonhome+pythonpath must be set before Py_Initialize(), otherwise there appear warning on the console
        // sadly, there is no api for setting the pythonpath, we have to use the environment variable
        if( !pythonHome.isEmpty() )
            setPythonHome( pythonHome );

        if( !pythonPath.isEmpty() )
            prependPythonPath( pythonPath );

#ifdef WNT
    //extend PATH under windows to include the branddir/program so ssl libs will be found
    //for use by terminal mailmerge dependency _ssl.pyd
    OUString sEnvName("PATH");
    OUString sPath;
    osl_getEnvironment(sEnvName.pData, &sPath.pData);
    OUString sBrandLocation("$BRAND_BASE_DIR/program");
    rtl::Bootstrap::expandMacros(sBrandLocation);
    osl::FileBase::getSystemPathFromFileURL(sBrandLocation, sBrandLocation);
    sPath = OUStringBuffer(sPath).
        append(static_cast<sal_Unicode>(SAL_PATHSEPARATOR)).
        append(sBrandLocation).makeStringAndClear();
    osl_setEnvironment(sEnvName.pData, sPath.pData);
#endif

#if PY_MAJOR_VERSION >= 3
        PyImport_AppendInittab( (char*)"pyuno", PyInit_pyuno );
#else
        PyImport_AppendInittab( (char*)"pyuno", initpyuno );
#endif
        // initialize python
        Py_Initialize();
        PyEval_InitThreads();

        PyThreadState *tstate = PyThreadState_Get();
        PyEval_ReleaseThread( tstate );
        // This tstate is never used again, so delete it here.
        // This prevents an assertion in PyThreadState_Swap on the
        // PyThreadAttach below.
        PyThreadState_Delete(tstate);
    }

    PyThreadAttach attach( PyInterpreterState_Head() );
    {
        if( ! Runtime::isInitialized() )
        {
            Runtime::initialize( ctx );
        }
        Runtime runtime;

        PyRef pyCtx = runtime.any2PyObject(
            com::sun::star::uno::makeAny( ctx ) );

        PyRef clazz = getObjectFromLoaderModule( "Loader" );
        PyRef args ( PyTuple_New( 1 ), SAL_NO_ACQUIRE );
        PyTuple_SetItem( args.get(), 0 , pyCtx.getAcquired() );
        PyRef pyInstance( PyObject_CallObject( clazz.get() , args.get() ), SAL_NO_ACQUIRE );
        runtime.pyObject2Any( pyInstance ) >>= ret;
    }
    return ret;
}

}

static const struct cppu::ImplementationEntry g_entries[] =
{
    {
        pyuno_loader::CreateInstance, pyuno_loader::getImplementationName,
        pyuno_loader::getSupportedServiceNames, cppu::createSingleComponentFactory,
        0 , 0
    },
    { 0, 0, 0, 0, 0, 0 }
};

extern "C"
{

SAL_DLLPUBLIC_EXPORT void * SAL_CALL pythonloader_component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    return cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#982751 Dereference null return value<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include <config_folders.h>

#include <pyuno/pyuno.hxx>

#include <osl/process.h>
#include <osl/file.hxx>
#include <osl/thread.h>

#include <rtl/ustrbuf.hxx>
#include <rtl/strbuf.hxx>
#include <rtl/bootstrap.hxx>

#include <cppuhelper/implementationentry.hxx>
#include <cppuhelper/factory.hxx>

// apparently PATH_MAX is not standard and not defined by MSVC
#ifndef PATH_MAX
#ifdef _MAX_PATH
#define PATH_MAX _MAX_PATH
#else
#ifdef MAX_PATH
#define PATH_MAX MAX_PATH
#else
#error no PATH_MAX
#endif
#endif
#endif

using pyuno::PyRef;
using pyuno::NOT_NULL;
using pyuno::Runtime;
using pyuno::PyThreadAttach;

using com::sun::star::registry::XRegistryKey;
using com::sun::star::uno::Reference;
using com::sun::star::uno::XInterface;
using com::sun::star::uno::Sequence;
using com::sun::star::uno::XComponentContext;
using com::sun::star::uno::RuntimeException;

namespace pyuno_loader
{

static void raiseRuntimeExceptionWhenNeeded() throw ( RuntimeException )
{
    if( PyErr_Occurred() )
    {
        PyRef excType, excValue, excTraceback;
        PyErr_Fetch( (PyObject **)&excType, (PyObject**)&excValue,(PyObject**)&excTraceback);
        Runtime runtime;
        com::sun::star::uno::Any a = runtime.extractUnoException( excType, excValue, excTraceback );
        OUStringBuffer buf;
        buf.appendAscii( "python-loader:" );
        if( a.hasValue() )
            buf.append( ((com::sun::star::uno::Exception *)a.getValue())->Message );
        throw RuntimeException( buf.makeStringAndClear() );
    }
}

static PyRef getLoaderModule() throw( RuntimeException )
{
    PyRef module(
        PyImport_ImportModule( "pythonloader" ),
        SAL_NO_ACQUIRE );
    raiseRuntimeExceptionWhenNeeded();
    if( !module.is() )
    {
        throw RuntimeException( "pythonloader: Couldn't load pythonloader module" );
    }
    return PyRef( PyModule_GetDict( module.get() ));
}

static PyRef getObjectFromLoaderModule( const char * func )
    throw ( RuntimeException )
{
    PyRef object( PyDict_GetItemString(getLoaderModule().get(), (char*)func ) );
    if( !object.is() )
    {
        OUStringBuffer buf;
        buf.appendAscii( "pythonloader: couldn't find core element pythonloader." );
        buf.appendAscii( func );
        throw RuntimeException(buf.makeStringAndClear());
    }
    return object;
}

OUString getImplementationName()
{
    return OUString( "org.openoffice.comp.pyuno.Loader" );
}

Sequence< OUString > getSupportedServiceNames()
{
    OUString serviceName( "com.sun.star.loader.Python" );
    return Sequence< OUString > ( &serviceName, 1 );
}

static void setPythonHome ( const OUString & pythonHome )
{
    OUString systemPythonHome;
    osl_getSystemPathFromFileURL( pythonHome.pData, &(systemPythonHome.pData) );
    OString o = OUStringToOString( systemPythonHome, osl_getThreadTextEncoding() );
#if PY_MAJOR_VERSION >= 3
    // static because Py_SetPythonHome just copies the "wide" pointer
    static wchar_t wide[PATH_MAX + 1];
    size_t len = mbstowcs(wide, o.pData->buffer, PATH_MAX + 1);
    if(len == (size_t)-1)
    {
        PyErr_SetString(PyExc_SystemError, "invalid multibyte sequence in python home path");
        return;
    }
    if(len == PATH_MAX + 1)
    {
        PyErr_SetString(PyExc_SystemError, "python home path is too long");
        return;
    }
    Py_SetPythonHome(wide);
#else
    rtl_string_acquire(o.pData); // increase reference count
    Py_SetPythonHome(o.pData->buffer);
#endif
}

static void prependPythonPath( const OUString & pythonPathBootstrap )
{
    OUStringBuffer bufPYTHONPATH( 256 );
    sal_Int32 nIndex = 0;
    while( true )
    {
        sal_Int32 nNew = pythonPathBootstrap.indexOf( ' ', nIndex );
        OUString fileUrl;
        if( nNew == -1 )
        {
            fileUrl = pythonPathBootstrap.copy(nIndex);
        }
        else
        {
            fileUrl = pythonPathBootstrap.copy(nIndex, nNew - nIndex);
        }
        OUString systemPath;
        osl_getSystemPathFromFileURL( fileUrl.pData, &(systemPath.pData) );
        bufPYTHONPATH.append( systemPath );
        bufPYTHONPATH.append( static_cast<sal_Unicode>(SAL_PATHSEPARATOR) );
        if( nNew == -1 )
            break;
        nIndex = nNew + 1;
    }
    const char * oldEnv = getenv( "PYTHONPATH");
    if( oldEnv )
        bufPYTHONPATH.append( OUString(oldEnv, strlen(oldEnv), osl_getThreadTextEncoding()) );

    OUString envVar("PYTHONPATH");
    OUString envValue(bufPYTHONPATH.makeStringAndClear());
    osl_setEnvironment(envVar.pData, envValue.pData);
}

Reference< XInterface > CreateInstance( const Reference< XComponentContext > & ctx )
{
    Reference< XInterface > ret;

    if( ! Py_IsInitialized() )
    {
        OUString pythonPath;
        OUString pythonHome;
        OUString path( "$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("pythonloader.uno" ));
        rtl::Bootstrap::expandMacros(path); //TODO: detect failure
        rtl::Bootstrap bootstrap(path);

        // look for pythonhome
        bootstrap.getFrom( OUString( "PYUNO_LOADER_PYTHONHOME"), pythonHome );
        bootstrap.getFrom( OUString( "PYUNO_LOADER_PYTHONPATH" ) , pythonPath );

        // pythonhome+pythonpath must be set before Py_Initialize(), otherwise there appear warning on the console
        // sadly, there is no api for setting the pythonpath, we have to use the environment variable
        if( !pythonHome.isEmpty() )
            setPythonHome( pythonHome );

        if( !pythonPath.isEmpty() )
            prependPythonPath( pythonPath );

#ifdef WNT
    //extend PATH under windows to include the branddir/program so ssl libs will be found
    //for use by terminal mailmerge dependency _ssl.pyd
    OUString sEnvName("PATH");
    OUString sPath;
    osl_getEnvironment(sEnvName.pData, &sPath.pData);
    OUString sBrandLocation("$BRAND_BASE_DIR/program");
    rtl::Bootstrap::expandMacros(sBrandLocation);
    osl::FileBase::getSystemPathFromFileURL(sBrandLocation, sBrandLocation);
    sPath = OUStringBuffer(sPath).
        append(static_cast<sal_Unicode>(SAL_PATHSEPARATOR)).
        append(sBrandLocation).makeStringAndClear();
    osl_setEnvironment(sEnvName.pData, sPath.pData);
#endif

#if PY_MAJOR_VERSION >= 3
        PyImport_AppendInittab( (char*)"pyuno", PyInit_pyuno );
#else
        PyImport_AppendInittab( (char*)"pyuno", initpyuno );
#endif
        // initialize python
        Py_Initialize();
        PyEval_InitThreads();

        PyThreadState *tstate = PyThreadState_Get();
        PyEval_ReleaseThread( tstate );
        // This tstate is never used again, so delete it here.
        // This prevents an assertion in PyThreadState_Swap on the
        // PyThreadAttach below.
        PyThreadState_Delete(tstate);
    }

    PyThreadAttach attach( PyInterpreterState_Head() );
    {
        if( ! Runtime::isInitialized() )
        {
            Runtime::initialize( ctx );
        }
        Runtime runtime;

        PyRef pyCtx = runtime.any2PyObject(
            com::sun::star::uno::makeAny( ctx ) );

        PyRef clazz = getObjectFromLoaderModule( "Loader" );
        PyRef args ( PyTuple_New( 1 ), SAL_NO_ACQUIRE, NOT_NULL );
        PyTuple_SetItem( args.get(), 0 , pyCtx.getAcquired() );
        PyRef pyInstance( PyObject_CallObject( clazz.get() , args.get() ), SAL_NO_ACQUIRE );
        runtime.pyObject2Any( pyInstance ) >>= ret;
    }
    return ret;
}

}

static const struct cppu::ImplementationEntry g_entries[] =
{
    {
        pyuno_loader::CreateInstance, pyuno_loader::getImplementationName,
        pyuno_loader::getSupportedServiceNames, cppu::createSingleComponentFactory,
        0 , 0
    },
    { 0, 0, 0, 0, 0, 0 }
};

extern "C"
{

SAL_DLLPUBLIC_EXPORT void * SAL_CALL pythonloader_component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    return cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );
}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>#include <agency/future.hpp>
#include <agency/new_executor_traits.hpp>
#include <iostream>
#include <cassert>

#include "test_executors.hpp"

template<class Executor>
void test()
{
  using executor_type = Executor;

  size_t n = 1;

  auto int_ready   = agency::detail::make_ready_future(0);
  auto void_ready  = agency::detail::make_ready_future();

  auto futures = std::make_tuple(std::move(void_ready), std::move(int_ready));

  std::mutex mut;
  executor_type exec;
  std::future<int> fut = agency::new_executor_traits<executor_type>::template when_all_execute_and_select<1>(exec, [&mut](int& x)
  {
    mut.lock();
    x += 1;
    mut.unlock();
  },
  std::move(futures));

  auto got = fut.get();

  assert(got == n);
  assert(exec.valid());
}

int main()
{
  using namespace test_executors;

  test<empty_executor>();
  test<single_agent_when_all_execute_and_select_executor>();
  test<multi_agent_when_all_execute_and_select_executor>();
  test<single_agent_then_execute_executor>();

  test<multi_agent_execute_returning_user_defined_container_executor>();
  test<multi_agent_execute_returning_default_container_executor>();
  test<multi_agent_execute_returning_void_executor>();

  test<multi_agent_async_execute_returning_user_defined_container_executor>();

  std::cout << "OK" << std::endl;

  return 0;
}

<commit_msg>Test multi_agent_async_execute_returning_default_container_executor with test_single_agent_when_all_execute_and_select.cpp.<commit_after>#include <agency/future.hpp>
#include <agency/new_executor_traits.hpp>
#include <iostream>
#include <cassert>

#include "test_executors.hpp"

template<class Executor>
void test()
{
  using executor_type = Executor;

  size_t n = 1;

  auto int_ready   = agency::detail::make_ready_future(0);
  auto void_ready  = agency::detail::make_ready_future();

  auto futures = std::make_tuple(std::move(void_ready), std::move(int_ready));

  std::mutex mut;
  executor_type exec;
  std::future<int> fut = agency::new_executor_traits<executor_type>::template when_all_execute_and_select<1>(exec, [&mut](int& x)
  {
    mut.lock();
    x += 1;
    mut.unlock();
  },
  std::move(futures));

  auto got = fut.get();

  assert(got == n);
  assert(exec.valid());
}

int main()
{
  using namespace test_executors;

  test<empty_executor>();
  test<single_agent_when_all_execute_and_select_executor>();
  test<multi_agent_when_all_execute_and_select_executor>();
  test<single_agent_then_execute_executor>();

  test<multi_agent_execute_returning_user_defined_container_executor>();
  test<multi_agent_execute_returning_default_container_executor>();
  test<multi_agent_execute_returning_void_executor>();

  test<multi_agent_async_execute_returning_user_defined_container_executor>();
  test<multi_agent_async_execute_returning_default_container_executor>();

  std::cout << "OK" << std::endl;

  return 0;
}

<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This is really Posix minus Mac. Mac code is in base_paths_mac.mm.

#include "base/base_paths.h"

#include <unistd.h>

#include "base/env_var.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/linux_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/sys_string_conversions.h"

namespace base {

#if defined(OS_LINUX)
const char kSelfExe[] = "/proc/self/exe";
#elif defined(OS_SOLARIS)
const char kSelfExe[] = getexecname();
#elif defined(OS_FREEBSD)
const char kSelfExe[] = "/proc/curproc/file";
#endif

bool PathProviderPosix(int key, FilePath* result) {
  FilePath path;
  switch (key) {
    case base::FILE_EXE:
    case base::FILE_MODULE: {  // TODO(evanm): is this correct?
      char bin_dir[PATH_MAX + 1];
      int bin_dir_size = readlink(kSelfExe, bin_dir, PATH_MAX);
      if (bin_dir_size < 0 || bin_dir_size > PATH_MAX) {
        NOTREACHED() << "Unable to resolve " << kSelfExe << ".";
        return false;
      }
      bin_dir[bin_dir_size] = 0;
      *result = FilePath(bin_dir);
      return true;
    }
    case base::DIR_SOURCE_ROOT:
      // On POSIX, unit tests execute two levels deep from the source root.
      // For example:  sconsbuild/{Debug|Release}/net_unittest
      if (PathService::Get(base::DIR_EXE, &path)) {
        path = path.DirName().DirName();
        if (file_util::PathExists(path.Append("base/base_paths_posix.cc"))) {
          *result = path;
          return true;
        }
      }
      // If that failed (maybe the build output is symlinked to a different
      // drive) try assuming the current directory is the source root.
      if (file_util::GetCurrentDirectory(&path) &&
          file_util::PathExists(path.Append("base/base_paths_posix.cc"))) {
        *result = path;
        return true;
      }
      LOG(ERROR) << "Couldn't find your source root.  "
                 << "Try running from your chromium/src directory.";
      return false;
    case base::DIR_USER_CACHE:
      scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
      FilePath cache_dir(base::GetXDGDirectory(env.get(), "XDG_CACHE_HOME",
                                               ".cache"));
      *result = cache_dir;
      return true;
  }
  return false;
}

}  // namespace base
<commit_msg>Add support for user-defined source root directory.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// This is really Posix minus Mac. Mac code is in base_paths_mac.mm.

#include "base/base_paths.h"

#include <unistd.h>

#include "base/env_var.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/linux_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/scoped_ptr.h"
#include "base/sys_string_conversions.h"

namespace base {

#if defined(OS_LINUX)
const char kSelfExe[] = "/proc/self/exe";
#elif defined(OS_SOLARIS)
const char kSelfExe[] = getexecname();
#elif defined(OS_FREEBSD)
const char kSelfExe[] = "/proc/curproc/file";
#endif

bool PathProviderPosix(int key, FilePath* result) {
  FilePath path;
  switch (key) {
    case base::FILE_EXE:
    case base::FILE_MODULE: {  // TODO(evanm): is this correct?
      char bin_dir[PATH_MAX + 1];
      int bin_dir_size = readlink(kSelfExe, bin_dir, PATH_MAX);
      if (bin_dir_size < 0 || bin_dir_size > PATH_MAX) {
        NOTREACHED() << "Unable to resolve " << kSelfExe << ".";
        return false;
      }
      bin_dir[bin_dir_size] = 0;
      *result = FilePath(bin_dir);
      return true;
    }
    case base::DIR_SOURCE_ROOT: {
      // Allow passing this in the environment, for more flexibility in build
      // tree configurations (sub-project builds, gyp --output_dir, etc.)
      scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
      std::string cr_source_root;
      if (env->GetEnv("CR_SOURCE_ROOT", &cr_source_root)) {
        path = FilePath(cr_source_root);
        if (file_util::PathExists(path.Append("base/base_paths_posix.cc"))) {
          *result = path;
          return true;
        } else {
          LOG(WARNING) << "CR_SOURCE_ROOT is set, but it appears to not "
                       << "point to the correct source root directory.";
        }
      }
      // On POSIX, unit tests execute two levels deep from the source root.
      // For example:  sconsbuild/{Debug|Release}/net_unittest
      if (PathService::Get(base::DIR_EXE, &path)) {
        path = path.DirName().DirName();
        if (file_util::PathExists(path.Append("base/base_paths_posix.cc"))) {
          *result = path;
          return true;
        }
      }
      // If that failed (maybe the build output is symlinked to a different
      // drive) try assuming the current directory is the source root.
      if (file_util::GetCurrentDirectory(&path) &&
          file_util::PathExists(path.Append("base/base_paths_posix.cc"))) {
        *result = path;
        return true;
      }
      LOG(ERROR) << "Couldn't find your source root.  "
                 << "Try running from your chromium/src directory.";
      return false;
    }
    case base::DIR_USER_CACHE:
      scoped_ptr<base::EnvVarGetter> env(base::EnvVarGetter::Create());
      FilePath cache_dir(base::GetXDGDirectory(env.get(), "XDG_CACHE_HOME",
                                               ".cache"));
      *result = cache_dir;
      return true;
  }
  return false;
}

}  // namespace base
<|endoftext|>


<commit_before>/*  This file is part of the Kate project.
 *
 *  Copyright (C) 2012 Christoph Cullmann <cullmann@kde.org>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 */

#include "kateprojectinfoviewindex.h"
#include "kateprojectpluginview.h"

#include <QVBoxLayout>

KateProjectInfoViewIndex::KateProjectInfoViewIndex (KateProjectPluginView *pluginView, KateProject *project)
  : QWidget ()
  , m_pluginView (pluginView)
  , m_project (project)
  , m_lineEdit (new QLineEdit())
  , m_treeView (new QTreeView())
  , m_model (new QStandardItemModel (m_treeView))
{
  /**
   * default style
   */
  m_treeView->setEditTriggers (QAbstractItemView::NoEditTriggers);

  /**
   * attach model
   * kill selection model
   */
  QItemSelectionModel *m = m_treeView->selectionModel();
  m_treeView->setModel (m_model);
  delete m;

  /**
   * layout widget
   */
  QVBoxLayout *layout = new QVBoxLayout;
  layout->setSpacing (0);
  layout->addWidget (m_lineEdit);
  layout->addWidget (m_treeView);
  setLayout (layout);

  /**
   * connect needed signals
   */
  connect (m_lineEdit, SIGNAL(textChanged (const QString &)), this, SLOT(slotTextChanged (const QString &)));
  connect (m_treeView, SIGNAL(clicked (const QModelIndex &)), this, SLOT(slotClicked (const QModelIndex &)));

  /**
   * trigger once search with nothing
   */
  slotTextChanged (QString());
}

KateProjectInfoViewIndex::~KateProjectInfoViewIndex ()
{
}

void KateProjectInfoViewIndex::slotTextChanged (const QString &text)
{
  /**
   * setup model
   */
  m_model->clear();
  m_model->setHorizontalHeaderLabels (QStringList () << "Name" << "Kind" << "File" << "Line");

  /**
   * get results
   */
  if (m_project->projectIndex() && !text.isEmpty())
    m_project->projectIndex()->findMatches (*m_model, text, KateProjectIndex::FindMatches);

  /**
   * resize
   */
  m_treeView->resizeColumnToContents (2);
  m_treeView->resizeColumnToContents (1);
  m_treeView->resizeColumnToContents (0);
}

void KateProjectInfoViewIndex::slotClicked (const QModelIndex &index)
{
  /**
   * get path
   */
  QString filePath = m_model->item (index.row(), 2)->text();
  if (filePath.isEmpty())
    return;

  /**
   * create view
   */
  KTextEditor::View *view = m_pluginView->mainWindow()->openUrl (KUrl::fromPath (filePath));
  if (!view)
    return;

  /**
   * set cursor, if possible
   */
  int line = m_model->item (index.row(), 3)->text().toInt();
  if (line >= 1)
    view->setCursorPosition (KTextEditor::Cursor (line - 1, 0));
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<commit_msg>better sorting possibilities<commit_after>/*  This file is part of the Kate project.
 *
 *  Copyright (C) 2012 Christoph Cullmann <cullmann@kde.org>
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  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
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 */

#include "kateprojectinfoviewindex.h"
#include "kateprojectpluginview.h"

#include <QVBoxLayout>

KateProjectInfoViewIndex::KateProjectInfoViewIndex (KateProjectPluginView *pluginView, KateProject *project)
  : QWidget ()
  , m_pluginView (pluginView)
  , m_project (project)
  , m_lineEdit (new QLineEdit())
  , m_treeView (new QTreeView())
  , m_model (new QStandardItemModel (m_treeView))
{
  /**
   * default style
   */
  m_treeView->setEditTriggers (QAbstractItemView::NoEditTriggers);
  m_model->setHorizontalHeaderLabels (QStringList () << "Name" << "Kind" << "File" << "Line");

  /**
   * attach model
   * kill selection model
   */
  QItemSelectionModel *m = m_treeView->selectionModel();
  m_treeView->setModel (m_model);
  delete m;

  /**
   * layout widget
   */
  QVBoxLayout *layout = new QVBoxLayout;
  layout->setSpacing (0);
  layout->addWidget (m_lineEdit);
  layout->addWidget (m_treeView);
  setLayout (layout);

  /**
   * connect needed signals
   */
  connect (m_lineEdit, SIGNAL(textChanged (const QString &)), this, SLOT(slotTextChanged (const QString &)));
  connect (m_treeView, SIGNAL(clicked (const QModelIndex &)), this, SLOT(slotClicked (const QModelIndex &)));

  /**
   * trigger once search with nothing
   */
  slotTextChanged (QString());
}

KateProjectInfoViewIndex::~KateProjectInfoViewIndex ()
{
}

void KateProjectInfoViewIndex::slotTextChanged (const QString &text)
{
  /**
   * init
   */
  m_treeView->setSortingEnabled (false);
  m_model->setRowCount(0);

  /**
   * get results
   */
  if (m_project->projectIndex() && !text.isEmpty())
    m_project->projectIndex()->findMatches (*m_model, text, KateProjectIndex::FindMatches);

  /**
   * tree view polish ;)
   */
  m_treeView->setSortingEnabled (true);
  m_treeView->resizeColumnToContents (2);
  m_treeView->resizeColumnToContents (1);
  m_treeView->resizeColumnToContents (0);
}

void KateProjectInfoViewIndex::slotClicked (const QModelIndex &index)
{
  /**
   * get path
   */
  QString filePath = m_model->item (index.row(), 2)->text();
  if (filePath.isEmpty())
    return;

  /**
   * create view
   */
  KTextEditor::View *view = m_pluginView->mainWindow()->openUrl (KUrl::fromPath (filePath));
  if (!view)
    return;

  /**
   * set cursor, if possible
   */
  int line = m_model->item (index.row(), 3)->text().toInt();
  if (line >= 1)
    view->setCursorPosition (KTextEditor::Cursor (line - 1, 0));
}

// kate: space-indent on; indent-width 2; replace-tabs on;
<|endoftext|>