/*
 * This file was generated automatically by ExtUtils::ParseXS version 3.28 from the
 * contents of GLog.xs. Do not edit this file, edit GLog.xs instead.
 *
 *    ANY CHANGES MADE HERE WILL BE LOST!
 *
 */

#line 1 "GLog.xs"
/*
 * Copyright (C) 2003-2005, 2009, 2012-2013 by the gtk2-perl team (see the
 * file AUTHORS for the full list)
 *
 * 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.1 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; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * $Id$
 */

#include "gperl.h"
#include "gperl-gtypes.h"
#include "gperl-private.h" /* for GPERL_SET_CONTEXT */

#if 0
  "Skipped embedded POD."
#endif
#line 41 "GLog.xs"

#if 0
/* Log level shift offset for user defined
 * log levels (0-7 are used by GLib).
 */
#define G_LOG_LEVEL_USER_SHIFT  (8)

/* GLib log levels that are considered fatal by default */
#define G_LOG_FATAL_MASK        (G_LOG_FLAG_RECURSION | G_LOG_LEVEL_ERROR)
#endif

SV *
newSVGLogLevelFlags (GLogLevelFlags flags)
{
	return gperl_convert_back_flags (GPERL_TYPE_LOG_LEVEL_FLAGS, flags);
}

GLogLevelFlags
SvGLogLevelFlags (SV * sv)
{
	return gperl_convert_flags (GPERL_TYPE_LOG_LEVEL_FLAGS, sv);
}

/* for GLogFunc style, to be invoked by gperl_log_func() below */
static GPerlCallback *
gperl_log_callback_new (SV *log_func, SV *user_data)
{
	GType param_types[3];
	param_types[0] = G_TYPE_STRING;
	param_types[1] = GPERL_TYPE_LOG_LEVEL_FLAGS;
	param_types[2] = G_TYPE_STRING;
	return gperl_callback_new (log_func, user_data,
				   3, param_types, G_TYPE_NONE);
}
static void
gperl_log_func (const gchar   *log_domain,
                GLogLevelFlags log_level,
                const gchar   *message,
                gpointer       user_data)
{
	gperl_callback_invoke ((GPerlCallback *) user_data, NULL,
	                       log_domain, log_level, message);
}

#if GLIB_CHECK_VERSION (2, 6, 0)
/* the GPerlCallback currently installed through
   g_log_set_default_handler(), or NULL if no such */
static GPerlCallback *gperl_log_default_handler_callback = NULL;
G_LOCK_DEFINE_STATIC (gperl_log_default_handler_callback);
#endif

void
gperl_log_handler (const gchar   *log_domain,
                   GLogLevelFlags log_level,
                   const gchar   *message,
                   gpointer       user_data)
{
	char * desc;

	gboolean in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
	gboolean is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
	PERL_UNUSED_VAR (user_data);

	log_level &= G_LOG_LEVEL_MASK;

	if (!message)
		message = "(NULL) message";

	switch (log_level) {
		case G_LOG_LEVEL_CRITICAL: desc = "CRITICAL"; break;
		case G_LOG_LEVEL_ERROR:    desc = "ERROR";    break;
		case G_LOG_LEVEL_WARNING:  desc = "WARNING";  break;
		case G_LOG_LEVEL_MESSAGE:  desc = "Message";  break;
		default: desc = "LOG";
	}

	GPERL_SET_CONTEXT;
	warn ("%s%s%s %s**: %s",
	      (log_domain ? log_domain : ""),
	      (log_domain ? "-" : ""),
	      desc,
	      (in_recursion ? "(recursed) " : ""),
	      message);

	/* the standard log handler calls abort() for G_LOG_LEVEL_ERROR
	 * messages.  this is handy for being able to stop gdb on the
	 * error and get a backtrace.  we originally mapped the error
	 * level stuff to croak(), but this broke the ability to find
	 * these errors in gdb, and didn't stop the script as expected
	 * in the perl debugger.  so, let's preserve the GLib semantics. */
	if (is_fatal)
		/* XXX would be nice to get a perl backtrace here, but
		 * XXX Carp::cluck() doesn't print anything useful here. */
		abort ();
}

#define ALL_LOGS (G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION)

#if 0
  "Skipped embedded POD."
#endif
#line 149 "GLog.xs"
gint
gperl_handle_logs_for (const gchar * log_domain)
{
	return g_log_set_handler (log_domain, ALL_LOGS,
	                          gperl_log_handler, NULL);
}

