-#define _generic_LC_utf8(macro, p, utf8) \
- (UTF8_IS_INVARIANT(*(p)) \
- ? macro(*(p)) \
- : (UTF8_IS_DOWNGRADEABLE_START(*(p))) \
- ? macro(TWO_BYTE_UTF8_TO_NATIVE(*(p), *((p)+1))) \
- : utf8)
-
-#define _generic_LC_swash_utf8(macro, classnum, p) \
- _generic_LC_utf8(macro, p, _is_utf8_FOO(classnum, p))
-#define _generic_LC_func_utf8(macro, above_latin1, p) \
- _generic_LC_utf8(macro, p, above_latin1(p))
-
-#define isALPHANUMERIC_LC_utf8(p) _generic_LC_swash_utf8(isALPHANUMERIC_LC, \
- _CC_ALPHANUMERIC, p)
-#define isALPHA_LC_utf8(p) _generic_LC_swash_utf8(isALPHA_LC, _CC_ALPHA, p)
-#define isASCII_LC_utf8(p) isASCII_LC(*p)
-#define isBLANK_LC_utf8(p) _generic_LC_func_utf8(isBLANK_LC, is_HORIZWS_high, p)
-#define isCNTRL_LC_utf8(p) _generic_LC_utf8(isCNTRL_LC, p, 0)
-#define isDIGIT_LC_utf8(p) _generic_LC_swash_utf8(isDIGIT_LC, _CC_DIGIT, p)
-#define isGRAPH_LC_utf8(p) _generic_LC_swash_utf8(isGRAPH_LC, _CC_GRAPH, p)
-#define isIDCONT_LC_utf8(p) _generic_LC_func_utf8(isIDCONT_LC, _is_utf8_perl_idcont, p)
-#define isIDFIRST_LC_utf8(p) _generic_LC_func_utf8(isIDFIRST_LC, _is_utf8_perl_idstart, p)
-#define isLOWER_LC_utf8(p) _generic_LC_swash_utf8(isLOWER_LC, _CC_LOWER, p)
-#define isPRINT_LC_utf8(p) _generic_LC_swash_utf8(isPRINT_LC, _CC_PRINT, p)
-#define isPSXSPC_LC_utf8(p) isSPACE_LC_utf8(p) /* space is identical to posix
- space under locale */
-#define isPUNCT_LC_utf8(p) _generic_LC_swash_utf8(isPUNCT_LC, _CC_PUNCT, p)
-#define isSPACE_LC_utf8(p) _generic_LC_func_utf8(isSPACE_LC, is_XPERLSPACE_high, p)
-#define isUPPER_LC_utf8(p) _generic_LC_swash_utf8(isUPPER_LC, _CC_UPPER, p)
-#define isWORDCHAR_LC_utf8(p) _generic_LC_swash_utf8(isWORDCHAR_LC, \
- _CC_WORDCHAR, p)
-#define isXDIGIT_LC_utf8(p) _generic_LC_func_utf8(isXDIGIT_LC, is_XDIGIT_high, p)
+#define _generic_LC_utf8(name, p) _base_generic_utf8(name, name, p, 1)
+
+#define isALPHA_LC_utf8(p) _generic_LC_utf8(ALPHA, p)
+#define isALPHANUMERIC_LC_utf8(p) _generic_LC_utf8(ALPHANUMERIC, p)
+#define isASCII_LC_utf8(p) _generic_LC_utf8(ASCII, p)
+#define isBLANK_LC_utf8(p) _generic_LC_utf8(BLANK, p)
+#define isCNTRL_LC_utf8(p) _generic_LC_utf8(CNTRL, p)
+#define isDIGIT_LC_utf8(p) _generic_LC_utf8(DIGIT, p)
+#define isGRAPH_LC_utf8(p) _generic_LC_utf8(GRAPH, p)
+#define isIDCONT_LC_utf8(p) _generic_LC_utf8(IDCONT, p)
+#define isIDFIRST_LC_utf8(p) _generic_LC_utf8(IDFIRST, p)
+#define isLOWER_LC_utf8(p) _generic_LC_utf8(LOWER, p)
+#define isPRINT_LC_utf8(p) _generic_LC_utf8(PRINT, p)
+#define isPSXSPC_LC_utf8(p) _generic_LC_utf8(PSXSPC, p)
+#define isPUNCT_LC_utf8(p) _generic_LC_utf8(PUNCT, p)
+#define isSPACE_LC_utf8(p) _generic_LC_utf8(SPACE, p)
+#define isUPPER_LC_utf8(p) _generic_LC_utf8(UPPER, p)
+#define isWORDCHAR_LC_utf8(p) _generic_LC_utf8(WORDCHAR, p)
+#define isXDIGIT_LC_utf8(p) _generic_LC_utf8(XDIGIT, p)
+
+/* For internal core Perl use only: the base macros for defining macros like
+ * isALPHA_LC_utf8_safe. These are like _generic_utf8, but if the first code
+ * point in 'p' is within the 0-255 range, it uses locale rules from the
+ * passed-in 'macro' parameter */
+#define _generic_LC_utf8_safe(macro, p, e, above_latin1) \
+ (__ASSERT_(_utf8_safe_assert(p, e)) \
+ (UTF8_IS_INVARIANT(*(p))) \
+ ? macro(*(p)) \
+ : (UTF8_IS_DOWNGRADEABLE_START(*(p)) \
+ ? ((LIKELY((e) - (p) > 1 && UTF8_IS_CONTINUATION(*((p)+1)))) \
+ ? macro(EIGHT_BIT_UTF8_TO_NATIVE(*(p), *((p)+1))) \
+ : (_force_out_malformed_utf8_message( \
+ (U8 *) (p), (U8 *) (e), 0, 1), 0)) \
+ : above_latin1))
+
+#define _generic_LC_swash_utf8_safe(macro, classnum, p, e) \
+ _generic_LC_utf8_safe(macro, p, e, \
+ _is_utf8_FOO_with_len(classnum, p, e))
+
+#define _generic_LC_func_utf8_safe(macro, above_latin1, p, e) \
+ _generic_LC_utf8_safe(macro, p, e, above_latin1(p, e))
+
+#define _generic_LC_non_swash_utf8_safe(classnum, above_latin1, p, e) \
+ _generic_LC_utf8_safe(classnum, p, e, \
+ (UNLIKELY((e) - (p) < UTF8SKIP(p)) \
+ ? (_force_out_malformed_utf8_message( \
+ (U8 *) (p), (U8 *) (e), 0, 1), 0) \
+ : above_latin1(p)))
+
+#define isALPHANUMERIC_LC_utf8_safe(p, e) \
+ _generic_LC_swash_utf8_safe(isALPHANUMERIC_LC, \
+ _CC_ALPHANUMERIC, p, e)
+#define isALPHA_LC_utf8_safe(p, e) \
+ _generic_LC_swash_utf8_safe(isALPHA_LC, _CC_ALPHA, p, e)
+#define isASCII_LC_utf8_safe(p, e) \
+ (__ASSERT_(_utf8_safe_assert(p, e)) isASCII_LC(*(p)))
+#define isBLANK_LC_utf8_safe(p, e) \
+ _generic_LC_non_swash_utf8_safe(isBLANK_LC, is_HORIZWS_high, p, e)
+#define isCNTRL_LC_utf8_safe(p, e) \
+ _generic_LC_utf8_safe(isCNTRL_LC, p, e, 0)
+#define isDIGIT_LC_utf8_safe(p, e) \
+ _generic_LC_swash_utf8_safe(isDIGIT_LC, _CC_DIGIT, p, e)
+#define isGRAPH_LC_utf8_safe(p, e) \
+ _generic_LC_swash_utf8_safe(isGRAPH_LC, _CC_GRAPH, p, e)
+#define isIDCONT_LC_utf8_safe(p, e) \
+ _generic_LC_func_utf8_safe(isIDCONT_LC, \
+ _is_utf8_perl_idcont_with_len, p, e)
+#define isIDFIRST_LC_utf8_safe(p, e) \
+ _generic_LC_func_utf8_safe(isIDFIRST_LC, \
+ _is_utf8_perl_idstart_with_len, p, e)
+#define isLOWER_LC_utf8_safe(p, e) \
+ _generic_LC_swash_utf8_safe(isLOWER_LC, _CC_LOWER, p, e)
+#define isPRINT_LC_utf8_safe(p, e) \
+ _generic_LC_swash_utf8_safe(isPRINT_LC, _CC_PRINT, p, e)
+#define isPSXSPC_LC_utf8_safe(p, e) isSPACE_LC_utf8_safe(p, e)
+#define isPUNCT_LC_utf8_safe(p, e) \
+ _generic_LC_swash_utf8_safe(isPUNCT_LC, _CC_PUNCT, p, e)
+#define isSPACE_LC_utf8_safe(p, e) \
+ _generic_LC_non_swash_utf8_safe(isSPACE_LC, is_XPERLSPACE_high, p, e)
+#define isUPPER_LC_utf8_safe(p, e) \
+ _generic_LC_swash_utf8_safe(isUPPER_LC, _CC_UPPER, p, e)
+#define isWORDCHAR_LC_utf8_safe(p, e) \
+ _generic_LC_swash_utf8_safe(isWORDCHAR_LC, _CC_WORDCHAR, p, e)
+#define isXDIGIT_LC_utf8_safe(p, e) \
+ _generic_LC_non_swash_utf8_safe(isXDIGIT_LC, is_XDIGIT_high, p, e)