summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Blandy <jimb@red-bean.com>1999-09-02 10:47:19 +0000
committerJim Blandy <jimb@red-bean.com>1999-09-02 10:47:19 +0000
commit313ab4b3d451b1c070e130bac3c99a2d3f003c31 (patch)
tree41103c1eeb9f297885f4d9a645f9269a94e35342
parent755a7125790fab364e1f4747aa31b18c99adb398 (diff)
downloadguile-313ab4b3d451b1c070e130bac3c99a2d3f003c31.tar.gz
* Makefile.am (check_PROGRAMS): add check_mb.
(check_mb_SOURCES, check_mb_LDADD): New variables. (check-local): Run check_mb. * check_mb.c: New file, testing multibyte processing functions. * mb.c (scm_mb_get_func): Fix typo in variable name. (scm_mb_walk): Fix another typo in variable name. (scm_mb_multibyte_to_fixed): Use the right variable for the end of the multibyte text. (scm_mb_fixed_to_multibyte): Use the return value from scm_mb_put, instead of making a separate call to scm_mb_len.
-rw-r--r--libguile/Makefile.am5
-rw-r--r--libguile/Makefile.in36
-rw-r--r--libguile/check_mb.c324
-rw-r--r--libguile/mb.c11
-rw-r--r--libguile/mb.h17
5 files changed, 364 insertions, 29 deletions
diff --git a/libguile/Makefile.am b/libguile/Makefile.am
index 364a9c76f..dda9508d6 100644
--- a/libguile/Makefile.am
+++ b/libguile/Makefile.am
@@ -105,15 +105,18 @@ modinclude_DATA = scmconfig.h
bin_SCRIPTS = guile-snarf
check_ldadd = libguile.la ${THREAD_LIBS_LOCAL}
-check_PROGRAMS = gh_test_c gh_test_repl
+check_PROGRAMS = gh_test_c gh_test_repl check_mb
gh_test_c_SOURCES = gh_test_c.c
gh_test_c_LDADD = ${check_ldadd}
gh_test_repl_SOURCES = gh_test_repl.c
gh_test_repl_LDADD = ${check_ldadd}
+check_mb_SOURCES = check_mb.c
+check_mb_LDADD = ${check_ldadd}
check-local:
echo '(+ 1 2 3)' | GUILE_LOAD_PATH=${top_srcdir}:.. ./gh_test_c; echo
echo '(+ 1 2 3)' | GUILE_LOAD_PATH=${top_srcdir}:.. ./gh_test_repl; echo
+ GUILE_LOAD_PATH=${top_srcdir}:.. ./check_mb
EXTRA_DIST = ChangeLog-gh ChangeLog-scm ChangeLog-threads dynl-dl.c \
dynl-dld.c dynl-shl.c dynl-vms.c DYNAMIC-LINKING cpp_signal.c cpp_errno.c \
diff --git a/libguile/Makefile.in b/libguile/Makefile.in
index 6d4445cc4..a2e42006f 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 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 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 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 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 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 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
@@ -133,11 +133,13 @@ modinclude_DATA = scmconfig.h
bin_SCRIPTS = guile-snarf
check_ldadd = libguile.la ${THREAD_LIBS_LOCAL}
-check_PROGRAMS = gh_test_c gh_test_repl
+check_PROGRAMS = gh_test_c gh_test_repl check_mb
gh_test_c_SOURCES = gh_test_c.c
gh_test_c_LDADD = ${check_ldadd}
gh_test_repl_SOURCES = gh_test_repl.c
gh_test_repl_LDADD = ${check_ldadd}
+check_mb_SOURCES = check_mb.c
+check_mb_LDADD = ${check_ldadd}
EXTRA_DIST = ChangeLog-gh ChangeLog-scm ChangeLog-threads dynl-dl.c dynl-dld.c dynl-shl.c dynl-vms.c DYNAMIC-LINKING cpp_signal.c cpp_errno.c cpp_err_symbols.in cpp_sig_symbols.in cpp_cnvt.awk coop-threads.h.cygnus coop-threads.c.cygnus mit-pthreads.h mit-pthreads.c fsu-pthreads.h
@@ -168,7 +170,7 @@ 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 modules.lo net_db.lo numbers.lo objects.lo objprop.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 \
@@ -185,6 +187,9 @@ gh_test_c_LDFLAGS =
gh_test_repl_OBJECTS = gh_test_repl.o
gh_test_repl_DEPENDENCIES = libguile.la
gh_test_repl_LDFLAGS =
+check_mb_OBJECTS = check_mb.o
+check_mb_DEPENDENCIES = libguile.la
+check_mb_LDFLAGS =
SCRIPTS = $(bin_SCRIPTS)
CFLAGS = @CFLAGS@
@@ -206,17 +211,17 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
GZIP_ENV = --best
DEP_FILES = .deps/alist.P .deps/alloca.P .deps/arbiters.P .deps/async.P \
-.deps/backtrace.P .deps/boolean.P .deps/chars.P .deps/continuations.P \
-.deps/cpp_err_symbols.P .deps/cpp_sig_symbols.P .deps/debug.P \
-.deps/dynl.P .deps/dynwind.P .deps/eq.P .deps/error.P .deps/eval.P \
-.deps/evalext.P .deps/feature.P .deps/filesys.P .deps/fluids.P \
-.deps/fports.P .deps/gc.P .deps/gdbint.P .deps/gh_data.P \
+.deps/backtrace.P .deps/boolean.P .deps/chars.P .deps/check_mb.P \
+.deps/continuations.P .deps/cpp_err_symbols.P .deps/cpp_sig_symbols.P \
+.deps/debug.P .deps/dynl.P .deps/dynwind.P .deps/eq.P .deps/error.P \
+.deps/eval.P .deps/evalext.P .deps/feature.P .deps/filesys.P \
+.deps/fluids.P .deps/fports.P .deps/gc.P .deps/gdbint.P .deps/gh_data.P \
.deps/gh_eval.P .deps/gh_funcs.P .deps/gh_init.P .deps/gh_io.P \
.deps/gh_list.P .deps/gh_predicates.P .deps/gh_test_c.P \
.deps/gh_test_repl.P .deps/gsubr.P .deps/guardians.P .deps/guile.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/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 \
@@ -228,8 +233,8 @@ DEP_FILES = .deps/alist.P .deps/alloca.P .deps/arbiters.P .deps/async.P \
.deps/struct.P .deps/symbols.P .deps/tag.P .deps/threads.P \
.deps/throw.P .deps/unif.P .deps/variable.P .deps/vectors.P \
.deps/version.P .deps/vports.P .deps/weaks.P
-SOURCES = $(libguile_la_SOURCES) $(EXTRA_libguile_la_SOURCES) $(guile_SOURCES) $(gh_test_c_SOURCES) $(gh_test_repl_SOURCES)
-OBJECTS = $(libguile_la_OBJECTS) $(guile_OBJECTS) $(gh_test_c_OBJECTS) $(gh_test_repl_OBJECTS)
+SOURCES = $(libguile_la_SOURCES) $(EXTRA_libguile_la_SOURCES) $(guile_SOURCES) $(gh_test_c_SOURCES) $(gh_test_repl_SOURCES) $(check_mb_SOURCES)
+OBJECTS = $(libguile_la_OBJECTS) $(guile_OBJECTS) $(gh_test_c_OBJECTS) $(gh_test_repl_OBJECTS) $(check_mb_OBJECTS)
all: all-redirect
.SUFFIXES:
@@ -380,6 +385,10 @@ gh_test_repl: $(gh_test_repl_OBJECTS) $(gh_test_repl_DEPENDENCIES)
@rm -f gh_test_repl
$(LINK) $(gh_test_repl_LDFLAGS) $(gh_test_repl_OBJECTS) $(gh_test_repl_LDADD) $(LIBS)
+check_mb: $(check_mb_OBJECTS) $(check_mb_DEPENDENCIES)
+ @rm -f check_mb
+ $(LINK) $(check_mb_LDFLAGS) $(check_mb_OBJECTS) $(check_mb_LDADD) $(LIBS)
+
install-binSCRIPTS: $(bin_SCRIPTS)
@$(NORMAL_INSTALL)
$(mkinstalldirs) $(DESTDIR)$(bindir)
@@ -658,6 +667,7 @@ maintainer-clean-generic clean mostlyclean distclean maintainer-clean
check-local:
echo '(+ 1 2 3)' | GUILE_LOAD_PATH=${top_srcdir}:.. ./gh_test_c; echo
echo '(+ 1 2 3)' | GUILE_LOAD_PATH=${top_srcdir}:.. ./gh_test_repl; echo
+ GUILE_LOAD_PATH=${top_srcdir}:.. ./check_mb
libpath.h: $(srcdir)/Makefile.in $(top_builddir)/config.status
@echo "Generating libpath.h..."
diff --git a/libguile/check_mb.c b/libguile/check_mb.c
new file mode 100644
index 000000000..2131cecb2
--- /dev/null
+++ b/libguile/check_mb.c
@@ -0,0 +1,324 @@
+/* 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.
+ */
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gh.h>
+
+struct pair {
+ scm_char_t character;
+ unsigned char encoding[10];
+ int encoding_length;
+};
+
+struct pair pairs[] = {
+
+ /* Check some ASCII characters. */
+ { 0, { 0 }, 1 },
+ { 127, { 127 }, 1 },
+ { 31, { 31 }, 1 },
+ { 32, { 32 }, 1 },
+ { 42, { 42 }, 1 },
+
+ /* Sometimes we mark something as an "end of range", when it's not
+ actually the last character that would use that encoding form.
+ This is because not all character set numbers are assigned, and we
+ can't use unassigned character set numbers. So the value given is
+ the last value which actually corresponds to something in a real
+ character set. */
+
+ /* Check some characters encoded in two bytes. */
+ { 2208, { 0x81, 0xA0 }, 2 }, /* beginning of range */
+ { 3839, { 0x8d, 0xFF }, 2 }, /* end of range */
+ { 2273, { 0x81, 0xE1 }, 2 },
+
+ /* Check some big characters encoded in three bytes. */
+ { 20512, { 0x90, 0xA0, 0xA0 }, 3 }, /* beginning of range */
+ { 180223, { 0x99, 0xFF, 0xFF }, 3 }, /* end of range */
+ { 53931, { 0x92, 0xA5, 0xAB }, 3 },
+
+ /* Check some small characters encoded in three bytes --- some from
+ the 0x9A prefix range, and some from the 0x9B prefix range. */
+ { 6176, { 0x9A, 0xA0, 0xA0 }, 3 }, /* start of the #9A prefix range */
+ { 7167, { 0x9A, 0xA7, 0xFF }, 3 }, /* end of the #9A prefix range */
+ { 14368, { 0x9B, 0xE0, 0xA0 }, 3 }, /* start of the #9B prefix range */
+ { 14591, { 0x9B, 0xE1, 0xFF }, 3 }, /* end of the #9B prefix range */
+
+ /* Check some characters encoded in four bytes. */
+ { 266272, { 0x9C, 0xF0, 0xA0, 0xA0 }, 4 },/* start of the #9C prefix range */
+ { 294911, { 0x9C, 0xF1, 0xFF, 0xFF }, 4 },/* end of the #9C prefix range */
+ { 348192, { 0x9D, 0xF5, 0xA0, 0xA0 }, 4 },/* start of the #9D prefix range */
+ { 475135, { 0x9D, 0xFC, 0xFF, 0xFF }, 4 },/* start of the #9D prefix range */
+
+ { 0, { 0 }, 0 }
+};
+
+#define NUM_PAIRS ((sizeof (pairs) / sizeof (pairs[0])) - 1)
+
+
+static void
+test_one_char_encodings ()
+{
+ struct pair *p;
+
+ for (p = pairs; p->encoding_length > 0; p++)
+ {
+ unsigned char buffer[scm_mb_max_len + 10];
+ int i;
+ int len;
+
+ /* scm_mb_len_char should return a sane value. */
+ len = scm_mb_len_char (p->character);
+ if (len <= 0 || len > scm_mb_max_len)
+ exit (1);
+ if (len != p->encoding_length)
+ exit (1);
+
+ /* scm_mb_put should return the same length, and write that many
+ characters, but no more. */
+ memset (buffer, 1, sizeof (buffer));
+ if (scm_mb_put (p->character, buffer) != len)
+ exit (1);
+ for (i = 0; i < len; i++)
+ if (buffer[i] == 1)
+ exit (1);
+ for (; i < sizeof (buffer); i++)
+ if (buffer[i] != 1)
+ exit (1);
+
+ /* Compare the encoding against the one in our table. */
+ if (memcmp (buffer, p->encoding, len))
+ exit (1);
+
+ /* Try to get the character, and see if it works. */
+ if (scm_mb_get (buffer) != p->character)
+ exit (1);
+
+ /* Check against value returned by scm_mb_len. */
+ if (scm_mb_len (buffer[0]) != len)
+ exit (1);
+
+ /* Test ceiling and floor functions. */
+ for (i = 0; i < len; i++)
+ if (scm_mb_floor (buffer + i) != buffer)
+ exit (1);
+ for (i = 1; i < len; i++)
+ if (scm_mb_ceiling (buffer + i) != buffer + len)
+ exit (1);
+ }
+}
+
+
+/* Fill BUFFER with LEN random numbers in the range 0 to MODULUS - 1.
+ Use SEED to choose the random numbers. */
+static void
+make_permutation (int modulus, int len, int *buffer, unsigned int seed)
+{
+ int i;
+
+ srandom (seed);
+ for (i = 0; i < len; i++)
+ buffer[i] = (unsigned long) random () % modulus;
+
+ if (len > 0)
+ buffer[(unsigned long) random % len] = seed % modulus;
+}
+
+#define MAX_STRING_LEN 20
+static void
+test_string_encodings ()
+{
+ int perm[MAX_STRING_LEN];
+ unsigned char buffer[scm_mb_max_len * MAX_STRING_LEN];
+ int start[MAX_STRING_LEN];
+ unsigned int seed;
+ int len;
+
+ for (seed = 0; seed < 100; seed++)
+ for (len = 0; len < MAX_STRING_LEN; len++)
+ {
+ int i;
+ int bytes;
+ struct pair *p;
+ unsigned char *t;
+
+ /* Choose a random sequence of characters to try out. */
+ make_permutation (NUM_PAIRS, len, perm, seed);
+
+ /* Render those characters into the buffer. */
+ t = buffer;
+ bytes = 0;
+ for (i = 0; i < len; i++)
+ {
+ start[i] = t - buffer;
+ p = &pairs[perm[i]];
+ t += scm_mb_put (p->character, t);
+ bytes += p->encoding_length;
+ }
+ if (t != buffer + bytes)
+ exit (1);
+
+ /* Check its length. */
+ if (scm_mb_count (buffer, bytes) != len)
+ exit (1);
+
+ /* Read it back using the offsets we recorded. */
+ for (i = 0; i < len; i++)
+ {
+ if (! scm_mb_boundary_p (buffer + start[i]))
+ exit (1);
+ if (scm_mb_get (buffer + start[i]) != pairs[perm[i]].character)
+ exit (1);
+ }
+
+ /* Read it back using scm_mb_walk. */
+ t = buffer;
+ for (i = 0; i < len; i++)
+ {
+ if (scm_mb_walk ((const unsigned char **)&t) != pairs[perm[i]].character)
+ exit (1);
+ if (t > buffer + bytes)
+ exit (1);
+ }
+ if (t != buffer + bytes)
+ exit (1);
+
+ /* Try going forward and backward for each character. */
+ for (i = 0; i < len - 1; i++)
+ {
+ if (scm_mb_prev (buffer + start[i + 1]) != buffer + start[i])
+ exit (1);
+ if (scm_mb_next (buffer + start[i]) != buffer + start[i + 1])
+ exit (1);
+ }
+
+ /* Try fetching characters out of the middle, without caching. */
+ for (i = 0; i < len; i++)
+ if (scm_mb_index (buffer, bytes, i) != buffer + start[i])
+ exit (1);
+
+ /* Try fetching characters out of the middle, with caching. */
+ {
+ struct scm_mb_cache cache;
+
+ cache.character = 0;
+ cache.byte = 0;
+
+ /* scan forwards */
+ for (i = 0; i < len; i++)
+ if (scm_mb_index_cached (buffer, bytes, i, &cache)
+ != buffer + start[i])
+ exit (1);
+
+ /* scan backwards */
+ for (i = len - 1; i >= 0; i--)
+ if (scm_mb_index_cached (buffer, bytes, i, &cache)
+ != buffer + start[i])
+ exit (1);
+
+ /* Try fetching characters in random order, with caching. */
+ {
+ int index[MAX_STRING_LEN];
+
+ for (i = 0; i < len; i++)
+ index[i] = i;
+
+ srandom (seed + len + 1);
+ for (i = 0; i < len; i++)
+ {
+ int j, temp;
+ j = (unsigned long) random () % len;
+ temp = index[i];
+ index[i] = index[j];
+ index[j] = temp;
+ }
+
+ for (i = 0; i < len; i++)
+ if (scm_mb_index_cached (buffer, bytes, index[i], &cache)
+ != buffer + start[index[i]])
+ exit (1);
+ }
+ }
+
+ /* Try converting whole strings back and forth. */
+ {
+ int result_len;
+ scm_char_t *copy = scm_mb_multibyte_to_fixed (buffer, bytes,
+ &result_len);
+ unsigned char *copy2;
+
+ if (result_len != len)
+ exit (1);
+ for (i = 0; i < len; i++)
+ if (copy[i] != pairs[perm[i]].character)
+ exit (1);
+
+ copy2 = scm_mb_fixed_to_multibyte (copy, len, &result_len);
+ if (result_len != bytes)
+ exit (1);
+ if (memcmp (copy2, buffer, bytes))
+ exit (1);
+ if (copy2[bytes] != '\0')
+ exit (1);
+
+ free (copy);
+ free (copy2);
+ }
+ }
+}
+
+static void
+main_prog (int argc, char *argv[])
+{
+ test_one_char_encodings ();
+ test_string_encodings ();
+}
+
+int
+main (int argc, char *argv[])
+{
+ gh_enter (argc, argv, main_prog);
+ return 0;
+}
+
diff --git a/libguile/mb.c b/libguile/mb.c
index 10c5b19e1..d7c9574ba 100644
--- a/libguile/mb.c
+++ b/libguile/mb.c
@@ -244,7 +244,7 @@ scm_mb_get_func (const unsigned char *p)
}
else if (lead < 0x9A)
{
- unsigned char set = load;
+ unsigned char set = lead;
unsigned char pos_hi = p[1] & 0x7f;
unsigned char pos_lo = p[2] & 0x7f;
@@ -417,7 +417,7 @@ scm_mb_count (const unsigned char *p, int len)
scm_char_t
scm_mb_walk (const unsigned char **pp)
{
- const unsigned char *p = *p;
+ const unsigned char *p = *pp;
scm_char_t c = scm_mb_get (p);
*pp = p + scm_mb_len (*p);
return c;
@@ -540,7 +540,7 @@ scm_mb_multibyte_to_fixed (const unsigned char *p, int len, int *result_len)
buf = scm_must_malloc (len * sizeof (*buf), "scm_mb_multibyte_to_fixed");
buf_len = 0;
- while (p < len)
+ while (p < end)
{
scm_char_t c = scm_mb_get (p);
if (c < 0)
@@ -574,10 +574,7 @@ scm_mb_fixed_to_multibyte (const scm_char_t *fixed, int len, int *result_len)
buf = scm_must_malloc (buf_size + 1, "scm_mb_fixed_to_multibyte");
p = buf;
for (i = 0; i < len; i++)
- {
- scm_mb_put (fixed[i], p);
- p += scm_mb_len (*p);
- }
+ p += scm_mb_put (fixed[i], p);
/* Was the size we computed actually correct? */
if (p != buf + buf_size)
diff --git a/libguile/mb.h b/libguile/mb.h
index 725c5661d..4ef94dc91 100644
--- a/libguile/mb.h
+++ b/libguile/mb.h
@@ -98,8 +98,8 @@ extern int scm_mb_len_char_func (scm_char_t c);
#define scm_mb_boundary_p(p) (*(p) < 0xA0)
/* Round P to the previous/next character boundary. */
-extern unsigned char *scm_mb_floor (const unsigned char *p);
-extern unsigned char *scm_mb_ceiling (const unsigned char *p);
+extern const unsigned char *scm_mb_floor (const unsigned char *p);
+extern const unsigned char *scm_mb_ceiling (const unsigned char *p);
/* Multibyte string functions. */
@@ -111,13 +111,14 @@ extern int scm_mb_count (const unsigned char *p, int len);
extern scm_char_t scm_mb_walk (const unsigned char **pp);
/* Return the address of the character before P. */
-extern unsigned char *scm_mb_prev (const unsigned char *p);
+extern const unsigned char *scm_mb_prev (const unsigned char *p);
/* Return the address of the character after P. */
-extern unsigned char *scm_mb_next (const unsigned char *p);
+extern const unsigned char *scm_mb_next (const unsigned char *p);
/* Return the location of the I'th character in LEN bytes at P. */
-extern unsigned char *scm_mb_index (const unsigned char *p, int len, int i);
+extern const unsigned char *scm_mb_index (const unsigned char *p, int len,
+ int i);
/* A cache of information about the positions of characters in
strings. Initialize all elements to zero before using. */
@@ -132,9 +133,9 @@ struct scm_mb_cache {
((i) <= (cache)->character && (cache)->character == (cache)->byte \
? &(p)[(i)] \
: scm_mb_index_cached_func ((p), (len), (i), (cache)))
-extern unsigned char *scm_mb_index_cached_func (const unsigned char *p,
- int len, int i,
- struct scm_mb_cache *cache);
+extern const unsigned char *scm_mb_index_cached_func (const unsigned char *p,
+ int len, int i,
+ struct scm_mb_cache *cache);
/* Convert a multibyte string to an array of scm_char_t's.
The caller is responsible for freeing the result. */