From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: ludovic.courtes@laas.fr (Ludovic =?iso-8859-1?Q?Court=E8s?=) Newsgroups: gmane.lisp.guile.devel Subject: Text collation Date: Tue, 19 Sep 2006 11:23:03 +0200 Organization: LAAS-CNRS Message-ID: <877j00cirs.fsf@laas.fr> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: sea.gmane.org 1158657841 21396 80.91.229.2 (19 Sep 2006 09:24:01 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Tue, 19 Sep 2006 09:24:01 +0000 (UTC) Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Tue Sep 19 11:23:59 2006 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by ciao.gmane.org with esmtp (Exim 4.43) id 1GPbpS-0004qb-Ow for guile-devel@m.gmane.org; Tue, 19 Sep 2006 11:23:47 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1GPbpR-0000h2-EO for guile-devel@m.gmane.org; Tue, 19 Sep 2006 05:23:45 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1GPbp8-0000TM-SR for guile-devel@gnu.org; Tue, 19 Sep 2006 05:23:27 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1GPbp6-0000Ph-SW for guile-devel@gnu.org; Tue, 19 Sep 2006 05:23:25 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1GPbp6-0000ON-7s for guile-devel@gnu.org; Tue, 19 Sep 2006 05:23:24 -0400 Original-Received: from [140.93.0.15] (helo=laas.laas.fr) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA:32) (Exim 4.52) id 1GPbs8-0006I0-Oh for guile-devel@gnu.org; Tue, 19 Sep 2006 05:26:33 -0400 Original-Received: by laas.laas.fr (8.13.7/8.13.4) with SMTP id k8J9NE0g022924; Tue, 19 Sep 2006 11:23:21 +0200 (CEST) Original-To: Guile-Devel X-URL: http://www.laas.fr/~lcourtes/ X-Revolutionary-Date: Jour du Travail de =?iso-8859-1?Q?l'Ann=E9e?= 214 de la =?iso-8859-1?Q?R=E9volution?= X-PGP-Key-ID: 0xEB1F5364 X-PGP-Key: http://www.laas.fr/~lcourtes/ludovic.asc X-PGP-Fingerprint: 821D 815D 902A 7EAB 5CEE D120 7FBA 3D4F EB1F 5364 X-OS: powerpc-unknown-linux-gnu Mail-Followup-To: Guile-Devel User-Agent: Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux) X-Spam-Score: 0 () X-Scanned-By: MIMEDefang at CNRS-LAAS X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.lisp.guile.devel:6100 Archived-At: --=-=-= Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: quoted-printable X-MIME-Autoconverted: from 8bit to quoted-printable by laas.laas.fr id k8J9NE0g022924 Hi, Guile doesn't provide any locale-dependent string comparison primitive. `string (define l (make-locale LC_COLLATE_MASK "fr_FR")) guile> l # guile> (string-locale (string-locale (char-locale (char-locale (setlocale LC_COLLATE "fr_FR") "fr_FR" guile> (string-locale @@ -24,10 +25,13 @@ #include "libguile/feature.h" #include "libguile/i18n.h" #include "libguile/strings.h" +#include "libguile/chars.h" #include "libguile/dynwind.h" +#include "libguile/validate.h" #include "gettext.h" #include +#include /* `strcoll ()' */ int @@ -312,10 +316,206 @@ } #undef FUNC_NAME -void + +/* Locale objects, string and character collation. */ + +SCM_SMOB (scm_tc16_locale_smob_type, "locale", 0); + +SCM_SMOB_FREE (scm_tc16_locale_smob_type, smob_locale_free, locale) +{ +#ifdef __GNU_LIBRARY__ + freelocale ((locale_t)SCM_SMOB_DATA (locale)); +#endif + + return 0; +} + +#ifndef __GNU_LIBRARY__ + +/* Provide the locale category masks as found in glibc (copied from + as found in glibc 2.3.6). */ + +# define LC_CTYPE_MASK (1 << LC_CTYPE) +# define LC_NUMERIC_MASK (1 << LC_NUMERIC) +# define LC_TIME_MASK (1 << LC_TIME) +# define LC_COLLATE_MASK (1 << LC_COLLATE) +# define LC_MONETARY_MASK (1 << LC_MONETARY) +# define LC_MESSAGES_MASK (1 << LC_MESSAGES) +# define LC_PAPER_MASK (1 << LC_PAPER) +# define LC_NAME_MASK (1 << LC_NAME) +# define LC_ADDRESS_MASK (1 << LC_ADDRESS) +# define LC_TELEPHONE_MASK (1 << LC_TELEPHONE) +# define LC_MEASUREMENT_MASK (1 << LC_MEASUREMENT) +# define LC_IDENTIFICATION_MASK (1 << LC_IDENTIFICATION) +# define LC_ALL_MASK (LC_CTYPE_MASK \ + | LC_NUMERIC_MASK \ + | LC_TIME_MASK \ + | LC_COLLATE_MASK \ + | LC_MONETARY_MASK \ + | LC_MESSAGES_MASK \ + | LC_PAPER_MASK \ + | LC_NAME_MASK \ + | LC_ADDRESS_MASK \ + | LC_TELEPHONE_MASK \ + | LC_MEASUREMENT_MASK \ + | LC_IDENTIFICATION_MASK \ + ) + +#endif + + +SCM_DEFINE (scm_make_locale, "make-locale", 2, 1, 0, + (SCM category_mask, SCM locale_name, SCM base_locale), + "Return a reference to a data structure representing a set of " + "locale datasets. Unlike for the @var{category} parameter for " + "@code{setlocale}, the @var{category_mask} parameter here uses " + "a single bit for each category, made by OR'ing together " + "@code{LC_*_MASK} bits.") +#define FUNC_NAME s_scm_make_locale +{ +#ifdef __GNU_LIBRARY__ + SCM locale; + int c_category_mask; + char *c_locale_name; + locale_t c_base_locale, c_locale; + + SCM_VALIDATE_INT_COPY (1, category_mask, c_category_mask); + SCM_VALIDATE_STRING (2, locale_name); + c_locale_name = scm_to_locale_string (locale_name); + + if (base_locale != SCM_UNDEFINED) + { + SCM_VALIDATE_SMOB (3, base_locale, locale_smob_type); + c_base_locale = (locale_t)SCM_SMOB_DATA (base_locale); + } + else + c_base_locale = NULL; + + c_locale = newlocale (c_category_mask, c_locale_name, c_base_locale); + free (c_base_locale); + + if (!c_locale) + locale = SCM_BOOL_F; + else + SCM_NEWSMOB (locale, scm_tc16_locale_smob_type, c_locale); + + return locale; +#else + /* FIXME: Handle this situation, for instance: + SCM_RETURN_NEWSMOB (scm_tc16_locale_smob_type, + scm_list_3 (category_mask, locale_name, + base_locale)); */ + return SCM_BOOL_F; +#endif +} +#undef FUNC_NAME + + +/* Compare null-terminated strings C_S1 and C_S2 according to LOCALE. Return + an integer whose sign is the same as the difference between C_S1 and + C_S2. */ +static inline int +compare_strings (const char *c_s1, const char *c_s2, SCM locale, + const char *func_name) +#define FUNC_NAME func_name +{ +#ifdef __GNU_LIBRARY__ + locale_t c_locale; +#endif + int result; + +#ifdef __GNU_LIBRARY__ + if (locale != SCM_UNDEFINED) + { + SCM_VALIDATE_SMOB (3, locale, locale_smob_type); + c_locale = (locale_t)SCM_SMOB_DATA (locale); + } + else + c_locale = NULL; + + if (c_locale) + result = strcoll_l (c_s1, c_s2, c_locale); + else +#endif + +#if HAVE_STRCOLL + result = strcoll (c_s1, c_s2); +#else + result = strcmp (c_s1, c_s2); +#endif + + return result; +} +#undef FUNC_NAME + + +SCM_DEFINE (scm_string_locale_lt, "string-locale