From 56e1d04ae71a05586fa3414aabdef0de720d0720 Mon Sep 17 00:00:00 2001
From: Ron Yorston <rmy@pobox.com>
Date: Mon, 9 Aug 2021 14:58:37 +0100
Subject: win32: code shrink character class detection

Add a routine to detect the names of character classes.  Use it
in fnmatch(3) and regcomp(3), replacing local code in the former.

Saves 216 bytes.
---
 win32/Kbuild        |  1 +
 win32/fnmatch.c     | 32 ++++++++++++++------------------
 win32/match_class.c |  7 +++++++
 win32/match_class.h | 11 +++++++++++
 win32/regcomp.c     | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 83 insertions(+), 18 deletions(-)
 create mode 100644 win32/match_class.c
 create mode 100644 win32/match_class.h

diff --git a/win32/Kbuild b/win32/Kbuild
index cabd70849..6ab0dc077 100644
--- a/win32/Kbuild
+++ b/win32/Kbuild
@@ -13,6 +13,7 @@ lib-$(CONFIG_PLATFORM_MINGW32) += ioctl.o
 lib-$(CONFIG_FEATURE_PRNG_ISAAC) += isaac.o
 lib-$(CONFIG_PLATFORM_MINGW32) += mingw.o
 lib-$(CONFIG_PLATFORM_MINGW32) += process.o
+lib-$(CONFIG_PLATFORM_MINGW32) += match_class.o
 lib-$(CONFIG_PLATFORM_MINGW32) += mntent.o
 lib-$(CONFIG_PLATFORM_MINGW32) += net.o
 lib-$(CONFIG_PLATFORM_MINGW32) += poll.o
diff --git a/win32/fnmatch.c b/win32/fnmatch.c
index 0e76a7ba1..7d8fde6a2 100644
--- a/win32/fnmatch.c
+++ b/win32/fnmatch.c
@@ -17,7 +17,7 @@
    Boston, MA 02111-1307, USA.  */
 
 #include <platform.h>
-int index_in_strings(const char *strings, const char *key) FAST_FUNC;
+#include "match_class.h"
 
 #if HAVE_CONFIG_H
 # include <config.h>
