diff options
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | iconv/iconv_prog.c | 123 | ||||
-rw-r--r-- | libc.map | 1 | ||||
-rw-r--r-- | libio/fileops.c | 106 | ||||
-rw-r--r-- | libio/libioP.h | 1 |
5 files changed, 188 insertions, 57 deletions
@@ -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. diff --git a/iconv/iconv_prog.c b/iconv/iconv_prog.c index 719f20d..6b34d34 100644 --- a/iconv/iconv_prog.c +++ b/iconv/iconv_prog.c @@ -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 (""); +} @@ -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; diff --git a/libio/fileops.c b/libio/fileops.c index d184916..c75accd 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -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 (;;) + + want = n; + + while (want > 0) { - /* Data available. */ - _IO_ssize_t count = fp->_IO_read_end - fp->_IO_read_ptr; - if (count > 0) + have = fp->_IO_read_end - fp->_IO_read_ptr; + if (want <= have) { - if (count > more) - count = more; - if (count > 20) + memcpy (s, fp->_IO_read_ptr, want); + fp->_IO_read_ptr += want; + want = 0; + } + else + { + if (have > 0) { -#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; + memcpy (s, fp->_IO_read_ptr, have); + want -= have; + s += have; + fp->_IO_read_ptr += have; } - else if (count <= 0) - count = 0; - else + + /* Check for backup and repeat */ + if (_IO_in_backup (fp)) { - 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); + _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), diff --git a/libio/libioP.h b/libio/libioP.h index 785bfee..0452c77 100644 --- a/libio/libioP.h +++ b/libio/libioP.h @@ -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 *)); |