#if 0
  "Skipped embedded POD."
#endif
#line 159 "GLog.xs"

#line 154 "GLog.c"
#ifndef PERL_UNUSED_VAR
#  define PERL_UNUSED_VAR(var) if (0) var = var
#endif

#ifndef dVAR
#  define dVAR		dNOOP
#endif


/* This stuff is not part of the API! You have been warned. */
#ifndef PERL_VERSION_DECIMAL
#  define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s)
#endif
#ifndef PERL_DECIMAL_VERSION
#  define PERL_DECIMAL_VERSION \
	  PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
#endif
#ifndef PERL_VERSION_GE
#  define PERL_VERSION_GE(r,v,s) \
	  (PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s))
#endif
#ifndef PERL_VERSION_LE
#  define PERL_VERSION_LE(r,v,s) \
	  (PERL_DECIMAL_VERSION <= PERL_VERSION_DECIMAL(r,v,s))
#endif

/* XS_INTERNAL is the explicit static-linkage variant of the default
 * XS macro.
 *
 * XS_EXTERNAL is the same as XS_INTERNAL except it does not include
 * "STATIC", ie. it exports XSUB symbols. You probably don't want that
 * for anything but the BOOT XSUB.
 *
 * See XSUB.h in core!
 */


/* TODO: This might be compatible further back than 5.10.0. */
#if PERL_VERSION_GE(5, 10, 0) && PERL_VERSION_LE(5, 15, 1)
#  undef XS_EXTERNAL
#  undef XS_INTERNAL
#  if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING)
#    define XS_EXTERNAL(name) __declspec(dllexport) XSPROTO(name)
#    define XS_INTERNAL(name) STATIC XSPROTO(name)
#  endif
#  if defined(__SYMBIAN32__)
#    define XS_EXTERNAL(name) EXPORT_C XSPROTO(name)
#    define XS_INTERNAL(name) EXPORT_C STATIC XSPROTO(name)
#  endif
#  ifndef XS_EXTERNAL
#    if defined(HASATTRIBUTE_UNUSED) && !defined(__cplusplus)
#      define XS_EXTERNAL(name) void name(pTHX_ CV* cv __attribute__unused__)
#      define XS_INTERNAL(name) STATIC void name(pTHX_ CV* cv __attribute__unused__)
#    else
#      ifdef __cplusplus
#        define XS_EXTERNAL(name) extern "C" XSPROTO(name)
#        define XS_INTERNAL(name) static XSPROTO(name)
#      else
#        define XS_EXTERNAL(name) XSPROTO(name)
#        define XS_INTERNAL(name) STATIC XSPROTO(name)
#      endif
#    endif
#  endif
#endif

/* perl >= 5.10.0 && perl <= 5.15.1 */


/* The XS_EXTERNAL macro is used for functions that must not be static
 * like the boot XSUB of a module. If perl didn't have an XS_EXTERNAL
 * macro defined, the best we can do is assume XS is the same.
 * Dito for XS_INTERNAL.
 */
#ifndef XS_EXTERNAL
#  define XS_EXTERNAL(name) XS(name)
#endif
#ifndef XS_INTERNAL
#  define XS_INTERNAL(name) XS(name)
#endif

/* Now, finally, after all this mess, we want an ExtUtils::ParseXS
 * internal macro that we're free to redefine for varying linkage due
 * to the EXPORT_XSUB_SYMBOLS XS keyword. This is internal, use
 * XS_EXTERNAL(name) or XS_INTERNAL(name) in your code if you need to!
 */

#undef XS_EUPXS
#if defined(PERL_EUPXS_ALWAYS_EXPORT)
#  define XS_EUPXS(name) XS_EXTERNAL(name)
#else
   /* default to internal */
#  define XS_EUPXS(name) XS_INTERNAL(name)
#endif

#ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
#define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)

/* prototype to pass -Wmissing-prototypes */
STATIC void
S_croak_xs_usage(const CV *const cv, const char *const params);

