This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
gzipped charmap installation
- To: libc-alpha at sources dot redhat dot com
- Subject: gzipped charmap installation
- From: Bruno Haible <haible at ilog dot fr>
- Date: Sun, 1 Oct 2000 14:47:41 +0200 (CEST)
The total size of the charmaps has grown from 3 MB to 11 MB in glibc-2.2.
Here are the total sizes of /usr/share/i18n/charmaps:
glibc-2.1.3 3336 KB
glibc-2.1.94 11696 KB
Since the charmaps are only ever used by "localedef" and "locale -m", i.e.
very rarely, here is a patch to install them in gzipped format. (Same as
what is done with man pages, info pages, X11 PCF fonts, etc.) The total
size then decreases to
glibc-2.1.94 with gzip 2352 KB
glibc-2.1.94 with bzip2 1812 KB
"localedef" continues to accept the same arguments as before, "locale -m"
produces the same output as before. But they are modified to look first
for an uncompressed charmap, then for a gzipped charmap, then (for the
sake of distributions, like Mandrake, which generally prefer bzip2 to
gzip) for a bzipped charmap. When reading the charmap, the decompressor
is called in a subprocess.
In order to avoid code duplication between locale.c and charmap.c, the
patch abstract the charmap directory handling routines into an extra file,
used by both "locale" and "localedef".
The patch furthermore
- adds an include file include/spawn.h so I can use <spawn.h> inside
glibc,
- uses xstrdup instead of strdup in locale.c, for reliability,
- makes the _DIRENT_HAVE_D_TYPE code consistent with the default code
(The default code calls 'stat', not 'lstat', therefore the
_DIRENT_HAVE_D_TYPE code should not treat symbolic links pointing
to regular files as invalid.)
- removes the obsolete repertoiremaps variables and installation rules
from localedata/Makefile.
2000-09-30 Bruno Haible <haible@clisp.cons.org>
* locale/programs/charmap-dir.h: New file.
* locale/programs/charmap-dir.c: New file.
* locale/programs/linereader.h (lr_create): New declaration.
* locale/programs/linereader.c (lr_create): New function, split out
from lr_open.
(lr_open): Tailcall lr_create.
* locale/programs/locale.c: Include "charmap-dir.h". Don't include
<unistd.h>.
(xstrdup): New declaration.
(more_help): Use xstrdup instead of strdup.
(write_locales): Likewise. When encountering a symbolic link, call
stat.
(write_charmaps): Simplify using the charmap-dir.h functions.
Use xstrdup instead of strdup.
* locale/programs/charmap.c: Include "charmap-dir.h". Don't include
<dirent.h> and <unistd.h>.
(cmlr_open): New function.
(charmap_read): Use cmlr_open instead of lr_open. Simplify using the
charmap-dir.h functions.
* locale/Makefile (distribute): Add charmap-dir.h.
(lib-modules): Add charmap-dir.
(CFLAGS-charmap-dir.c): Set to -Wno-write-strings, because posix_spawn
wants a 'char **', not a 'const char **'.
* include/spawn.h: New file.
2000-09-30 Bruno Haible <haible@clisp.cons.org>
* Makefile (repertoiremaps): Remove variable.
(distribute): Remove repertoiremaps.
(install-others): Likewise. Add .gz to charmaps.
($(inst_i18ndir)/charmaps/%): Install in gzipped format.
*** glibc-20000928/locale/programs/charmap-dir.h.bak Fri Sep 29 11:02:56 2000
--- glibc-20000928/locale/programs/charmap-dir.h Sat Sep 30 20:47:50 2000
***************
*** 0 ****
--- 1,48 ----
+ /* Copyright (C) 2000 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. */
+
+ #ifndef _CHARMAP_DIR_H
+ #define _CHARMAP_DIR_H 1
+
+ /* The data type of a charmap directory being traversed. */
+ typedef struct charmap_dir CHARMAP_DIR;
+
+ /* Starts a charmap directory traversal.
+ Returns a CHARMAP_DIR, or NULL if the directory doesn't exist. */
+ extern CHARMAP_DIR *charmap_opendir (const char *directory);
+
+ /* Reads the next directory entry.
+ Returns its charmap name, or NULL if past the last entry or upon error.
+ The storage returned may be overwritten by a later charmap_readdir
+ call on the same CHARMAP_DIR. */
+ extern const char *charmap_readdir (CHARMAP_DIR *dir);
+
+ /* Finishes a charmap directory traversal, and frees the resources
+ attached to the CHARMAP_DIR. */
+ extern int charmap_closedir (CHARMAP_DIR *dir);
+
+ /* Returns a NULL terminated list of alias names of a charmap. */
+ extern char **charmap_aliases (const char *directory, const char *name);
+
+ /* Frees an alias list returned by charmap_aliases. */
+ extern void charmap_free_aliases (char **aliases);
+
+ /* Opens a charmap for reading, given its name (not an alias name). */
+ extern FILE *charmap_open (const char *directory, const char *name);
+
+ #endif /* _CHARMAP_DIR_H */
*** glibc-20000928/locale/programs/charmap-dir.c.bak Fri Sep 29 11:02:59 2000
--- glibc-20000928/locale/programs/charmap-dir.c Sat Sep 30 22:15:50 2000
***************
*** 0 ****
--- 1,312 ----
+ /* Copyright (C) 2000 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 <dirent.h>
+ #include <errno.h>
+ #include <error.h>
+ #include <fcntl.h>
+ #include <libintl.h>
+ #include <spawn.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+ #include <sys/stat.h>
+
+ #include "charmap-dir.h"
+
+ extern void *xmalloc (size_t n);
+ extern void *xrealloc (void *p, size_t n);
+
+ /* The data type of a charmap directory being traversed. */
+ struct charmap_dir
+ {
+ DIR *dir;
+ /* The directory pathname, ending in a slash. */
+ char *directory;
+ size_t directory_len;
+ /* Scratch area used for returning pathnames. */
+ char *pathname;
+ size_t pathname_size;
+ };
+
+ /* Starts a charmap directory traversal.
+ Returns a CHARMAP_DIR, or NULL if the directory doesn't exist. */
+ CHARMAP_DIR *
+ charmap_opendir (const char *directory)
+ {
+ struct charmap_dir *cdir;
+ DIR *dir;
+ size_t len;
+ int add_slash;
+
+ dir = opendir (directory);
+ if (dir == NULL)
+ {
+ error (1, errno, gettext ("cannot read character map directory `%s'"),
+ directory);
+ return NULL;
+ }
+
+ cdir = (struct charmap_dir *) xmalloc (sizeof (struct charmap_dir));
+ cdir->dir = dir;
+
+ len = strlen (directory);
+ add_slash = (len == 0 || directory[len - 1] != '/');
+ cdir->directory = (char *) xmalloc (len + add_slash + 1);
+ memcpy (cdir->directory, directory, len);
+ if (add_slash)
+ cdir->directory[len] = '/';
+ cdir->directory[len + add_slash] = '\0';
+ cdir->directory_len = len + add_slash;
+
+ cdir->pathname = NULL;
+ cdir->pathname_size = 0;
+
+ return cdir;
+ }
+
+ /* Reads the next directory entry.
+ Returns its charmap name, or NULL if past the last entry or upon error.
+ The storage returned may be overwritten by a later charmap_readdir
+ call on the same CHARMAP_DIR. */
+ const char *
+ charmap_readdir (CHARMAP_DIR *cdir)
+ {
+ for (;;)
+ {
+ struct dirent *dirent;
+ size_t len;
+ size_t size;
+ char *filename;
+ mode_t mode;
+
+ dirent = readdir (cdir->dir);
+ if (dirent == NULL)
+ return NULL;
+ if (strcmp (dirent->d_name, ".") == 0)
+ continue;
+ if (strcmp (dirent->d_name, "..") == 0)
+ continue;
+
+ len = strlen (dirent->d_name);
+
+ size = cdir->directory_len + len + 1;
+ if (size > cdir->pathname_size)
+ {
+ free (cdir->pathname);
+ if (size < 2 * cdir->pathname_size)
+ size = 2 * cdir->pathname_size;
+ cdir->pathname = (char *) xmalloc (size);
+ cdir->pathname_size = size;
+ }
+
+ stpcpy (stpcpy (cdir->pathname, cdir->directory), dirent->d_name);
+ filename = cdir->pathname + cdir->directory_len;
+
+ #ifdef _DIRENT_HAVE_D_TYPE
+ if (dirent->d_type != DT_UNKNOWN && dirent->d_type != DT_LNK)
+ mode = DTTOIF (dirent->d_type);
+ else
+ #endif
+ {
+ struct stat statbuf;
+
+ if (stat (cdir->pathname, &statbuf) < 0)
+ continue;
+
+ mode = statbuf.st_mode;
+ }
+
+ if (!S_ISREG (mode))
+ continue;
+
+ /* For compressed charmaps, the canonical charmap name does not
+ include the extension. */
+ if (len > 3 && memcmp (&filename[len - 3], ".gz", 3) == 0)
+ filename[len - 3] = '\0';
+ else if (len > 4 && memcmp (&filename[len - 4], ".bz2", 4) == 0)
+ filename[len - 4] = '\0';
+
+ return filename;
+ }
+ }
+
+ /* Finishes a charmap directory traversal, and frees the resources
+ attached to the CHARMAP_DIR. */
+ int
+ charmap_closedir (CHARMAP_DIR *cdir)
+ {
+ DIR *dir = cdir->dir;
+
+ free (cdir->directory);
+ free (cdir->pathname);
+ free (cdir);
+ return closedir (dir);
+ }
+
+ /* Creates a subprocess decompressing the given pathname, and returns
+ a stream reading its output (the decompressed data). */
+ static
+ FILE *
+ fopen_uncompressed (const char *pathname, char *compressor)
+ {
+ int pfd;
+
+ pfd = open (pathname, O_RDONLY);
+ if (pfd >= 0)
+ {
+ struct stat statbuf;
+ int fd[2];
+
+ if (fstat (pfd, &statbuf) >= 0
+ && S_ISREG (statbuf.st_mode)
+ && pipe (fd) >= 0)
+ {
+ char *argv[4] = { compressor, "-d", "-c", NULL };
+ posix_spawn_file_actions_t actions;
+
+ if (posix_spawn_file_actions_init (&actions) == 0)
+ {
+ if (posix_spawn_file_actions_adddup2 (&actions,
+ fd[1], STDOUT_FILENO) == 0
+ && posix_spawn_file_actions_addclose (&actions, fd[1]) == 0
+ && posix_spawn_file_actions_addclose (&actions, fd[0]) == 0
+ && posix_spawn_file_actions_adddup2 (&actions,
+ pfd, STDIN_FILENO) == 0
+ && posix_spawn_file_actions_addclose (&actions, pfd) == 0
+ && posix_spawnp (NULL, compressor, &actions, NULL,
+ argv, environ) == 0)
+ {
+ posix_spawn_file_actions_destroy (&actions);
+ close (fd[1]);
+ close (pfd);
+ return fdopen (fd[0], "r");
+ }
+ posix_spawn_file_actions_destroy (&actions);
+ }
+ close (fd[1]);
+ close (fd[0]);
+ }
+ close (pfd);
+ }
+ return NULL;
+ }
+
+ /* Opens a charmap for reading, given its name (not an alias name). */
+ FILE *
+ charmap_open (const char *directory, const char *name)
+ {
+ size_t dlen = strlen (directory);
+ int add_slash = (dlen == 0 || directory[dlen - 1] != '/');
+ size_t nlen = strlen (name);
+ char *pathname;
+ char *p;
+ FILE *stream;
+
+ pathname = alloca (dlen + add_slash + nlen + 5);
+ p = stpcpy (pathname, directory);
+ if (add_slash)
+ *p++ = '/';
+ p = stpcpy (p, name);
+
+ stream = fopen (pathname, "r");
+ if (stream != NULL)
+ return stream;
+
+ memcpy (p, ".gz", 4);
+ stream = fopen_uncompressed (pathname, "gzip");
+ if (stream != NULL)
+ return stream;
+
+ memcpy (p, ".bz2", 5);
+ stream = fopen_uncompressed (pathname, "bzip2");
+ if (stream != NULL)
+ return stream;
+
+ return NULL;
+ }
+
+ /* An empty alias list. Avoids the need to return NULL from
+ charmap_aliases. */
+ static char *empty[1];
+
+ /* Returns a NULL terminated list of alias names of a charmap. */
+ char **
+ charmap_aliases (const char *directory, const char *name)
+ {
+ FILE *stream;
+ char **aliases;
+ size_t naliases;
+
+ stream = charmap_open (directory, name);
+ if (stream == NULL)
+ return empty;
+
+ aliases = NULL;
+ naliases = 0;
+
+ while (!feof (stream))
+ {
+ char *alias = NULL;
+ char junk[BUFSIZ];
+
+ if (fscanf (stream, " <code_set_name> %as", &alias) == 1
+ || fscanf (stream, "%% alias %as", &alias) == 1)
+ {
+ aliases = (char **) xrealloc (aliases,
+ (naliases + 2) * sizeof (char *));
+ aliases[naliases++] = alias;
+ }
+
+ /* Read the rest of the line. */
+ if (fgets (junk, sizeof junk, stream) != NULL)
+ {
+ if (strstr (junk, "CHARMAP") != NULL)
+ /* We cannot expect more aliases from now on. */
+ break;
+
+ while (strchr (junk, '\n') == NULL
+ && fgets (junk, sizeof junk, stream) != NULL)
+ continue;
+ }
+ }
+
+ fclose (stream);
+
+ if (naliases == 0)
+ return empty;
+
+ aliases[naliases] = NULL;
+ return aliases;
+ }
+
+ /* Frees an alias list returned by charmap_aliases. */
+ void
+ charmap_free_aliases (char **aliases)
+ {
+ if (aliases != empty)
+ {
+ char **p;
+
+ for (p = aliases; *p; p++)
+ free (*p);
+
+ free (aliases);
+ }
+ }
*** glibc-20000928/locale/programs/linereader.h.bak Tue Sep 7 16:54:47 1999
--- glibc-20000928/locale/programs/linereader.h Sat Sep 30 01:02:56 2000
***************
*** 1,4 ****
! /* Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper, <drepper@gnu.org>.
--- 1,4 ----
! /* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper, <drepper@gnu.org>.
***************
*** 85,90 ****
--- 85,91 ----
/* Functions defined in linereader.c. */
extern struct linereader *lr_open (const char *fname, kw_hash_fct_t hf);
+ extern struct linereader *lr_create (FILE *fp, const char *fname, kw_hash_fct_t hf);
extern int lr_eof (struct linereader *lr);
extern void lr_close (struct linereader *lr);
extern int lr_next (struct linereader *lr);
*** glibc-20000928/locale/programs/linereader.c.bak Tue Aug 15 11:06:58 2000
--- glibc-20000928/locale/programs/linereader.c Sat Sep 30 01:02:03 2000
***************
*** 47,69 ****
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 ? : "<stdin>");
result->buf = NULL;
result->bufsize = 0;
result->lineno = 1;
--- 47,75 ----
lr_open (const char *fname, kw_hash_fct_t hf)
{
FILE *fp;
if (fname == NULL || strcmp (fname, "-") == 0
|| strcmp (fname, "/dev/stdin") == 0)
! return lr_create (stdin, "<stdin>", hf);
else
{
fp = fopen (fname, "r");
if (fp == NULL)
return NULL;
+ return lr_create (fp, fname, hf);
}
+ }
+
+ struct linereader *
+ lr_create (FILE *fp, const char *fname, kw_hash_fct_t hf)
+ {
+ struct linereader *result;
+ int n;
result = (struct linereader *) xmalloc (sizeof (*result));
result->fp = fp;
! result->fname = xstrdup (fname);
result->buf = NULL;
result->bufsize = 0;
result->lineno = 1;
*** glibc-20000928/locale/programs/locale.c.bak Wed Jul 12 18:11:43 2000
--- glibc-20000928/locale/programs/locale.c Sat Sep 30 21:45:44 2000
***************
*** 35,44 ****
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
- #include <unistd.h>
#include <sys/stat.h>
#include "localeinfo.h"
/* If set print the name of the category. */
--- 35,46 ----
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "localeinfo.h"
+ #include "charmap-dir.h"
+
+ extern char *xstrdup (const char *__str);
/* If set print the name of the category. */
***************
*** 251,257 ****
{
case ARGP_KEY_HELP_EXTRA:
/* We print some extra information. */
! return strdup (gettext ("\
Report bugs using the `glibcbug' script to <bugs@gnu.org>.\n"));
default:
break;
--- 253,259 ----
{
case ARGP_KEY_HELP_EXTRA:
/* We print some extra information. */
! return xstrdup (gettext ("\
Report bugs using the `glibcbug' script to <bugs@gnu.org>.\n"));
default:
break;
***************
*** 320,326 ****
{
mode_t mode;
#ifdef _DIRENT_HAVE_D_TYPE
! if (dirent->d_type != DT_UNKNOWN)
mode = DTTOIF (dirent->d_type);
else
#endif
--- 322,328 ----
{
mode_t mode;
#ifdef _DIRENT_HAVE_D_TYPE
! if (dirent->d_type != DT_UNKNOWN && dirent->d_type != DT_LNK)
mode = DTTOIF (dirent->d_type);
else
#endif
***************
*** 348,354 ****
"/LC_CTYPE");
if (stat (buf, &st) == 0 && S_ISREG (st.st_mode))
! PUT (strdup (dirent->d_name));
}
}
--- 350,356 ----
"/LC_CTYPE");
if (stat (buf, &st) == 0 && S_ISREG (st.st_mode))
! PUT (xstrdup (dirent->d_name));
}
}
***************
*** 425,431 ****
*cp++ = '\0';
/* Add the alias. */
! PUT (strdup (alias));
}
}
--- 427,433 ----
*cp++ = '\0';
/* Add the alias. */
! PUT (xstrdup (alias));
}
}
***************
*** 453,536 ****
write_charmaps (void)
{
void *all_data = NULL;
! DIR *dir;
! struct dirent *dirent;
! dir = opendir (CHARMAP_PATH);
if (dir == NULL)
! {
! error (1, errno, gettext ("cannot read character map directory `%s'"),
! CHARMAP_PATH);
! return;
! }
!
! /* 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)
! {
! char *buf = NULL;
! mode_t mode;
!
! #ifdef _DIRENT_HAVE_D_TYPE
! if (dirent->d_type != DT_UNKNOWN)
! mode = DTTOIF (dirent->d_type);
! else
! #endif
! {
! struct stat st;
! buf = alloca (sizeof (CHARMAP_PATH) + strlen (dirent->d_name) + 1);
!
! stpcpy (stpcpy (stpcpy (buf, CHARMAP_PATH), "/"), dirent->d_name);
! if (stat (buf, &st) < 0)
! continue;
! mode = st.st_mode;
! }
! if (S_ISREG (mode))
! {
! FILE *fp;
! PUT (strdup (dirent->d_name));
! /* Read the file and learn about the code set name. */
! if (buf == NULL)
! {
! buf = alloca (sizeof (CHARMAP_PATH)
! + strlen (dirent->d_name) + 1);
!
! stpcpy (stpcpy (stpcpy (buf, CHARMAP_PATH), "/"),
! dirent->d_name);
! }
!
! fp = fopen (buf, "r");
! if (fp != NULL)
! {
! char *name = NULL;
!
! while (!feof (fp))
! {
! char junk[BUFSIZ];
!
! if (fscanf (fp, " <code_set_name> %as", &name) == 1)
! break;
!
! while (fgets (junk, sizeof junk, fp) != NULL
! && strchr (junk, '\n') == NULL)
! continue;
! }
!
! fclose (fp);
!
! if (name != NULL)
! PUT (name);
! }
! }
! }
! closedir (dir);
twalk (all_data, print_names);
}
--- 455,492 ----
write_charmaps (void)
{
void *all_data = NULL;
! CHARMAP_DIR *dir;
! const char *dirent;
! /* Look for all files in the charmap directory. */
! dir = charmap_opendir (CHARMAP_PATH);
if (dir == NULL)
! return;
! while ((dirent = charmap_readdir (dir)) != NULL)
! {
! char **aliases;
! char **p;
! PUT (xstrdup (dirent));
! aliases = charmap_aliases (CHARMAP_PATH, dirent);
! #if 0
! /* Add the code_set_name and the aliases. */
! for (p = aliases; *p; p++)
! PUT (xstrdup (*p));
! #else
! /* Add the code_set_name only. Most aliases are obsolete. */
! p = aliases;
! if (*p)
! PUT (xstrdup (*p));
! #endif
! charmap_free_aliases (aliases);
! }
! charmap_closedir (dir);
twalk (all_data, print_names);
}
*** glibc-20000928/locale/programs/charmap.c.bak Sat Sep 30 00:52:16 2000
--- glibc-20000928/locale/programs/charmap.c Sat Sep 30 22:05:22 2000
***************
*** 22,39 ****
#endif
#include <ctype.h>
- #include <dirent.h>
#include <errno.h>
#include <libintl.h>
#include <limits.h>
#include <obstack.h>
#include <stdlib.h>
#include <string.h>
- #include <unistd.h>
#include "error.h"
#include "linereader.h"
#include "charmap.h"
#include "locfile.h"
#include "repertoire.h"
--- 22,38 ----
#endif
#include <ctype.h>
#include <errno.h>
#include <libintl.h>
#include <limits.h>
#include <obstack.h>
#include <stdlib.h>
#include <string.h>
#include "error.h"
#include "linereader.h"
#include "charmap.h"
+ #include "charmap-dir.h"
#include "locfile.h"
#include "repertoire.h"
***************
*** 55,60 ****
--- 54,84 ----
int nbytes, char *bytes, const char *from,
const char *to, int decimal_ellipsis, int step);
+ static struct linereader *
+ cmlr_open (const char *directory, const char *name, kw_hash_fct_t hf)
+ {
+ FILE *fp;
+
+ fp = charmap_open (directory, name);
+ if (fp == NULL)
+ return NULL;
+ else
+ {
+ size_t dlen = strlen (directory);
+ int add_slash = (dlen == 0 || directory[dlen - 1] != '/');
+ size_t nlen = strlen (name);
+ char *pathname;
+ char *p;
+
+ pathname = alloca (dlen + add_slash + nlen + 1);
+ p = stpcpy (pathname, directory);
+ if (add_slash)
+ *p++ = '/';
+ stpcpy (p, name);
+
+ return lr_create (fp, pathname, hf);
+ }
+ }
struct charmap_t *
charmap_read (const char *filename)
***************
*** 76,101 ****
char *i18npath = getenv ("I18NPATH");
if (i18npath != NULL && *i18npath != '\0')
{
! char path[strlen (filename) + 1 + strlen (i18npath)
! + sizeof ("/charmaps/") - 1];
char *next;
i18npath = strdupa (i18npath);
-
while (cmfile == NULL
&& (next = strsep (&i18npath, ":")) != NULL)
{
! stpcpy (stpcpy (stpcpy (path, next), "/charmaps/"),
! filename);
!
! cmfile = lr_open (path, charmap_hash);
if (cmfile == NULL)
{
/* Try without the "/charmaps" part. */
! stpcpy (stpcpy (path, next), filename);
!
! cmfile = lr_open (path, charmap_hash);
}
}
}
--- 100,119 ----
char *i18npath = getenv ("I18NPATH");
if (i18npath != NULL && *i18npath != '\0')
{
! char path[strlen (i18npath) + sizeof ("/charmaps")];
char *next;
i18npath = strdupa (i18npath);
while (cmfile == NULL
&& (next = strsep (&i18npath, ":")) != NULL)
{
! stpcpy (stpcpy (path, next), "/charmaps");
! cmfile = cmlr_open (path, filename, charmap_hash);
if (cmfile == NULL)
{
/* Try without the "/charmaps" part. */
! cmfile = cmlr_open (next, filename, charmap_hash);
}
}
}
***************
*** 103,112 ****
if (cmfile == NULL)
{
/* Try the default directory. */
! char path[sizeof (CHARMAP_PATH) + strlen (filename) + 1];
!
! stpcpy (stpcpy (stpcpy (path, CHARMAP_PATH), "/"), filename);
! cmfile = lr_open (path, charmap_hash);
}
}
}
--- 121,127 ----
if (cmfile == NULL)
{
/* Try the default directory. */
! cmfile = cmlr_open (CHARMAP_PATH, filename, charmap_hash);
}
}
}
***************
*** 125,197 ****
/* OK, one more try. We also accept the names given to the
character sets in the files. Sometimes they differ from the
file name. */
! DIR *dir;
! struct dirent *dirent;
! dir = opendir (CHARMAP_PATH);
if (dir != NULL)
{
! while ((dirent = readdir (dir)) != NULL)
! if (strcmp (dirent->d_name, ".") != 0
! && strcmp (dirent->d_name, "..") != 0)
! {
! char buf[sizeof (CHARMAP_PATH)
! + strlen (dirent->d_name) + 1];
! FILE *fp;
! #ifdef _DIRENT_HAVE_D_TYPE
! if (dirent->d_type != DT_UNKNOWN && dirent->d_type != DT_REG)
! continue;
! #endif
! stpcpy (stpcpy (stpcpy (buf, CHARMAP_PATH), "/"),
! dirent->d_name);
! fp = fopen (buf, "r");
! if (fp != NULL)
{
! char *name = NULL;
! while (!feof (fp))
! {
! char junk[BUFSIZ];
!
! if (fscanf (fp, " <code_set_name> %as", &name) == 1
! || fscanf (fp, "%% alias %as", &name) == 1)
! {
! if (strcasecmp (name, filename) == 0)
! break;
!
! free (name);
! name = NULL;
! }
!
! if (fgets (junk, sizeof junk, fp) != NULL)
! {
! if (strstr (junk, "CHARMAP") != NULL)
! /* We cannot expect more aliases from now on. */
! break;
!
! while (strchr (junk, '\n') == NULL
! && fgets (junk, sizeof junk, fp) != NULL)
! continue;
! }
! }
!
! fclose (fp);
!
! if (name != NULL)
! {
! struct linereader *cmfile;
!
! cmfile = lr_open (buf, charmap_hash);
! result = (cmfile == NULL
! ? NULL : parse_charmap (cmfile));
! break;
! }
! }
! }
! closedir (dir);
}
}
--- 140,181 ----
/* OK, one more try. We also accept the names given to the
character sets in the files. Sometimes they differ from the
file name. */
! CHARMAP_DIR *dir;
! dir = charmap_opendir (CHARMAP_PATH);
if (dir != NULL)
{
! const char *dirent;
! while ((dirent = charmap_readdir (dir)) != NULL)
! {
! char **aliases;
! char **p;
! int found;
!
! aliases = charmap_aliases (CHARMAP_PATH, dirent);
! found = 0;
! for (p = aliases; *p; p++)
! if (strcasecmp (*p, filename) == 0)
{
! found = 1;
! break;
! }
! charmap_free_aliases (aliases);
! if (found)
! {
! struct linereader *cmfile;
! cmfile = cmlr_open (CHARMAP_PATH, dirent, charmap_hash);
! if (cmfile != NULL)
! result = parse_charmap (cmfile);
! break;
! }
! }
!
! charmap_closedir (dir);
}
}
***************
*** 199,207 ****
{
struct linereader *cmfile;
! cmfile = lr_open (CHARMAP_PATH "/" DEFAULT_CHARMAP, charmap_hash);
!
! result = cmfile == NULL ? NULL : parse_charmap (cmfile);
if (result == NULL)
error (4, errno, _("default character map file `%s' not found"),
--- 183,191 ----
{
struct linereader *cmfile;
! cmfile = cmlr_open (CHARMAP_PATH, DEFAULT_CHARMAP, charmap_hash);
! if (cmfile != NULL)
! result = parse_charmap (cmfile);
if (result == NULL)
error (4, errno, _("default character map file `%s' not found"),
*** glibc-20000928/locale/Makefile.bak Tue Sep 26 14:39:55 2000
--- glibc-20000928/locale/Makefile Sat Sep 30 17:47:23 2000
***************
*** 33,39 ****
charmap-kw.gperf charmap-kw.h locfile-token.h \
locfile-kw.gperf locfile-kw.h linereader.h \
locfile.h charmap.h repertoire.h localedef.h \
! 3level.h)
routines = setlocale findlocale loadlocale localeconv nl_langinfo \
nl_langinfo_l mb_cur_max codeset_name \
newlocale duplocale freelocale
--- 33,39 ----
charmap-kw.gperf charmap-kw.h locfile-token.h \
locfile-kw.gperf locfile-kw.h linereader.h \
locfile.h charmap.h repertoire.h localedef.h \
! 3level.h charmap-dir.h)
routines = setlocale findlocale loadlocale localeconv nl_langinfo \
nl_langinfo_l mb_cur_max codeset_name \
newlocale duplocale freelocale
***************
*** 59,65 ****
localedef-modules := $(categories:%=ld-%) charmap linereader locfile \
repertoire
locale-modules := locale-spec
! lib-modules := simple-hash xmalloc xstrdup
GPERF = gperf
--- 59,65 ----
localedef-modules := $(categories:%=ld-%) charmap linereader locfile \
repertoire
locale-modules := locale-spec
! lib-modules := charmap-dir simple-hash xmalloc xstrdup
GPERF = gperf
***************
*** 94,99 ****
--- 94,100 ----
CFLAGS-charmap.c = -Wno-write-strings -Wno-char-subscripts
CFLAGS-locfile.c = -Wno-write-strings -Wno-char-subscripts
+ CFLAGS-charmap-dir.c = -Wno-write-strings
# Depend on libc.so so a DT_NEEDED is generated in the shared objects.
# This ensures they will load libc.so for needed symbols if loaded by
*** glibc-20000928/include/spawn.h.bak Sat Sep 30 17:40:55 2000
--- glibc-20000928/include/spawn.h Sat Sep 30 17:41:59 2000
***************
*** 0 ****
--- 1 ----
+ #include <posix/spawn.h>
*** glibc-20000928/localedata/Makefile.bak Tue Sep 26 14:39:55 2000
--- glibc-20000928/localedata/Makefile Sat Sep 30 22:47:38 2000
***************
*** 31,40 ****
locales := $(filter-out $(addprefix locales/, CVS RCS SCCS %~), \
$(wildcard locales/*))
- # List of repertoire maps.
- repertoiremaps := $(filter-out $(addprefix repertoiremaps/, CVS RCS SCCS %~), \
- $(wildcard repertoiremaps/*))
-
subdir-dirs = tests-mbwc
vpath %.c tests-mbwc
--- 31,36 ----
***************
*** 64,70 ****
$(addprefix tstfmon_,$(fmon-tests)) \
distribute := CHECKSUMS README SUPPORTED ChangeLog \
! $(charmaps) $(locales) $(repertoiremaps) \
tst-rpmatch.sh tst-locale.sh tst-fmon.sh sort-test.sh \
tst-fmon.data $(test-input-data) $(ld-test-srcs) \
th_TH.in cs_CZ.in tst-mbswcs.sh tst-trans.sh tst-ctype.sh \
--- 60,66 ----
$(addprefix tstfmon_,$(fmon-tests)) \
distribute := CHECKSUMS README SUPPORTED ChangeLog \
! $(charmaps) $(locales) \
tst-rpmatch.sh tst-locale.sh tst-fmon.sh sort-test.sh \
tst-fmon.data $(test-input-data) $(ld-test-srcs) \
th_TH.in cs_CZ.in tst-mbswcs.sh tst-trans.sh tst-ctype.sh \
***************
*** 98,112 ****
endif
# Files to install.
! install-others := $(addprefix $(inst_i18ndir)/, $(charmaps) $(locales) \
! $(repertoiremaps))
include ../Rules
! # Install the source files in the appropriate directories.
! $(inst_i18ndir)/charmaps/%: charmaps/% $(+force); $(do-install)
$(inst_i18ndir)/locales/%: locales/% $(+force); $(do-install)
- $(inst_i18ndir)/repertoiremaps/%: repertoiremaps/% $(+force); $(do-install)
# gcc does not know all the format specifiers we are using here.
CFLAGS-tst-mbswcs1.c = -Wno-format
--- 94,114 ----
endif
# Files to install.
! install-others := $(addprefix $(inst_i18ndir)/, \
! $(addsuffix .gz, $(charmaps)) \
! $(locales))
include ../Rules
! # Install the charmap files in gzipped format.
! $(inst_i18ndir)/charmaps/%.gz: charmaps/% $(+force)
! $(make-target-directory)
! rm -f $(@:.gz=) $@
! $(INSTALL_DATA) $< $(@:.gz=)
! gzip -9 $(@:.gz=)
!
! # Install the locale source files in the appropriate directory.
$(inst_i18ndir)/locales/%: locales/% $(+force); $(do-install)
# gcc does not know all the format specifiers we are using here.
CFLAGS-tst-mbswcs1.c = -Wno-format