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

#line 1 "LineBreak.xs"
/*
 * LineBreak.xs - Perl XS glue for Sombok package.
 * 
 * Copyright (C) 2009-2013 Hatuka*nezumi - IKEDA Soji <hatuka(at)nezumi.nu>.
 * 
 * This file is part of the Unicode::LineBreak package.  This program is
 * free software; you can redistribute it and/or modify it under the same
 * terms as Perl itself.
 *
 * $Id$
 */

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#define NEED_newRV_noinc
#define NEED_sv_2pv_flags
#define NEED_newRV_noinc_GLOBAL
#define NEED_sv_2pv_flags_GLOBAL
#define NEED_sv_2pv_nolen
#include "ppport.h"
#include "sombok.h"

/* for Win32 with Visual Studio (MSVC) */
#ifdef _MSC_VER
#  ifndef snprintf
#      define snprintf _snprintf
#  endif /* snprintf */
#  define strcasecmp _stricmp
#endif /* _MSC_VER */

/* Type synonyms for typemap. */
typedef IV swapspec_t;
typedef gcstring_t *generic_string;

/***
 *** Data conversion.
 ***/

/*
 * Create Unicode string from Perl utf8-flagged string.
 */
static
unistr_t *SVtounistr(unistr_t *buf, SV *str)
{
    U8 *utf8, *utf8ptr;
    STRLEN utf8len, unilen, len;
    unichar_t *uniptr;

    if (buf == NULL) {
	if ((buf = malloc(sizeof(unistr_t))) == NULL)
	    croak("SVtounistr: %s", strerror(errno));
    } else if (buf->str)
	free(buf->str);
    buf->str = NULL;
    buf->len = 0;

    if (SvOK(str))
	utf8 = (U8 *)SvPV(str, utf8len);
    else
	return buf;
    if (utf8len <= 0)
	return buf;
    unilen = utf8_length(utf8, utf8 + utf8len);
    if ((buf->str = (unichar_t *)malloc(sizeof(unichar_t) * unilen)) == NULL)
	croak("SVtounistr: %s", strerror(errno));

    utf8ptr = utf8;
    uniptr = buf->str;
    while (utf8ptr < utf8 + utf8len) {
#if PERL_VERSION >= 20 || (PERL_VERSION == 19 && PERL_SUBVERSION >= 4)
	*uniptr = (unichar_t) NATIVE_TO_UNI(
	    utf8_to_uvchr_buf(utf8ptr, utf8 + utf8len, &len));
#elif PERL_VERSION >= 16 || (PERL_VERSION == 15 && PERL_SUBVERSION >= 9)
	*uniptr = (unichar_t) utf8_to_uvuni_buf(utf8ptr, utf8 + utf8len,
						&len);
#else
	*uniptr = (unichar_t) utf8n_to_uvuni(utf8ptr,
					     utf8 + utf8len - utf8ptr, &len,
					     ckWARN(WARN_UTF8) ? 0 :
					     UTF8_ALLOW_ANY);
#endif
	if (len < 0) {
	    free(buf->str);
	    buf->str = NULL;
	    buf->len = 0;
	    croak("SVtounistr: Not well-formed UTF-8");
	}
	if (len == 0) {
	    free(buf->str);
	    buf->str = NULL;
	    buf->len = 0;
	    croak("SVtounistr: Internal error");
	}
	utf8ptr += len;
	uniptr++;
    }
    buf->len = unilen;
    return buf;
}

/*
 * Create Unicode string from Perl string NOT utf8-flagged.
 */
static
unistr_t *SVupgradetounistr(unistr_t *buf, SV *str)
{
    char *s;
    size_t len, i;

    if (buf == NULL) {
	if ((buf = malloc(sizeof(unistr_t))) == NULL)
	    croak("SVupgradetounistr: %s", strerror(errno));
    } else if (buf->str)
	free(buf->str);
    buf->str = NULL;
    buf->len = 0;

    if (SvOK(str))
	s = SvPV(str, len);
    else
	return buf;
    if (len == 0)
	return buf;
    if ((buf->str = malloc(sizeof(unichar_t) * len)) == NULL)
	croak("SVupgradetounistr: %s", strerror(errno));

    for (i = 0; i < len; i++)
	buf->str[i] = (unichar_t)(unsigned char)s[i];
    buf->len = len;
    return buf;
}

/*
 * Create Perl utf8-flagged string from Unicode string.
 */
static
SV *unistrtoSV(unistr_t *unistr, size_t uniidx, size_t unilen)
{
    U8 *buf = NULL, *newbuf;
    STRLEN utf8len;
    unichar_t *uniptr;
    SV *utf8;

    if (unistr == NULL || unistr->str == NULL || unilen == 0) {
	utf8 = newSVpvn("", 0);
	SvUTF8_on(utf8);
	return utf8;
    }

    utf8len = 0;
    uniptr = unistr->str + uniidx;
    while (uniptr < unistr->str + uniidx + unilen &&
	   uniptr < unistr->str + unistr->len) {
	if ((newbuf = realloc(buf,
			      sizeof(U8) * (utf8len + UTF8_MAXLEN + 1)))
	    == NULL) {
	    free(buf);
	    croak("unistrtoSV: %s", strerror(errno));
	}
	buf = newbuf;
#if PERL_VERSION >= 20 || (PERL_VERSION == 19 && PERL_SUBVERSION >= 4)
	utf8len = uvchr_to_utf8(buf + utf8len, UNI_TO_NATIVE(*uniptr)) - buf;
#else
	utf8len = uvuni_to_utf8(buf + utf8len, *uniptr) - buf;
#endif
	uniptr++;
    }

    utf8 = newSVpvn((char *)(void *)buf, utf8len);
    SvUTF8_on(utf8);
    free(buf);
    return utf8;
}

/*
 * Convert Perl object to C object
 */
#define PerltoC(type, arg) \
    (INT2PTR(type, SvIV((SV *)SvRV(arg))))

/*
 * Create Perl object from C object
 */
# define setCtoPerl(arg, klass, var) \
    STMT_START { \
	sv_setref_iv(arg, klass, (IV)(var)); \
	SvREADONLY_on(arg); \
    } STMT_END
static
SV *CtoPerl(char *klass, void *obj)
{
    SV *sv;

    sv = newSViv(0);
    setCtoPerl(sv, klass, obj);  
    return sv;
}

/*
 * Convert Perl utf8-flagged string (GCString) to grapheme cluster string.
 */
static
gcstring_t *SVtogcstring(SV *sv, linebreak_t *lbobj)
{
    unistr_t unistr = {NULL, 0};

    if (!sv_isobject(sv)) {
	SVtounistr(&unistr, sv);
	return gcstring_new(&unistr, lbobj);
    } else if (sv_derived_from(sv, "Unicode::GCString"))
	return PerltoC(gcstring_t *, sv);
    else
	croak("Unknown object %s", HvNAME(SvSTASH(SvRV(sv))));
}

#if 0
/*
 * Convert Perl LineBreak object to C linebreak object.
 */
static
linebreak_t *SVtolinebreak(SV *sv)
{
    if (!sv_isobject(sv))
	croak("Not object");
    else if (sv_derived_from(sv, "Unicode::LineBreak"))
	return PerltoC(linebreak_t *, sv);
    else
	croak("Unknown object %s", HvNAME(SvSTASH(SvRV(sv))));
}
#endif /* 0 */

/*
 * Convert Perl SV to boolean (n.b. string "YES" means true).
 */
static
int SVtoboolean(SV *sv)
{
    char *str;

    if (!sv || !SvOK(sv))
	return 0;
    if (SvPOK(sv))
	return strcasecmp((str = SvPV_nolen(sv)), "YES") == 0 ||
	    atof(str) != 0.0;
    return SvNV(sv) != 0.0;
}

/***
 *** Other utilities
 ***/

/*
 * Do regex match once then returns offset and length.
 */
void do_pregexec_once(REGEXP *rx, unistr_t *str)
{
    SV *screamer;
    char *str_arg, *str_beg, *str_end;
    size_t offs_beg, offs_end;

    screamer = unistrtoSV(str, 0, str->len);
    SvREADONLY_on(screamer);
    str_beg = str_arg = SvPVX(screamer);
    str_end = SvEND(screamer);

    if (pregexec(rx, str_arg, str_end, str_beg, 0, screamer, 1)) {
#if PERL_VERSION >= 11
	offs_beg = ((regexp *)SvANY(rx))->offs[0].start;
	offs_end = ((regexp *)SvANY(rx))->offs[0].end;
#elif ((PERL_VERSION == 10) || (PERL_VERSION == 9 && PERL_SUBVERSION >= 5))
	offs_beg = rx->offs[0].start;
	offs_end = rx->offs[0].end;
#else /* PERL_VERSION */
	offs_beg = rx->startp[0];
	offs_end = rx->endp[0];
#endif
	str->str += utf8_length((U8 *)str_beg, (U8 *)(str_beg + offs_beg));
	str->len = utf8_length((U8 *)(str_beg + offs_beg),
			       (U8 *)(str_beg + offs_end));
    } else
	str->str = NULL;

    SvREFCNT_dec(screamer);
}

/***
 *** Callbacks for Sombok library.
 ***/

/*
 * Increment/decrement reference count
 */
void ref_func(void *sv, int datatype, int d)
{
    if (sv == NULL)
	return;
    if (0 < d)
	SvREFCNT_inc((SV *)sv);
    else if (d < 0)
	SvREFCNT_dec((SV *)sv);
}

/*
 * Call preprocessing function
 */
