summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Blandy <jimb@red-bean.com>1999-09-06 05:56:10 +0000
committerJim Blandy <jimb@red-bean.com>1999-09-06 05:56:10 +0000
commit5083e79d95b1bbae9a6cccee48890dd80305593b (patch)
treeffd66b1662e8ef8e98c34267a1cd8ef01133dc3c
parent9b5a0fb7e80ae667e535fbf642c50db2c6fb8f16 (diff)
downloadguile-5083e79d95b1bbae9a6cccee48890dd80305593b.tar.gz
* mbconv.c: New file.
* init.c: #include "mbconv.h". (scm_boot_guile_1): call scm_init_mbconv. * mbconv.h: Add extern declaration for scm_init_mbconv. * Makefile.am (libguile_la_SOURCES, BUILT_SOURCES, modinclude_HEADERS): Include the `mbconv' files in the lists. * Makefile.in: Regenerated. * scmconfig.h.in: Regenerated (see configure.in changes).
-rw-r--r--libguile/Makefile.am40
-rw-r--r--libguile/Makefile.in27
-rw-r--r--libguile/init.c4
-rw-r--r--libguile/mbconv.c366
-rw-r--r--libguile/scmconfig.h.in3
5 files changed, 406 insertions, 34 deletions
diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index dda9508d6..fdef34945 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -41,12 +41,12 @@ libguile_la_SOURCES = \
gh_data.c gh_eval.c gh_funcs.c gh_init.c gh_io.c gh_list.c \
gh_predicates.c gsubr.c guardians.c hash.c hashtab.c init.c \
ioext.c keywords.c lang.c list.c load.c macros.c mallocs.c mb.c \
- modules.c net_db.c numbers.c objects.c objprop.c options.c pairs.c \
- ports.c posix.c print.c procprop.c procs.c ramap.c random.c read.c \
- root.c scmsigs.c script.c simpos.c smob.c socket.c sort.c \
- srcprop.c stackchk.c stacks.c stime.c strings.c strop.c strorder.c \
- strports.c struct.c symbols.c tag.c throw.c unif.c variable.c \
- vectors.c version.c vports.c weaks.c
+ mbconv.c modules.c net_db.c numbers.c objects.c objprop.c \
+ options.c pairs.c ports.c posix.c print.c procprop.c procs.c \
+ ramap.c random.c read.c root.c scmsigs.c script.c simpos.c smob.c \
+ socket.c sort.c srcprop.c stackchk.c stacks.c stime.c strings.c \
+ strop.c strorder.c strports.c struct.c symbols.c tag.c throw.c \
+ unif.c variable.c vectors.c version.c vports.c weaks.c
BUILT_SOURCES = \
cpp_err_symbols.c cpp_sig_symbols.c libpath.h alist.x arbiters.x \
@@ -54,13 +54,13 @@ BUILT_SOURCES = \
dynl.x dynwind.x eq.x error.x eval.x evalext.x feature.x filesys.x \
fluids.x fports.x gc.x gsubr.x guardians.x hash.x hashtab.x init.x \
ioext.x iselect.x keywords.x lang.x list.x load.x macros.x \
- mallocs.x mb.x modules.x net_db.x numbers.x objects.x objprop.x \
- options.x pairs.x ports.x posix.x print.x procprop.x procs.x \
- random.x ramap.x read.x regex-posix.x root.x scmsigs.x script.x \
- simpos.x smob.x socket.x sort.x srcprop.x stackchk.x stacks.x \
- stime.x strings.x strop.x strorder.x strports.x struct.x symbols.x \
- tag.x threads.x throw.x unif.x variable.x vectors.x version.x \
- vports.x weaks.x
+ mallocs.x mb.x mbconv.x modules.x net_db.x numbers.x objects.x \
+ objprop.x options.x pairs.x ports.x posix.x print.x procprop.x \
+ procs.x random.x ramap.x read.x regex-posix.x root.x scmsigs.x \
+ script.x simpos.x smob.x socket.x sort.x srcprop.x stackchk.x \
+ stacks.x stime.x strings.x strop.x strorder.x strports.x struct.x \
+ symbols.x tag.x threads.x throw.x unif.x variable.x vectors.x \
+ version.x vports.x weaks.x
EXTRA_libguile_la_SOURCES = _scm.h \
strerror.c inet_aton.c putenv.c \
@@ -90,13 +90,13 @@ modinclude_HEADERS = \
evalext.h feature.h filesys.h fports.h gc.h gdb_interface.h \
gdbint.h genio.h gsubr.h guardians.h hash.h hashtab.h init.h \
ioext.h keywords.h kw.h lang.h list.h load.h macros.h mallocs.h \
- mb.h modules.h net_db.h numbers.h objects.h objprop.h options.h \
- pairs.h ports.h posix.h regex-posix.h print.h procprop.h procs.h \
- random.h ramap.h read.h root.h scmsigs.h script.h simpos.h smob.h \
- socket.h sort.h srcprop.h stackchk.h stacks.h stime.h strings.h \
- strop.h strorder.h strports.h struct.h symbols.h tag.h tags.h \
- throw.h unif.h variable.h vectors.h version.h vports.h weaks.h \
- snarf.h threads.h coop-defs.h fluids.h iselect.h
+ mb.h mbconv.h modules.h net_db.h numbers.h objects.h objprop.h \
+ options.h pairs.h ports.h posix.h regex-posix.h print.h procprop.h \
+ procs.h random.h ramap.h read.h root.h scmsigs.h script.h simpos.h \
+ smob.h socket.h sort.h srcprop.h stackchk.h stacks.h stime.h \
+ strings.h strop.h strorder.h strports.h struct.h symbols.h tag.h \
+ tags.h throw.h unif.h variable.h vectors.h version.h vports.h \
+ weaks.h snarf.h threads.h coop-defs.h fluids.h iselect.h
## This file is generated at configure time. That is why it is DATA
## and not a header -- headers are included in the distribution.
diff --git a/libguile/Makefile.in b/libguile/Makefile.in
index a2e42006f..2e4c47289 100644
--- a/libguile/Makefile.in
+++ b/libguile/Makefile.in
@@ -103,10 +103,10 @@ bin_PROGRAMS = guile
guile_SOURCES = guile.c
guile_LDADD = libguile.la ${THREAD_LIBS_LOCAL}
-libguile_la_SOURCES = alist.c arbiters.c async.c backtrace.c boolean.c chars.c continuations.c debug.c dynl.c dynwind.c eq.c error.c eval.c evalext.c feature.c filesys.c fluids.c fports.c gc.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c gh_io.c gh_list.c gh_predicates.c gsubr.c guardians.c hash.c hashtab.c init.c ioext.c keywords.c lang.c list.c load.c macros.c mallocs.c mb.c modules.c net_db.c numbers.c objects.c objprop.c options.c pairs.c ports.c posix.c print.c procprop.c procs.c ramap.c random.c read.c root.c scmsigs.c script.c simpos.c smob.c socket.c sort.c srcprop.c stackchk.c stacks.c stime.c strings.c strop.c strorder.c strports.c struct.c symbols.c tag.c throw.c unif.c variable.c vectors.c version.c vports.c weaks.c
+libguile_la_SOURCES = alist.c arbiters.c async.c backtrace.c boolean.c chars.c continuations.c debug.c dynl.c dynwind.c eq.c error.c eval.c evalext.c feature.c filesys.c fluids.c fports.c gc.c gdbint.c gh_data.c gh_eval.c gh_funcs.c gh_init.c gh_io.c gh_list.c gh_predicates.c gsubr.c guardians.c hash.c hashtab.c init.c ioext.c keywords.c lang.c list.c load.c macros.c mallocs.c mb.c mbconv.c modules.c net_db.c numbers.c objects.c objprop.c options.c pairs.c ports.c posix.c print.c procprop.c procs.c ramap.c random.c read.c root.c scmsigs.c script.c simpos.c smob.c socket.c sort.c srcprop.c stackchk.c stacks.c stime.c strings.c strop.c strorder.c strports.c struct.c symbols.c tag.c throw.c unif.c variable.c vectors.c version.c vports.c weaks.c
-BUILT_SOURCES = cpp_err_symbols.c cpp_sig_symbols.c libpath.h alist.x arbiters.x async.x backtrace.x boolean.x chars.x continuations.x debug.x dynl.x dynwind.x eq.x error.x eval.x evalext.x feature.x filesys.x fluids.x fports.x gc.x gsubr.x guardians.x hash.x hashtab.x init.x ioext.x iselect.x keywords.x lang.x list.x load.x macros.x mallocs.x mb.x modules.x net_db.x numbers.x objects.x objprop.x options.x pairs.x ports.x posix.x print.x procprop.x procs.x random.x ramap.x read.x regex-posix.x root.x scmsigs.x script.x simpos.x smob.x socket.x sort.x srcprop.x stackchk.x stacks.x stime.x strings.x strop.x strorder.x strports.x struct.x symbols.x tag.x threads.x throw.x unif.x variable.x vectors.x version.x vports.x weaks.x
+BUILT_SOURCES = cpp_err_symbols.c cpp_sig_symbols.c libpath.h alist.x arbiters.x async.x backtrace.x boolean.x chars.x continuations.x debug.x dynl.x dynwind.x eq.x error.x eval.x evalext.x feature.x filesys.x fluids.x fports.x gc.x gsubr.x guardians.x hash.x hashtab.x init.x ioext.x iselect.x keywords.x lang.x list.x load.x macros.x mallocs.x mb.x mbconv.x modules.x net_db.x numbers.x objects.x objprop.x options.x pairs.x ports.x posix.x print.x procprop.x procs.x random.x ramap.x read.x regex-posix.x root.x scmsigs.x script.x simpos.x smob.x socket.x sort.x srcprop.x stackchk.x stacks.x stime.x strings.x strop.x strorder.x strports.x struct.x symbols.x tag.x threads.x throw.x unif.x variable.x vectors.x version.x vports.x weaks.x
EXTRA_libguile_la_SOURCES = _scm.h strerror.c inet_aton.c putenv.c threads.c alloca.c regex-posix.c iselect.c
@@ -125,7 +125,7 @@ pkginclude_HEADERS = gh.h
# These are headers visible as <libguile/mumble.h>.
modincludedir = $(includedir)/libguile
-modinclude_HEADERS = __scm.h alist.h arbiters.h async.h backtrace.h boolean.h chars.h continuations.h debug.h dynl.h dynwind.h eq.h error.h eval.h evalext.h feature.h filesys.h fports.h gc.h gdb_interface.h gdbint.h genio.h gsubr.h guardians.h hash.h hashtab.h init.h ioext.h keywords.h kw.h lang.h list.h load.h macros.h mallocs.h mb.h modules.h net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h regex-posix.h print.h procprop.h procs.h random.h ramap.h read.h root.h scmsigs.h script.h simpos.h smob.h socket.h sort.h srcprop.h stackchk.h stacks.h stime.h strings.h strop.h strorder.h strports.h struct.h symbols.h tag.h tags.h throw.h unif.h variable.h vectors.h version.h vports.h weaks.h snarf.h threads.h coop-defs.h fluids.h iselect.h
+modinclude_HEADERS = __scm.h alist.h arbiters.h async.h backtrace.h boolean.h chars.h continuations.h debug.h dynl.h dynwind.h eq.h error.h eval.h evalext.h feature.h filesys.h fports.h gc.h gdb_interface.h gdbint.h genio.h gsubr.h guardians.h hash.h hashtab.h init.h ioext.h keywords.h kw.h lang.h list.h load.h macros.h mallocs.h mb.h mbconv.h modules.h net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h posix.h regex-posix.h print.h procprop.h procs.h random.h ramap.h read.h root.h scmsigs.h script.h simpos.h smob.h socket.h sort.h srcprop.h stackchk.h stacks.h stime.h strings.h strop.h strorder.h strports.h struct.h symbols.h tag.h tags.h throw.h unif.h variable.h vectors.h version.h vports.h weaks.h snarf.h threads.h coop-defs.h fluids.h iselect.h
modinclude_DATA = scmconfig.h
@@ -170,12 +170,13 @@ error.lo eval.lo evalext.lo feature.lo filesys.lo fluids.lo fports.lo \
gc.lo gdbint.lo gh_data.lo gh_eval.lo gh_funcs.lo gh_init.lo gh_io.lo \
gh_list.lo gh_predicates.lo gsubr.lo guardians.lo hash.lo hashtab.lo \
init.lo ioext.lo keywords.lo lang.lo list.lo load.lo macros.lo \
-mallocs.lo mb.lo modules.lo net_db.lo numbers.lo objects.lo objprop.lo \
-options.lo pairs.lo ports.lo posix.lo print.lo procprop.lo procs.lo \
-ramap.lo random.lo read.lo root.lo scmsigs.lo script.lo simpos.lo \
-smob.lo socket.lo sort.lo srcprop.lo stackchk.lo stacks.lo stime.lo \
-strings.lo strop.lo strorder.lo strports.lo struct.lo symbols.lo tag.lo \
-throw.lo unif.lo variable.lo vectors.lo version.lo vports.lo weaks.lo
+mallocs.lo mb.lo mbconv.lo modules.lo net_db.lo numbers.lo objects.lo \
+objprop.lo options.lo pairs.lo ports.lo posix.lo print.lo procprop.lo \
+procs.lo ramap.lo random.lo read.lo root.lo scmsigs.lo script.lo \
+simpos.lo smob.lo socket.lo sort.lo srcprop.lo stackchk.lo stacks.lo \
+stime.lo strings.lo strop.lo strorder.lo strports.lo struct.lo \
+symbols.lo tag.lo throw.lo unif.lo variable.lo vectors.lo version.lo \
+vports.lo weaks.lo
PROGRAMS = $(bin_PROGRAMS)
guile_OBJECTS = guile.o
@@ -222,10 +223,10 @@ DEP_FILES = .deps/alist.P .deps/alloca.P .deps/arbiters.P .deps/async.P \
.deps/hash.P .deps/hashtab.P .deps/inet_aton.P .deps/init.P \
.deps/ioext.P .deps/iselect.P .deps/keywords.P .deps/lang.P \
.deps/list.P .deps/load.P .deps/macros.P .deps/mallocs.P .deps/mb.P \
-.deps/modules.P .deps/net_db.P .deps/numbers.P .deps/objects.P \
-.deps/objprop.P .deps/options.P .deps/pairs.P .deps/ports.P \
-.deps/posix.P .deps/print.P .deps/procprop.P .deps/procs.P \
-.deps/putenv.P .deps/ramap.P .deps/random.P .deps/read.P \
+.deps/mbconv.P .deps/modules.P .deps/net_db.P .deps/numbers.P \
+.deps/objects.P .deps/objprop.P .deps/options.P .deps/pairs.P \
+.deps/ports.P .deps/posix.P .deps/print.P .deps/procprop.P \
+.deps/procs.P .deps/putenv.P .deps/ramap.P .deps/random.P .deps/read.P \
.deps/regex-posix.P .deps/root.P .deps/scmsigs.P .deps/script.P \
.deps/simpos.P .deps/smob.P .deps/socket.P .deps/sort.P .deps/srcprop.P \
.deps/stackchk.P .deps/stacks.P .deps/stime.P .deps/strerror.P \
diff --git a/libguile/init.c b/libguile/init.c
index d9a8b2dca..527403074 100644
--- a/libguile/init.c
+++ b/libguile/init.c
@@ -46,7 +46,6 @@
#include "_scm.h"
/* Everybody has an init function. */
-#include "mb.h"
#include "alist.h"
#include "arbiters.h"
#include "async.h"
@@ -82,6 +81,8 @@
#include "load.h"
#include "macros.h"
#include "mallocs.h"
+#include "mb.h"
+#include "mbconv.h"
#include "modules.h"
#include "net_db.h"
#include "numbers.h"
@@ -449,6 +450,7 @@ scm_boot_guile_1 (base, closure)
#endif
start_stack (base);
scm_init_mb ();
+ scm_init_mbconv ();
scm_init_gsubr ();
scm_init_feature ();
scm_init_alist ();
diff --git a/libguile/mbconv.c b/libguile/mbconv.c
new file mode 100644
index 000000000..e3a256aa0
--- /dev/null
+++ b/libguile/mbconv.c
@@ -0,0 +1,366 @@
+/* Copyright (C) 1999 Free Software Foundation, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307 USA
+ *
+ * As a special exception, the Free Software Foundation gives permission
+ * for additional uses of the text contained in its release of GUILE.
+ *
+ * The exception is that, if you link the GUILE library with other files
+ * to produce an executable, this does not by itself cause the
+ * resulting executable to be covered by the GNU General Public License.
+ * Your use of that executable is in no way restricted on account of
+ * linking the GUILE library code into it.
+ *
+ * This exception does not however invalidate any other reasons why
+ * the executable file might be covered by the GNU General Public License.
+ *
+ * This exception applies only to the code released by the
+ * Free Software Foundation under the name GUILE. If you copy
+ * code from other Free Software Foundation releases into a copy of
+ * GUILE, as the General Public License permits, the exception does
+ * not apply to the code that you add in this way. To avoid misleading
+ * anyone as to the status of such modified files, you must delete
+ * this exception notice from them.
+ *
+ * If you write modifications of your own for GUILE, it is your choice
+ * whether to permit this exception to apply to your modifications.
+ * If you do not wish that, delete this exception notice.
+ */
+
+/* Much code here is borrowed from Tom Tromey's libunicode --- thanks,
+ Tom! Unfortunately, I can't simply use libunicode itself at the
+ moment, since our canonical internal encoding is different. When
+ Emacs and Guile switch to UTF-8, hopefully that will change. */
+
+
+/* Headers. */
+
+#include "_scm.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mbconv.h"
+
+#ifdef HAVE_ICONV
+# include <iconv.h>
+#else
+/* This is harmless as it is completely ignored by the code when the
+ above condition is false. */
+typedef void *iconv_t;
+#endif
+
+
+/* Exceptions. */
+
+SCM_GLOBAL_SYMBOL (scm_text_unknown_encoding, "text:unknown-encoding");
+static const char text_unknown_encoding_msg[] =
+ "unable to convert from encoding `%s' to encoding `%s'";
+
+
+/* The implementation of the conversion context object. */
+
+struct scm_mb_iconv_ours
+{
+ /* Converter from source character set to Guile character set. */
+ struct scm_mb_encoding *from;
+
+ /* Converter private data. */
+ void *from_data;
+
+ /* Converter from Guile character set to destination character set. */
+ struct scm_mb_encoding *to;
+
+ /* Converter private data. */
+ void *to_data;
+
+ /* Buffer used to store intermediate results. */
+ scm_char_t *buffer;
+
+ /* Number of valid characters in buffer. */
+ size_t valid;
+
+ /* Total number of character slots in buffer. */
+ size_t size;
+};
+
+struct scm_mb_iconv
+{
+ /* Type of converter. */
+ enum {
+ scm_mb_iconv_type_native,
+ scm_mb_iconv_type_ours
+ } type;
+
+ union
+ {
+ iconv_t native; /* Used in `native' case. */
+ struct scm_mb_iconv_ours ours; /* Used in `our' case. */
+ } u;
+};
+
+
+/* The registry of all encodings. */
+
+/* Linked list of all character sets. */
+static struct scm_mb_encoding *encodings;
+
+void
+scm_mb_register_encoding (struct scm_mb_encoding *vec)
+{
+ vec->next = encodings;
+ encodings = vec;
+}
+
+static struct scm_mb_encoding *
+find_encoding (const char *name)
+{
+ struct scm_mb_encoding *cs;
+
+ for (cs = encodings; cs; cs = cs->next)
+ {
+ int i;
+ for (i = 0; cs->names[i]; ++i)
+ {
+ if (! strcasecmp (cs->names[i], name))
+ return cs;
+ }
+ }
+
+ return cs;
+}
+
+
+/* Creating and destroying conversion contexts. */
+
+static void
+no_memory_for_open (struct scm_mb_iconv *r)
+{
+ if (r)
+ {
+ if (r->u.ours.buffer) free (r->u.ours.buffer);
+ free (r);
+ }
+
+ scm_memory_error ("scm_mb_iconv_open");
+}
+
+struct scm_mb_iconv *
+scm_mb_iconv_open (const char *tocode, const char *fromcode)
+{
+ struct scm_mb_iconv *r = (struct scm_mb_iconv *) malloc (sizeof (*r));
+
+ if (! r)
+ no_memory_for_open (r);
+
+ r->u.ours.buffer = 0;
+
+ /* Try our encodings first. */
+ r->u.ours.from = find_encoding (fromcode);
+ if (r->u.ours.from)
+ r->u.ours.to = find_encoding (tocode);
+ if (r->u.ours.from && r->u.ours.to)
+ {
+ r->type = scm_mb_iconv_type_ours;
+
+ /* FIXME: how to pick the size? */
+ r->u.ours.size = 1024;
+ r->u.ours.buffer = (scm_char_t *) malloc (r->u.ours.size
+ * sizeof (scm_char_t));
+ if (! r->u.ours.buffer)
+ no_memory_for_open (r);
+
+ r->u.ours.valid = 0;
+
+ if (r->u.ours.from->init
+ && ! r->u.ours.from->init (&r->u.ours.from_data))
+ no_memory_for_open (r);
+
+ if (r->u.ours.to->init && ! r->u.ours.to->init (&r->u.ours.to_data))
+ {
+ if (r->u.ours.from->destroy)
+ r->u.ours.from->destroy (&r->u.ours.from_data);
+ no_memory_for_open (r);
+ }
+
+ return r;
+ }
+
+#ifdef HAVE_ICONV
+ /* We don't have the conversions the user requested. Try the
+ system's iconv library. */
+ r->u.native = iconv_open (tocode, fromcode);
+ if (r->u.native != (iconv_t) -1)
+ {
+ r->type = scm_mb_iconv_type_native;
+ return r;
+ }
+#endif
+
+ free (r);
+
+ {
+ SCM args = SCM_LIST2 (scm_makfrom0str (fromcode),
+ scm_makfrom0str (tocode));
+
+ scm_error (scm_text_unknown_encoding, "scm_mb_iconv_open",
+ text_unknown_encoding_msg, args, args);
+ }
+
+ return 0;
+}
+
+void
+scm_mb_iconv_close (struct scm_mb_iconv *cd)
+{
+ switch (cd->type)
+ {
+ case scm_mb_iconv_type_native:
+#ifdef HAVE_ICONV
+ if (iconv_close (cd->u.native) < 0)
+ scm_syserror ("scm_mb_iconv_close");
+ break;
+#else
+ abort ();
+#endif
+
+ case scm_mb_iconv_type_ours:
+ if (cd->u.ours.to->destroy)
+ cd->u.ours.to->destroy (&cd->u.ours.to_data);
+ if (cd->u.ours.from->destroy)
+ cd->u.ours.from->destroy (&cd->u.ours.from_data);
+ free (cd->u.ours.buffer);
+ break;
+ }
+
+ free (cd);
+}
+
+
+/* Actually converting text. */
+
+size_t
+scm_mb_iconv (struct scm_mb_iconv *context,
+ const char **inbuf, size_t *inbytesleft,
+ char **outbuf, size_t *outbytesleft)
+{
+ struct scm_mb_iconv_ours *ours;
+
+#ifdef HAVE_ICONV
+ if (context->type == scm_mb_iconv_type_native)
+ {
+ size_t result = iconv (context->u.native,
+ inbuf, inbytesleft,
+ outbuf, outbytesleft);
+ if (result == (size_t) -1)
+ switch (errno)
+ {
+ case EILSEQ: return scm_mb_iconv_bad_encoding;
+ case E2BIG: return scm_mb_iconv_more_room;
+ case EINVAL: return scm_mb_iconv_incomplete_encoding;
+ default:
+ scm_syserror ("scm_mb_iconv");
+ }
+ else
+ return result;
+ }
+#endif /* HAVE_ICONV */
+
+ ours = &context->u.ours;
+
+ /* If inbuf or *inbuf is zero, then we need to reset the conversion
+ states. */
+ if (! inbuf || ! *inbuf)
+ {
+ int result;
+
+ /* Try to reset the output conversion first; if it fails, we need to
+ leave the input conversion state untouched. */
+ result = ours->to->reset (ours->to_data, outbuf, outbytesleft);
+ if (result < 0)
+ return result;
+
+ /* Reset the input context. */
+ return ours->from->reset (ours->from_data, 0, 0);
+ }
+
+ if (! outbuf || *outbytesleft <= 0)
+ return scm_mb_iconv_more_room;
+
+ /* Oh! We actually have some *TEXT* to convert! Not bureaucracy!!! */
+ while (*inbytesleft > 0)
+ {
+ /* Convert as many characters as possible from the input buffer
+ into the intermediate scm_char_t buffer. */
+ {
+ scm_char_t *buf = ours->buffer + ours->valid;
+ size_t buf_left = ours->size - ours->valid;
+ enum scm_mb_read_result read_result
+ = ours->from->read (ours->from_data, inbuf, inbytesleft,
+ &buf, &buf_left);
+ ours->valid = ours->size - buf_left;
+
+ if (*inbytesleft < 0)
+ abort ();
+
+ switch (read_result)
+ {
+ case scm_mb_read_ok:
+ break;
+ case scm_mb_read_incomplete:
+ return scm_mb_iconv_incomplete_encoding;
+ case scm_mb_read_error:
+ return scm_mb_iconv_bad_encoding;
+ default:
+ abort ();
+ }
+ }
+
+ /* Convert as many characters as possible from the intermediate
+ scm_char_t buffer to the output buffer. */
+ {
+ scm_char_t *buf = ours->buffer;
+ size_t buf_left = ours->valid;
+ enum scm_mb_write_result write_result
+ = ours->to->write (ours->to_data, &buf, &buf_left,
+ outbuf, outbytesleft);
+ if (buf_left > 0)
+ memmove (ours->buffer, buf, buf_left * sizeof (scm_char_t));
+ ours->valid = buf_left;
+ switch (write_result)
+ {
+ case scm_mb_write_ok:
+ break;
+ case scm_mb_write_more_room:
+ return scm_mb_iconv_more_room;
+ default:
+ abort ();
+ }
+ }
+ }
+
+ return 0;
+}
+
+
+/* Initialization. */
+
+void
+scm_init_mbconv ()
+{
+#include "mbconv.x"
+}
diff --git a/libguile/scmconfig.h.in b/libguile/scmconfig.h.in
index 4412efdd8..3ffd8fc34 100644
--- a/libguile/scmconfig.h.in
+++ b/libguile/scmconfig.h.in
@@ -236,6 +236,9 @@
/* Define if you have the gettimeofday function. */
#undef HAVE_GETTIMEOFDAY
+/* Define if you have the iconv function. */
+#undef HAVE_ICONV
+
/* Define if you have the inet_aton function. */
#undef HAVE_INET_ATON