Subject: Re: lib/18151: Multibyte locale support for statically linked programs
To: None <itojun@iijlab.net>
From: Anders Hjalmarsson <hjalmar@hjalmar.to>
List: tech-userlevel
Date: 09/03/2002 20:52:53
> 
> 	without locale modules compiled in there's no use in having 
> 	locale-related logic.
> 
> itojun

Here is a revised version of the patches. I hope this addresses your
concerns. If STATIC_LOCALES is empty the old stubs are used, so everything
is like before, the new code is only used if STATIC_LOCALES is non-empty.

-hjalmar

Index: share/mk/bsd.README
===================================================================
RCS file: /cvsroot/sharesrc/share/mk/bsd.README,v
retrieving revision 1.101
diff -u -r1.101 bsd.README
--- bsd.README	2002/08/19 14:51:58	1.101
+++ bsd.README	2002/09/03 18:45:36
@@ -364,6 +364,12 @@
 		point and possibly soft-float library support.  Defaults
 		to "no".
 
+STATIC_LOCALES	The list of locale modules to be compiled-in in the static
+		libc.a (and libc_p.a). Currently supported locales are:
+		BIG5 EUC EUCTW ISO2022 MSKanji UTF8
+		Defaults to "", which means that no multibyte locales
+		are supported by statically linked programs.
+
 bsd.own.mk is generally useful when building your own Makefiles so that
 they use the same default owners etc. as the rest of the tree.
 
Index: share/mk/bsd.own.mk
===================================================================
RCS file: /cvsroot/sharesrc/share/mk/bsd.own.mk,v
retrieving revision 1.305
diff -u -r1.305 bsd.own.mk
--- bsd.own.mk	2002/08/03 22:10:07	1.305
+++ bsd.own.mk	2002/09/03 18:45:37
@@ -479,4 +479,9 @@
 USE_XF86_4?=	yes
 .endif
 
+# The list of locale modules to be compiled-in in the static
+# libc.a (and libc_p.a).
+#STATIC_LOCALES?=BIG5 EUC EUCTW ISO2022 MSKanji UTF8
+STATIC_LOCALES?=
+
 .endif		# _BSD_OWN_MK_


Index: lib/libc/Makefile
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/Makefile,v
retrieving revision 1.107
diff -u -r1.107 Makefile
--- Makefile	2002/08/19 14:55:14	1.107
+++ Makefile	2002/09/03 18:45:50
@@ -38,7 +38,7 @@
 
 .if ${MACHINE_ARCH} == "i386"
 # Set lint to exit on warnings
-LINTFLAGS+=	-w
+# XXX citrus modules not clean LINTFLAGS+=	-w
 .endif
 # ignore 'empty translation unit' warnings.
 LINTFLAGS+=	-X 272
@@ -150,8 +150,9 @@
 FILESDIR=	/var/db
 
 
-# workaround for I18N stuffs: build singlebyte setlocale() for libc.a,
-# multibyte for libc.so.  the quirk should be removed when we support
+# workaround for I18N stuffs: build singlebyte, and a compiled-in set of
+# multibyte locales for libc.a, dynamically loadable multibyte locales
+# for libc.so.  the quirk should be removed when we support
 # dlopen() from within statically linked binaries.
 CSHLIBFLAGS+=	-D_I18N_DYNAMIC
 
Index: lib/libc/citrus/Makefile.inc
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/citrus/Makefile.inc,v
retrieving revision 1.2
diff -u -r1.2 Makefile.inc
--- Makefile.inc	2002/08/19 13:35:06	1.2
+++ Makefile.inc	2002/09/03 18:45:53
@@ -11,6 +11,23 @@
 
 SRCS+=	citrus_ctype.c citrus_module.c citrus_none.c
 
+# Add the locale modules to compile-in in the static libc.a (and libc_p.a)
+# If a new locale module is added, the includes and the table in
+# citrus_module.c must be updated.
+# A new module must have the file name citrus_xxx.c where xxx is the lower
+# case name of the module.
+# Currently the modules specified by STATIC_LOCALES are included in the
+# shared libc (but never used). This is a bug.
+.if ${STATIC_LOCALES} != ""
+.PATH: ${.CURDIR}/citrus/modules
+CPPFLAGS+=-I${.CURDIR}/citrus
+CPPFLAGS+=-D_I18N_STATIC
+.for var in ${STATIC_LOCALES}
+SRCS+=	citrus_${var:tl}.c
+CPPFLAGS+=-D_I18N_STATIC_${var}
+.endfor
+.endif # STATIC_LOCALES
+
 # to be dynamically loaded - see lib/i18n_module
 #SRCS+=	citrus_big5.c citrus_euc.c citrus_euctw.c citrus_iso2022.c \
 #	citrus_mskanji.c citrus_utf8.c
Index: lib/libc/citrus/citrus_ctype.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/citrus/citrus_ctype.c,v
retrieving revision 1.2
diff -u -r1.2 citrus_ctype.c
--- citrus_ctype.c	2002/03/18 09:02:50	1.2
+++ citrus_ctype.c	2002/09/03 18:45:53
@@ -55,7 +55,7 @@
 	NULL				/* ce_module */
 };
 