static
gcstring_t *prep_func(linebreak_t *lbobj, void *dataref, unistr_t *str,
		      unistr_t *text)
{
    AV *data;
    SV *sv, **pp, *func = NULL;
    REGEXP *rx = NULL;
    size_t count, i, j;
    gcstring_t *gcstr, *ret;

    if (dataref == NULL ||
	(data = (AV *)SvRV((SV *)dataref)) == NULL)
	return (lbobj->errnum = EINVAL), NULL;

    /* Pass I */

    if (text != NULL) {
	if ((pp = av_fetch(data, 0, 0)) == NULL)
	    return (lbobj->errnum = EINVAL), NULL;

#if ((PERL_VERSION >= 10) || (PERL_VERSION >= 9 && PERL_SUBVERSION >= 5))
	if (SvRXOK(*pp))
	    rx = SvRX(*pp);
#else /* PERL_VERSION */
	if (SvROK(*pp) && SvMAGICAL(sv = SvRV(*pp))) {
	    MAGIC *mg;
	    if ((mg = mg_find(sv, PERL_MAGIC_qr)) != NULL)
		rx = (REGEXP *)mg->mg_obj;
	}
#endif /* PERL_VERSION */
	if (rx == NULL)
	    return (lbobj->errnum = EINVAL), NULL;

	do_pregexec_once(rx, str);
	return NULL;
    }

    /* Pass II */

    if ((pp = av_fetch(data, 1, 0)) == NULL)
        func = NULL;
    else if (SvOK(*pp))
        func = *pp;
    else
        func = NULL;

    if (func == NULL) {
	if ((ret = gcstring_newcopy(str, lbobj)) == NULL)
	    return (lbobj->errnum = errno ? errno : ENOMEM), NULL;
    } else {
	dSP;
	ENTER;
	SAVETMPS;
	PUSHMARK(SP);
	linebreak_incref(lbobj); /* mortal but should not be destroyed.*/
	XPUSHs(sv_2mortal(CtoPerl("Unicode::LineBreak", lbobj)));
	XPUSHs(sv_2mortal(unistrtoSV(str, 0, str->len)));
	PUTBACK;
	count = call_sv(func, G_ARRAY | G_EVAL);

	SPAGAIN;
	if (SvTRUE(ERRSV)) {
	    if (!lbobj->errnum)
		 lbobj->errnum = LINEBREAK_EEXTN;
	    return NULL;
	}

	if ((ret = gcstring_new(NULL, lbobj)) == NULL)
	    return (lbobj->errnum = errno ? errno : ENOMEM), NULL;

	for (i = 0; i < count; i++) {
	    sv = POPs;
	    if (!SvOK(sv))
		continue;
	    gcstr = SVtogcstring(sv, lbobj);

	    for (j = 0; j < gcstr->gclen; j++) {
		if (gcstr->gcstr[j].flag &
		    (LINEBREAK_FLAG_ALLOW_BEFORE |
		     LINEBREAK_FLAG_PROHIBIT_BEFORE))
		    continue;
		if (i < count - 1 && j == 0)
		    gcstr->gcstr[j].flag |= LINEBREAK_FLAG_ALLOW_BEFORE;
		else if (0 < j)
		    gcstr->gcstr[j].flag |= LINEBREAK_FLAG_PROHIBIT_BEFORE;
	    }

	    gcstring_replace(ret, 0, 0, gcstr);
	    if (!sv_isobject(sv))
		gcstring_destroy(gcstr);
	}

	PUTBACK;
	FREETMPS;
	LEAVE;
    }

    return ret;
}

/*
 * Call format function
 */
static
char *linebreak_states[] = {
    NULL, "sot", "sop", "sol", "", "eol", "eop", "eot", NULL
};
static
gcstring_t *format_func(linebreak_t *lbobj, linebreak_state_t action,
			gcstring_t *str)
{
    SV *sv;
    char *actionstr;
    int count;
    gcstring_t *ret;

    dSP;
    if (action <= LINEBREAK_STATE_NONE || LINEBREAK_STATE_MAX <= action)
	return NULL;
    actionstr = linebreak_states[(size_t)action];
    ENTER;
    SAVETMPS;
    PUSHMARK(SP);
    linebreak_incref(lbobj); /* mortal but should not be destroyed. */
    XPUSHs(sv_2mortal(CtoPerl("Unicode::LineBreak", lbobj)));
    XPUSHs(sv_2mortal(newSVpv(actionstr, 0)));
    XPUSHs(sv_2mortal(CtoPerl("Unicode::GCString", gcstring_copy(str))));
    PUTBACK;
    count = call_sv(lbobj->format_data, G_SCALAR | G_EVAL);

    SPAGAIN;
    if (SvTRUE(ERRSV)) {
	if (!lbobj->errnum)
	    lbobj->errnum = LINEBREAK_EEXTN;
	POPs;
	return NULL;
    } else if (count != 1)
	croak("format_func: internal error");
    else
	sv = POPs;
    if (!SvOK(sv))
	ret = NULL;
    else
	ret = SVtogcstring(sv, lbobj);
    if (sv_isobject(sv))
	ret = gcstring_copy(ret);

    PUTBACK;
    FREETMPS;
    LEAVE;

    return ret;
}

/*
 * Call sizing function
 */
static
double sizing_func(linebreak_t *lbobj, double len,
		   gcstring_t *pre, gcstring_t *spc, gcstring_t *str)
{
    int count;
    double ret;

    dSP;
    ENTER;
    SAVETMPS;
    PUSHMARK(SP);
    linebreak_incref(lbobj); /* mortal but should not be destroyed. */
    XPUSHs(sv_2mortal(CtoPerl("Unicode::LineBreak", lbobj)));
    XPUSHs(sv_2mortal(newSVnv(len))); 
    XPUSHs(sv_2mortal(CtoPerl("Unicode::GCString", gcstring_copy(pre))));
    XPUSHs(sv_2mortal(CtoPerl("Unicode::GCString", gcstring_copy(spc))));
    XPUSHs(sv_2mortal(CtoPerl("Unicode::GCString", gcstring_copy(str))));
    PUTBACK;
    count = call_sv(lbobj->sizing_data, G_SCALAR | G_EVAL);

    SPAGAIN;
    if (SvTRUE(ERRSV)) {
	if (!lbobj->errnum)
	    lbobj->errnum = LINEBREAK_EEXTN;
	POPs;
	return -1;
    } else if (count != 1)
	croak("sizing_func: internal error");
    else
	ret = POPn;

    PUTBACK;
    FREETMPS;
    LEAVE;

    return ret;
}

/*
 * Call urgent breaking function
 */
static
gcstring_t *urgent_func(linebreak_t *lbobj, gcstring_t *str)
{
    SV *sv;
    int count;
    size_t i;
    gcstring_t *gcstr, *ret;

    dSP;
    ENTER;
    SAVETMPS;
    PUSHMARK(SP);
    linebreak_incref(lbobj); /* mortal but should not be destroyed. */
    XPUSHs(sv_2mortal(CtoPerl("Unicode::LineBreak", lbobj)));
    XPUSHs(sv_2mortal(CtoPerl("Unicode::GCString", gcstring_copy(str))));
    PUTBACK;
    count = call_sv(lbobj->urgent_data, G_ARRAY | G_EVAL);

    SPAGAIN;
    if (SvTRUE(ERRSV)) {
	if (!lbobj->errnum)
	    lbobj->errnum = LINEBREAK_EEXTN;
	return NULL;
    } if (count == 0)
	return NULL;

    ret = gcstring_new(NULL, lbobj);
    for (i = count; i; i--) {
	sv = POPs;
	if (SvOK(sv)) {
	    gcstr = SVtogcstring(sv, lbobj);
	    if (gcstr->gclen)
		gcstr->gcstr[0].flag = LINEBREAK_FLAG_ALLOW_BEFORE;
	    gcstring_replace(ret, 0, 0, gcstr);
	    if (!sv_isobject(sv))
		gcstring_destroy(gcstr);
	}
    }

    PUTBACK;
    FREETMPS;
    LEAVE;

    return ret;
}


#line 562 "LineBreak.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 706 "LineBreak.c"

