Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Update.
2000-10-01  Bruno Haible  <haible@clisp.cons.org>

	* charmaps/BIG5: Add a width table.
	* charmaps/GB18030: Likewise.
	* charmaps/ISO-8859-6: Likewise.
	* charmaps/ISO-8859-8: Likewise.
	* charmaps/TIS-620: Likewise.
  • Loading branch information
Ulrich Drepper committed Oct 1, 2000
1 parent d77cd29 commit 3e07621
Show file tree
Hide file tree
Showing 9 changed files with 480 additions and 163 deletions.
1 change: 1 addition & 0 deletions include/spawn.h
@@ -0,0 +1 @@
#include <posix/spawn.h>
5 changes: 3 additions & 2 deletions locale/Makefile
Expand Up @@ -33,7 +33,7 @@ distribute = localeinfo.h categories.def iso-639.def iso-3166.def \
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)
3level.h charmap-dir.h)
routines = setlocale findlocale loadlocale localeconv nl_langinfo \
nl_langinfo_l mb_cur_max codeset_name \
newlocale duplocale freelocale
Expand All @@ -59,7 +59,7 @@ vpath %.gperf programs
localedef-modules := $(categories:%=ld-%) charmap linereader locfile \
repertoire
locale-modules := locale-spec
lib-modules := simple-hash xmalloc xstrdup
lib-modules := charmap-dir simple-hash xmalloc xstrdup


GPERF = gperf
Expand Down Expand Up @@ -94,6 +94,7 @@ locale-CPPFLAGS := -DLOCALE_PATH='$(localepath)' \

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
Expand Down
312 changes: 312 additions & 0 deletions locale/programs/charmap-dir.c
@@ -0,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);
}
}
48 changes: 48 additions & 0 deletions locale/programs/charmap-dir.h
@@ -0,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 */

0 comments on commit 3e07621

Please sign in to comment.