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.
This commit is contained in:
Roland McGrath 1996-03-28 08:30:38 +00:00
parent 53f770e0f9
commit 19bc17a905
78 changed files with 10096 additions and 4587 deletions

105
ChangeLog
View file

@ -1,3 +1,108 @@
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.
Wed Mar 27 14:52:11 1996 Roland McGrath <roland@charlie-brown.gnu.ai.mit.edu>
* elf/rtld.c (dl_main): Call _dl_sysdep_start_cleanup after

View file

@ -171,8 +171,8 @@ localedir = $(datadir)/locale
endif
# Where to install the locale charmap source files.
ifndef nlsdir
nlsdir = $(datadir)/nls
ifndef i18ndir
i18ndir = $(datadir)/i18n
endif

View file

@ -54,7 +54,7 @@ endif
subdirs = csu assert ctype db locale intl math setjmp signal stdlib \
stdio-common $(stdio) malloc string wcsmbs time dirent grp pwd\
posix io termios resource misc socket sysvipc gmon gnulib \
$(wildcard crypt) manual $(sysdep-subdirs) elf
wctype $(wildcard crypt) manual $(sysdep-subdirs) elf
export subdirs := $(subdirs) # Benign, useless in GNU make before 3.63.
# The mach and hurd subdirectories have many generated header files which

View file

@ -1,4 +1,4 @@
/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc.
/* Copyright (C) 1991, 1992, 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -21,11 +21,15 @@ Cambridge, MA 02139, USA. */
/* Defined in locale/C-ctype.c. */
extern const char _nl_C_LC_CTYPE_class[];
extern const char _nl_C_LC_CTYPE_class32[];
extern const char _nl_C_LC_CTYPE_toupper[];
extern const char _nl_C_LC_CTYPE_tolower[];
extern const char _nl_C_LC_CTYPE_names[];
#define b(u,x) (((u int *) _nl_C_LC_CTYPE_##x) + 128);
#define b(u,x,o) (((const u int *) _nl_C_LC_CTYPE_##x) + o);
const unsigned short int *__ctype_b = b(unsigned short, class);
const int *__ctype_tolower = b(, tolower);
const int *__ctype_toupper = b(, toupper);
const unsigned short int *__ctype_b = b (unsigned short, class, 128);
const unsigned int *__ctype32_b = b (unsigned, class32, 0);
const int *__ctype_tolower = b (, tolower, 128);
const int *__ctype_toupper = b (, toupper, 128);
const unsigned int *__ctype_names = b (unsigned, names, 0);

View file

@ -1,4 +1,4 @@
/* Copyright (C) 1991, 1992, 1993, 1995 Free Software Foundation, Inc.
/* Copyright (C) 1991, 1992, 1993, 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -27,6 +27,7 @@ Cambridge, MA 02139, USA. */
__BEGIN_DECLS
#ifndef _ISbit
/* These are all the characteristics of characters.
If there get to be more than 16 distinct characteristics,
many things must be changed that use `unsigned short int's.
@ -55,11 +56,9 @@ enum
_ISblank = _ISbit (8), /* Blank (usually SPC and TAB). */
_IScntrl = _ISbit (9), /* Control character. */
_ISpunct = _ISbit (10), /* Punctuation. */
/* The following are defined in POSIX.2 as being combinations of the
classes above. */
_ISalnum = _ISalpha | _ISdigit /* Alphanumeric. */
_ISalnum = _ISbit (11) /* Alphanumeric. */
};
#endif /* ! _ISbit */
/* These are defined in ctype-info.c.
The declarations here must match those in localeinfo.h.
@ -70,7 +69,8 @@ enum
char' values and for EOF; we also support negative `signed char' values
for broken old programs. The case conversion arrays are of `int's
rather than `unsigned char's because tolower (EOF) must be EOF, which
doesn't fit into an `unsigned char'. */
doesn't fit into an `unsigned char'. But today more important is that
the arrays are also used for multi-byte character sets. */
extern __const unsigned short int *__ctype_b; /* Characteristics. */
extern __const int *__ctype_tolower; /* Case conversions. */
extern __const int *__ctype_toupper; /* Case conversions. */

View file

@ -36,7 +36,7 @@ ifdef gettext-srcdir
%.h:: ../gpl2lgpl.sed $(gettext-srcdir)/intl/%.h; $(copysrc)
define copysrc
sed -f $^ $@.new
sed -f $^ > $@.new
chmod a-w $@.new
mv -f $@.new $@
test ! -d CVS || cvs commit -m'Updated from $<' $@

View file

@ -511,26 +511,41 @@ int
DEFUN(_IO_sputbackc, (fp, c),
register _IO_FILE *fp AND int c)
{
int result;
if (fp->_IO_read_ptr > fp->_IO_read_base
&& (unsigned char)fp->_IO_read_ptr[-1] == (unsigned char)c)
{
fp->_IO_read_ptr--;
return (unsigned char)c;
result = (unsigned char)c;
}
return _IO_PBACKFAIL (fp, c);
else
result = _IO_PBACKFAIL (fp, c);
if (result != EOF)
fp->_flags &= ~_IO_EOF_SEEN;
return result;
}
int
DEFUN(_IO_sungetc, (fp),
register _IO_FILE *fp)
{
int result;
if (fp->_IO_read_ptr > fp->_IO_read_base)
{
fp->_IO_read_ptr--;
return (unsigned char)*fp->_IO_read_ptr;
result = (unsigned char)*fp->_IO_read_ptr;
}
else
return _IO_PBACKFAIL (fp, EOF);
result = _IO_PBACKFAIL (fp, EOF);
if (result != EOF)
fp->_flags &= ~_IO_EOF_SEEN;
return result;
}
#if 0 /* Work in progress */

View file

@ -3,7 +3,7 @@
#include "localeinfo.h"
#include <endian.h>
const char _nl_C_LC_CTYPE_class[] =
const char _nl_C_LC_CTYPE_class[768] =
/* 0x80 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
/* 0x86 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
/* 0x8c */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
@ -33,19 +33,19 @@ const char _nl_C_LC_CTYPE_class[] =
/* 0x1c */ "\002\000" "\002\000" "\002\000" "\002\000" "\001\140" "\004\300"
/* 0x22 */ "\004\300" "\004\300" "\004\300" "\004\300" "\004\300" "\004\300"
/* 0x28 */ "\004\300" "\004\300" "\004\300" "\004\300" "\004\300" "\004\300"
/* 0x2e */ "\004\300" "\004\300" "\000\330" "\000\330" "\000\330" "\000\330"
/* 0x34 */ "\000\330" "\000\330" "\000\330" "\000\330" "\000\330" "\000\330"
/* 0x2e */ "\004\300" "\004\300" "\010\330" "\010\330" "\010\330" "\010\330"
/* 0x34 */ "\010\330" "\010\330" "\010\330" "\010\330" "\010\330" "\010\330"
/* 0x3a */ "\004\300" "\004\300" "\004\300" "\004\300" "\004\300" "\004\300"
/* 0x40 */ "\004\300" "\000\325" "\000\325" "\000\325" "\000\325" "\000\325"
/* 0x46 */ "\000\325" "\000\305" "\000\305" "\000\305" "\000\305" "\000\305"
/* 0x4c */ "\000\305" "\000\305" "\000\305" "\000\305" "\000\305" "\000\305"
/* 0x52 */ "\000\305" "\000\305" "\000\305" "\000\305" "\000\305" "\000\305"
/* 0x58 */ "\000\305" "\000\305" "\000\305" "\004\300" "\004\300" "\004\300"
/* 0x5e */ "\004\300" "\004\300" "\004\300" "\000\326" "\000\326" "\000\326"
/* 0x64 */ "\000\326" "\000\326" "\000\326" "\000\306" "\000\306" "\000\306"
/* 0x6a */ "\000\306" "\000\306" "\000\306" "\000\306" "\000\306" "\000\306"
/* 0x70 */ "\000\306" "\000\306" "\000\306" "\000\306" "\000\306" "\000\306"
/* 0x76 */ "\000\306" "\000\306" "\000\306" "\000\306" "\000\306" "\004\300"
/* 0x40 */ "\004\300" "\010\325" "\010\325" "\010\325" "\010\325" "\010\325"
/* 0x46 */ "\010\325" "\010\305" "\010\305" "\010\305" "\010\305" "\010\305"
/* 0x4c */ "\010\305" "\010\305" "\010\305" "\010\305" "\010\305" "\010\305"
/* 0x52 */ "\010\305" "\010\305" "\010\305" "\010\305" "\010\305" "\010\305"
/* 0x58 */ "\010\305" "\010\305" "\010\305" "\004\300" "\004\300" "\004\300"
/* 0x5e */ "\004\300" "\004\300" "\004\300" "\010\326" "\010\326" "\010\326"
/* 0x64 */ "\010\326" "\010\326" "\010\326" "\010\306" "\010\306" "\010\306"
/* 0x6a */ "\010\306" "\010\306" "\010\306" "\010\306" "\010\306" "\010\306"
/* 0x70 */ "\010\306" "\010\306" "\010\306" "\010\306" "\010\306" "\010\306"
/* 0x76 */ "\010\306" "\010\306" "\010\306" "\010\306" "\010\306" "\004\300"
/* 0x7c */ "\004\300" "\004\300" "\004\300" "\002\000" "\002\000" "\002\000"
/* 0x82 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
/* 0x88 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
@ -69,8 +69,96 @@ const char _nl_C_LC_CTYPE_class[] =
/* 0xf4 */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
/* 0xfa */ "\002\000" "\002\000" "\002\000" "\002\000" "\002\000" "\002\000"
;
const char _nl_C_LC_CTYPE_class32[1024] =
/* 0x00 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x03 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x06 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x09 */ "\003\040\000\000" "\002\040\000\000" "\002\040\000\000"
/* 0x0c */ "\002\040\000\000" "\002\040\000\000" "\002\000\000\000"
/* 0x0f */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x12 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x15 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x18 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x1b */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x1e */ "\002\000\000\000" "\002\000\000\000" "\001\140\000\000"
/* 0x21 */ "\004\300\000\000" "\004\300\000\000" "\004\300\000\000"
/* 0x24 */ "\004\300\000\000" "\004\300\000\000" "\004\300\000\000"
/* 0x27 */ "\004\300\000\000" "\004\300\000\000" "\004\300\000\000"
/* 0x2a */ "\004\300\000\000" "\004\300\000\000" "\004\300\000\000"
/* 0x2d */ "\004\300\000\000" "\004\300\000\000" "\004\300\000\000"
/* 0x30 */ "\010\330\000\000" "\010\330\000\000" "\010\330\000\000"
/* 0x33 */ "\010\330\000\000" "\010\330\000\000" "\010\330\000\000"
/* 0x36 */ "\010\330\000\000" "\010\330\000\000" "\010\330\000\000"
/* 0x39 */ "\010\330\000\000" "\004\300\000\000" "\004\300\000\000"
/* 0x3c */ "\004\300\000\000" "\004\300\000\000" "\004\300\000\000"
/* 0x3f */ "\004\300\000\000" "\004\300\000\000" "\010\325\000\000"
/* 0x42 */ "\010\325\000\000" "\010\325\000\000" "\010\325\000\000"
/* 0x45 */ "\010\325\000\000" "\010\325\000\000" "\010\305\000\000"
/* 0x48 */ "\010\305\000\000" "\010\305\000\000" "\010\305\000\000"
/* 0x4b */ "\010\305\000\000" "\010\305\000\000" "\010\305\000\000"
/* 0x4e */ "\010\305\000\000" "\010\305\000\000" "\010\305\000\000"
/* 0x51 */ "\010\305\000\000" "\010\305\000\000" "\010\305\000\000"
/* 0x54 */ "\010\305\000\000" "\010\305\000\000" "\010\305\000\000"
/* 0x57 */ "\010\305\000\000" "\010\305\000\000" "\010\305\000\000"
/* 0x5a */ "\010\305\000\000" "\004\300\000\000" "\004\300\000\000"
/* 0x5d */ "\004\300\000\000" "\004\300\000\000" "\004\300\000\000"
/* 0x60 */ "\004\300\000\000" "\010\326\000\000" "\010\326\000\000"
/* 0x63 */ "\010\326\000\000" "\010\326\000\000" "\010\326\000\000"
/* 0x66 */ "\010\326\000\000" "\010\306\000\000" "\010\306\000\000"
/* 0x69 */ "\010\306\000\000" "\010\306\000\000" "\010\306\000\000"
/* 0x6c */ "\010\306\000\000" "\010\306\000\000" "\010\306\000\000"
/* 0x6f */ "\010\306\000\000" "\010\306\000\000" "\010\306\000\000"
/* 0x72 */ "\010\306\000\000" "\010\306\000\000" "\010\306\000\000"
/* 0x75 */ "\010\306\000\000" "\010\306\000\000" "\010\306\000\000"
/* 0x78 */ "\010\306\000\000" "\010\306\000\000" "\010\306\000\000"
/* 0x7b */ "\004\300\000\000" "\004\300\000\000" "\004\300\000\000"
/* 0x7e */ "\004\300\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x81 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x84 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x87 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x8a */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x8d */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x90 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x93 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x96 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x99 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x9c */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0x9f */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xa2 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xa5 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xa8 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xab */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xae */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xb1 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xb4 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xb7 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xba */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xbd */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xc0 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xc3 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xc6 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xc9 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xcc */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xcf */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xd2 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xd5 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xd8 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xdb */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xde */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xe1 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xe4 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xe7 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xea */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xed */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xf0 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xf3 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xf6 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xf9 */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xfc */ "\002\000\000\000" "\002\000\000\000" "\002\000\000\000"
/* 0xff */ "\002\000\000\000"
;
#if BYTE_ORDER == LITTLE_ENDIAN
const char _nl_C_LC_CTYPE_toupper[] =
const char _nl_C_LC_CTYPE_toupper[1536] =
/* 0x80 */ "\200\000\000\000" "\201\000\000\000" "\202\000\000\000"
/* 0x83 */ "\203\000\000\000" "\204\000\000\000" "\205\000\000\000"
/* 0x86 */ "\206\000\000\000" "\207\000\000\000" "\210\000\000\000"
@ -200,7 +288,7 @@ const char _nl_C_LC_CTYPE_toupper[] =
/* 0xfa */ "\372\000\000\000" "\373\000\000\000" "\374\000\000\000"
/* 0xfd */ "\375\000\000\000" "\376\000\000\000" "\377\000\000\000"
;
const char _nl_C_LC_CTYPE_tolower[] =
const char _nl_C_LC_CTYPE_tolower[1536] =
/* 0x80 */ "\200\000\000\000" "\201\000\000\000" "\202\000\000\000"
/* 0x83 */ "\203\000\000\000" "\204\000\000\000" "\205\000\000\000"
/* 0x86 */ "\206\000\000\000" "\207\000\000\000" "\210\000\000\000"
@ -330,8 +418,96 @@ const char _nl_C_LC_CTYPE_tolower[] =
/* 0xfa */ "\372\000\000\000" "\373\000\000\000" "\374\000\000\000"
/* 0xfd */ "\375\000\000\000" "\376\000\000\000" "\377\000\000\000"
;
const char _nl_C_LC_CTYPE_names[1024] =
/* 0x00 */ "\000\000\000\000" "\001\000\000\000" "\002\000\000\000"
/* 0x03 */ "\003\000\000\000" "\004\000\000\000" "\005\000\000\000"
/* 0x06 */ "\006\000\000\000" "\007\000\000\000" "\010\000\000\000"
/* 0x09 */ "\011\000\000\000" "\012\000\000\000" "\013\000\000\000"
/* 0x0c */ "\014\000\000\000" "\015\000\000\000" "\016\000\000\000"
/* 0x0f */ "\017\000\000\000" "\020\000\000\000" "\021\000\000\000"
/* 0x12 */ "\022\000\000\000" "\023\000\000\000" "\024\000\000\000"
/* 0x15 */ "\025\000\000\000" "\026\000\000\000" "\027\000\000\000"
/* 0x18 */ "\030\000\000\000" "\031\000\000\000" "\032\000\000\000"
/* 0x1b */ "\033\000\000\000" "\034\000\000\000" "\035\000\000\000"
/* 0x1e */ "\036\000\000\000" "\037\000\000\000" "\040\000\000\000"
/* 0x21 */ "\041\000\000\000" "\042\000\000\000" "\043\000\000\000"
/* 0x24 */ "\044\000\000\000" "\045\000\000\000" "\046\000\000\000"
/* 0x27 */ "\047\000\000\000" "\050\000\000\000" "\051\000\000\000"
/* 0x2a */ "\052\000\000\000" "\053\000\000\000" "\054\000\000\000"
/* 0x2d */ "\055\000\000\000" "\056\000\000\000" "\057\000\000\000"
/* 0x30 */ "\060\000\000\000" "\061\000\000\000" "\062\000\000\000"
/* 0x33 */ "\063\000\000\000" "\064\000\000\000" "\065\000\000\000"
/* 0x36 */ "\066\000\000\000" "\067\000\000\000" "\070\000\000\000"
/* 0x39 */ "\071\000\000\000" "\072\000\000\000" "\073\000\000\000"
/* 0x3c */ "\074\000\000\000" "\075\000\000\000" "\076\000\000\000"
/* 0x3f */ "\077\000\000\000" "\100\000\000\000" "\101\000\000\000"
/* 0x42 */ "\102\000\000\000" "\103\000\000\000" "\104\000\000\000"
/* 0x45 */ "\105\000\000\000" "\106\000\000\000" "\107\000\000\000"
/* 0x48 */ "\110\000\000\000" "\111\000\000\000" "\112\000\000\000"
/* 0x4b */ "\113\000\000\000" "\114\000\000\000" "\115\000\000\000"
/* 0x4e */ "\116\000\000\000" "\117\000\000\000" "\120\000\000\000"
/* 0x51 */ "\121\000\000\000" "\122\000\000\000" "\123\000\000\000"
/* 0x54 */ "\124\000\000\000" "\125\000\000\000" "\126\000\000\000"
/* 0x57 */ "\127\000\000\000" "\130\000\000\000" "\131\000\000\000"
/* 0x5a */ "\132\000\000\000" "\133\000\000\000" "\134\000\000\000"
/* 0x5d */ "\135\000\000\000" "\136\000\000\000" "\137\000\000\000"
/* 0x60 */ "\140\000\000\000" "\141\000\000\000" "\142\000\000\000"
/* 0x63 */ "\143\000\000\000" "\144\000\000\000" "\145\000\000\000"
/* 0x66 */ "\146\000\000\000" "\147\000\000\000" "\150\000\000\000"
/* 0x69 */ "\151\000\000\000" "\152\000\000\000" "\153\000\000\000"
/* 0x6c */ "\154\000\000\000" "\155\000\000\000" "\156\000\000\000"
/* 0x6f */ "\157\000\000\000" "\160\000\000\000" "\161\000\000\000"
/* 0x72 */ "\162\000\000\000" "\163\000\000\000" "\164\000\000\000"
/* 0x75 */ "\165\000\000\000" "\166\000\000\000" "\167\000\000\000"
/* 0x78 */ "\170\000\000\000" "\171\000\000\000" "\172\000\000\000"
/* 0x7b */ "\173\000\000\000" "\174\000\000\000" "\175\000\000\000"
/* 0x7e */ "\176\000\000\000" "\177\000\000\000" "\200\000\000\000"
/* 0x81 */ "\201\000\000\000" "\202\000\000\000" "\203\000\000\000"
/* 0x84 */ "\204\000\000\000" "\205\000\000\000" "\206\000\000\000"
/* 0x87 */ "\207\000\000\000" "\210\000\000\000" "\211\000\000\000"
/* 0x8a */ "\212\000\000\000" "\213\000\000\000" "\214\000\000\000"
/* 0x8d */ "\215\000\000\000" "\216\000\000\000" "\217\000\000\000"
/* 0x90 */ "\220\000\000\000" "\221\000\000\000" "\222\000\000\000"
/* 0x93 */ "\223\000\000\000" "\224\000\000\000" "\225\000\000\000"
/* 0x96 */ "\226\000\000\000" "\227\000\000\000" "\230\000\000\000"
/* 0x99 */ "\231\000\000\000" "\232\000\000\000" "\233\000\000\000"
/* 0x9c */ "\234\000\000\000" "\235\000\000\000" "\236\000\000\000"
/* 0x9f */ "\237\000\000\000" "\240\000\000\000" "\241\000\000\000"
/* 0xa2 */ "\242\000\000\000" "\243\000\000\000" "\244\000\000\000"
/* 0xa5 */ "\245\000\000\000" "\246\000\000\000" "\247\000\000\000"
/* 0xa8 */ "\250\000\000\000" "\251\000\000\000" "\252\000\000\000"
/* 0xab */ "\253\000\000\000" "\254\000\000\000" "\255\000\000\000"
/* 0xae */ "\256\000\000\000" "\257\000\000\000" "\260\000\000\000"
/* 0xb1 */ "\261\000\000\000" "\262\000\000\000" "\263\000\000\000"
/* 0xb4 */ "\264\000\000\000" "\265\000\000\000" "\266\000\000\000"
/* 0xb7 */ "\267\000\000\000" "\270\000\000\000" "\271\000\000\000"
/* 0xba */ "\272\000\000\000" "\273\000\000\000" "\274\000\000\000"
/* 0xbd */ "\275\000\000\000" "\276\000\000\000" "\277\000\000\000"
/* 0xc0 */ "\300\000\000\000" "\301\000\000\000" "\302\000\000\000"
/* 0xc3 */ "\303\000\000\000" "\304\000\000\000" "\305\000\000\000"
/* 0xc6 */ "\306\000\000\000" "\307\000\000\000" "\310\000\000\000"
/* 0xc9 */ "\311\000\000\000" "\312\000\000\000" "\313\000\000\000"
/* 0xcc */ "\314\000\000\000" "\315\000\000\000" "\316\000\000\000"
/* 0xcf */ "\317\000\000\000" "\320\000\000\000" "\321\000\000\000"
/* 0xd2 */ "\322\000\000\000" "\323\000\000\000" "\324\000\000\000"
/* 0xd5 */ "\325\000\000\000" "\326\000\000\000" "\327\000\000\000"
/* 0xd8 */ "\330\000\000\000" "\331\000\000\000" "\332\000\000\000"
/* 0xdb */ "\333\000\000\000" "\334\000\000\000" "\335\000\000\000"
/* 0xde */ "\336\000\000\000" "\337\000\000\000" "\340\000\000\000"
/* 0xe1 */ "\341\000\000\000" "\342\000\000\000" "\343\000\000\000"
/* 0xe4 */ "\344\000\000\000" "\345\000\000\000" "\346\000\000\000"
/* 0xe7 */ "\347\000\000\000" "\350\000\000\000" "\351\000\000\000"
/* 0xea */ "\352\000\000\000" "\353\000\000\000" "\354\000\000\000"
/* 0xed */ "\355\000\000\000" "\356\000\000\000" "\357\000\000\000"
/* 0xf0 */ "\360\000\000\000" "\361\000\000\000" "\362\000\000\000"
/* 0xf3 */ "\363\000\000\000" "\364\000\000\000" "\365\000\000\000"
/* 0xf6 */ "\366\000\000\000" "\367\000\000\000" "\370\000\000\000"
/* 0xf9 */ "\371\000\000\000" "\372\000\000\000" "\373\000\000\000"
/* 0xfc */ "\374\000\000\000" "\375\000\000\000" "\376\000\000\000"
/* 0xff */ "\377\000\000\000"
;
#elif BYTE_ORDER == BIG_ENDIAN
const char _nl_C_LC_CTYPE_toupper[] =
const char _nl_C_LC_CTYPE_toupper[1536] =
/* 0x80 */ "\000\000\000\200" "\000\000\000\201" "\000\000\000\202"
/* 0x83 */ "\000\000\000\203" "\000\000\000\204" "\000\000\000\205"
/* 0x86 */ "\000\000\000\206" "\000\000\000\207" "\000\000\000\210"
@ -461,7 +637,7 @@ const char _nl_C_LC_CTYPE_toupper[] =
/* 0xfa */ "\000\000\000\372" "\000\000\000\373" "\000\000\000\374"
/* 0xfd */ "\000\000\000\375" "\000\000\000\376" "\000\000\000\377"
;
const char _nl_C_LC_CTYPE_tolower[] =
const char _nl_C_LC_CTYPE_tolower[1536] =
/* 0x80 */ "\000\000\000\200" "\000\000\000\201" "\000\000\000\202"
/* 0x83 */ "\000\000\000\203" "\000\000\000\204" "\000\000\000\205"
/* 0x86 */ "\000\000\000\206" "\000\000\000\207" "\000\000\000\210"
@ -591,18 +767,140 @@ const char _nl_C_LC_CTYPE_tolower[] =
/* 0xfa */ "\000\000\000\372" "\000\000\000\373" "\000\000\000\374"
/* 0xfd */ "\000\000\000\375" "\000\000\000\376" "\000\000\000\377"
;
const char _nl_C_LC_CTYPE_names[1024] =
/* 0x00 */ "\000\000\000\000" "\000\000\000\001" "\000\000\000\002"
/* 0x03 */ "\000\000\000\003" "\000\000\000\004" "\000\000\000\005"
/* 0x06 */ "\000\000\000\006" "\000\000\000\007" "\000\000\000\010"
/* 0x09 */ "\000\000\000\011" "\000\000\000\012" "\000\000\000\013"
/* 0x0c */ "\000\000\000\014" "\000\000\000\015" "\000\000\000\016"
/* 0x0f */ "\000\000\000\017" "\000\000\000\020" "\000\000\000\021"
/* 0x12 */ "\000\000\000\022" "\000\000\000\023" "\000\000\000\024"
/* 0x15 */ "\000\000\000\025" "\000\000\000\026" "\000\000\000\027"
/* 0x18 */ "\000\000\000\030" "\000\000\000\031" "\000\000\000\032"
/* 0x1b */ "\000\000\000\033" "\000\000\000\034" "\000\000\000\035"
/* 0x1e */ "\000\000\000\036" "\000\000\000\037" "\000\000\000\040"
/* 0x21 */ "\000\000\000\041" "\000\000\000\042" "\000\000\000\043"
/* 0x24 */ "\000\000\000\044" "\000\000\000\045" "\000\000\000\046"
/* 0x27 */ "\000\000\000\047" "\000\000\000\050" "\000\000\000\051"
/* 0x2a */ "\000\000\000\052" "\000\000\000\053" "\000\000\000\054"
/* 0x2d */ "\000\000\000\055" "\000\000\000\056" "\000\000\000\057"
/* 0x30 */ "\000\000\000\060" "\000\000\000\061" "\000\000\000\062"
/* 0x33 */ "\000\000\000\063" "\000\000\000\064" "\000\000\000\065"
/* 0x36 */ "\000\000\000\066" "\000\000\000\067" "\000\000\000\070"
/* 0x39 */ "\000\000\000\071" "\000\000\000\072" "\000\000\000\073"
/* 0x3c */ "\000\000\000\074" "\000\000\000\075" "\000\000\000\076"
/* 0x3f */ "\000\000\000\077" "\000\000\000\100" "\000\000\000\101"
/* 0x42 */ "\000\000\000\102" "\000\000\000\103" "\000\000\000\104"
/* 0x45 */ "\000\000\000\105" "\000\000\000\106" "\000\000\000\107"
/* 0x48 */ "\000\000\000\110" "\000\000\000\111" "\000\000\000\112"
/* 0x4b */ "\000\000\000\113" "\000\000\000\114" "\000\000\000\115"
/* 0x4e */ "\000\000\000\116" "\000\000\000\117" "\000\000\000\120"
/* 0x51 */ "\000\000\000\121" "\000\000\000\122" "\000\000\000\123"
/* 0x54 */ "\000\000\000\124" "\000\000\000\125" "\000\000\000\126"
/* 0x57 */ "\000\000\000\127" "\000\000\000\130" "\000\000\000\131"
/* 0x5a */ "\000\000\000\132" "\000\000\000\133" "\000\000\000\134"
/* 0x5d */ "\000\000\000\135" "\000\000\000\136" "\000\000\000\137"
/* 0x60 */ "\000\000\000\140" "\000\000\000\141" "\000\000\000\142"
/* 0x63 */ "\000\000\000\143" "\000\000\000\144" "\000\000\000\145"
/* 0x66 */ "\000\000\000\146" "\000\000\000\147" "\000\000\000\150"
/* 0x69 */ "\000\000\000\151" "\000\000\000\152" "\000\000\000\153"
/* 0x6c */ "\000\000\000\154" "\000\000\000\155" "\000\000\000\156"
/* 0x6f */ "\000\000\000\157" "\000\000\000\160" "\000\000\000\161"
/* 0x72 */ "\000\000\000\162" "\000\000\000\163" "\000\000\000\164"
/* 0x75 */ "\000\000\000\165" "\000\000\000\166" "\000\000\000\167"
/* 0x78 */ "\000\000\000\170" "\000\000\000\171" "\000\000\000\172"
/* 0x7b */ "\000\000\000\173" "\000\000\000\174" "\000\000\000\175"
/* 0x7e */ "\000\000\000\176" "\000\000\000\177" "\000\000\000\200"
/* 0x81 */ "\000\000\000\201" "\000\000\000\202" "\000\000\000\203"
/* 0x84 */ "\000\000\000\204" "\000\000\000\205" "\000\000\000\206"
/* 0x87 */ "\000\000\000\207" "\000\000\000\210" "\000\000\000\211"
/* 0x8a */ "\000\000\000\212" "\000\000\000\213" "\000\000\000\214"
/* 0x8d */ "\000\000\000\215" "\000\000\000\216" "\000\000\000\217"
/* 0x90 */ "\000\000\000\220" "\000\000\000\221" "\000\000\000\222"
/* 0x93 */ "\000\000\000\223" "\000\000\000\224" "\000\000\000\225"
/* 0x96 */ "\000\000\000\226" "\000\000\000\227" "\000\000\000\230"
/* 0x99 */ "\000\000\000\231" "\000\000\000\232" "\000\000\000\233"
/* 0x9c */ "\000\000\000\234" "\000\000\000\235" "\000\000\000\236"
/* 0x9f */ "\000\000\000\237" "\000\000\000\240" "\000\000\000\241"
/* 0xa2 */ "\000\000\000\242" "\000\000\000\243" "\000\000\000\244"
/* 0xa5 */ "\000\000\000\245" "\000\000\000\246" "\000\000\000\247"
/* 0xa8 */ "\000\000\000\250" "\000\000\000\251" "\000\000\000\252"
/* 0xab */ "\000\000\000\253" "\000\000\000\254" "\000\000\000\255"
/* 0xae */ "\000\000\000\256" "\000\000\000\257" "\000\000\000\260"
/* 0xb1 */ "\000\000\000\261" "\000\000\000\262" "\000\000\000\263"
/* 0xb4 */ "\000\000\000\264" "\000\000\000\265" "\000\000\000\266"
/* 0xb7 */ "\000\000\000\267" "\000\000\000\270" "\000\000\000\271"
/* 0xba */ "\000\000\000\272" "\000\000\000\273" "\000\000\000\274"
/* 0xbd */ "\000\000\000\275" "\000\000\000\276" "\000\000\000\277"
/* 0xc0 */ "\000\000\000\300" "\000\000\000\301" "\000\000\000\302"
/* 0xc3 */ "\000\000\000\303" "\000\000\000\304" "\000\000\000\305"
/* 0xc6 */ "\000\000\000\306" "\000\000\000\307" "\000\000\000\310"
/* 0xc9 */ "\000\000\000\311" "\000\000\000\312" "\000\000\000\313"
/* 0xcc */ "\000\000\000\314" "\000\000\000\315" "\000\000\000\316"
/* 0xcf */ "\000\000\000\317" "\000\000\000\320" "\000\000\000\321"
/* 0xd2 */ "\000\000\000\322" "\000\000\000\323" "\000\000\000\324"
/* 0xd5 */ "\000\000\000\325" "\000\000\000\326" "\000\000\000\327"
/* 0xd8 */ "\000\000\000\330" "\000\000\000\331" "\000\000\000\332"
/* 0xdb */ "\000\000\000\333" "\000\000\000\334" "\000\000\000\335"
/* 0xde */ "\000\000\000\336" "\000\000\000\337" "\000\000\000\340"
/* 0xe1 */ "\000\000\000\341" "\000\000\000\342" "\000\000\000\343"
/* 0xe4 */ "\000\000\000\344" "\000\000\000\345" "\000\000\000\346"
/* 0xe7 */ "\000\000\000\347" "\000\000\000\350" "\000\000\000\351"
/* 0xea */ "\000\000\000\352" "\000\000\000\353" "\000\000\000\354"
/* 0xed */ "\000\000\000\355" "\000\000\000\356" "\000\000\000\357"
/* 0xf0 */ "\000\000\000\360" "\000\000\000\361" "\000\000\000\362"
/* 0xf3 */ "\000\000\000\363" "\000\000\000\364" "\000\000\000\365"
/* 0xf6 */ "\000\000\000\366" "\000\000\000\367" "\000\000\000\370"
/* 0xf9 */ "\000\000\000\371" "\000\000\000\372" "\000\000\000\373"
/* 0xfc */ "\000\000\000\374" "\000\000\000\375" "\000\000\000\376"
/* 0xff */ "\000\000\000\377"
;
#else
#error "BYTE_ORDER" BYTE_ORDER " not handled."
#endif
const char _nl_C_LC_CTYPE_width[256] =
/* 0x00 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0x10 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0x20 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0x30 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0x40 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0x50 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0x60 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0x70 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0x80 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0x90 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0xa0 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0xb0 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0xc0 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0xd0 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0xe0 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
/* 0xf0 */ "\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001\001"
;
const struct locale_data _nl_C_LC_CTYPE =
const struct locale_data _nl_C_LC_CTYPE =
{
NULL, 0, /* no file mapped */
5,
13,
{
_nl_C_LC_CTYPE_class,
NULL, NULL,
_nl_C_LC_CTYPE_toupper,
_nl_C_LC_CTYPE_tolower
{ string: _nl_C_LC_CTYPE_class },
#if BYTE_ORDER == LITTLE_ENDIAN
{ string: NULL }, { string: NULL },
#endif
{ string: _nl_C_LC_CTYPE_toupper },
{ string: _nl_C_LC_CTYPE_tolower },
{ string: NULL },
#if BYTE_ORDER == BIG_ENDIAN
{ string: NULL },
#endif
{ string: _nl_C_LC_CTYPE_class32 },
{ string: _nl_C_LC_CTYPE_names },
#if BYTE_ORDER == BIG_ENDIAN
{ string: NULL },
#endif
{ word: 256 }, { word: 1 },
{ string: "upper\0" "lower\0" "alpha\0" "digit\0" "xdigit\0" "space\0"
"print\0" "graph\0" "blank\0" "cntrl\0" "punct\0" "alnum\0" },
{ string: "tolower\0" "toupper\0" },
{ string: _nl_C_LC_CTYPE_width }
}
};

View file

@ -1,5 +1,5 @@
/* Generated by GNU locale 0.1.
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. */
@ -11,9 +11,9 @@ const struct locale_data _nl_C_LC_MESSAGES =
NULL, 0, /* no file mapped */
4,
{
"[yY][[:alpha:]]",
"[nN][[:alpha:]]",
"",
""
{ string: "[yY][[:alpha:]]" },
{ string: "[nN][[:alpha:]]" },
{ string: "" },
{ string: "" }
}
};

View file

@ -1,5 +1,5 @@
/* Generated by GNU locale 0.1.
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. */
@ -11,20 +11,20 @@ const struct locale_data _nl_C_LC_MONETARY =
NULL, 0, /* no file mapped */
15,
{
"",
"",
"",
"",
"\177",
"",
"",
"\177",
"\177",
"\177",
"\177",
"\177",
"\177",
"\177",
"\177"
{ string: "" },
{ string: "" },
{ string: "" },
{ string: "" },
{ string: "\177" },
{ string: "" },
{ string: "" },
{ string: "\177" },
{ string: "\177" },
{ string: "\177" },
{ string: "\177" },
{ string: "\177" },
{ string: "\177" },
{ string: "\177" },
{ string: "\177" }
}
};

View file

@ -1,5 +1,5 @@
/* Generated by GNU locale 0.1.
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. */
@ -11,8 +11,8 @@ const struct locale_data _nl_C_LC_NUMERIC =
NULL, 0, /* no file mapped */
3,
{
".",
"",
"\177"
{ string: "." },
{ string: "" },
{ string: "\177" }
}
};

View file

@ -1,5 +1,5 @@
/* Generated by GNU locale 0.1.
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. */
@ -9,51 +9,52 @@ PARTICULAR PURPOSE. */
const struct locale_data _nl_C_LC_TIME =
{
NULL, 0, /* no file mapped */
44,
45,
{
"Sun",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
"AM",
"PM",
"%a %b %d %H:%M:%S %Y",
"%m/%d/%y",
"%H:%M:%S",
NULL
{ string: "Sun" },
{ string: "Mon" },
{ string: "Tue" },
{ string: "Wed" },
{ string: "Thu" },
{ string: "Fri" },
{ string: "Sat" },
{ string: "Sunday" },
{ string: "Monday" },
{ string: "Tuesday" },
{ string: "Wednesday" },
{ string: "Thursday" },
{ string: "Friday" },
{ string: "Saturday" },
{ string: "Jan" },
{ string: "Feb" },
{ string: "Mar" },
{ string: "Apr" },
{ string: "May" },
{ string: "Jun" },
{ string: "Jul" },
{ string: "Aug" },
{ string: "Sep" },
{ string: "Oct" },
{ string: "Nov" },
{ string: "Dec" },
{ string: "January" },
{ string: "February" },
{ string: "March" },
{ string: "April" },
{ string: "May" },
{ string: "June" },
{ string: "July" },
{ string: "August" },
{ string: "September" },
{ string: "October" },
{ string: "November" },
{ string: "December" },
{ string: "AM" },
{ string: "PM" },
{ string: "%a %b %d %H:%M:%S %Y" },
{ string: "%m/%d/%y" },
{ string: "%H:%M:%S" },
{ string: "%I:%M:%S %p" },
{ string: NULL }
}
};

View file

@ -13,8 +13,8 @@
# 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., 675 Mass Ave,
# Cambridge, MA 02139, USA.
# not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Makefile for locales.
@ -24,20 +24,25 @@ subdir := locale
headers = locale.h
distribute = localeinfo.h categories.def \
$(localedef-modules:=.c) $(locale-modules:=.c) \
$(lib-modules:=.c) config.h hash.h iso-4217.def \
keyword.gperf keyword.h localedef.h token.h
$(lib-modules:=.c) config.h simple-hash.h iso-4217.def \
charmap-kw.gperf charmap-kw.h locfile-token.h \
locfile-kw.gperf locfile-kw.h linereader.h \
locales.h locfile.h stringtrans.h
routines = setlocale loadlocale localeconv nl_langinfo
categories = ctype messages monetary numeric time collate
aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc
others = localedef locale
install-bin = localedef locale
others = localedef# locale
install-bin = localedef# locale
extra-objs = $(localedef-modules:=.o) $(locale-modules:=.o) \
$(lib-modules:=.o)
localedef-modules := charmap locfile-lex locfile-parse locale-ctype \
monetary messages collate numeric
vpath %.c programs
vpath %.h programs
localedef-modules := $(categories:%=ld-%) charmap charset linereader \
locfile stringtrans
locale-modules := ctypedump
lib-modules := locfile-hash xmalloc
lib-modules := simple-hash xmalloc xstrdup
GPERF = gperf
@ -45,14 +50,18 @@ GPERFFLAGS = -acCgopt -k1,2,5,$$
include ../Rules
keyword.h: keyword.gperf
$(GPERF) $(GPERFFLAGS) $< > $@.new
programs/%-kw.h: programs/%-kw.gperf
$(GPERF) $(GPERFFLAGS) -N $(@F:-kw.h=_hash) $< > $@.new
mv -f $@.new $@
$(objpfx)localedef: $(localedef-modules:%=$(objpfx)%.o)
$(objpfx)locale: $(locale-modules:%=$(objpfx)%.o)
$(objpfx)localedef $(objpfx)locale: $(lib-modules:%=$(objpfx)%.o)
CPPFLAGS += -DLOCALE_PATH='"$(localedir)"' -DCHARMAP_PATH='"$(nlsdir)/charmap"'
CPPFLAGS := -DLOCALE_PATH='"$(localedir)"' \
-DCHARMAP_PATH='"$(i18ndir)/charmap"' \
-DLOCSRCDIR='"$(i18ndir)/locales"' -DHAVE_CONFIG_H \
-Iliblib -Iprograms $(CPPFLAGS)
CFLAGS-locfile-lex.c = -Wno-write-strings
CFLAGS-charmap.c = -Wno-write-strings
CFLAGS-locfile.c = -Wno-write-strings

View file

@ -1,5 +1,5 @@
/* Definition of all available locale categories and their items. -*- C -*-
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
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
@ -32,88 +32,111 @@ Cambridge, MA 02139, USA. */
program code which loads this file.
The various value types for the items are `string', `stringarray', `byte'
and `bytearray'. These cover all possible values in the current locale
definitions. `min' and `max' can be individually used again. */
`bytearray', and `word'. These cover all possible values in the current
locale definitions. `min' and `max' can be individually used again. */
#ifndef NO_POSTLOAD
#define NO_POSTLOAD NULL
#endif
DEFINE_CATEGORY (LC_COLLATE, "LC_COLLATE",
(
{ 0 } /* No data encoding yet. */
), NO_POSTLOAD, collate_input, NULL, NULL )
DEFINE_CATEGORY
(
LC_COLLATE, "LC_COLLATE",
(
DEFINE_ELEMENT (_NL_COLLATE_NRULES, "collate-nrules", std, word)
DEFINE_ELEMENT (_NL_COLLATE_RULES, "collate-rules", std, string)
DEFINE_ELEMENT (_NL_COLLATE_HASH_SIZE, "collate-hash-size", std, word)
DEFINE_ELEMENT (_NL_COLLATE_HASH_LAYERS, "collate-hash-layers", std, word)
DEFINE_ELEMENT (_NL_COLLATE_TABLE_EB, "collate-table-eb", std, string)
DEFINE_ELEMENT (_NL_COLLATE_TABLE_EL, "collate-table-el", std, string)
DEFINE_ELEMENT (_NL_COLLATE_UNDEFINED, "collate-undefined", std, word)
DEFINE_ELEMENT (_NL_COLLATE_EXTRA_EB, "collate-extra-eb", std, string)
DEFINE_ELEMENT (_NL_COLLATE_EXTRA_EL, "collate-extra-el", std, string)
), _nl_postload_collate, collate_input, NULL, NULL)
/* The actual definition of ctype is meaningless here. It is hard coded in
the code because it has to be handled very specially. Only the names of
the functions are important. */
DEFINE_CATEGORY (LC_CTYPE, "LC_CTYPE",
(
{ _NL_CTYPE_CLASS, "ctype-class", std, string },
{ _NL_CTYPE_TOUPPER_EB, "ctype-toupper-eb", std, string },
{ _NL_CTYPE_TOLOWER_EB, "ctype-tolower-eb", std, string },
{ _NL_CTYPE_TOUPPER_EL, "ctype-toupper-el", std, string },
{ _NL_CTYPE_TOLOWER_EL, "ctype-tolower-el", std, string },
{ 0 }
), _nl_postload_ctype,
ctype_input, ctype_check, ctype_output )
the functions and the value types are important. */
DEFINE_CATEGORY
(
LC_CTYPE, "LC_CTYPE",
(
DEFINE_ELEMENT (_NL_CTYPE_CLASS, "ctype-class", std, string)
DEFINE_ELEMENT (_NL_CTYPE_TOUPPER_EB, "ctype-toupper-eb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_TOLOWER_EB, "ctype-tolower-eb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_TOUPPER_EL, "ctype-toupper-el", std, string)
DEFINE_ELEMENT (_NL_CTYPE_TOLOWER_EL, "ctype-tolower-el", std, string)
DEFINE_ELEMENT (_NL_CTYPE_NAMES_EB, "ctype-names-eb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_NAMES_EL, "ctype-names-eb", std, string)
DEFINE_ELEMENT (_NL_CTYPE_HASH_SIZE, "ctype-hash-size", std, word)
DEFINE_ELEMENT (_NL_CTYPE_HASH_LAYERS, "ctype-hash-layers", std, word)
DEFINE_ELEMENT (_NL_CTYPE_CLASS_NAMES, "ctype-class-names", std, string)
DEFINE_ELEMENT (_NL_CTYPE_MAP_NAMES, "ctype-map-names", std, string)
DEFINE_ELEMENT (_NL_CTYPE_WIDTH, "ctype-width", std, bytearray)
), _nl_postload_ctype, ctype_input, ctype_check, ctype_output)
DEFINE_CATEGORY (LC_MONETARY, "LC_MONETARY",
(
{ INT_CURR_SYMBOL, "int_curr_symbol", std, string },
{ CURRENCY_SYMBOL, "currency_symbol", std, string },
{ MON_DECIMAL_POINT, "mon_decimal_point", std, string },
{ MON_THOUSANDS_SEP, "mon_thousands_sep", std, string },
{ MON_GROUPING, "mon_grouping", std, bytearray },
{ POSITIVE_SIGN, "positive_sign", std, string },
{ NEGATIVE_SIGN, "negative_sign", std, string },
{ INT_FRAC_DIGITS, "int_frac_digits", std, byte },
{ FRAC_DIGITS, "frac_digits", std, byte },
{ P_CS_PRECEDES, "p_cs_precedes", std, byte, 0, 1 },
{ P_SEP_BY_SPACE, "p_sep_by_space", std, byte, 0, 2 },
{ N_CS_PRECEDES, "n_cs_precedes", std, byte, 0, 1 },
{ N_SEP_BY_SPACE, "n_sep_by_space", std, byte, 0, 2 },
{ P_SIGN_POSN, "p_sign_posn", std, byte, 0, 4 },
{ N_SIGN_POSN, "n_sign_posn", std, byte, 0, 4 },
{ 0 }
), NO_POSTLOAD, NULL, monetary_check, NULL )
DEFINE_CATEGORY
(
LC_MONETARY, "LC_MONETARY",
(
DEFINE_ELEMENT (INT_CURR_SYMBOL, "int_curr_symbol", std, string)
DEFINE_ELEMENT (CURRENCY_SYMBOL, "currency_symbol", std, string)
DEFINE_ELEMENT (MON_DECIMAL_POINT, "mon_decimal_point", std, string)
DEFINE_ELEMENT (MON_THOUSANDS_SEP, "mon_thousands_sep", std, string)
DEFINE_ELEMENT (MON_GROUPING, "mon_grouping", std, bytearray)
DEFINE_ELEMENT (POSITIVE_SIGN, "positive_sign", std, string)
DEFINE_ELEMENT (NEGATIVE_SIGN, "negative_sign", std, string)
DEFINE_ELEMENT (INT_FRAC_DIGITS, "int_frac_digits", std, byte)
DEFINE_ELEMENT (FRAC_DIGITS, "frac_digits", std, byte)
DEFINE_ELEMENT (P_CS_PRECEDES, "p_cs_precedes", std, byte, 0, 1)
DEFINE_ELEMENT (P_SEP_BY_SPACE, "p_sep_by_space", std, byte, 0, 2)
DEFINE_ELEMENT (N_CS_PRECEDES, "n_cs_precedes", std, byte, 0, 1)
DEFINE_ELEMENT (N_SEP_BY_SPACE, "n_sep_by_space", std, byte, 0, 2)
DEFINE_ELEMENT (P_SIGN_POSN, "p_sign_posn", std, byte, 0, 4)
DEFINE_ELEMENT (N_SIGN_POSN, "n_sign_posn", std, byte, 0, 4)
), NO_POSTLOAD, NULL, monetary_check, NULL)
DEFINE_CATEGORY (LC_NUMERIC, "LC_NUMERIC",
(
{ DECIMAL_POINT, "decimal_point", std, string },
{ THOUSANDS_SEP, "thousands_sep", std, string },
{ GROUPING, "grouping", std, bytearray },
{ 0 }
), NO_POSTLOAD, NULL, numeric_check, NULL)
DEFINE_CATEGORY
(
LC_NUMERIC, "LC_NUMERIC",
(
DEFINE_ELEMENT (DECIMAL_POINT, "decimal_point", std, string)
DEFINE_ELEMENT (THOUSANDS_SEP, "thousands_sep", std, string)
DEFINE_ELEMENT (GROUPING, "grouping", std, bytearray)
), NO_POSTLOAD, NULL, numeric_check, NULL)
DEFINE_CATEGORY (LC_TIME, "LC_TIME",
(
{ ABDAY_1, "abday", std, stringarray, 7, 7 },
{ DAY_1, "day", std, stringarray, 7, 7 },
{ ABMON_1, "abmon", std, stringarray, 12, 12 },
{ MON_1, "mon", std, stringarray, 12, 12 },
{ AM_STR, "am_pm", std, stringarray, 2, 2 },
{ D_T_FMT, "d_t_fmt", std, string },
{ D_FMT, "d_fmt", std, string },
{ T_FMT, "t_fmt", std, string },
{ T_FMT_AMPM, "t_fmt_ampm", std, string },
{ ERA, "era", opt, string },
{ ERA_YEAR, "era_year", opt, string },
{ ERA_D_FMT, "era_d_fmt", opt, string },
{ ALT_DIGITS, "alt_digits", opt, stringarray, 0, 100 },
{ 0 }
), NO_POSTLOAD, NULL, NULL, NULL )
DEFINE_CATEGORY
(
LC_TIME, "LC_TIME",
(
DEFINE_ELEMENT (ABDAY_1, "abday", std, stringarray, 7, 7)
DEFINE_ELEMENT (DAY_1, "day", std, stringarray, 7, 7)
DEFINE_ELEMENT (ABMON_1, "abmon", std, stringarray, 12, 12)
DEFINE_ELEMENT (MON_1, "mon", std, stringarray, 12, 12)
DEFINE_ELEMENT (AM_STR, "am_pm", std, stringarray, 2, 2)
DEFINE_ELEMENT (D_T_FMT, "d_t_fmt", std, string)
DEFINE_ELEMENT (D_FMT, "d_fmt", std, string)
DEFINE_ELEMENT (T_FMT, "t_fmt", std, string)
DEFINE_ELEMENT (T_FMT_AMPM, "t_fmt_ampm", std, string)
DEFINE_ELEMENT (ERA, "era", opt, string)
DEFINE_ELEMENT (ERA_YEAR, "era_year", opt, string)
DEFINE_ELEMENT (ERA_D_FMT, "era_d_fmt", opt, string)
DEFINE_ELEMENT (ALT_DIGITS, "alt_digits", opt, stringarray, 0, 100)
DEFINE_ELEMENT (ERA_D_T_FMT, "era_d_t_fmt", opt, string)
DEFINE_ELEMENT (ERA_T_FMT, "era_t_fmt", opt, string)
), NO_POSTLOAD, NULL, NULL, NULL)
DEFINE_CATEGORY (LC_MESSAGES, "LC_MESSAGES",
(
{ YESEXPR, "yesexpr", std, string },
{ NOEXPR, "noexpr", std, string },
{ YESSTR, "yesstr", opt, string },
{ NOSTR, "nostr", opt, string },
{ 0 }
), NO_POSTLOAD, NULL, messages_check, NULL )
DEFINE_CATEGORY
(
LC_MESSAGES, "LC_MESSAGES",
(
DEFINE_ELEMENT (YESEXPR, "yesexpr", std, string)
DEFINE_ELEMENT (NOEXPR, "noexpr", std, string)
DEFINE_ELEMENT (YESSTR, "yesstr", opt, string)
DEFINE_ELEMENT (NOSTR, "nostr", opt, string)
), NO_POSTLOAD, NULL, messages_check, NULL)

View file

@ -1,524 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <ctype.h>
#include <errno.h>
#include <libintl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "localedef.h"
#include "hash.h"
/* Data structure for representing charmap database. */
struct charmap charmap_data;
/* Line number in charmap file. */
static unsigned int line_no;
/* Prototypes for local functions. */
static void read_prolog (FILE *infile);
static unsigned long read_body (FILE *infile);
/* Read complete table of symbolic names for character set from file. If
this file does not exist or is not readable a default file is tried.
If this also is not readable no character map is defined. */
void
charmap_read (const char *filename)
{
unsigned long max_char;
long path_max = pathconf (".", _PC_PATH_MAX);
char buf[path_max];
FILE *infile = NULL;
/* Initialize charmap data. */
charmap_data.codeset_name = NULL;
charmap_data.mb_cur_max = -1;
charmap_data.mb_cur_min = -1;
charmap_data.escape_char = '\\';
charmap_data.comment_char = '#';
if (filename != NULL)
{
strcpy (buf, filename);
infile = fopen (filename, "r");
if (infile == NULL && filename[0] != '/')
{
snprintf (buf, path_max, "%s/%s", CHARMAP_PATH, filename);
infile = fopen (buf, "r");
}
}
if (infile == NULL)
{
if (filename != NULL)
error (0, errno, gettext ("input file `%s' not found"), filename);
snprintf (buf, path_max, "%s/%s", CHARMAP_PATH, DEFAULT_CHARMAP);
infile = fopen (buf, "r");
if (infile == NULL)
error (4, errno, gettext ("input file `%s' not found"), filename);
}
charmap_data.filename = buf;
init_hash (&charmap_data.table, 500);
line_no = 0;
/* Read the prolog of the charmap file. */
read_prolog (infile);
/* Last works on the charmap tables global data. */
if (charmap_data.mb_cur_max == -1)
charmap_data.mb_cur_max = 1;
if (charmap_data.mb_cur_min == -1)
charmap_data.mb_cur_min = charmap_data.mb_cur_max;
if ((size_t) charmap_data.mb_cur_max > sizeof (long))
{
error (2, 0, gettext ("program limitation: for now only upto %Zu "
"bytes per character are allowed"), sizeof (long));
}
/* Now process all entries. */
max_char = read_body (infile);
/* We don't need the file anymore. */
fclose (infile);
/* Determine the optimal table size when using the simple modulo hashing
function. */
if (max_char >= 256)
{
int size;
/* Current best values, initialized to some never reached high value. */
int best_count = 10000;
int best_size = 10000;
int best_product = best_count * best_size;
/* Give warning. */
error (-1, 0, gettext ("computing character table size: this may take "
"a while"));
for (size = 256; size <= best_product; ++size)
{
/* Array with slot counters. */
int cnt[size];
/* Current character. */
int ch;
/* Maximal number of characters in any slot. */
int maxcnt = 0;
/* Product of current size and maximal count. */
int product = 0;
/* Iteration pointer through hashing table. */
char *ptr = NULL;
/* Initializes counters to zero. */
memset(cnt, 0, size * sizeof (int));
/* Iterate through whole hashing table. */
while (product < best_product
&& iterate_table (&charmap_data.table, (void **) &ptr,
(void **) &ch))
{
/* Increment slot counter. */
++cnt[ch % size];
/* Test for current maximum. */
if (cnt[ch % size] > maxcnt)
{
maxcnt = cnt[ch % size];
product = maxcnt * size;
}
}
if (product < best_product)
{
best_count = maxcnt;
best_size = size;
best_product = best_count * best_size;
}
}
charmap_data.hash_size = best_size;
charmap_data.hash_layers = best_count;
}
else
{
charmap_data.hash_size = 256;
charmap_data.hash_layers = 1;
}
}
#define SYNTAX_ERROR \
do { error (0, 0, gettext ("%s:%u: syntax error in charmap file"), \
charmap_data.filename, line_no); \
goto end_of_loop; } while (0)
/* Read the prolog of the charmap file until the line containing `CHARMAP'.
All possible entries are processed. */
static void
read_prolog (FILE *infile)
{
size_t bufsize = sysconf (_SC_LINE_MAX);
char buf[bufsize];
while (1)
{
char *cp = buf;
char len;
/* Read the next line. */
fgets (buf, bufsize, infile);
len = strlen (buf);
/* On EOF simply return. */
if (len == 0 || buf[len - 1] != '\n')
error (4, 0, gettext ("%s: unexpected end of file in charmap"),
charmap_data.filename);
/* This is the next line. */
++line_no;
/* Comments and empty lines are ignored. */
if (len == 1 || buf[0] == charmap_data.comment_char)
continue;
buf[len - 1] = '\0';
/* Throw away leading white spaces. This is not defined in POSIX.2
so don't do it if conformance is requested. */
if (!posix_conformance)
while (isspace (*cp))
++cp;
/* If `CHARMAP' is read the prolog is over. */
if (strncmp (cp, "CHARMAP", 7) == 0
&& (!posix_conformance || cp[7] == '\0'))
return;
/* Now it can be only one of special symbols defining the charmap
parameters. All are beginning with '<'. */
if (*cp != '<')
SYNTAX_ERROR;
++cp;
if (strncmp (cp, "code_set_name>", 14) == 0)
{
char *startp;
#define cp_to_arg(no,pred) \
cp += no; \
while (isspace (*cp)) \
++cp; \
if (*cp == '\0' || !pred (*cp)) \
SYNTAX_ERROR;
cp_to_arg (14,isgraph)
if (charmap_data.codeset_name != NULL)
{
error (0, 0, gettext ("%s:%u: duplicate code set name "
"specification"),
charmap_data.filename, line_no);
free (charmap_data.codeset_name);
}
startp = cp;
while (*cp != '\0' && isgraph (*cp) && !isspace (*cp))
++cp;
charmap_data.codeset_name = (char *) xmalloc (cp - startp + 1);
strncpy (startp, startp, cp - startp);
}
else if (strncmp (cp, "mb_cur_max>", 11) == 0)
{
int new_val;
cp_to_arg (11,isdigit)
if (charmap_data.mb_cur_max != -1)
error (0, 0,
gettext ("%s:%u: duplicate definition of mb_cur_max"),
charmap_data.filename, line_no);
new_val = (int) strtol (cp, &cp, posix_conformance ? 10 : 0);
if (new_val < 1)
error (0, 0, gettext ("%s:%u: illegal value for mb_cur_max: %d"),
charmap_data.filename, line_no, new_val);
else
charmap_data.mb_cur_max = new_val;
}
else if (strncmp (cp, "mb_cur_min>", 11) == 0)
{
int new_val;
cp_to_arg (11,isdigit)
if (charmap_data.mb_cur_max != -1)
error (0, 0,
gettext ("%s:%u: duplicate definition of mb_cur_min"),
charmap_data.filename, line_no);
new_val = (int) strtol (cp, &cp, posix_conformance ? 10 : 0);
if (new_val < 1)
error (0, 0, gettext ("%s:%u: illegal value for mb_cur_min: %d"),
charmap_data.filename, line_no, new_val);
else
charmap_data.mb_cur_min = new_val;
}
else if (strncmp (cp, "escape_char>", 12) == 0)
{
cp_to_arg (12, isgraph)
charmap_data.escape_char = *cp;
}
else if (strncmp (cp, "comment_char>", 13) == 0)
{
cp_to_arg (13, isgraph)
charmap_data.comment_char = *cp;
}
else
SYNTAX_ERROR;
end_of_loop:
}
}
#undef cp_to_arg
static unsigned long
read_body (FILE *infile)
{
unsigned long max_char = 0;
size_t bufsize = sysconf (_SC_LINE_MAX);
char buf[bufsize];
char name_str[bufsize / 2];
char code_str[bufsize / 2];
while (1)
{
char *cp = buf;
size_t len;
/* Read the next line. */
fgets (buf, bufsize, infile);
len = strlen (buf);
/* On EOF simply return. */
if (len == 0)
error (0, 0, gettext ("%s: `END CHARMAP' is missing"),
charmap_data.filename);
/* This is the next line. */
++line_no;
if (len == bufsize - 1)
{
error (0, 0, gettext ("%s:%u: line too long; use `getconf "
"LINE_MAX' to get the current maximum line"
"length"), charmap_data.filename, line_no);
do
{
fgets (buf, bufsize, infile);
len = strlen (buf);
}
while (len == bufsize - 1);
continue;
}
/* Comments and empty lines are ignored. */
if (len == 1 || buf[0] == charmap_data.comment_char)
continue;
buf[len - 1] = '\0';
/* Throw away leading white spaces. This is not defined in POSIX.2
so don't do it if conformance is requested. */
if (!posix_conformance)
while (isspace (*cp))
++cp;
if (*cp == '<')
{
char *end1p, *end2p, *start2p;
size_t cnt = 0;
unsigned long char_value = 0;
if (sscanf (cp + 1, "%s %s", name_str, code_str) != 2)
SYNTAX_ERROR;
end1p = cp = name_str;
while (*cp != '\0' && *cp != '>')
{
if (*cp == charmap_data.escape_char)
if (*++cp == '\0')
SYNTAX_ERROR;
*end1p++ = *cp++;
}
if (*cp == '\0')
/* No final '>'. Make error condition. */
end1p = name_str;
else
++cp;
*end1p = '\0';
if (*cp == '.' && *++cp == '.' && *++cp == '.' && *++cp == '<')
{
/* This might be the alternate form. */
start2p = end2p = ++cp;
while (*cp != '\0' && *cp != '>')
{
if (*cp == charmap_data.escape_char)
if (*++cp == '\0')
SYNTAX_ERROR;
*end2p = *cp++;
}
if (*cp == '\0')
/* NO final '>'. Make error condition. */
end2p = start2p;
else
++cp;
}
else
start2p = end2p = NULL;
if (end1p == name_str || (start2p != NULL && start2p != end2p)
|| *cp != '\0'
|| *code_str != charmap_data.escape_char)
SYNTAX_ERROR;
cp = code_str;
do
{
char *begin;
long val;
switch (*++cp)
{
case 'd':
val = strtol ((begin = cp + 1), &cp, 10);
break;
case 'x':
val = strtol ((begin = cp + 1), &cp, 16);
break;
default:
val = strtol ((begin = cp), &cp, 8);
break;
}
if (begin == cp)
SYNTAX_ERROR;
if (posix_conformance && cp - begin < 2)
error (0, 0, gettext ("%s:%u: byte constant has less than "
"two digits"),
charmap_data.filename, line_no);
if (val < 0 || val > 255)
{
error (0, 0, gettext ("%s:%u: character encoding must be "
"given in 8-bit bytes"),
charmap_data.filename, line_no);
goto end_of_loop;
}
if (cnt < (size_t) charmap_data.mb_cur_max)
{
if (cnt < sizeof (long)) /* FIXME */
char_value = (char_value << 8) | val;
}
else
{
error (0, 0, gettext ("%s:%u: number of bytes in character "
"definition exceeds `mb_cur_max'"),
charmap_data.filename, line_no);
break;
}
++cnt;
}
while (*cp == charmap_data.escape_char);
/* Ignore the rest of the line (comment). */
if (end2p == NULL)
{
if (insert_entry (&charmap_data.table, name_str,
end1p - name_str, (void *) char_value))
error (0, 0, gettext ("%s:%u: duplicate entry"),
charmap_data.filename, line_no);
max_char = MAX (max_char, char_value);
}
else
{
char *en1, *en2, *start1p;
long n1, n2, n;
start1p = name_str;
while (*start1p == *start2p && !isdigit (*start1p)
&& start1p < end1p)
++start1p, ++start2p;
n1 = strtol (start1p, &en1, 10);
n2 = strtol (start2p, &en2, 10);
if (en1 - start1p != en2 - start2p || en1 != end1p
|| en2 != end2p)
SYNTAX_ERROR;
if (n1 > n2)
error (0, 0, gettext ("%s:%u: starting character is bigger "
"than last"),
charmap_data.filename, line_no);
n = n1;
while (n <= n2)
{
snprintf(start1p, en1 - start1p, "%0*d", en1 - start1p, n);
if (insert_entry (&charmap_data.table, name_str,
en1 - name_str,
(void *) (char_value + n - n1)))
error (0, 0, gettext ("%s:%u: duplicate entry"),
charmap_data.filename, line_no);
max_char = MAX (max_char, char_value + n - n1);
++n;
}
}
}
else
{
if (strncmp (cp, "END CHARMAP", 11) == 0)
return max_char;
SYNTAX_ERROR;
}
end_of_loop:
}
return max_char;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/

View file

@ -1,212 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <langinfo.h>
#include <libintl.h>
#include "localedef.h"
#include "token.h"
/* defined in locfile-lex.c: flag to indicate that unknown element names
are allowed. */
extern int reject_new_char;
#define SYNTAX_ERROR \
error (0, 0, gettext ("%s:%Zd: syntax error in locale definition file"), \
locfile_data.filename, locfile_data.line_no);
void
collate_input (int token)
{
int read_order_start = 0;
while (1)
{
char *ptr;
int len;
if (token == TOK_END)
/* This is the end of the category. */
{
token = xlocfile_lex (&ptr, &len);
if (token != _NL_NUM_LC_COLLATE)
{
error (0, 0, gettext ("%s:%Zd: category `%s' does not end "
"with `END %s'"), locfile_data.filename,
locfile_data.line_no, "LC_COLLATE", "LC_COLLATE");
ignore_to_eol (0, 0);
}
else
ignore_to_eol (0, 1);
/* Start next category. */
break;
}
#if 0
/* Process line. */
if (read_order_start == 0)
/* We're still in the preambel. */
{
switch (token)
{
case TOK_COLLATING_ELEMENT:
reject_new_char = 0;
token = xlocfile_lex (&ptr, &len);
reject_new_char = 1;
if (token == TOK_CHAR)
{
error (0, 0, gettext ("%s:%Zd: symbolic name must not be "
"duplicate name in charmap"),
locfile_data.filename, locfile_data.line_no);
ignore_to_eol (0, 0);
break;
}
else if (token != TOK_ILL_CHAR)
{
SYNTAX_ERROR;
ignore_to_eol (0, 0);
break;
}
else
{
char elem_name[len + 1];
memcpy (elem_name, ptr, len);
elem_name[len] = '\0';
/* Test whether defined in symbol table. */
token = xlocfile_lex (&ptr, &len);
if (token != TOK_FROM)
{
SYNTAX_ERROR;
ignore_to_eol (0, 0);
break;
}
token = xlocfile_lex (&ptr, &len);
if (token != TOK_STRING)
{
SYNTAX_ERROR;
ignore_to_eol (0, 0);
break;
}
/* Insert collating element into table. */
/* Rest of the line should be empty. */
ignore_to_eol (0, 1);
}
break;
case TOK_COLLATING_SYMBOL:
reject_new_char = 0;
token = xlocfile_lex (&ptr, &len);
reject_new_char = 1;
if (token == TOK_CHAR)
{
error (0, 0, gettext ("%s:%Zd: symbolic name must not "
"duplicate name in charmap"),
locfile_data.filename, locfile_data.line_no);
ignore_to_eol (0, 0);
break;
}
else if (token != TOK_ILL_CHAR)
{
SYNTAX_ERROR;
ignore_to_eol (0, 0);
break;
}
else
{
/* Test whether defined in element table. */
/* Insert collating symbol into table. */
ignore_to_eol (0, 1);
}
case TOK_ORDER_START:
nsort_rules = 0;
do
{
token = xlocfile_lex (&ptr, &len);
if (nsort_rules == 0 && token == ENDOFLINE)
break;
if (token != TOK_BACKWARD && token != TOK_FORWARD
&& token != TOK_POSITION)
{
SYNTAX_ERROR;
break;
}
switch (token)
{
case TOK_BACKWARD:
if ((sort_rule[nsort_rules] & FORWARD_BIT) != 0)
error (0, 0, gettext ("%s:%Zd: directives `forward' "
"and `backward' are mutually "
"exclusive"),
locfile_data.filename, locfile_data.lineno);
else
sort_rule[nsort_rules] |= BACKWARD_BIT;
break;
case TOK_FORWARD:
if ((sort_rule[nsort_rules] & BACKWARD_BIT) != 0)
error (0, 0, gettext ("%s:%Zd: directives `forward' "
"and `backward' are mutually "
"exclusive"),
locfile_data.filename, locfile_data.lineno);
else
sort_rule[nsort_rules] |= FORWARD_BIT;
break;
case TOK_POSITION:
sort_rule[nsort_rules] |= POSITION_BIT;
break;
}
++nsort_rules;
}
break;
default:
SYNTAX_ERROR;
ignore_to_eol (token, 0);
}
}
else
{
}
#endif
ignore_to_eol(token,0);
/* Get next token. */
token = xlocfile_lex (&ptr, &len);
}
}
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/

View file

@ -1,45 +0,0 @@
/* config.h used by locale and localedef programs in GNU libc.
Copyright (C) 1995 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#ifndef _CONFIG_H
#define _CONFIG_H
#define PACKAGE "libc"
#define VERSION __libc_version
extern const char __libc_version[];
#define DEFAULT_CHARMAP "POSIX"
/* These are tested by xmalloc.c and error.c. */
#define HAVE_VPRINTF 1
#define STDC_HEADERS 1
#define HAVE_STRERROR 1
#define program_name program_invocation_name
typedef unsigned short u16;
typedef int i32;
typedef int u32;
/* Get the global libc configuration info. */
#include_next <config.h>
#endif /* config.h */

View file

@ -1,50 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#ifndef _HASH_H
#define _HASH_H
#include <obstack.h>
typedef struct hash_table
{
unsigned long size;
unsigned long filled;
void *first;
void *table;
struct obstack mem_pool;
}
hash_table;
int init_hash (hash_table *htab, unsigned long init_size);
int delete_hash(hash_table *htab);
int insert_entry (hash_table *htab, const char *key, size_t keylen,
void *data);
int find_entry (hash_table *htab, const char *key, size_t keylen,
void **result);
int iterate_table (hash_table *htab, void **ptr, void **result);
#endif /* hash.h */
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/

View file

@ -1,77 +0,0 @@
%{
/* `strncmp' is used for comparison. */
#include <string.h>
/* This file defines `enum token'. */
#include "token.h"
%}
struct locale_keyword { char *name; enum token token_id; };
%%
END, TOK_END
IGNORE, TOK_IGNORE
LC_COLLATE, _NL_NUM_LC_COLLATE
LC_CTYPE, _NL_NUM_LC_CTYPE
LC_MESSAGES, _NL_NUM_LC_MESSAGES
LC_MONETARY, _NL_NUM_LC_MONETARY
LC_NUMERIC, _NL_NUM_LC_NUMERIC
LC_TIME, _NL_NUM_LC_TIME
UNDEFINED, TOK_UNDEFINED
abday, ABDAY_1
abmon, ABMON_1
alpha, TOK_ALPHA
alt_digits, ALT_DIGITS
am_pm, AM_STR
backward, TOK_BACKWARD
blank, TOK_BLANK
cntrl, TOK_CNTRL
collating_element, TOK_COLLATING_ELEMENT
collating_symbol, TOK_COLLATING_SYMBOL
comment_char, TOK_COMMENT_CHAR
copy, TOK_COPY
currency_symbol, CURRENCY_SYMBOL
d_fmt, D_FMT
d_t_fmt, D_T_FMT
day, DAY_1
decimal_point, DECIMAL_POINT
digit, TOK_DIGIT
era, ERA
era_d_fmt, ERA_D_FMT
era_year, ERA_YEAR
escape_char, TOK_ESCAPE_CHAR
forward, TOK_FORWARD
frac_digits, FRAC_DIGITS
from, TOK_FROM
graph, TOK_GRAPH
grouping, GROUPING
int_curr_symbol, INT_CURR_SYMBOL
int_frac_digits, INT_FRAC_DIGITS
lower, TOK_LOWER
mon, MON_1
mon_decimal_point, MON_DECIMAL_POINT
mon_grouping, MON_GROUPING
mon_thousands_sep, MON_THOUSANDS_SEP
n_cs_precedes, N_CS_PRECEDES
n_sep_by_space, N_SEP_BY_SPACE
n_sign_posn, N_SIGN_POSN
negative_sign, NEGATIVE_SIGN
noexpr, NOEXPR
nostr, NOSTR
order_end, TOK_ORDER_END
order_start, TOK_ORDER_START
p_cs_precedes, P_CS_PRECEDES
p_sep_by_space, P_SEP_BY_SPACE
p_sign_posn, P_SIGN_POSN
position, TOK_POSITION
positive_sign, POSITIVE_SIGN
print, TOK_PRINT
punct, TOK_PUNCT
space, TOK_SPACE
t_fmt, T_FMT
t_fmt_ampm, T_FMT_AMPM
thousands_sep, THOUSANDS_SEP
tolower, TOK_TOLOWER
toupper, TOK_TOUPPER
upper, TOK_UPPER
xdigit, TOK_XDIGIT
yesexpr, YESEXPR
yesstr, YESSTR

View file

@ -1,180 +0,0 @@
/* C code produced by gperf version 2.5 (GNU C++ version) */
/* Command-line: gperf -acCgopt -k1,2,5, keyword.gperf */
/* `strncmp' is used for comparison. */
#include <string.h>
/* This file defines `enum token'. */
#include "token.h"
struct locale_keyword { char *name; enum token token_id; };
#define TOTAL_KEYWORDS 68
#define MIN_WORD_LENGTH 3
#define MAX_WORD_LENGTH 17
#define MIN_HASH_VALUE 4
#define MAX_HASH_VALUE 140
/* maximum key range = 137, duplicates = 0 */
#ifdef __GNUC__
inline
#endif
static unsigned int
hash (register const char *str, register int len)
{
static const unsigned char asso_values[] =
{
141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
141, 141, 141, 141, 141, 141, 141, 141, 141, 141,
141, 141, 141, 141, 141, 141, 141, 0, 141, 65,
5, 0, 141, 30, 141, 141, 0, 141, 0, 95,
141, 141, 0, 141, 45, 10, 141, 141, 141, 141,
141, 141, 141, 141, 141, 5, 141, 10, 85, 0,
20, 0, 40, 35, 30, 10, 141, 0, 30, 15,
15, 0, 0, 141, 55, 0, 0, 80, 141, 15,
10, 0, 141, 141, 141, 141, 141, 141,
};
register int hval = len;
switch (hval)
{
default:
case 5:
hval += asso_values[str[4]];
case 4:
case 3:
case 2:
hval += asso_values[str[1]];
case 1:
hval += asso_values[str[0]];
}
return hval;
}
#ifdef __GNUC__
inline
#endif
const struct locale_keyword *
in_word_set (register const char *str, register int len)
{
static const struct locale_keyword wordlist[] =
{
{"",}, {"",}, {"",}, {"",},
{"copy", TOK_COPY},
{"space", TOK_SPACE},
{"yesstr", YESSTR},
{"toupper", TOK_TOUPPER},
{"position", TOK_POSITION},
{"",},
{"t_fmt", T_FMT},
{"escape_char", TOK_ESCAPE_CHAR},
{"comment_char", TOK_COMMENT_CHAR},
{"positive_sign", POSITIVE_SIGN},
{"",},
{"t_fmt_ampm", T_FMT_AMPM},
{"",},
{"yesexpr", YESEXPR},
{"mon", MON_1},
{"p_sep_by_space", P_SEP_BY_SPACE},
{"LC_NUMERIC", _NL_NUM_LC_NUMERIC},
{"noexpr", NOEXPR},
{"tolower", TOK_TOLOWER},
{"p_cs_precedes", P_CS_PRECEDES},
{"UNDEFINED", TOK_UNDEFINED},
{"",},
{"collating_symbol", TOK_COLLATING_SYMBOL},
{"collating_element", TOK_COLLATING_ELEMENT},
{"negative_sign", NEGATIVE_SIGN},
{"",},
{"d_fmt", D_FMT},
{"",},
{"mon_thousands_sep", MON_THOUSANDS_SEP},
{"day", DAY_1},
{"n_sep_by_space", N_SEP_BY_SPACE},
{"digit", TOK_DIGIT},
{"IGNORE", TOK_IGNORE},
{"LC_TIME", _NL_NUM_LC_TIME},
{"n_cs_precedes", N_CS_PRECEDES},
{"",},
{"int_curr_symbol", INT_CURR_SYMBOL},
{"",}, {"",},
{"thousands_sep", THOUSANDS_SEP},
{"",},
{"am_pm", AM_STR},
{"xdigit", TOK_XDIGIT},
{"",},
{"decimal_point", DECIMAL_POINT},
{"",},
{"cntrl", TOK_CNTRL},
{"p_sign_posn", P_SIGN_POSN},
{"mon_decimal_point", MON_DECIMAL_POINT},
{"LC_CTYPE", _NL_NUM_LC_CTYPE},
{"",},
{"alpha", TOK_ALPHA},
{"",},
{"forward", TOK_FORWARD},
{"era", ERA},
{"",},
{"print", TOK_PRINT},
{"",},
{"mon_grouping", MON_GROUPING},
{"era_year", ERA_YEAR},
{"",}, {"",},
{"n_sign_posn", N_SIGN_POSN},
{"",},
{"END", TOK_END},
{"",},
{"alt_digits", ALT_DIGITS},
{"",},
{"d_t_fmt", D_T_FMT},
{"",}, {"",},
{"nostr", NOSTR},
{"LC_MESSAGES", _NL_NUM_LC_MESSAGES},
{"",}, {"",}, {"",},
{"int_frac_digits", INT_FRAC_DIGITS},
{"",}, {"",}, {"",},
{"era_d_fmt", ERA_D_FMT},
{"punct", TOK_PUNCT},
{"",}, {"",}, {"",}, {"",},
{"lower", TOK_LOWER},
{"",}, {"",}, {"",}, {"",},
{"currency_symbol", CURRENCY_SYMBOL},
{"",}, {"",},
{"grouping", GROUPING},
{"from", TOK_FROM},
{"abday", ABDAY_1},
{"",}, {"",}, {"",}, {"",},
{"LC_COLLATE", _NL_NUM_LC_COLLATE},
{"LC_MONETARY", _NL_NUM_LC_MONETARY},
{"",}, {"",}, {"",}, {"",},
{"frac_digits", FRAC_DIGITS},
{"",}, {"",}, {"",},
{"abmon", ABMON_1},
{"",}, {"",},
{"backward", TOK_BACKWARD},
{"order_end", TOK_ORDER_END},
{"blank", TOK_BLANK},
{"order_start", TOK_ORDER_START},
{"",}, {"",}, {"",},
{"graph", TOK_GRAPH},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",},
{"upper", TOK_UPPER},
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
{
register int key = hash (str, len);
if (key <= MAX_HASH_VALUE && key >= 0)
{
register const char *s = wordlist[key].name;
if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
return &wordlist[key];
}
}
return 0;
}

View file

@ -1,5 +1,5 @@
/* nl_langinfo -- Access to locale-dependent parameters.
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -98,9 +98,25 @@ typedef enum
ERA_YEAR, /* Year in alternate era format. */
ERA_D_FMT, /* Date in alternate era format. */
ALT_DIGITS, /* Alternate symbols for digits. */
ERA_D_T_FMT, /* Date and time in alternate era format. */
ERA_T_FMT, /* Time in alternate era format. */
_NL_NUM_LC_TIME, /* Number of indices in LC_TIME category. */
/* LC_COLLATE category: text sorting.
This information is accessed by the strcoll and strxfrm functions.
These `nl_langinfo' names are used only internally. */
_NL_COLLATE_NRULES = _NL_ITEM (LC_COLLATE, 0),
_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_NUM_LC_COLLATE,
/* LC_CTYPE category: character classification.
This information is accessed by the functions in <ctype.h>.
These `nl_langinfo' names are used only internally. */
@ -109,6 +125,14 @@ typedef enum
_NL_CTYPE_TOLOWER_EB,
_NL_CTYPE_TOUPPER_EL,
_NL_CTYPE_TOLOWER_EL,
_NL_CTYPE_CLASS32,
_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,
_NL_NUM_LC_CTYPE,
/* LC_MONETARY category: formatting of monetary quantities.
@ -144,9 +168,6 @@ typedef enum
NOSTR, /* Output string for ``no''. */
_NL_NUM_LC_MESSAGES,
/* Stubs for unfinished categories. */
_NL_NUM_LC_COLLATE = _NL_ITEM (LC_COLLATE, 0),
/* This marks the highest value used. */
_NL_NUM
} nl_item;

View file

@ -1,5 +1,5 @@
/* Define current locale data for LC_COLLATE category.
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -14,9 +14,34 @@ 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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "localeinfo.h"
#include <endian.h>
_NL_CURRENT_DEFINE (LC_COLLATE);
const u32_t *__collate_table;
const u32_t *__collate_extra;
void
_nl_postload_collate (void)
{
#if BYTE_ORDER == BIG_ENDIAN
#define bo(x) x##_EB
#elif BYTE_ORDER == LITTLE_ENDIAN
#define bo(x) x##_EL
#else
#error bizarre byte order
#endif
#define paste(a,b) paste1(a,b)
#define paste1(a,b) a##b
#define current(x) \
((const unsigned int *) _NL_CURRENT (LC_COLLATE, paste(_NL_COLLATE_,x)))
__collate_table = current (bo (TABLE));
__collate_extra = current (bo (EXTRA));
}

View file

@ -1,5 +1,5 @@
/* Define current locale data for LC_CTYPE category.
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -47,7 +47,10 @@ _nl_postload_ctype (void)
((const unsigned int *) _NL_CURRENT (LC_CTYPE, paste(_NL_CTYPE_,x)) \
+ 128)
extern const unsigned int *__ctype_names;
__ctype_b = current (unsigned short, CLASS);
__ctype_toupper = current (, bo (TOUPPER));
__ctype_tolower = current (, bo (TOLOWER));
__ctype_names = current (unsigned, bo (NAMES));
}

View file

@ -1,5 +1,5 @@
/* Functions to read locale data files.
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -28,12 +28,31 @@ Cambridge, MA 02139, USA. */
#include "localeinfo.h"
const size_t _nl_category_num_items[] =
{
{
#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
[category] = _NL_ITEM_INDEX (_NL_NUM_##category),
[category] = _NL_ITEM_INDEX (_NL_NUM_##category),
#include "categories.def"
#undef DEFINE_CATEGORY
};
};
#define NO_PAREN(arg, rest...) arg, ##rest
#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
static const enum value_type _nl_value_type_##category[] = { NO_PAREN items };
#define DEFINE_ELEMENT(element, element_name, optstd, type, rest...) \
[_NL_ITEM_INDEX (element)] = type,
#include "categories.def"
#undef DEFINE_CATEGORY
static const enum value_type *_nl_value_types[] =
{
#define DEFINE_CATEGORY(category, category_name, items, a, b, c, d) \
[category] = _nl_value_type_##category,
#include "categories.def"
#undef DEFINE_CATEGORY
};
struct locale_data *
_nl_load_locale (int category, char **name)
@ -178,7 +197,7 @@ _nl_load_locale (int category, char **name)
}
newdata = malloc (sizeof *newdata +
W (filedata->nstrings) * sizeof (char *));
W (filedata->nstrings) * sizeof (union locale_data_value));
if (! newdata)
goto puntmap;
@ -194,7 +213,10 @@ _nl_load_locale (int category, char **name)
errno = EINVAL;
goto puntmap;
}
newdata->strings[i] = newdata->filedata + idx;
if (_nl_value_types[category][i] == word)
newdata->values[i].word = W (*((u32_t *) (newdata->filedata + idx)));
else
newdata->values[i].string = newdata->filedata + idx;
}
__close (fd);

View file

@ -1,821 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <alloca.h>
#include <fcntl.h>
#include <libintl.h>
#include <locale.h>
#include <localeinfo.h>
#include <langinfo.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/uio.h>
#include "localedef.h"
#include "token.h"
/* Arrays representing ctype tables. They must be initialized for the
right size to hold the full charmap. */
static u16 *ctype_b;
static i32 *names_b, *toupper_b, *tolower_b;
/* For accessing the element of the (possibly sparse) array we use this
macro. */
#define ELEM(arr, idx) \
(arr)[({ int h = idx % charmap_data.hash_size; \
int n = 0; \
while (n < charmap_data.hash_layers \
&& names_b[n * charmap_data.hash_size + h] != idx) \
++n; \
if (n >= charmap_data.hash_layers) \
error (6, 0, gettext ("internal error in %s, line %u"), \
__FUNCTION__, __LINE__); \
n * charmap_data.hash_size + h; })]
/* The bit used for representing a special class. */
#define BITPOS(class) ((class) - TOK_UPPER)
#define BIT(class) (1 << BITPOS (class))
/* Remember which class or conversion is already done. */
static unsigned short class_done = 0;
static unsigned short toupper_done = 0;
static unsigned short tolower_done = 0;
#define SYNTAX_ERROR \
error (0, 0, gettext ("%s:%Zd: syntax error in locale definition file"), \
locfile_data.filename, locfile_data.line_no);
/* Prototypes for local functions. */
static void allocate_arrays (void);
static void set_class_defaults (void);
static int valid_char (int ch);
/* Read CTYPE category. The initial token is given as a parameter. */
void
ctype_input (int token)
{
char *ptr;
int len;
/* If necessary allocate arrays. */
allocate_arrays ();
while (token != TOK_END)
{
switch (token)
{
case TOK_UPPER: case TOK_LOWER: case TOK_ALPHA: case TOK_DIGIT:
case TOK_XDIGIT: case TOK_SPACE: case TOK_PRINT: case TOK_GRAPH:
case TOK_BLANK: case TOK_CNTRL: case TOK_PUNCT:
{
/* TAKE CARE: the order of the tokens in "token.h" determines
the bit used to indicate the membership in the class. This
also has to correspond to the values used in <ctype.h>. */
int bit = BIT (token);
int was_ell = 0;
int last = -1;
if ((class_done & bit) != 0)
{
char tmp[len + 1];
memcpy (tmp, ptr, len);
tmp[len] = '\0';
error (0, 0, gettext ("%s:%Zd: duplicate definiton of item "
"`%s' in category `LC_CTYPE'"),
locfile_data.filename, locfile_data.line_no, tmp);
}
class_done |= bit;
do
{
token = xlocfile_lex (&ptr, &len);
if (token == TOK_ENDOFLINE)
{
SYNTAX_ERROR;
break;
}
if (token == TOK_ELLIPSIS)
{
if (was_ell != 0 || last < 0)
{
error (0, 0, gettext ("%s:%Zd: illegal use of `...'"),
locfile_data.filename, locfile_data.line_no);
break;
}
was_ell = 1;
continue;
}
if (token != TOK_CHAR)
{
if (token != TOK_ILL_CHAR)
SYNTAX_ERROR;
was_ell = 0;
last = -1;
continue;
}
if (len < 0 || !valid_char (len))
{
was_ell = 0;
last = -1;
continue;
}
/* We have found a valid character. Include it to
the class' bit set. */
if (was_ell == 0)
{
ELEM (ctype_b, len) |= bit;
last = len;
}
else
{
int i;
if (last > len)
{
error (0, 0, gettext ("%s:%Zd: lower bound of "
"ellipsis not smaller"),
locfile_data.filename, locfile_data.line_no);
was_ell = 0;
last = -1;
continue;
}
for (i = last + 1; i <= len; ++i)
ELEM (ctype_b, i) |= bit;
last = -1;
}
was_ell = 0;
}
while ((token = locfile_lex (&ptr, &len)) == TOK_CHAR
&& len == ';');
/* Rest of the line should be empty. */
ignore_to_eol (token, 0);
}
break;
case TOK_TOUPPER: case TOK_TOLOWER:
{
int from;
int to = -1;
int is_upper = token == TOK_TOUPPER;
if (((is_upper ? toupper_done : tolower_done) & BIT (token)) != 0)
error (0, 0, gettext ("%s:%Zd: duplicate definition of item "
"`%s' in category `LC_CTYPE'"),
locfile_data.filename, locfile_data.line_no,
is_upper ? "toupper" : "tolower");
(is_upper ? toupper_done : tolower_done) |= BIT (token);
do
{
int ignore;
token = xlocfile_lex (&ptr, &len);
if (token != TOK_CHAR || len != '(')
{
SYNTAX_ERROR;
break;
}
token = xlocfile_lex (&ptr, &len);
if (token != TOK_CHAR && token != TOK_ILL_CHAR)
{
SYNTAX_ERROR;
break;
}
from = len;
ignore = token == TOK_ILL_CHAR;
token = xlocfile_lex (&ptr, &len);
if (token != TOK_CHAR || len != ',')
{
SYNTAX_ERROR;
break;
}
token = xlocfile_lex (&ptr, &len);
if (token != TOK_CHAR && token != TOK_ILL_CHAR)
{
SYNTAX_ERROR;
break;
}
to = len;
ignore |= token == TOK_ILL_CHAR;
token = xlocfile_lex (&ptr, &len);
if (token != TOK_CHAR || len != ')')
{
SYNTAX_ERROR;
break;
}
if (!ignore && valid_char (from) && valid_char (to))
/* Have a valid pair. */
ELEM (is_upper ? toupper_b : tolower_b, from) = to;
}
while ((token = locfile_lex (&ptr, &len)) == TOK_CHAR
&& len == ';');
/* Rest of the line should be empty. */
ignore_to_eol (token, 1);
}
break;
default:
SYNTAX_ERROR;
ignore_to_eol (0, 0);
break;
}
/* Read next token. */
token = xlocfile_lex (&ptr, &len);
}
token = xlocfile_lex (&ptr, &len);
if (token != _NL_NUM_LC_CTYPE)
{
error (0, 0, gettext ("%s:%Zd: category `%s' does not end with "
"`END %s'"), locfile_data.filename,
locfile_data.line_no, "LC_CTYPE", "LC_CTYPE");
ignore_to_eol (0, 0);
}
else
ignore_to_eol (0, posix_conformance);
}
void
ctype_check(void)
{
/* Here are a lot of things to check. See POSIX.2, table 2-6. */
#define NCLASS 11
static const struct
{
const char *name;
const char allow[NCLASS];
}
valid_table[NCLASS] =
{
/* The order is important. See token.h for more information.
M = Always, D = Default, - = Permitted, X = Mutually exclusive */
[BITPOS (TOK_UPPER)] = { "upper", "--MX-XDDXXX" },
[BITPOS (TOK_LOWER)] = { "lower", "--MX-XDDXXX" },
[BITPOS (TOK_ALPHA)] = { "alpha", "---X-XDDXXX" },
[BITPOS (TOK_DIGIT)] = { "digit", "XXX--XDDXXX" },
[BITPOS (TOK_XDIGIT)] = { "xdigit", "-----XDDXXX" },
[BITPOS (TOK_SPACE)] = { "space", "XXXXX------" },
[BITPOS (TOK_PRINT)] = { "print", "---------X-" },
[BITPOS (TOK_GRAPH)] = { "graph", "---------X-" },
[BITPOS (TOK_BLANK)] = { "blank", "XXXXXM-----" },
[BITPOS (TOK_CNTRL)] = { "cntrl", "XXXXX-XX--X" },
[BITPOS (TOK_PUNCT)] = { "punct", "XXXXX-DD-X-" }
};
int ch, cls1, cls2, eq, space_char;
u16 tmp;
/* Set default value for classes not specified. */
set_class_defaults ();
/* Check according to table. */
for (ch = 0; ch < charmap_data.hash_size * charmap_data.hash_layers; ++ch)
{
if (ch != 0 && names_b[ch] == 0)
continue;
tmp = ELEM (ctype_b, names_b[ch]);
for (cls1 = 0; cls1 < NCLASS; ++cls1)
if ((tmp & (1 << cls1)) != 0)
for (cls2 = 0; cls2 < NCLASS; ++cls2)
if (cls2 != cls1 && valid_table[cls1].allow[cls2] != '-')
{
eq = (tmp & (1 << cls2)) != 0;
switch (valid_table[cls1].allow[cls2])
{
case 'M':
if (!eq)
error (0, 0, gettext ("character '\\%o' in class `%s' "
"must be in class `%s'"), ch,
valid_table[cls1].name, valid_table[cls2].name);
break;
case 'X':
if (eq)
error (0, 0, gettext ("character '\\%o' inc class `%s' "
"must not be in class `%s'"), ch,
valid_table[cls1].name, valid_table[cls2].name);
break;
case 'D':
ELEM (ctype_b, names_b[ch]) |= 1 << cls2;
break;
default:
error (5, 0, gettext ("internal error in %s, line %u"),
__FUNCTION__, __LINE__);
}
}
}
/* ... and now test <SP> as a special case. */
if (find_entry (&charmap_data.table, "SP", 2, (void **) &space_char) == 0)
error (0, 0, gettext ("character <SP> not defined in character map"));
else if ((tmp = BITPOS (TOK_SPACE),
(ELEM (ctype_b, space_char) & BIT (TOK_SPACE)) == 0)
|| (tmp = BITPOS (TOK_BLANK),
(ELEM (ctype_b, space_char) & BIT (TOK_BLANK)) == 0))
error (0, 0, gettext ("<SP> character not in class `%s'"),
valid_table[tmp].name);
else if ((tmp = BITPOS (TOK_PUNCT),
(ELEM (ctype_b, space_char) & BIT (TOK_PUNCT)) != 0)
|| (tmp = BITPOS (TOK_GRAPH),
(ELEM (ctype_b, space_char) & BIT (TOK_GRAPH)) != 0))
error (0, 0, gettext ("<SP> character must not be in class `%s'"),
valid_table[tmp].name);
else
ELEM (ctype_b, space_char) |= BIT (TOK_PRINT);
}
/* These macros can change little to big endian and vice versa. */
#define SWAP16(v) \
((u16) (((((unsigned short) (v)) & 0x00ff) << 8) \
| ((((unsigned short) (v)) & 0xff00) >> 8)))
#define SWAP32(v) \
((u32) (((((u32) (v)) & 0x000000ff) << 24) \
| ((((u32) (v)) & 0x0000ff00) << 8) \
| ((((u32) (v)) & 0x00ff0000) >> 8) \
| ((((u32) (v)) & 0xff000000) >> 24)))
int
ctype_output (void)
{
char *path, *t;
int ch;
/* File descriptor for output file. */
int fd;
/* Magic number. */
i32 magic = LIMAGIC (LC_CTYPE);
/* Number of table. */
int tables = 6;
/* Number ints in leading information table. */
#if 0
i32 n = 2 + 2 * tables;
#else
i32 n = 5;
#endif
/* Values describing the character set. */
char mb_cur_min = (char) charmap_data.mb_cur_min;
char mb_cur_max = (char) charmap_data.mb_cur_max;
/* Optimal size of hashing table. */
i32 hash_size = charmap_data.hash_size;
i32 hash_layers = charmap_data.hash_layers;
/* Number of elements in the tables. */
int size = hash_size * charmap_data.hash_layers;
/* Positions of the tables. */
i32 pos[14] =
{
/* No, no. We don't play towers of Hanoi. This is a more or less
readable table of the offsets of the different strings in the
produced file. It is seperated in three columns which represent
the number of values with 1, 2, and 4 bytes. */
#if 0
4 * (2 + n),
1 + 4 * (2 + n),
2 + 4 * (2 + n),
2 + 4 * (3 + n),
2 + 4 * (4 + n),
2 + 2 * (128 + size) + 4 * (4 + n),
2 + 2 * (128 + size) + 4 * ((4 + n) + (size + 128)),
2 + 2 * (128 + size) + 4 * ((4 + n) + 2 * (size + 128)),
2 + 2 * (128 + size) + 4 * ((4 + n) + 2 * (size + 128) + 1 * size),
2 + 2 * (128 + size) + 4 * ((5 + n) + 2 * (size + 128) + 1 * size),
2 + 2 * (128 + size) + 4 * ((6 + n) + 2 * (size + 128) + 1 * size),
2 + 2 * (2 * (128 + size)) + 4 * ((6 + n) + 2 * (size + 128) + 1 * size),
2 + 2 * (2 * (128 + size)) + 4 * ((6 + n) + 3 * (size + 128) + 1 * size),
2 + 2 * (2 * (128 + size)) + 4 * ((6 + n) + 4 * (size + 128) + 1 * size),
#else
4 * (2 + n),
2 * (128 + size) + 4 * (2 + n),
2 * (128 + size) + 4 * ((2 + n) + (size + 128)),
2 * (128 + size) + 4 * ((2 + n) + 2 * (size + 128)),
2 * (128 + size) + 4 * ((2 + n) + 3 * (size + 128)),
#endif
};
/* Parameter to writev. */
struct iovec iov[11] =
{
{ &magic, sizeof (i32) },
{ &n, sizeof (i32) },
#if 0
{ pos, sizeof (pos) },
{ &mb_cur_min, 1 },
{ &mb_cur_max, 1 },
{ &hash_size, sizeof (i32) },
{ &hash_layers, sizeof (i32) },
#else
{ pos, 5 * 4 },
#endif
{ ctype_b - 128, (size + 128) * sizeof (u16) },
{ toupper_b - 128, (size + 128) * sizeof (i32) },
{ tolower_b - 128, (size + 128) * sizeof (i32) },
{ names_b, size * sizeof (i32) }
};
int result = 0;
/* Now we can bring the representations into the right form. */
for (ch = -128; ch < -1; ++ch)
{
ctype_b[ch] = ctype_b[256 + ch];
toupper_b[ch] = toupper_b[256 + ch];
tolower_b[ch] = tolower_b[256 + ch];
}
/* Set value for EOF. */
ctype_b[-1] = 0;
toupper_b[-1] = -1;
tolower_b[-1] = -1;
for (ch = -128; ch < size; ++ch)
ctype_b[ch] = htons (ctype_b[ch]);
/* Construct the output filename from the argument given to
localedef on the command line. */
path = (char *) alloca (strlen (output_path) +
strlen (category[LC_CTYPE].name) + 1);
t = stpcpy (path, output_path);
strcpy (t, category[LC_CTYPE].name);
fd = creat (path, 0666);
if (fd == -1)
{
error (0, 0, gettext ("cannot open output file `%s': %m"), path);
result = 1;
}
else
{
int idx;
#if 0
if (writev (fd, iov, 10) == -1)
#else
if (writev (fd, iov, 6) == -1)
#endif
{
error (0, 0, gettext ("cannot write output file `%s': %m"), path);
result = 1;
goto close_and_return;
}
/* Now we have to write the three tables with different endianess. */
hash_size = SWAP32 (hash_size);
for (idx = -128; idx < size; ++idx)
{
ctype_b[idx] = SWAP16 (ctype_b[idx]);
toupper_b[idx] = SWAP32 (toupper_b[idx]);
tolower_b[idx] = SWAP32 (tolower_b[idx]);
if (idx >= 0)
names_b[idx] = SWAP32 (names_b[idx]);
}
#if 0
if (writev (fd, iov + 5, 6) == -1)
#else
if (writev (fd, iov + 3, 2) == -1)
#endif
{
error (0, 0, gettext ("cannot write output file `%s': %m"), path);
result = 1;
}
close_and_return:
close (fd);
}
return result;
}
/* If necessary allocate the memory for the arrays according to the
current character map. */
static void
allocate_arrays (void)
{
/* Init ctype data structures. */
if (ctype_b == NULL)
/* All data structures are not initialized yet. */
{
/* You wonder about this amount of memory? This is only because
some users do not manage to address the array with unsigned
values or data types with range >= 256. '\200' would result
in the array index -128. To help these poor people we
duplicate the entries for 128 upto 255 below the entry for \0. */
int ch, h, n;
char *ptr;
int size = charmap_data.hash_size * charmap_data.hash_layers;
ctype_b = xmalloc ((size - (-128)) * sizeof (u16));
bzero (ctype_b, (size - (-128)) * sizeof (u16));
ctype_b += 128;
names_b = xmalloc (size * sizeof (i32));
bzero (names_b, size * sizeof (i32));
toupper_b = xmalloc ((size - (-128)) * sizeof (i32));
bzero (toupper_b, (size - (-128)) * sizeof (i32));
toupper_b += 128;
tolower_b = xmalloc ((size - (-128)) * sizeof (i32));
bzero (tolower_b, (size - (-128)) * sizeof (i32));
tolower_b += 128;
ptr = NULL;
/* Mark the place of the NUL character as occupied. */
names_b[0] = 1;
while (iterate_table (&charmap_data.table, (void **) &ptr,
(void **) &ch))
{
/* We already handled the NUL character. */
if (ch == 0)
continue;
h = ch % charmap_data.hash_size;
n = 0;
while (names_b[h + n * charmap_data.hash_size] != 0)
++n;
names_b[h + n * charmap_data.hash_size] = ch;
toupper_b[h + n * charmap_data.hash_size] = ch;
tolower_b[h + n * charmap_data.hash_size] = ch;
}
/* Correct the value for NUL character. */
names_b[0] = 0;
}
}
static void
set_class_defaults (void)
{
/* These function defines the default values for the classes and conversions
according to POSIX.2 2.5.2.1.
It may seem that the order of these if-blocks is arbitrary but it is NOT.
Don't move them unless you know what you do! */
void set_default (int bit, int from, int to)
{
char tmp[4];
int ch;
/* Define string. */
strcpy (tmp, "<?>");
for (ch = from; ch <= to; ++ch)
{
int code;
tmp[1] = ch;
code = find_char (tmp + 1, 1);
if (code == -1)
error (5, 0, gettext ("character `%s' not defined while needed "
"as default value"), tmp);
ELEM (ctype_b, code) |= bit;
}
}
/* If necessary allocate arrays. */
allocate_arrays ();
/* Set default values if keyword was not present. */
if ((class_done & BIT (TOK_UPPER)) == 0)
/* "If this keyword [lower] is not specified, the lowercase letters
`A' through `Z', ..., shall automatically belong to this class,
with implementation defined character values." */
set_default (BIT (TOK_UPPER), 'A', 'Z');
if ((class_done & BIT (TOK_LOWER)) == 0)
/* "If this keyword [lower] is not specified, the lowercase letters
`a' through `z', ..., shall automatically belong to this class,
with implementation defined character values." */
set_default (BIT (TOK_LOWER), 'a', 'z');
if ((class_done & BIT (TOK_DIGIT)) == 0)
/* "If this keyword [digit] is not specified, the digits `0' through
`9', ..., shall automatically belong to this class, with
implementation-defined character values." */
set_default (BIT (TOK_DIGIT), '0', '9');
if ((class_done & BIT (TOK_SPACE)) == 0)
/* "If this keyword [space] is not specified, the characters <space>,
<form-feed>, <newline>, <carriage-return>, <tab>, and
<vertical-tab>, ..., shall automatically belong to this class,
with implementtation-defined character values." */
{
int code;
code = find_char ("space", 5);
if (code == -1)
error (5, 0, gettext ("character `%s' not defined while needed as "
"default value"), "<space>");
ELEM (ctype_b, code) |= BIT (TOK_SPACE);
code = find_char ("form-feed", 9);
if (code == -1)
error (5, 0, gettext ("character `%s' not defined while needed as "
"default value"), "<form-feed>");
ELEM (ctype_b, code) |= BIT (TOK_SPACE);
code = find_char ("newline", 7);
if (code == -1)
error (5, 0, gettext ("character `%s' not defined while needed as "
"default value"), "<newline>");
ELEM (ctype_b, code) |= BIT (TOK_SPACE);
code = find_char ("carriage-return", 15);
if (code == -1)
error (5, 0, gettext ("character `%s' not defined while needed as "
"default value"), "<carriage-return>");
ELEM (ctype_b, code) |= BIT (TOK_SPACE);
code = find_char ("tab", 3);
if (code == -1)
error (5, 0, gettext ("character `%s' not defined while needed as "
"default value"), "<tab>");
ELEM (ctype_b, code) |= BIT (TOK_SPACE);
code = find_char ("vertical-tab", 11);
if (code == -1)
error (5, 0, gettext ("character `%s' not defined while needed as "
"default value"), "<vertical-tab>");
ELEM (ctype_b, code) |= BIT (TOK_SPACE);
}
if ((class_done & BIT (TOK_XDIGIT)) == 0)
/* "If this keyword is not specified, the digits `0' to `9', the
uppercase letters `A' through `F', and the lowercase letters `a'
through `f', ..., shell automatically belong to this class, with
implementation defined character values." */
{
if ((class_done & BIT (TOK_XDIGIT)) == 0)
set_default (BIT (TOK_XDIGIT), '0', '9');
if ((class_done & BIT (TOK_XDIGIT)) == 0)
set_default (BIT (TOK_XDIGIT), 'A', 'F');
if ((class_done & BIT (TOK_XDIGIT)) == 0)
set_default (BIT (TOK_XDIGIT), 'a', 'f');
}
if ((class_done & BIT (TOK_BLANK)) == 0)
/* "If this keyword [blank] is unspecified, the characters <space> and
<tab> shall belong to this character class." */
{
int code;
code = find_char ("space", 5);
if (code == -1)
error (5, 0, gettext ("character `%s' not defined while needed as "
"default value"), "<space>");
ELEM (ctype_b, code) |= BIT (TOK_BLANK);
code = find_char ("tab", 3);
if (code == -1)
error (5, 0, gettext ("character `%s' not defined while needed as "
"default value"), "<tab>");
ELEM (ctype_b, code) |= BIT (TOK_BLANK);
}
if ((class_done & BIT (TOK_GRAPH)) == 0)
/* "If this keyword [graph] is not specified, characters specified for
the keywords `upper', `lower', `alpha', `digit', `xdigit' and `punct',
shall belong to this character class." */
{
int ch;
unsigned short int mask = BIT (TOK_UPPER) | BIT (TOK_LOWER) |
BIT (TOK_ALPHA) | BIT (TOK_DIGIT) | BIT (TOK_XDIGIT) | BIT (TOK_PUNCT);
for (ch = 0; ch < charmap_data.hash_size * charmap_data.hash_layers;
++ch)
{
if (ch != 0 && names_b[ch] == 0)
continue;
if ((ELEM (ctype_b, names_b[ch]) & mask) != 0)
ELEM (ctype_b, names_b[ch]) |= BIT (TOK_GRAPH);
}
}
if ((class_done & BIT (TOK_PRINT)) == 0)
/* "If this keyword [print] is not provided, characters specified for
the keywords `upper', `lower', `alpha', `digit', `xdigit', `punct',
and the <space> character shall belong to this character class." */
{
int ch;
int space = find_char ("space", 5);
unsigned short int mask = BIT (TOK_UPPER) | BIT (TOK_LOWER) |
BIT (TOK_ALPHA) | BIT (TOK_DIGIT) | BIT (TOK_XDIGIT) | BIT (TOK_PUNCT);
if (space == -1)
error (5, 0, gettext ("character `%s' not defined while needed as "
"default value"), "<space>");
for (ch = 0; ch < charmap_data.hash_size * charmap_data.hash_layers;
++ch)
{
if (ch != 0 && names_b[ch] == 0)
continue;
if ((ELEM (ctype_b, names_b[ch]) & mask) != 0)
ELEM (ctype_b, names_b[ch]) |= BIT (TOK_PRINT);
}
ELEM (ctype_b, space) |= BIT (TOK_PRINT);
}
if (toupper_done == 0)
/* "If this keyword [toupper] is not spcified, the lowercase letters
`a' through `z', and their corresponding uppercase letters `A' to
`Z', ..., shall automatically be included, with implementation-
defined character values." */
{
char tmp[4];
int ch;
strcpy (tmp, "<?>");
for (ch = 'a'; ch <= 'z'; ++ch)
{
int code_to, code_from;
tmp[1] = ch;
code_from = find_char (tmp + 1, 1);
if (code_from == -1)
error (5, 0, gettext ("character `%s' not defined while needed "
"as default value"), tmp);
/* This conversion is implementation defined. */
tmp[1] = ch + ('A' - 'a');
code_to = find_char (tmp + 1, 1);
if (code_to == -1)
error (5, 0, gettext ("character `%s' not defined while needed "
"as default value"), tmp);
ELEM (toupper_b, code_from) = code_to;
}
}
if (tolower_done == 0)
/* "If this keyword [tolower] is not specified, the mapping shall be
the reverse mapping of the one specified to `toupper'." */
{
int ch;
for (ch = 0; ch < charmap_data.hash_size * charmap_data.hash_layers;
++ch)
{
if (ch != 0 && names_b[ch] == 0)
continue;
if (toupper_b[ch] != names_b[ch])
ELEM (tolower_b, toupper_b[ch]) = names_b[ch];
}
}
}
/* Test whether the given character is valid for the current charmap. */
static int
valid_char (int ch)
{
/* FIXME: this assumes 32-bit integers. */
int ok = ch >= 0
&& (charmap_data.mb_cur_max < 4
? ch < 1 << (8 * charmap_data.mb_cur_max) : 1);
return ok;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/

View file

@ -1,259 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <getopt.h>
#include <libintl.h>
#include <locale.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include "error.h"
#include "localedef.h"
/* The charmap file used. If none given DEFAULT_CHARMAP is used. */
static char *charmap_file;
/* If set output is always written, even when warning are given. */
static int force_output;
/* The input file name. */
static char *input_file;
/* Path leading to the destination directory for the produced files. */
char *output_path;
/* If this is defined be POSIX conform. */
int posix_conformance;
/* If not zero give a lot more messages. */
int verbose;
/* Long options. */
static const struct option long_options[] =
{
{ "charmap", required_argument, NULL, 'f' },
{ "debug", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{ "force", no_argument, NULL, 'c' },
{ "inputfile", required_argument, NULL, 'i' },
{ "posix", no_argument, &posix_conformance, 1 },
{ "verbose", no_argument, &verbose, 1},
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
/* Prototypes for local functions. */
static void usage (int status) __attribute__ ((noreturn));
static int construct_output_path (const char *path);
int
main(int argc, char *argv[])
{
int optchar;
int cannot_write;
int do_help = 0;
int do_version = 0;
/* Set initial values for global varaibles. */
charmap_file = NULL;
force_output = 0;
input_file = 0;
posix_conformance = getenv ("POSIXLY_CORRECT") != NULL;
verbose = 0;
/* Set locale. Do not set LC_ALL because the other categories must
not be affected (acccording to POSIX.2). */
setlocale (LC_MESSAGES, "");
setlocale (LC_CTYPE, "");
/* Initialize the message catalog. */
textdomain (PACKAGE);
while ((optchar = getopt_long (argc, argv, "cdf:hi:vV", long_options, NULL))
!= EOF)
switch (optchar)
{
case '\0':
break;
case 'c':
force_output = 1;
break;
case 'f':
if (charmap_file != NULL)
error (0, 0, gettext ("\"%s %s\" overwrites old option \"%s\""),
"-f", optarg, charmap_file);
charmap_file = optarg;
break;
case 'h':
do_help = 1;
break;
case 'i':
if (input_file != NULL)
error (0, 0, gettext ("\"%s %s\" overwrites old option \"%s\""),
"-i", optarg, input_file);
input_file = optarg;
break;
case 'v':
verbose = 1;
break;
case 'V':
do_version = 1;
break;
default:
usage (4);
break;
}
/* POSIX.2 requires to be verbose about missing characters in the
character map. */
verbose |= posix_conformance;
/* Version information is requested. */
if (do_version)
{
fprintf (stderr, "GNU %s %s\n", PACKAGE, VERSION);
exit (EXIT_SUCCESS);
}
/* Help is requested. */
if (do_help)
usage (0);
if (argc - optind != 1)
/* We need exactly one non-option parameter. */
usage (4);
/* The parameter describes the output path of the constructed files.
If the files cannot be written return a non-zero value. */
cannot_write = construct_output_path (argv[optind]);
/* Now that the parameters are processed we have to reset the local
ctype locale. (POSIX.2 4.35.5.2) */
setlocale (LC_CTYPE, "POSIX");
/* Look whether the system really allows locale definitions. */
if (sysconf (_SC_2_LOCALEDEF) < 0)
error (3, 0,
gettext ("warning: system does not define `_POSIX2_LOCALEDEF'"));
/* Process charmap file. */
charmap_read (charmap_file);
/* Now read the locale file. */
locfile_read (input_file);
/* Check all categories for consistency. */
categories_check ();
/* We are now able to write the data files. If warning were given we
do it only if it is explicitly requested (--force). */
if (error_message_count == 0 || force_output != 0)
if (cannot_write != 0)
error (0, 0, gettext ("cannot write output file `%s': %s"),
output_path, strerror (cannot_write));
else
categories_write ();
else
error (0, 0,
gettext ("no output file produced because warning were issued"));
exit (EXIT_SUCCESS);
}
/* Display usage information and exit. */
static void
usage(int status)
{
if (status != EXIT_SUCCESS)
fprintf (stderr, gettext ("Try `%s --help' for more information.\n"),
program_invocation_name);
else
printf(gettext ("\
Usage: %s [OPTION]... name\n\
Mandatory arguments to long options are mandatory for short options too.\n\
-c, --force create output even if warning messages have been issued\n\
-h, --help display this help and exit\n\
-V, --version output version information and exit\n\
\n\
-i, --inputfile=FILE source definitions are found in FILE\n\
-f, --charmap=FILE symbolic character names defined in FILE\n\
\n\
-v, --verbose print more messages\n\
--posix be strictly POSIX conform\n\
\n\
System's directory for character maps: %s\n\
locale files : %s\n\
"), program_invocation_name, CHARMAP_PATH, LOCALE_PATH);
exit (status);
}
/* The parameter to localedef describes the output path. If it does
contain a '/' character it is a relativ path. Otherwise it names the
locale this definition is for. */
static int
construct_output_path (const char *path)
{
int result = 0;
if (strchr (path, '/') == NULL)
{
/* This is a system path. */
int path_max_len = pathconf (LOCALE_PATH, _PC_PATH_MAX) + 1;
output_path = (char *) xmalloc (path_max_len);
snprintf (output_path, path_max_len, "%s/%s", LOCALE_PATH, path);
}
else
{
char *t;
/* This is a user path. */
output_path = malloc (strlen (path) + 2);
t = stpcpy (output_path, path);
*t = '\0';
}
if (euidaccess (output_path, W_OK) == -1)
/* Perhaps the directory does not exist now. Try to create it. */
if (errno == ENOENT)
{
if (mkdir (output_path, 0777) == -1)
result = errno;
}
else
result = errno;
if (result == 0)
strcat (output_path, "/");
return result;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/

View file

@ -1,196 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#ifndef _LOCALEDEF_H
#define _LOCALEDEF_H 1
#define __need_wchar_t
#include <stddef.h>
#include "config.h"
#include "hash.h"
/* Needed always. */
#define MAX(a, b) ({typeof (a) _a = (a); typeof (b) _b = (b); \
_a > _b ? _a : _b; })
#define MIN(a, b) ({typeof (a) _a = (a); typeof (b) _b = (b); \
_a < _b ? _a : _b; })
/* Determine number of elements in ARR. */
#define NELEMS(arr) ((sizeof (arr)) / (sizeof (arr[0])))
/* I simply love these GCC features ... :) */
#define NO_PAREN(arg, rest...) arg, ##rest
/* The character set used in the locale is defined in a character map file.
The information of the file is stored in the following struct. */
struct charmap
{
char *filename;
char *codeset_name;
int mb_cur_min;
int mb_cur_max;
char escape_char;
char comment_char;
hash_table table;
int hash_size;
int hash_layers;
};
/* Data structure for representing charmap database. */
extern struct charmap charmap_data;
/* We can map the types of the entries into four categories. */
enum value_type { none, string, stringarray, byte, bytearray, integer };
/* Definition of the data structure which represents a category and its
items. */
struct category
{
int cat_id;
const char *name;
size_t number;
struct cat_item
{
int item_id;
const char *name;
enum { std, opt } status;
enum value_type value_type;
int min;
int max;
} *item_desc;
char **item_value;
void (*infct)(int);
void (*checkfct)(void);
int (*outfct)(void);
int filled;
char *copy_locale;
};
/* This a the structure which contains all information about all
categories. */
extern struct category category[];
/* The function used to load the contents of a charmap file into the
the global variable `charmap_data'. */
void charmap_read (const char *filename);
/* Find a character constant given by its name in the hash table. */
static inline wchar_t find_char (const char *name, size_t len)
{
wchar_t retval;
if (find_entry (&charmap_data.table, name, len, (void **) &retval) != 0)
return retval;
else
return -1;
}
/* Path to the directory the output files are written in. */
extern char *output_path;
/* If this is defined be POSIX conform. */
extern int posix_conformance;
/* If not zero give a lot more messages. */
extern int verbose;
/* This structure contains all informations about the status of of
reading the locale definition file. */
struct locfile_data
{
const char *filename;
char escape_char;
char comment_char;
size_t bufsize;
char *buf;
char *strbuf;
size_t buf_ptr;
int continue_line;
size_t returned_tokens;
size_t line_no;
};
/* The status variable. */
extern struct locfile_data locfile_data;
/* Open the locale definition file. */
void locfile_open (const char *fname);
/* Return the next token from the locale definition file. */
int locfile_lex (char **token, int *token_len);
/* Dito, but check for EOF. */
int xlocfile_lex (char **token, int *token_len);
/* Ignore the rest of the line. First TOKEN given if != 0. Warn about
anything other than end of line if WARN_FLAG nonzero. */
void ignore_to_eol (int token, int warn_flag);
/* Code a character with UTF-8 if the character map has multi-byte
characters. */
int char_to_utf (char *buf, int char_val);
/* Read the locale defintion file FNAME and fill the appropriate
data structures. */
void locfile_read (const char *fname);
/* Check categories for consistency. */
void categories_check (void);
/* Write out the binary representation of the category data. */
void categories_write (void);
/* Treat reading the LC_COLLATE definition. */
void collate_input (int token);
/* Treat reading the LC_CTYPE definition. */
void ctype_input (int token);
void ctype_check (void);
int ctype_output (void);
/* Treat reading the LC_MONETARY definition. */
void monetary_check (void);
/* Treat reading the LC_MESSAGES definition. */
void messages_check (void);
/* Treat reading the LC_NUMERIC definition. */
void numeric_check (void);
/* Print an error message, possibly with NLS. */
void error (int status, int errnum, const char *format, ...)
__attribute__ ((format (printf, 3, 4)));
/* Library functions. */
void *xmalloc (size_t n);
void *xcalloc (size_t n, size_t s);
void *xrealloc (void *p, size_t n);
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/
#endif /* _LOCALEDEF_H */

View file

@ -1,5 +1,5 @@
/* localeinfo.h -- declarations for internal libc locale interfaces
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -25,17 +25,51 @@ Cambridge, MA 02139, USA. */
#include <sys/types.h>
/* Magic number at the beginning of a locale data file for CATEGORY. */
#define LIMAGIC(category) (0x051472CA ^ (category))
#define LIMAGIC(category) (0x960316de ^ (category))
/* Two special weight constants for the collation data. */
#define FORWARD_CHAR 0xfffffffd
#define ELLIPSIS_CHAR 0xfffffffe
#define IGNORE_CHAR 0xffffffff
/* Structure describing locale data in core for a category. */
struct locale_data
{
const char *filedata; /* Region mapping the file data. */
off_t filesize; /* Size of the file (and the region). */
{
const char *filedata; /* Region mapping the file data. */
off_t filesize; /* Size of the file (and the region). */
unsigned int nstrings; /* Number of strings below. */
const char *strings[0]; /* Items, usually pointers into `filedata'. */
};
unsigned int nstrings; /* Number of strings below. */
union locale_data_value
{
const char *string;
unsigned int word;
}
values[0]; /* Items, usually pointers into `filedata'. */
};
/* We know three kinds of collation sorting rules. */
enum coll_sort_rule
{
illegal_0__,
sort_forward,
sort_backward,
illegal_3__,
sort_position,
sort_forward_position,
sort_backward_position,
sort_mask
};
/* We can map the types of the entries into four categories. */
enum value_type
{
none,
string,
stringarray,
byte,
bytearray,
word
};
/* For each category declare the variable for the current locale data. */
@ -49,7 +83,11 @@ extern const struct locale_data * *const _nl_current[LC_ALL];
/* Extract the current CATEGORY locale's string for ITEM. */
#define _NL_CURRENT(category, item) \
(_nl_current_##category->strings[_NL_ITEM_INDEX (item)])
(_nl_current_##category->values[_NL_ITEM_INDEX (item)].string)
/* Extract the current CATEGORY locale's word for ITEM. */
#define _NL_CURRENT_WORD(category, item) \
(_nl_current_##category->values[_NL_ITEM_INDEX (item)].word)
/* This is used in lc-CATEGORY.c to define _nl_current_CATEGORY. */
#define _NL_CURRENT_DEFINE(category) \
@ -65,4 +103,11 @@ extern struct locale_data *_nl_load_locale (int category, char **name);
extern void _nl_free_locale (struct locale_data *);
/* XXX For now. */
typedef unsigned int u32_t;
/* Global variables for LC_COLLATE category data. */
extern const u32_t *__collate_table;
extern const u32_t *__collate_extra;
#endif /* localeinfo.h */

View file

@ -1,254 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <obstack.h>
#include <stdlib.h>
#include <string.h>
#include <values.h>
#include "hash.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
void *xmalloc (size_t n);
typedef struct hash_entry
{
int used;
char *key;
void *data;
struct hash_entry *next;
}
hash_entry;
/* Prototypes for local functions. */
static size_t lookup (hash_table *htab, const char *key, size_t keylen,
unsigned long hval);
static unsigned long compute_hashval(const char *key, size_t keylen);
static unsigned long next_prime(unsigned long seed);
static int is_prime(unsigned long candidate);
int
init_hash(hash_table *htab, unsigned long init_size)
{
/* We need the size to be a prime. */
init_size = next_prime (init_size);
/* Initialize the data structure. */
htab->size = init_size;
htab->filled = 0;
htab->first = NULL;
htab->table = calloc (init_size + 1, sizeof (hash_entry));
obstack_init (&htab->mem_pool);
return htab->table == NULL;
}
int
delete_hash(hash_table *htab)
{
free (htab->table);
obstack_free (&htab->mem_pool, NULL);
return 0;
}
int
insert_entry (hash_table *htab, const char *key, size_t keylen, void *data)
{
unsigned long hval = compute_hashval (key, keylen);
hash_entry *table = (hash_entry *) htab->table;
size_t idx = lookup (htab, key, keylen, hval);
if (table[idx].used)
/* We don't want to overwrite the old value. */
return 1;
else
{
hash_entry **p;
/* An empty bucket has been found. */
table[idx].used = hval;
table[idx].key = obstack_copy0 (&htab->mem_pool, key, keylen);
table[idx].data = data;
/* List the new value in the ordered list. */
for (p = (hash_entry **) &htab->first; *p != NULL && (*p)->data < data;
p = &(*p)->next);
if (*p == NULL || (*p)->data > data)
/* Insert new value in the list. */
{
table[idx].next = *p;
*p = &table[idx];
}
++htab->filled;
if (100 * htab->filled > 90 * htab->size)
{
/* Resize the table. */
unsigned long old_size = htab->size;
htab->size = next_prime (htab->size * 2);
htab->filled = 0;
htab->first = NULL;
htab->table = calloc (htab->size, sizeof (hash_entry));
for (idx = 1; idx <= old_size; ++idx)
if (table[idx].used)
insert_entry (htab, table[idx].key, strlen(table[idx].key),
table[idx].data);
free (table);
}
return 0;
}
/* NOTREACHED */
}
int
find_entry (hash_table *htab, const char *key, size_t keylen, void **result)
{
hash_entry *table = (hash_entry *) htab->table;
size_t idx = lookup (htab, key, keylen, compute_hashval (key, keylen));
int retval;
retval = table[idx].used;
*result = retval ? table[idx].data : NULL;
return retval;
}
int
iterate_table (hash_table *htab, void **ptr, void **result)
{
if (*ptr == NULL)
*ptr = (void *) htab->first;
else
{
*ptr = (void *) (((hash_entry *) *ptr)->next);
if (*ptr == NULL)
return 0;
}
*result = ((hash_entry *) *ptr)->data;
return 1;
}
static size_t
lookup (hash_table *htab, const char *key, size_t keylen, unsigned long hval)
{
unsigned long hash;
size_t idx;
hash_entry *table = (hash_entry *) htab->table;
/* First hash function: simply take the modul but prevent zero. */
hash = 1 + hval % htab->size;
idx = hash;
if (table[idx].used)
{
if (table[idx].used == hval && table[idx].key[keylen] == '\0'
&& strncmp (key, table[idx].key, keylen) == 0)
return idx;
/* Second hash function as suggested in [Knuth]. */
hash = 1 + hash % (htab->size - 2);
do
{
if (idx <= hash)
idx = htab->size + idx - hash;
else
idx -= hash;
/* If entry is found use it. */
if (table[idx].used == hval && table[idx].key[keylen] == '\0'
&& strncmp (key, table[idx].key, keylen) == 0)
return idx;
}
while (table[idx].used);
}
return idx;
}
static unsigned long
compute_hashval(const char *key, size_t keylen)
{
size_t cnt;
unsigned long hval, g;
/* Compute the hash value for the given string. */
cnt = 0;
hval = keylen;
while (cnt < keylen)
{
hval <<= 4;
hval += key[cnt++];
g = hval & (0xfL << (LONGBITS - 4));
if (g != 0)
{
hval ^= g >> (LONGBITS - 8);
hval ^= g;
}
}
return hval;
}
static unsigned long
next_prime(unsigned long seed)
{
/* Make it definitely odd. */
seed |= 1;
while (!is_prime (seed))
seed += 2;
return seed;
}
static int
is_prime(unsigned long candidate)
{
/* No even number and none less than 10 will be passwd here. */
unsigned long div = 3;
unsigned long sq = div * div;
while (sq < candidate && candidate % div != 0)
{
++div;
sq += 4 * div;
++div;
}
return candidate % div != 0;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/

View file

@ -1,533 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <ctype.h>
#include <langinfo.h>
#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "localedef.h"
#include "token.h"
/* Include the hashing table for the keywords. */
const struct locale_keyword* in_word_set (register const char *str,
register int len);
#include "keyword.h"
/* Contains the status of reading the locale definition file. */
struct locfile_data locfile_data;
/* This is a flag used while collation input. This is the only place
where element names beside the ones defined in the character map are
allowed. There we must not give error messages. */
int reject_new_char = 1;
/* Prototypes for local functions. */
static int get_char (void);
#define LD locfile_data
/* Opens the locale definition file and initializes the status data structure
for following calls of `locfile_lex'. */
void
locfile_open (const char *fname)
{
if (fname == NULL)
/* We read from stdin. */
LD.filename = "<stdin>";
else
{
if (freopen (fname, "r", stdin) == NULL)
error (4, 0, gettext ("input file `%s' not found"), fname);
LD.filename = fname;
}
/* Set default values. */
LD.escape_char = '\\';
LD.comment_char = '#';
LD.bufsize = sysconf (_SC_LINE_MAX);
LD.buf = (char *) xmalloc (LD.bufsize);
LD.strbuf = (char *) xmalloc (LD.bufsize);
LD.buf_ptr = LD.returned_tokens = LD.line_no = 0;
/* Now sign that we want immediately read a line. */
LD.continue_line = 1;
LD.buf[LD.buf_ptr] = '\0';
}
int
xlocfile_lex (char **token, int *token_len)
{
int retval = locfile_lex (token, token_len);
if (retval == 0)
/* I.e. end of file. */
error (4, 0, gettext ("%s: unexpected end of file in locale defintion "
"file"), locfile_data.filename);
return retval;
}
int
locfile_lex (char **token, int *token_len)
{
int start_again;
int retval = 0;
do
{
int start_ptr;
start_again = 0;
/* Read the next line. Skip over empty lines and comments. */
if ((LD.buf[LD.buf_ptr] == '\0' && LD.continue_line != 0)
|| LD.buf_ptr >= LD.bufsize
|| (posix_conformance == 0 && LD.buf[LD.buf_ptr] == LD.comment_char))
do
{
size_t linelen;
LD.buf_ptr = 0;
if (fgets (LD.buf, LD.bufsize, stdin) == NULL)
{
/* This makes subsequent calls also return EOF. */
LD.buf[0] = '\0';
return 0;
}
/* Increment line number counter. */
++LD.line_no;
/* We now have to look whether this line is continued and
whether it at all fits into our buffer. */
linelen = strlen (LD.buf);
if (linelen == LD.bufsize - 1)
/* The did not fit into the buffer. */
error (2, 0, gettext ("%s:%Zd: line too long; use "
"`getconf LINE_MAX' to get the maximum "
"line length"), LD.filename, LD.line_no);
/* Remove '\n' at end of line. */
if (LD.buf[linelen - 1] == '\n')
LD.buf[--linelen] = '\0';
if (linelen > 0 && LD.buf[linelen - 1] == LD.escape_char)
{
LD.buf[--linelen] = '\0';
LD.continue_line = 1;
}
else
LD.continue_line = 0;
while (isspace (LD.buf[LD.buf_ptr]))
++LD.buf_ptr;
/* We are not so restrictive and allow white spaces before
a comment. */
if (posix_conformance == 0
&& LD.buf[LD.buf_ptr] == LD.comment_char
&& LD.buf_ptr != 0)
error (0, 0, gettext ("%s:%Zd: comment does not start in "
"column 1"), LD.filename, LD.line_no);
}
while (LD.buf[LD.buf_ptr] == '\0'
|| LD.buf[LD.buf_ptr] == LD.comment_char);
/* Get information for return values. */
*token = LD.buf + LD.buf_ptr;
start_ptr = LD.buf_ptr;
/* If no further character is in the line this is the end of a logical
line. This information is needed in the parser. */
if (LD.buf[LD.buf_ptr] == '\0')
{
LD.buf_ptr = LD.bufsize;
retval = TOK_ENDOFLINE;
}
else if (isalpha (LD.buf[LD.buf_ptr]))
/* The token is an identifier. The POSIX standard does not say
what characters might be contained but offical POSIX locale
definition files contain beside alnum characters '_', '-' and
'+'. */
{
const struct locale_keyword *kw;
do
++LD.buf_ptr;
while (isalnum (LD.buf[LD.buf_ptr]) || LD.buf[LD.buf_ptr] == '_'
|| LD.buf[LD.buf_ptr] == '-' || LD.buf[LD.buf_ptr] == '+');
/* Look in table of keywords. */
kw = in_word_set (*token, LD.buf_ptr - start_ptr);
if (kw == NULL)
retval = TOK_IDENT;
else
{
if (kw->token_id == TOK_ESCAPE_CHAR
|| kw->token_id == TOK_COMMENT_CHAR)
/* `escape_char' and `comment_char' are keywords for the
lexer. Do not give them to the parser. */
{
start_again = 1;
if (!isspace (LD.buf[LD.buf_ptr])
|| (posix_conformance && LD.returned_tokens > 0))
error (0, 0, gettext ("%s:%Zd: syntax error in locale "
"definition file"),
LD.filename, LD.line_no);
do
++LD.buf_ptr;
while (isspace (LD.buf[LD.buf_ptr]));
kw->token_id == TOK_ESCAPE_CHAR
? LD.escape_char
: LD.comment_char = LD.buf[LD.buf_ptr++];
ignore_to_eol (0, posix_conformance);
}
else
/* It is one of the normal keywords. */
retval = kw->token_id;
}
*token_len = LD.buf_ptr - start_ptr;
}
else if (LD.buf[LD.buf_ptr] == '"')
/* Read a string. All symbolic character descriptions are expanded.
This has to be done in a local buffer because a simple symbolic
character like <A> may expand to upto 6 bytes. */
{
char *last = LD.strbuf;
++LD.buf_ptr;
while (LD.buf[LD.buf_ptr] != '"')
{
int pre = LD.buf_ptr;
int char_val = get_char (); /* token, token_len); */
if (char_val == 0)
{
error (4, 0, gettext ("%s:%Zd: unterminated string at end "
"of line"), LD.filename, LD.line_no);
/* NOTREACHED */
}
if (char_val > 0)
/* Unknown characters are simply not stored. */
last += char_to_utf (last, char_val);
else
{
char tmp[LD.buf_ptr - pre + 1];
memcpy (tmp, &LD.buf[pre], LD.buf_ptr - pre);
tmp[LD.buf_ptr - pre] = '\0';
error (0, 0, gettext ("%s:%Zd: character `%s' not defined"),
LD.filename, LD.line_no, tmp);
}
}
if (LD.buf[LD.buf_ptr] != '\0')
++LD.buf_ptr;
*last = '\0';
*token = LD.strbuf;
*token_len = last - LD.strbuf;
retval = TOK_STRING;
}
else if (LD.buf[LD.buf_ptr] == '.' && LD.buf[LD.buf_ptr + 1] == '.'
&& LD.buf[LD.buf_ptr + 2] == '.')
{
LD.buf_ptr += 3;
retval = TOK_ELLIPSIS;
}
else if (LD.buf[LD.buf_ptr] == LD.escape_char)
{
char *endp;
++LD.buf_ptr;
switch (LD.buf[LD.buf_ptr])
{
case 'x':
if (isdigit (LD.buf[++LD.buf_ptr]))
{
retval = strtol (&LD.buf[LD.buf_ptr], &endp, 16);
if (endp - (LD.buf + LD.buf_ptr) < 2 || retval > 255)
retval = 'x';
else
LD.buf_ptr = endp - LD.buf;
}
else
retval = 'x';
break;
case 'd':
if (isdigit (LD.buf[++LD.buf_ptr]))
{
retval = strtol (&LD.buf[LD.buf_ptr], &endp, 10);
if (endp - (LD.buf + LD.buf_ptr) < 2 || retval > 255)
retval = 'd';
else
LD.buf_ptr = endp - LD.buf;
}
else
retval = 'd';
break;
case '0'...'9':
retval = strtol (&LD.buf[LD.buf_ptr], &endp, 8);
if (endp - (LD.buf + LD.buf_ptr) < 2 || retval > 255)
retval = LD.buf[LD.buf_ptr++];
else
LD.buf_ptr = endp - LD.buf;
break;
case 'a':
retval = '\a';
++LD.buf_ptr;
break;
case 'b':
retval = '\b';
++LD.buf_ptr;
break;
case 'f':
retval = '\f';
++LD.buf_ptr;
break;
case 'n':
retval = '\n';
++LD.buf_ptr;
break;
case 'r':
retval = '\r';
++LD.buf_ptr;
break;
case 't':
retval = '\t';
++LD.buf_ptr;
break;
case 'v':
retval = '\v';
++LD.buf_ptr;
break;
default:
retval = LD.buf[LD.buf_ptr++];
break;
}
}
else if (isdigit (LD.buf[LD.buf_ptr]))
{
char *endp;
*token_len = strtol (&LD.buf[LD.buf_ptr], &endp, 10);
LD.buf_ptr = endp - LD.buf;
retval = TOK_NUMBER;
}
else if (LD.buf[LD.buf_ptr] == '-' && LD.buf[LD.buf_ptr + 1] == '1')
{
LD.buf_ptr += 2;
retval = TOK_MINUS1;
}
else
{
int ch = get_char (); /* token, token_len); */
if (ch != -1)
{
*token_len = ch;
retval = TOK_CHAR;
}
else
retval = TOK_ILL_CHAR;
}
/* Ignore white space. */
while (isspace (LD.buf[LD.buf_ptr]))
++LD.buf_ptr;
}
while (start_again != 0);
++LD.returned_tokens;
return retval;
}
/* Code a character with UTF-8 if the character map has multi-byte
characters. */
int
char_to_utf (char *buf, int char_val)
{
if (charmap_data.mb_cur_max == 1)
{
*buf++ = char_val;
return 1;
}
else
{
/* The number of bits coded in each character. */
#define CBPC 6
static struct coding_tab
{
int mask;
int val;
}
tab[] =
{
{ 0x7f, 0x00 },
{ 0x7ff, 0xc0 },
{ 0xffff, 0xe0 },
{ 0x1fffff, 0xf0 },
{ 0x3ffffff, 0xf8 },
{ 0x7fffffff, 0xfc },
{ 0, }
};
struct coding_tab *t;
int c;
int cnt = 1;
for (t = tab; char_val > t->mask; ++t, ++cnt)
;
c = cnt;
buf += cnt;
while (c > 1)
{
*--buf = 0x80 | (char_val & ((1 << CBPC) - 1));
char_val >>= CBPC;
--c;
}
*--buf = t->val | char_val;
return cnt;
}
}
/* Ignore rest of line upto ENDOFLINE token, starting with given token.
If WARN_FLAG is set warn about any token but ENDOFLINE. */
void
ignore_to_eol (int token, int warn_flag)
{
if (token == TOK_ENDOFLINE)
return;
if (LD.buf[LD.buf_ptr] != '\0' && warn_flag)
error (0, 0, gettext ("%s:%Zd: trailing garbage at end of line"),
locfile_data.filename, locfile_data.line_no);
while (LD.continue_line)
{
LD.continue_line = 0;
/* Increment line number counter. */
++LD.line_no;
if (fgets (LD.buf, LD.bufsize, stdin) != NULL)
{
/* We now have to look whether this line is continued and
whether it at all fits into our buffer. */
int linelen = strlen (LD.buf);
if (linelen == LD.bufsize - 1)
/* The did not fit into the buffer. */
error (2, 0, gettext ("%s:%Zd: line too long; use `getconf "
"LINE_MAX' to get the current maximum "
"line length"), LD.filename, LD.line_no);
/* Remove '\n' at end of line. */
if (LD.buf[linelen - 1] == '\n')
--linelen;
if (LD.buf[linelen - 1] == LD.escape_char)
LD.continue_line = 1;
}
}
/* This causes to begin the next line. */
LD.buf_ptr = LD.bufsize;
}
/* Return the value of the character at the beginning of the input buffer.
Symbolic character constants are expanded. */
static int
get_char (void)
{
if (LD.buf[LD.buf_ptr] == '<')
/* This is a symbolic character name. */
{
int char_val;
char *startp = LD.buf + (++LD.buf_ptr);
char *endp = startp;
while (LD.buf[LD.buf_ptr] != '>' && isprint (LD.buf[LD.buf_ptr]))
{
if (LD.buf[LD.buf_ptr] == '\0'
|| (LD.buf[LD.buf_ptr] == LD.escape_char
&& LD.buf[++LD.buf_ptr] == '\0'))
break;
*endp++ = LD.buf[LD.buf_ptr++];
}
if (LD.buf[LD.buf_ptr] != '>' && LD.buf[LD.buf_ptr] == '\0')
{
error (0, 0, gettext ("%s:%Zd: end of line in character symbol"),
LD.filename, LD.line_no);
if (startp == endp)
return -1;
}
else
++LD.buf_ptr;
char_val = find_char (startp, endp - startp);
if (char_val == -1 && verbose != 0 && reject_new_char != 0)
{
/* Locale defintions are often given very general. Missing
characters are only reported when explicitely requested. */
char tmp[endp - startp + 3];
tmp[0] = '<';
memcpy (tmp + 1, startp, endp - startp);
tmp[endp - startp + 1] = '>';
tmp[endp - startp + 2] = '\0';
error (0, 0, gettext ("%s:%Zd: character `%s' not defined"),
LD.filename, LD.line_no, tmp);
}
return char_val;
}
else
return (int) LD.buf[LD.buf_ptr++];
}
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/

View file

@ -1,838 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <errno.h>
#include <assert.h>
#include <dirent.h>
#include <fcntl.h>
#include <langinfo.h>
#include <libintl.h>
#include <limits.h>
#include <obstack.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include "localedef.h"
#include "localeinfo.h"
#include "token.h"
/* We don't have these constants defined because we don't use them. Give
default values. */
#define CTYPE_MB_CUR_MIN 0
#define CTYPE_MB_CUR_MAX 0
#define CTYPE_HASH_SIZE 0
#define CTYPE_HASH_LAYERS 0
#define CTYPE_CLASS 0
#define CTYPE_TOUPPER_EB 0
#define CTYPE_TOLOWER_EB 0
#define CTYPE_TOUPPER_EL 0
#define CTYPE_TOLOWER_EL 0
/* We have all categories defined in `categories.def'. Now construct
the description and data structure used for all categories. */
#define DEFINE_CATEGORY(category, name, items, postload, in, check, out) \
struct cat_item category##_desc[] = \
{ \
NO_PAREN items \
}; \
\
char *category##_values[NELEMS (category##_desc) - 1] = { NULL, };
#include "categories.def"
#undef DEFINE_CATEGORY
struct category category[] =
{
#define DEFINE_CATEGORY(category, name, items, postload, in, check, out) \
[category] = { _NL_NUM_##category, name, NELEMS (category##_desc) - 1, \
category##_desc, category##_values, in, check, out },
#include "categories.def"
#undef DEFINE_CATEGORY
};
#define NCATEGORIES NELEMS (category)
#define SYNTAX_ERROR \
error (0, 0, gettext ("%s:%Zd: syntax error in locale definition file"), \
locfile_data.filename, locfile_data.line_no)
/* Prototypes for local functions. */
static int get_byte (char *byte_ptr);
static char *is_locale_name (int cat_no, const char *str, int len);
/* Read a locale definition file FILE. The format is defined in
POSIX.2 2.5.3. */
void
locfile_read (const char *fname)
{
/* Pointer to text of last token. */
char *ptr;
/* Length of last token (or if NUMBER the value itself). */
int len;
/* The last returned token. */
int token;
/* For error correction we remember whether the last token was correct. */
int correct_token = 1;
/* Open the desired input file on stdin. */
locfile_open (fname);
while ((token = locfile_lex (&ptr, &len)) != 0)
{
int cat_no;
for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
if (token == category[cat_no].cat_id)
break;
if (cat_no >= NCATEGORIES)
/* A syntax error occured. No valid category defintion starts. */
{
if (correct_token != 0)
error (0, 0, gettext ("%s:%Zd: locale category start expected"),
locfile_data.filename, locfile_data.line_no);
/* To prevent following errors mark as error case. */
correct_token = 0;
/* Synchronization point is the beginning of a new category.
Overread all line upto this silently. */
ignore_to_eol (0, 0);
continue;
}
/* Rest of the line should be empty. */
ignore_to_eol (0, 1);
/* Perhaps these category is already specified. We simply give a
warning and overwrite the values. */
if (category[cat_no].filled != 0)
error (0, 0, gettext ("%s:%Zd: multiple definition of locale "
"category %s"), locfile_data.filename,
locfile_data.line_no, category[cat_no].name);
/* We read the first token because this could be the copy statement. */
token = xlocfile_lex (&ptr, &len);
if (token == TOK_COPY)
/* Copying the definitions from an existing locale is requested. */
{
char *str;
/* Get the name of the locale to copy from. */
token = xlocfile_lex (&ptr, &len);
if (token != TOK_IDENT && token != TOK_STRING)
/* No name, then mark error and ignore everything upto next
start of an category section. */
{
/* To prevent following errors mark as error case. */
correct_token = 0;
/* Synchronization point is the beginning of a new category.
Overread all line upto this silently. */
ignore_to_eol (0, 0);
}
else if ((str = is_locale_name (cat_no, ptr, len)) != NULL)
/* Yes the name really names an existing locale file. We are
returned the complete file name. Store it so that we can
copy it in the output phase. */
{
category[cat_no].copy_locale = str;
category[cat_no].filled = 1;
ignore_to_eol (0, 1);
}
else
/* No, the name does not address a valid locale file. Mark
error case and ignore rest of category. */
{
char tmp[len + 1];
memcpy (tmp, ptr, len);
tmp[len] = '\0';
error (0, 0, gettext ("%s:%Zd: invalid locale `%s' in copy "
"statement"), locfile_data.filename,
locfile_data.line_no, tmp);
correct_token = 0;
ignore_to_eol (0, 0);
}
/* This should END as the next token. */
token = xlocfile_lex (&ptr, &len);
if (token == TOK_END)
/* This is the end of the category. */
{
token = xlocfile_lex (&ptr, &len);
if (token != category[cat_no].cat_id)
/* Wrong category name after END. */
{
error (0, 0, gettext ("%s:%Zd: category `%s' does not "
"end with `END %s'"),
locfile_data.filename, locfile_data.line_no,
category[cat_no].name, category[cat_no].name);
ignore_to_eol (0, 0);
}
else
ignore_to_eol (0, 1);
correct_token = 1;
}
else
/* No END following copy. Give error while not in error case. */
{
if (correct_token != 0)
error (0, 0, gettext ("%s:%Zd: `copy' must be sole rule"),
locfile_data.filename, locfile_data.line_no);
correct_token = 0;
ignore_to_eol (0, 0);
}
continue;
}
/* Now it's time to mark as mentioned in the locale file. */
category[cat_no].filled = 1;
if (category[cat_no].infct != NULL)
/* The category needs a special input handling. */
{
category[cat_no].infct(token);
continue;
}
/* Now process the given items. */
while (1)
{
int item_no;
if (token == TOK_END)
/* This is the end of the category. */
{
token = xlocfile_lex (&ptr, &len);
if (token != category[cat_no].cat_id)
{
error (0, 0, gettext ("%s:%Zd: category `%s' does not end "
"with `END %s'"),
locfile_data.filename, locfile_data.line_no,
category[cat_no].name, category[cat_no].name);
ignore_to_eol (0, 0);
}
else
ignore_to_eol (0, 1);
/* Start next category. */
break;
}
/* All other lines should describe valid items of the category. */
for (item_no = 0; item_no < category[cat_no].number; ++item_no)
if (category[cat_no].item_desc[item_no].item_id == token)
break;
if (item_no >= category[cat_no].number)
/* This is not a valid item of the category. */
{
SYNTAX_ERROR;
ignore_to_eol (0, 0);
token = xlocfile_lex (&ptr, &len);
/* And process next item. */
continue;
}
/* Test whether already a value is defined. */
if (category[cat_no].item_value[item_no] != NULL)
error (0, 0, gettext ("%s:%Zd: category item `%s' already "
"defined"),
locfile_data.filename, locfile_data.line_no,
category[cat_no].item_desc[item_no].name);
switch (category[cat_no].item_desc[item_no].value_type)
{
case string:
/* Get next token. This is the argument to the item. */
token = xlocfile_lex (&ptr, &len);
if (token != TOK_STRING)
SYNTAX_ERROR;
else
category[cat_no].item_value[item_no] = strdup (ptr);
ignore_to_eol (0, ptr != NULL);
break;
case stringarray:
/* This is a difficult case. The number of strings in
the array may vary. But for now its only necessary
with ALT_DIGITS from LC_TIME. This item is the last
so be can solve it by storing the number of string in
the first place and the string indeces following
that. */
{
int cnt;
char **buffer;
if (category[cat_no].item_value[item_no] != NULL)
buffer = (char **) category[cat_no].item_value[item_no];
else
buffer = (char **) xmalloc (
sizeof (char *) * category[cat_no].item_desc[item_no].max);
category[cat_no].item_value[item_no] = (char *) buffer;
/* As explained we may need a place to store the real number
of strings. */
if (category[cat_no].item_desc[item_no].min
!= category[cat_no].item_desc[item_no].max)
++buffer;
cnt = 0;
do
{
token = xlocfile_lex (&ptr, &len);
if (token != TOK_STRING)
{
SYNTAX_ERROR;
break;
}
if (cnt >= category[cat_no].item_desc[item_no].max)
{
error (0, 0, gettext ("%s:%Zd: too many elements "
"for item `%s`"),
locfile_data.filename, locfile_data.line_no,
category[cat_no].item_desc[item_no].name);
break;
}
buffer[cnt++] = strdup (ptr);
token = locfile_lex (&ptr, &len);
}
while (token == TOK_CHAR && len == ';');
ignore_to_eol (token, ptr != NULL);
if (cnt < category[cat_no].item_desc[item_no].min)
error (0, 0, gettext ("%s:%Zd: too few elements for item "
"`%s'"),
locfile_data.filename, locfile_data.line_no,
category[cat_no].item_desc[item_no].name);
if (category[cat_no].item_desc[item_no].min
!= category[cat_no].item_desc[item_no].max)
*(int *) category[cat_no].item_value[item_no] = cnt;
}
break;
case byte:
{
int ok;
category[cat_no].item_value[item_no] = (char *) xmalloc (
__alignof__ (char));
ok = get_byte (category[cat_no].item_value[item_no]);
ignore_to_eol (0, ok);
}
break;
case bytearray:
{
char *buffer;
int maxsize;
int cnt;
char byte;
int ok;
buffer = (char *) xmalloc ((maxsize = 30));
cnt = 0;
while ((ok = get_byte (&byte)))
{
if (cnt >= maxsize)
buffer = (char *) xmalloc ((maxsize *= 2));
buffer[cnt++] = byte;
token = locfile_lex (&ptr, &len);
if (token != TOK_CHAR || len != ';')
break;
}
buffer[cnt] = '\0';
category[cat_no].item_value[item_no] = buffer;
ignore_to_eol (token, ok);
}
break;
default:
error (5, 0, gettext ("internal error in %s, line %u"),
__FUNCTION__, __LINE__);
/* NOTREACHED */
}
/* Get next token. */
token = xlocfile_lex (&ptr, &len);
} /* while (1) */
}
}
/* Check given values for categories for consistency. */
void
categories_check (void)
{
int cat_no;
for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
if (category[cat_no].copy_locale == NULL)
if (category[cat_no].filled != 0)
if (category[cat_no].checkfct)
category[cat_no].checkfct();
else
{
int item_no;
for (item_no = 0; item_no < category[cat_no].number; ++item_no)
if (category[cat_no].item_value[item_no] == NULL)
{
int errcode;
/* If the item is defined in the standard is it an error to
have it not defined. */
errcode = category[cat_no].item_desc[item_no].status == std
? 5 : 0;
error (errcode, 0, gettext ("item `%s' of category `%s' "
"undefined"),
category[cat_no].item_desc[item_no].name,
category[cat_no].name);
}
}
else
error (0, 0, gettext ("category `%s' not defined"),
category[cat_no].name);
}
/* Write out the binary representation of the category data which can be
loaded by setlocale(1). */
void
categories_write (void)
{
struct locale_file
{
int magic;
int n;
int idx[0];
} *data;
struct obstack obstk;
int cat_no;
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
obstack_init (&obstk);
for (cat_no = 0; cat_no < NCATEGORIES; ++cat_no)
{
int result = 0;
if (category[cat_no].copy_locale != NULL)
/* Simply copy the addressed locale file of the specified
category. Please note that this is tried before the distinction
between categories which need special handling is made. */
{
int source;
/* Open source file. */
source = open (category[cat_no].copy_locale, O_RDONLY);
if (source < 0)
error (0, 0, gettext ("cannot copy locale definition file `%s'"),
category[cat_no].copy_locale);
else
{
/* Construct file name of output file and open for writing. */
char path[strlen (output_path)
+ strlen(category[cat_no].name) + 1];
int dest;
char *t;
t = stpcpy (path, output_path);
strcpy (t, category[cat_no].name);
dest = creat (path, 0666);
if (dest == -1)
error (0, 0, gettext ("cannot open output file `%s': %m"),
path);
else
{
char buffer[BUFSIZ];
int size;
/* Copy the files. */
do
{
size = read (source, buffer, BUFSIZ);
write (dest, buffer, size);
}
while (size > 0);
close (dest);
/* Show success. */
puts (category[cat_no].name);
}
close (source);
}
/* Next category. */
continue;
}
if (category[cat_no].outfct)
result = category[cat_no].outfct();
else
{
char *path, *t;
int fd;
struct iovec *iov;
int item_no, len, slen, cnt;
int elems = 0;
/* Count number of elements. */
for (item_no = 0; item_no < category[cat_no].number; ++item_no)
{
switch (category[cat_no].item_desc[item_no].value_type)
{
case string:
case byte:
case bytearray:
++elems;
break;
case stringarray:
elems += category[cat_no].item_desc[item_no].max;
break;
default:
error (5, 0, gettext ("internal error in %s, line %u"),
__FUNCTION__, __LINE__);
/* NOTREACHED */
}
}
/* We now have the number of elements. We build the structure
and a helper structure for writing all out. */
len = sizeof (struct locale_file) + elems * sizeof (int);
data = obstack_alloc (&obstk, len);
iov = obstack_alloc (&obstk, (elems + 1) * sizeof (struct iovec));
data->magic = LIMAGIC (cat_no);
data->n = elems;
iov[0].iov_base = data;
iov[0].iov_len = len;
cnt = 0;
for (item_no = 0; item_no < category[cat_no].number; ++item_no)
if (category[cat_no].item_value[item_no] == NULL)
{
switch (category[cat_no].item_desc[item_no].value_type)
{
case string:
case byte:
case bytearray:
data->idx[cnt] = len;
++len; /* We reserve one single byte for this entry. */
iov[1 + cnt].iov_base = (char *) "";
iov[1 + cnt].iov_len = 1;
++cnt;
break;
case stringarray:
{
int max;
int nstr;
max = category[cat_no].item_desc[item_no].max;
for (nstr = 0; nstr < max; ++nstr)
{
data->idx[cnt] = len;
++len;
iov[1 + cnt].iov_base = (char *) "";
iov[1 + cnt].iov_len = 1;
++cnt;
}
}
}
}
else
switch (category[cat_no].item_desc[item_no].value_type)
{
case string:
case bytearray:
data->idx[cnt] = len;
slen = strlen (category[cat_no].item_value[item_no]) + 1;
len += slen;
iov[1 + cnt].iov_base = category[cat_no].item_value[item_no];
iov[1 + cnt].iov_len = slen;
++cnt;
break;
case byte:
data->idx[cnt] = len;
slen = 1;
len += slen;
iov[1 + cnt].iov_base = category[cat_no].item_value[item_no];
iov[1 + cnt].iov_len = slen;
++cnt;
break;
case stringarray:
{
int nstr, nact;
char **first;
if (category[cat_no].item_desc[item_no].min
== category[cat_no].item_desc[item_no].max)
{
nstr = category[cat_no].item_desc[item_no].min;
first = (char **) category[cat_no].item_value[item_no];
}
else
{
nstr = *(int *) category[cat_no].item_value[item_no];
first =
((char **) category[cat_no].item_value[item_no]) + 1;
}
nact = nstr;
while (nstr > 0)
{
data->idx[cnt] = len;
if (*first != NULL)
{
slen = strlen (*first) + 1;
iov[1 + cnt].iov_base = *first;
}
else
{
slen = 1;
iov[1 + cnt].iov_base = (char *) "";
}
len += slen;
iov[1 + cnt].iov_len = slen;
++cnt;
++first;
--nstr;
}
while (nact < category[cat_no].item_desc[item_no].max)
{
data->idx[cnt] = len;
len += 1;
iov[1 + cnt].iov_base = (char *) "";
iov[1 + cnt].iov_len = 1;
++cnt;
++nact;
}
}
break;
default:
/* Cannot happen. */
break;
}
assert (cnt <= elems);
/* Construct the output filename from the argument given to
localedef on the command line. */
path = (char *) obstack_alloc (&obstk, strlen (output_path) +
2 * strlen (category[cat_no].name) + 5);
t = stpcpy (path, output_path);
strcpy (t, category[cat_no].name);
fd = creat (path, 0666);
if (fd == -1)
{
/* Check whether it failed because the named file is a directory.
In that case we use the file .../LC_xxx/SYS_LC_xxx, as the
loading functions of the C Library do. */
struct stat st;
if (stat (path, &st) == 0 && S_ISDIR (st.st_mode))
{
stpcpy (stpcpy (strchr (path, '\0'), "/SYS_"),
category[cat_no].name);
fd = creat (path, 0666);
}
}
if (fd == -1)
{
error (0, 0, gettext ("cannot open output file `%s': %m"),
path);
result = 1;
}
else
{
if (writev (fd, iov, cnt + 1) == -1)
{
error (0, 0, gettext ("cannot write output file `%s': %m"),
path);
result = 1;
}
if (elems==0) write(fd, &elems, 10);
close (fd);
}
/* The old data is not needed anymore, but keep the obstack
intact. */
obstack_free (&obstk, data);
}
if (result == 0)
puts (category[cat_no].name);
}
/* Now the whole obstack can be removed. */
obstack_free (&obstk, NULL);
}
/* Get the representation of a number. This is a positive integer or
the number -1 which is handled as a special symbol by the scanner. */
static int
get_byte (char *byte_ptr)
{
int token;
char *ptr;
int len;
token = locfile_lex (&ptr, &len);
if (token != TOK_NUMBER && token != TOK_MINUS1)
/* None of the valid number format. */
{
error (0, 0, gettext ("%s:%Zd: number expected"),
locfile_data.filename, locfile_data.line_no);
*byte_ptr = 0;
return 0;
}
if (token == TOK_MINUS1)
{
*byte_ptr = CHAR_MAX;
return 1;
}
if (len > CHAR_MAX)
/* The value of the numbers has to be less than CHAR_MAX. This is
ok for the information they have to express. */
{
error (0, 0, gettext ("%s:%Zd: invalid number"),
locfile_data.filename, locfile_data.line_no);
*byte_ptr = 0;
return 0;
}
*byte_ptr = len;
return 1;
}
/* Test whether the string STR with length LEN is the name of an existing
locale and whether a file for category CAT_NO is found in this directory.
This categories are looked for in the system locale definition file
directory.
Return the complete file name for the category file. */
static char *
is_locale_name (int cat_no, const char *str, int len)
{
static char **locale_names = NULL;
static int max_count = 0;
static int locale_count = 0;
int cnt, exist, fd;
char *fname;
struct stat st;
if (locale_names == NULL)
/* Read in the list of all available locales. */
{
DIR *dir;
struct dirent *dirent;
/* LOCALE_NAMES is not NULL anymore, but LOCALE_COUNT == 0. */
++locale_names;
dir = opendir (LOCALE_PATH);
if (dir == NULL)
{
error (1, errno, gettext ("cannot read locale directory `%s'"),
LOCALE_PATH);
return NULL;
}
/* Now we can look for all files in the directory. */
while ((dirent = readdir (dir)) != NULL)
if (strcmp (dirent->d_name, ".") != 0
&& strcmp (dirent->d_name, "..") != 0)
{
if (max_count == 0)
locale_names = (char **) xmalloc ((max_count = 10)
* sizeof (char *));
else if (locale_count >= max_count)
locale_names = (char **) xrealloc (locale_names,
(max_count *= 2)
* sizeof (char *));
locale_names[locale_count++] = strdup (dirent->d_name);
}
closedir (dir);
}
for (cnt = 0; cnt < locale_count; ++cnt)
if (strncmp (str, locale_names[cnt], len) == 0
&& locale_names[cnt][len] == '\0')
break;
if (cnt >= locale_count)
return NULL;
/* Now search for this specific locale file. */
asprintf (&fname, "%s/%s/%s", LOCALE_PATH, locale_names[cnt],
category[cat_no].name);
fd = open (fname, O_RDONLY);
if (fd < 0)
{
free (fname);
return NULL;
}
exist = fstat (fd, &st);
close (fd);
if (exist < 0)
{
free (fname);
return NULL;
}
return fname;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/

View file

@ -1,76 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <langinfo.h>
#include <libintl.h>
#include <locale.h>
#include <stdio.h>
#include <regex.h>
#include "localedef.h"
/* These are defined in locfile-parse.c. */
extern struct cat_item LC_MESSAGES_desc[];
extern char *LC_MESSAGES_values[];
void
messages_check(void)
{
int item_no;
/* First general check for existence. */
for (item_no = 0; item_no < category[LC_MESSAGES].number; ++item_no)
if (LC_MESSAGES_values[item_no] == NULL)
{
int errcode;
errcode = LC_MESSAGES_desc[item_no].status == std ? 5 : 0;
error (errcode, 0, gettext ("item `%s' of category `%s' undefined"),
LC_MESSAGES_desc[item_no].name, "LC_MESSAGES");
}
else
{
/* Some fields need special tests. */
if (LC_MESSAGES_desc[item_no].item_id == YESEXPR
|| LC_MESSAGES_desc[item_no].item_id == NOEXPR)
/* The expression has to be a POSIX extended regular expression. */
{
regex_t re;
int result;
result = regcomp (&re, LC_MESSAGES_values[item_no], REG_EXTENDED);
if (result != 0)
{
char errbuf[BUFSIZ];
(void) regerror (result, &re, errbuf, BUFSIZ);
error (0, 0, gettext ("no correct regular expression for "
"item `%s' in category `%s': %s"),
LC_MESSAGES_desc[item_no].name, "LC_MESSAGES", errbuf);
}
}
}
}
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/

View file

@ -1,132 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <langinfo.h>
#include <libintl.h>
#include <stdlib.h>
#include <string.h>
#include "localedef.h"
#include "token.h"
/* The content iof the field int_curr_symbol has to be taken from
ISO-4217. We test for correct values. */
#define DEFINE_INT_CURR(str) str,
static const char *const valid_int_curr[] =
{
# include "iso-4217.def"
};
#define NVALID_INT_CURR ((sizeof (valid_int_curr) \
/ sizeof (valid_int_curr[0])))
#undef DEFINE_INT_CURR
/* These are defined in locfile-parse.c. */
extern struct cat_item LC_MONETARY_desc[];
extern char *LC_MONETARY_values[];
static int _curr_strcmp(const char *s1, const char **s2);
void
monetary_check(void)
{
int item_no, val;
for (item_no = 0; LC_MONETARY_desc[item_no].item_id != 0; ++item_no)
/* Test whether the entry has been defined. Byte values are simply
stored. */
if (LC_MONETARY_values[item_no] == NULL)
{
int errcode;
errcode = LC_MONETARY_desc[item_no].status = std ? 5 : 0;
error (errcode, 0, gettext ("item `%s' of category `%s' undefined"),
LC_MONETARY_desc[item_no].name, "LC_MONETARY");
}
else
switch (LC_MONETARY_desc[item_no].item_id)
{
case INT_CURR_SYMBOL:
if (strlen (LC_MONETARY_values[item_no]) != 4)
error (0, 0,
gettext ("item `%s' of category `%s' has wrong length"),
LC_MONETARY_desc[item_no].name, "LC_MONETARY");
else if (bsearch (LC_MONETARY_values[item_no], valid_int_curr,
NVALID_INT_CURR, sizeof (char *),
(comparison_fn_t) _curr_strcmp) == NULL)
error (0, 0, gettext ("item `%s' does not correspond to any "
"valid name in ISO-4217"),
LC_MONETARY_desc[item_no].name);
break;
case P_CS_PRECEDES:
case P_SEP_BY_SPACE:
case N_CS_PRECEDES:
case N_SEP_BY_SPACE:
case P_SIGN_POSN:
case N_SIGN_POSN:
val = (int) *(char *) LC_MONETARY_values[item_no];
if (val < LC_MONETARY_desc[item_no].min
|| val > LC_MONETARY_desc[item_no].max)
error (0, 0, gettext ("value for item `%s' in category `%s' "
"must be in range %d...%d"),
LC_MONETARY_desc[item_no].name, "LC_MONETARY",
LC_MONETARY_desc[item_no].min,
LC_MONETARY_desc[item_no].max);
break;
case MON_DECIMAL_POINT:
/* The decimal point must not be empty. This is not said
explicitly in POSIX but ANSI C (ISO/IEC 9899) says in
4.4.2.1 it has to be != "". */
if (LC_MONETARY_values[item_no][0] == '\0')
error (0, 0,
gettext ("item `%s' in category `%s' must not be empty"),
LC_MONETARY_desc[item_no].name, "LC_MONETARY");
break;
case CURRENCY_SYMBOL:
case MON_THOUSANDS_SEP:
case MON_GROUPING:
case POSITIVE_SIGN:
case NEGATIVE_SIGN:
case INT_FRAC_DIGITS:
case FRAC_DIGITS:
/* Everything is ok for these values. */
break;
default:
error (5, 0, gettext ("Internal error in %s, line %u"),
__FUNCTION__, __LINE__);
/* NOTREACHED */
}
}
static int
_curr_strcmp(const char *s1, const char **s2)
{
return strcmp (s1, *s2);
}
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/

View file

@ -1,62 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <langinfo.h>
#include <libintl.h>
#include <locale.h>
#include "localedef.h"
/* These are defined in locfile-parse.c. */
extern struct cat_item LC_NUMERIC_desc[];
extern char *LC_NUMERIC_values[];
void
numeric_check(void)
{
int item_no;
/* First general check for existence. */
for (item_no = 0; item_no < category[LC_NUMERIC].number; ++item_no)
if (LC_NUMERIC_values[item_no] == NULL)
{
int errcode;
errcode = LC_NUMERIC_desc[item_no].status = std ? 5 : 0;
error (errcode, 0, gettext ("item `%s' of category `%s' undefined"),
LC_NUMERIC_desc[item_no].name, "LC_NUMERIC");
}
else
{
if (LC_NUMERIC_desc[item_no].item_id == DECIMAL_POINT
&& LC_NUMERIC_values[item_no][0] == '\0')
/* The decimal point must not be empty. This is not said
explicitly in POSIX but ANSI C (ISO/IEC 9899) says in
4.4.2.1 it has to be != "". */
error (0, 0,
gettext ("item `%s' in category `%s' must not be empty"),
LC_NUMERIC_desc[item_no].name, "LC_NUMERIC");
}
}
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/

View file

@ -0,0 +1,40 @@
%{
/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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 <string.h>
#include "locfile-token.h"
%}
struct keyword_t ;
%%
code_set_name, tok_code_set_name, 1
mb_cur_max, tok_mb_cur_max, 1
mb_cur_min, tok_mb_cur_min, 1
escape_char, tok_escape_char, 1
comment_char, tok_comment_char, 1
g0esc, tok_g0esc, 1
g1esc, tok_g1esc, 1
g2esc, tok_g2esc, 1
g3esc, tok_g3esc, 1
CHARMAP, tok_charmap, 0
END, tok_end, 0
WIDTH, tok_width, 0
WIDTH_VARIABLE, tok_width_variable, 0
WIDTH_DEFAULT, tok_width_default, 0

View file

@ -0,0 +1,117 @@
/* C code produced by gperf version 2.5 (GNU C++ version) */
/* Command-line: gperf -acCgopt -k1,2,5,$ -N charmap_hash programs/charmap-kw.gperf */
/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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 <string.h>
#include "locfile-token.h"
struct keyword_t ;
#define TOTAL_KEYWORDS 14
#define MIN_WORD_LENGTH 3
#define MAX_WORD_LENGTH 14
#define MIN_HASH_VALUE 3
#define MAX_HASH_VALUE 25
/* maximum key range = 23, duplicates = 0 */
#ifdef __GNUC__
inline
#endif
static unsigned int
hash (register const char *str, register int len)
{
static const unsigned char asso_values[] =
{
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 26, 14, 10,
15, 4, 26, 26, 26, 26, 26, 26, 26, 26,
26, 26, 26, 26, 26, 26, 26, 0, 0, 0,
26, 26, 0, 0, 26, 26, 26, 0, 0, 26,
0, 26, 26, 26, 5, 26, 26, 0, 26, 26,
26, 26, 26, 26, 26, 0, 26, 26, 0, 0,
26, 0, 26, 0, 26, 26, 26, 26, 26, 0,
15, 0, 0, 26, 0, 0, 26, 0, 26, 26,
0, 26, 26, 26, 26, 26, 26, 26,
};
register int hval = len;
switch (hval)
{
default:
case 5:
hval += asso_values[(int) str[4]];
case 4:
case 3:
case 2:
hval += asso_values[(int) str[1]];
case 1:
hval += asso_values[(int) str[0]];
break;
}
return hval + asso_values[(int) str[len - 1]];
}
#ifdef __GNUC__
inline
#endif
const struct keyword_t *
charmap_hash (register const char *str, register int len)
{
static const struct keyword_t wordlist[] =
{
{"",}, {"",}, {"",},
{"END", tok_end, 0},
{"",},
{"WIDTH", tok_width, 0},
{"",},
{"CHARMAP", tok_charmap, 0},
{"",},
{"g3esc", tok_g3esc, 1},
{"mb_cur_max", tok_mb_cur_max, 1},
{"escape_char", tok_escape_char, 1},
{"comment_char", tok_comment_char, 1},
{"code_set_name", tok_code_set_name, 1},
{"WIDTH_VARIABLE", tok_width_variable, 0},
{"g1esc", tok_g1esc, 1},
{"",}, {"",},
{"WIDTH_DEFAULT", tok_width_default, 0},
{"g0esc", tok_g0esc, 1},
{"g2esc", tok_g2esc, 1},
{"",}, {"",}, {"",}, {"",},
{"mb_cur_min", tok_mb_cur_min, 1},
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
{
register int key = hash (str, len);
if (key <= MAX_HASH_VALUE && key >= 0)
{
register const char *s = wordlist[key].name;
if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
return &wordlist[key];
}
}
return 0;
}

593
locale/programs/charmap.c Normal file
View file

@ -0,0 +1,593 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <libintl.h>
#include <obstack.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "error.h"
#include "linereader.h"
#include "charset.h"
/* Uncomment following line for production version. */
/* define NDEBUG 1 */
#include <assert.h>
/* Define the lookup function. */
#include "charmap-kw.h"
void *xmalloc (size_t __n);
/* Prototypes for local functions. */
static struct charset_t *parse_charmap (const char *filename);
struct charset_t *
charmap_read (const char *filename)
{
const char *pathnfile;
struct charset_t *result = NULL;
if (filename != NULL)
{
if (euidaccess (filename, R_OK) >= 0)
pathnfile = filename;
else
{
char *cp = xmalloc (strlen (filename) + sizeof CHARMAP_PATH + 1);
stpcpy (stpcpy (stpcpy (cp, CHARMAP_PATH), "/"), filename);
pathnfile = (const char *) cp;
}
result = parse_charmap (pathnfile);
if (result == NULL)
error (0, errno, _("character map file `%s' not found"), filename);
}
if (result == NULL)
{
pathnfile = CHARMAP_PATH "/" DEFAULT_CHARMAP;
result = parse_charmap (pathnfile);
if (result == NULL)
error (4, errno, _("default character map file `%s' not found"),
DEFAULT_CHARMAP);
}
return result;
}
static struct charset_t *
parse_charmap (const char *filename)
{
struct linereader *cmfile;
struct charset_t *result;
int state;
enum token_t expected_tok = tok_error;
const char *expected_str = NULL;
char *from_name = NULL;
char *to_name = NULL;
/* Determine path. */
cmfile = lr_open (filename, charmap_hash);
if (cmfile == NULL)
{
if (strchr (filename, '/') == NULL)
{
/* Look in the systems charmap directory. */
char *buf = xmalloc (strlen (filename) + 1 + sizeof (CHARMAP_PATH));
stpcpy (stpcpy (stpcpy (buf, CHARMAP_PATH), "/"), filename);
cmfile = lr_open (buf, charmap_hash);
if (cmfile == NULL)
free (buf);
}
if (cmfile == NULL)
return NULL;
}
/* Allocate room for result. */
result = (struct charset_t *) xmalloc (sizeof (struct charset_t));
memset (result, '\0', sizeof (struct charset_t));
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
obstack_init (&result->mem_pool);
if (init_hash (&result->char_table, 256))
{
free (result);
return NULL;
}
/* We use a state machine to describe the charmap description file
format. */
state = 1;
while (1)
{
/* What's on? */
struct token *now = lr_token (cmfile, NULL);
enum token_t nowtok = now->tok;
struct token *arg;
if (nowtok == tok_eof)
break;
switch (state)
{
case 1:
/* The beginning. We expect the special declarations, EOL or
`CHARMAP'. */
if (nowtok == tok_eol)
/* Ignore empty lines. */
continue;
if (nowtok == tok_charmap)
{
from_name = NULL;
to_name = NULL;
/* We have to set up the real work. Fill in some
default values. */
if (result->mb_cur_max == 0)
result->mb_cur_max = 1;
if (result->mb_cur_min == 0)
result->mb_cur_min = result->mb_cur_max;
if (result->mb_cur_min > result->mb_cur_max)
{
error (0, 0, _("\
%s: <mb_cur_max> must be greater than <mb_cur_min>\n"),
cmfile->fname);
result->mb_cur_min = result->mb_cur_max;
}
lr_ignore_rest (cmfile, 1);
state = 2;
continue;
}
if (nowtok != tok_code_set_name && nowtok != tok_mb_cur_max
&& nowtok != tok_mb_cur_min && nowtok != tok_escape_char
&& nowtok != tok_comment_char && nowtok != tok_g0esc
&& nowtok != tok_g1esc && nowtok != tok_g2esc
&& nowtok != tok_g3esc)
{
lr_error (cmfile, _("syntax error in prolog: %s"),
_("illegal definition"));
lr_ignore_rest (cmfile, 0);
continue;
}
/* We know that we need an argument. */
arg = lr_token (cmfile, NULL);
switch (nowtok)
{
case tok_code_set_name:
if (arg->tok != tok_ident)
{
badarg:
lr_error (cmfile, _("syntax error in prolog: %s"),
_("bad argument"));
lr_ignore_rest (cmfile, 0);
continue;
}
result->code_set_name = obstack_copy0 (&result->mem_pool,
arg->val.str.start,
arg->val.str.len);
lr_ignore_rest (cmfile, 1);
continue;
case tok_mb_cur_max:
case tok_mb_cur_min:
if (arg->tok != tok_number)
goto badarg;
if (arg->val.num < 1 || arg->val.num > 4)
{
lr_error (cmfile,
_("value for <%s> must lie between 1 and 4"),
nowtok == tok_mb_cur_min ? "mb_cur_min"
: "mb_cur_max");
lr_ignore_rest (cmfile, 0);
continue;
}
if ((nowtok == tok_mb_cur_max && result->mb_cur_min != 0
&& arg->val.num < result->mb_cur_min)
|| (nowtok == tok_mb_cur_min && result->mb_cur_max != 0
&& arg->val.num > result->mb_cur_max))
{
lr_error (cmfile, _("\
value of <mb_cur_max> must be greater than the value of <mb_cur_min>"));
lr_ignore_rest (cmfile, 0);
continue;
}
if (nowtok == tok_mb_cur_max)
result->mb_cur_max = arg->val.num;
else
result->mb_cur_min = arg->val.num;
lr_ignore_rest (cmfile, 1);
continue;
case tok_escape_char:
case tok_comment_char:
if (arg->tok != tok_ident)
goto badarg;
if (arg->val.str.len != 1)
{
lr_error (cmfile, _("\
argument to <%s> must be a single character"),
nowtok == tok_escape_char ? "escape_char"
: "comment_char");
lr_ignore_rest (cmfile, 0);
continue;
}
if (nowtok == tok_escape_char)
cmfile->escape_char = *arg->val.str.start;
else
cmfile->comment_char = *arg->val.str.start;
lr_ignore_rest (cmfile, 1);
continue;
case tok_g0esc:
case tok_g1esc:
case tok_g2esc:
case tok_g3esc:
lr_ignore_rest (cmfile, 0); /* XXX */
continue;
default:
/* Cannot happen. */
assert (! "Should not happen");
}
break;
case 2:
/* We have seen `CHARMAP' and now are in the body. Each line
must have the format "%s %s %s\n" or "%s...%s %s %s\n". */
if (nowtok == tok_eol)
/* Ignore empty lines. */
continue;
if (nowtok == tok_end)
{
expected_tok = tok_charmap;
expected_str = "CHARMAP";
state = 90;
continue;
}
if (nowtok != tok_bsymbol)
{
lr_error (cmfile, _("syntax error in %s definition: %s"),
"CHARMAP", _("no symbolic name given"));
lr_ignore_rest (cmfile, 0);
continue;
}
/* If the previous line was not completely correct free the
used memory. */
if (from_name != NULL)
obstack_free (&result->mem_pool, from_name);
from_name = (char *) obstack_copy0 (&result->mem_pool,
now->val.str.start,
now->val.str.len);
to_name = NULL;
state = 3;
continue;
case 3:
/* We have two possibilities: We can see an ellipsis or an
encoding value. */
if (nowtok == tok_ellipsis)
{
state = 4;
continue;
}
/* FALLTHROUGH */
case 5:
if (nowtok != tok_charcode && nowtok != tok_ucs2
&& nowtok != tok_ucs4)
{
lr_error (cmfile, _("syntax error in %s definition: %s"),
"CHARMAP", _("illegal encoding given"));
lr_ignore_rest (cmfile, 0);
state = 2;
continue;
}
if (nowtok == tok_charcode)
/* Write char value in table. */
charset_new_char (cmfile, result, now->val.charcode.nbytes,
now->val.charcode.val, from_name, to_name);
else
/* Determine ISO 10646 value and write into table. */
charset_new_unicode (cmfile, result, now->val.charcode.nbytes,
now->val.charcode.val, from_name, to_name);
/* Ignore trailing comment silently. */
lr_ignore_rest (cmfile, 0);
from_name = NULL;
to_name = NULL;
state = 2;
continue;
case 4:
if (nowtok != tok_bsymbol)
{
lr_error (cmfile, _("syntax error in %s definition: %s"),
"CHARMAP",
_("no symbolic name given for end of range"));
lr_ignore_rest (cmfile, 0);
continue;
}
/* If the previous line was not completely correct free the
used memory. */
to_name = (char *) obstack_copy0 (&result->mem_pool,
cmfile->token.val.str.start,
cmfile->token.val.str.len);
state = 3;
continue;
case 90:
if (nowtok != expected_tok)
lr_error (cmfile, _("\
`%1$s' definition does not end with `END %1$s'"), expected_str);
lr_ignore_rest (cmfile, nowtok == expected_tok);
state = 91;
continue;
case 91:
/* Waiting for WIDTH... */
if (nowtok == tok_width_default)
{
state = 92;
continue;
}
if (nowtok == tok_width)
{
lr_ignore_rest (cmfile, 1);
state = 93;
continue;
}
if (nowtok == tok_width_variable)
{
lr_ignore_rest (cmfile, 1);
state = 98;
continue;
}
lr_error (cmfile, _("\
only WIDTH definitions are allowed to follow the CHARMAP definition"));
lr_ignore_rest (cmfile, 0);
continue;
case 92:
if (nowtok != tok_number)
lr_error (cmfile, _("value for %s must be an integer"),
"WIDTH_DEFAULT");
else
result->width_default = now->val.num;
lr_ignore_rest (cmfile, nowtok == tok_number);
state = 91;
continue;
case 93:
/* We now expect `END WIDTH' or lines of the format "%s %d\n" or
"%s...%s %d\n". */
if (nowtok == tok_eol)
/* ignore empty lines. */
continue;
if (nowtok == tok_end)
{
expected_tok = tok_width;
expected_str = "WIDTH";
state = 90;
continue;
}
if (nowtok != tok_bsymbol)
{
lr_error (cmfile, _("syntax error in %s definition: %s"),
"WIDTH", _("no symbolic name given"));
lr_ignore_rest (cmfile, 0);
continue;
}
if (from_name != NULL)
obstack_free (&result->mem_pool, from_name);
from_name = (char *) obstack_copy0 (&result->mem_pool,
now->val.str.start,
now->val.str.len);
to_name = NULL;
state = 94;
continue;
case 94:
if (nowtok == tok_ellipsis)
state = 95;
case 96:
if (nowtok != tok_number)
lr_error (cmfile, _("value for %s must be an integer"),
"WIDTH");
else
{
/* XXX Store width for chars. */
from_name = NULL;
}
lr_ignore_rest (cmfile, nowtok == tok_number);
state = 93;
continue;
case 95:
if (nowtok != tok_bsymbol)
{
lr_error (cmfile, _("syntax error in %s definition: %s"),
"WIDTH", _("no symbolic name given for end of range"));
lr_ignore_rest (cmfile, 0);
state = 93;
continue;
}
to_name = (char *) obstack_copy0 (&result->mem_pool,
now->val.str.start,
now->val.str.len);
lr_ignore_rest (cmfile, 1);
state = 96;
continue;
case 98:
/* We now expect `END WIDTH_VARIABLE' or lines of the format
"%s\n" or "%s...%s\n". */
if (nowtok == tok_eol)
/* ignore empty lines. */
continue;
if (nowtok == tok_end)
{
expected_tok = tok_width_variable;
expected_str = "WIDTH_VARIABLE";
state = 90;
continue;
}
if (nowtok != tok_bsymbol)
{
lr_error (cmfile, _("syntax error in %s definition: %s"),
"WIDTH_VARIABLE", _("no symbolic name given"));
lr_ignore_rest (cmfile, 0);
continue;
}
if (from_name != NULL)
obstack_free (&result->mem_pool, from_name);
from_name = (char *) obstack_copy0 (&result->mem_pool,
now->val.str.start,
now->val.str.len);
to_name = NULL;
state = 99;
continue;
case 99:
if (nowtok == tok_ellipsis)
state = 100;
/* Store info. */
from_name = NULL;
/* Warn */
state = 98;
continue;
case 100:
if (nowtok != tok_bsymbol)
lr_error (cmfile, _("syntax error in %s definition: %s"),
"WIDTH_VARIABLE",
_("no symbolic name given for end of range"));
else
{
to_name = (char *) obstack_copy0 (&result->mem_pool,
now->val.str.start,
now->val.str.len);
/* XXX Enter value into table. */
}
lr_ignore_rest (cmfile, nowtok == tok_bsymbol);
state = 98;
continue;
default:
error (5, 0, _("%s: error in state machine"), __FILE__);
/* NOTREACHED */
}
break;
}
if (state != 91)
error (0, 0, _("%s: premature end of file"), cmfile->fname);
lr_close (cmfile);
return result;
}

132
locale/programs/charset.c Normal file
View file

@ -0,0 +1,132 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <alloca.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "error.h"
#include "charset.h"
static void
insert_char (struct linereader *lr, struct charset_t *cs, int bytes,
unsigned int value, const char *from, const char *to);
void
charset_new_char (struct linereader *lr, struct charset_t *cs, int bytes,
unsigned int value, const char *from, const char *to)
{
if (bytes < cs->mb_cur_min)
lr_error (lr, _("too few bytes in character encoding"));
else if (bytes > cs->mb_cur_max)
lr_error (lr, _("too many bytes in character encoding"));
else
insert_char (lr, cs, bytes, value, from, to);
}
void
charset_new_unicode (struct linereader *lr, struct charset_t *cs, int bytes,
unsigned int value, const char *from, const char *to)
{
/* For now: perhaps <Uxxxx> support will be removed again... */
insert_char (lr, cs, bytes, value, from, to);
}
unsigned int
charset_find_value (const struct charset_t *cs, const char *name, size_t len)
{
void *result;
if (find_entry ((hash_table *) &cs->char_table, name, len, &result) < 0)
return ILLEGAL_CHAR_VALUE;
return (unsigned int) result;
}
static void
insert_char (struct linereader *lr, struct charset_t *cs, int bytes,
unsigned int value, const char *from, const char *to)
{
const char *cp;
char *buf;
int prefix_len, len1, len2;
unsigned int from_nr, to_nr, cnt;
if (to == NULL)
{
if (insert_entry (&cs->char_table, from, strlen (from), (void *) value)
< 0)
lr_error (lr, _("duplicate character name `%s'"), from);
return;
}
/* We have a range: the names must have names with equal prefixes
and an equal number of digits, where the second number is greater
or equal than the first. */
len1 = strlen (from);
len2 = strlen (to);
if (len1 != len2)
{
illegal_range:
lr_error (lr, _("illegal names for character range"));
return;
}
cp = &from[len1 - 1];
while (isdigit (*cp) && cp >= from)
--cp;
prefix_len = (cp - from) + 1;
if (cp == &from[len1 - 1] || strncmp (from, to, prefix_len) != 0)
goto illegal_range;
from_nr = strtoul (&from[prefix_len], NULL, 10);
to_nr = strtoul (&to[prefix_len], NULL, 10);
if (from_nr > to_nr)
{
lr_error (lr, _("upper limit in range is not smaller then lower limit"));
return;
}
buf = alloca (len1 + 1);
memcpy (buf, from, prefix_len);
for (cnt = from_nr; cnt <= to_nr; ++cnt)
{
sprintf (&buf[prefix_len], "%0d", cnt);
if (insert_entry (&cs->char_table, buf, len1, (void *) cnt) < 0)
lr_error (lr, _("duplicate character name `%s'"), buf);
}
}

61
locale/programs/charset.h Normal file
View file

@ -0,0 +1,61 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifndef _CHARSET_H
#define _CHARSET_H
#include <obstack.h>
#include "simple-hash.h"
#include "linereader.h"
struct charset_t
{
const char *code_set_name;
int mb_cur_min;
int mb_cur_max;
int width_default;
struct obstack mem_pool;
hash_table char_table;
};
/* We need one value to mark the error case. Let's use 0xffffffff.
I.e., it is placed in the last page of ISO 10646. For now only the
first is used and we have plenty of room. */
#define ILLEGAL_CHAR_VALUE 0xffffffffu
/* Prototypes for charmap handling functions. */
struct charset_t *charmap_read (const char *filename);
/* Prototypes for funciton to insert new character. */
void charset_new_char (struct linereader *lr, struct charset_t *cs, int bytes,
unsigned int value, const char *from, const char *to);
void charset_new_unicode (struct linereader *lr, struct charset_t *cs,
int bytes, unsigned int value, const char *from,
const char *to);
unsigned int charset_find_value (const struct charset_t *__cs,
const char *__name, size_t __len);
#endif /* charset.h */

33
locale/programs/config.h Normal file
View file

@ -0,0 +1,33 @@
#ifndef _LD_CONFIG_H
#define _LD_CONFIG_H
/* Use the internal textdomain used for libc messages. */
#define PACKAGE _libc_intl_domainname
#ifndef VERSION
/* Get libc version number. */
#include "../../version.h"
#endif
#define DEFAULT_CHARMAP "POSIX"
#ifndef PARAMS
# if __STDC__
# define PARAMS(args) args
# else
# define PARAMS(args) ()
# endif
#endif
#define HAVE_VPRINTF 1
typedef int wint_t;
typedef unsigned short int u16_t;
int euidaccess (__const char *__name, int __type);
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
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
@ -21,7 +21,7 @@ Cambridge, MA 02139, USA. */
#include <stdio.h>
#include <netinet/in.h> /* Just for htons() */
#include "localedef.h"
/*#include "localedef.h"*/
#include "localeinfo.h"
@ -31,10 +31,10 @@ Cambridge, MA 02139, USA. */
#define SWAP32(v) \
((u32) (((((u32) (v)) & 0x000000ff) << 24) \
| ((((u32) (v)) & 0x0000ff00) << 8) \
| ((((u32) (v)) & 0x00ff0000) >> 8) \
| ((((u32) (v)) & 0xff000000) >> 24)))
((u32_t) (((((u32_t) (v)) & 0x000000ff) << 24) \
| ((((u32_t) (v)) & 0x0000ff00) << 8) \
| ((((u32_t) (v)) & 0x00ff0000) >> 8) \
| ((((u32_t) (v)) & 0xff000000) >> 24)))
@ -53,13 +53,13 @@ print_int_in_char (unsigned int val)
printf ("\"\\%03o\\%03o\\%03o\\%03o\"", p[0], p[1], p[2], p[3]);
}
int
ctype_output (void)
{
int ch;
int result = 0;
const char *locname = (getenv ("LC_ALL") ?: getenv ("LC_CTYPE") ?:
const char *locname = (getenv ("LC_ALL") ?: getenv ("LC_CTYPE") ?:
getenv ("LANG") ?: "POSIX");
puts ("#include <endian.h>\n");

1549
locale/programs/ld-collate.c Normal file

File diff suppressed because it is too large Load diff

1310
locale/programs/ld-ctype.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,237 @@
/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <alloca.h>
#include <langinfo.h>
#include <string.h>
#include <sys/uio.h>
#ifdef HAVE_REGEX
# include <regex.h>
#else
# include <rx.h>
#endif
/* Undefine following line in production version. */
/* #define NDEBUG 1 */
#include <assert.h>
#include "locales.h"
#include "stringtrans.h"
#include "localeinfo.h"
void *xmalloc (size_t __n);
/* The real definition of the struct for the LC_MESSAGES locale. */
struct locale_messages_t
{
const char *yesexpr;
const char *noexpr;
const char *yesstr;
const char *nostr;
};
void
messages_startup (struct linereader *lr, struct localedef_t *locale,
struct charset_t *charset)
{
struct locale_messages_t *messages;
/* It is important that we always use UCS1 encoding for strings now. */
encoding_method = ENC_UCS1;
locale->categories[LC_MESSAGES].messages = messages =
(struct locale_messages_t *) xmalloc (sizeof (struct locale_messages_t));
memset (messages, '\0', sizeof (struct locale_messages_t));
}
void
messages_finish (struct localedef_t *locale)
{
struct locale_messages_t *messages
= locale->categories[LC_MESSAGES].messages;
/* The fields YESSTR and NOSTR are optional. */
if (messages->yesexpr == NULL)
error (0, 0, _("field `%s' in category `%s' undefined"),
"yesexpr", "LC_MESSAGES");
else
{
int result;
regex_t re;
/* Test whether it are correct regular expressions. */
result = regcomp (&re, messages->yesexpr, REG_EXTENDED);
if (result != 0)
{
char errbuf[BUFSIZ];
(void) regerror (result, &re, errbuf, BUFSIZ);
error (0, 0, _("\
no correct regular expression for field `%s' in category `%s': %s"),
"yesexpr", "LC_MESSAGES", errbuf);
}
}
if (messages->noexpr == NULL)
error (0, 0, _("field `%s' in category `%s' undefined"),
"noexpr", "LC_MESSAGES");
else
{
int result;
regex_t re;
/* Test whether it are correct regular expressions. */
result = regcomp (&re, messages->noexpr, REG_EXTENDED);
if (result != 0)
{
char errbuf[BUFSIZ];
(void) regerror (result, &re, errbuf, BUFSIZ);
error (0, 0, _("\
no correct regular expression for field `%s' in category `%s': %s"),
"noexpr", "LC_MESSAGES", errbuf);
}
}
}
void
messages_output (struct localedef_t *locale, const char *output_path)
{
struct locale_messages_t *messages
= locale->categories[LC_MESSAGES].messages;
struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES)];
struct locale_file data;
u32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES)];
size_t cnt = 0;
if ((locale->binary & (1 << LC_MESSAGES)) != 0)
{
iov[0].iov_base = messages;
iov[0].iov_len = locale->len[LC_MESSAGES];
write_locale_data (output_path, "LC_MESSAGES", 1, iov);
return;
}
data.magic = LIMAGIC (LC_MESSAGES);
data.n = _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES);
iov[cnt].iov_base = (void *) &data;
iov[cnt].iov_len = sizeof (data);
++cnt;
iov[cnt].iov_base = (void *) idx;
iov[cnt].iov_len = sizeof (idx);
++cnt;
idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
iov[cnt].iov_base = (void *) (messages->yesexpr ?: "");
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) (messages->noexpr ?: "");
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) (messages->yesstr ?: "");
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) (messages->nostr ?: "");
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
assert (cnt + 1 == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES));
write_locale_data (output_path, "LC_MESSAGES",
2 + _NL_ITEM_INDEX (_NL_NUM_LC_MESSAGES), iov);
}
void
messages_add (struct linereader *lr, struct localedef_t *locale,
enum token_t tok, struct token *code,
struct charset_t *charset)
{
struct locale_messages_t *messages
= locale->categories[LC_MESSAGES].messages;
switch (tok)
{
case tok_yesexpr:
if (code->val.str.start == NULL)
{
lr_error (lr, _("unknown character in field `%s' of category `%s'"),
"yesexpr", "LC_MESSAGES");
messages->yesexpr = "";
}
else
messages->yesexpr = code->val.str.start;
break;
case tok_noexpr:
if (code->val.str.start == NULL)
{
lr_error (lr, _("unknown character in field `%s' of category `%s'"),
"noexpr", "LC_MESSAGES");
messages->noexpr = "";
}
else
messages->noexpr = code->val.str.start;
break;
case tok_yesstr:
if (code->val.str.start == NULL)
{
lr_error (lr, _("unknown character in field `%s' of category `%s'"),
"yesstr", "LC_MESSAGES");
messages->yesstr = "";
}
else
messages->yesstr = code->val.str.start;
break;
case tok_nostr:
if (code->val.str.start == NULL)
{
lr_error (lr, _("unknown character in field `%s' of category `%s'"),
"nostr", "LC_MESSAGES");
messages->nostr = "";
}
else
messages->nostr = code->val.str.start;
break;
default:
assert (! "unknown token in category `LC_MESSAGES': should not happen");
}
}