STATIC void
S_croak_xs_usage(const CV *const cv, const char *const params)
{
    const GV *const gv = CvGV(cv);

    PERL_ARGS_ASSERT_CROAK_XS_USAGE;

    if (gv) {
        const char *const gvname = GvNAME(gv);
        const HV *const stash = GvSTASH(gv);
        const char *const hvname = stash ? HvNAME(stash) : NULL;

        if (hvname)
	    Perl_croak_nocontext("Usage: %s::%s(%s)", hvname, gvname, params);
        else
	    Perl_croak_nocontext("Usage: %s(%s)", gvname, params);
    } else {
        /* Pants. I don't think that it should be possible to get here. */
	Perl_croak_nocontext("Usage: CODE(0x%"UVxf")(%s)", PTR2UV(cv), params);
    }
}
#undef  PERL_ARGS_ASSERT_CROAK_XS_USAGE

#define croak_xs_usage        S_croak_xs_usage

#endif

/* NOTE: the prototype of newXSproto() is different in versions of perls,
 * so we define a portable version of newXSproto()
 */
#ifdef newXS_flags
#define newXSproto_portable(name, c_impl, file, proto) newXS_flags(name, c_impl, file, proto, 0)
#else
#define newXSproto_portable(name, c_impl, file, proto) (PL_Sv=(SV*)newXS(name, c_impl, file), sv_setpv(PL_Sv, proto), (CV*)PL_Sv)
#endif /* !defined(newXS_flags) */

#if PERL_VERSION_LE(5, 21, 5)
#  define newXS_deffile(a,b) Perl_newXS(aTHX_ a,b,file)
#else
#  define newXS_deffile(a,b) Perl_newXS_deffile(aTHX_ a,b)
#endif

#line 298 "GLog.c"

XS_EUPXS(XS_Glib__Log_set_handler); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Glib__Log_set_handler)
{
    dVAR; dXSARGS;
    if (items < 4 || items > 5)
       croak_xs_usage(cv,  "class, log_domain, log_levels, log_func, user_data=NULL");
    {
#line 198 "GLog.xs"
	GPerlCallback * callback;
#line 309 "GLog.c"
	guint	RETVAL;
	dXSTARG;
	gchar_ornull *	log_domain;
	SV *	log_levels = ST(2)
;
	SV *	log_func = ST(3)
;
	SV *	user_data;

	/* same as SvGChar(), but allows undef as NULL */
	if (gperl_sv_is_defined (ST(1))) {
		sv_utf8_upgrade (ST(1));
		log_domain = (gchar_ornull *)SvPV_nolen (ST(1));
	} else {
		log_domain = NULL;
	}
;

	if (items < 5)
	    user_data = NULL;
	else {
	    user_data = ST(4)
;
	}
#line 200 "GLog.xs"
	callback = gperl_log_callback_new (log_func, user_data);
	RETVAL = g_log_set_handler (log_domain,
				    SvGLogLevelFlags (log_levels),
				    gperl_log_func, callback);
	/* we have no choice but to leak the callback. */
	/* FIXME what about keeping a hash by the ID, and freeing it on
	 *       Glib::Log->remove_handler ($id)? */
        /*pcg: would probably take more memory in typical programs... */
#line 343 "GLog.c"
	XSprePUSH; PUSHu((UV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Glib__Log_remove_handler); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Glib__Log_remove_handler)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "class, log_domain, handler_id");
    {
	gchar_ornull *	log_domain;
	guint	handler_id = (guint)SvUV(ST(2))
;

	/* same as SvGChar(), but allows undef as NULL */
	if (gperl_sv_is_defined (ST(1))) {
		sv_utf8_upgrade (ST(1));
		log_domain = (gchar_ornull *)SvPV_nolen (ST(1));
	} else {
		log_domain = NULL;
	}
;

	g_log_remove_handler(log_domain, handler_id);
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Glib__Log_default_handler); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Glib__Log_default_handler)
{
    dVAR; dXSARGS;
    if (items < 3)
       croak_xs_usage(cv,  "log_domain, log_level, message, ...");
    {
	const gchar *	log_domain;
	SV *	log_level = ST(1)
;
	const gchar *	message;

	/* same as SvGChar(), but not in a function */
	sv_utf8_upgrade (ST(0));
	log_domain = (const gchar *)SvPV_nolen (ST(0))
;

	/* same as SvGChar(), but not in a function */
	sv_utf8_upgrade (ST(2));
	message = (const gchar *)SvPV_nolen (ST(2))
;
#line 228 "GLog.xs"
	g_log_default_handler (log_domain, SvGLogLevelFlags(log_level),
			       message, NULL);
#line 400 "GLog.c"
    }
    XSRETURN_EMPTY;
}

