mirror of
git://sourceware.org/git/glibc.git
synced 2025-04-12 14:21:18 +08:00
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:
parent
53f770e0f9
commit
19bc17a905
105
ChangeLog
105
ChangeLog
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
2
Makefile
2
Makefile
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
@ -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 $<' $@
|
||||
|
@ -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 */
|
||||
|
344
locale/C-ctype.c
344
locale/C-ctype.c
@ -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 }
|
||||
}
|
||||
};
|
||||
|
@ -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: "" }
|
||||
}
|
||||
};
|
||||
|
@ -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" }
|
||||
}
|
||||
};
|
||||
|
@ -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" }
|
||||
}
|
||||
};
|
||||
|
@ -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 }
|
||||
}
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
524
locale/charmap.c
524
locale/charmap.c
@ -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:
|
||||
*/
|
212
locale/collate.c
212
locale/collate.c
@ -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:
|
||||
*/
|
@ -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 */
|
@ -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:
|
||||
*/
|
||||
|
@ -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
|
180
locale/keyword.h
180
locale/keyword.h
@ -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;
|
||||
}
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
*/
|
@ -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:
|
||||
*/
|
@ -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 */
|
@ -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 */
|
||||
|
@ -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:
|
||||
*/
|
@ -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:
|
||||
*/
|
@ -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:
|
||||
*/
|
@ -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:
|
||||
*/
|
@ -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:
|
||||
*/
|
@ -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:
|
||||
*/
|
40
locale/programs/charmap-kw.gperf
Normal file
40
locale/programs/charmap-kw.gperf
Normal 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
|
117
locale/programs/charmap-kw.h
Normal file
117
locale/programs/charmap-kw.h
Normal 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
593
locale/programs/charmap.c
Normal 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
132
locale/programs/charset.c
Normal 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
61
locale/programs/charset.h
Normal 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
33
locale/programs/config.h
Normal 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
|
@ -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
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
1310
locale/programs/ld-ctype.c
Normal file
File diff suppressed because it is too large
Load Diff
237
locale/programs/ld-messages.c
Normal file
237
locale/programs/ld-messages.c
Normal 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");
|
||||
}
|
||||
}
|
385
locale/programs/ld-monetary.c
Normal file
385
locale/programs/ld-monetary.c
Normal 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);
|
||||
}
|
208
locale/programs/ld-numeric.c
Normal file
208
locale/programs/ld-numeric.c
Normal 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
310
locale/programs/ld-time.c
Normal 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");
|
||||
}
|
||||
}
|
579
locale/programs/linereader.c
Normal file
579
locale/programs/linereader.c
Normal 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;
|
||||
}
|
158
locale/programs/linereader.h
Normal file
158
locale/programs/linereader.h
Normal 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 */
|
@ -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
461
locale/programs/localedef.c
Normal 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 = ©_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
207
locale/programs/locales.h
Normal 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 */
|
99
locale/programs/locfile-kw.gperf
Normal file
99
locale/programs/locfile-kw.gperf
Normal 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
|
211
locale/programs/locfile-kw.h
Normal file
211
locale/programs/locfile-kw.h
Normal 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;
|
||||
}
|
147
locale/programs/locfile-token.h
Normal file
147
locale/programs/locfile-token.h
Normal 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
979
locale/programs/locfile.c
Normal 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
75
locale/programs/locfile.h
Normal 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 */
|
146
locale/programs/stringtrans.c
Normal file
146
locale/programs/stringtrans.c
Normal 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;
|
||||
}
|
38
locale/programs/stringtrans.h
Normal file
38
locale/programs/stringtrans.h
Normal 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 */
|
@ -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. */
|
||||
|
@ -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
171
locale/weight.h
Normal 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)
|
77
misc/error.c
77
misc/error.c
@ -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);
|
||||
|
@ -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_ */
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
142
string/strcoll.c
142
string/strcoll.c
@ -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;
|
||||
}
|
||||
|
175
string/strxfrm.c
175
string/strxfrm.c
@ -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
30
wctype/Makefile
Normal 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
45
wctype/cname-lookup.h
Normal 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
39
wctype/iswctype.c
Normal 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
75
wctype/test_wctype.c
Normal 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
36
wctype/towctrans.c
Normal 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
52
wctype/wcfuncs.c
Normal 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
59
wctype/wctrans.c
Normal 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
56
wctype/wctype.c
Normal 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
215
wctype/wctype.h
Normal 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 */
|
Loading…
x
Reference in New Issue
Block a user