+ /* Returns a copy of a swash initiated by the called function. This is the
+ * public interface, and returning a copy prevents others from doing
+ * mischief on the original */
+
+ return newSVsv(_core_swash_init(pkg, name, listsv, minbits, none, NULL, NULL));
+}
+
+SV*
+Perl__core_swash_init(pTHX_ const char* pkg, const char* name, SV *listsv, I32 minbits, I32 none, SV* invlist, U8* const flags_p)
+{
+ /* Initialize and return a swash, creating it if necessary. It does this
+ * by calling utf8_heavy.pl in the general case. The returned value may be
+ * the swash's inversion list instead if the input parameters allow it.
+ * Which is returned should be immaterial to callers, as the only
+ * operations permitted on a swash, swash_fetch() and
+ * _get_swash_invlist(), handle both these transparently.
+ *
+ * This interface should only be used by functions that won't destroy or
+ * adversely change the swash, as doing so affects all other uses of the
+ * swash in the program; the general public should use 'Perl_swash_init'
+ * instead.
+ *
+ * pkg is the name of the package that <name> should be in.
+ * name is the name of the swash to find. Typically it is a Unicode
+ * property name, including user-defined ones
+ * listsv is a string to initialize the swash with. It must be of the form
+ * documented as the subroutine return value in
+ * L<perlunicode/User-Defined Character Properties>
+ * minbits is the number of bits required to represent each data element.
+ * It is '1' for binary properties.
+ * none I (khw) do not understand this one, but it is used only in tr///.
+ * invlist is an inversion list to initialize the swash with (or NULL)
+ * flags_p if non-NULL is the address of various input and output flag bits
+ * to the routine, as follows: ('I' means is input to the routine;
+ * 'O' means output from the routine. Only flags marked O are
+ * meaningful on return.)
+ * _CORE_SWASH_INIT_USER_DEFINED_PROPERTY indicates if the swash
+ * came from a user-defined property. (I O)
+ * _CORE_SWASH_INIT_RETURN_IF_UNDEF indicates that instead of croaking
+ * when the swash cannot be located, to simply return NULL. (I)
+ * _CORE_SWASH_INIT_ACCEPT_INVLIST indicates that the caller will accept a
+ * return of an inversion list instead of a swash hash if this routine
+ * thinks that would result in faster execution of swash_fetch() later
+ * on. (I)
+ *
+ * Thus there are three possible inputs to find the swash: <name>,
+ * <listsv>, and <invlist>. At least one must be specified. The result
+ * will be the union of the specified ones, although <listsv>'s various
+ * actions can intersect, etc. what <name> gives.
+ *
+ * <invlist> is only valid for binary properties */
+
+ dVAR;
+ SV* retval = &PL_sv_undef;
+ HV* swash_hv = NULL;
+ const int invlist_swash_boundary =
+ (flags_p && *flags_p & _CORE_SWASH_INIT_ACCEPT_INVLIST)
+ ? 512 /* Based on some benchmarking, but not extensive, see commit
+ message */
+ : -1; /* Never return just an inversion list */
+
+ assert(listsv != &PL_sv_undef || strNE(name, "") || invlist);
+ assert(! invlist || minbits == 1);
+
+ /* If data was passed in to go out to utf8_heavy to find the swash of, do
+ * so */
+ if (listsv != &PL_sv_undef || strNE(name, "")) {
+ dSP;
+ const size_t pkg_len = strlen(pkg);
+ const size_t name_len = strlen(name);
+ HV * const stash = gv_stashpvn(pkg, pkg_len, 0);
+ SV* errsv_save;
+ GV *method;
+
+ PERL_ARGS_ASSERT__CORE_SWASH_INIT;
+
+ PUSHSTACKi(PERLSI_MAGIC);