XS_EUPXS(XS_Unicode__LineBreak_EAWidths); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_EAWidths)
{
    dVAR; dXSARGS;
    if (items != 0)
       croak_xs_usage(cv,  "");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
#line 557 "LineBreak.xs"
	char **p;
#line 719 "LineBreak.c"
#line 559 "LineBreak.xs"
	for (p = (char **)linebreak_propvals_EA; *p != NULL; p++)
	    XPUSHs(sv_2mortal(newSVpv(*p, 0)));
#line 723 "LineBreak.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Unicode__LineBreak_LBClasses); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_LBClasses)
{
    dVAR; dXSARGS;
    if (items != 0)
       croak_xs_usage(cv,  "");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
#line 565 "LineBreak.xs"
	char **p;
#line 741 "LineBreak.c"
#line 567 "LineBreak.xs"
	for (p = (char **)linebreak_propvals_LB; *p != NULL; p++)
	    XPUSHs(sv_2mortal(newSVpv(*p, 0)));
#line 745 "LineBreak.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Unicode__LineBreak__new); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak__new)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "klass");
    {
	char *	klass = (char *)SvPV_nolen(ST(0))
;
	linebreak_t *	RETVAL;
#line 575 "LineBreak.xs"
	if ((RETVAL = linebreak_new(ref_func)) == NULL)
	    croak("%s->_new: %s", klass, strerror(errno));
	linebreak_set_stash(RETVAL, newRV_noinc((SV *)newHV()));
	SvREFCNT_dec(RETVAL->stash); /* fixup */
#line 767 "LineBreak.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
	    setCtoPerl(RETVALSV, "Unicode::LineBreak", RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__LineBreak_copy); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_copy)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "self");
    {
	linebreak_t *	self;
	linebreak_t *	RETVAL;

	if (! sv_isobject(ST(0)))
	    croak("copy: Not object");
	else if (sv_derived_from(ST(0), "Unicode::LineBreak"))
	    self = PerltoC(linebreak_t *, ST(0));
	else
	    croak("copy: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 587 "LineBreak.xs"
	RETVAL = linebreak_copy(self);
#line 799 "LineBreak.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
	    setCtoPerl(RETVALSV, "Unicode::LineBreak", RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__LineBreak_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_DESTROY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "self");
    {
	linebreak_t *	self;

	if (! sv_isobject(ST(0)))
	    croak("DESTROY: Not object");
	else if (sv_derived_from(ST(0), "Unicode::LineBreak"))
	    self = PerltoC(linebreak_t *, ST(0));
	else
	    croak("DESTROY: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 596 "LineBreak.xs"
	linebreak_destroy(self);
#line 830 "LineBreak.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Unicode__LineBreak__config); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak__config)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	linebreak_t *	self;
#line 602 "LineBreak.xs"
	size_t i;
	char *key;
	void *func;
	SV *val;
	char *opt;
#line 850 "LineBreak.c"
	SV *	RETVAL;

	if (! sv_isobject(ST(0)))
	    croak("_config: Not object");
	else if (sv_derived_from(ST(0), "Unicode::LineBreak"))
	    self = PerltoC(linebreak_t *, ST(0));
	else
	    croak("_config: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 608 "LineBreak.xs"
	RETVAL = NULL;
	if (items < 2)
	    croak("_config: Too few arguments");
	else if (items < 3) {
	    key = (char *)SvPV_nolen(ST(1));

	    if (strcasecmp(key, "BreakIndent") == 0)
		RETVAL = newSVuv(self->options &
				 LINEBREAK_OPTION_BREAK_INDENT); 
	    else if (strcasecmp(key, "CharMax") == 0)
		RETVAL = newSVuv(self->charmax);
	    else if (strcasecmp(key, "ColMax") == 0)
		RETVAL = newSVnv((NV)self->colmax);
	    else if (strcasecmp(key, "ColMin") == 0)
		RETVAL = newSVnv((NV)self->colmin);
	    else if (strcasecmp(key, "ComplexBreaking") == 0)
		RETVAL = newSVuv(self->options &
				 LINEBREAK_OPTION_COMPLEX_BREAKING);
	    else if (strcasecmp(key, "Context") == 0) {
		if (self->options & LINEBREAK_OPTION_EASTASIAN_CONTEXT)
		    RETVAL = newSVpvn("EASTASIAN", 9);
		else
		    RETVAL = newSVpvn("NONEASTASIAN", 12);
	    } else if (strcasecmp(key, "EAWidth") == 0) {
		AV *av, *codes = NULL, *ret = NULL;
		propval_t p = PROP_UNKNOWN;
		unichar_t c;
		size_t i;

		if (self->map == NULL || self->mapsiz == 0)
		    XSRETURN_UNDEF;

		for (i = 0; i < self->mapsiz; i++)
		    if (self->map[i].eaw != PROP_UNKNOWN) {
			if (p != self->map[i].eaw){
			    p = self->map[i].eaw;
			    codes = newAV();
			    av = newAV();
			    av_push(av, newRV_noinc((SV *)codes));
			    av_push(av, newSViv((IV)p));
			    if (ret == NULL)
				ret = newAV();
			    av_push(ret, newRV_noinc((SV *)av));
			}
			for (c = self->map[i].beg; c <= self->map[i].end; c++)
			    av_push(codes, newSVuv(c));
		    }

		if (ret == NULL)
		    XSRETURN_UNDEF;
		RETVAL = newRV_noinc((SV *)ret);
	    } else if (strcasecmp(key, "Format") == 0) {
		func = self->format_func;
		if (func == NULL)
		    XSRETURN_UNDEF;
		else if (func == linebreak_format_NEWLINE)
		    RETVAL = newSVpvn("NEWLINE", 7);
		else if (func == linebreak_format_SIMPLE)
		    RETVAL = newSVpvn("SIMPLE", 6);
		else if (func == linebreak_format_TRIM)
		    RETVAL = newSVpvn("TRIM", 4);
		else if (func == format_func) {
		    if ((val = (SV *)self->format_data) == NULL)
			XSRETURN_UNDEF;
		    ST(0) = val; /* should not be mortal. */
		    XSRETURN(1);
		} else
		    croak("_config: internal error");
	    } else if (strcasecmp(key, "HangulAsAL") == 0)
		RETVAL = newSVuv(self->options &
				 LINEBREAK_OPTION_HANGUL_AS_AL);
	    else if (strcasecmp(key, "LBClass") == 0) {
		AV *av, *codes = NULL, *ret = NULL;
		propval_t p = PROP_UNKNOWN;
		unichar_t c;
		size_t i;

		if (self->map == NULL || self->mapsiz == 0)
		    XSRETURN_UNDEF;

		for (i = 0; i < self->mapsiz; i++)
		    if (self->map[i].lbc != PROP_UNKNOWN) {
			if (p != self->map[i].lbc){
			    p = self->map[i].lbc;
			    codes = newAV();
			    av = newAV();
			    av_push(av, newRV_noinc((SV *)codes));
			    av_push(av, newSViv((IV)p));
			    if (ret == NULL)
				ret = newAV();
			    av_push(ret, newRV_noinc((SV *)av));
			}
			for (c = self->map[i].beg; c <= self->map[i].end; c++)
			    av_push(codes, newSVuv(c));
		    }

		if (ret == NULL)
		    XSRETURN_UNDEF;
		RETVAL = newRV_noinc((SV *)ret);
	    } else if (strcasecmp(key, "LegacyCM") == 0)
		RETVAL = newSVuv(self->options & LINEBREAK_OPTION_LEGACY_CM);
	    else if (strcasecmp(key, "Newline") == 0) {
		unistr_t unistr = {self->newline.str, self->newline.len};
		if (self->newline.str == NULL || self->newline.len == 0)
		    RETVAL = unistrtoSV(&unistr, 0, 0);
		else
		    RETVAL = unistrtoSV(&unistr, 0, self->newline.len);
	    } else if (strcasecmp(key, "Prep") == 0) {
		AV *av;
		if (self->prep_func == NULL || self->prep_func[0] == NULL)
		    XSRETURN_UNDEF;
		av = newAV();
		for (i = 0; (func = self->prep_func[i]) != NULL; i++)
		    if (func == linebreak_prep_URIBREAK) {
			if (self->prep_data == NULL ||
			    self->prep_data[i] == NULL)
			    av_push(av, newSVpvn("NONBREAKURI", 11));
			else
			    av_push(av, newSVpvn("BREAKURI", 8));
		    } else if (func == prep_func) {
			if (self->prep_data == NULL ||
			    self->prep_data[i] == NULL)
			    croak("_config: internal error");
			SvREFCNT_inc(self->prep_data[i]); /* avoid freed */
			av_push(av, self->prep_data[i]);
		    } else
			croak("_config: internal error");
		RETVAL = newRV_noinc((SV *)av);
	    } else if (strcasecmp(key, "Sizing") == 0) {
		func = self->sizing_func;
		if (func == NULL)
		    XSRETURN_UNDEF;
		else if (func == linebreak_sizing_UAX11)
		    RETVAL = newSVpvn("UAX11", 5);
		else if (func == sizing_func) {
		    if ((val = (SV *)self->sizing_data) == NULL)
			XSRETURN_UNDEF;
		    ST(0) = val; /* should not be mortal. */
		    XSRETURN(1);
		} else
		    croak("_config: internal error");
	    } else if (strcasecmp(key, "Urgent") == 0) {
		func = self->urgent_func;
		if (func == NULL)
		    XSRETURN_UNDEF;
		else if (func == linebreak_urgent_ABORT)
		    RETVAL = newSVpvn("CROAK", 5);
		else if (func == linebreak_urgent_FORCE)
		    RETVAL = newSVpvn("FORCE", 5);
		else if (func == urgent_func) {
		    if ((val = (SV *)self->urgent_data) == NULL)
			XSRETURN_UNDEF;
		    ST(0) = val; /* should not be mortal. */
		    XSRETURN(1);
		} else
		    croak("_config: internal error");
	    } else if (strcasecmp(key, "ViramaAsJoiner") == 0)
		RETVAL = newSVuv(self->options & LINEBREAK_OPTION_VIRAMA_AS_JOINER);
	    else {
		warn("_config: Getting unknown option %s", key);
		XSRETURN_UNDEF;
	    }
	} else if (!(items % 2))
	    croak("_config: Argument size mismatch");
	else for (RETVAL = NULL, i = 1; i < items; i += 2) {
	    if (!SvPOK(ST(i)))
		croak("_config: Illegal argument");
	    key = (char *)SvPV_nolen(ST(i));
	    val = ST(i + 1);

	    if (strcasecmp(key, "Prep") == 0) {
		SV *sv, *pattern, *func;
		AV *av;
		REGEXP *rx = NULL;

		if (! SvOK(val))
		    linebreak_add_prep(self, NULL, NULL);
		else if (SvROK(val) &&
		    SvTYPE(av = (AV *)SvRV(val)) == SVt_PVAV &&
		    0 < av_len(av) + 1) {
		    pattern = *av_fetch(av, 0, 0);
#if ((PERL_VERSION >= 10) || (PERL_VERSION >= 9 && PERL_SUBVERSION >= 5))
		    if (SvRXOK(pattern))
			rx = SvRX(pattern);
#else /* PERL_VERSION */
		    if (SvROK(pattern) && SvMAGICAL(sv = SvRV(pattern))) {
			MAGIC *mg;
			if ((mg = mg_find(sv, PERL_MAGIC_qr)) != NULL)
			    rx = (REGEXP *)mg->mg_obj;
		    }
#endif
		    if (rx != NULL)
			SvREFCNT_inc(pattern); /* FIXME:avoid freed */
		    else if (SvOK(pattern)) {
#if ((PERL_VERSION >= 10) || (PERL_VERSION == 9 && PERL_SUBVERSION >= 5))
			rx = pregcomp(pattern, 0);
#else /* PERL_VERSION */
			{
			    PMOP *pm;
			    New(1, pm, 1, PMOP);
			    rx = pregcomp(SvPVX(pattern), SvEND(pattern), pm);
			}
#endif
			if (rx != NULL) {
#if PERL_VERSION >= 11
			    pattern = newRV_noinc((SV *)rx);
			    sv_bless(pattern, gv_stashpv("Regexp", 0));
#else /* PERL_VERSION */
			    sv = newSV(0);
			    sv_magic(sv, (SV *)rx, PERL_MAGIC_qr, NULL, 0);
			    pattern = newRV_noinc(sv);
			    sv_bless(pattern, gv_stashpv("Regexp", 0));
#endif
			}
		    } else
			rx = NULL;

		    if (rx == NULL)
			croak("_config: Not a regex");

		    if (av_fetch(av, 1, 0) == NULL)
			func = NULL;
		    else if (SvOK(func = *av_fetch(av, 1, 0)))
			SvREFCNT_inc(func); /* avoid freed */
		    else
			func = NULL;

		    av = newAV();
		    av_push(av, pattern);
		    if (func != NULL)
			av_push(av, func);
		    sv = newRV_noinc((SV *)av);
		    linebreak_add_prep(self, prep_func, (void *)sv);
		    SvREFCNT_dec(sv); /* fixup */
		} else {
		    char *s = SvPV_nolen(val);

		    if (strcasecmp(s, "BREAKURI") == 0)
			linebreak_add_prep(self, linebreak_prep_URIBREAK, val);
		    else if (strcasecmp(s, "NONBREAKURI") == 0)
			linebreak_add_prep(self, linebreak_prep_URIBREAK,
					   NULL);
		    else
			croak("_config: Unknown preprocess option: %s", s);
		}
	    } else if (strcasecmp(key, "Format") == 0) {
		if (! SvOK(val))
		    linebreak_set_format(self, NULL, NULL);
		else if (sv_derived_from(val, "CODE"))
		    linebreak_set_format(self, format_func, (void *)val);
		else {
		    char *s = SvPV_nolen(val);

		    if (strcasecmp(s, "DEFAULT") == 0) {
			warn("_config: "
			     "Method name \"DEFAULT\" for Format option was "
			     "obsoleted. Use \"SIMPLE\"");
			linebreak_set_format(self, linebreak_format_SIMPLE,
					     NULL);
		    } else if (strcasecmp(s, "SIMPLE") == 0)
			linebreak_set_format(self, linebreak_format_SIMPLE,
					     NULL);
		    else if (strcasecmp(s, "NEWLINE") == 0)
			linebreak_set_format(self, linebreak_format_NEWLINE,
					     NULL);
		    else if (strcasecmp(s, "TRIM") == 0)
			linebreak_set_format(self, linebreak_format_TRIM,
					     NULL);
		    else
			croak("_config: Unknown Format option: %s", s);
		}
	    } else if (strcasecmp(key, "Sizing") == 0) {
		if (! SvOK(val))
		    linebreak_set_sizing(self, NULL, NULL);
		else if (sv_derived_from(val, "CODE"))
		    linebreak_set_sizing(self, sizing_func, (void *)val);
		else {
		    char *s = SvPV_nolen(val);

		    if (strcasecmp(s, "DEFAULT") == 0) {
			warn("_config: "
			     "Method name \"DEFAULT\" for Sizing option "
			     "was obsoleted. Use \"UAX11\"");
			linebreak_set_sizing(self, linebreak_sizing_UAX11,
					     NULL);
		    } else if (strcasecmp(s, "UAX11") == 0)
			linebreak_set_sizing(self, linebreak_sizing_UAX11,
					     NULL);
		    else
			croak("_config: Unknown Sizing option: %s", s);
		}
	    } else if (strcasecmp(key, "Urgent") == 0) {
		if (! SvOK(val))
		    linebreak_set_urgent(self, NULL, NULL);
		else if (sv_derived_from(val, "CODE"))
		    linebreak_set_urgent(self, urgent_func, (void *)val);
		else {
		    char *s = SvPV_nolen(val);

		    if (strcasecmp(s, "NONBREAK") == 0) {
			warn("_config: "
			     "Method name \"NONBREAK\" for Urgent "
			     "option was obsoleted. Use undef");
			linebreak_set_urgent(self, NULL, NULL);
		    } else if (strcasecmp(s, "CROAK") == 0)
			linebreak_set_urgent(self, linebreak_urgent_ABORT,
					     NULL);
		    else if (strcasecmp(s, "FORCE") == 0)
			linebreak_set_urgent(self, linebreak_urgent_FORCE,
					     NULL);
		    else
			croak("_config: Unknown Urgent option: %s", s);
		}
	    } else if (strcasecmp(key, "BreakIndent") == 0) {
		if (SVtoboolean(val))
		    self->options |= LINEBREAK_OPTION_BREAK_INDENT;
		else
		    self->options &= ~LINEBREAK_OPTION_BREAK_INDENT;
	    } else if (strcasecmp(key, "CharMax") == 0)
		self->charmax = SvUV(val);
	    else if (strcasecmp(key, "ColMax") == 0)
		self->colmax = (double)SvNV(val);
	    else if (strcasecmp(key, "ColMin") == 0)
		self->colmin = (double)SvNV(val);
	    else if (strcasecmp(key, "ComplexBreaking") == 0) {
		if (SVtoboolean(val))
		    self->options |= LINEBREAK_OPTION_COMPLEX_BREAKING;
		else
		    self->options &= ~LINEBREAK_OPTION_COMPLEX_BREAKING;
	    } else if (strcasecmp(key, "Context") == 0) {
		if (SvOK(val))
		    opt = (char *)SvPV_nolen(val);
		else
		    opt = NULL;
		if (opt && strcasecmp(opt, "EASTASIAN") == 0)
		    self->options |= LINEBREAK_OPTION_EASTASIAN_CONTEXT;
		else
		    self->options &= ~LINEBREAK_OPTION_EASTASIAN_CONTEXT;
	    } else if (strcasecmp(key, "EAWidth") == 0) {
		AV *av, *codes;
		SV *sv;
		propval_t p;
		size_t i;

		if (! SvOK(val))
		    linebreak_clear_eawidth(self);
		else if (SvROK(val) &&
		    SvTYPE(av = (AV *)SvRV(val)) == SVt_PVAV &&
		    av_len(av) + 1 == 2 &&
		    av_fetch(av, 0, 0) != NULL && av_fetch(av, 1, 0) != NULL) {
		    sv = *av_fetch(av, 1, 0);
		    if (SvIOK(sv))
			p = (propval_t) SvIV(sv);
		    else
			croak("_config: Invalid argument");

		    sv = *av_fetch(av, 0, 0);
		    if (SvROK(sv) &&
			SvTYPE(codes = (AV *)SvRV(sv)) == SVt_PVAV) {
			for (i = 0; i < av_len(codes) + 1; i++) {
			    if (av_fetch(codes, i, 0) == NULL)
				continue;
			    if (! SvIOK(sv = *av_fetch(codes, i, 0)))
				croak("_config: Invalid argument");
			    linebreak_update_eawidth(self,
						     (unichar_t) SvUV(sv), p);
			}
		    } else if (SvIOK(sv)) {
			linebreak_update_eawidth(self, (unichar_t) SvUV(sv),
						 p);
		    } else
			croak("_config: Invalid argument");
		} else
		    croak("_config: Invalid argument");
	    } else if (strcasecmp(key, "HangulAsAL") == 0) {
		if (SVtoboolean(val))
		    self->options |= LINEBREAK_OPTION_HANGUL_AS_AL;
		else
		    self->options &= ~LINEBREAK_OPTION_HANGUL_AS_AL;
	    } else if (strcasecmp(key, "LBClass") == 0) {
		AV *av, *codes;
		SV *sv;
		propval_t p;
		size_t i;

		if (! SvOK(val))
		    linebreak_clear_lbclass(self);
		else if (SvROK(val) &&
		    SvTYPE(av = (AV *)SvRV(val)) == SVt_PVAV &&
		    av_len(av) + 1 == 2 &&
		    av_fetch(av, 0, 0) != NULL && av_fetch(av, 1, 0) != NULL) {
		    sv = *av_fetch(av, 1, 0);
		    if (SvIOK(sv))
			p = (propval_t) SvIV(sv);
		    else
			croak("_config: Invalid argument");

		    sv = *av_fetch(av, 0, 0);
		    if (SvROK(sv) &&
			SvTYPE(codes = (AV *)SvRV(sv)) == SVt_PVAV) {
			for (i = 0; i < av_len(codes) + 1; i++) {
			    if (av_fetch(codes, i, 0) == NULL)
				continue;
			    if (! SvIOK(sv = *av_fetch(codes, i, 0)))
				croak("_config: Invalid argument");
			    linebreak_update_lbclass(self,
						     (unichar_t) SvUV(sv), p);
			}
		    } else if (SvIOK(sv)) {
			linebreak_update_lbclass(self, (unichar_t) SvUV(sv),
						 p);
		    } else
			croak("_config: Invalid argument");
		} else
		    croak("_config: Invalid argument");
	    } else if (strcasecmp(key, "LegacyCM") == 0) {
		if (SVtoboolean(val))
		    self->options |= LINEBREAK_OPTION_LEGACY_CM;
		else
		    self->options &= ~LINEBREAK_OPTION_LEGACY_CM;
	    } else if (strcasecmp(key, "Newline") == 0) {
		if (!sv_isobject(val)) {
		    unistr_t unistr = {NULL, 0};
		    SVtounistr(&unistr, val);
		    linebreak_set_newline(self, &unistr);	
		    free(unistr.str);
		} else if (sv_derived_from(val, "Unicode::GCString"))
		    linebreak_set_newline(self,
					  (unistr_t *)PerltoC(gcstring_t *,
							      val));
		else
		    croak("_config: Unknown object %s",
			  HvNAME(SvSTASH(SvRV(val))));
	    } else if (strcasecmp(key, "ViramaAsJoiner") == 0) {
		if (SVtoboolean(val))
		    self->options |= LINEBREAK_OPTION_VIRAMA_AS_JOINER;
		else
		    self->options &= ~LINEBREAK_OPTION_VIRAMA_AS_JOINER;
	    } else
		warn("_config: Setting unknown option %s", key);
	}
#line 1303 "LineBreak.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__LineBreak_as_hashref); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_as_hashref)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	linebreak_t *	self;

	if (! sv_isobject(ST(0)))
	    croak("as_hashref: Not object");
	else if (sv_derived_from(ST(0), "Unicode::LineBreak"))
	    self = PerltoC(linebreak_t *, ST(0));
	else
	    croak("as_hashref: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1056 "LineBreak.xs"
	if (self->stash == NULL)
	    XSRETURN_UNDEF;
	ST(0) = self->stash; /* should not be mortal */
	XSRETURN(1);
#line 1333 "LineBreak.c"
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__LineBreak_as_scalarref); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_as_scalarref)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	linebreak_t *	self;
#line 1065 "LineBreak.xs"
	char buf[64];
#line 1349 "LineBreak.c"
	SV *	RETVAL;

	if (! sv_isobject(ST(0)))
	    croak("as_scalarref: Not object");
	else if (sv_derived_from(ST(0), "Unicode::LineBreak"))
	    self = PerltoC(linebreak_t *, ST(0));
	else
	    croak("as_scalarref: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1067 "LineBreak.xs"
	buf[0] = '\0';
	snprintf(buf, 64, "%s(0x%lx)", HvNAME(SvSTASH(SvRV(ST(0)))),
		 (unsigned long)(void *)self);
	RETVAL = newRV_noinc(newSVpv(buf, 0));
#line 1365 "LineBreak.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__LineBreak_as_string); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_as_string)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	linebreak_t *	self;
#line 1078 "LineBreak.xs"
	char buf[64];
#line 1383 "LineBreak.c"
	SV *	RETVAL;

	if (! sv_isobject(ST(0)))
	    croak("as_string: Not object");
	else if (sv_derived_from(ST(0), "Unicode::LineBreak"))
	    self = PerltoC(linebreak_t *, ST(0));
	else
	    croak("as_string: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1080 "LineBreak.xs"
	buf[0] = '\0';
	snprintf(buf, 64, "%s(0x%lx)", HvNAME(SvSTASH(SvRV(ST(0)))),
		 (unsigned long)(void *)self);
	RETVAL = newSVpv(buf, 0);
#line 1399 "LineBreak.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__LineBreak_lbrule); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_lbrule)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "self, b_idx, a_idx");
    {
	linebreak_t *	self;
	propval_t	b_idx = (unsigned char)SvUV(ST(1))
;
	propval_t	a_idx = (unsigned char)SvUV(ST(2))
;
	propval_t	RETVAL;
	dXSTARG;

	if (! sv_isobject(ST(0)))
	    croak("lbrule: Not object");
	else if (sv_derived_from(ST(0), "Unicode::LineBreak"))
	    self = PerltoC(linebreak_t *, ST(0));
	else
	    croak("lbrule: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1094 "LineBreak.xs"
	warn("lbrule() is obsoleted.  Use breakingRule()");
	if (!SvOK(ST(1)) || !SvOK(ST(2)))
	    XSRETURN_UNDEF;
	if (self == NULL)
	    XSRETURN_UNDEF;
	RETVAL = linebreak_get_lbrule(self, b_idx, a_idx);
	if (RETVAL == PROP_UNKNOWN)
	    XSRETURN_UNDEF;
#line 1439 "LineBreak.c"
	XSprePUSH; PUSHu((UV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__LineBreak_breakingRule); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_breakingRule)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "lbobj, bgcstr, agcstr");
    {
	linebreak_t *	lbobj;
	generic_string	bgcstr;
	generic_string	agcstr;
#line 1112 "LineBreak.xs"
	propval_t blbc, albc;
#line 1458 "LineBreak.c"
	propval_t	RETVAL;
	dXSTARG;

	if (! sv_isobject(ST(0)))
	    croak("breakingRule: Not object");
	else if (sv_derived_from(ST(0), "Unicode::LineBreak"))
	    lbobj = PerltoC(linebreak_t *, ST(0));
	else
	    croak("breakingRule: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;

	if (! SvOK(ST(1)))
	    bgcstr = NULL;
	else
	if (! sv_isobject(ST(1))) {
	    unistr_t unistr = { NULL, 0 };
	    /* Generic string must be well-formed. */
	    SVtounistr(&unistr, ST(1));
	    if ((bgcstr = gcstring_new(&unistr, lbobj)) == NULL)
		croak("breakingRule: %s", strerror(errno));
	    /* let Unicode buffer be mortal. */
	    sv_2mortal(CtoPerl("Unicode::GCString", bgcstr));
	    #undef lbobj
	} else
	if (sv_derived_from(ST(1), "Unicode::GCString"))
	    bgcstr = (generic_string)PerltoC(gcstring_t *, ST(1));
	else
	    croak("breakingRule: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(1)))))
;

	if (! SvOK(ST(2)))
	    agcstr = NULL;
	else
	if (! sv_isobject(ST(2))) {
	    unistr_t unistr = { NULL, 0 };
	    /* Generic string must be well-formed. */
	    SVtounistr(&unistr, ST(2));
	    if ((agcstr = gcstring_new(&unistr, lbobj)) == NULL)
		croak("breakingRule: %s", strerror(errno));
	    /* let Unicode buffer be mortal. */
	    sv_2mortal(CtoPerl("Unicode::GCString", agcstr));
	    #undef lbobj
	} else
	if (sv_derived_from(ST(2), "Unicode::GCString"))
	    agcstr = (generic_string)PerltoC(gcstring_t *, ST(2));
	else
	    croak("breakingRule: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(2)))))
;
#line 1114 "LineBreak.xs"
	if (!SvOK(ST(1)) || !SvOK(ST(2)))
	    XSRETURN_UNDEF;
	if (lbobj == NULL)
	    XSRETURN_UNDEF;
	if ((blbc = gcstring_lbclass_ext(bgcstr, -1)) == PROP_UNKNOWN)
	    XSRETURN_UNDEF;
	if ((albc = gcstring_lbclass(agcstr, 0)) == PROP_UNKNOWN)
	    XSRETURN_UNDEF;
	RETVAL = linebreak_get_lbrule(lbobj, blbc, albc);
	if (RETVAL == PROP_UNKNOWN)
	    XSRETURN_UNDEF;
#line 1522 "LineBreak.c"
	XSprePUSH; PUSHu((UV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__LineBreak_reset); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_reset)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "self");
    {
	linebreak_t *	self;

	if (! sv_isobject(ST(0)))
	    croak("reset: Not object");
	else if (sv_derived_from(ST(0), "Unicode::LineBreak"))
	    self = PerltoC(linebreak_t *, ST(0));
	else
	    croak("reset: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1133 "LineBreak.xs"
	linebreak_reset(self);
#line 1548 "LineBreak.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Unicode__LineBreak_strsize); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_strsize)
{
    dVAR; dXSARGS;
    if (items < 5)
       croak_xs_usage(cv,  "lbobj, len, pre, spc, str, ...");
    {
	linebreak_t *	lbobj;
	double	len = (double)SvNV(ST(1))
;
	SV *	pre = ST(2)
;
	generic_string	spc;
	generic_string	str;
	double	RETVAL;
	dXSTARG;

	if (! sv_isobject(ST(0)))
	    croak("strsize: Not object");
	else if (sv_derived_from(ST(0), "Unicode::LineBreak"))
	    lbobj = PerltoC(linebreak_t *, ST(0));
	else
	    croak("strsize: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;

	if (! SvOK(ST(3)))
	    spc = NULL;
	else
	if (! sv_isobject(ST(3))) {
	    unistr_t unistr = { NULL, 0 };
	    /* Generic string must be well-formed. */
	    SVtounistr(&unistr, ST(3));
	    if ((spc = gcstring_new(&unistr, lbobj)) == NULL)
		croak("strsize: %s", strerror(errno));
	    /* let Unicode buffer be mortal. */
	    sv_2mortal(CtoPerl("Unicode::GCString", spc));
	    #undef lbobj
	} else
	if (sv_derived_from(ST(3), "Unicode::GCString"))
	    spc = (generic_string)PerltoC(gcstring_t *, ST(3));
	else
	    croak("strsize: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(3)))))
;

	if (! SvOK(ST(4)))
	    str = NULL;
	else
	if (! sv_isobject(ST(4))) {
	    unistr_t unistr = { NULL, 0 };
	    /* Generic string must be well-formed. */
	    SVtounistr(&unistr, ST(4));
	    if ((str = gcstring_new(&unistr, lbobj)) == NULL)
		croak("strsize: %s", strerror(errno));
	    /* let Unicode buffer be mortal. */
	    sv_2mortal(CtoPerl("Unicode::GCString", str));
	    #undef lbobj
	} else
	if (sv_derived_from(ST(4), "Unicode::GCString"))
	    str = (generic_string)PerltoC(gcstring_t *, ST(4));
	else
	    croak("strsize: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(4)))))
;
#line 1144 "LineBreak.xs"
	warn("strsize() is obsoleted.  Use Unicode::GCString::columns");
	if (5 < items)
	     warn("``max'' argument of strsize was obsoleted");

	RETVAL = linebreak_sizing_UAX11(lbobj, len, NULL, spc, str);
	if (RETVAL == -1.0)
	    croak("strsize: %s", strerror(lbobj->errnum));
#line 1627 "LineBreak.c"
	XSprePUSH; PUSHn((double)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__LineBreak_break); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_break)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "self, input");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	linebreak_t *	self;
	unistr_t *	input;
#line 1160 "LineBreak.xs"
	gcstring_t **ret, *r;
	size_t i;
#line 1648 "LineBreak.c"

	if (! sv_isobject(ST(0)))
	    croak("break: Not object");
	else if (sv_derived_from(ST(0), "Unicode::LineBreak"))
	    self = PerltoC(linebreak_t *, ST(0));
	else
	    croak("break: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;

	if (! SvOK(ST(1)))
	    input = NULL;
	else
	if (! sv_isobject(ST(1))) {
	    gcstring_t *gcstr; /* container of buffer. */
	    if ((gcstr = malloc(sizeof(gcstring_t))) == NULL)
		croak("break: %s", strerror(errno));
	    memset(gcstr, 0, sizeof(gcstring_t));
	    /* String not being decoded must be treated as Unicode. */
	    if (! SvUTF8(ST(1)))
		SVupgradetounistr((unistr_t *)gcstr, ST(1));
	    else
		SVtounistr((unistr_t *)gcstr, ST(1));
	    input = (unistr_t *)gcstr;
	    /* let Unicode buffer be mortal. */
	    sv_2mortal(CtoPerl("Unicode::GCString", gcstr));
	} else
	if (sv_derived_from(ST(1), "Unicode::GCString"))
	    input = (unistr_t *)PerltoC(gcstring_t *, ST(1));
	else
	    croak("break: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(1)))))
;
#line 1163 "LineBreak.xs"
	if (input == NULL)
	    XSRETURN_UNDEF;
	ret = linebreak_break(self, input);

	if (ret == NULL) {
	    if (self->errnum == LINEBREAK_EEXTN)
		croak("%s", SvPV_nolen(ERRSV));
	    else if (self->errnum == LINEBREAK_ELONG)
		croak("%s", "Excessive line was found");
	    else if (self->errnum)
		croak("%s", strerror(self->errnum));
	    else
		croak("%s", "Unknown error");
	}

	switch (GIMME_V) {
	case G_SCALAR:
	    r = gcstring_new(NULL, self);
	    for (i = 0; ret[i] != NULL; i++)
		gcstring_append(r, ret[i]);
	    linebreak_free_result(ret, 1);
	    XPUSHs(sv_2mortal(unistrtoSV((unistr_t *)r, 0, r->len)));
	    gcstring_destroy(r);
	    XSRETURN(1);

	case G_ARRAY:
	    for (i = 0; ret[i] != NULL; i++)
		XPUSHs(sv_2mortal(CtoPerl("Unicode::GCString", ret[i])));
	    linebreak_free_result(ret, 0);
	    XSRETURN(i);

	default:
	    linebreak_free_result(ret, 1);
	    XSRETURN_EMPTY;
	}
#line 1718 "LineBreak.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Unicode__LineBreak_break_partial); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_break_partial)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "self, input");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	linebreak_t *	self;
	unistr_t *	input;
#line 1205 "LineBreak.xs"
	gcstring_t **ret, *r;
	size_t i;
#line 1739 "LineBreak.c"

	if (! sv_isobject(ST(0)))
	    croak("break_partial: Not object");
	else if (sv_derived_from(ST(0), "Unicode::LineBreak"))
	    self = PerltoC(linebreak_t *, ST(0));
	else
	    croak("break_partial: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;

	if (! SvOK(ST(1)))
	    input = NULL;
	else
	if (! sv_isobject(ST(1))) {
	    gcstring_t *gcstr; /* container of buffer. */
	    if ((gcstr = malloc(sizeof(gcstring_t))) == NULL)
		croak("break_partial: %s", strerror(errno));
	    memset(gcstr, 0, sizeof(gcstring_t));
	    /* String not being decoded must be treated as Unicode. */
	    if (! SvUTF8(ST(1)))
		SVupgradetounistr((unistr_t *)gcstr, ST(1));
	    else
		SVtounistr((unistr_t *)gcstr, ST(1));
	    input = (unistr_t *)gcstr;
	    /* let Unicode buffer be mortal. */
	    sv_2mortal(CtoPerl("Unicode::GCString", gcstr));
	} else
	if (sv_derived_from(ST(1), "Unicode::GCString"))
	    input = (unistr_t *)PerltoC(gcstring_t *, ST(1));
	else
	    croak("break_partial: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(1)))))
;
#line 1208 "LineBreak.xs"
	ret = linebreak_break_partial(self, input);

	if (ret == NULL) {
	    if (self->errnum == LINEBREAK_EEXTN)
		croak("%s", SvPV_nolen(ERRSV));
	    else if (self->errnum == LINEBREAK_ELONG)
		croak("%s", "Excessive line was found");
	    else if (self->errnum)
		croak("%s", strerror(self->errnum));
	    else
		croak("%s", "Unknown error");
	}

	switch (GIMME_V) {
	case G_SCALAR:
	    r = gcstring_new(NULL, self);
	    for (i = 0; ret[i] != NULL; i++)
		gcstring_append(r, ret[i]);
	    linebreak_free_result(ret, 1);
	    XPUSHs(sv_2mortal(unistrtoSV((unistr_t *)r, 0, r->len)));
	    gcstring_destroy(r);
	    XSRETURN(1);

	case G_ARRAY:
	    for (i = 0; ret[i] != NULL; i++)
		XPUSHs(sv_2mortal(CtoPerl("Unicode::GCString", ret[i])));
	    linebreak_free_result(ret, 0);
	    XSRETURN(i);

	default:
	    linebreak_free_result(ret, 1);
	    XSRETURN_EMPTY;
	}
#line 1807 "LineBreak.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Unicode__LineBreak_UNICODE_VERSION); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_UNICODE_VERSION)
{
    dVAR; dXSARGS;
    if (items != 0)
       croak_xs_usage(cv,  "");
    {
	const char *	RETVAL;
	dXSTARG;
#line 1245 "LineBreak.xs"
	RETVAL = linebreak_unicode_version;
#line 1825 "LineBreak.c"
	sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__LineBreak_SOMBOK_VERSION); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak_SOMBOK_VERSION)
{
    dVAR; dXSARGS;
    if (items != 0)
       croak_xs_usage(cv,  "");
    {
	const char *	RETVAL;
	dXSTARG;
#line 1252 "LineBreak.xs"
	RETVAL = SOMBOK_VERSION;
#line 1843 "LineBreak.c"
	sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__LineBreak__SouthEastAsian_supported); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__LineBreak__SouthEastAsian_supported)
{
    dVAR; dXSARGS;
    if (items != 0)
       croak_xs_usage(cv,  "");
    {
	const char *	RETVAL;
	dXSTARG;
#line 1263 "LineBreak.xs"
	RETVAL = linebreak_southeastasian_supported;
	if (RETVAL == NULL)
	    XSRETURN_UNDEF;
#line 1863 "LineBreak.c"
	sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString__new); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString__new)
{
    dVAR; dXSARGS;
    if (items < 2 || items > 3)
       croak_xs_usage(cv,  "klass, str, lbobj=NULL");
    {
	char *	klass = (char *)SvPV_nolen(ST(0))
;
	unistr_t *	str;
	linebreak_t *	lbobj;
	gcstring_t *	RETVAL;

	if (! SvOK(ST(1)))
	    str = NULL;
	else
	if (! sv_isobject(ST(1))) {
	    gcstring_t *gcstr; /* container of buffer. */
	    if ((gcstr = malloc(sizeof(gcstring_t))) == NULL)
		croak("_new: %s", strerror(errno));
	    memset(gcstr, 0, sizeof(gcstring_t));
	    /* String not being decoded must be treated as Unicode. */
	    if (! SvUTF8(ST(1)))
		SVupgradetounistr((unistr_t *)gcstr, ST(1));
	    else
		SVtounistr((unistr_t *)gcstr, ST(1));
	    str = (unistr_t *)gcstr;
	    /* let Unicode buffer be mortal. */
	    sv_2mortal(CtoPerl("Unicode::GCString", gcstr));
	} else
	if (sv_derived_from(ST(1), "Unicode::GCString"))
	    str = (unistr_t *)PerltoC(gcstring_t *, ST(1));
	else
	    croak("_new: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(1)))))
;

	if (items < 3)
	    lbobj = NULL;
	else {
	    if (! sv_isobject(ST(2)))
		croak("_new: Not object");
	    else if (sv_derived_from(ST(2), "Unicode::LineBreak"))
		lbobj = PerltoC(linebreak_t *, ST(2));
	    else
		croak("_new: Unknown object %s",
		      HvNAME(SvSTASH(SvRV(ST(2)))))
;
	}
#line 1278 "LineBreak.xs"
	if (str == NULL)
	    XSRETURN_UNDEF;
	/* FIXME:buffer is copied twice. */
	if ((RETVAL = gcstring_newcopy(str, lbobj)) == NULL)
	    croak("%s->_new: %s", klass, strerror(errno));
#line 1925 "LineBreak.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
	    setCtoPerl(RETVALSV, "Unicode::GCString", RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_DESTROY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "self");
    {
	gcstring_t *	self;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("DESTROY: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1291 "LineBreak.xs"
	gcstring_destroy(self);
#line 1957 "LineBreak.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Unicode__GCString_as_array); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_as_array)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "self");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
	gcstring_t *	self;
#line 1298 "LineBreak.xs"
	size_t i;
#line 1975 "LineBreak.c"

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("as_array: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1300 "LineBreak.xs"
	if (self != NULL)
	    for (i = 0; i < self->gclen; i++)
		XPUSHs(sv_2mortal(
			   CtoPerl("Unicode::GCString", 
				   gcstring_substr(self, i, 1))));
#line 1992 "LineBreak.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Unicode__GCString_as_scalarref); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_as_scalarref)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	gcstring_t *	self;
#line 1310 "LineBreak.xs"
	char buf[64];
#line 2009 "LineBreak.c"
	SV *	RETVAL;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("as_scalarref: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1312 "LineBreak.xs"
	buf[0] = '\0';
	snprintf(buf, 64, "%s(0x%lx)", HvNAME(SvSTASH(SvRV(ST(0)))),
		 (unsigned long)(void *)self);
	RETVAL = newRV_noinc(newSVpv(buf, 0));
#line 2026 "LineBreak.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_as_string); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_as_string)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	gcstring_t *	self;
	SV *	RETVAL;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("as_string: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1324 "LineBreak.xs"
	RETVAL = unistrtoSV((unistr_t *)self, 0, self->len);
#line 2055 "LineBreak.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_chars); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_chars)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "self");
    {
	gcstring_t *	self;
	size_t	RETVAL;
	dXSTARG;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("chars: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1333 "LineBreak.xs"
	RETVAL = self->len;
#line 2085 "LineBreak.c"
	XSprePUSH; PUSHu((UV)RETVAL);
    }
    XSRETURN(1);
}

#define lbobj self->lbobj

XS_EUPXS(XS_Unicode__GCString_cmp); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_cmp)
{
    dVAR; dXSARGS;
    if (items < 2 || items > 3)
       croak_xs_usage(cv,  "self, str, swap=FALSE");
    {
	gcstring_t *	self;
	generic_string	str;
	swapspec_t	swap;
	int	RETVAL;
	dXSTARG;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("cmp: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;

	if (! SvOK(ST(1)))
	    str = NULL;
	else
	if (! sv_isobject(ST(1))) {
	    unistr_t unistr = { NULL, 0 };
	    /* Generic string must be well-formed. */
	    SVtounistr(&unistr, ST(1));
	    if ((str = gcstring_new(&unistr, lbobj)) == NULL)
		croak("cmp: %s", strerror(errno));
	    /* let Unicode buffer be mortal. */
	    sv_2mortal(CtoPerl("Unicode::GCString", str));
	    #undef lbobj
	} else
	if (sv_derived_from(ST(1), "Unicode::GCString"))
	    str = (generic_string)PerltoC(gcstring_t *, ST(1));
	else
	    croak("cmp: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(1)))))
;

	if (items < 3)
	    swap = FALSE;
	else {
	    if (SvOK(ST(2)))
		swap = (IV)SvIV(ST(2));
	    else
		swap = -1
;
	}
#line 1345 "LineBreak.xs"
	if (swap == TRUE)
	    RETVAL = gcstring_cmp(str, self);
	else
	    RETVAL = gcstring_cmp(self, str);
#line 2150 "LineBreak.c"
	XSprePUSH; PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_columns); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_columns)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "self");
    {
	gcstring_t *	self;
	size_t	RETVAL;
	dXSTARG;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("columns: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1356 "LineBreak.xs"
	RETVAL = gcstring_columns(self);
#line 2179 "LineBreak.c"
	XSprePUSH; PUSHu((UV)RETVAL);
    }
    XSRETURN(1);
}

#define lbobj self->lbobj

XS_EUPXS(XS_Unicode__GCString_concat); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_concat)
{
    dVAR; dXSARGS;
    if (items < 2 || items > 3)
       croak_xs_usage(cv,  "self, str, swap=FALSE");
    {
	gcstring_t *	self;
	generic_string	str;
	swapspec_t	swap;
	gcstring_t *	RETVAL;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("concat: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;

	if (! SvOK(ST(1)))
	    str = NULL;
	else
	if (! sv_isobject(ST(1))) {
	    unistr_t unistr = { NULL, 0 };
	    /* Generic string must be well-formed. */
	    SVtounistr(&unistr, ST(1));
	    if ((str = gcstring_new(&unistr, lbobj)) == NULL)
		croak("concat: %s", strerror(errno));
	    /* let Unicode buffer be mortal. */
	    sv_2mortal(CtoPerl("Unicode::GCString", str));
	    #undef lbobj
	} else
	if (sv_derived_from(ST(1), "Unicode::GCString"))
	    str = (generic_string)PerltoC(gcstring_t *, ST(1));
	else
	    croak("concat: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(1)))))
;

	if (items < 3)
	    swap = FALSE;
	else {
	    if (SvOK(ST(2)))
		swap = (IV)SvIV(ST(2));
	    else
		swap = -1
;
	}
#line 1368 "LineBreak.xs"
	if (swap == TRUE)
	    RETVAL = gcstring_concat(str, self);
	else if (swap == -1) {
	    gcstring_append(self, str);
	    XSRETURN(1);
	} else
	    RETVAL = gcstring_concat(self, str);
#line 2246 "LineBreak.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
	    setCtoPerl(RETVALSV, "Unicode::GCString", RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_copy); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_copy)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "self");
    {
	gcstring_t *	self;
	gcstring_t *	RETVAL;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("copy: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1383 "LineBreak.xs"
	RETVAL = gcstring_copy(self);
#line 2279 "LineBreak.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
	    setCtoPerl(RETVALSV, "Unicode::GCString", RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_eos); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_eos)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "self");
    {
	gcstring_t *	self;
	int	RETVAL;
	dXSTARG;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("eos: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1391 "LineBreak.xs"
	RETVAL = gcstring_eos(self);
#line 2313 "LineBreak.c"
	XSprePUSH; PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_flag); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_flag)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	gcstring_t *	self;
#line 1400 "LineBreak.xs"
	int i;
	unsigned int flag;
#line 2331 "LineBreak.c"
	unsigned int	RETVAL;
	dXSTARG;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("flag: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1403 "LineBreak.xs"
	warn("flag() will be deprecated in near future");
	if (1 < items)
	    i = SvIV(ST(1));
	else
	    i = self->pos;
	if (i < 0 || self == NULL || self->gclen <= i)
	    XSRETURN_UNDEF;
	if (2 < items) {
	    flag = SvUV(ST(2));
	    if (flag == (flag & 255))
		self->gcstr[i].flag = (unsigned char)flag;
	    else
		warn("flag: unknown flag(s)");
	}
	RETVAL = (unsigned int)self->gcstr[i].flag;
#line 2360 "LineBreak.c"
	XSprePUSH; PUSHu((UV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_item); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_item)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	gcstring_t *	self;
#line 1426 "LineBreak.xs"
	int i;
#line 2377 "LineBreak.c"
	gcstring_t *	RETVAL;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("item: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1428 "LineBreak.xs"
	if (1 < items)
	    i = SvIV(ST(1));
	else
	    i = self->pos;
	if (i < 0 || self == NULL || self->gclen <= i)
	    XSRETURN_UNDEF;

	RETVAL = gcstring_substr(self, i, 1);
#line 2398 "LineBreak.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
	    setCtoPerl(RETVALSV, "Unicode::GCString", RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_join); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_join)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	gcstring_t *	self;
#line 1443 "LineBreak.xs"
	size_t i;
	gcstring_t *str;
#line 2421 "LineBreak.c"
	gcstring_t *	RETVAL;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("join: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1446 "LineBreak.xs"
	switch (items) {
	case 0:
	    croak("join: Too few arguments");
	case 1:
	    RETVAL = gcstring_new(NULL, self->lbobj);
	    break;
	case 2:
	    RETVAL = SVtogcstring(ST(1), self->lbobj);
	    if (sv_isobject(ST(1)))
		RETVAL = gcstring_copy(RETVAL);
	    break;
	default:
	    RETVAL = SVtogcstring(ST(1), self->lbobj);
	    if (sv_isobject(ST(1)))
		RETVAL = gcstring_copy(RETVAL);
	    for (i = 2; i < items; i++) {
		gcstring_append(RETVAL, self);
		str = SVtogcstring(ST(i), self->lbobj);
		gcstring_append(RETVAL, str);
		if (!sv_isobject(ST(i)))
		    gcstring_destroy(str);
	    }
	    break;
	}
#line 2458 "LineBreak.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
	    setCtoPerl(RETVALSV, "Unicode::GCString", RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_lbc); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_lbc)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "self");
    {
	gcstring_t *	self;
	propval_t	RETVAL;
	dXSTARG;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("lbc: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1478 "LineBreak.xs"
	if ((RETVAL = gcstring_lbclass(self, 0)) == PROP_UNKNOWN)
	    XSRETURN_UNDEF;
#line 2493 "LineBreak.c"
	XSprePUSH; PUSHu((UV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_lbcext); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_lbcext)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "self");
    {
	gcstring_t *	self;
	propval_t	RETVAL;
	dXSTARG;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("lbcext: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1488 "LineBreak.xs"
	if ((RETVAL = gcstring_lbclass_ext(self, -1)) == PROP_UNKNOWN)
	    XSRETURN_UNDEF;
#line 2523 "LineBreak.c"
	XSprePUSH; PUSHu((UV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_lbclass); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_lbclass)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	gcstring_t *	self;
#line 1498 "LineBreak.xs"
	int i;
#line 2540 "LineBreak.c"
	propval_t	RETVAL;
	dXSTARG;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("lbclass: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1500 "LineBreak.xs"
	warn("lbclass() is obsoleted.  Use lbc()");
	if (1 < items)
	    i = SvIV(ST(1));
	else
	    i = self->pos;
	RETVAL = gcstring_lbclass(self, i);
	if (RETVAL == PROP_UNKNOWN)
	    XSRETURN_UNDEF;
#line 2562 "LineBreak.c"
	XSprePUSH; PUSHu((UV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_lbclass_ext); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_lbclass_ext)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	gcstring_t *	self;
#line 1516 "LineBreak.xs"
	int i;
#line 2579 "LineBreak.c"
	propval_t	RETVAL;
	dXSTARG;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("lbclass_ext: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1518 "LineBreak.xs"
	warn("lbclass_ext() is obsoleted.  Use lbcext()");
	if (1 < items)
	    i = SvIV(ST(1));
	else
	    i = self->pos;
	RETVAL = gcstring_lbclass_ext(self, i);
	if (RETVAL == PROP_UNKNOWN)
	    XSRETURN_UNDEF;
#line 2601 "LineBreak.c"
	XSprePUSH; PUSHu((UV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_length); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_length)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "self");
    {
	gcstring_t *	self;
	size_t	RETVAL;
	dXSTARG;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("length: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1534 "LineBreak.xs"
	RETVAL = self->gclen;
#line 2630 "LineBreak.c"
	XSprePUSH; PUSHu((UV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_next); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_next)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	gcstring_t *	self;
#line 1543 "LineBreak.xs"
	gcchar_t *gc;
#line 2647 "LineBreak.c"
	gcstring_t *	RETVAL;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("next: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1545 "LineBreak.xs"
	if (gcstring_eos(self))
	    XSRETURN_UNDEF;
	gc = gcstring_next(self);
	RETVAL = gcstring_substr(self, gc - self->gcstr, 1);
#line 2664 "LineBreak.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
	    setCtoPerl(RETVALSV, "Unicode::GCString", RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Unicode__GCString_pos); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_pos)
{
    dVAR; dXSARGS;
    if (items < 1)
       croak_xs_usage(cv,  "self, ...");
    {
	gcstring_t *	self;
	size_t	RETVAL;
	dXSTARG;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("pos: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;
#line 1557 "LineBreak.xs"
	if (1 < items)
	    gcstring_setpos(self, SvIV(ST(1)));
	RETVAL = self->pos;
#line 2700 "LineBreak.c"
	XSprePUSH; PUSHu((UV)RETVAL);
    }
    XSRETURN(1);
}

#define lbobj self->lbobj

XS_EUPXS(XS_Unicode__GCString_substr); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Unicode__GCString_substr)
{
    dVAR; dXSARGS;
    if (items < 2 || items > 4)
       croak_xs_usage(cv,  "self, offset, length=self->gclen, replacement=NULL");
    {
	gcstring_t *	self;
	int	offset = (int)SvIV(ST(1))
;
	int	length;
	generic_string	replacement;
	gcstring_t *	RETVAL;

	if (! SvOK(ST(0)))
	    self = NULL;
	else
	if (sv_derived_from(ST(0), "Unicode::GCString"))
	    self = (gcstring_t *)PerltoC(gcstring_t *, ST(0));
	else
	    croak("substr: Unknown object %s",
		  HvNAME(SvSTASH(SvRV(ST(0)))))
;

	if (items < 3)
	    length = self->gclen;
	else {
	    length = (int)SvIV(ST(2))
;
	}

	if (items < 4)
	    replacement = NULL;
	else {
	    if (! SvOK(ST(3)))
		replacement = NULL;
	    else
	    if (! sv_isobject(ST(3))) {
		unistr_t unistr = { NULL, 0 };
		/* Generic string must be well-formed. */
		SVtounistr(&unistr, ST(3));
		if ((replacement = gcstring_new(&unistr, lbobj)) == NULL)
		    croak("substr: %s", strerror(errno));
		/* let Unicode buffer be mortal. */
		sv_2mortal(CtoPerl("Unicode::GCString", replacement));
		#undef lbobj
	    } else
	    if (sv_derived_from(ST(3), "Unicode::GCString"))
		replacement = (generic_string)PerltoC(gcstring_t *, ST(3));
	    else
		croak("substr: Unknown object %s",
		      HvNAME(SvSTASH(SvRV(ST(3)))))
;
	}
#line 1572 "LineBreak.xs"
	RETVAL = gcstring_substr(self, offset, length);
	if (replacement != NULL)
	    if (gcstring_replace(self, offset, length, replacement) == NULL)
		croak("substr: %s", strerror(errno));
	if (RETVAL == NULL)
	    croak("substr: %s", strerror(errno));
#line 2769 "LineBreak.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
	    setCtoPerl(RETVALSV, "Unicode::GCString", RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}

#ifdef __cplusplus
extern "C"
#endif
XS_EXTERNAL(boot_Unicode__LineBreak); /* prototype to pass -Wmissing-prototypes */
XS_EXTERNAL(boot_Unicode__LineBreak)
{
#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

        newXS_deffile("Unicode::LineBreak::EAWidths", XS_Unicode__LineBreak_EAWidths);
        newXS_deffile("Unicode::LineBreak::LBClasses", XS_Unicode__LineBreak_LBClasses);
        (void)newXSproto_portable("Unicode::LineBreak::_new", XS_Unicode__LineBreak__new, file, "$");
        (void)newXSproto_portable("Unicode::LineBreak::copy", XS_Unicode__LineBreak_copy, file, "$");
        (void)newXSproto_portable("Unicode::LineBreak::DESTROY", XS_Unicode__LineBreak_DESTROY, file, "$");
        newXS_deffile("Unicode::LineBreak::_config", XS_Unicode__LineBreak__config);
        newXS_deffile("Unicode::LineBreak::as_hashref", XS_Unicode__LineBreak_as_hashref);
        newXS_deffile("Unicode::LineBreak::as_scalarref", XS_Unicode__LineBreak_as_scalarref);
        newXS_deffile("Unicode::LineBreak::as_string", XS_Unicode__LineBreak_as_string);
        (void)newXSproto_portable("Unicode::LineBreak::lbrule", XS_Unicode__LineBreak_lbrule, file, "$$$");
        (void)newXSproto_portable("Unicode::LineBreak::breakingRule", XS_Unicode__LineBreak_breakingRule, file, "$$$");
        (void)newXSproto_portable("Unicode::LineBreak::reset", XS_Unicode__LineBreak_reset, file, "$");
        (void)newXSproto_portable("Unicode::LineBreak::strsize", XS_Unicode__LineBreak_strsize, file, "$$$$$;$");
        (void)newXSproto_portable("Unicode::LineBreak::break", XS_Unicode__LineBreak_break, file, "$$");
        (void)newXSproto_portable("Unicode::LineBreak::break_partial", XS_Unicode__LineBreak_break_partial, file, "$$");
        newXS_deffile("Unicode::LineBreak::UNICODE_VERSION", XS_Unicode__LineBreak_UNICODE_VERSION);
        newXS_deffile("Unicode::LineBreak::SOMBOK_VERSION", XS_Unicode__LineBreak_SOMBOK_VERSION);
        (void)newXSproto_portable("Unicode::LineBreak::SouthEastAsian::supported", XS_Unicode__LineBreak__SouthEastAsian_supported, file, "");
        (void)newXSproto_portable("Unicode::GCString::_new", XS_Unicode__GCString__new, file, "$$;$");
        (void)newXSproto_portable("Unicode::GCString::DESTROY", XS_Unicode__GCString_DESTROY, file, "$");
        (void)newXSproto_portable("Unicode::GCString::as_array", XS_Unicode__GCString_as_array, file, "$");
        newXS_deffile("Unicode::GCString::as_scalarref", XS_Unicode__GCString_as_scalarref);
        (void)newXSproto_portable("Unicode::GCString::as_string", XS_Unicode__GCString_as_string, file, "$;$;$");
        (void)newXSproto_portable("Unicode::GCString::chars", XS_Unicode__GCString_chars, file, "$");
        (void)newXSproto_portable("Unicode::GCString::cmp", XS_Unicode__GCString_cmp, file, "$$;$");
        newXS_deffile("Unicode::GCString::columns", XS_Unicode__GCString_columns);
        (void)newXSproto_portable("Unicode::GCString::concat", XS_Unicode__GCString_concat, file, "$$;$");
        (void)newXSproto_portable("Unicode::GCString::copy", XS_Unicode__GCString_copy, file, "$");
        newXS_deffile("Unicode::GCString::eos", XS_Unicode__GCString_eos);
        (void)newXSproto_portable("Unicode::GCString::flag", XS_Unicode__GCString_flag, file, "$;$;$");
        (void)newXSproto_portable("Unicode::GCString::item", XS_Unicode__GCString_item, file, "$;$");
        newXS_deffile("Unicode::GCString::join", XS_Unicode__GCString_join);
        (void)newXSproto_portable("Unicode::GCString::lbc", XS_Unicode__GCString_lbc, file, "$");
        (void)newXSproto_portable("Unicode::GCString::lbcext", XS_Unicode__GCString_lbcext, file, "$");
        (void)newXSproto_portable("Unicode::GCString::lbclass", XS_Unicode__GCString_lbclass, file, "$;$");
        (void)newXSproto_portable("Unicode::GCString::lbclass_ext", XS_Unicode__GCString_lbclass_ext, file, "$;$");
        (void)newXSproto_portable("Unicode::GCString::length", XS_Unicode__GCString_length, file, "$");
        (void)newXSproto_portable("Unicode::GCString::next", XS_Unicode__GCString_next, file, "$;$;$");
        (void)newXSproto_portable("Unicode::GCString::pos", XS_Unicode__GCString_pos, file, "$;$");
        (void)newXSproto_portable("Unicode::GCString::substr", XS_Unicode__GCString_substr, file, "$$;$;$");
#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
}

