/*
* Locale-independent macros for testing character properties and
- * stripping the 8th bit from characters. Assumed to be handed
- * a value between 0 and 255, i.e. don't hand them a char, as
- * those might be in the range -128 to 127.
+ * stripping the 8th bit from characters.
+ *
+ * Byte values outside the ASCII range are considered unprintable, so
+ * both ND_ISPRINT() and ND_ISGRAPH() return "false" for them.
+ *
+ * Assumed to be handed a value between 0 and 255, i.e. don't hand them
+ * a char, as those might be in the range -128 to 127.
*/
#define ND_ISASCII(c) (!((c) & 0x80)) /* value is an ASCII code point */
#define ND_ISPRINT(c) ((c) >= 0x20 && (c) <= 0x7E)
#define ND_ISGRAPH(c) ((c) > 0x20 && (c) <= 0x7E)
#define ND_TOASCII(c) ((c) & 0x7F)
+/*
+ * Locale-independent macros for coverting to upper or lower case.
+ *
+ * Byte values outside the ASCII range are not converted. Byte values
+ * *in* the ASCII range are converted to byte values in the ASCII range;
+ * in particular, 'i' is upper-cased to 'I" and 'I' is lower-cased to 'i',
+ * even in Turkish locales.
+ *
+ * Assumed to be handed a value between 0 and 255, i.e. don't hand
+ * them a char, as those might be in the range -128 to 127.
+ */
+#define ND_TOLOWER(c) (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))
+#define ND_TOUPPER(c) (((c) >= 'a' && (c) <= 'z') ? (c) - 'a' + 'z' : (c))
+
#if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \
(defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \
(defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \