glibc/string/strcoll.c
Roland McGrath 19bc17a905 Thu Mar 28 03:25:10 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu>
* intl/Makefile (copysrc): Add missing > in sed cmd.

Sat Mar 23 17:52:49 1996  Ulrich Drepper  <drepper@gnu.ai.mit.edu>

	* Makeconfig: Rename Makefile variable nlsdir to i18ndir and
	change value to $(datadir)/i18n.  `nls' is not an appropriate
	name.

	* Makefile (subdirs): Add new subdir wctype.

	* ctype/ctype-info.c: Add new global variable __ctype_names
	and initialize from _nl_C_LC_CTYPE.

	* ctype/ctype.h: In P1003.3b/D11 `alnum' is a separate character
        class.  Use bit 11.
	[_ISbit]: Protect definition of bitmasks because they are also
	used in wctype.h.

	* libio/genops.c (_IO_sputbackc, _IO_sungetc): Clear EOF flag
	after successfully pushing back a character.

	Fundamental changes in locale implementation.  Almost nothing
	from the old code is used anymore.
	* locale/charmap.c, locale/collate.c, locale/config.h,
 	locale/ctypedump.c, locale/hash.h, locale/keyword.gperf,
 	locale/keyword.h, locale/loadlocale.c, locale/locale-ctype.c,
 	locale/locale.c locale/localeconv.c, locale/localedef.c,
 	locale/localedef.h, locale/locfile-hash.c, locale/locfile-lex.c,
 	locale/locfile-parse.c, locale/messages.c, locale/monetary.c,
 	locale/numeric.c, locale/setlocale.c, locale/token.h,
 	locale/xmalloc.c: Removed.

	* locale/Makefile: Update for new locale implementation with
	program source code distributed in subdir.

	* locale/categories.def, locale/iso-4217.def: Updated file
        for new locale implementation.

	* locale/langinfo.h: Updated for new locale implementation.
	(ERA_D_T_FMT, ERA_T_FMT): New official values according to
	P1003.2b/D11.
	(_NL_COLLATE_NRULES, _NL_COLLATE_RULES, _NL_COLLATE_HASH_SIZE,
	_NL_COLLATE_HASH_LAYERS, _NL_COLLATE_TABLE_EB,
	_NL_COLLATE_TABLE_EL, _NL_COLLATE_UNDEFINED, _NL_COLLATE_EXTRA_EB,
	_NL_COLLATE_EXTRA_EL, _NL_CTYPE_NAMES_EB, _NL_CTYPE_NAMES_EL,
	_NL_CTYPE_HASH_SIZE, _NL_CTYPE_HASH_LAYERS, _NL_CTYPE_CLASS_NAMES,
	_NL_CTYPE_MAP_NAMES, _NL_CTYPE_WIDTH): New internal values for
	extended LC_CTYPE and LC_COLLATE implementation.

	* locale/simple-hash.c, locale/simple-hash.h, locale/xmalloc.c,
 	locale/xstrdup.c: Helper functions for locale related programs.

	* locale/C-collate.c, locale/C-ctype.c,
        locale/C-messages.c, locale/C-monetary.c,
        locale/C-numeric.c, locale/C-time.c,
        locale/lc-collate.c, locale/lc-ctype.c,
        locale/lc-messages.c, locale/lc-monetary.c,
        locale/lc-numeric.c, locale/lc-time.c: New implementation of locale
        functions, and new generated "C" locale data.

	* locale/loadlocale.c: Now handles word fields in locale binary
        automatically by changing the endianess if necessary.

	* locale/localeinfo.h (LIMAGIC): Changed magic number because
	of incompatible changes.
	(locale_data): Changed definition to allow word as a value type.
	(coll_sort_rule): Values for collation sorting mode.
	(_NL_CURRENT_WORD): New macro to access word value of locale entry.
	(__collate_table, __collate_extra): Declare new global variables
	for collation tables.

	* locale/programs/charmap-kw.gperf, locale/programs/charmap-kw.h,
        locale/programs/charmap.c, locale/programs/charset.c,
        locale/programs/charset.h, locale/programs/config.h,
        locale/programs/ctypedump.c, locale/programs/ld-collate.c,
        locale/programs/ld-ctype.c, locale/programs/ld-messages.c,
        locale/programs/ld-monetary.c, locale/programs/ld-numeric.c,
        locale/programs/ld-time.c, locale/programs/linereader.c,
        locale/programs/linereader.h, locale/programs/locale.c,
        locale/programs/localedef.c, locale/programs/locales.h,
        locale/programs/locfile-kw.gperf, locale/programs/locfile-kw.h,
        locale/programs/locfile-token.h, locale/programs/locfile.c,
        locale/programs/locfile.h, locale/programs/stringtrans.c,
        locale/programs/stringtrans.h: Implementation of locale related
        programs.

	* locale/weight.h: Functions to access collation tables.

	* posix/unistd.h: Define _POSIX2_LOCALEDEF.

	* stdio-common/printf_fp.c: Fix bug with printing certain numbers
	< 10^-1.  Reported by Bill Metzenthen.

	* stdio-common/tfformat.c: Add new test for above bug.

	* string/strcoll.c, string/strxfrm.c: Real implementation of
        string collation according to ISO C.

	* wctype/Makefile, wctype/cname-lookup.h, wctype/iswctype.c,
        wctype/test_wctype.c, wctype/towctrans.c, wctype/wcfuncs.c,
        wctype/wctrans.c, wctype/wctype.c, wctype/wctype.h: New files.
        Implementation of wide character classes and mapping.