#if GLIB_CHECK_VERSION (2, 6, 0)
#define XSubPPtmpAAAA 1


XS_EUPXS(XS_Glib__Log_set_default_handler); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Glib__Log_set_default_handler)
{
    dVAR; dXSARGS;
    if (items < 2 || items > 3)
       croak_xs_usage(cv,  "class, log_func, user_data=NULL");
    {
#line 261 "GLog.xs"
	GLogFunc new_func = &g_log_default_handler;
	GLogFunc old_func;
	GPerlCallback *new_callback = NULL;
	GPerlCallback *old_callback;
#line 421 "GLog.c"
	SV *	RETVAL;
	SV *	log_func = ST(1)
;
	SV *	user_data;

	if (items < 3)
	    user_data = NULL;
	else {
	    user_data = ST(2)
;
	}
#line 266 "GLog.xs"
	if (gperl_sv_is_defined (log_func)) {
		/* check for log_func == \&Glib::Log::default_handler and
		 * turn that into g_log_default_handler() directly, rather
		 * than making a callback into perl and out again.  This is
		 * mainly an optimization, but if something weird has
		 * happened then the direct C function will be much more
		 * likely to work.
		 */
		HV *st;
		GV *gv;
		CV *cv = sv_2cv(log_func, &st, &gv, 0);
		if (cv && CvXSUB(cv) == XS_Glib__Log_default_handler) {
			/* new_func already initialized to
			 * g_log_default_handler above
                         */
		} else {
			new_func = gperl_log_func;
			new_callback = gperl_log_callback_new
				(log_func, user_data);
		}
	}

	G_LOCK (gperl_log_default_handler_callback);

	old_func = g_log_set_default_handler (new_func, new_callback);
	old_callback = gperl_log_default_handler_callback;
	gperl_log_default_handler_callback = new_callback;

	G_UNLOCK (gperl_log_default_handler_callback);

	RETVAL = &PL_sv_undef;
	if (old_func == g_log_default_handler) {
		CV *cv = get_cv ("Glib::Log::default_handler", 0);
		assert (cv);
		RETVAL = newRV_inc ((SV*) cv);
		SvREFCNT_inc (RETVAL);
	} else if (old_func == gperl_log_func) {
		RETVAL = old_callback->func;
		SvREFCNT_inc (RETVAL);
	}
	if (old_callback) {
		gperl_callback_destroy (old_callback);
	}
#line 477 "GLog.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}

#endif

XS_EUPXS(XS_Glib_log); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Glib_log)
{
    dVAR; dXSARGS;
    if (items != 4)
       croak_xs_usage(cv,  "class, log_domain, log_level, message");
    {
	gchar_ornull *	log_domain;
	SV *	log_level = ST(2)
;
	const gchar *	message;

	/* same as SvGChar(), but allows undef as NULL */
	if (gperl_sv_is_defined (ST(1))) {
		sv_utf8_upgrade (ST(1));
		log_domain = (gchar_ornull *)SvPV_nolen (ST(1));
	} else {
		log_domain = NULL;
	}
;

	/* same as SvGChar(), but not in a function */
	sv_utf8_upgrade (ST(3));
	message = (const gchar *)SvPV_nolen (ST(3))
;
#line 324 "GLog.xs"
	g_log (log_domain, SvGLogLevelFlags (log_level), "%s", message);
#line 513 "GLog.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Glib__Log_set_fatal_mask); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Glib__Log_set_fatal_mask)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "class, log_domain, fatal_mask");
    {
	SV *	RETVAL;
	const gchar *	log_domain;
	SV *	fatal_mask = ST(2)
;

	/* same as SvGChar(), but not in a function */
	sv_utf8_upgrade (ST(1));
	log_domain = (const gchar *)SvPV_nolen (ST(1))
;
#line 330 "GLog.xs"
	RETVAL = newSVGLogLevelFlags 
		(g_log_set_fatal_mask (log_domain,
		                       SvGLogLevelFlags (fatal_mask)));
#line 539 "GLog.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Glib__Log_set_always_fatal); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Glib__Log_set_always_fatal)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "class, fatal_mask");
    {
	SV *	RETVAL;
	SV *	fatal_mask = ST(1)
;
#line 338 "GLog.xs"
	RETVAL = newSVGLogLevelFlags 
		(g_log_set_always_fatal (SvGLogLevelFlags (fatal_mask)));
#line 560 "GLog.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Glib_error); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Glib_error)
{
    dVAR; dXSARGS;
    dXSI32;
    if (items != 3)
       croak_xs_usage(cv,  "class, domain, message");
    {
#line 373 "GLog.xs"
	GLogLevelFlags flags = G_LOG_LEVEL_MESSAGE;
#line 578 "GLog.c"
	gchar_ornull *	domain;
	const gchar *	message;

	/* same as SvGChar(), but allows undef as NULL */
	if (gperl_sv_is_defined (ST(1))) {
		sv_utf8_upgrade (ST(1));
		domain = (gchar_ornull *)SvPV_nolen (ST(1));
	} else {
		domain = NULL;
	}
;

	/* same as SvGChar(), but not in a function */
	sv_utf8_upgrade (ST(2));
	message = (const gchar *)SvPV_nolen (ST(2))
;
#line 375 "GLog.xs"
	switch (ix) {
		case 0: flags = G_LOG_LEVEL_ERROR; break;
		case 1: flags = G_LOG_LEVEL_MESSAGE; break;
		case 2: flags = G_LOG_LEVEL_CRITICAL; break;
		case 3: flags = G_LOG_LEVEL_WARNING; break;
	}
	g_log (domain, flags, "%s", message);
#line 603 "GLog.c"
    }
    XSRETURN_EMPTY;
}

#ifdef __cplusplus
extern "C"
#endif
XS_EXTERNAL(boot_Glib__Log); /* prototype to pass -Wmissing-prototypes */
XS_EXTERNAL(boot_Glib__Log)
{
#if PERL_VERSION_LE(5, 21, 5)
    dVAR; dXSARGS;
#else
    dVAR; dXSBOOTARGSXSAPIVERCHK;
#endif
#if (PERL_REVISION == 5 && PERL_VERSION < 9)
    char* file = __FILE__;
#else
    const char* file = __FILE__;
#endif

    PERL_UNUSED_VAR(file);

    PERL_UNUSED_VAR(cv); /* -W */
    PERL_UNUSED_VAR(items); /* -W */
#if PERL_VERSION_LE(5, 21, 5)
    XS_VERSION_BOOTCHECK;
#  ifdef XS_APIVERSION_BOOTCHECK
    XS_APIVERSION_BOOTCHECK;
#  endif
#endif

    {
        CV * cv;

        newXS_deffile("Glib::Log::set_handler", XS_Glib__Log_set_handler);
        newXS_deffile("Glib::Log::remove_handler", XS_Glib__Log_remove_handler);
        newXS_deffile("Glib::Log::default_handler", XS_Glib__Log_default_handler);
#if XSubPPtmpAAAA
        newXS_deffile("Glib::Log::set_default_handler", XS_Glib__Log_set_default_handler);
#endif
        newXS_deffile("Glib::log", XS_Glib_log);
        newXS_deffile("Glib::Log::set_fatal_mask", XS_Glib__Log_set_fatal_mask);
        newXS_deffile("Glib::Log::set_always_fatal", XS_Glib__Log_set_always_fatal);
        cv = newXS_deffile("Glib::critical", XS_Glib_error);
        XSANY.any_i32 = 2;
        cv = newXS_deffile("Glib::error", XS_Glib_error);
        XSANY.any_i32 = 0;
        cv = newXS_deffile("Glib::message", XS_Glib_error);
        XSANY.any_i32 = 1;
        cv = newXS_deffile("Glib::warning", XS_Glib_error);
        XSANY.any_i32 = 3;
    }

    /* Initialisation Section */

#line 166 "GLog.xs"
	gperl_handle_logs_for (NULL);
	/* gperl_handle_logs_for ("main"); */
	gperl_handle_logs_for ("GLib");
	gperl_handle_logs_for ("GLib-GObject");
	gperl_register_fundamental (GPERL_TYPE_LOG_LEVEL_FLAGS,
	                            "Glib::LogLevelFlags");

#if XSubPPtmpAAAA
#endif
#line 670 "GLog.c"

    /* End of Initialisation Section */

#if PERL_VERSION_LE(5, 21, 5)
#  if PERL_VERSION_GE(5, 9, 0)
    if (PL_unitcheckav)
        call_list(PL_scopestack_ix, PL_unitcheckav);
#  endif
    XSRETURN_YES;
#else
    Perl_xs_boot_epilog(aTHX_ ax);
#endif
}

