/* build_command_runner.c generated by valac 0.18.0.1-c1117, the Vala compiler
 * generated from build_command_runner.vala, do not modify */

/*
 * This file is part of LaTeXila.
 *
 * Copyright © 2010-2012 Sébastien Wilmet
 *
 * LaTeXila 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 3 of the License, or
 * (at your option) any later version.
 *
 * LaTeXila is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Sébastien Wilmet
 */
/* Run a single command line.*/

#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>


#define TYPE_BUILD_COMMAND_RUNNER (build_command_runner_get_type ())
#define BUILD_COMMAND_RUNNER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_BUILD_COMMAND_RUNNER, BuildCommandRunner))
#define BUILD_COMMAND_RUNNER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_BUILD_COMMAND_RUNNER, BuildCommandRunnerClass))
#define IS_BUILD_COMMAND_RUNNER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_BUILD_COMMAND_RUNNER))
#define IS_BUILD_COMMAND_RUNNER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_BUILD_COMMAND_RUNNER))
#define BUILD_COMMAND_RUNNER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_BUILD_COMMAND_RUNNER, BuildCommandRunnerClass))

typedef struct _BuildCommandRunner BuildCommandRunner;
typedef struct _BuildCommandRunnerClass BuildCommandRunnerClass;
typedef struct _BuildCommandRunnerPrivate BuildCommandRunnerPrivate;
#define _g_free0(var) (var = (g_free (var), NULL))
#define _g_io_channel_unref0(var) ((var == NULL) ? NULL : (var = (g_io_channel_unref (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))

struct _BuildCommandRunner {
	GObject parent_instance;
	BuildCommandRunnerPrivate * priv;
};

struct _BuildCommandRunnerClass {
	GObjectClass parent_class;
};

struct _BuildCommandRunnerPrivate {
	gchar** _command_args;
	gint _command_args_length1;
	gint __command_args_size_;
	gchar* _working_directory;
	GPid* _child_pid;
	guint _child_watch_handler;
	GIOChannel* _out_channel;
};


static gpointer build_command_runner_parent_class = NULL;

GType build_command_runner_get_type (void) G_GNUC_CONST;
#define BUILD_COMMAND_RUNNER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_BUILD_COMMAND_RUNNER, BuildCommandRunnerPrivate))
enum  {
	BUILD_COMMAND_RUNNER_DUMMY_PROPERTY
};
BuildCommandRunner* build_command_runner_new (gchar** command_args, int command_args_length1, const gchar* working_directory);
BuildCommandRunner* build_command_runner_construct (GType object_type, gchar** command_args, int command_args_length1, const gchar* working_directory);
static gchar** _vala_array_dup1 (gchar** self, int length);
void build_command_runner_execute_with_output (BuildCommandRunner* self, GError** error);
static void build_command_runner_redirect_stderr_to_stdout (BuildCommandRunner* self);
static void _build_command_runner_redirect_stderr_to_stdout_gspawn_child_setup_func (gpointer self);
static GPid* _g_pid_dup (GPid* self);
static void build_command_runner_on_exit (BuildCommandRunner* self, GPid pid, gint exit_status);
static void _build_command_runner_on_exit_gchild_watch_func (GPid pid, gint status, gpointer self);
void build_command_runner_execute_without_output (BuildCommandRunner* self, GError** error);
void build_command_runner_abort (BuildCommandRunner* self);
gchar* build_command_runner_get_output (BuildCommandRunner* self);
static gchar* build_command_runner_validate_output (BuildCommandRunner* self, const gchar* output);
static void build_command_runner_finalize (GObject* obj);
static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func);
static gint _vala_array_length (gpointer array);


static gchar** _vala_array_dup1 (gchar** self, int length) {
	gchar** result;
	int i;
	result = g_new0 (gchar*, length + 1);
	for (i = 0; i < length; i++) {
		gchar* _tmp0_;
		_tmp0_ = g_strdup (self[i]);
		result[i] = _tmp0_;
	}
	return result;
}


BuildCommandRunner* build_command_runner_construct (GType object_type, gchar** command_args, int command_args_length1, const gchar* working_directory) {
	BuildCommandRunner * self = NULL;
	gchar** _tmp0_;
	gint _tmp0__length1;
	gchar** _tmp1_;
	gint _tmp1__length1;
	const gchar* _tmp2_;
	gchar* _tmp3_;
	g_return_val_if_fail (working_directory != NULL, NULL);
	self = (BuildCommandRunner*) g_object_new (object_type, NULL);
	_tmp0_ = command_args;
	_tmp0__length1 = command_args_length1;
	_tmp1_ = (_tmp0_ != NULL) ? _vala_array_dup1 (_tmp0_, _tmp0__length1) : ((gpointer) _tmp0_);
	_tmp1__length1 = _tmp0__length1;
	self->priv->_command_args = (_vala_array_free (self->priv->_command_args, self->priv->_command_args_length1, (GDestroyNotify) g_free), NULL);
	self->priv->_command_args = _tmp1_;
	self->priv->_command_args_length1 = _tmp1__length1;
	self->priv->__command_args_size_ = self->priv->_command_args_length1;
	_tmp2_ = working_directory;
	_tmp3_ = g_strdup (_tmp2_);
	_g_free0 (self->priv->_working_directory);
	self->priv->_working_directory = _tmp3_;
	return self;
}


BuildCommandRunner* build_command_runner_new (gchar** command_args, int command_args_length1, const gchar* working_directory) {
	return build_command_runner_construct (TYPE_BUILD_COMMAND_RUNNER, command_args, command_args_length1, working_directory);
}


static void _build_command_runner_redirect_stderr_to_stdout_gspawn_child_setup_func (gpointer self) {
	build_command_runner_redirect_stderr_to_stdout (self);
}


static GPid* _g_pid_dup (GPid* self) {
	GPid* dup;
	dup = g_new0 (GPid, 1);
	memcpy (dup, self, sizeof (GPid));
	return dup;
}


static gpointer __g_pid_dup0 (gpointer self) {
	return self ? _g_pid_dup (self) : NULL;
}


static void _build_command_runner_on_exit_gchild_watch_func (GPid pid, gint status, gpointer self) {
	build_command_runner_on_exit (self, pid, status);
}


void build_command_runner_execute_with_output (BuildCommandRunner* self, GError** error) {
	gint std_out = 0;
	const gchar* _tmp0_;
	gchar** _tmp1_;
	gint _tmp1__length1;
	GPid _tmp2_ = 0;
	gint _tmp3_ = 0;
	GPid _tmp4_;
	GPid* _tmp5_;
	GPid* _tmp6_;
	guint _tmp7_ = 0U;
	gint _tmp8_;
	GIOChannel* _tmp9_;
	GIOChannel* _tmp10_;
	GError * _inner_error_ = NULL;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_working_directory;
	_tmp1_ = self->priv->_command_args;
	_tmp1__length1 = self->priv->_command_args_length1;
	g_spawn_async_with_pipes (_tmp0_, _tmp1_, NULL, G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, _build_command_runner_redirect_stderr_to_stdout_gspawn_child_setup_func, self, &_tmp2_, NULL, &_tmp3_, NULL, &_inner_error_);
	_g_free0 (self->priv->_child_pid);
	_tmp4_ = _tmp2_;
	_tmp5_ = __g_pid_dup0 (&_tmp4_);
	self->priv->_child_pid = _tmp5_;
	std_out = _tmp3_;
	if (_inner_error_ != NULL) {
		g_propagate_error (error, _inner_error_);
		return;
	}
	_tmp6_ = self->priv->_child_pid;
	_tmp7_ = g_child_watch_add_full (G_PRIORITY_DEFAULT_IDLE, *_tmp6_, _build_command_runner_on_exit_gchild_watch_func, g_object_ref (self), g_object_unref);
	self->priv->_child_watch_handler = _tmp7_;
	_tmp8_ = std_out;
	_tmp9_ = g_io_channel_unix_new (_tmp8_);
	_g_io_channel_unref0 (self->priv->_out_channel);
	self->priv->_out_channel = _tmp9_;
	_tmp10_ = self->priv->_out_channel;
	g_io_channel_set_encoding (_tmp10_, NULL, &_inner_error_);
	if (_inner_error_ != NULL) {
		g_propagate_error (error, _inner_error_);
		return;
	}
}