@@ -373,56 +373,52 @@ internal_fnmatch (const char *pattern, const char *string,
 		    if (__iswctype (__btowc ((unsigned char) *n), wt))
 		      goto matched;
 # else
-#define CHAR_CLASSES \
-		    "alnum\0alpha\0blank\0cntrl\0digit\0graph\0" \
-			"lower\0print\0punct\0space\0upper\0xdigit\0"
-
-			switch (index_in_strings(CHAR_CLASSES, str)) {
-		    case 0:
+			switch (match_class(str)) {
+		    case CCLASS_ALNUM:
 				if (ISALNUM ((unsigned char) *n))
 					goto matched;
 				break;
-			case 1:
+			case CCLASS_ALPHA:
 				if (ISALPHA ((unsigned char) *n))
 					goto matched;
 				break;
-			case 2:
+			case CCLASS_BLANK:
 				if (ISBLANK ((unsigned char) *n))
 					goto matched;
 				break;
-			case 3:
+			case CCLASS_CNTRL:
 				if (ISCNTRL ((unsigned char) *n))
 					goto matched;
 				break;
-			case 4:
+			case CCLASS_DIGIT:
 				if (ISDIGIT ((unsigned char) *n))
 					goto matched;
 				break;
-			case 5:
+			case CCLASS_GRAPH:
 				if (ISGRAPH ((unsigned char) *n))
 					goto matched;
 				break;
-			case 6:
+			case CCLASS_LOWER:
 				if (ISLOWER ((unsigned char) *n))
 					goto matched;
 				break;
-			case 7:
+			case CCLASS_PRINT:
 				if (ISPRINT ((unsigned char) *n))
 					goto matched;
 				break;
-			case 8:
+			case CCLASS_PUNCT:
 				if (ISPUNCT ((unsigned char) *n))
 					goto matched;
 				break;
-			case 9:
+			case CCLASS_SPACE:
 				if (ISSPACE ((unsigned char) *n))
 					goto matched;
 				break;
-			case 10:
+			case CCLASS_UPPER:
 				if (ISUPPER ((unsigned char) *n))
 					goto matched;
 				break;
-			case 11:
+			case CCLASS_XDIGIT:
 				if (ISXDIGIT ((unsigned char) *n))
 					goto matched;
 				break;
diff --git a/win32/match_class.c b/win32/match_class.c
new file mode 100644
index 000000000..789e0df02
--- /dev/null
+++ b/win32/match_class.c
@@ -0,0 +1,7 @@
+#include "libbb.h"
+#include "match_class.h"
+
+int match_class(const char *name)
+{
+	return index_in_strings(CHAR_CLASSES, name);
+}
diff --git a/win32/match_class.h b/win32/match_class.h
new file mode 100644
index 000000000..92fd1323f
--- /dev/null
+++ b/win32/match_class.h
@@ -0,0 +1,11 @@
+#define CHAR_CLASSES \
+			"alnum\0alpha\0blank\0cntrl\0digit\0graph\0" \
+			"lower\0print\0punct\0space\0upper\0xdigit\0"
+
+enum {
+	CCLASS_ALNUM, CCLASS_ALPHA, CCLASS_BLANK, CCLASS_CNTRL,
+	CCLASS_DIGIT, CCLASS_GRAPH, CCLASS_LOWER, CCLASS_PRINT,
+	CCLASS_PUNCT, CCLASS_SPACE, CCLASS_UPPER, CCLASS_XDIGIT
+};
+
+extern int match_class(const char *name);
diff --git a/win32/regcomp.c b/win32/regcomp.c
index dca7e6ef3..e1692d341 100644
--- a/win32/regcomp.c
+++ b/win32/regcomp.c
@@ -18,6 +18,8 @@
    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301 USA.  */
 
+#include "match_class.h"
+
 #define UNUSED_PARAM __attribute__ ((__unused__))
 
 static reg_errcode_t re_compile_internal (regex_t *preg, const char * pattern,
@@ -3571,6 +3573,7 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
       }						\
   } while (0)
 
+#if 0
   if (strcmp (class_name, "alnum") == 0)
     BUILD_CHARCLASS_LOOP (isalnum);
   else if (strcmp (class_name, "cntrl") == 0)
@@ -3602,6 +3605,53 @@ build_charclass (RE_TRANSLATE_TYPE trans, bitset_t sbcset,
     BUILD_CHARCLASS_LOOP (isxdigit);
   else
     return REG_ECTYPE;
+#else
+	switch (match_class(class_name)) {
+	case CCLASS_ALNUM:
+		BUILD_CHARCLASS_LOOP (isalnum);
+		break;
+	case CCLASS_CNTRL:
+		BUILD_CHARCLASS_LOOP (iscntrl);
+		break;
+	case CCLASS_LOWER:
+		BUILD_CHARCLASS_LOOP (islower);
+		break;
+	case CCLASS_SPACE:
+		BUILD_CHARCLASS_LOOP (isspace);
+		break;
+	case CCLASS_ALPHA:
+		BUILD_CHARCLASS_LOOP (isalpha);
+		break;
+	case CCLASS_DIGIT:
+		BUILD_CHARCLASS_LOOP (isdigit);
+		break;
+	case CCLASS_PRINT:
+		BUILD_CHARCLASS_LOOP (isprint);
+		break;
+	case CCLASS_UPPER:
+		BUILD_CHARCLASS_LOOP (isupper);
+		break;
+	case CCLASS_BLANK:
+#ifndef GAWK
+		BUILD_CHARCLASS_LOOP (isblank);
+#else
+		/* see comments above */
+		BUILD_CHARCLASS_LOOP (is_blank);
+#endif
+		break;
+	case CCLASS_GRAPH:
+		BUILD_CHARCLASS_LOOP (isgraph);
+		break;
+	case CCLASS_PUNCT:
+		BUILD_CHARCLASS_LOOP (ispunct);
+		break;
+	case CCLASS_XDIGIT:
+		BUILD_CHARCLASS_LOOP (isxdigit);
+		break;
+	default:
+		return REG_ECTYPE;
+	}
+#endif
 
   return REG_NOERROR;
 }
-- 
cgit v1.2.3-55-g6feb