-#ifdef _I18N_DYNAMIC
+#if defined(_I18N_DYNAMIC) || defined(_I18N_STATIC)
 
 static int _initctypemodule(_citrus_ctype_t, char const *, _citrus_module_t,
 			    void *, size_t, size_t);
@@ -176,7 +176,7 @@
 }
 
 #else
-/* !_I18N_DYNAMIC */
+/* !(_I18N_DYNAMIC || _I18N_STATIC) */
 
 int
 /*ARGSUSED*/
Index: lib/libc/citrus/citrus_module.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libc/citrus/citrus_module.c,v
retrieving revision 1.2
diff -u -r1.2 citrus_module.c
--- citrus_module.c	2002/04/20 05:55:47	1.2
+++ citrus_module.c	2002/09/03 18:45:53
@@ -345,22 +345,118 @@
 	if (handle)
 		dlclose((void *)handle);
 }
-#else
-/* !_I18N_DYNAMIC */
+#elif defined(_I18N_STATIC)
+
+/*
+ * Compiled-in multibyte locale support for statically linked programs.
+ */
+
+#include "citrus_ctype.h"
+#include "modules/citrus_big5.h"
+#include "modules/citrus_euc.h"
+#include "modules/citrus_euctw.h"
+#include "modules/citrus_iso2022.h"
+#include "modules/citrus_mskanji.h"
+#include "modules/citrus_utf8.h"
+
+#define _CITRUS_GETOPS_FUNC(_m_, _if_) _citrus_##_m_##_##_if_##_getops
+
+#define _CITRUS_LOCALE_TABLE_ENTRY(_n_) \
+{ #_n_, _CITRUS_GETOPS_FUNC(_n_, ctype) }
 
+/*
+ * Table of compiled-in locales.
+ */
+static const struct _citrus_locale_table_rec {
+	const char *name;
+	_CITRUS_CTYPE_GETOPS_FUNC_BASE((*ctype_fun));
+} _citrus_static_locale_table[] = {
+#ifdef _I18N_STATIC_BIG5
+	_CITRUS_LOCALE_TABLE_ENTRY(BIG5),
+#endif
+#ifdef _I18N_STATIC_EUC
+	_CITRUS_LOCALE_TABLE_ENTRY(EUC),
+#endif
+#ifdef _I18N_STATIC_EUCTW
+	_CITRUS_LOCALE_TABLE_ENTRY(EUCTW),
+#endif
+#ifdef _I18N_STATIC_ISO2022
+	_CITRUS_LOCALE_TABLE_ENTRY(ISO2022),
+#endif
+#ifdef _I18N_STATIC_MSKanji
+	_CITRUS_LOCALE_TABLE_ENTRY(MSKanji),
+#endif
+#ifdef _I18N_STATIC_UTF8
+	_CITRUS_LOCALE_TABLE_ENTRY(UTF8),
+#endif
+	{ 0, 0 }
+};
+
 void *
-/*ARGSUSED*/
 _citrus_find_getops(_citrus_module_t handle, const char *modname,
 		    const char *ifname)
 {
-	return (NULL);
+	const struct _citrus_locale_table_rec *p;
+
+	_DIAGASSERT(handle != NULL);
+	_DIAGASSERT(modname != NULL);
+	_DIAGASSERT(ifname != NULL);
+
+	/* LINTED handle is always from _citrus_load_module */
+	p = (const struct _citrus_locale_table_rec *)handle;
+
+	/* Sanity check, should perhaps be a _DIAGASSERT */
+	if (strcmp(p->name, modname))
+		return (NULL);
+
+	/* Currently only ctype is implemented. */
+	if (!strcmp(ifname, "ctype"))
+		return (void *)p->ctype_fun;
+	else
+		return (NULL);
+}
+
+int
+_citrus_load_module(_citrus_module_t *rhandle, char const *encname)
+{
+	const struct _citrus_locale_table_rec *p;
+
+	_DIAGASSERT(rhandle != NULL);
+
+	for (p = _citrus_static_locale_table; p->name; p++) {
+		if (!strcmp(p->name, encname)) {
+			/* LINTED will be used only by _citrus_find_getops */
+			*rhandle = (_citrus_module_t)p;
+			return (0);
+		}
+	}
+
+	/* Not found */
+	return (EINVAL);
 }
 
+void
+/*ARGSUSED*/
+_citrus_unload_module(_citrus_module_t handle)
+{
+}
+
+#else
+/* No static multibyte locales */
+
 int
 /*ARGSUSED*/
-_citrus_load_module(_citrus_module_t *rhandle, char const *modname)
+_citrus_load_module(_citrus_module_t *rhandle, char const *encname)
 {
 	return (EINVAL);
+}
+
+void *
+/*ARGSUSED*/
+_citrus_find_getops(_citrus_module_t handle, const char *modname,
+		    const char *ifname)
+{
+	return (NULL);
 }
 
 void