void build_command_runner_execute_without_output (BuildCommandRunner* self, GError** error) {
	GSpawnFlags flags;
	const gchar* _tmp0_;
	gchar** _tmp1_;
	gint _tmp1__length1;
	GPid _tmp2_ = 0;
	GPid _tmp3_;
	GPid* _tmp4_;
	GPid* _tmp5_;
	guint _tmp6_ = 0U;
	GError * _inner_error_ = NULL;
	g_return_if_fail (self != NULL);
	flags = ((G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH) | G_SPAWN_STDOUT_TO_DEV_NULL) | G_SPAWN_STDERR_TO_DEV_NULL;
	_tmp0_ = self->priv->_working_directory;
	_tmp1_ = self->priv->_command_args;
	_tmp1__length1 = self->priv->_command_args_length1;
	g_spawn_async (_tmp0_, _tmp1_, NULL, flags, NULL, NULL, &_tmp2_, &_inner_error_);
	_g_free0 (self->priv->_child_pid);
	_tmp3_ = _tmp2_;
	_tmp4_ = __g_pid_dup0 (&_tmp3_);
	self->priv->_child_pid = _tmp4_;
	if (_inner_error_ != NULL) {
		g_propagate_error (error, _inner_error_);
		return;
	}
	_tmp5_ = self->priv->_child_pid;
	_tmp6_ = g_child_watch_add_full (G_PRIORITY_DEFAULT_IDLE, *_tmp5_, _build_command_runner_on_exit_gchild_watch_func, g_object_ref (self), g_object_unref);
	self->priv->_child_watch_handler = _tmp6_;
}


void build_command_runner_abort (BuildCommandRunner* self) {
	GPid* _tmp0_;
	g_return_if_fail (self != NULL);
	_tmp0_ = self->priv->_child_pid;
	if (_tmp0_ != NULL) {
		GPid* _tmp1_;
		_tmp1_ = self->priv->_child_pid;
		kill (*_tmp1_, SIGTERM);
		_g_free0 (self->priv->_child_pid);
		self->priv->_child_pid = NULL;
	}
}


gchar* build_command_runner_get_output (BuildCommandRunner* self) {
	gchar* result = NULL;
	GIOChannel* _tmp0_;
	gchar* _tmp2_;
	gchar* output;
	const gchar* _tmp10_;
	gboolean _tmp11_ = FALSE;
	const gchar* _tmp12_;
	gchar* _tmp13_ = NULL;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = self->priv->_out_channel;
	if (_tmp0_ == NULL) {
		gchar* _tmp1_;
		_tmp1_ = g_strdup ("");
		result = _tmp1_;
		return result;
	}
	_tmp2_ = g_strdup ("");
	output = _tmp2_;
	{
		GIOChannel* _tmp3_;
		gchar* _tmp4_ = NULL;
		_tmp3_ = self->priv->_out_channel;
		g_io_channel_read_to_end (_tmp3_, &_tmp4_, NULL, &_inner_error_);
		_g_free0 (output);
		output = _tmp4_;
		if (_inner_error_ != NULL) {
			if (_inner_error_->domain == G_CONVERT_ERROR) {
				goto __catch0_g_convert_error;
			}
			if (_inner_error_->domain == G_IO_CHANNEL_ERROR) {
				goto __catch0_g_io_channel_error;
			}
			_g_free0 (output);
			g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
			g_clear_error (&_inner_error_);
			return NULL;
		}
	}
	goto __finally0;
	__catch0_g_convert_error:
	{
		GError* e = NULL;
		GError* _tmp5_;
		const gchar* _tmp6_;
		e = _inner_error_;
		_inner_error_ = NULL;
		_tmp5_ = e;
		_tmp6_ = _tmp5_->message;
		g_warning ("build_command_runner.vala:100: Read output: convert error: %s", _tmp6_);
		_g_error_free0 (e);
	}
	goto __finally0;
	__catch0_g_io_channel_error:
	{
		GError* e = NULL;
		GError* _tmp7_;
		const gchar* _tmp8_;
		e = _inner_error_;
		_inner_error_ = NULL;
		_tmp7_ = e;
		_tmp8_ = _tmp7_->message;
		g_warning ("build_command_runner.vala:104: Read output: IO channel error: %s", _tmp8_);
		_g_error_free0 (e);
	}
	__finally0:
	if (_inner_error_ != NULL) {
		_g_free0 (output);
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
		g_clear_error (&_inner_error_);
		return NULL;
	}
	{
		GIOChannel* _tmp9_;
		_tmp9_ = self->priv->_out_channel;
		g_io_channel_shutdown (_tmp9_, FALSE, &_inner_error_);
		if (_inner_error_ != NULL) {
			goto __catch1_g_error;
		}
	}
	goto __finally1;
	__catch1_g_error:
	{
		GError* e = NULL;
		e = _inner_error_;
		_inner_error_ = NULL;
		_g_error_free0 (e);
	}
	__finally1:
	if (_inner_error_ != NULL) {
		_g_free0 (output);
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
		g_clear_error (&_inner_error_);
		return NULL;
	}
	_g_io_channel_unref0 (self->priv->_out_channel);
	self->priv->_out_channel = NULL;
	_tmp10_ = output;
	_tmp11_ = g_utf8_validate (_tmp10_, (gssize) (-1), NULL);
	if (_tmp11_) {
		result = output;
		return result;
	}
	_tmp12_ = output;
	_tmp13_ = build_command_runner_validate_output (self, _tmp12_);
	result = _tmp13_;
	_g_free0 (output);
	return result;
}


