-/* Posix and regular space differ only in U+000B, which is in ASCII (and hence
- * Latin1 */
-#define isPSXSPC_utf8(p) _generic_utf8(_CC_PSXSPC, is_XPERLSPACE_high, p)
-
-#define isALNUM_LC_utf8(p) isALNUM_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-#define isIDFIRST_LC_utf8(p) isIDFIRST_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-#define isALPHA_LC_utf8(p) isALPHA_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-#define isBLANK_LC_utf8(p) isBLANK_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-#define isSPACE_LC_utf8(p) isSPACE_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-#define isDIGIT_LC_utf8(p) isDIGIT_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-#define isUPPER_LC_utf8(p) isUPPER_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-#define isLOWER_LC_utf8(p) isLOWER_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-#define isALNUMC_LC_utf8(p) isALNUMC_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-#define isCNTRL_LC_utf8(p) isCNTRL_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-#define isGRAPH_LC_utf8(p) isGRAPH_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-#define isPRINT_LC_utf8(p) isPRINT_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-#define isPUNCT_LC_utf8(p) isPUNCT_LC_uvchr(valid_utf8_to_uvchr(p, 0))
-
-#define isPSXSPC_LC_utf8(c) (isSPACE_LC_utf8(c) ||(c) == '\f')
+/* For internal core Perl use only. If the input is in the Latin1 range, use
+ * the macro 'macro' on 'p' which is a pointer to a UTF-8 string. Otherwise
+ * use the value given by the 'utf8' parameter. This relies on the fact that
+ * ASCII characters have the same representation whether utf8 or not. Note
+ * that it assumes that the utf8 has been validated, and ignores 'use bytes' */
+#define _generic_LC_utf8(macro, p, utf8) \
+ (UTF8_IS_INVARIANT(*(p)) \
+ ? macro(*(p)) \
+ : (UTF8_IS_DOWNGRADEABLE_START(*(p))) \
+ ? macro(TWO_BYTE_UTF8_TO_UNI(*(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)
+
+/* Macros for backwards compatibility and for completeness when the ASCII and
+ * Latin1 values are identical */
+#define isALPHAU(c) isALPHA_L1(c)
+#define isDIGIT_L1(c) isDIGIT_A(c)
+#define isOCTAL(c) isOCTAL_A(c)
+#define isOCTAL_L1(c) isOCTAL_A(c)
+#define isXDIGIT_L1(c) isXDIGIT_A(c)
+#define isALNUM(c) isWORDCHAR(c)
+#define isALNUMU(c) isWORDCHAR_L1(c)
+#define isALNUM_LC(c) isWORDCHAR_LC(c)
+#define isALNUM_uni(c) isWORDCHAR_uni(c)
+#define isALNUM_LC_uvchr(c) isWORDCHAR_LC_uvchr(c)
+#define isALNUM_utf8(p) isWORDCHAR_utf8(p)
+#define isALNUM_LC_utf8(p) isWORDCHAR_LC_utf8(p)
+#define isALNUMC_A(c) isALPHANUMERIC_A(c) /* Mnemonic: "C's alnum" */
+#define isALNUMC_L1(c) isALPHANUMERIC_L1(c)
+#define isALNUMC(c) isALPHANUMERIC(c)
+#define isALNUMC_LC(c) isALPHANUMERIC_LC(c)
+#define isALNUMC_uni(c) isALPHANUMERIC_uni(c)
+#define isALNUMC_LC_uvchr(c) isALPHANUMERIC_LC_uvchr(c)
+#define isALNUMC_utf8(p) isALPHANUMERIC_utf8(p)
+#define isALNUMC_LC_utf8(p) isALPHANUMERIC_LC_utf8(p)