1996-03-28 08:30:38 +00:00

159 lines
4.4 KiB
C

/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Ulrich Drepper, <drepper@gnu.ai.mit.edu>.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "localeinfo.h"
#ifndef STRING_TYPE
# define STRING_TYPE char
# define USTRING_TYPE unsigned char
# define STRCOLL strcoll
#endif
/* Include the shared helper functions. `strxfrm'/`wcsxfrm' also use
these functions. */
#include "weight.h"
/* Compare S1 and S2, returning less than, equal to or
greater than zero if the collated form of S1 is lexicographically
less than, equal to or greater than the collated form of S2. */
int
STRCOLL (s1, s2)
const STRING_TYPE *s1;
const STRING_TYPE *s2;
{
weight_t *s1forw = NULL;
weight_t *s1backw = NULL;
weight_t *s2forw = NULL;
weight_t *s2backw = NULL;
size_t pass;
/* If the current locale does not specify locale data we use normal
8-bit string comparison. */
if (collate_nrules == 0)
return strcmp (s1, s2);
/* Get full information about the strings. This means we get
information for all passes in a special data structure. */
get_string (s1, s1forw, s1backw);
get_string (s2, s2forw, s2backw);
/* Now we have all the information. In at most the given number of
passes we can finally decide about the order. */
for (pass = 0; pass < collate_nrules; ++pass)
{
int forward = (collate_rules[pass] & sort_forward) != 0;
const weight_t *s1run = forward ? s1forw : s1backw;
const weight_t *s2run = forward ? s2forw : s2backw;
int s1idx = forward ? 0 : s1run->data[pass].number - 1;
int s2idx = forward ? 0 : s2run->data[pass].number - 1;
do
{
int s1ignore = 0;
int s2ignore = 0;
u32_t w1, w2;
/* Here we have to check for IGNORE entries. If these are
found we count them and go on witht he next value. */
while ((w1 = s1run->data[pass].value[s1idx]) == IGNORE_CHAR)
{
++s1ignore;
if ((forward && ++s1idx >= s1run->data[pass].number)
|| (!forward && --s1idx < 0))
{
weight_t *nextp = forward ? s1run->next : s1run->prev;
if (nextp == NULL)
{
w1 = 0;
break;
}
s1run = nextp;
s1idx = forward ? 0 : s1run->data[pass].number - 1;
}
}
while ((w2 = s2run->data[pass].value[s2idx]) == IGNORE_CHAR)
{
++s2ignore;
if ((forward && ++s2idx >= s2run->data[pass].number)
|| (!forward && --s2idx < 0))
{
weight_t *nextp = forward ? s2run->next : s2run->prev;
if (nextp == NULL)
{
w2 = 0;
break;
}
s2run = nextp;
s2idx = forward ? 0 : s2run->data[pass].number - 1;
}
}
/* Now we have information of the number of ignored
weights and the value of the next weight. */
if ((collate_rules[pass] & sort_position) != 0
&& s1ignore != s2ignore && (w1 != 0 || w2 != 0))
return s1ignore < s2ignore ? -1 : 1;
if (w1 != w2)
return w1 < w2 ? -1 : 1;
/* We have to increment the index counters. */
if ((forward && ++s1idx >= s1run->data[pass].number)
|| (!forward && --s1idx < 0))
if (forward)
{
s1run = s1run->next;
s1idx = 0;
}
else
{
s1run = s1run->prev;
if (s1run != NULL)
s1idx = s1run->data[pass].number - 1;
}
if ((forward && ++s2idx >= s2run->data[pass].number)
|| (!forward && --s2idx < 0))
if (forward)
{
s2run = s2run->next;
s2idx = 0;
}
else
{
s2run = s2run->prev;
if (s2run != NULL)
s2idx = s2run->data[pass].number - 1;
}
}
while (s1run != NULL && s2run != NULL);
if (s1run != s2run)
return s1run != NULL ? 1 : -1;
}
return 0;
}