From 313ab4b3d451b1c070e130bac3c99a2d3f003c31 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Thu, 2 Sep 1999 10:47:19 +0000 Subject: * 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. --- libguile/Makefile.am | 5 +- libguile/Makefile.in | 36 +++--- libguile/check_mb.c | 324 +++++++++++++++++++++++++++++++++++++++++++++++++++ libguile/mb.c | 11 +- libguile/mb.h | 17 +-- 5 files changed, 364 insertions(+), 29 deletions(-) create mode 100644 libguile/check_mb.c 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 . 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 +#include +#include + +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. */ -- cgit v1.2.1