static void build_command_runner_on_exit (BuildCommandRunner* self, GPid pid, gint exit_status) {
	gint _tmp0_;
	g_return_if_fail (self != NULL);
	self->priv->_child_watch_handler = (guint) 0;
	_g_free0 (self->priv->_child_pid);
	self->priv->_child_pid = NULL;
	_tmp0_ = exit_status;
	g_signal_emit_by_name (self, "finished", _tmp0_);
}


static void build_command_runner_redirect_stderr_to_stdout (BuildCommandRunner* self) {
	g_return_if_fail (self != NULL);
	dup2 (STDOUT_FILENO, STDERR_FILENO);
}


static gchar* build_command_runner_validate_output (BuildCommandRunner* self, const gchar* output) {
	gchar* result = NULL;
	gchar* _tmp0_;
	gchar* new_output;
	const gchar* _tmp1_;
	gchar** _tmp2_;
	gchar** _tmp3_ = NULL;
	gchar** lines;
	gint lines_length1;
	gint _lines_size_;
	gchar** _tmp4_;
	gint _tmp4__length1;
	GError * _inner_error_ = NULL;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (output != NULL, NULL);
	_tmp0_ = g_strdup ("");
	new_output = _tmp0_;
	_tmp1_ = output;
	_tmp3_ = _tmp2_ = g_strsplit (_tmp1_, "\n", 0);
	lines = _tmp3_;
	lines_length1 = _vala_array_length (_tmp2_);
	_lines_size_ = lines_length1;
	_tmp4_ = lines;
	_tmp4__length1 = lines_length1;
	{
		gchar** line_collection = NULL;
		gint line_collection_length1 = 0;
		gint _line_collection_size_ = 0;
		gint line_it = 0;
		line_collection = _tmp4_;
		line_collection_length1 = _tmp4__length1;
		for (line_it = 0; line_it < _tmp4__length1; line_it = line_it + 1) {
			gchar* _tmp5_;
			gchar* line = NULL;
			_tmp5_ = g_strdup (line_collection[line_it]);
			line = _tmp5_;
			{
				const gchar* _tmp6_;
				gchar* _tmp7_ = NULL;
				gchar* line_utf8;
				const gchar* _tmp8_;
				gboolean _tmp12_ = FALSE;
				const gchar* _tmp13_;
				gboolean _tmp16_;
				_tmp6_ = line;
				_tmp7_ = g_locale_to_utf8 (_tmp6_, (gssize) (-1), NULL, NULL, NULL);
				line_utf8 = _tmp7_;
				_tmp8_ = line_utf8;
				if (_tmp8_ == NULL) {
					{
						const gchar* _tmp9_;
						gchar* _tmp10_ = NULL;
						gchar* _tmp11_;
						_tmp9_ = line;
						_tmp10_ = g_convert (_tmp9_, (gssize) (-1), "UTF-8", "ISO-8859-1", NULL, NULL, &_inner_error_);
						_tmp11_ = _tmp10_;
						if (_inner_error_ != NULL) {
							if (_inner_error_->domain == G_CONVERT_ERROR) {
								goto __catch2_g_convert_error;
							}
							_g_free0 (line_utf8);
							_g_free0 (line);
							lines = (_vala_array_free (lines, lines_length1, (GDestroyNotify) g_free), NULL);
							_g_free0 (new_output);
							g_critical ("file %s: line %d: unexpected error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
							g_clear_error (&_inner_error_);
							return NULL;
						}
						_g_free0 (line_utf8);
						line_utf8 = _tmp11_;
					}
					goto __finally2;
					__catch2_g_convert_error:
					{
						GError* e = NULL;
						e = _inner_error_;
						_inner_error_ = NULL;
						_g_error_free0 (e);
					}
					__finally2:
					if (_inner_error_ != NULL) {
						_g_free0 (line_utf8);
						_g_free0 (line);
						lines = (_vala_array_free (lines, lines_length1, (GDestroyNotify) g_free), NULL);
						_g_free0 (new_output);
						g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code);
						g_clear_error (&_inner_error_);
						return NULL;
					}
				}
				_tmp13_ = line_utf8;
				if (_tmp13_ != NULL) {
					const gchar* _tmp14_;
					gboolean _tmp15_ = FALSE;
					_tmp14_ = line_utf8;
					_tmp15_ = g_utf8_validate (_tmp14_, (gssize) (-1), NULL);
					_tmp12_ = _tmp15_;
				} else {
					_tmp12_ = FALSE;
				}
				_tmp16_ = _tmp12_;
				if (_tmp16_) {
					const gchar* _tmp17_;
					const gchar* _tmp18_;
					gchar* _tmp19_;
					gchar* _tmp20_;
					gchar* _tmp21_;
					_tmp17_ = new_output;
					_tmp18_ = line_utf8;
					_tmp19_ = g_strconcat (_tmp18_, "\n", NULL);
					_tmp20_ = _tmp19_;
					_tmp21_ = g_strconcat (_tmp17_, _tmp20_, NULL);
					_g_free0 (new_output);
					new_output = _tmp21_;
					_g_free0 (_tmp20_);
				} else {
					const gchar* _tmp22_;
					_tmp22_ = line;
					g_warning ("build_command_runner.vala:165: Read output failed: %s", _tmp22_);
				}
				_g_free0 (line_utf8);
				_g_free0 (line);
			}
		}
	}
	result = new_output;
	lines = (_vala_array_free (lines, lines_length1, (GDestroyNotify) g_free), NULL);
	return result;
}


