1998-04-01 16:10  Ulrich Drepper  <drepper@cygnus.com>

	* libc.map: Add __gconv_alias_db, __gconv_nmodules, __gconv_modules_db.
	* iconv/iconv_prog.c: Implement --list option to print available
	coded character sets.

1998-04-01 18:10  Zack Weinberg  <zack@rabi.phys.columbia.edu>

	Make fread() read large blocks straight to the user buffer.

	* libio/fileops.c (_IO_file_xsgetn): New function.
	(_IO_file_jumps): Use it.
	* libio/libioP.h: Prototype it.
This commit is contained in:
Ulrich Drepper 1998-04-01 16:15:20 +00:00
parent 5891046a86
commit 8fe0fd03e5
5 changed files with 192 additions and 61 deletions

View file

@ -1,3 +1,17 @@
1998-04-01 16:10 Ulrich Drepper <drepper@cygnus.com>
* libc.map: Add __gconv_alias_db, __gconv_nmodules, __gconv_modules_db.
* iconv/iconv_prog.c: Implement --list option to print available
coded character sets.
1998-04-01 18:10 Zack Weinberg <zack@rabi.phys.columbia.edu>
Make fread() read large blocks straight to the user buffer.
* libio/fileops.c (_IO_file_xsgetn): New function.
(_IO_file_jumps): Use it.
* libio/libioP.h: Prototype it.
1998-04-01 Ulrich Drepper <drepper@cygnus.com>
* iconv/gconv_conf.c (builtin_aliases): New variable.

View file

@ -19,11 +19,14 @@
Boston, MA 02111-1307, USA. */
#include <argp.h>
#include <ctype.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <gconv.h>
#include <iconv.h>
#include <locale.h>
#include <search.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -41,6 +44,7 @@ static void print_version (FILE *stream, struct argp_state *state);
void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
#define OPT_VERBOSE 1000
#define OPT_LIST 1001
/* Definitions of arguments for argp functions. */
static const struct argp_option options[] =
@ -48,6 +52,8 @@ static const struct argp_option options[] =
{ NULL, 0, NULL, 0, N_("Input/Output format specification:") },
{ "from-code", 'f', "NAME", 0, N_("encoding of original text") },
{ "to-code", 't', "NAME", 0, N_("encoding for output") },
{ NULL, 0, NULL, 0, N_("Information:") },
{ "list", OPT_LIST, NULL, 0, N_("list all known coded character sets") },
{ NULL, 0, NULL, 0, N_("Output control:") },
{ "output", 'o', "FILE", 0, N_("output file") },
{ "verbose", OPT_VERBOSE, NULL, 0, N_("print progress information") },
@ -83,11 +89,15 @@ static const char *output_file;
/* Nonzero if verbose ouput is wanted. */
static int verbose;
/* Nonzero if list of all coded character sets is wanted. */
static int list;
/* Prototypes for the functions doing the actual work. */
static int process_block (iconv_t cd, const char *addr, size_t len,
FILE *output);
static int process_fd (iconv_t cd, int fd, FILE *output);
static int process_file (iconv_t cd, FILE *input, FILE *output);
static void print_known_names (void);
int
@ -107,6 +117,13 @@ main (int argc, char *argv[])
/* Parse and process arguments. */
argp_parse (&argp, argc, argv, 0, &remaining, NULL);
/* List all coded character sets if wanted. */
if (list)
{
print_known_names ();
exit (EXIT_SUCCESS);
}
/* If either the from- or to-code is not specified this is an error
since we do not know what to do. */
if (from_code == NULL && to_code == NULL)
@ -237,6 +254,9 @@ parse_opt (int key, char *arg, struct argp_state *state)
case OPT_VERBOSE:
verbose = 1;
break;
case OPT_LIST:
list = 1;
break;
default:
return ARGP_ERR_UNKNOWN;
}
@ -412,3 +432,106 @@ process_file (iconv_t cd, FILE *input, FILE *output)
we haven't read anything so far. */
return process_fd (cd, fileno (input), output);
}
/* Print all known character sets/encodings. */
static void *printlist;
static size_t column;
static int not_first;
static void
insert_print_list (const void *nodep, VISIT value, int level)
{
if (value == leaf || value == postorder)
{
const struct gconv_alias *s = *(const struct gconv_alias **) nodep;
tsearch (s->fromname, &printlist, (__compar_fn_t) strcoll);
}
}
static void
do_print (const void *nodep, VISIT value, int level)
{
if (value == leaf || value == postorder)
{
const char *s = *(const char **) nodep;
size_t len = strlen (s);
size_t cnt;
while (len > 0 && s[len - 1] == '/')
--len;
for (cnt = 0; cnt < len; ++cnt)
if (isalnum (s[cnt]))
break;
if (cnt == len)
return;
if (not_first)
{
putchar (',');
++column;
if (column > 2 && column + len > 77)
{
fputs ("\n ", stdout);
column = 2;
}
else
{
putchar (' ');
++column;
}
}
else
not_first = 1;
fwrite (s, len, 1, stdout);
column += len;
}
}
static void
print_known_names (void)
{
size_t cnt;
iconv_t h;
/* We must initialize the internal databases first. */
h = iconv_open ("L1", "L1");
iconv_close (h);
/* First add the aliases. */
twalk (__gconv_alias_db, insert_print_list);
/* Add the from- and to-names from the known modules. */
for (cnt = 0; cnt < __gconv_nmodules; ++cnt)
{
if (__gconv_modules_db[cnt]->from_pattern == NULL)
{
tsearch (__gconv_modules_db[cnt]->from_constpfx, &printlist,
(__compar_fn_t) strcoll);
tsearch (__gconv_modules_db[cnt]->to_string, &printlist,
(__compar_fn_t) strcoll);
}
else
tsearch (__gconv_modules_db[cnt]->from_pattern, &printlist,
(__compar_fn_t) strcoll);
}
fputs (_("\
The following list contain all the coded character sets known. This does\n\
not necessarily mean that all combinations of these names can be used for\n\
the FROM and TO command line parameters. One coded character set can be\n\
listed with several different names (aliases).\n\
Some of the names are no plain strings but instead regular expressions and\n\
they match a variety of names which can be given as parameters to the\n\
program.\n\n "), stdout);
/* Now print the collected names. */
column = 2;
twalk (printlist, do_print);
if (column != 0)
puts ("");
}