View file

@ -0,0 +1,385 @@
/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <langinfo.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
/* Undefine following line in production version. */
/* #define NDEBUG 1 */
#include <assert.h>
#include "locales.h"
#include "localeinfo.h"
#include "stringtrans.h"
void *xmalloc (size_t __n);
void *xrealloc (void *__ptr, size_t __n);
/* The real definition of the struct for the LC_NUMERIC locale. */
struct locale_monetary_t
{
const char *int_curr_symbol;
const char *currency_symbol;
const char *mon_decimal_point;
const char *mon_thousands_sep;
char *mon_grouping;
size_t mon_grouping_max;
size_t mon_grouping_act;
const char *positive_sign;
const char *negative_sign;
signed char int_frac_digits;
signed char frac_digits;
signed char p_cs_precedes;
signed char p_sep_by_space;
signed char n_cs_precedes;
signed char n_sep_by_space;
signed char p_sign_posn;
signed char n_sign_posn;
};
/* The content iof the field int_curr_symbol has to be taken from
ISO-4217. We test for correct values. */
#define DEFINE_INT_CURR(str) str,
static const char *const valid_int_curr[] =
{
# include "../iso-4217.def"
};
#define NR_VALID_INT_CURR ((sizeof (valid_int_curr) \
/ sizeof (valid_int_curr[0])))
#undef DEFINE_INT_CURR
/* Prototypes for local functions. */
static int curr_strcmp(const char *s1, const char **s2);
void
monetary_startup (struct linereader *lr, struct localedef_t *locale,
struct charset_t *charset)
{
struct locale_monetary_t *monetary;
/* It is important that we always use UCS1 encoding for strings now. */
encoding_method = ENC_UCS1;
locale->categories[LC_MONETARY].monetary = monetary =
(struct locale_monetary_t *) xmalloc (sizeof (struct locale_monetary_t));
memset (monetary, '\0', sizeof (struct locale_monetary_t));
monetary->mon_grouping_max = 80;
monetary->mon_grouping =
(char *) xmalloc (monetary->mon_grouping_max);
monetary->mon_grouping_act = 0;
monetary->int_frac_digits = -2;
monetary->frac_digits = -2;
monetary->p_cs_precedes = -2;
monetary->p_sep_by_space = -2;
monetary->n_cs_precedes = -2;
monetary->n_sep_by_space = -2;
monetary->p_sign_posn = -2;
monetary->n_sign_posn = -2;
}
void
monetary_finish (struct localedef_t *locale)
{
struct locale_monetary_t *monetary
= locale->categories[LC_MONETARY].monetary;
#define TEST_ELEM(cat) \
if (monetary->cat == NULL) \
error (0, 0, _("field `%s' in category `%s' not defined"), \
#cat, "LC_MONETARY")
TEST_ELEM (int_curr_symbol);
TEST_ELEM (currency_symbol);
TEST_ELEM (mon_decimal_point);
TEST_ELEM (mon_thousands_sep);
TEST_ELEM (positive_sign);
TEST_ELEM (negative_sign);
/* The international currency symbol must come from ISO 4217. */
if (monetary->int_curr_symbol != NULL)
{
if (strlen (monetary->int_curr_symbol) != 4)
error (0, 0, _("\
value of field `int_curr_symbol' in category `LC_MONETARY' has wrong length"));
else if (bsearch (monetary->int_curr_symbol, valid_int_curr,
NR_VALID_INT_CURR, sizeof (const char *),
(comparison_fn_t) curr_strcmp) == NULL)
error (0, 0, _("\
value of field `int_curr_symbol' in category `LC_MONETARY' does \
not correspond to a valid name in ISO 4217"));
}
/* The decimal point must not be empty. This is not said explicitly
in POSIX but ANSI C (ISO/IEC 9899) says in 4.4.2.1 it has to be
!= "". */
if (monetary->mon_decimal_point[0] == '\0')
{
error (0, 0, _("\
value for field `%s' in category `%s' must not be the empty string"),
"mon_decimal_point", "LC_MONETARY");
}
if (monetary->mon_grouping_act == 0)
error (0, 0, _("field `%s' in category `%s' not defined"),
"mon_grouping", "LC_MONETARY");
#undef TEST_ELEM
#define TEST_ELEM(cat, min, max) \
if (monetary->cat == -2) \
error (0, 0, _("field `%s' in category `%s' not defined"), \
#cat, "LC_MONETARY"); \
else if (monetary->cat < min || monetary->cat > max) \
error (0, 0, _("\
value for field `%s' in category `%s' must be in range %d...%d"), \
#cat, "LC_MONETARY", min, max)
TEST_ELEM (int_frac_digits, -128, 127); /* No range check. */
TEST_ELEM (frac_digits, -128, 127); /* No range check. */
TEST_ELEM (p_cs_precedes, -1, 1);
TEST_ELEM (p_sep_by_space, -1, 2);
TEST_ELEM (n_cs_precedes, -1, 1);
TEST_ELEM (n_sep_by_space, -1, 2);
TEST_ELEM (p_sign_posn, -1, 4);
TEST_ELEM (n_sign_posn, -1, 4);
}
void
monetary_output (struct localedef_t *locale, const char *output_path)
{
struct locale_monetary_t *monetary
= locale->categories[LC_MONETARY].monetary;
struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)];
struct locale_file data;
u32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_MONETARY)];
size_t cnt = 0;
if ((locale->binary & (1 << LC_MONETARY)) != 0)
{
iov[0].iov_base = monetary;
iov[0].iov_len = locale->len[LC_MONETARY];
write_locale_data (output_path, "LC_MONETARY", 1, iov);
return;
}
data.magic = LIMAGIC (LC_MONETARY);
data.n = _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY);
iov[cnt].iov_base = (void *) &data;
iov[cnt].iov_len = sizeof (data);
++cnt;
iov[cnt].iov_base = (void *) idx;
iov[cnt].iov_len = sizeof (idx);
++cnt;
idx[cnt - 2] = iov[0].iov_len + iov[1].iov_len;
iov[cnt].iov_base = (void *) (monetary->int_curr_symbol ?: "");
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) (monetary->currency_symbol ?: "");
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) (monetary->mon_decimal_point ?: "");
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) (monetary->mon_thousands_sep ?: "");
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = alloca (monetary->mon_grouping_act + 1);
iov[cnt].iov_len = monetary->mon_grouping_act + 1;
memcpy (iov[cnt].iov_base, monetary->mon_grouping,
monetary->mon_grouping_act);
((char *) iov[cnt].iov_base)[monetary->mon_grouping_act] = '\0';
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) (monetary->positive_sign ?: "");
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) (monetary->negative_sign ?: "");
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) &monetary->int_frac_digits;
iov[cnt].iov_len = 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) &monetary->frac_digits;
iov[cnt].iov_len = 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) &monetary->p_cs_precedes;
iov[cnt].iov_len = 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) &monetary->p_sep_by_space;
iov[cnt].iov_len = 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) &monetary->n_cs_precedes;
iov[cnt].iov_len = 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) &monetary->n_sep_by_space;
iov[cnt].iov_len = 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) &monetary->p_sign_posn;
iov[cnt].iov_len = 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) &monetary->n_sign_posn;
iov[cnt].iov_len = 1;
assert (cnt + 1 == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY));
write_locale_data (output_path, "LC_MONETARY",
2 + _NL_ITEM_INDEX (_NL_NUM_LC_MONETARY), iov);
}
void
monetary_add (struct linereader *lr, struct localedef_t *locale,
enum token_t tok, struct token *code,
struct charset_t *charset)
{
struct locale_monetary_t *monetary
= locale->categories[LC_MONETARY].monetary;
switch (tok)
{
#define STR_ELEM(cat) \
case tok_##cat: \
if (monetary->cat != NULL) \
lr_error (lr, _("\
field `%s' in category `%s' declared more than once"), \
#cat, "LC_MONETARY"); \
else if (code->val.str.start == NULL) \
{ \
lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
#cat, "LC_MONETARY"); \
monetary->cat = ""; \
} \
else \
monetary->cat = code->val.str.start; \
break
STR_ELEM (int_curr_symbol);
STR_ELEM (currency_symbol);
STR_ELEM (mon_decimal_point);
STR_ELEM (mon_thousands_sep);
STR_ELEM (positive_sign);
STR_ELEM (negative_sign);
#define INT_ELEM(cat) \
case tok_##cat: \
if (monetary->cat != -2) \
lr_error (lr, _("\
field `%s' in category `%s' declared more than once"), \
#cat, "LC_MONETARY"); \
else \
monetary->cat = code->val.num; \
break
INT_ELEM (int_frac_digits);
INT_ELEM (frac_digits);
INT_ELEM (p_cs_precedes);
INT_ELEM (p_sep_by_space);
INT_ELEM (n_cs_precedes);
INT_ELEM (n_sep_by_space);
INT_ELEM (p_sign_posn);
INT_ELEM (n_sign_posn);
case tok_mon_grouping:
if (monetary->mon_grouping_act == monetary->mon_grouping_max)
{
monetary->mon_grouping_max *= 2;
monetary->mon_grouping =
(char *) xrealloc (monetary->mon_grouping,
monetary->mon_grouping_max);
}
if (monetary->mon_grouping[monetary->mon_grouping_act - 1]
== '\177')
lr_error (lr, _("\
`-1' must be last entry in `%s' field in `%s' category"),
"mon_grouping", "LC_MONETARY");
else
{
if (code->tok == tok_minus1)
monetary->mon_grouping[monetary->mon_grouping_act++] = '\177';
else if (code->val.num == 0)
lr_error (lr, _("\
values for field `%s' in category `%s' must not be zero"),
"mon_grouping", "LC_MONETARY");
else if (code->val.num > 126)
lr_error (lr, _("\
values for field `%s' in category `%s' must be smaller than 127"),
"mon_grouping", "LC_MONETARY");
else
monetary->mon_grouping[monetary->mon_grouping_act++]
= code->val.num;
}
break;
default:
assert (! "unknown token in category `LC_MONETARY': should not happen");
}
}
static int
curr_strcmp(const char *s1, const char **s2)
{
return strcmp (s1, *s2);
}

View file

@ -0,0 +1,208 @@
/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <langinfo.h>
#include <string.h>
/* Undefine following line in production version. */
/* #define NDEBUG 1 */
#include <assert.h>
#include "locales.h"
#include "localeinfo.h"
#include "stringtrans.h"
void *xmalloc (size_t __n);
void *xrealloc (void *__ptr, size_t __n);
/* The real definition of the struct for the LC_NUMERIC locale. */
struct locale_numeric_t
{
const char *decimal_point;
const char *thousands_sep;
char *grouping;
size_t grouping_max;
size_t grouping_act;
};
void
numeric_startup (struct linereader *lr, struct localedef_t *locale,
struct charset_t *charset)
{
struct locale_numeric_t *numeric;
/* It is important that we always use UCS1 encoding for strings now. */
encoding_method = ENC_UCS1;
locale->categories[LC_NUMERIC].numeric = numeric =
(struct locale_numeric_t *) xmalloc (sizeof (struct locale_numeric_t));
memset (numeric, '\0', sizeof (struct locale_numeric_t));
numeric->grouping_max = 80;
numeric->grouping = (char *) xmalloc (numeric->grouping_max);
numeric->grouping_act = 0;
}
void
numeric_finish (struct localedef_t *locale)
{
struct locale_numeric_t *numeric = locale->categories[LC_NUMERIC].numeric;
#define TEST_ELEM(cat) \
if (numeric->cat == NULL) \
error (0, 0, _("field `%s' in category `%s' not defined"), \
#cat, "LC_NUMERIC")
TEST_ELEM (decimal_point);
TEST_ELEM (thousands_sep);
/* The decimal point must not be empty. This is not said explicitly
in POSIX but ANSI C (ISO/IEC 9899) says in 4.4.2.1 it has to be
!= "". */
if (numeric->decimal_point[0] == '\0')
{
error (0, 0, _("\
value for field `%s' in category `%s' must not be the empty string"),
"decimal_point", "LC_NUMERIC");
}
if (numeric->grouping_act == 0)
error (0, 0, _("field `%s' in category `%s' not defined"),
"grouping", "LC_NUMERIC");
}
void
numeric_output (struct localedef_t *locale, const char *output_path)
{
struct locale_numeric_t *numeric = locale->categories[LC_NUMERIC].numeric;
struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC)];
struct locale_file data;
u32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC)];
size_t cnt = 0;
if ((locale->binary & (1 << LC_NUMERIC)) != 0)
{
iov[0].iov_base = numeric;
iov[0].iov_len = locale->len[LC_NUMERIC];
write_locale_data (output_path, "LC_NUMERIC", 1, iov);
return;
}
data.magic = LIMAGIC (LC_NUMERIC);
data.n = _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC);
iov[cnt].iov_base = (void *) &data;
iov[cnt].iov_len = sizeof (data);
++cnt;
iov[cnt].iov_base = (void *) idx;
iov[cnt].iov_len = sizeof (idx);
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) (numeric->decimal_point ?: "");
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = (void *) (numeric->thousands_sep ?: "");
iov[cnt].iov_len = strlen (iov[cnt].iov_base) + 1;
++cnt;
idx[cnt - 2] = idx[cnt - 3] + iov[cnt - 1].iov_len;
iov[cnt].iov_base = alloca (numeric->grouping_act + 1);
iov[cnt].iov_len = numeric->grouping_act + 1;
memcpy (iov[cnt].iov_base, numeric->grouping, numeric->grouping_act);
((char *) iov[cnt].iov_base)[numeric->grouping_act] = '\0';
assert (cnt + 1 == 2 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC));
write_locale_data (output_path, "LC_NUMERIC",
2 + _NL_ITEM_INDEX (_NL_NUM_LC_NUMERIC), iov);
}
void
numeric_add (struct linereader *lr, struct localedef_t *locale,
enum token_t tok, struct token *code,
struct charset_t *charset)
{
struct locale_numeric_t *numeric = locale->categories[LC_NUMERIC].numeric;
switch (tok)
{
#define STR_ELEM(cat) \
case tok_##cat: \
if (numeric->cat != NULL) \
lr_error (lr, _("\
field `%s' in category `%s' declared more than once"), \
#cat, "LC_NUMERIC"); \
else if (code->val.str.start == NULL) \
{ \
lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
#cat, "LC_NUMERIC"); \
numeric->cat = ""; \
} \
else \
numeric->cat = code->val.str.start; \
break
STR_ELEM (decimal_point);
STR_ELEM (thousands_sep);
case tok_grouping:
if (numeric->grouping_act == numeric->grouping_max)
{
numeric->grouping_max *= 2;
numeric->grouping = (char *) xrealloc (numeric->grouping,
numeric->grouping_max);
}
if (numeric->grouping_act > 0
&& (numeric->grouping[numeric->grouping_act - 1] == '\177'))
{
lr_error (lr, _("\
`-1' must be last entry in `%s' field in `%s' category"),
"grouping", "LC_NUMERIC");
--numeric->grouping_act;
}
if (code->tok == tok_minus1)
numeric->grouping[numeric->grouping_act++] = '\177';
else if (code->val.num > 126)
lr_error (lr, _("\
values for field `%s' in category `%s' must be smaller than 127"),
"grouping", "LC_NUMERIC");
else
numeric->grouping[numeric->grouping_act++] = code->val.num;
break;
default:
assert (! "unknown token in category `LC_NUMERIC': should not happen");
}
}

310
locale/programs/ld-time.c Normal file
View file

@ -0,0 +1,310 @@
/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <langinfo.h>
#include <string.h>
/* Undefine following line in production version. */
/* #define NDEBUG 1 */
#include <assert.h>
#include "locales.h"
#include "localeinfo.h"
#include "stringtrans.h"
void *xmalloc (size_t __n);
/* The real definition of the struct for the LC_TIME locale. */
struct locale_time_t
{
const char *abday[7];
size_t cur_num_abday;
const char *day[7];
size_t cur_num_day;
const char *abmon[12];
size_t cur_num_abmon;
const char *mon[12];
size_t cur_num_mon;
const char *am_pm[2];
size_t cur_num_am_pm;
const char *d_t_fmt;
const char *d_fmt;
const char *t_fmt;
const char *t_fmt_ampm;
const char *era;
const char *era_year;
const char *era_d_t_fmt;
const char *era_t_fmt;
const char *era_d_fmt;
const char *alt_digits[100];
size_t cur_num_alt_digits;
};
void
time_startup (struct linereader *lr, struct localedef_t *locale,
struct charset_t *charset)
{
struct locale_time_t *time;
/* It is important that we always use UCS1 encoding for strings now. */
encoding_method = ENC_UCS1;
locale->categories[LC_TIME].time = time =
(struct locale_time_t *) xmalloc (sizeof (struct locale_time_t));
memset (time, '\0', sizeof (struct locale_time_t));
}
void
time_finish (struct localedef_t *locale)
{
struct locale_time_t *time = locale->categories[LC_TIME].time;
#define TESTARR_ELEM(cat, max) \
if (time->cur_num_##cat == 0) \
error (0, 0, _("field `%s' in category `%s' not defined"), \
#cat, "LC_TIME"); \
else if (time->cur_num_##cat != max) \
error (0, 0, _("field `%s' in category `%s' has not enough values"), \
#cat, "LC_TIME")
TESTARR_ELEM (abday, 7);
TESTARR_ELEM (day, 7);
TESTARR_ELEM (abmon, 12);
TESTARR_ELEM (mon, 12);
TESTARR_ELEM (am_pm, 2);
#define TEST_ELEM(cat) \
if (time->cat == NULL) \
error (0, 0, _("field `%s' in category `%s' not defined"), \
#cat, "LC_TIME")
TEST_ELEM (d_t_fmt);
TEST_ELEM (d_fmt);
TEST_ELEM (t_fmt);
TEST_ELEM (t_fmt_ampm);
}
void
time_output (struct localedef_t *locale, const char *output_path)
{
struct locale_time_t *time = locale->categories[LC_TIME].time;
struct iovec iov[2 + _NL_ITEM_INDEX (_NL_NUM_LC_TIME)
+ time->cur_num_alt_digits];
struct locale_file data;
u32_t idx[_NL_ITEM_INDEX (_NL_NUM_LC_TIME)];
size_t cnt, last_idx, num;
if ((locale->binary & (1 << LC_TIME)) != 0)
{
iov[0].iov_base = time;
iov[0].iov_len = locale->len[LC_TIME];
write_locale_data (output_path, "LC_TIME", 1, iov);
return;
}
data.magic = LIMAGIC (LC_TIME);
data.n = _NL_ITEM_INDEX (_NL_NUM_LC_TIME);
iov[0].iov_base = (void *) &data;
iov[0].iov_len = sizeof (data);
iov[1].iov_base = (void *) idx;
iov[1].iov_len = sizeof (idx);
idx[0] = iov[0].iov_len + iov[1].iov_len;
/* The ab'days. */
for (cnt = 0; cnt <= _NL_ITEM_INDEX (ABDAY_7); ++cnt)
{
iov[2 + cnt].iov_base =
(void *) (time->abday[cnt - _NL_ITEM_INDEX (ABDAY_1)] ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
}
/* The days. */
for (; cnt <= _NL_ITEM_INDEX (DAY_7); ++cnt)
{
iov[2 + cnt].iov_base =
(void *) (time->day[cnt - _NL_ITEM_INDEX (DAY_1)] ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
}
/* The ab'mons. */
for (; cnt <= _NL_ITEM_INDEX (ABMON_12); ++cnt)
{
iov[2 + cnt].iov_base =
(void *) (time->abmon[cnt - _NL_ITEM_INDEX (ABMON_1)] ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
}
/* The mons. */
for (; cnt <= _NL_ITEM_INDEX (MON_12); ++cnt)
{
iov[2 + cnt].iov_base =
(void *) (time->mon[cnt - _NL_ITEM_INDEX (MON_1)] ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
}
/* AM/PM. */
for (; cnt <= _NL_ITEM_INDEX (PM_STR); ++cnt)
{
iov[2 + cnt].iov_base =
(void *) (time->am_pm[cnt - _NL_ITEM_INDEX (AM_STR)] ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
}
iov[2 + cnt].iov_base = (void *) (time->d_t_fmt ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
++cnt;
iov[2 + cnt].iov_base = (void *) (time->d_fmt ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
++cnt;
iov[2 + cnt].iov_base = (void *) (time->t_fmt ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
++cnt;
iov[2 + cnt].iov_base = (void *) (time->t_fmt_ampm ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
++cnt;
iov[2 + cnt].iov_base = (void *) (time->era ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
++cnt;
iov[2 + cnt].iov_base = (void *) (time->era_year ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
++cnt;
iov[2 + cnt].iov_base = (void *) (time->era_d_fmt ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + cnt] = idx[cnt] + iov[2 + cnt].iov_len;
last_idx = ++cnt;
idx[1 + last_idx] = idx[last_idx];
for (num = 0; num < time->cur_num_alt_digits; ++num, ++cnt)
{
iov[2 + cnt].iov_base = (void *) (time->alt_digits[num] ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + last_idx] += iov[2 + cnt].iov_len;
}
++last_idx;
iov[2 + cnt].iov_base = (void *) (time->era_d_t_fmt ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
idx[1 + last_idx] = idx[last_idx] + iov[2 + cnt].iov_len;
++cnt;
iov[2 + cnt].iov_base = (void *) (time->era_d_fmt ?: "");
iov[2 + cnt].iov_len = strlen (iov[2 + cnt].iov_base) + 1;
++cnt;
assert (cnt == (_NL_ITEM_INDEX (_NL_NUM_LC_TIME) - 1
+ time->cur_num_alt_digits));
write_locale_data (output_path, "LC_TIME", 2 + cnt, iov);
}
void
time_add (struct linereader *lr, struct localedef_t *locale,
enum token_t tok, struct token *code,
struct charset_t *charset)
{
struct locale_time_t *time = locale->categories[LC_TIME].time;
switch (tok)
{
#define STRARR_ELEM(cat, max) \
case tok_##cat: \
if (time->cur_num_##cat >= max) \
lr_error (lr, _(" \
too many values for field `%s' in category `LC_TIME'"), \
#cat, "LC_TIME"); \
else if (code->val.str.start == NULL) \
{ \
lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
#cat, "LC_TIME"); \
time->cat[time->cur_num_##cat++] = ""; \
} \
else \
time->cat[time->cur_num_##cat++] \
= code->val.str.start; \
break
STRARR_ELEM (abday, 7);
STRARR_ELEM (day, 7);
STRARR_ELEM (abmon, 12);
STRARR_ELEM (mon, 12);
STRARR_ELEM (am_pm, 2);
STRARR_ELEM (alt_digits, 100);
#define STR_ELEM(cat) \
case tok_##cat: \
if (time->cat != NULL) \
lr_error (lr, _("\
field `%s' in category `%s' declared more than once"), \
#cat, "LC_TIME"); \
else if (code->val.str.start == NULL) \
{ \
lr_error (lr, _("unknown character in field `%s' of category `%s'"),\
#cat, "LC_TIME"); \
time->cat = ""; \
} \
else \
time->cat = code->val.str.start; \
break
STR_ELEM (d_t_fmt);
STR_ELEM (d_fmt);
STR_ELEM (t_fmt);
STR_ELEM (t_fmt_ampm);
STR_ELEM (era);
STR_ELEM (era_year);
STR_ELEM (era_d_t_fmt);
STR_ELEM (era_d_fmt);
STR_ELEM (era_t_fmt);
default:
assert (! "unknown token in category `LC_TIME': should not happen");
}
}

View file

@ -0,0 +1,579 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <libintl.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "error.h"
#include "linereader.h"
#include "charset.h"
#include "stringtrans.h"
void *xmalloc (size_t __n);
void *xrealloc (void *__p, size_t __n);
char *xstrdup (const char *__str);
static struct token *get_toplvl_escape (struct linereader *lr);
static struct token *get_symname (struct linereader *lr);
static struct token *get_ident (struct linereader *lr);
static struct token *get_string (struct linereader *lr,
const struct charset_t *charset);
struct linereader *
lr_open (const char *fname, kw_hash_fct_t hf)
{
FILE *fp;
struct linereader *result;
int n;
if (fname == NULL || strcmp (fname, "-") == 0
|| strcmp (fname, "/dev/stdin") == 0)
fp = stdin;
else
{
fp = fopen (fname, "r");
if (fp == NULL)
return NULL;
}
result = (struct linereader *) xmalloc (sizeof (*result));
result->fp = fp;
result->fname = xstrdup (fname);
result->buf = NULL;
result->bufsize = 0;
result->lineno = 1;
result->idx = 0;
result->comment_char = '#';
result->escape_char = '\\';
result->translate_strings = 1;
n = getdelim (&result->buf, &result->bufsize, '\n', result->fp);
if (n < 0)
{
int save = errno;
fclose (result->fp);
free (result);
errno = save;
return NULL;
}
if (n > 1 && result->buf[n - 2] == '\\' && result->buf[n - 1] == '\n')
n -= 2;
result->buf[n] = '\0';
result->bufact = n;
result->hash_fct = hf;
return result;
}
int
lr_eof (struct linereader *lr)
{
return lr->bufact = 0;
}
void
lr_close (struct linereader *lr)
{
fclose (lr->fp);
free (lr->buf);
free (lr);
}
int
lr_next (struct linereader *lr)
{
int n;
n = getdelim (&lr->buf, &lr->bufsize, '\n', lr->fp);
if (n < 0)
return -1;
++lr->lineno;
if (n > 1 && lr->buf[n - 2] == lr->escape_char && lr->buf[n - 1] == '\n')
{
/* An escaped newline character is substituted with a single <SP>. */
--n;
lr->buf[n - 1] = ' ';
}
lr->buf[n] = '\0';
lr->bufact = n;
lr->idx = 0;
return 0;
}
/* Defined in error.c. */
/* This variable is incremented each time `error' is called. */
extern unsigned int error_message_count;
/* The calling program should define program_name and set it to the
name of the executing program. */
extern char *program_name;
struct token *
lr_token (struct linereader *lr, const struct charset_t *charset)
{
int ch;
while (1)
{
do
{
ch = lr_getc (lr);
if (ch == '\n')
{
lr->token.tok = tok_eol;
return &lr->token;
}
}
while (isspace (ch));
if (ch == EOF)
{
lr->token.tok = tok_eof;
return &lr->token;
};
if (ch != lr->comment_char)
break;
/* Ignore rest of line. */
lr_ignore_rest (lr, 0);
lr->token.tok = tok_eol;
return &lr->token;
}
/* Match escape sequences. */
if (ch == lr->escape_char)
return get_toplvl_escape (lr);
/* Match ellipsis. */
if (ch == '.' && strncmp (&lr->buf[lr->idx], "..", 2) == 0)
{
lr_getc (lr);
lr_getc (lr);
lr->token.tok = tok_ellipsis;
return &lr->token;
}
switch (ch)
{
case '<':
return get_symname (lr);
case '0' ... '9':
lr->token.tok = tok_number;
lr->token.val.num = ch - '0';
while (isdigit (ch = lr_getc (lr)))
{
lr->token.val.num *= 10;
lr->token.val.num += ch - '0';
}
if (isalpha (ch))
lr_error (lr, _("garbage at end of digit"));
lr_ungetn (lr, 1);
return &lr->token;
case ';':
lr->token.tok = tok_semicolon;
return &lr->token;
case ',':
lr->token.tok = tok_comma;
return &lr->token;
case '(':
lr->token.tok = tok_open_brace;
return &lr->token;
case ')':
lr->token.tok = tok_close_brace;
return &lr->token;
case '"':
return get_string (lr, charset);
case '-':
ch = lr_getc (lr);
if (ch == '1')
{
lr->token.tok = tok_minus1;
return &lr->token;
}
lr_ungetn (lr, 2);
break;
}
return get_ident (lr);
}
static struct token *
get_toplvl_escape (struct linereader *lr)
{
/* This is supposed to be a numeric value. We return the
numerical value and the number of bytes. */
size_t start_idx = lr->idx - 1;
unsigned int value = 0;
int nbytes = 0;
int ch;
do
{
unsigned int byte = 0;
unsigned int base = 8;
ch = lr_getc (lr);
if (ch == 'd')
{
base = 10;
ch = lr_getc (lr);
}
else if (ch == 'x')
{
base = 16;
ch = lr_getc (lr);
}
if ((base == 16 && !isxdigit (ch))
|| (base != 16 && (ch < '0' || ch >= '0' + base)))
{
esc_error:
lr->token.val.str.start = &lr->buf[start_idx];
while (ch != EOF || !isspace (ch))
ch = lr_getc (lr);
lr->token.val.str.len = lr->idx - start_idx;
lr->token.tok = tok_error;
return &lr->token;
}
if (isdigit (ch))
byte = ch - '0';
else
byte = tolower (ch) - 'a' + 10;
ch = lr_getc (lr);
if ((base == 16 && !isxdigit (ch))
|| (base != 16 && (ch < '0' || ch >= '0' + base)))
goto esc_error;
byte *= base;
if (isdigit (ch))
byte += ch - '0';
else
byte += tolower (ch) - 'a' + 10;
ch = lr_getc (lr);
if (base != 16 && isdigit (ch))
{
byte *= base;
base += ch - '0';
ch = lr_getc (lr);
}
value *= 256;
value += byte;
++nbytes;
}
while (ch == lr->escape_char && nbytes < 4);
if (!isspace (ch))
lr_error (lr, _("garbage at end of character code specification"));
lr_ungetn (lr, 1);
lr->token.tok = tok_charcode;
lr->token.val.charcode.val = value;
lr->token.val.charcode.nbytes = nbytes;
return &lr->token;
}
#define ADDC(ch) \
do \
{ \
if (bufact == bufmax) \
{ \
bufmax *= 2; \
buf = xrealloc (buf, bufmax); \
} \
buf[bufact++] = (ch); \
} \
while (0)
static struct token *
get_symname (struct linereader *lr)
{
/* Symbol in brackets. We must distinguish three kinds:
1. reserved words
2. ISO 10646 position values
3. all other. */
char *buf;
size_t bufact = 0;
size_t bufmax = 56;
const struct keyword_t *kw;
int ch;
buf = (char *) xmalloc (bufmax);
do
{
ch = lr_getc (lr);
if (ch == lr->escape_char)
{
int c2 = lr_getc (lr);
ADDC (c2);
if (c2 == '\n')
ch = '\n';
}
else
ADDC (ch);
}
while (ch != '>' && ch != '\n');
if (ch == '\n')
lr_error (lr, _("unterminated symbolic name"));
/* Test for ISO 10646 position value. */
if (buf[0] == 'U' && (bufact == 6 || bufact == 10))
{
char *cp = buf + 1;
while (cp < &buf[bufact - 1] && isxdigit (*cp))
++cp;
if (cp == &buf[bufact - 1])
{
/* Yes, it is. */
lr->token.tok = bufact == 6 ? tok_ucs2 : tok_ucs4;
lr->token.val.charcode.val = strtoul (buf, NULL, 16);
lr->token.val.charcode.nbytes = lr->token.tok == tok_ucs2 ? 2 : 4;
return &lr->token;
}
}
/* It is a symbolic name. Test for reserved words. */
kw = lr->hash_fct (buf, bufact - 1);
if (kw != NULL && kw->symname_or_ident == 1)
{
lr->token.tok = kw->token;
free (buf);
}
else
{
lr->token.tok = tok_bsymbol;
buf[bufact] = '\0';
buf = xrealloc (buf, bufact + 1);
lr->token.val.str.start = buf;
lr->token.val.str.len = bufact - 1;
}
return &lr->token;
}
static struct token *
get_ident (struct linereader *lr)
{
char *buf;
size_t bufact;
size_t bufmax = 56;
const struct keyword_t *kw;
int ch;
buf = xmalloc (bufmax);
bufact = 0;
ADDC (lr->buf[lr->idx - 1]);
while (!isspace ((ch = lr_getc (lr))) && ch != '"' && ch != ';'
&& ch != '<' && ch != ',')
/* XXX Handle escape sequences? */
ADDC (ch);
lr_ungetn (lr, 1);
kw = lr->hash_fct (buf, bufact);
if (kw != NULL && kw->symname_or_ident == 0)
{
lr->token.tok = kw->token;
free (buf);
}
else
{
lr->token.tok = tok_ident;
buf[bufact] = '\0';
buf = xrealloc (buf, bufact + 1);
lr->token.val.str.start = buf;
lr->token.val.str.len = bufact;
}
return &lr->token;
}
static struct token *
get_string (struct linereader *lr, const struct charset_t *charset)
{
int illegal_string = 0;
char *buf, *cp;
size_t bufact;
size_t bufmax = 56;
int ch;
buf = xmalloc (bufmax);
bufact = 0;
while ((ch = lr_getc (lr)) != '"' && ch != '\n' && ch != EOF)
if (ch != '<' || charset == NULL)
{
if (ch == lr->escape_char)
{
ch = lr_getc (lr);
if (ch == '\n' || ch == EOF)
break;
}
ADDC (ch);
}
else
{
/* We have to get the value of the symbol. */
unsigned int value;
size_t startidx = bufact;
if (!lr->translate_strings)
ADDC ('<');
while ((ch = lr_getc (lr)) != '>' && ch != '\n' && ch != EOF)
{
if (ch == lr->escape_char)
{
ch = lr_getc (lr);
if (ch == '\n' || ch == EOF)
break;
}
ADDC (ch);
}
if (ch == '\n' || ch == EOF)
lr_error (lr, _("unterminated string"));
else
if (!lr->translate_strings)
ADDC ('>');
if (lr->translate_strings)
{
value = charset_find_value (charset, &buf[startidx],
bufact - startidx);
if (value == ILLEGAL_CHAR_VALUE)
illegal_string = 1;
bufact = startidx;
if (bufmax - bufact < 8)
{
bufmax *= 2;
buf = (char *) xrealloc (buf, bufmax);
}
cp = &buf[bufact];
if (encode_char (value, &cp))
illegal_string = 1;
bufact = cp - buf;
}
}
/* Catch errors with trailing escape character. */
if (bufact > 0 && buf[bufact - 1] == lr->escape_char
&& (bufact == 1 || buf[bufact - 2] != lr->escape_char))
{
lr_error (lr, _("illegal escape sequence at end of string"));
--bufact;
}
else if (ch == '\n' || ch == EOF)
lr_error (lr, _("unterminated string"));
/* Terminate string if necessary. */
if (lr->translate_strings)
{
cp = &buf[bufact];
if (encode_char (0, &cp))
illegal_string = 1;
bufact = cp - buf;
}
else
ADDC ('\0');
lr->token.tok = tok_string;
if (illegal_string)
{
free (buf);
lr->token.val.str.start = NULL;
lr->token.val.str.len = 0;
}
else
{
buf = xrealloc (buf, bufact + 1);
lr->token.val.str.start = buf;
lr->token.val.str.len = bufact;
}
return &lr->token;
}

View file

@ -0,0 +1,158 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifndef _LINEREADER_H
#define _LINEREADER_H 1
#include <ctype.h>
#include <libintl.h>
#include <stdio.h>
#include "error.h"
#include "locfile-token.h"
typedef const struct keyword_t *(*kw_hash_fct_t) (const char *, int);
struct charset_t;
struct token
{
enum token_t tok;
union
{
struct
{
char *start;
size_t len;
} str;
unsigned long int num;
struct
{
unsigned int val;
int nbytes;
} charcode;
} val;
};
struct linereader
{
FILE *fp;
const char *fname;
char *buf;
size_t bufsize;
size_t bufact;
size_t lineno;
size_t idx;
char comment_char;
char escape_char;
struct token token;
int translate_strings;
kw_hash_fct_t hash_fct;
};
/* Functions defined in linereader.c. */
struct linereader *lr_open (const char *fname, kw_hash_fct_t hf);
int lr_eof (struct linereader *lr);
void lr_close (struct linereader *lr);
int lr_next (struct linereader *lr);
struct token *lr_token (struct linereader *lr,
const struct charset_t *charset);
#define lr_error(lr, fmt, args...) \
error_at_line (0, 0, lr->fname, lr->lineno, fmt, ## args)
static inline int
lr_getc (struct linereader *lr)
{
if (lr->idx == lr->bufact)
{
if (lr->bufact != 0)
if (lr_next (lr) < 0)
return EOF;
if (lr->bufact == 0)
return EOF;
}
return lr->buf[lr->idx] == '\32' ? EOF : lr->buf[lr->idx++];
}
static inline int
lr_ungetc (struct linereader *lr, int ch)
{
if (lr->idx == 0)
return -1;
lr->buf[--lr->idx] = ch;
return 0;
}
static inline int
lr_ungetn (struct linereader *lr, int n)
{
if (lr->idx < n)
return -1;
lr->idx -= n;
return 0;
}
static inline void
lr_ignore_rest (struct linereader *lr, int verbose)
{
if (verbose)
{
while (isspace (lr->buf[lr->idx]) && lr->buf[lr->idx] != '\n'
&& lr->buf[lr->idx] != lr->comment_char)
if (lr->buf[lr->idx] == '\0')
{
if (lr_next (lr) < 0)
return;
}
else
++lr->idx;
if (lr->buf[lr->idx] != '\n' &&lr->buf[lr->idx] != lr->comment_char)
lr_error (lr, _("trailing garbage at end of line"));
}
/* Ignore continued line. */
while (lr->bufact > 0 && lr->buf[lr->bufact - 1] != '\n')
if (lr_next (lr) < 0)
break;
lr->idx = lr->bufact;
}
#endif /* linereader.h */

View file

@ -1,4 +1,4 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
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
@ -26,7 +26,8 @@ Cambridge, MA 02139, USA. */
#include <unistd.h>
#include <errno.h>
#include "localedef.h"
/*#include "localedef.h"*/
#include "localeinfo.h"
/* If set dump C code describing the current locale. */
@ -40,16 +41,16 @@ static int show_keyword_name;
/* Long options. */
static const struct option long_options[] =
{
{ "all-locales", no_argument, NULL, 'a' },
{ "category-name", no_argument, &show_category_name, 1 },
{ "charmaps", no_argument, NULL, 'm' },
{ "dump", no_argument, &do_dump, 1 },
{ "help", no_argument, NULL, 'h' },
{ "keyword-name", no_argument, &show_keyword_name, 1 },
{ "version", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 }
};
{
{ "all-locales", no_argument, NULL, 'a' },
{ "category-name", no_argument, &show_category_name, 1 },
{ "charmaps", no_argument, NULL, 'm' },
{ "dump", no_argument, &do_dump, 1 },
{ "help", no_argument, NULL, 'h' },
{ "keyword-name", no_argument, &show_keyword_name, 1 },
{ "version", no_argument, NULL, 'v' },
{ NULL, 0, NULL, 0 }
};
/* We don't have these constants defined because we don't use them. Give
@ -63,7 +64,18 @@ static const struct option long_options[] =
#define CTYPE_TOLOWER_EB 0
#define CTYPE_TOUPPER_EL 0
#define CTYPE_TOLOWER_EL 0
/* XXX Hack */
struct cat_item
{
int item_id;
const char *name;
enum { std, opt } status;
enum value_type value_type;
int min;
int max;
};
/* We have all categories defined in `categories.def'. Now construct
the description and data structure used for all categories. */
@ -73,7 +85,7 @@ static const struct option long_options[] =
NO_PAREN items \
};
#include "categories.def"
#include "locale/aux/categories.def"
#undef DEFINE_CATEGORY
static struct category category[] =
@ -81,7 +93,7 @@ static struct category category[] =
#define DEFINE_CATEGORY(category, name, items, postload, in, check, out) \
{ _NL_NUM_##category, name, NELEMS (category##_desc) - 1, \
category##_desc, NULL, NULL, NULL, out },
#include "categories.def"
#include "locale/aux/categories.def"
#undef DEFINE_CATEGORY
};
#define NCATEGORIES NELEMS (category)
@ -404,7 +416,7 @@ show_info (const char *name)
return;
}
for (item_no = 0; item_no < category[cat_no].number; ++item_no)
if (strcmp (name, category[cat_no].item_desc[item_no].name) == 0)
{
@ -530,10 +542,3 @@ dump_category (const char *name)
puts (" }\n};");
}
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/

461
locale/programs/localedef.c Normal file
View file

@ -0,0 +1,461 @@
/* Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <libintl.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "error.h"
#include "charset.h"
#include "locfile.h"
/* Undefine the following line in the production version. */
/* #define NDEBUG 1 */
#include <assert.h>
/* List of locale definition files which are used in `copy' instructions. */
struct copy_def_list_t
{
struct copy_def_list_t *next;
const char *name;
int mask;
struct localedef_t *locale;
struct
{
void *data;
size_t len;
} binary[6];
};
/* List of copied locales. */
struct copy_def_list_t *copy_list;
/* If this is defined be POSIX conform. */
int posix_conformance;
/* Name of the running program. */
const char *program_name;
/* If not zero give a lot more messages. */
int verbose;
/* Long options. */
static const struct option long_options[] =
{
{ "charmap", required_argument, NULL, 'f' },
{ "code-set-name", required_argument, NULL, 'u' },
{ "help", no_argument, NULL, 'h' },
{ "force", no_argument, NULL, 'c' },
{ "inputfile", required_argument, NULL, 'i' },
{ "posix", no_argument, &posix_conformance, 1 },
{ "verbose", no_argument, &verbose, 1},
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 }
};
/* Prototypes for global functions. */
void *xmalloc (size_t __n);
/* Prototypes for local functions. */
static void usage (int status) __attribute__ ((noreturn));
static void error_print (void);
static const char *construct_output_path (const char *path);
int
main (int argc, char *argv[])
{
int optchar;
int do_help = 0;
int do_version = 0;
int force_output = 0;
const char *charmap_file = NULL;
const char *input_file = NULL;
const char *ucs_csn = NULL;
const char *output_path;
int cannot_write_why;
struct charset_t *charset;
struct localedef_t *localedef;
struct copy_def_list_t *act_add_locdef;
/* Set initial values for global varaibles. */
copy_list = NULL;
posix_conformance = getenv ("POSIXLY_CORRECT") != NULL;
program_name = argv[0];
error_print_progname = error_print;
verbose = 0;
/* Set locale. Do not set LC_ALL because the other categories must
not be affected (acccording to POSIX.2). */
setlocale (LC_MESSAGES, "");
setlocale (LC_CTYPE, "");
/* Initialize the message catalog. */
#if 0
/* In the final version for glibc we can use the variable. */
textdomain (_libc_intl_domainname);
#else
textdomain ("SYS_libc");
#endif
while ((optchar = getopt_long (argc, argv, "cf:hi:u:vV", long_options, NULL))
!= EOF)
switch (optchar)
{
case '\0': /* Long option. */
break;
case 'c':
force_output = 1;
break;
case 'f':
charmap_file = optarg;
break;
case 'h':
do_help = 1;
break;
case 'i':
input_file = optarg;
break;
case 'u':
ucs_csn = optarg;
break;
case 'v':
verbose = 1;
break;
case 'V':
do_version = 1;
break;
default:
usage (4); /* A value >3 is forced by POSIX. */
break;
}
/* POSIX.2 requires to be verbose about missing characters in the
character map. */
verbose |= posix_conformance;
/* Version information is requested. */
if (do_version)
{
fprintf (stderr, "%s - GNU %s %s\n", program_name, PACKAGE, VERSION);
exit (0);
}
/* Help is requested. */
if (do_help)
/* Possible violation: POSIX.2 4.35.8 defines the return value 0 as
"No errors occured and the locale(s) were successfully created."
But giving a other value than 0 does not make sense here. It
is perhaps not that important because POSIX does not specify the
-h option for localedef. */
usage (0);
if (argc - optind != 1)
/* We need exactly one non-option parameter. */
usage (4);
/* The parameter describes the output path of the constructed files.
If the described files cannot be written return a NULL pointer. */
output_path = construct_output_path (argv[optind]);
cannot_write_why = errno;
/* Now that the parameters are processed we have to reset the local
ctype locale. (P1003.2 4.35.5.2) */
setlocale (LC_CTYPE, "POSIX");
/* Look whether the system really allows locale definitions. POSIX
defines error code 3 for this situation so I think it must be
a fatal error (see P1003.2 4.35.8). */
if (sysconf (_SC_2_LOCALEDEF) < 0)
error (3, 0, _("FATAL: system does not define `_POSIX2_LOCALEDEF'"));
/* Process charmap file. */
charset = charmap_read (charmap_file);
/* Now read the locale file. */
localedef = locfile_read (input_file, charset);
if (localedef->failed != 0)
error (4, errno, _("cannot open locale definition file `%s'"), input_file);
/* Perhaps we saw some `copy' instructions. Process the given list.
We use a very simple algorithm: we look up the list from the
beginning every time. */
do
{
int cat;
for (act_add_locdef = copy_list; act_add_locdef != NULL;
act_add_locdef = act_add_locdef->next)
{
for (cat = LC_COLLATE; cat <= LC_MESSAGES; ++cat)
if ((act_add_locdef->mask & (1 << cat)) != 0)
{
act_add_locdef->mask &= ~(1 << cat);
break;
}
if (cat <= LC_MESSAGES)
break;
}
if (act_add_locdef != NULL)
{
int avail = 0;
if (act_add_locdef->locale == NULL)
act_add_locdef->locale = locfile_read (act_add_locdef->name,
charset);
if (! act_add_locdef->locale->failed)
{
avail = act_add_locdef->locale->categories[cat].generic != NULL;
if (avail)
localedef->categories[cat].generic
= act_add_locdef->locale->categories[cat].generic;
}
if (! avail)
{
const char *locale_names[] = { "LC_COLLATE", "LC_CTYPE",
"LC_MONETARY", "LC_NUMERIC",
"LC_TIME", "LC_MESSAGES" };
char *fname;
int fd;
struct stat st;
asprintf (&fname, LOCALE_PATH "/%s/%s", act_add_locdef->name,
locale_names[cat]);
fd = open (fname, O_RDONLY);
if (fd == -1)
{
free (fname);
asprintf (&fname, LOCALE_PATH "/%s/%s/SYS_%s",
act_add_locdef->name, locale_names[cat],
locale_names[cat]);
fd = open (fname, O_RDONLY);
if (fd == -1)
error (5, 0, _("\
locale file `%s', used in `copy' statement, not found"),
act_add_locdef->name);
}
if (fstat (fd, &st) < 0)
error (5, errno, _("\
cannot `stat' locale file `%s'"),
fname);
localedef->len[cat] = st.st_size;
localedef->categories[cat].generic
= mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (localedef->categories[cat].generic == (void *) -1)
{
size_t left = st.st_size;
void *read_ptr;
localedef->categories[cat].generic
= xmalloc (st.st_size);
read_ptr = localedef->categories[cat].generic;
do
{
long int n;
n = read (fd, read_ptr, left);
if (n == 1)
error (5, errno, _("cannot read locale file `%s'"),
fname);
read_ptr += n;
left -= n;
}
while (left > 0);
}
close (fd);
free (fname);
localedef->binary |= 1 << cat;
}
}
}
while (act_add_locdef != NULL);
/* Check the categories we processed in source form. */
check_all_categories (localedef, charset);
/* We are now able to write the data files. If warning were given we
do it only if it is explicitly requested (--force). */
if (error_message_count == 0 || force_output != 0)
{
if (cannot_write_why != 0)
error (4, cannot_write_why, _("cannot write output files to `%s'"),
output_path);
else
write_all_categories (localedef, output_path);
}
else
error (4, 0, _("no output file produced because warning were issued"));
/* This exit status is prescribed by POSIX.2 4.35.7. */
exit (error_message_count != 0);
}
void
def_to_process (const char *name, int category)
{
struct copy_def_list_t *new, **rp;
for (rp = &copy_list; *rp != NULL; rp = &(*rp)->next)
if (strcmp (name, (*rp)->name) == 0)
break;
if (*rp == NULL)
{
size_t cnt;
*rp = (struct copy_def_list_t *) xmalloc (sizeof (**rp));
(*rp)->next = NULL;
(*rp)->name = name;
(*rp)->mask = 0;
(*rp)->locale = NULL;
for (cnt = 0; cnt < 6; ++cnt)
{
(*rp)->binary[cnt].data = NULL;
(*rp)->binary[cnt].len = 0;
}
}
new = *rp;
if ((new->mask & category) != 0)
/* We already have the information. This cannot happen. */
error (5, 0, _("\
category data requested more than once: should not happen"));
new->mask |= category;
}
/* Display usage information and exit. */
static void
usage (int status)
{
if (status != 0)
fprintf (stderr, _("Try `%s --help' for more information.\n"),
program_name);
else
printf (_("\
Usage: %s [OPTION]... name\n\
Mandatory arguments to long options are mandatory for short options too.\n\
-c, --force create output even if warning messages were issued\n\
-h, --help display this help and exit\n\
-f, --charmap=FILE symbolic character names defined in FILE\n\
-i, --inputfile=FILE source definitions are found in FILE\n\
-u, --code-set-name=NAME specify code set for mapping ISO 10646 elements\n\
-v, --verbose print more messages\n\
-V, --version output version information and exit\n\
--posix be strictly POSIX conform\n\
\n\
System's directory for character maps: %s\n\
locale files : %s\n"),
program_name, CHARMAP_PATH, LOCALE_PATH);
exit (status);
}
/* The address of this function will be assigned to the hook in the error
functions. */
static void
error_print ()
{
/* We don't want the program name to be printed in messages. Emacs'
compile.el does not like this. */
}
/* The parameter to localedef describes the output path. If it does
contain a '/' character it is a relativ path. Otherwise it names the
locale this definition is for. */
static const char *
construct_output_path (const char *path)
{
char *result;
if (strchr (path, '/') == NULL)
{
/* This is a system path. */
int path_max_len = pathconf (LOCALE_PATH, _PC_PATH_MAX) + 1;
result = (char *) xmalloc (path_max_len);
snprintf (result, path_max_len, "%s/%s", LOCALE_PATH, path);
}
else
{
char *t;
/* This is a user path. */
result = xmalloc (strlen (path) + 2);
t = stpcpy (result, path);
*t = '\0';
}
errno = 0;
if (euidaccess (result, W_OK) == -1)
/* Perhaps the directory does not exist now. Try to create it. */
if (errno == ENOENT)
{
errno = 0;
mkdir (result, 0777);
}
strcat (result, "/");
return result;
}

207
locale/programs/locales.h Normal file
View file

@ -0,0 +1,207 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifndef _LOCALES_H
#define _LOCALES_H
#include <ctype.h>
/* Undefine following line in production version. */
/* #define NDEBUG 1 */
#include <assert.h>
#include "linereader.h"
#include "locfile-token.h"
#include "charset.h"
#include "locfile.h"
#include "localeinfo.h"
/* Header of the locale data files. */
struct locale_file
{
int magic;
int n;
};
/* Handle LC_CTYPE category. */
static inline unsigned int
charclass_to_bit (enum token_t tok)
{
static unsigned int lastbit = _ISalnum;
switch (tok)
{
#define CLASS(name) case tok_##name: return _IS##name
CLASS (upper);
CLASS (lower);
CLASS (alpha);
CLASS (digit);
CLASS (alnum);
CLASS (space);
CLASS (cntrl);
CLASS (punct);
CLASS (graph);
CLASS (print);
CLASS (xdigit);
CLASS (blank);
#undef CLASS
case tok_string:
lastbit <<= 1;
if (lastbit == 0ul)
/* Exit status 2 means a limitation in the implementation is
exceeded. */
error (2, 0, _("too many character classes defined"));
return lastbit;
default:
assert (1 == 0);
}
return 0;
}
/* Remember name of newly created charclass. */
void ctype_startup (struct linereader *lr, struct localedef_t *locale,
struct charset_t *__charset);
void ctype_finish (struct localedef_t *__locale, struct charset_t *__charset);
void ctype_output (struct localedef_t *locale, const char *output_path);
int ctype_is_charclass (struct linereader *lr, struct localedef_t *locale,
const char *__name);
void ctype_class_new (struct linereader *lr, struct localedef_t *locale,
enum token_t __tok, struct token *__code,
struct charset_t *__charset);
void ctype_class_start (struct linereader *lr, struct localedef_t *locale,
enum token_t __tok, const char *__name,
struct charset_t *__charset);
void ctype_class_from (struct linereader *lr, struct localedef_t *locale,
struct token *__code, struct charset_t *__charset);
void ctype_class_to (struct linereader *lr, struct localedef_t *locale,
struct token *__code, struct charset_t *__charset);
void ctype_class_end (struct linereader *lr, struct localedef_t *locale);
int ctype_is_charmap (struct linereader *lr, struct localedef_t *locale,
const char *__name);
void ctype_map_new (struct linereader *lr, struct localedef_t *locale,
enum token_t __tok, struct token *__code,
struct charset_t *__charset);
void ctype_map_start (struct linereader *lr, struct localedef_t *locale,
enum token_t __tok, const char *__name,
struct charset_t *__charset);
void ctype_map_from (struct linereader *lr, struct localedef_t *locale,
struct token *__code, struct charset_t *__charset);
void ctype_map_to (struct linereader *lr, struct localedef_t *locale,
struct token *__code, struct charset_t *__charset);
void ctype_map_end (struct linereader *lr, struct localedef_t *locale);
/* Handle LC_COLLATE category. */
void collate_startup (struct linereader *__lr, struct localedef_t *__locale,
struct charset_t *__charset);
void collate_finish (struct localedef_t *__locale,
struct charset_t *__charset);
void collate_output (struct localedef_t *locale, const char *output_path);
void collate_element_to (struct linereader *__lr, struct localedef_t *__locale,
struct token *__code, struct charset_t *__charset);
void collate_element_from (struct linereader *__lr,
struct localedef_t *__locale, struct token *__code,
struct charset_t *__charset);
void collate_symbol (struct linereader *__lr, struct localedef_t *__locale,
struct token *__code, struct charset_t *__charset);
void collate_new_order (struct linereader *__lr, struct localedef_t *__locale,
enum coll_sort_rule __sort_rule);
void collate_build_arrays (struct linereader *__lr,
struct localedef_t *__locale);
int collate_order_elem (struct linereader *__lr, struct localedef_t *__locale,
struct token *__code, struct charset_t *__charset);
int collate_weight_bsymbol (struct linereader *__lr,
struct localedef_t *__locale,
struct token *__code, struct charset_t *__charset);
int collate_next_weight (struct linereader *__lr,
struct localedef_t *__locale);
int collate_simple_weight (struct linereader *__lr,
struct localedef_t *__locale,
struct token *__code, struct charset_t *__charset);
void collate_end_weight (struct linereader *__lr,
struct localedef_t *__locale);
/* Handle LC_MONETARY category. */
void monetary_startup (struct linereader *__lr, struct localedef_t *__locale,
struct charset_t *__charset);
void monetary_finish (struct localedef_t *__locale);
void monetary_output (struct localedef_t *locale, const char *output_path);
void monetary_add (struct linereader *lr, struct localedef_t *locale,
enum token_t __tok, struct token *__code,
struct charset_t *__charset);
/* Handle LC_NUMERIC category. */
void numeric_startup (struct linereader *__lr, struct localedef_t *__locale,
struct charset_t *__charset);
void numeric_finish (struct localedef_t *__locale);
void numeric_output (struct localedef_t *locale, const char *output_path);
void numeric_add (struct linereader *lr, struct localedef_t *locale,
enum token_t __tok, struct token *__code,
struct charset_t *__charset);
/* Handle LC_TIME category. */
void time_startup (struct linereader *__lr, struct localedef_t *__locale,
struct charset_t *__charset);
void time_finish (struct localedef_t *__locale);
void time_output (struct localedef_t *locale, const char *output_path);
void time_add (struct linereader *lr, struct localedef_t *locale,
enum token_t __tok, struct token *__code,
struct charset_t *__charset);
/* Handle LC_MESSAGES category. */
void messages_startup (struct linereader *__lr, struct localedef_t *__locale,
struct charset_t *__charset);
void messages_finish (struct localedef_t *__locale);
void messages_output (struct localedef_t *locale, const char *output_path);
void messages_add (struct linereader *lr, struct localedef_t *locale,
enum token_t __tok, struct token *__code,
struct charset_t *__charset);
#endif /* locales.h */

View file

@ -0,0 +1,99 @@
%{
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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 <string.h>
#include "locfile-token.h"
%}
struct keyword_t ;
%%
escape_char, tok_escape_char, 0
comment_char, tok_comment_char, 0
LC_CTYPE, tok_lc_ctype, 0
END, tok_end, 0
copy, tok_copy, 0
upper, tok_upper, 0
lower, tok_lower, 0
alpha, tok_alpha, 0
digit, tok_digit, 0
alnum, tok_alnum, 0
space, tok_space, 0
cntrl, tok_cntrl, 0
punct, tok_punct, 0
graph, tok_graph, 0
print, tok_print, 0
xdigit, tok_xdigit, 0
blank, tok_blank, 0
charclass, tok_charclass, 0
charmap, tok_charmap, 0
toupper, tok_toupper, 0
tolower, tok_tolower, 0
LC_COLLATE, tok_lc_collate, 0
collating-element, tok_collating_element, 0
collating-symbol, tok_collating_symbol, 0
order_start, tok_order_start, 0
order_end, tok_order_end, 0
from, tok_from, 0
forward, tok_forward, 0
backward, tok_backward, 0
position, tok_position, 0
UNDEFINED, tok_undefined, 0
IGNORE, tok_ignore, 0
LC_MONETARY, tok_lc_monetary, 0
int_curr_symbol, tok_int_curr_symbol, 0
currency_symbol, tok_currency_symbol, 0
mon_decimal_point, tok_mon_decimal_point, 0
mon_thousands_sep, tok_mon_thousands_sep, 0
mon_grouping, tok_mon_grouping, 0
positive_sign, tok_positive_sign, 0
negative_sign, tok_negative_sign, 0
int_frac_digits, tok_int_frac_digits, 0
frac_digits, tok_frac_digits, 0
p_cs_precedes, tok_p_cs_precedes, 0
p_sep_by_space, tok_p_sep_by_space, 0
n_cs_precedes, tok_n_cs_precedes, 0
n_sep_by_space, tok_n_sep_by_space, 0
p_sign_posn, tok_p_sign_posn, 0
n_sign_posn, tok_n_sign_posn, 0
LC_NUMERIC, tok_lc_numeric, 0
decimal_point, tok_decimal_point, 0
thousands_sep, tok_thousands_sep, 0
grouping, tok_grouping, 0
LC_TIME, tok_lc_time, 0
abday, tok_abday, 0
day, tok_day, 0
abmon, tok_abmon, 0
mon, tok_mon, 0
d_t_fmt, tok_d_t_fmt, 0
d_fmt, tok_d_fmt, 0
t_fmt, tok_t_fmt, 0
am_pm, tok_am_pm, 0
t_fmt_ampm, tok_t_fmt_ampm, 0
era, tok_era, 0
era_year, tok_era_year, 0
era_d_fmt, tok_era_d_fmt, 0
era_d_t_fmt, tok_era_d_t_fmt, 0
era_t_fmt, tok_era_t_fmt, 0
alt_digits, tok_alt_digits, 0
LC_MESSAGES, tok_lc_messages, 0
yesexpr, tok_yesexpr, 0
noexpr, tok_noexpr, 0
yesstr, tok_yesstr, 0
nostr, tok_nostr, 0

View file

@ -0,0 +1,211 @@
/* C code produced by gperf version 2.5 (GNU C++ version) */
/* Command-line: gperf -acCgopt -k1,2,5,$ -N locfile_hash programs/locfile-kw.gperf */
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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 <string.h>
#include "locfile-token.h"
struct keyword_t ;
#define TOTAL_KEYWORDS 73
#define MIN_WORD_LENGTH 3
#define MAX_WORD_LENGTH 17
#define MIN_HASH_VALUE 3
#define MAX_HASH_VALUE 185
/* maximum key range = 183, duplicates = 0 */
#ifdef __GNUC__
inline
#endif
static unsigned int
hash (register const char *str, register int len)
{
static const unsigned char asso_values[] =
{
186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
186, 186, 186, 186, 186, 186, 186, 186, 186, 186,
186, 186, 186, 186, 186, 186, 186, 0, 0, 0,
0, 0, 186, 0, 186, 186, 0, 186, 0, 35,
186, 186, 0, 0, 0, 5, 186, 186, 186, 0,
186, 186, 186, 186, 186, 15, 186, 0, 0, 5,
15, 10, 55, 30, 15, 75, 186, 20, 5, 40,
10, 0, 0, 186, 35, 30, 0, 70, 186, 10,
20, 75, 186, 186, 186, 186, 186, 186,
};
register int hval = len;
switch (hval)
{
default:
case 5:
hval += asso_values[(int) str[4]];
case 4:
case 3:
case 2:
hval += asso_values[(int) str[1]];
case 1:
hval += asso_values[(int) str[0]];
break;
}
return hval + asso_values[(int) str[len - 1]];
}
#ifdef __GNUC__
inline
#endif
const struct keyword_t *
locfile_hash (register const char *str, register int len)
{
static const struct keyword_t wordlist[] =
{
{"",}, {"",}, {"",},
{"END", tok_end, 0},
{"",}, {"",},
{"IGNORE", tok_ignore, 0},
{"LC_TIME", tok_lc_time, 0},
{"LC_CTYPE", tok_lc_ctype, 0},
{"",},
{"alpha", tok_alpha, 0},
{"LC_MESSAGES", tok_lc_messages, 0},
{"",}, {"",},
{"UNDEFINED", tok_undefined, 0},
{"LC_NUMERIC", tok_lc_numeric, 0},
{"",}, {"",},
{"position", tok_position, 0},
{"",},
{"t_fmt", tok_t_fmt, 0},
{"",},
{"collating-element", tok_collating_element, 0},
{"positive_sign", tok_positive_sign, 0},
{"",},
{"abmon", tok_abmon, 0},
{"collating-symbol", tok_collating_symbol, 0},
{"",}, {"",}, {"",},
{"cntrl", tok_cntrl, 0},
{"",}, {"",},
{"backward", tok_backward, 0},
{"",},
{"d_fmt", tok_d_fmt, 0},
{"",}, {"",}, {"",},
{"p_sep_by_space", tok_p_sep_by_space, 0},
{"print", tok_print, 0},
{"",},
{"toupper", tok_toupper, 0},
{"negative_sign", tok_negative_sign, 0},
{"",},
{"LC_COLLATE", tok_lc_collate, 0},
{"LC_MONETARY", tok_lc_monetary, 0},
{"",},
{"era", tok_era, 0},
{"n_sep_by_space", tok_n_sep_by_space, 0},
{"blank", tok_blank, 0},
{"noexpr", tok_noexpr, 0},
{"tolower", tok_tolower, 0},
{"mon", tok_mon, 0},
{"era_t_fmt", tok_era_t_fmt, 0},
{"space", tok_space, 0},
{"",},
{"mon_thousands_sep", tok_mon_thousands_sep, 0},
{"thousands_sep", tok_thousands_sep, 0},
{"",},
{"alt_digits", tok_alt_digits, 0},
{"",},
{"comment_char", tok_comment_char, 0},
{"",},
{"charclass", tok_charclass, 0},
{"t_fmt_ampm", tok_t_fmt_ampm, 0},
{"p_sign_posn", tok_p_sign_posn, 0},
{"charmap", tok_charmap, 0},
{"",},
{"era_d_fmt", tok_era_d_fmt, 0},
{"",},
{"era_d_t_fmt", tok_era_d_t_fmt, 0},
{"mon_decimal_point", tok_mon_decimal_point, 0},
{"p_cs_precedes", tok_p_cs_precedes, 0},
{"",},
{"punct", tok_punct, 0},
{"n_sign_posn", tok_n_sign_posn, 0},
{"forward", tok_forward, 0},
{"decimal_point", tok_decimal_point, 0},
{"",},
{"lower", tok_lower, 0},
{"order_start", tok_order_start, 0},
{"",},
{"n_cs_precedes", tok_n_cs_precedes, 0},
{"copy", tok_copy, 0},
{"nostr", tok_nostr, 0},
{"escape_char", tok_escape_char, 0},
{"",}, {"",}, {"",},
{"alnum", tok_alnum, 0},
{"",},
{"d_t_fmt", tok_d_t_fmt, 0},
{"day", tok_day, 0},
{"order_end", tok_order_end, 0},
{"digit", tok_digit, 0},
{"",}, {"",}, {"",}, {"",},
{"graph", tok_graph, 0},
{"",}, {"",},
{"grouping", tok_grouping, 0},
{"",},
{"currency_symbol", tok_currency_symbol, 0},
{"",}, {"",}, {"",}, {"",},
{"int_curr_symbol", tok_int_curr_symbol, 0},
{"",},
{"mon_grouping", tok_mon_grouping, 0},
{"",}, {"",}, {"",},
{"xdigit", tok_xdigit, 0},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"am_pm", tok_am_pm, 0},
{"yesstr", tok_yesstr, 0},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"from", tok_from, 0},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",},
{"upper", tok_upper, 0},
{"frac_digits", tok_frac_digits, 0},
{"yesexpr", tok_yesexpr, 0},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"abday", tok_abday, 0},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"era_year", tok_era_year, 0},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
{"",}, {"",}, {"",},
{"int_frac_digits", tok_int_frac_digits, 0},
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
{
register int key = hash (str, len);
if (key <= MAX_HASH_VALUE && key >= 0)
{
register const char *s = wordlist[key].name;
if (*s == *str && !strncmp (str + 1, s + 1, len - 1))
return &wordlist[key];
}
}
return 0;
}

View file

@ -0,0 +1,147 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifndef _TOKEN_H
#define _TOKEN_H
enum token_t
{
tok_none = 0,
tok_eof,
tok_eol,
tok_bsymbol,
tok_ident,
tok_ellipsis,
tok_semicolon,
tok_comma,
tok_open_brace,
tok_close_brace,
tok_charcode,
tok_ucs2,
tok_ucs4,
tok_number,
tok_minus1,
tok_string,
tok_escape_char,
tok_comment_char,
tok_end,
tok_g0esc,
tok_g1esc,
tok_g2esc,
tok_g3esc,
tok_code_set_name,
tok_mb_cur_max,
tok_mb_cur_min,
tok_charmap,
tok_width,
tok_width_variable,
tok_width_default,
tok_lc_ctype,
tok_copy,
tok_upper,
tok_lower,
tok_alpha,
tok_digit,
tok_xdigit,
tok_space,
tok_print,
tok_graph,
tok_blank,
tok_cntrl,
tok_punct,
tok_alnum,
tok_charclass,
tok_toupper,
tok_tolower,
tok_lc_collate,
tok_collating_element,
tok_collating_symbol,
tok_order_start,
tok_order_end,
tok_from,
tok_forward,
tok_backward,
tok_position,
tok_undefined,
tok_ignore,
tok_lc_monetary,
tok_int_curr_symbol,
tok_currency_symbol,
tok_mon_decimal_point,
tok_mon_thousands_sep,
tok_mon_grouping,
tok_positive_sign,
tok_negative_sign,
tok_int_frac_digits,
tok_frac_digits,
tok_p_cs_precedes,
tok_p_sep_by_space,
tok_n_cs_precedes,
tok_n_sep_by_space,
tok_p_sign_posn,
tok_n_sign_posn,
tok_lc_numeric,
tok_decimal_point,
tok_thousands_sep,
tok_grouping,
tok_lc_time,
tok_abday,
tok_day,
tok_abmon,
tok_mon,
tok_d_t_fmt,
tok_d_fmt,
tok_t_fmt,
tok_am_pm,
tok_t_fmt_ampm,
tok_era,
tok_era_year,
tok_era_d_fmt,
tok_era_d_t_fmt,
tok_era_t_fmt,
tok_alt_digits,
tok_lc_messages,
tok_yesexpr,
tok_noexpr,
tok_yesstr,
tok_nostr,
tok_error
};
struct keyword_t
{
const char *name;
enum token_t token;
int symname_or_ident;
/* Only for locdef file. */
int locale;
enum token_t base;
enum token_t group;
enum token_t list;
};
#endif /* token.h */

979
locale/programs/locfile.c Normal file
View file

@ -0,0 +1,979 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include <locale.h>
#include <malloc.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/uio.h>
#include "locfile.h"
#include "linereader.h"
#include "localeinfo.h"
#include "locales.h"
/* Uncomment the following line in the production version. */
/* #define NDEBUG 1 */
#include <assert.h>
/* Define the lookup function. */
#include "locfile-kw.h"
/* Some useful macros. */
#define MIN(a, b) (__extension__ ({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a < _b ? _a : _b; }))
void *xmalloc (size_t __n);
char *xstrdup (const char *__str);
struct localedef_t *
locfile_read (const char *filename, struct charset_t *charset)
{
struct linereader *ldfile;
struct localedef_t *result;
int state;
enum token_t expected_tok = tok_none;
const char *expected_str = NULL;
enum token_t ctype_tok_sym = tok_none;
const char *ctype_tok_str = NULL;
int copy_category = 0;
int cnt;
/* Allocate space for result. */
result = (struct localedef_t *) xmalloc (sizeof (struct localedef_t));
memset (result, '\0', sizeof (struct localedef_t));
ldfile = lr_open (filename, locfile_hash);
if (ldfile == NULL)
{
if (filename[0] != '/')
{
char path[strlen (filename) + 1 + sizeof (LOCSRCDIR)];
stpcpy (stpcpy (stpcpy (path, LOCSRCDIR), "/"), filename);
ldfile = lr_open (path, locfile_hash);
}
if (ldfile == NULL)
{
result->failed = 1;
return result;
}
}
#define HANDLE_COPY(category, token, string) \
if (nowtok == tok_copy) \
{ \
copy_category = category; \
expected_tok = token; \
expected_str = string; \
state = 8; \
continue; \
} \
++state
#define LOCALE_PROLOG(token, string) \
if (nowtok == tok_eol) \
/* Ignore empty lines. */ \
continue; \
if (nowtok == tok_end) \
{ \
expected_tok = token; \
expected_str = string; \
state = 4; \
continue; \
} \
if (nowtok == tok_copy) \
goto only_copy;
#define READ_STRING(fn, errlabel) \
do \
{ \
arg = lr_token (ldfile, charset); \
if (arg->tok != tok_string) \
goto errlabel; \
fn (ldfile, result, nowtok, arg, charset); \
lr_ignore_rest (ldfile, 1); \
} \
while (0)
#define READ_STRING_LIST(fn, errlabel) \
do \
{ \
arg = lr_token (ldfile, charset); \
while (arg->tok == tok_string) \
{ \
fn (ldfile, result, nowtok, arg, charset); \
arg = lr_token (ldfile, charset); \
if (arg->tok != tok_semicolon) \
break; \
arg = lr_token (ldfile, charset); \
} \
if (arg->tok != tok_eol) \
goto errlabel; \
} \
while (0)
#define READ_NUMBER(fn, errlabel) \
do \
{ \
arg = lr_token (ldfile, charset); \
if (arg->tok != tok_minus1 && arg->tok != tok_number) \
goto errlabel; \
fn (ldfile, result, nowtok, arg, charset); \
lr_ignore_rest (ldfile, 1); \
} \
while (0)
#define READ_NUMBER_LIST(fn, errlabel) \
do \
{ \
arg = lr_token (ldfile, charset); \
while (arg->tok == tok_minus1 || arg->tok == tok_number) \
{ \
fn (ldfile, result, nowtok, arg, charset); \
arg = lr_token (ldfile, charset); \
if (arg->tok != tok_semicolon) \
break; \
arg = lr_token (ldfile, charset); \
} \
if (arg->tok != tok_eol) \
goto errlabel; \
} \
while (0)
#define SYNTAX_ERROR(string) \
lr_error (ldfile, string); \
lr_ignore_rest (ldfile, 0);
/* Parse locale definition file and store result in RESULT. */
state = 1;
while (1)
{
/* What's on? */
struct token *now = lr_token (ldfile, charset);
enum token_t nowtok = now->tok;
struct token *arg;
if (nowtok == tok_eof)
break;
switch (state)
{
case 1:
/* The beginning. We expect the special declarations, EOL or
the start of any locale. */
if (nowtok == tok_eol)
/* Ignore empty lines. */
continue;
switch (nowtok)
{
case tok_escape_char:
case tok_comment_char:
/* We need an argument. */
arg = lr_token (ldfile, charset);
if (arg->tok != tok_ident)
{
SYNTAX_ERROR (_("bad argument"));
continue;
}
if (arg->val.str.len != 1)
{
lr_error (ldfile, _("\
argument to `%s' must be a single character"),
nowtok == tok_escape_char ? "escape_char"
: "comment_char");
lr_ignore_rest (ldfile, 0);
continue;
}
if (nowtok == tok_escape_char)
ldfile->escape_char = *arg->val.str.start;
else
ldfile->comment_char = *arg->val.str.start;
break;
case tok_lc_ctype:
state = 2;
break;
case tok_lc_collate:
state = 10;
break;
case tok_lc_monetary:
state = 20;
break;
case tok_lc_numeric:
state = 30;
break;
case tok_lc_time:
state = 40;
break;
case tok_lc_messages:
state = 50;
break;
default:
SYNTAX_ERROR (_("\
syntax error: not inside a locale definition section"));
continue;
}
lr_ignore_rest (ldfile, 1);
continue;
case 2:
HANDLE_COPY (LC_CTYPE, tok_lc_ctype, "LC_CYTPE");
ctype_startup (ldfile, result, charset);
/* FALLTHROUGH */
case 3:
/* Here we accept all the character classes, tolower/toupper,
and following ANSI C:1995 self-defined classes. */
LOCALE_PROLOG (tok_lc_ctype, "LC_CTYPE");
if (nowtok == tok_charclass)
{
READ_STRING_LIST (ctype_class_new, bad_new_charclass);
continue;
bad_new_charclass:
SYNTAX_ERROR (_("\
syntax error in definition of new character class"));
continue;
}
if (nowtok == tok_charmap)
{
READ_STRING_LIST (ctype_map_new, bad_new_charmap);
continue;
bad_new_charmap:
SYNTAX_ERROR (_("\
syntax error in definition of new character map"));
continue;
}
if (nowtok == tok_upper || nowtok == tok_lower
|| nowtok == tok_alpha || nowtok == tok_digit
|| nowtok == tok_alnum || nowtok == tok_space
|| nowtok == tok_cntrl || nowtok == tok_punct
|| nowtok == tok_graph || nowtok == tok_print
|| nowtok == tok_xdigit || nowtok == tok_blank)
{
ctype_tok_sym = nowtok;
ctype_tok_str = NULL;
state = 5;
continue;
}
if (nowtok == tok_toupper|| nowtok == tok_tolower)
{
ctype_tok_sym = nowtok;
ctype_tok_str = NULL;
state = 6;
continue;
}
if (nowtok != tok_ident)
goto bad_charclass;
/* We possibly have a self-defined character class. */
if (ctype_is_charclass (ldfile, result, now->val.str.start))
{
ctype_tok_sym = nowtok;
ctype_tok_str = now->val.str.start;
state = 5;
continue;
}
/* ...or a self-defined character map. */
if (ctype_is_charmap (ldfile, result, now->val.str.start))
{
ctype_tok_sym = nowtok;
ctype_tok_str = now->val.str.start;
state = 6;
continue;
}
SYNTAX_ERROR (_("syntax error in definition of LC_CTYPE category"));
continue;
case 4:
/* Handle `END xxx'. */
if (nowtok != expected_tok)
lr_error (ldfile, _("\
`%1$s' definition does not end with `END %1$s'"), expected_str);
lr_ignore_rest (ldfile, nowtok == expected_tok);
state = 1;
continue;
case 5:
/* Here we expect a semicolon separated list of bsymbols. The
bit to be set in the word is given in CHARCLASS_BIT. */
arg = now;
ctype_class_start (ldfile, result, ctype_tok_sym, ctype_tok_str,
charset);
while (arg->tok != tok_eol)
{
/* Any token other than a bsymbol is an error. */
if (arg->tok != tok_bsymbol)
{
bad_charclass:
SYNTAX_ERROR (_("\
syntax error in character class definition"));
break;
}
/* Lookup value for token and write into array. */
ctype_class_from (ldfile, result, arg, charset);
arg = lr_token (ldfile, charset);
if (arg->tok == tok_semicolon)
arg = lr_token (ldfile, charset);
else if (arg->tok != tok_eol)
goto bad_charclass;
/* Look for ellipsis. */
if (arg->tok == tok_ellipsis)
{
arg = lr_token (ldfile, charset);
if (arg->tok != tok_semicolon)
goto bad_charclass;
arg = lr_token (ldfile, charset);
if (arg->tok != tok_bsymbol)
goto bad_charclass;
/* Write range starting at LAST to ARG->VAL. */
ctype_class_to (ldfile, result, arg, charset);
arg = lr_token (ldfile, charset);
if (arg->tok == tok_semicolon)
arg = lr_token (ldfile, charset);
else if (arg->tok != tok_eol)
goto bad_charclass;
}
}
/* Mark class as already seen. */
ctype_class_end (ldfile, result);
state = 3;
continue;
case 6:
/* Here we expect a list of character mappings. Note: the
first opening brace is already matched. */
ctype_map_start (ldfile, result, ctype_tok_sym, ctype_tok_str,
charset);
while (1)
{
/* Match ( bsymbol , bsymbol ) */
if (now->tok != tok_open_brace)
goto bad_charmap;
now = lr_token (ldfile, charset);
if (now->tok != tok_bsymbol)
{
bad_charmap:
SYNTAX_ERROR (_("\
syntax error in character mapping definition"));
state = 3;
break;
}
/* Lookup arg and assign to FROM. */
ctype_map_from (ldfile, result, now, charset);
now = lr_token (ldfile, charset);
if (now->tok != tok_comma)
goto bad_charmap;
now = lr_token (ldfile, charset);
if (now->tok != tok_bsymbol)
goto bad_charmap;
/* Lookup arg and assign to TO. */
ctype_map_to (ldfile, result, now, charset);
now = lr_token (ldfile, charset);
if (now->tok != tok_close_brace)
goto bad_charmap;
now = lr_token (ldfile, charset);
if (now->tok == tok_eol)
{
state = 3;
break;
}
if (now->tok != tok_semicolon)
goto bad_charmap;
now = lr_token (ldfile, charset);
}
ctype_map_end (ldfile, result);
continue;
case 8:
{
/* We have seen `copy'. First match the argument. */
int warned = 0;
if (nowtok != tok_string)
lr_error (ldfile, _("expect string argument for `copy'"));
else
def_to_process (now->val.str.start, 1 << copy_category);
lr_ignore_rest (ldfile, nowtok == tok_string);
/* The rest of the line must be empty
and the next keyword must be `END xxx'. */
while (lr_token (ldfile, charset)->tok != tok_end)
{
if (warned == 0)
{
only_copy:
lr_error (ldfile, _("\
no other keyword shall be specified when `copy' is used"));
warned = 1;
}
lr_ignore_rest (ldfile, 0);
}
state = 4;
}
continue;
case 10:
HANDLE_COPY (LC_COLLATE, tok_lc_collate, "LC_COLLATE");
collate_startup (ldfile, result, charset);
/* FALLTHROUGH */
case 11:
/* Process the LC_COLLATE section. We expect `END LC_COLLATE'
any of the collation specifications, or any bsymbol. */
LOCALE_PROLOG (tok_lc_collate, "LC_COLLATE");
if (nowtok == tok_order_start)
{
state = 12;
continue;
}
if (nowtok != tok_collating_element
&& nowtok != tok_collating_symbol)
{
bad_collation:
lr_error (ldfile, _("\
syntax error in collation definition"));
lr_ignore_rest (ldfile, 0);
continue;
}
/* Get argument. */
arg = lr_token (ldfile, charset);
if (arg->tok != tok_bsymbol)
{
lr_error (ldfile, _("\
collation symbol expected after `%s'"),
nowtok == tok_collating_element
? "collating-element" : "collating-symbol");
lr_ignore_rest (ldfile, 0);
continue;
}
if (nowtok == tok_collating_element)
{
/* Save to-value as new name. */
collate_element_to (ldfile, result, arg, charset);
arg = lr_token (ldfile, charset);
if (arg->tok != tok_from)
{
lr_error (ldfile, _("\
`from' expected after first argument to `collating-element'"));
lr_ignore_rest (ldfile, 0);
continue;
}
arg = lr_token (ldfile, charset);
if (arg->tok != tok_string)
{
lr_error (ldfile, _("\
from-value of `collating-element' must be a string"));
lr_ignore_rest (ldfile, 0);
continue;
}
/* Enter new collating element. */
collate_element_from (ldfile, result, arg, charset);
}
else
/* Enter new collating symbol into table. */
collate_symbol (ldfile, result, arg, charset);
lr_ignore_rest (ldfile, 1);
continue;
case 12:
/* We parse the rest of the line containing `order_start'.
In any case we continue with parsing the symbols. */
state = 13;
cnt = 0;
while (now->tok != tok_eol)
{
int collation_method = 0;
++cnt;
do
{
if (now->tok == tok_forward)
collation_method |= sort_forward;
else if (now->tok == tok_backward)
collation_method |= sort_backward;
else if (now->tok == tok_position)
collation_method |= sort_position;
else
{
lr_error (ldfile, _("unknown collation directive"));
lr_ignore_rest (ldfile, 0);
continue;
}
now = lr_token (ldfile, charset);
}
while (now->tok == tok_comma
&& (now == lr_token (ldfile, charset) != tok_none));
/* Check for consistency: forward and backwards are
mutually exclusive. */
if ((collation_method & sort_forward) != 0
&& (collation_method & sort_backward) != 0)
{
lr_error (ldfile, _("\
sorting order `forward' and `backward' are mutually exclusive"));
/* The recover clear the backward flag. */
collation_method &= ~sort_backward;
}
/* ??? I don't know whether this is correct but while
thinking about the `strcoll' functions I found that I
need a direction when performing position depended
collation. So I assume here that implicitly the
direction `forward' is given when `position' alone is
written. --drepper */
if (collation_method == sort_position)
collation_method |= sort_forward;
/* Enter info about next collation order. */
collate_new_order (ldfile, result, collation_method);
if (now->tok != tok_eol && now->tok != tok_semicolon)
{
lr_error (ldfile, _("\
syntax error in `order_start' directive"));
lr_ignore_rest (ldfile, 0);
break;
}
if (now->tok == tok_semicolon)
now = lr_token (ldfile, charset);
}
/* If no argument to `order_start' is given, one `forward'
argument is implicitely assumed. */
if (cnt == 0)
collate_new_order (ldfile, result, sort_forward);
/* We now know about all sorting rules. */
collate_build_arrays (ldfile, result);
continue;
case 13:
/* We read one symbol a line until `order_end' is found. */
{
static int last_correct = 1;
if (nowtok == tok_order_end)
{
state = 14;
lr_ignore_rest (ldfile, 1);
continue;
}
/* Ignore empty lines. */
if (nowtok == tok_eol)
continue;
if (nowtok != tok_bsymbol && nowtok != tok_undefined
&& nowtok != tok_ellipsis)
{
if (last_correct == 1)
{
lr_error (ldfile, _("\
syntax error in collating order definition"));
last_correct = 0;
}
lr_ignore_rest (ldfile, 0);
continue;
}
else
{
last_correct = 1;
/* Remember current token. */
if (collate_order_elem (ldfile, result, now, charset) < 0)
continue;
}
/* Read optional arguments. */
arg = lr_token (ldfile, charset);
while (arg->tok != tok_eol)
{
if (arg->tok != tok_ignore && arg->tok != tok_ellipsis
&& arg->tok != tok_bsymbol && arg->tok != tok_string)
break;
if (arg->tok == tok_ignore || arg->tok == tok_ellipsis
|| arg->tok == tok_string)
{
/* Call handler for simple weights. */
if (collate_simple_weight (ldfile, result, arg, charset)
< 0)
goto illegal_weight;
arg = lr_token (ldfile, charset);
}
else
do
{
/* Collect char. */
int ok = collate_weight_bsymbol (ldfile, result, arg,
charset);
if (ok < 0)
goto illegal_weight;
arg = lr_token (ldfile, charset);
}
while (arg->tok == tok_bsymbol);
/* Are there more weights? */
if (arg->tok != tok_semicolon)
break;
/* Yes, prepare next weight. */
if (collate_next_weight (ldfile, result) < 0)
goto illegal_weight;
arg = lr_token (ldfile, charset);
}
if (arg->tok != tok_eol)
{
SYNTAX_ERROR (_("syntax error in order specification"));
}
collate_end_weight (ldfile, result);
illegal_weight:
}
continue;
case 14:
/* Following to the `order_end' keyword we don't expect
anything but the `END'. */
if (nowtok == tok_eol)
continue;
if (nowtok != tok_end)
goto bad_collation;
expected_tok = tok_lc_collate;
expected_str = "LC_COLLATE";
state = 4;
ldfile->translate_strings = 1;
continue;
case 20:
HANDLE_COPY (LC_MONETARY, tok_lc_monetary, "LC_MONETARY");
monetary_startup (ldfile, result, charset);
/* FALLTHROUGH */
case 21:
LOCALE_PROLOG (tok_lc_monetary, "LC_MONETARY");
switch (nowtok)
{
case tok_int_curr_symbol:
case tok_currency_symbol:
case tok_mon_decimal_point:
case tok_mon_thousands_sep:
case tok_positive_sign:
case tok_negative_sign:
READ_STRING (monetary_add, bad_monetary);
break;
case tok_int_frac_digits:
case tok_frac_digits:
case tok_p_cs_precedes:
case tok_p_sep_by_space:
case tok_n_cs_precedes:
case tok_n_sep_by_space:
case tok_p_sign_posn:
case tok_n_sign_posn:
READ_NUMBER (monetary_add, bad_monetary);
break;
case tok_mon_grouping:
/* We have a semicolon separated list of integers. */
READ_NUMBER_LIST (monetary_add, bad_monetary);
break;
default:
bad_monetary:
SYNTAX_ERROR (_("syntax error in monetary locale definition"));
}
continue;
case 30:
HANDLE_COPY (LC_NUMERIC, tok_lc_numeric, "LC_NUMERIC");
numeric_startup (ldfile, result, charset);
/* FALLTHROUGH */
case 31:
LOCALE_PROLOG (tok_lc_numeric, "LC_NUMERIC");
switch (nowtok)
{
case tok_decimal_point:
case tok_thousands_sep:
READ_STRING (numeric_add, bad_numeric);
break;
case tok_grouping:
/* We have a semicolon separated list of integers. */
READ_NUMBER_LIST (numeric_add, bad_numeric);
break;
default:
bad_numeric:
SYNTAX_ERROR (_("syntax error in numeric locale definition"));
}
continue;
case 40:
HANDLE_COPY (LC_TIME, tok_lc_time, "LC_TIME");
time_startup (ldfile, result, charset);
/* FALLTHROUGH */
case 41:
LOCALE_PROLOG (tok_lc_time, "LC_TIME");
switch (nowtok)
{
case tok_abday:
case tok_day:
case tok_abmon:
case tok_mon:
case tok_am_pm:
case tok_alt_digits:
READ_STRING_LIST (time_add, bad_time);
continue;
case tok_d_t_fmt:
case tok_d_fmt:
case tok_t_fmt:
case tok_t_fmt_ampm:
case tok_era:
case tok_era_year:
case tok_era_d_t_fmt:
case tok_era_d_fmt:
case tok_era_t_fmt:
READ_STRING (time_add, bad_time);
break;
default:
bad_time:
SYNTAX_ERROR (_("syntax error in time locale definition"));
}
continue;
case 50:
HANDLE_COPY (LC_MESSAGES, tok_lc_messages, "LC_MESSAGES");
messages_startup (ldfile, result, charset);
/* FALLTHROUGH */
case 51:
LOCALE_PROLOG (tok_lc_messages, "LC_MESSAGES");
switch (nowtok)
{
case tok_yesexpr:
case tok_noexpr:
case tok_yesstr:
case tok_nostr:
READ_STRING (messages_add, bad_message);
break;
default:
bad_message:
SYNTAX_ERROR (_("syntax error in message locale definition"));
}
continue;
default:
error (5, 0, _("%s: error in state machine"), __FILE__);
/* NOTREACHED */
}
break;
}
/* We read all of the file. */
lr_close (ldfile);
/* Let's see what information is available. */
for (cnt = LC_CTYPE; cnt <= LC_MESSAGES; ++cnt)
if (result->categories[cnt].generic != NULL)
result->avail |= 1 << cnt;
return result;
}
void
check_all_categories (struct localedef_t *locale, struct charset_t *charset)
{
/* Call the finishing functions for all locales. */
if ((locale->binary & (1 << LC_CTYPE)) == 0)
ctype_finish (locale, charset);
if ((locale->binary & (1 << LC_COLLATE)) == 0)
collate_finish (locale, charset);
if ((locale->binary & (1 << LC_MONETARY)) == 0)
monetary_finish (locale);
if ((locale->binary & (1 << LC_NUMERIC)) == 0)
numeric_finish (locale);
if ((locale->binary & (1 << LC_TIME)) == 0)
time_finish (locale);
if ((locale->binary & (1 << LC_MESSAGES)) == 0)
messages_finish (locale);
}
void
write_all_categories (struct localedef_t *locale, const char *output_path)
{
/* Call all functions to write locale data. */
ctype_output (locale, output_path);
collate_output (locale, output_path);
monetary_output (locale, output_path);
numeric_output (locale, output_path);
time_output (locale, output_path);
messages_output (locale, output_path);
}
void
write_locale_data (const char *output_path, const char *category,
size_t n_elem, struct iovec *vec)
{
size_t cnt, step;
int fd;
char *fname;
asprintf (&fname, "%s/%s", output_path, category);
fd = creat (fname, 0666);
if (fd == -1)
{
int save_err = errno;
if (errno == EISDIR)
{
free (fname);
asprintf (&fname, "%1$s/%2$s/SYS_%2$s", output_path, category);
fd = creat (fname, 0666);
if (fd == -1)
save_err = errno;
}
if (fd == -1)
{
error (0, save_err, _("cannot open output file for category `%s'"),
category);
return;
}
}
free (fname);
/* Write the data using writev. But we must take care for the
limitation of the implementation. */
for (cnt = 0; cnt < n_elem; cnt += step)
{
/* XXX Fixme: should be in libc header. */
#ifndef MAX_IOVEC
# define MAX_IOVEC 8
#endif
step = MIN (MAX_IOVEC, n_elem - cnt);
if (writev (fd, &vec[cnt], step) < 0)
{
error (0, errno, _("failure while writing data for category `%s'"),
category);
break;
}
}
close (fd);
}

75
locale/programs/locfile.h Normal file
View file

@ -0,0 +1,75 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifndef _LOCFILE_H
#define _LOCFILE_H
#include <sys/uio.h>
#include "charset.h"
/* Opaque types for the different loales. */
struct locale_ctype_t;
struct locale_collate_t;
struct locale_monetary_t;
struct locale_numeric_t;
struct locale_time_t;
struct locale_messages_t;
struct localedef_t
{
int failed;
int avail;
int binary;
union
{
void *generic;
struct locale_ctype_t *ctype;
struct locale_collate_t *collate;
struct locale_monetary_t *monetary;
struct locale_numeric_t *numeric;
struct locale_time_t *time;
struct locale_messages_t *messages;
} categories[6];
size_t len[6];
};
/* Found in localedef.c. */
void def_to_process (const char *name, int category);
/* Found in locfile.c. */
struct localedef_t *locfile_read (const char *filename,
struct charset_t *charset);
void check_all_categories (struct localedef_t *locale,
struct charset_t *charset);
void write_all_categories (struct localedef_t *locale,
const char *output_path);
void write_locale_data (const char *output_path, const char *category,
size_t n_elem, struct iovec *vec);
#endif /* locfile.h */

View file

@ -0,0 +1,146 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
COntributed 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. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <assert.h>
#include <stdlib.h>
#include "charset.h"
#include "stringtrans.h"
/* Global variable. */
enum encoding_method encoding_method = ENC_UCS4;
void *xmalloc (size_t __n);
void *xrealloc (void *__p, size_t __n);
#define ADDC(ch) \
do \
{ \
if (bufact == bufmax) \
{ \
bufmax *= 2; \
buf = xrealloc (buf, bufmax); \
} \
buf[bufact++] = (ch); \
} \
while (0)
char *
translate_string (char *str, struct charset_t *charset)
{
char *buf;
size_t bufact = 0;
size_t bufmax = 56;
buf = (char *) xmalloc (bufmax);
while (str[0] != '\0')
{
char *tp;
unsigned int value;
if (str[0] != '<')
{
ADDC (*str++);
continue;
}
tp = &str[1];
while (tp[0] != '\0' && tp[0] != '>')
if (tp[0] == '\\')
if (tp[1] != '\0')
tp += 2;
else
++tp;
else
++tp;
if (tp[0] == '\0')
{
free (buf);
return NULL;
}
value = charset_find_value (charset, str + 1, tp - (str + 1));
if (value == ILLEGAL_CHAR_VALUE)
{
free (buf);
return NULL;
}
else
{
/* Encode string using current method. */
char *cp;
if (bufmax - bufact < 8)
{
bufmax *= 2;
buf = (char *) xrealloc (buf, bufmax);
}
cp = &buf[bufact];
if (encode_char (value, &cp) < 0)
{
free (buf);
return NULL;
}
bufact = cp - buf;
}
str = &tp[1];
}
ADDC ('\0');
return buf;;
}
int
encode_char (unsigned int value, char **cpp)
{
switch (encoding_method)
{
case ENC_UCS1:
if (value > 255)
return -11;
*(*cpp)++ = (char) value;
break;
case ENC_UCS4:
*(*cpp)++ = (char) (value >> 24);
*(*cpp)++ = (char) ((value >> 16) & 0xff);
*(*cpp)++ = (char) ((value >> 8) & 0xff);
*(*cpp)++ = (char) (value & 0xff);
break;
default:
return -1;
}
return 0;
}

View file

@ -0,0 +1,38 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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. */
#ifndef _TRANSLATE_H
#define _TRANSLATE_H 1
enum encoding_method
{
ENC_UCS1,
ENC_UCS4
};
extern enum encoding_method encoding_method;
char *translate_string (char *__str, struct charset_t *__charset);
int encode_char (unsigned int __value, char **__cpp);
#endif /* translate.h */

View file

@ -1,4 +1,4 @@
/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc.
/* Copyright (C) 1991, 1992, 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@ -290,7 +290,7 @@ setlocale (int category, const char *name)
/* The composite name did not specify all categories. */
return NULL;
}
/* Load the new data for each category. */
while (category-- > 0)
/* Only actually load the data if anything will use it. */

View file

@ -1,54 +0,0 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#ifndef _TOKEN_H
#define _TOKEN_H 1
/* Define those keywords which does not correspond directly to any
item in a category. Those already have values. */
enum token
{
/* We must make sure that these values do not overlap with the
other possible return values of the lexer. */
TOK_LAST_USED = _NL_NUM,
/* General tokens. */
TOK_END, TOK_COMMENT_CHAR, TOK_COPY, TOK_ESCAPE_CHAR, TOK_FROM,
TOK_ENDOFLINE, TOK_IDENT, TOK_STRING, TOK_ELLIPSIS, TOK_CHAR,
TOK_ILL_CHAR, TOK_NUMBER, TOK_MINUS1,
/* Tokens from the collate category. */
TOK_IGNORE, TOK_UNDEFINED, TOK_BACKWARD, TOK_FORWARD, TOK_POSITION,
TOK_COLLATING_ELEMENT, TOK_COLLATING_SYMBOL, TOK_ORDER_END,
TOK_ORDER_START,
/* Tokens from the ctype category. */
TOK_TOLOWER, TOK_TOUPPER,
/* The order here is important. It must correspond to the bits
used for indicating the class membership (ctype.h). */
TOK_UPPER, TOK_LOWER, TOK_ALPHA, TOK_DIGIT, TOK_XDIGIT, TOK_SPACE,
TOK_PRINT, TOK_GRAPH, TOK_BLANK, TOK_CNTRL, TOK_PUNCT,
};
/*
* Local Variables:
* mode:c
* c-basic-offset:2
* End:
*/
#endif /* token.h */

171
locale/weight.h Normal file
View file

@ -0,0 +1,171 @@
/* Copyright (C) 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 <alloca.h>
#ifndef STRING_TYPE
# error STRING_TYPE not defined
#endif
#ifndef USTRING_TYPE
# error USTRING_TYPE not defined
#endif
typedef struct weight_t
{
struct weight_t *prev;
struct weight_t *next;
struct data_pair {
size_t number;
u32_t *value;
} data[0];
} weight_t;
/* The following five macros grant access to the non-byte order
dependend values in the collate locale file. */
#define collate_nrules \
(_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES))
#define collate_hash_size \
(_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_HASH_SIZE))
#define collate_hash_layers \
(_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_HASH_LAYERS))
#define collate_undefined \
(_NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_UNDEFINED))
#define collate_rules \
(_NL_CURRENT (LC_COLLATE, _NL_COLLATE_RULES))
static __inline int get_weight (const STRING_TYPE **str, weight_t *result);
static __inline int
get_weight (const STRING_TYPE **str, weight_t *result)
{
unsigned int ch = *((USTRING_TYPE *) (*str))++;
size_t slot;
if (sizeof (STRING_TYPE) == 1)
slot = ch * (collate_nrules + 1);
else
{
const size_t level_size = collate_hash_size * (collate_nrules + 1);
size_t level;
slot = (ch * (collate_nrules + 1)) % collate_hash_size;
level = 0;
while (__collate_table[slot] != (u32_t) ch)
{
if (__collate_table[slot + 1] == 0
|| ++level >= collate_hash_layers)
{
size_t idx = collate_undefined;
size_t cnt;
for (cnt = 0; cnt < collate_nrules; ++cnt)
{
result->data[cnt].number = __collate_extra[idx++];
result->data[cnt].value = &__collate_extra[idx];
idx += result->data[cnt].number;
}
return 0;
}
slot += level_size;
}
}
if (__collate_table[slot + 1] != FORWARD_CHAR)
{
/* We have a simple form. One one value for each weight. */
size_t cnt;
for (cnt = 0; cnt < collate_nrules; ++cnt)
{
result->data[cnt].number = 1;
result->data[cnt].value = &__collate_table[slot + 1 + cnt];
}
return ch == 0;
}
/* We now look for any collation element which starts with CH.
There might none, but the last list member is a catch-all case
because it is simple the character CH. The value of this entry
might be the same as UNDEFINED. */
slot = __collate_table[slot + 2];
while (1)
{
size_t idx;
/* This is a comparison between a u32_t array (aka wchar_t) and
an 8-bit string. */
for (idx = 0; __collate_extra[slot + 2 + idx] != 0; ++idx)
if (__collate_extra[slot + 2 + idx] != (u32_t) str[idx])
break;
/* When the loop finished with all character of the collation
element used, we found the longest prefix. */
if (__collate_extra[slot + 2 + idx] == 0)
{
size_t cnt;
idx += slot + 3;
for (cnt = 0; cnt < collate_nrules; ++cnt)
{
result->data[cnt].number = __collate_extra[idx++];
result->data[cnt].value = &__collate_extra[idx];
idx += result->data[cnt].number;
}
return 0;
}
/* To next entry in list. */
slot += __collate_extra[slot];
}
/* NOTREACHED */
return 0; /* To calm down gcc. */
}
/* To process a string efficiently we retrieve all information about
the string at once. The following macro constructs a double linked
list of this information. It is a macro because we use `alloca'
and we use a double linked list because of the backward collation
order. */
#define get_string(str, forw, backw) \
do \
{ \
weight_t *newp; \
do \
{ \
newp = (weight_t *) alloca (sizeof (weight_t) \
+ (collate_nrules \
* sizeof (struct data_pair))); \
\
newp->prev = backw; \
if (backw == NULL) \
forw = newp; \
else \
backw->next = newp; \
newp->next = NULL; \
backw = newp; \
} \
while (get_weight (&str, newp) == 0); \
} \
while (0)

View file

@ -47,11 +47,15 @@ Cambridge, MA 02139, USA. */
void exit ();
#endif
#ifndef _
#define _(String) String
#endif
/* If NULL, error will flush stdout, then print on stderr the program
name, a colon and a space. Otherwise, error will call this
function without parameters instead. */
void (*error_print_progname) (
#if __STDC__
#if __STDC__ - 0
void
#endif
);
@ -85,7 +89,7 @@ private_strerror (errnum)
if (errnum > 0 && errnum <= sys_nerr)
return sys_errlist[errnum];
return "Unknown system error";
return _("Unknown system error");
}
#define strerror private_strerror
#endif /* HAVE_STRERROR */
@ -133,7 +137,74 @@ error (status, errnum, message, va_alist)
#endif
++error_message_count;
if (errnum)
fprintf (stderr, ": %s", strerror (errnum));
putc ('\n', stderr);
fflush (stderr);
if (status)
exit (status);
}
/* Sometimes we want to have at most one error per line. This
variable controls whether this mode is selected or not. */
int error_one_per_line;
void
#if defined(VA_START) && __STDC__
error_at_line (int status, int errnum, const char *file_name,
unsigned int line_number, const char *message, ...)
#else
error_at_line (status, errnum, file_name, line_number, message, va_alist)
int status;
int errnum;
const char *file_name;
unsigned int line_number;
char *message;
va_dcl
#endif
{
#ifdef VA_START
va_list args;
#endif
if (error_one_per_line)
{
static const char *old_file_name;
static unsigned int old_line_number;
if (old_line_number == line_number
&& (file_name == old_file_name || !strcmp (old_file_name, file_name))
/* Simply return and print nothing. */
return;
old_file_name = file_name;
old_line_number = line_number;
}
if (error_print_progname)
(*error_print_progname) ();
else
{
fflush (stdout);
fprintf (stderr, "%s:", program_name);
}
if (file_name != NULL)
fprintf (stderr, "%s:%d: ", file_name, line_number);
#ifdef VA_START
VA_START (args, message);
# if HAVE_VPRINTF || _LIBC
vfprintf (stderr, message, args);
# else
_doprnt (message, args, stderr);
# endif
va_end (args);
#else
fprintf (stderr, message, a1, a2, a3, a4, a5, a6, a7, a8);
#endif
++error_message_count;
if (errnum)
fprintf (stderr, ": %s", strerror (errnum));
putc ('\n', stderr);

View file

@ -44,6 +44,10 @@ Cambridge, MA 02139, USA. */
extern void error (int status, int errnum, const char *format, ...)
__attribute__ ((__format__ (__printf__, 3, 4)));
extern void error_at_line (int status, int errnum, const char *fname,
unsigned int lineno, const char *format, ...)
__attribute__ ((__format__ (__printf__, 5, 6)));
/* If NULL, error will flush stdout, then print on stderr the program
name, a colon and a space. Otherwise, error will call this
function without parameters instead. */
@ -51,10 +55,15 @@ extern void (*error_print_progname) (void);
#else
void error ();
void error_at_line ();
extern void (*error_print_progname) ();
#endif
/* This variable is incremented each time `error' is called. */
extern unsigned int error_message_count;
/* Sometimes we want to have at most one error per line. This
variable controls whether this mode is selected or not. */
extern int error_one_per_line;
#endif /* _error_h_ */

View file

@ -50,6 +50,10 @@ __BEGIN_DECLS
Software Development Utilities Option. */
#define _POSIX2_SW_DEV 1
/* If defined, the implementation supports the
creation of locales with the localedef utility. */
#define _POSIX2_LOCALEDEF 1
/* Get values of POSIX options:

View file

@ -625,11 +625,22 @@ __printf_fp (FILE *fp,
/* All factors but 10^-1 are tested now. */
if (exponent > 0)
{
int cnt_l;
cy = __mpn_mul_1 (tmp, frac, fracsize, 10);
tmpsize = fracsize;
assert (cy == 0 || tmp[tmpsize - 1] < 20);
(void) __mpn_rshift (frac, tmp, tmpsize, MIN (4, exponent));
count_trailing_zeros (cnt_l, tmp[0]);
if (cnt_l < MIN (4, exponent))
{
cy = __mpn_lshift (frac, tmp, tmpsize,
BITS_PER_MP_LIMB - MIN (4, exponent));
if (cy != 0)
frac[tmpsize++] = cy;
}
else
(void) __mpn_rshift (frac, tmp, tmpsize, MIN (4, exponent));
fracsize = tmpsize;
exp10 |= 1;
assert (frac[fracsize - 1] < 10);

View file

@ -10,7 +10,7 @@ typedef struct
const char *format_string;
} sprint_double_type;
sprint_double_type sprint_doubles[] =
sprint_double_type sprint_doubles[] =
{
__LINE__, 30.3, "< +30.3>", "<%+15.10g>",
__LINE__, 10.0, "<10.00>", "<%5.2f>",
@ -4071,6 +4071,23 @@ int main()
testcount++;
}
/* And one special test. */
{
const char ref[] = "1.7763568394002504646778106689453125e-15";
int i;
d = 1.0;
for (i = 1; i < 50; ++i)
d /= 2;
sprintf (buffer, "%.100g", d);
if (!matches (buffer, ref))
{
++errcount;
printf (
"Error in line %d using \"%s\". Result is \"%s\"; should be: \"%s\".\n",
__LINE__, "%.100g", buffer, ref);
}
}
if (errcount == 0)
{
printf("Encountered no errors in %d tests.\n", testcount);

View file

@ -1,5 +1,6 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
/* 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
@ -13,22 +14,145 @@ 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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
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 lexiographically
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 char *s1;
const char *s2;
STRCOLL (s1, s2)
const STRING_TYPE *s1;
const STRING_TYPE *s2;
{
/* XXX LC_COLLATE not implemented yet. */
return strcmp (s1, 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;
}

View file

@ -1,5 +1,6 @@
/* Copyright (C) 1995 Free Software Foundation, Inc.
/* 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
@ -13,12 +14,87 @@ 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., 675 Mass Ave,
Cambridge, MA 02139, USA. */
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 STRXFRM strxfrm
# define STRLEN strlen
# define STPNCPY __stpncpy
#endif
/* Include the shared helper functions. `strxfrm'/`wcsxfrm' also use
these functions. */
#include "weight.h"
/* Write 32 bit value UTF-8 encoded but only if enough space is left. */
static __inline size_t
print_val (value, dest, max, act)
u32_t value;
STRING_TYPE *dest;
size_t max;
size_t act;
{
char tmp[6];
int idx = 0;
if (value < 0x80)
tmp[idx++] = (char) value;
else
{
tmp[idx++] = '\x80' + (char) (value & 0x3f);
value >>= 6;
if (value < 0x20)
tmp[idx++] = '\xc0' + (char) value;
else
{
tmp[idx++] = '\x80' + (char) (value & 0x3f);
value >>= 6;
if (value < 0x10)
tmp[idx++] = '\xe0' + (char) value;
else
{
tmp[idx++] = '\x80' + (char) (value & 0x3f);
value >>= 6;
if (value < 0x08)
tmp[idx++] = '\xf0' + (char) value;
else
{
tmp[idx++] = '\x80' + (char) (value & 0x3f);
value >>= 6;
if (value < 0x04)
tmp[idx++] = '\xf8' + (char) value;
else
{
tmp[idx++] = '\x80' + (char) (value & 0x3f);
tmp[idx++] = '\xfc' + (char) (value >> 6);
}
}
}
}
}
while (idx-- > 0)
{
if (act < max)
dest[act] = tmp[idx];
++act;
}
return act;
}
/* Transform SRC into a form such that the result of strcmp
@ -27,13 +103,94 @@ Cambridge, MA 02139, USA. */
their transformation. The transformed string is put in at
most N characters of DEST and its length is returned. */
size_t
strxfrm (dest, src, n)
char *dest;
const char *src;
STRXFRM (dest, src, n)
STRING_TYPE *dest;
const STRING_TYPE *src;
size_t n;
{
if (n == 0)
return strlen (src);
weight_t *forw = NULL;
weight_t *backw = NULL;
size_t pass;
size_t written;
return __stpncpy (dest, src, n) - dest;
/* If the current locale does not specify locale data we use normal
8-bit string comparison. */
if (collate_nrules == 0)
{
if (n != 0)
STPNCPY (dest, src, n);
return STRLEN (src);
}
/* Get full information about the string. This means we get
information for all passes in a special data structure. */
get_string (src, forw, backw);
/* Now we have all the information. In at most the given number of
passes we can finally decide about the order. */
written = 0;
for (pass = 0; pass < collate_nrules; ++pass)
{
int forward = (collate_rules[pass] & sort_forward) != 0;
const weight_t *run = forward ? forw : backw;
int idx = forward ? 0 : run->data[pass].number - 1;
do
{
int ignore = 0;
u32_t w;
/* Here we have to check for IGNORE entries. If these are
found we count them and go on witht he next value. */
while ((w = run->data[pass].value[idx]) == IGNORE_CHAR)
{
++ignore;
if ((forward && ++idx >= run->data[pass].number)
|| (!forward && --idx < 0))
{
weight_t *nextp = forward ? run->next : run->prev;
if (nextp == NULL)
{
w = 0;
break;
}
run = nextp;
idx = forward ? 0 : run->data[pass].number - 1;
}
}
/* Now we have information of the number of ignored weights
and the value of the next weight. We have to add 2
because 0 means EOS and 1 is the intermediate string end. */
if ((collate_rules[pass] & sort_position) != 0)
written = print_val (ignore + 2, dest, n, written);
if (w != 0)
written = print_val (w, dest, n, written);
/* We have to increment the index counters. */
if ((forward && ++idx >= run->data[pass].number)
|| (!forward && --idx < 0))
if (forward)
{
run = run->next;
idx = 0;
}
else
{
run = run->prev;
if (run != NULL)
idx = run->data[pass].number - 1;
}
}
while (run != NULL);
/* Write marker for end of word. */
if (pass + 1 < collate_nrules)
written = print_val (1, dest, n, written);
}
/* Terminate string. */
return print_val (0, dest, n, written);
}

30
wctype/Makefile Normal file
View file

@ -0,0 +1,30 @@
# Copyright (C) 1996 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# 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., 675 Mass Ave,
# Cambridge, MA 02139, USA.
#
# Sub-makefile for wctype portion of the library.
#
subdir := wctype
headers := wctype.h
distribute := cname-lookup.h
routines := wcfuncs wctype iswctype wctrans towctrans
tests := test_wctype
include ../Rules

45
wctype/cname-lookup.h Normal file
View file

@ -0,0 +1,45 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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 "localeinfo.h"
/* Some words on the runtime of this functions. Although there is a
loop in the function the runtime is asymptotically quasi constant.
The reason is that even for the largest character sets HASH_LAYERS
will not grow beyond 15 (a guess!). */
static __inline size_t
cname_lookup (wint_t wc)
{
extern unsigned int *__ctype_names;
unsigned int hash_size, hash_layers;
size_t result, cnt;
hash_size = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_HASH_SIZE);
hash_layers = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_HASH_LAYERS);
result = wc % hash_size;
for (cnt = 0; cnt < hash_layers; ++cnt)
{
if (__ctype_names[result] == wc)
break;
result += hash_size;
}
return cnt < hash_layers ? result : ~((size_t) 0);
}

39
wctype/iswctype.c Normal file
View file

@ -0,0 +1,39 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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 <ctype.h>
#include <wctype.h>
#include "cname-lookup.h"
extern unsigned int *__ctype32_b;
int
iswctype (wint_t wc, wctype_t desc)
{
size_t idx;
idx = cname_lookup (wc);
if (idx == ~((size_t) 0))
return 0;
return __ctype32_b[idx] & desc;
}

75
wctype/test_wctype.c Normal file
View file

@ -0,0 +1,75 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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 <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <wctype.h>
int
main (int argc, char *argv[])
{
int result = 0;
wctype_t bit_alnum = wctype ("alnum");
wctype_t bit_alpha = wctype ("alpha");
wctype_t bit_cntrl = wctype ("cntrl");
wctype_t bit_digit = wctype ("digit");
wctype_t bit_graph = wctype ("graph");
wctype_t bit_lower = wctype ("lower");
wctype_t bit_print = wctype ("print");
wctype_t bit_punct = wctype ("punct");
wctype_t bit_space = wctype ("space");
wctype_t bit_upper = wctype ("upper");
wctype_t bit_xdigit = wctype ("xdigit");
int ch;
if (wctype ("does not exist") != 0)
{
puts ("wctype return value != 0 for non existing property");
result = 1;
}
for (ch = 0; ch < 256; ++ch)
{
#define TEST(test) \
do \
if (is##test (ch) != iswctype ((wchar_t) ch, bit_##test)) \
{ \
printf ("class `%s' test for character \\%o failed\n", \
#test, ch); \
result = 1; \
} \
while (0)
TEST (alnum);
TEST (alpha);
TEST (cntrl);
TEST (digit);
TEST (graph);
TEST (lower);
TEST (print);
TEST (punct);
TEST (space);
TEST (upper);
TEST (xdigit);
}
if (result == 0)
puts ("All test successful!");
exit (result);
}

36
wctype/towctrans.c Normal file
View file

@ -0,0 +1,36 @@
/* towctrans - map wide character using given mapping.
Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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 <wctype.h>
/* Define the lookup function. */
#include "cname-lookup.h"
wint_t
towctrans (wint_t wc, wctrans_t desc)
{
size_t idx;
idx = cname_lookup (wc);
if (idx == ~((size_t) 0))
/* Character is not known. Default action is to simply return it. */
return wc;
return (wint_t) desc[idx];
}

52
wctype/wcfuncs.c Normal file
View file

@ -0,0 +1,52 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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. */
#define __NO_WCTYPE
#include <wctype.h>
#include <ctype.h> /* For __ctype_tolower and __ctype_toupper. */
/* Provide real-function versions of all the wctype macros. */
#define func(name, type) \
int name (wc) wint_t wc; { return iswctype (wc, type); }
func (iswalnum, _ISalnum)
func (iswalpha, _ISalpha)
func (iswcntrl, _IScntrl)
func (iswdigit, _ISdigit)
func (iswlower, _ISlower)
func (iswgraph, _ISgraph)
func (iswprint, _ISprint)
func (iswpunct, _ISpunct)
func (iswspace, _ISspace)
func (iswupper, _ISupper)
func (iswxdigit, _ISxdigit)
wint_t
towlower (wc)
wint_t wc;
{
return towctrans (wc, __ctype_tolower);
}
wint_t
towupper (wc)
wint_t wc;
{
return towctrans (wc, __ctype_toupper);
}

59
wctype/wctrans.c Normal file
View file

@ -0,0 +1,59 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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 <ctype.h>
#include <string.h>
#include <wctype.h>
#include "localeinfo.h"
wctrans_t
wctrans (const char *property)
{
const char *names;
size_t cnt;
unsigned int **result;
names = _NL_CURRENT (LC_CTYPE, _NL_CTYPE_MAP_NAMES);
cnt = 0;
while (names[0] != '\0')
{
if (strcmp (property, names) == 0)
break;
names = strchr (names, '\0') + 1;
++cnt;
}
if (names[0] == '\0')
return 0;
if (cnt == 0)
return (wctrans_t) __ctype_toupper;
else if (cnt == 1)
return (wctrans_t) __ctype_tolower;
/* We have to search the table. */
result = (unsigned int **) &_NL_CURRENT (LC_CTYPE, _NL_CTYPE_WIDTH);
#if __BYTE_ORDER == _BIG_ENDIAN
return (wctrans_t) result[1 + 2 * cnt];
#else
return (wctrans_t) result[1 + 2 * cnt + 1];
#endif
}

56
wctype/wctype.c Normal file
View file

@ -0,0 +1,56 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed 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 <endian.h>
#include <string.h>
#include <wctype.h>
#include "localeinfo.h"
wctype_t
wctype (const char *property)
{
const char *names;
wctype_t result;
names = _NL_CURRENT (LC_CTYPE, _NL_CTYPE_CLASS_NAMES);
for (result = 1; result != 0; result <<= 1)
{
if (strcmp (property, names) == 0)
break;
names = strchr (names, '\0') + 1;
if (names[0] == '\0')
return 0;
}
#if __BYTE_ORDER == __BIG_ENDIAN
return result;
#else
# define SWAPU32(w) \
(((w) << 24) | (((w) & 0xff00) << 8) | (((w) >> 8) & 0xff00) | ((w) >> 24))
# define SWAPU16(w) \
(((w) >> 8) | ((w) << 8))
if (sizeof (wctype_t) == 4)
return SWAPU32 (result);
else
return SWAPU16 (result);
#endif
}

215
wctype/wctype.h Normal file
View file

@ -0,0 +1,215 @@
/* Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
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. */
/*
* ISO/IEC 9899:1990/Amendment 1:1995 7.15:
* Wide-character classification and mapping utilities <wctype.h>
*/
#ifndef _WCTYPE_H
#define _WCTYPE_H 1
#include <features.h>
__BEGIN_DECLS
/* FIXME: should this go into <stddef.h>??? */
#if 0
#define __need_wint_t
#include <stddef.h>
#else
/* Integral type unchanged by default argument promotions that can
hold any value corresponding to members of the extended character
set, as well as at least one value that does not correspond to any
member of the extended character set. */
typedef unsigned int wint_t;
#endif
/* Scalar type that can hold values which represent locale-specific
character mappings. */
typedef const unsigned int *wctrans_t;
/* Scalar type that can hold values which represent locale-specific
character classifications. */
#if 0
typedef unsigned long int wctype_t;
#else
/* For compatibility reasons we have to use shorts for now. */
typedef unsigned short int wctype_t;
#endif
/* Constant expression of type `wint_t' whose value does not correspond
to any member of the extended character set. */
#ifndef WEOF
#define WEOF (0xffffffffu)
#endif
#ifndef _ISbit
/* These are all the characteristics of characters.
If there get to be more than 16 distinct characteristics,
many things must be changed that use `unsigned short int's.
The characteristics are stored always in network byte order (big
endian). We define the bit value interpretations here dependent on the
machine's byte order. */
#include <endian.h>
#if __BYTE_ORDER == __BIG_ENDIAN
#define _ISbit(bit) (1 << bit)
#else /* __BYTE_ORDER == __LITTLE_ENDIAN */
#define _ISbit(bit) (bit < 8 ? ((1 << bit) << 8) : ((1 << bit) >> 8))
#endif
enum
{
_ISupper = _ISbit (0), /* UPPERCASE. */
_ISlower = _ISbit (1), /* lowercase. */
_ISalpha = _ISbit (2), /* Alphabetic. */
_ISdigit = _ISbit (3), /* Numeric. */
_ISxdigit = _ISbit (4), /* Hexadecimal numeric. */
_ISspace = _ISbit (5), /* Whitespace. */
_ISprint = _ISbit (6), /* Printing. */
_ISgraph = _ISbit (7), /* Graphical. */
_ISblank = _ISbit (8), /* Blank (usually SPC and TAB). */
_IScntrl = _ISbit (9), /* Control character. */
_ISpunct = _ISbit (10), /* Punctuation. */
_ISalnum = _ISbit (11) /* Alphanumeric. */
};
#endif /* Not _ISbit */
/*
* Wide-character classification functions: 7.15.2.1.
*/
/* Test for any wide character for which `iswalpha' or `iswdigit' is
true. */
int iswalnum __P ((wint_t __wc));
/* Test for any wide character for which `iswupper' or 'iswlower' is
true, or any wide character that is one of a locale-specific set of
wide-characters for which none of `iswcntrl', `iswdigit',
`iswpunct', or `iswspace' is true. */
int iswalpha __P ((wint_t __wc));
/* Test for any control wide character. */
int iswcntrl __P ((wint_t __wc));
/* Test for any wide character that corresponds to a decimal-digit
character. */
int iswdigit __P ((wint_t __wc));
/* Test for any wide character for which `iswprint' is true and
`iswspace' is false. */
int iswgraph __P ((wint_t __wc));
/* Test for any wide character that corresponds to a lowercase letter
or is one of a locale-specific set of wide characters for which
none of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */
int iswlower __P ((wint_t __wc));
/* Test for any printing wide character. */
int iswprint __P ((wint_t __wc));
/* Test for any printing wide character that is one of a
locale-specific et of wide characters for which neither `iswspace'
nor `iswalnum' is true. */
int iswpunct __P ((wint_t __wc));
/* Test for any wide character that corresponds to a locale-specific
set of wide characters for which none of `iswalnum', `iswgraph', or
`iswpunct' is true. */
int iswspace __P ((wint_t __wc));
/* Test for any wide character that corresponds to an uppercase letter
or is one of a locale-specific set of wide character for which none
of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */
int iswupper __P ((wint_t __wc));
/* Test for any wide character that corresponds to a hexadecimal-digit
character equivalent to that performed be the functions described
in the previous subclause. */
int iswxdigit __P ((wint_t __wc));
/*
* Extensible wide-character classification functions: 7.15.2.2.
*/
/* Construct value that describes a class of wide characters identified
by the string argument PROPERTY. */
wctype_t wctype __P ((__const char *__property));
/* Determine whether the wide-character WC has the property described by
DESC. */
int iswctype __P ((wint_t __wc, wctype_t __desc));
/*
* Wide-character case-mapping functions: 7.15.3.1.
*/
/* Converts an uppercase letter to the corresponding lowercase letter. */
wint_t towlower __P ((wint_t __wc));
/* Converts an lowercase letter to the corresponding uppercase letter. */
wint_t towupper __P ((wint_t __wc));
/*
* Extensible wide-character mapping functions: 7.15.3.2.
*/
/* Construct value that describes a mapping between wide characters
identified by the string argument PROPERTY. */
wctrans_t wctrans __P ((__const char *__property));
/* Map the wide character WC using the mapping described by DESC. */
wint_t towctrans __P ((wint_t __wc, wctrans_t __desc));
#ifndef __NO_WCTYPE
#define iswalnum(wc) iswctype ((wc), _ISalnum)
#define iswalpha(wc) iswctype ((wc), _ISalpha)
#define iswcntrl(wc) iswctype ((wc), _IScntrl)
#define iswdigit(wc) iswctype ((wc), _ISdigit)
#define iswlower(wc) iswctype ((wc), _ISlower)
#define iswgraph(wc) iswctype ((wc), _ISgraph)
#define iswprint(wc) iswctype ((wc), _ISprint)
#define iswpunct(wc) iswctype ((wc), _ISpunct)
#define iswspace(wc) iswctype ((wc), _ISspace)
#define iswupper(wc) iswctype ((wc), _ISupper)
#define iswxdigit(wc) iswctype ((wc), _ISxdigit)
#ifdef __USE_GNU
#define iswblank(wc) iswctype ((wc), _ISblank)
#endif
/* Pointer to conversion tables. */
extern __const int *__ctype_tolower; /* Case conversions. */
extern __const int *__ctype_toupper; /* Case conversions. */
#define towlower(wc) towctrans (wc, __ctype_tolower)
#define towupper(wc) towctrans (wc, __ctype_toupper)
#endif /* Not __NO_WCTYPE. */
__END_DECLS
#endif /* wctype.h */