static void build_command_runner_class_init (BuildCommandRunnerClass * klass) {
	build_command_runner_parent_class = g_type_class_peek_parent (klass);
	g_type_class_add_private (klass, sizeof (BuildCommandRunnerPrivate));
	G_OBJECT_CLASS (klass)->finalize = build_command_runner_finalize;
	g_signal_new ("finished", TYPE_BUILD_COMMAND_RUNNER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
}


static void build_command_runner_instance_init (BuildCommandRunner * self) {
	self->priv = BUILD_COMMAND_RUNNER_GET_PRIVATE (self);
	self->priv->_child_pid = NULL;
	self->priv->_child_watch_handler = (guint) 0;
	self->priv->_out_channel = NULL;
}


static void build_command_runner_finalize (GObject* obj) {
	BuildCommandRunner * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_BUILD_COMMAND_RUNNER, BuildCommandRunner);
	self->priv->_command_args = (_vala_array_free (self->priv->_command_args, self->priv->_command_args_length1, (GDestroyNotify) g_free), NULL);
	_g_free0 (self->priv->_working_directory);
	_g_free0 (self->priv->_child_pid);
	_g_io_channel_unref0 (self->priv->_out_channel);
	G_OBJECT_CLASS (build_command_runner_parent_class)->finalize (obj);
}


GType build_command_runner_get_type (void) {
	static volatile gsize build_command_runner_type_id__volatile = 0;
	if (g_once_init_enter (&build_command_runner_type_id__volatile)) {
		static const GTypeInfo g_define_type_info = { sizeof (BuildCommandRunnerClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) build_command_runner_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (BuildCommandRunner), 0, (GInstanceInitFunc) build_command_runner_instance_init, NULL };
		GType build_command_runner_type_id;
		build_command_runner_type_id = g_type_register_static (G_TYPE_OBJECT, "BuildCommandRunner", &g_define_type_info, 0);
		g_once_init_leave (&build_command_runner_type_id__volatile, build_command_runner_type_id);
	}
	return build_command_runner_type_id__volatile;
}


static void _vala_array_destroy (gpointer array, gint array_length, GDestroyNotify destroy_func) {
	if ((array != NULL) && (destroy_func != NULL)) {
		int i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}


static void _vala_array_free (gpointer array, gint array_length, GDestroyNotify destroy_func) {
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}


static gint _vala_array_length (gpointer array) {
	int length;
	length = 0;
	if (array) {
		while (((gpointer*) array)[length]) {
			length++;
		}
	}
	return length;
}