View file

@ -427,6 +427,7 @@ GLIBC_2.1 {
global:
# global variables
_IO_2_1_stdin_; _IO_2_1_stdout_; _IO_2_1_stderr_;
__gconv_alias_db; __gconv_nmodules; __gconv_modules_db;
# This is for ix86 only.
_fp_hw;

View file

@ -775,80 +775,72 @@ _IO_file_xsputn (f, data, n)
return n - to_do;
}
#if 0
/* Work in progress */
_IO_size_t
_IO_file_xsgetn (fp, data, n)
_IO_FILE *fp;
void *data;
_IO_size_t n;
{
register _IO_size_t more = n;
register _IO_size_t want, have, count;
register char *s = data;
for (;;)
{
/* Data available. */
_IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr;
if (count > 0)
{
if (count > more)
count = more;
if (count > 20)
{
#ifdef _LIBC
s = __mempcpy (s, fp->_IO_read_ptr, count);
#else
memcpy (s, fp->_IO_read_ptr, count);
s += count;
#endif
fp->_IO_read_ptr += count;
}
else if (count <= 0)
count = 0;
else
{
register char *p = fp->_IO_read_ptr;
register int i = (int) count;
while (--i >= 0)
*s++ = *p++;
fp->_IO_read_ptr = p;
}
more -= count;
}
#if 0
if (! _IO_in put_mode (fp)
&& ! _IO_have_markers (fp) && ! IO_have_backup (fp))
{
/* This is an optimization of _IO_file_underflow */
if (fp->_flags & _IO_NO_READS)
break;
/* If we're reading a lot of data, don't bother allocating
a buffer. But if we're only reading a bit, perhaps we should ??*/
if (count <= 512 && fp->_IO_buf_base == NULL)
_IO_doallocbuf (fp);
if (fp->_flags & (_IO_LINE_BUF|_IO_UNBUFFERED))
_IO_flush_all_linebuffered ();
_IO_switch_to_get_mode (fp); ???;
count = _IO_SYSREAD (fp, s, more);
want = n;
while (want > 0)
{
have = fp->_IO_read_end - fp->_IO_read_ptr;
if (want <= have)
{
memcpy (s, fp->_IO_read_ptr, want);
fp->_IO_read_ptr += want;
want = 0;
}
else
{
if (have > 0)
{
memcpy (s, fp->_IO_read_ptr, have);
want -= have;
s += have;
fp->_IO_read_ptr += have;
}
/* Check for backup and repeat */
if (_IO_in_backup (fp))
{
_IO_switch_to_main_get_area (fp);
continue;
}
/* If we now want less than a buffer, underflow and repeat
the copy. Otherwise, _IO_SYSREAD directly to
the user buffer. */
if (fp->_IO_buf_base && want < fp->_IO_buf_end - fp->_IO_buf_base)
{
if (__underflow (fp) == EOF)
break;
continue;
}
count = _IO_SYSREAD (fp, s, want);
if (count <= 0)
{
if (count == 0)
fp->_flags |= _IO_EOF_SEEN;
else
fp->_flags |= _IO_ERR_SEEN, count = 0;
}
{
if (count == 0)
fp->_flags |= _IO_EOF_SEEN;
else
fp->_flags |= _IO_ERR_SEEN;
break;
}
s += count;
more -= count;
want -= count;
}
#endif
if (more == 0 || __underflow (fp) == EOF)
break;
}
return n - more;
return n - want;
}
#endif
struct _IO_jump_t _IO_file_jumps =
{
@ -859,7 +851,7 @@ struct _IO_jump_t _IO_file_jumps =
JUMP_INIT(uflow, _IO_default_uflow),
JUMP_INIT(pbackfail, _IO_default_pbackfail),
JUMP_INIT(xsputn, _IO_file_xsputn),
JUMP_INIT(xsgetn, _IO_default_xsgetn),
JUMP_INIT(xsgetn, _IO_file_xsgetn),
JUMP_INIT(seekoff, _IO_file_seekoff),
JUMP_INIT(seekpos, _IO_default_seekpos),
JUMP_INIT(setbuf, _IO_file_setbuf),

View file

@ -368,6 +368,7 @@ extern int _IO_file_doallocate __P ((_IO_FILE *));
extern _IO_FILE* _IO_file_setbuf __P ((_IO_FILE *, char *, _IO_ssize_t));
extern _IO_fpos64_t _IO_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int));
extern _IO_size_t _IO_file_xsputn __P ((_IO_FILE *, const void *, _IO_size_t));
extern _IO_size_t _IO_file_xsgetn __P ((_IO_FILE *, void *, _IO_size_t));
extern int _IO_file_stat __P ((_IO_FILE *, void *));
extern int _IO_file_close __P ((_IO_FILE *));
extern int _IO_file_underflow __P ((_IO_FILE *));